]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/fuse/inode.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / fs / fuse / inode.c
index cfce3ad86a9253c8f82f793da306979357f4df6f..9e3f68cc1bd1338e2c8a6f73de6646fface53be7 100644 (file)
@@ -71,6 +71,11 @@ struct fuse_mount_data {
        unsigned blksize;
 };
 
+struct fuse_forget_link *fuse_alloc_forget()
+{
+       return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);
+}
+
 static struct inode *fuse_alloc_inode(struct super_block *sb)
 {
        struct inode *inode;
@@ -90,8 +95,8 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        INIT_LIST_HEAD(&fi->queued_writes);
        INIT_LIST_HEAD(&fi->writepages);
        init_waitqueue_head(&fi->page_waitq);
-       fi->forget_req = fuse_request_alloc();
-       if (!fi->forget_req) {
+       fi->forget = fuse_alloc_forget();
+       if (!fi->forget) {
                kmem_cache_free(fuse_inode_cachep, inode);
                return NULL;
        }
@@ -99,27 +104,20 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        return inode;
 }
 
-static void fuse_destroy_inode(struct inode *inode)
+static void fuse_i_callback(struct rcu_head *head)
 {
-       struct fuse_inode *fi = get_fuse_inode(inode);
-       BUG_ON(!list_empty(&fi->write_files));
-       BUG_ON(!list_empty(&fi->queued_writes));
-       if (fi->forget_req)
-               fuse_request_free(fi->forget_req);
+       struct inode *inode = container_of(head, struct inode, i_rcu);
+       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(fuse_inode_cachep, inode);
 }
 
-void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
-                     u64 nodeid, u64 nlookup)
+static void fuse_destroy_inode(struct inode *inode)
 {
-       struct fuse_forget_in *inarg = &req->misc.forget_in;
-       inarg->nlookup = nlookup;
-       req->in.h.opcode = FUSE_FORGET;
-       req->in.h.nodeid = nodeid;
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(struct fuse_forget_in);
-       req->in.args[0].value = inarg;
-       fuse_request_send_noreply(fc, req);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       BUG_ON(!list_empty(&fi->write_files));
+       BUG_ON(!list_empty(&fi->queued_writes));
+       kfree(fi->forget);
+       call_rcu(&inode->i_rcu, fuse_i_callback);
 }
 
 static void fuse_evict_inode(struct inode *inode)
@@ -129,8 +127,8 @@ static void fuse_evict_inode(struct inode *inode)
        if (inode->i_sb->s_flags & MS_ACTIVE) {
                struct fuse_conn *fc = get_fuse_conn(inode);
                struct fuse_inode *fi = get_fuse_inode(inode);
-               fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup);
-               fi->forget_req = NULL;
+               fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup);
+               fi->forget = NULL;
        }
 }
 
@@ -534,6 +532,7 @@ void fuse_conn_init(struct fuse_conn *fc)
        INIT_LIST_HEAD(&fc->interrupts);
        INIT_LIST_HEAD(&fc->bg_queue);
        INIT_LIST_HEAD(&fc->entry);
+       fc->forget_list_tail = &fc->forget_list_head;
        atomic_set(&fc->num_waiting, 0);
        fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND;
        fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD;
@@ -618,10 +617,8 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
                goto out_iput;
 
        entry = d_obtain_alias(inode);
-       if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) {
-               entry->d_op = &fuse_dentry_operations;
+       if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID)
                fuse_invalidate_entry_cache(entry);
-       }
 
        return entry;
 
@@ -720,10 +717,8 @@ static struct dentry *fuse_get_parent(struct dentry *child)
        }
 
        parent = d_obtain_alias(inode);
-       if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) {
-               parent->d_op = &fuse_dentry_operations;
+       if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID)
                fuse_invalidate_entry_cache(parent);
-       }
 
        return parent;
 }
@@ -990,6 +985,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
                iput(root);
                goto err_put_conn;
        }
+       /* only now - we want root dentry with NULL ->d_op */
+       sb->s_d_op = &fuse_dentry_operations;
 
        init_req = fuse_request_alloc();
        if (!init_req)