From c8ba2379a8dae3cc7a7fdeb6ee00fb95332212aa Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 10 Dec 2002 12:26:00 +0000 Subject: [PATCH] added release() callback --- ChangeLog | 4 ++++ example/fusexmp.c | 1 + example/hello.c | 1 + example/null.c | 1 + include/fuse.h | 8 +++++++ include/linux/fuse.h | 1 + kernel/dev.c | 1 + kernel/file.c | 22 +++++++++++++++++++ kernel/fuse_i.h | 3 +++ lib/fuse.c | 50 ++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 90 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9a8286e..1b033f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2002-12-10 Miklos Szeredi + + * The release() VFS call is now exported to the FUSE interface + 2002-12-05 Miklos Szeredi * 64 bit file offset fixes in the fuse kernel module diff --git a/example/fusexmp.c b/example/fusexmp.c index 8b48af6..e783423 100644 --- a/example/fusexmp.c +++ b/example/fusexmp.c @@ -267,6 +267,7 @@ static struct fuse_operations xmp_oper = { read: xmp_read, write: xmp_write, statfs: xmp_statfs, + release: NULL }; int main(int argc, char *argv[]) diff --git a/example/hello.c b/example/hello.c index be8930e..cd8fb5d 100644 --- a/example/hello.c +++ b/example/hello.c @@ -86,6 +86,7 @@ static struct fuse_operations hello_oper = { read: hello_read, write: NULL, statfs: NULL, + release: NULL }; int main(int argc, char *argv[]) diff --git a/example/null.c b/example/null.c index 6b2c1b6..b712b5c 100644 --- a/example/null.c +++ b/example/null.c @@ -89,6 +89,7 @@ static struct fuse_operations null_oper = { read: null_read, write: null_write, statfs: null_statfs, + release: NULL }; int main(int argc, char *argv[]) diff --git a/include/fuse.h b/include/fuse.h index 28d5f3b..f92914f 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -75,6 +75,13 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t, const char *, int type); * - read(), write() are not passed a filehandle, but rather a * pathname. The offset of the read and write is passed as the last * argument, like the pread() and pwrite() system calls. + * + * - release() is called when an open file has: + * 1) all file descriptors closed + * 2) all memory mappings unmapped + * This call need only be implemented if this information is required, + * otherwise set this function to NULL. + * */ struct fuse_operations { int (*getattr) (const char *, struct stat *); @@ -95,6 +102,7 @@ struct fuse_operations { int (*read) (const char *, char *, size_t, off_t); int (*write) (const char *, const char *, size_t, off_t); int (*statfs) (struct fuse_statfs *); + int (*release) (const char *); }; /** Extra context that may be needed by some filesystems */ diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 24905c4..eef77d9 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -93,6 +93,7 @@ enum fuse_opcode { FUSE_READ = 15, FUSE_WRITE = 16, FUSE_STATFS = 17, + FUSE_RELEASE = 18 }; /* Conservative buffer size for the client */ diff --git a/kernel/dev.c b/kernel/dev.c index 7cf3844..002e23b 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -447,6 +447,7 @@ static struct fuse_conn *new_conn(void) INIT_LIST_HEAD(&fc->processing); sema_init(&fc->outstanding, MAX_OUTSTANDING); fc->reqctr = 1; + fc->has_release = 1; } return fc; } diff --git a/kernel/file.c b/kernel/file.c index 14ba59b..4940117 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -40,6 +40,27 @@ static int fuse_open(struct inode *inode, struct file *file) return out.h.error; } +static int fuse_release(struct inode *inode, struct file *file) +{ + struct fuse_conn *fc = INO_FC(inode); + struct fuse_in in = FUSE_IN_INIT; + struct fuse_out out = FUSE_OUT_INIT; + + if(!fc->has_release) + return 0; + + in.h.opcode = FUSE_RELEASE; + in.h.ino = inode->i_ino; + request_send(fc, &in, &out); + + if(out.h.error == -ENOSYS) { + fc->has_release = 0; + return 0; + } + + return out.h.error; +} + static int fuse_readpage(struct file *file, struct page *page) { @@ -159,6 +180,7 @@ static int fuse_commit_write(struct file *file, struct page *page, static struct file_operations fuse_file_operations = { open: fuse_open, + release: fuse_release, read: generic_file_read, write: generic_file_write, mmap: generic_file_mmap, diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 23cc914..e4730e6 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -56,6 +56,9 @@ struct fuse_conn { /** The next unique request id */ int reqctr; + + /* Flag indicating whether the release call is supported */ + int has_release; }; /** One input argument of a request */ diff --git a/lib/fuse.c b/lib/fuse.c index 1a11ae6..71959c4 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -19,6 +19,31 @@ #define FUSE_MAX_PATH 4096 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg)) +static const char *opname(enum fuse_opcode opcode) +{ + switch(opcode) { + case FUSE_LOOKUP: return "LOOKUP"; + case FUSE_FORGET: return "FORGET"; + case FUSE_GETATTR: return "GETATTR"; + case FUSE_SETATTR: return "SETATTR"; + case FUSE_READLINK: return "READLINK"; + case FUSE_SYMLINK: return "SYMLINK"; + case FUSE_GETDIR: return "GETDIR"; + case FUSE_MKNOD: return "MKNOD"; + case FUSE_MKDIR: return "MKDIR"; + case FUSE_UNLINK: return "UNLINK"; + case FUSE_RMDIR: return "RMDIR"; + case FUSE_RENAME: return "RENAME"; + case FUSE_LINK: return "LINK"; + case FUSE_OPEN: return "OPEN"; + case FUSE_READ: return "READ"; + case FUSE_WRITE: return "WRITE"; + case FUSE_STATFS: return "STATFS"; + case FUSE_RELEASE: return "RELEASE"; + default: return "???"; + } +} + static inline void inc_avail(struct fuse *f) { pthread_mutex_lock(&f->lock); @@ -728,6 +753,22 @@ static void do_open(struct fuse *f, struct fuse_in_header *in, send_reply(f, in, res, NULL, 0); } +static void do_release(struct fuse *f, struct fuse_in_header *in) +{ + int res; + char *path; + + res = -ENOENT; + path = get_path(f, in->ino); + if(path != NULL) { + res = -ENOSYS; + if(f->op.release) + res = f->op.release(path); + free(path); + } + send_reply(f, in, res, NULL, 0); +} + static void do_read(struct fuse *f, struct fuse_in_header *in, struct fuse_read_in *arg) { @@ -834,8 +875,9 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) dec_avail(f); if((f->flags & FUSE_DEBUG)) { - printf("unique: %i, opcode: %i, ino: %li, insize: %i\n", in->unique, - in->opcode, in->ino, cmd->buflen); + printf("unique: %i, opcode: %s (%i), ino: %li, insize: %i\n", + in->unique, opname(in->opcode), in->opcode, in->ino, + cmd->buflen); fflush(stdout); } @@ -907,6 +949,10 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) do_statfs(f, in); break; + case FUSE_RELEASE: + do_release(f, in); + break; + default: fprintf(stderr, "Operation %i not implemented\n", in->opcode); send_reply(f, in, -ENOSYS, NULL, 0); -- 2.30.2