Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
[linux-2.6-block.git] / fs / fuse / inode.c
index e8799c11424b93f0581497c5774db2122780b40b..2913db2a5b99bee2b01b79d07b1451f752f0ec01 100644 (file)
@@ -362,8 +362,8 @@ static void fuse_send_destroy(struct fuse_conn *fc)
        if (req && fc->conn_init) {
                fc->destroy_req = NULL;
                req->in.h.opcode = FUSE_DESTROY;
-               req->force = 1;
-               req->background = 0;
+               __set_bit(FR_FORCE, &req->flags);
+               __clear_bit(FR_BACKGROUND, &req->flags);
                fuse_request_send(fc, req);
                fuse_put_request(fc, req);
        }
@@ -421,7 +421,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
        memset(&outarg, 0, sizeof(outarg));
        args.in.numargs = 0;
        args.in.h.opcode = FUSE_STATFS;
-       args.in.h.nodeid = get_node_id(dentry->d_inode);
+       args.in.h.nodeid = get_node_id(d_inode(dentry));
        args.out.numargs = 1;
        args.out.args[0].size = sizeof(outarg);
        args.out.args[0].value = &outarg;
@@ -567,30 +567,46 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
        return 0;
 }
 
+static void fuse_iqueue_init(struct fuse_iqueue *fiq)
+{
+       memset(fiq, 0, sizeof(struct fuse_iqueue));
+       init_waitqueue_head(&fiq->waitq);
+       INIT_LIST_HEAD(&fiq->pending);
+       INIT_LIST_HEAD(&fiq->interrupts);
+       fiq->forget_list_tail = &fiq->forget_list_head;
+       fiq->connected = 1;
+}
+
+static void fuse_pqueue_init(struct fuse_pqueue *fpq)
+{
+       memset(fpq, 0, sizeof(struct fuse_pqueue));
+       spin_lock_init(&fpq->lock);
+       INIT_LIST_HEAD(&fpq->processing);
+       INIT_LIST_HEAD(&fpq->io);
+       fpq->connected = 1;
+}
+
 void fuse_conn_init(struct fuse_conn *fc)
 {
        memset(fc, 0, sizeof(*fc));
        spin_lock_init(&fc->lock);
        init_rwsem(&fc->killsb);
        atomic_set(&fc->count, 1);
-       init_waitqueue_head(&fc->waitq);
+       atomic_set(&fc->dev_count, 1);
        init_waitqueue_head(&fc->blocked_waitq);
        init_waitqueue_head(&fc->reserved_req_waitq);
-       INIT_LIST_HEAD(&fc->pending);
-       INIT_LIST_HEAD(&fc->processing);
-       INIT_LIST_HEAD(&fc->io);
-       INIT_LIST_HEAD(&fc->interrupts);
+       fuse_iqueue_init(&fc->iq);
        INIT_LIST_HEAD(&fc->bg_queue);
        INIT_LIST_HEAD(&fc->entry);
-       fc->forget_list_tail = &fc->forget_list_head;
+       INIT_LIST_HEAD(&fc->devices);
        atomic_set(&fc->num_waiting, 0);
        fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND;
        fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD;
        fc->khctr = 0;
        fc->polled_files = RB_ROOT;
-       fc->reqctr = 0;
        fc->blocked = 0;
        fc->initialized = 0;
+       fc->connected = 1;
        fc->attr_version = 1;
        get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
 }
