fix
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 11 Nov 2004 14:01:09 +0000 (14:01 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 11 Nov 2004 14:01:09 +0000 (14:01 +0000)
ChangeLog
kernel/dev.c
kernel/fuse_i.h
kernel/inode.c

index c6a68e2cd5a7964ce848c3cf93dcb9869e9150f3..055c6f8d47eda6fbdda8d31a111adc52f8b7808e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,12 @@
-2004-11-10  Miklos Szeredi <miklos@szeredi.hu>
+2004-11-11  Miklos Szeredi <miklos@szeredi.hu>
 
        * Check kernel interface version in fusermount to prevent
        strangeness in case of mismatch.
 
+       * Fix potential race between umount and fuse_invalidate
+
+       * Check superblock of proc file in addition to inode number
+
 2004-11-10  Miklos Szeredi <miklos@szeredi.hu>
 
        * Released 2.1-pre0
index c87d6c48ebf3bb2da0c5687fdbfd8b5c8a7bbe8c..fca6c20e88511170b282b06007a2b547c9be3265 100644 (file)
@@ -479,7 +479,11 @@ static int fuse_user_request(struct fuse_conn *fc, const char *buf,
        
        switch (uh.opcode) {
        case FUSE_INVALIDATE:
-               err = fuse_invalidate(fc, &uh);
+               down(&fc->sb_sem);
+               err = -ENODEV;
+               if (fc->sb)
+                       err = fuse_invalidate(fc, &uh);
+               up(&fc->sb_sem);
                break;
 
        default:
@@ -602,6 +606,7 @@ static struct fuse_conn *new_conn(void)
                INIT_LIST_HEAD(&fc->processing);
                INIT_LIST_HEAD(&fc->unused_list);
                sema_init(&fc->unused_sem, MAX_OUTSTANDING);
+               sema_init(&fc->sb_sem, 1);
                for (i = 0; i < MAX_OUTSTANDING; i++) {
                        struct fuse_req *req = fuse_request_alloc();
                        if (!req) {
index c74238b1ada83511ad71bdc8dbd67d0350a11be5..c256bb250848dcf1a27fd6d376e20c2cd5aef2b6 100644 (file)
@@ -224,6 +224,9 @@ struct fuse_conn {
        /** Controls the maximum number of outstanding requests */
        struct semaphore unused_sem;
 
+       /** Semaphore protecting the super block from going away */
+       struct semaphore sb_sem;
+
        /** The list of unused requests */
        struct list_head unused_list;
        
index 8de566ccb491a2e9e6d4f62594782ae7d93211ac..b11a8c28b0600159e8037a732716fb731ca7c88f 100644 (file)
@@ -123,8 +123,10 @@ static void fuse_put_super(struct super_block *sb)
 {
        struct fuse_conn *fc = SB_FC(sb);
 
+       down(&fc->sb_sem);
        spin_lock(&fuse_lock);
        fc->sb = NULL;
+       up(&fc->sb_sem);
        fc->uid = 0;
        fc->flags = 0;
        /* Flush all readers on this fs */
@@ -311,7 +313,8 @@ static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
        struct inode *ino;
 
        ino = file->f_dentry->d_inode;
-       if (!ino || !proc_fuse_dev || proc_fuse_dev->low_ino != ino->i_ino) {
+       if (!ino || !proc_fuse_dev || proc_mnt->mnt_sb != ino->i_sb ||
+           proc_fuse_dev->low_ino != ino->i_ino) {
                printk("FUSE: bad communication file descriptor\n");
                return NULL;
        }
@@ -432,8 +435,10 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
        return 0;
 
  err:
+       down(&fc->sb_sem);
        spin_lock(&fuse_lock);
        fc->sb = NULL;
+       up(&fc->sb_sem);
        fuse_release_conn(fc);
        spin_unlock(&fuse_lock);
        SB_FC(sb) = NULL;