Added a sys_open_entry_ref() call to the VFS layer.
Implemented the beginnings of a Tracker like mode in the fs_shell - started and stopped using the new "tracker" command; it will get all notifications the file system sends. Right now it's very simple, it just opens the file, does a stat(), and closes the file again, and guess what, I could reproduce our favourite problem with it!! So it will be finally fixed in the next few days. Some cleanups. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3559 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
57ec89d1b5
commit
55288b8eda
@ -13,6 +13,7 @@
|
||||
Dominic Giampaolo
|
||||
dbg@be.com
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
@ -22,6 +23,7 @@
|
||||
#include "myfs.h"
|
||||
#include "kprotos.h"
|
||||
#include "argv.h"
|
||||
#include "tracker.h"
|
||||
|
||||
#include <fs_attr.h>
|
||||
#include <fs_query.h>
|
||||
@ -798,7 +800,7 @@ copydir(char *fromPath,char *toPath)
|
||||
|
||||
from = opendir(fromPath);
|
||||
if (from == NULL) {
|
||||
printf("could not open %s\n",fromPath);
|
||||
printf("could not open %s\n", fromPath);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -813,27 +815,27 @@ copydir(char *fromPath,char *toPath)
|
||||
dirent_t *attr;
|
||||
struct stat st;
|
||||
|
||||
if (!strcmp(dirent->d_name,".") || !strcmp(dirent->d_name,".."))
|
||||
if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
|
||||
continue;
|
||||
|
||||
strcpy(from_name, fromPath);
|
||||
if (from_name[strlen(from_name) - 1] != '/')
|
||||
strcat(from_name,"/");
|
||||
strcat(from_name, "/");
|
||||
strcat(from_name, dirent->d_name);
|
||||
|
||||
if (stat(from_name,&st) != 0)
|
||||
if (stat(from_name, &st) != 0)
|
||||
continue;
|
||||
|
||||
if (st.st_mode & S_IFDIR) {
|
||||
char path[1024];
|
||||
strcpy(path,toPath);
|
||||
strcat(path,"/");
|
||||
strcat(path,dirent->d_name);
|
||||
strcpy(path, toPath);
|
||||
strcat(path, "/");
|
||||
strcat(path, dirent->d_name);
|
||||
|
||||
if ((err = sys_mkdir(1, -1, path, MY_S_IRWXU)) == B_OK)
|
||||
copydir(from_name,path);
|
||||
copydir(from_name, path);
|
||||
else
|
||||
printf("Could not create directory %s: (%s)\n",path,strerror(err));
|
||||
printf("Could not create directory %s: (%s)\n", path, strerror(err));
|
||||
} else {
|
||||
fd = open(from_name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@ -841,7 +843,7 @@ copydir(char *fromPath,char *toPath)
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(myfs_name, "%s/%s", toPath,dirent->d_name);
|
||||
sprintf(myfs_name, "%s/%s", toPath, dirent->d_name);
|
||||
if ((bfd = sys_open(1, -1, myfs_name, O_RDWR|O_CREAT,
|
||||
MY_S_IFREG|MY_S_IRWXU, 0)) < 0) {
|
||||
close(fd);
|
||||
@ -855,7 +857,7 @@ copydir(char *fromPath,char *toPath)
|
||||
struct attr_info attrInfo;
|
||||
int32 size = bufferSize, bytesRead;
|
||||
|
||||
if (fs_stat_attr(fd,attr->d_name,&attrInfo) != 0)
|
||||
if (fs_stat_attr(fd, attr->d_name, &attrInfo) != 0)
|
||||
continue;
|
||||
|
||||
if (attrInfo.size <= size)
|
||||
@ -872,7 +874,8 @@ copydir(char *fromPath,char *toPath)
|
||||
|
||||
err = sys_write_attr(1, bfd, attr->d_name, attrInfo.type, buff, size, 0);
|
||||
if (err < B_OK) {
|
||||
printf("write attr failed: %s\n",strerror(err));
|
||||
printf("write attr (\"%s\", type = %p, %p, %ld bytes) failed: %s\n",
|
||||
attr->d_name, (void *)attrInfo.type, buff, size, strerror(err));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -978,6 +981,86 @@ do_threadfiletest(int argc, char **argv)
|
||||
}
|
||||
|
||||
|
||||
port_id gTrackerPort;
|
||||
|
||||
|
||||
static void
|
||||
tracker_query_file(dev_t device, ino_t parent, char *name)
|
||||
{
|
||||
struct stat stat;
|
||||
int status;
|
||||
|
||||
int fd = sys_open_entry_ref(1, device, parent, name, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
printf("tracker: could not open file: %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
status = sys_rstat(true, fd, NULL, &stat, 1);
|
||||
if (status < 0) {
|
||||
printf("tracker: could not stat file: %s\n", name);
|
||||
}
|
||||
|
||||
sys_close(true, fd);
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
tracker_loop(void *data)
|
||||
{
|
||||
// create global messaging port
|
||||
|
||||
gTrackerPort = create_port(128, "fsh tracker port");
|
||||
if (gTrackerPort < B_OK)
|
||||
return gTrackerPort;
|
||||
|
||||
while (true) {
|
||||
update_message message;
|
||||
uint32 code;
|
||||
status_t status = read_port(gTrackerPort, &code, &message, sizeof(message));
|
||||
if (status < B_OK)
|
||||
continue;
|
||||
|
||||
if (code == FSH_KILL_TRACKER)
|
||||
break;
|
||||
|
||||
if (code == FSH_NOTIFY_LISTENER) {
|
||||
printf("tracker: notify listener received\n");
|
||||
tracker_query_file(message.device, message.parentNode, message.name);
|
||||
} else if (code == B_QUERY_UPDATE) {
|
||||
printf("tracker: query update received\n");
|
||||
tracker_query_file(message.device, message.parentNode, message.name);
|
||||
} else {
|
||||
printf("tracker: unknown code received: 0x%lx\n", code);
|
||||
}
|
||||
}
|
||||
|
||||
delete_port(gTrackerPort);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_tracker(int argc, char **argv)
|
||||
{
|
||||
static thread_id thread = -1;
|
||||
|
||||
if (thread < B_OK) {
|
||||
puts("starting tracker...");
|
||||
|
||||
thread = spawn_thread(tracker_loop, "tracker", B_NORMAL_PRIORITY, NULL);
|
||||
resume_thread(thread);
|
||||
} else {
|
||||
status_t status;
|
||||
puts("stopping tracker.");
|
||||
|
||||
write_port(gTrackerPort, FSH_KILL_TRACKER, NULL, 0);
|
||||
wait_for_thread(thread, &status);
|
||||
|
||||
thread = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_attrtest(int argc, char **argv)
|
||||
{
|
||||
@ -1412,6 +1495,7 @@ cmd_entry fsh_cmds[] =
|
||||
{ "cptest", do_copytest, "copies all files from the given path" },
|
||||
{ "threads", do_threadtest, "copies several files, and does a lat_fs simulaneously" },
|
||||
{ "mfile", do_threadfiletest, "copies several big files simulaneously" },
|
||||
{ "tracker", do_tracker, "starts a Tracker like background thread that will listen to fs updates" },
|
||||
{ "cio", do_cio, "does a I/O speed test" },
|
||||
|
||||
// additional commands from the file system will be included here
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "lock.h"
|
||||
#include "fsproto.h"
|
||||
#include "kprotos.h"
|
||||
#include "tracker.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -1059,6 +1060,74 @@ errorA:
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_open_entry_ref(bool kernel, nspace_id device, vnode_id parent, const char *name,
|
||||
int openMode, bool coe)
|
||||
{
|
||||
int err;
|
||||
vnode *vn;
|
||||
vnode_id vnid;
|
||||
void *cookie;
|
||||
ofile *f;
|
||||
int nfd;
|
||||
fdarray *fds;
|
||||
op_create *opc;
|
||||
op_open *opo;
|
||||
op_free_cookie *opf;
|
||||
|
||||
err = get_file_vn(device, parent, name, TRUE, &vn);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
opo = vn->ns->fs->ops.open;
|
||||
if (!opo) {
|
||||
err = EINVAL;
|
||||
goto error1;
|
||||
}
|
||||
err = (*opo)(vn->ns->data, vn->data, openMode, &cookie);
|
||||
if (err)
|
||||
goto error1;
|
||||
|
||||
/*
|
||||
* find a file descriptor
|
||||
*/
|
||||
|
||||
f = (ofile *)calloc(sizeof(ofile), 1);
|
||||
if (!f) {
|
||||
err = ENOMEM;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
f->type = FD_FILE;
|
||||
f->vn = vn;
|
||||
f->cookie = cookie;
|
||||
f->ocnt = 0;
|
||||
f->rcnt = 0;
|
||||
f->pos = 0;
|
||||
f->omode = openMode;
|
||||
|
||||
nfd = new_fd(kernel, -1, f, -1, coe);
|
||||
if (nfd < 0) {
|
||||
err = EMFILE;
|
||||
goto error3;
|
||||
}
|
||||
|
||||
return nfd;
|
||||
|
||||
error3:
|
||||
free(f);
|
||||
error2:
|
||||
(*vn->ns->fs->ops.close)(vn->ns->data, vn->data, cookie);
|
||||
opf = vn->ns->fs->ops.free_cookie;
|
||||
if (opf)
|
||||
(*opf)(vn->ns->data, vn->data, cookie);
|
||||
|
||||
error1:
|
||||
dec_vnode(vn, FALSE);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sys_close
|
||||
*/
|
||||
@ -3205,7 +3274,8 @@ notify_listener(int op, nspace_id nsid, vnode_id vnida, vnode_id vnidb, vnode_id
|
||||
}
|
||||
printf("notify_listener: %s\n", text);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
return send_notification(0, 0, FSH_NOTIFY_LISTENER, op, nsid, -1, vnida, vnidb, vnidc, name);
|
||||
}
|
||||
|
||||
|
||||
@ -3214,11 +3284,27 @@ send_notification(port_id port, long token, ulong what, long op, nspace_id nsida
|
||||
nspace_id nsidb, vnode_id vnida, vnode_id vnidb, vnode_id vnidc,
|
||||
const char *name)
|
||||
{
|
||||
update_message message;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("send_notification... op = %s, name = %s, port = %ld, token = %ld\n",
|
||||
op == B_ENTRY_CREATED ? "B_ENTRY_CREATED" : "B_ENTRY_REMOVED", name, port, token);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
message.op = op;
|
||||
message.device = nsida;
|
||||
message.toDevice = nsidb;
|
||||
message.parentNode = vnida;
|
||||
message.targetNode = vnidb;
|
||||
message.node = vnidc;
|
||||
|
||||
if (name != NULL) {
|
||||
strcpy(message.name, name);
|
||||
// name is 256 character at maximum
|
||||
} else
|
||||
message.name[0] = '\0';
|
||||
|
||||
return write_port(gTrackerPort, what, &message, sizeof(message));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,17 +2,18 @@
|
||||
#define my_dirent dirent
|
||||
|
||||
int sys_symlink(bool kernel, const char *oldpath, int nfd,
|
||||
const char *newpath);
|
||||
const char *newpath);
|
||||
ssize_t sys_readlink(bool kernel, int fd, const char *path, char *buf,
|
||||
size_t bufsize);
|
||||
size_t bufsize);
|
||||
int sys_mkdir(bool kernel, int fd, const char *path, int perms);
|
||||
int sys_open(bool kernel, int fd, const char *path, int omode,
|
||||
int perms, bool coe);
|
||||
int perms, bool coe);
|
||||
int sys_open_entry_ref(bool kernel, nspace_id device, vnode_id parent,
|
||||
const char *name, int openMode, bool coe);
|
||||
int sys_close(bool kernel, int fd);
|
||||
fs_off_t sys_lseek(bool kernel, int fd, fs_off_t pos, int whence);
|
||||
ssize_t sys_read(bool kernel, int fd, void *buf, size_t len);
|
||||
ssize_t sys_write(bool kernel, int fd, void *buf, size_t len);
|
||||
int sys_ioctl(bool kernel, int fd, int cmd, void *arg, size_t sz);
|
||||
int sys_unlink(bool kernel, int fd, const char *path);
|
||||
int sys_link(bool kernel, int ofd, const char *oldpath, int nfd,
|
||||
const char *newpath);
|
||||
|
25
src/tests/add-ons/kernel/file_systems/fs_shell/tracker.h
Normal file
25
src/tests/add-ons/kernel/file_systems/fs_shell/tracker.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef TRACKER_H
|
||||
#define TRACKER_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <AppDefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#define FSH_KILL_TRACKER 'kill'
|
||||
#define FSH_NOTIFY_LISTENER 'notl'
|
||||
|
||||
typedef struct update_message {
|
||||
int32 op;
|
||||
dev_t device;
|
||||
dev_t toDevice;
|
||||
ino_t parentNode;
|
||||
ino_t targetNode;
|
||||
ino_t node;
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
} update_message;
|
||||
|
||||
|
||||
extern port_id gTrackerPort;
|
||||
|
||||
#endif /* TRACKER_H */
|
Loading…
x
Reference in New Issue
Block a user