diff --git a/[refs] b/[refs] index a8c3a1ef11c5..b8789b0b498e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5a5fb1ea74d8b82ca1461b885a1334fb21e037be +refs/heads/master: 6dbbcb120570d747b00783820ee02d1e1bcf63de diff --git a/trunk/fs/fuse/dev.c b/trunk/fs/fuse/dev.c index 4967bd40b953..104a62dadb94 100644 --- a/trunk/fs/fuse/dev.c +++ b/trunk/fs/fuse/dev.c @@ -128,12 +128,16 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) } } +/* + * Called with sbput_sem held for read (request_end) or write + * (fuse_put_super). By the time fuse_put_super() is finished, all + * inodes belonging to background requests must be released, so the + * iputs have to be done within the locked region. + */ void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) { iput(req->inode); iput(req->inode2); - if (req->file) - fput(req->file); spin_lock(&fc->lock); list_del(&req->bg_entry); if (fc->num_background == FUSE_MAX_BACKGROUND) { @@ -178,6 +182,11 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) if (fc->mounted) fuse_release_background(fc, req); up_read(&fc->sbput_sem); + + /* fput must go outside sbput_sem, otherwise it can deadlock */ + if (req->file) + fput(req->file); + if (end) end(fc, req); else