Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 26 Jan 2009 17:49:22 +0000 (09:49 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 26 Jan 2009 17:49:22 +0000 (09:49 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
  fuse: fix poll notify
  fuse: destroy bdi on umount
  fuse: fuse_fill_super error handling cleanup
  fuse: fix missing fput on error
  fuse: fix NULL deref in fuse_file_alloc()

fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/inode.c

index e0c7ada08a1fe6f3caed4b31dc81fbb4ae9e1984..ba76b68c52ffe2d127178d71ca5b5ab2ecc6a353 100644 (file)
@@ -281,7 +281,8 @@ __releases(&fc->lock)
                        fc->blocked = 0;
                        wake_up_all(&fc->blocked_waitq);
                }
-               if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
+               if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
+                   fc->connected) {
                        clear_bdi_congested(&fc->bdi, READ);
                        clear_bdi_congested(&fc->bdi, WRITE);
                }
@@ -825,16 +826,21 @@ static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size,
                            struct fuse_copy_state *cs)
 {
        struct fuse_notify_poll_wakeup_out outarg;
-       int err;
+       int err = -EINVAL;
 
        if (size != sizeof(outarg))
-               return -EINVAL;
+               goto err;
 
        err = fuse_copy_one(cs, &outarg, sizeof(outarg));
        if (err)
-               return err;
+               goto err;
 
+       fuse_copy_finish(cs);
        return fuse_notify_poll_wakeup(fc, &outarg);
+
+err:
+       fuse_copy_finish(cs);
+       return err;
 }
 
 static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
@@ -845,6 +851,7 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
                return fuse_notify_poll(fc, size, cs);
 
        default:
+               fuse_copy_finish(cs);
                return -EINVAL;
        }
 }
@@ -923,7 +930,6 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
         */
        if (!oh.unique) {
                err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), &cs);
-               fuse_copy_finish(&cs);
                return err ? err : nbytes;
        }
 
index e8162646a9b5840766636477d1ae14f32ddc569f..d9fdb7cec5388756720374f9b4c70ec56d453bb2 100644 (file)
@@ -54,7 +54,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
                ff->reserved_req = fuse_request_alloc();
                if (!ff->reserved_req) {
                        kfree(ff);
-                       ff = NULL;
+                       return NULL;
                } else {
                        INIT_LIST_HEAD(&ff->write_entry);
                        atomic_set(&ff->count, 0);
index 47c96fdca1ac69afbf7f7eb841a9a50690754ee7..459b73dd45e1302298ab75a5e6c4bee86849ebae 100644 (file)
@@ -292,6 +292,7 @@ static void fuse_put_super(struct super_block *sb)
        list_del(&fc->entry);
        fuse_ctl_remove_conn(fc);
        mutex_unlock(&fuse_mutex);
+       bdi_destroy(&fc->bdi);
        fuse_conn_put(fc);
 }
 
@@ -532,7 +533,6 @@ void fuse_conn_put(struct fuse_conn *fc)
                if (fc->destroy_req)
                        fuse_request_free(fc->destroy_req);
                mutex_destroy(&fc->inst_mutex);
-               bdi_destroy(&fc->bdi);
                fc->release(fc);
        }
 }
@@ -805,16 +805,18 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        int err;
        int is_bdev = sb->s_bdev != NULL;
 
+       err = -EINVAL;
        if (sb->s_flags & MS_MANDLOCK)
-               return -EINVAL;
+               goto err;
 
        if (!parse_fuse_opt((char *) data, &d, is_bdev))
-               return -EINVAL;
+               goto err;
 
        if (is_bdev) {
 #ifdef CONFIG_BLOCK
+               err = -EINVAL;
                if (!sb_set_blocksize(sb, d.blksize))
-                       return -EINVAL;
+                       goto err;
 #endif
        } else {
                sb->s_blocksize = PAGE_CACHE_SIZE;
@@ -826,20 +828,22 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_export_op = &fuse_export_operations;
 
        file = fget(d.fd);
+       err = -EINVAL;
        if (!file)
-               return -EINVAL;
+               goto err;
 
        if (file->f_op != &fuse_dev_operations)
-               return -EINVAL;
+               goto err_fput;
 
        fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+       err = -ENOMEM;
        if (!fc)
-               return -ENOMEM;
+               goto err_fput;
 
        err = fuse_conn_init(fc, sb);
        if (err) {
                kfree(fc);
-               return err;
+               goto err_fput;
        }
 
        fc->release = fuse_free_conn;
@@ -854,12 +858,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        err = -ENOMEM;
        root = fuse_get_root_inode(sb, d.rootmode);
        if (!root)
-               goto err;
+               goto err_put_conn;
 
        root_dentry = d_alloc_root(root);
        if (!root_dentry) {
                iput(root);
-               goto err;
+               goto err_put_conn;
        }
 
        init_req = fuse_request_alloc();
@@ -903,9 +907,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fuse_request_free(init_req);
  err_put_root:
        dput(root_dentry);
- err:
-       fput(file);
+ err_put_conn:
        fuse_conn_put(fc);
+ err_fput:
+       fput(file);
+ err:
        return err;
 }