@@ -740,7 +756,7 @@ static struct dentry *fuse_fh_to_parent(struct super_block *sb,
 
 static struct dentry *fuse_get_parent(struct dentry *child)
 {
-       struct inode *child_inode = child->d_inode;
+       struct inode *child_inode = d_inode(child);
        struct fuse_conn *fc = get_fuse_conn(child_inode);
        struct inode *inode;
        struct dentry *parent;
@@ -930,6 +946,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
 
 static void fuse_free_conn(struct fuse_conn *fc)
 {
+       WARN_ON(!list_empty(&fc->devices));
        kfree_rcu(fc, rcu);
 }
 
@@ -975,8 +992,42 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
        return 0;
 }
 
+struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc)
+{
+       struct fuse_dev *fud;
+
+       fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL);
+       if (fud) {
+               fud->fc = fuse_conn_get(fc);
+               fuse_pqueue_init(&fud->pq);
+
+               spin_lock(&fc->lock);
+               list_add_tail(&fud->entry, &fc->devices);
+               spin_unlock(&fc->lock);
+       }
+
+       return fud;
+}
+EXPORT_SYMBOL_GPL(fuse_dev_alloc);
+
+void fuse_dev_free(struct fuse_dev *fud)
+{
+       struct fuse_conn *fc = fud->fc;
+
+       if (fc) {
+               spin_lock(&fc->lock);
+               list_del(&fud->entry);
+               spin_unlock(&fc->lock);
+
+               fuse_conn_put(fc);
+       }
+       kfree(fud);
+}
+EXPORT_SYMBOL_GPL(fuse_dev_free);
+
 static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 {
+       struct fuse_dev *fud;
        struct fuse_conn *fc;
        struct inode *root;
        struct fuse_mount_data d;
@@ -1026,12 +1077,17 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
                goto err_fput;
 
        fuse_conn_init(fc);
+       fc->release = fuse_free_conn;
+
+       fud = fuse_dev_alloc(fc);
+       if (!fud)
+               goto err_put_conn;
 
        fc->dev = sb->s_dev;
        fc->sb = sb;
        err = fuse_bdi_init(fc, sb);
        if (err)
-               goto err_put_conn;
+               goto err_dev_free;
 
        sb->s_bdi = &fc->bdi;
 
@@ -1040,7 +1096,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
                fc->dont_mask = 1;
        sb->s_flags |= MS_POSIXACL;
 
-       fc->release = fuse_free_conn;
        fc->flags = d.flags;
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
@@ -1053,14 +1108,14 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        root = fuse_get_root_inode(sb, d.rootmode);
        root_dentry = d_make_root(root);
        if (!root_dentry)
-               goto err_put_conn;
+               goto err_dev_free;
        /* only now - we want root dentry with NULL ->d_op */
        sb->s_d_op = &fuse_dentry_operations;
 
        init_req = fuse_request_alloc(0);
        if (!init_req)
                goto err_put_root;
-       init_req->background = 1;
+       __set_bit(FR_BACKGROUND, &init_req->flags);
 
        if (is_bdev) {
                fc->destroy_req = fuse_request_alloc(0);
@@ -1079,8 +1134,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 
        list_add_tail(&fc->entry, &fuse_conn_list);
        sb->s_root = root_dentry;
-       fc->connected = 1;
-       file->private_data = fuse_conn_get(fc);
+       file->private_data = fud;
        mutex_unlock(&fuse_mutex);
        /*
         * atomic_dec_and_test() in fput() provides the necessary
@@ -1099,6 +1153,8 @@ 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_dev_free:
+       fuse_dev_free(fud);
  err_put_conn:
        fuse_bdi_destroy(fc);
        fuse_conn_put(fc);
@@ -1238,7 +1294,6 @@ static void fuse_fs_cleanup(void)
 }
 
 static struct kobject *fuse_kobj;
-static struct kobject *connections_kobj;
 
 static int fuse_sysfs_init(void)
 {
@@ -1250,11 +1305,9 @@ static int fuse_sysfs_init(void)
                goto out_err;
        }
 
-       connections_kobj = kobject_create_and_add("connections", fuse_kobj);
-       if (!connections_kobj) {
-               err = -ENOMEM;
+       err = sysfs_create_mount_point(fuse_kobj, "connections");
+       if (err)
                goto out_fuse_unregister;
-       }
 
        return 0;
 
@@ -1266,7 +1319,7 @@ static int fuse_sysfs_init(void)
 
 static void fuse_sysfs_cleanup(void)
 {
-       kobject_put(connections_kobj);
+       sysfs_remove_mount_point(fuse_kobj, "connections");
        kobject_put(fuse_kobj);
 }