diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index cfce3ad86a9..f62b32cffea 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -71,6 +71,11 @@ struct fuse_mount_data { | |||
71 | unsigned blksize; | 71 | unsigned blksize; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct fuse_forget_link *fuse_alloc_forget() | ||
75 | { | ||
76 | return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); | ||
77 | } | ||
78 | |||
74 | static struct inode *fuse_alloc_inode(struct super_block *sb) | 79 | static struct inode *fuse_alloc_inode(struct super_block *sb) |
75 | { | 80 | { |
76 | struct inode *inode; | 81 | struct inode *inode; |
@@ -90,8 +95,8 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
90 | INIT_LIST_HEAD(&fi->queued_writes); | 95 | INIT_LIST_HEAD(&fi->queued_writes); |
91 | INIT_LIST_HEAD(&fi->writepages); | 96 | INIT_LIST_HEAD(&fi->writepages); |
92 | init_waitqueue_head(&fi->page_waitq); | 97 | init_waitqueue_head(&fi->page_waitq); |
93 | fi->forget_req = fuse_request_alloc(); | 98 | fi->forget = fuse_alloc_forget(); |
94 | if (!fi->forget_req) { | 99 | if (!fi->forget) { |
95 | kmem_cache_free(fuse_inode_cachep, inode); | 100 | kmem_cache_free(fuse_inode_cachep, inode); |
96 | return NULL; | 101 | return NULL; |
97 | } | 102 | } |
@@ -99,27 +104,20 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
99 | return inode; | 104 | return inode; |
100 | } | 105 | } |
101 | 106 | ||
102 | static void fuse_destroy_inode(struct inode *inode) | 107 | static void fuse_i_callback(struct rcu_head *head) |
103 | { | 108 | { |
104 | struct fuse_inode *fi = get_fuse_inode(inode); | 109 | struct inode *inode = container_of(head, struct inode, i_rcu); |
105 | BUG_ON(!list_empty(&fi->write_files)); | 110 | INIT_LIST_HEAD(&inode->i_dentry); |
106 | BUG_ON(!list_empty(&fi->queued_writes)); | ||
107 | if (fi->forget_req) | ||
108 | fuse_request_free(fi->forget_req); | ||
109 | kmem_cache_free(fuse_inode_cachep, inode); | 111 | kmem_cache_free(fuse_inode_cachep, inode); |
110 | } | 112 | } |
111 | 113 | ||
112 | void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | 114 | static void fuse_destroy_inode(struct inode *inode) |
113 | u64 nodeid, u64 nlookup) | ||
114 | { | 115 | { |
115 | struct fuse_forget_in *inarg = &req->misc.forget_in; | 116 | struct fuse_inode *fi = get_fuse_inode(inode); |
116 | inarg->nlookup = nlookup; | 117 | BUG_ON(!list_empty(&fi->write_files)); |
117 | req->in.h.opcode = FUSE_FORGET; | 118 | BUG_ON(!list_empty(&fi->queued_writes)); |
118 | req->in.h.nodeid = nodeid; | 119 | kfree(fi->forget); |
119 | req->in.numargs = 1; | 120 | call_rcu(&inode->i_rcu, fuse_i_callback); |
120 | req->in.args[0].size = sizeof(struct fuse_forget_in); | ||
121 | req->in.args[0].value = inarg; | ||
122 | fuse_request_send_noreply(fc, req); | ||
123 | } | 121 | } |
124 | 122 | ||
125 | static void fuse_evict_inode(struct inode *inode) | 123 | static void fuse_evict_inode(struct inode *inode) |
@@ -129,8 +127,8 @@ static void fuse_evict_inode(struct inode *inode) | |||
129 | if (inode->i_sb->s_flags & MS_ACTIVE) { | 127 | if (inode->i_sb->s_flags & MS_ACTIVE) { |
130 | struct fuse_conn *fc = get_fuse_conn(inode); | 128 | struct fuse_conn *fc = get_fuse_conn(inode); |
131 | struct fuse_inode *fi = get_fuse_inode(inode); | 129 | struct fuse_inode *fi = get_fuse_inode(inode); |
132 | fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup); | 130 | fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); |
133 | fi->forget_req = NULL; | 131 | fi->forget = NULL; |
134 | } | 132 | } |
135 | } | 133 | } |
136 | 134 | ||
@@ -534,6 +532,7 @@ void fuse_conn_init(struct fuse_conn *fc) | |||
534 | INIT_LIST_HEAD(&fc->interrupts); | 532 | INIT_LIST_HEAD(&fc->interrupts); |
535 | INIT_LIST_HEAD(&fc->bg_queue); | 533 | INIT_LIST_HEAD(&fc->bg_queue); |
536 | INIT_LIST_HEAD(&fc->entry); | 534 | INIT_LIST_HEAD(&fc->entry); |
535 | fc->forget_list_tail = &fc->forget_list_head; | ||
537 | atomic_set(&fc->num_waiting, 0); | 536 | atomic_set(&fc->num_waiting, 0); |
538 | fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; | 537 | fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; |
539 | fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; | 538 | fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; |
@@ -619,7 +618,7 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, | |||
619 | 618 | ||
620 | entry = d_obtain_alias(inode); | 619 | entry = d_obtain_alias(inode); |
621 | if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) { | 620 | if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) { |
622 | entry->d_op = &fuse_dentry_operations; | 621 | d_set_d_op(entry, &fuse_dentry_operations); |
623 | fuse_invalidate_entry_cache(entry); | 622 | fuse_invalidate_entry_cache(entry); |
624 | } | 623 | } |
625 | 624 | ||
@@ -721,7 +720,7 @@ static struct dentry *fuse_get_parent(struct dentry *child) | |||
721 | 720 | ||
722 | parent = d_obtain_alias(inode); | 721 | parent = d_obtain_alias(inode); |
723 | if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) { | 722 | if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) { |
724 | parent->d_op = &fuse_dentry_operations; | 723 | d_set_d_op(parent, &fuse_dentry_operations); |
725 | fuse_invalidate_entry_cache(parent); | 724 | fuse_invalidate_entry_cache(parent); |
726 | } | 725 | } |
727 | 726 | ||