From 55288b8eda438d2a7e4524ef3ec7b16088975875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 17 Jun 2003 22:02:23 +0000 Subject: [PATCH] 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 --- .../kernel/file_systems/fs_shell/fsh.c | 108 ++++++++++++++++-- .../kernel/file_systems/fs_shell/kernel.c | 90 ++++++++++++++- .../kernel/file_systems/fs_shell/kprotos.h | 9 +- .../kernel/file_systems/fs_shell/tracker.h | 25 ++++ 4 files changed, 214 insertions(+), 18 deletions(-) create mode 100644 src/tests/add-ons/kernel/file_systems/fs_shell/tracker.h diff --git a/src/tests/add-ons/kernel/file_systems/fs_shell/fsh.c b/src/tests/add-ons/kernel/file_systems/fs_shell/fsh.c index 31559d5499..03dedc5da7 100644 --- a/src/tests/add-ons/kernel/file_systems/fs_shell/fsh.c +++ b/src/tests/add-ons/kernel/file_systems/fs_shell/fsh.c @@ -13,6 +13,7 @@ Dominic Giampaolo dbg@be.com */ + #include #include #include @@ -22,6 +23,7 @@ #include "myfs.h" #include "kprotos.h" #include "argv.h" +#include "tracker.h" #include #include @@ -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 diff --git a/src/tests/add-ons/kernel/file_systems/fs_shell/kernel.c b/src/tests/add-ons/kernel/file_systems/fs_shell/kernel.c index b0e4266f71..408e0bbce4 100644 --- a/src/tests/add-ons/kernel/file_systems/fs_shell/kernel.c +++ b/src/tests/add-ons/kernel/file_systems/fs_shell/kernel.c @@ -20,6 +20,7 @@ #include "lock.h" #include "fsproto.h" #include "kprotos.h" +#include "tracker.h" #include @@ -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)); } diff --git a/src/tests/add-ons/kernel/file_systems/fs_shell/kprotos.h b/src/tests/add-ons/kernel/file_systems/fs_shell/kprotos.h index 2d02122b00..ace5e0e907 100644 --- a/src/tests/add-ons/kernel/file_systems/fs_shell/kprotos.h +++ b/src/tests/add-ons/kernel/file_systems/fs_shell/kprotos.h @@ -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); diff --git a/src/tests/add-ons/kernel/file_systems/fs_shell/tracker.h b/src/tests/add-ons/kernel/file_systems/fs_shell/tracker.h new file mode 100644 index 0000000000..46006f4c6b --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/fs_shell/tracker.h @@ -0,0 +1,25 @@ +#ifndef TRACKER_H +#define TRACKER_H + +#include +#include +#include + + +#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 */