aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 4967bd40b953..104a62dadb94 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -128,12 +128,16 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
128 } 128 }
129} 129}
130 130
131/*
132 * Called with sbput_sem held for read (request_end) or write
133 * (fuse_put_super). By the time fuse_put_super() is finished, all
134 * inodes belonging to background requests must be released, so the
135 * iputs have to be done within the locked region.
136 */
131void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) 137void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
132{ 138{
133 iput(req->inode); 139 iput(req->inode);
134 iput(req->inode2); 140 iput(req->inode2);
135 if (req->file)
136 fput(req->file);
137 spin_lock(&fc->lock); 141 spin_lock(&fc->lock);
138 list_del(&req->bg_entry); 142 list_del(&req->bg_entry);
139 if (fc->num_background == FUSE_MAX_BACKGROUND) { 143 if (fc->num_background == FUSE_MAX_BACKGROUND) {
@@ -178,6 +182,11 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
178 if (fc->mounted) 182 if (fc->mounted)
179 fuse_release_background(fc, req); 183 fuse_release_background(fc, req);
180 up_read(&fc->sbput_sem); 184 up_read(&fc->sbput_sem);
185
186 /* fput must go outside sbput_sem, otherwise it can deadlock */
187 if (req->file)
188 fput(req->file);
189
181 if (end) 190 if (end)
182 end(fc, req); 191 end(fc, req);
183 else 192 else