aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/fuse_i.h
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-04-11 15:14:26 -0400
committerMiklos Szeredi <miklos@szeredi.hu>2006-04-11 15:14:26 -0400
commit73ce8355c243a434524a34c05cc417dd0467996e (patch)
treea5bc5bfb31c41a5806caf763533943e7411e6543 /fs/fuse/fuse_i.h
parent2514395ef88b46e895726a8d40966cb83de7940c (diff)
[fuse] fix deadlock between fuse_put_super() and request_end()
A deadlock was possible, when the last reference to the superblock was held due to a background request containing a file reference. Releasing the file would release the vfsmount which in turn would release the superblock. Since sbput_sem is held during the fput() and fuse_put_super() tries to acquire this same semaphore, a deadlock results. The chosen soltuion is to get rid of sbput_sem, and instead use the spinlock to ensure the referenced inodes/file are released only once. Since the actual release may sleep, defer these outside the locked region, but using local variables instead of the structure members. This is a much more rubust solution. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Diffstat (limited to 'fs/fuse/fuse_i.h')
-rw-r--r--fs/fuse/fuse_i.h12
1 files changed, 3 insertions, 9 deletions
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 19c7185a7546..ee9b83042510 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -255,15 +255,9 @@ struct fuse_conn {
255 /** waitq for blocked connection */ 255 /** waitq for blocked connection */
256 wait_queue_head_t blocked_waitq; 256 wait_queue_head_t blocked_waitq;
257 257
258 /** RW semaphore for exclusion with fuse_put_super() */
259 struct rw_semaphore sbput_sem;
260
261 /** The next unique request id */ 258 /** The next unique request id */
262 u64 reqctr; 259 u64 reqctr;
263 260
264 /** Mount is active */
265 unsigned mounted;
266
267 /** Connection established, cleared on umount, connection 261 /** Connection established, cleared on umount, connection
268 abort and device release */ 262 abort and device release */
269 unsigned connected; 263 unsigned connected;
@@ -474,11 +468,11 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req);
474void request_send_background(struct fuse_conn *fc, struct fuse_req *req); 468void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
475 469
476/** 470/**
477 * Release inodes and file associated with background request 471 * Remove request from the the background list
478 */ 472 */
479void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req); 473void fuse_remove_background(struct fuse_conn *fc, struct fuse_req *req);
480 474
481/* Abort all requests */ 475/** Abort all requests */
482void fuse_abort_conn(struct fuse_conn *fc); 476void fuse_abort_conn(struct fuse_conn *fc);
483 477
484/** 478/**