added release() callback
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 10 Dec 2002 12:26:00 +0000 (12:26 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 10 Dec 2002 12:26:00 +0000 (12:26 +0000)
ChangeLog
example/fusexmp.c
example/hello.c
example/null.c
include/fuse.h
include/linux/fuse.h
kernel/dev.c
kernel/file.c
kernel/fuse_i.h
lib/fuse.c

index 9a8286eba9ba80f5aec930b865d4b9c6cdf4c99c..1b033f26fd24eb3448072d4df0e66d80de3fe3e9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2002-12-10  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * The release() VFS call is now exported to the FUSE interface
+
 2002-12-05  Miklos Szeredi <mszeredi@inf.bme.hu>
 
        * 64 bit file offset fixes in the fuse kernel module
index 8b48af663919e51a9657f1b7ae5371ca1329098d..e783423e38d57a0fbcc55ddd0ecf6ab046b58f63 100644 (file)
@@ -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[])
index be8930e8f32d78b0f78fddb7ce7cd359046ab7d7..cd8fb5d351e471b3e85048e7cd728ab0a3392f7a 100644 (file)
@@ -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[])
index 6b2c1b65f6daca53b3cf15e7982c1e8cbbe0c60f..b712b5c7843249254b9cb6e986c2089e192218e3 100644 (file)
@@ -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[])
index 28d5f3ba319acf1e7049a3de3f62ee22d6a99af1..f92914fbb22dc48e170e6f70f5f4febc850b462d 100644 (file)
@@ -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 */
index 24905c44b0b2efa0215e73d7a712dc01b780d5fa..eef77d9faa615f754966e8dac601fee9aba5b941 100644 (file)
@@ -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 */
index 7cf38449ce63341f38440a00ebf7a920b8cb3509..002e23b17606330422e021116d58bb7dad1dbe1a 100644 (file)
@@ -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;
 }
index 14ba59b62f285510eeb8c478db80b4f693a90be6..49401176c522d65a43abe1fdf34923a306bf5152 100644 (file)
@@ -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,
index 23cc914fa36d39e47fffef691296606bd5c17d85..e4730e65dcce7a5242e9992e2b6f14a2ffcd2336 100644 (file)
@@ -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 */
index 1a11ae63fba5c9759b482a93da7e212f2b11a086..71959c4b7c16037eb1e597462f2b4eb15bd4e016 100644 (file)
 #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);