Index: include/fuse.h =================================================================== RCS file: /cvsroot/fuse/fuse/include/fuse.h,v retrieving revision 1.124 diff -u -r1.124 fuse.h --- include/fuse.h 22 May 2007 11:09:01 -0000 1.124 +++ include/fuse.h 22 May 2007 18:16:04 -0000 @@ -419,6 +419,8 @@ * Introduced in version 2.6 */ int (*bmap) (const char *, size_t blocksize, uint64_t *idx); + + int (*enter) (const char *); }; /** Extra context that may be needed by some filesystems @@ -653,6 +655,7 @@ uint64_t *idx); void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); void fuse_fs_destroy(struct fuse_fs *fs); +int fuse_fs_enter(struct fuse_fs *fs, const char *path); /** * Create a new fuse filesystem object Index: include/fuse_lowlevel.h =================================================================== RCS file: /cvsroot/fuse/fuse/include/fuse_lowlevel.h,v retrieving revision 1.45 diff -u -r1.45 fuse_lowlevel.h --- include/fuse_lowlevel.h 25 Apr 2007 16:19:14 -0000 1.45 +++ include/fuse_lowlevel.h 22 May 2007 18:16:07 -0000 @@ -790,6 +790,8 @@ */ void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, uint64_t idx); + + void (*enter) (fuse_req_t req, fuse_ino_t ino); }; /** @@ -960,6 +962,8 @@ */ int fuse_reply_bmap(fuse_req_t req, uint64_t idx); +int fuse_reply_enter(fuse_req_t req, int fd); + /* ----------------------------------------------------------- * * Filling a buffer in readdir * * ----------------------------------------------------------- */ Index: kernel/fuse_kernel.h =================================================================== RCS file: /cvsroot/fuse/fuse/kernel/fuse_kernel.h,v retrieving revision 1.39 diff -u -r1.39 fuse_kernel.h --- kernel/fuse_kernel.h 22 May 2007 11:09:01 -0000 1.39 +++ kernel/fuse_kernel.h 22 May 2007 18:16:08 -0000 @@ -169,6 +169,7 @@ FUSE_INTERRUPT = 36, FUSE_BMAP = 37, FUSE_DESTROY = 38, + FUSE_ENTER = 39, }; /* The read buffer is required to be at least 8k, but may be much larger */ @@ -349,6 +350,10 @@ __u64 block; }; +struct fuse_enter_out { + __u64 fd; +}; + struct fuse_in_header { __u32 len; __u32 opcode; Index: lib/fuse.c =================================================================== RCS file: /cvsroot/fuse/fuse/lib/fuse.c,v retrieving revision 1.199 diff -u -r1.199 fuse.c --- lib/fuse.c 11 May 2007 09:19:36 -0000 1.199 +++ lib/fuse.c 22 May 2007 18:16:12 -0000 @@ -1097,6 +1097,15 @@ return -ENOSYS; } +int fuse_fs_enter(struct fuse_fs *fs, const char *path) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.enter) + return fs->op.enter(path); + else + return -ENOSYS; +} + static int is_open(struct fuse *f, fuse_ino_t dir, const char *name) { struct node *node; @@ -2749,6 +2758,31 @@ reply_err(req, err); } +static void fuse_lib_enter(fuse_req_t req, fuse_ino_t ino) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path; + int res; + + res = -ENOENT; + pthread_rwlock_rdlock(&f->tree_lock); + path = get_path(f, ino); + if (path != NULL) { + fuse_prepare_interrupt(f, req, &d); + res = fuse_fs_enter(f->fs, path); + fuse_finish_interrupt(f, req, &d); + free(path); + } + pthread_rwlock_unlock(&f->tree_lock); + if (res < 0) + reply_err(req, res); + else { + fuse_reply_enter(req, res); + close(res); + } +} + static struct fuse_lowlevel_ops fuse_path_ops = { .init = fuse_lib_init, .destroy = fuse_lib_destroy, @@ -2784,6 +2818,7 @@ .getlk = fuse_lib_getlk, .setlk = fuse_lib_setlk, .bmap = fuse_lib_bmap, + .enter = fuse_lib_enter, }; static void free_cmd(struct fuse_cmd *cmd) Index: lib/fuse_lowlevel.c =================================================================== RCS file: /cvsroot/fuse/fuse/lib/fuse_lowlevel.c,v retrieving revision 1.62 diff -u -r1.62 fuse_lowlevel.c --- lib/fuse_lowlevel.c 25 Apr 2007 16:19:15 -0000 1.62 +++ lib/fuse_lowlevel.c 22 May 2007 18:16:15 -0000 @@ -412,6 +412,16 @@ return send_reply_ok(req, &arg, sizeof(arg)); } +int fuse_reply_enter(fuse_req_t req, int fd) +{ + struct fuse_enter_out arg; + + memset(&arg, 0, sizeof(arg)); + arg.fd = fd; + + return send_reply_ok(req, &arg, sizeof(arg)); +} + static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { char *name = (char *) inarg; @@ -1016,6 +1026,16 @@ send_reply_ok(req, NULL, 0); } +static void do_enter(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + (void) inarg; + + if (req->f->op.enter) + req->f->op.enter(req, nodeid); + else + fuse_reply_err(req, ENOSYS); +} + void *fuse_req_userdata(fuse_req_t req) { return req->f->userdata; @@ -1088,6 +1108,7 @@ [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, [FUSE_BMAP] = { do_bmap, "BMAP" }, [FUSE_DESTROY] = { do_destroy, "DESTROY" }, + [FUSE_ENTER] = { do_enter, "ENTER" }, }; #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))