aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-10-17 02:31:04 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:04 -0400
commita131de0a482ac95e6469f56981c7b063593fdc5d (patch)
tree0799985119f15525cc8c3c93a4cacad307405a5a
parent819c4b3b4009275caae973691378235c177a1429 (diff)
fuse: no abort on interrupt
Don't set 'aborted' flag on a request if it's interrupted. We have to wait for the answer anyway, and this would only a very little time while copying the reply. This means, that write() on the fuse device will not return -ENOENT during normal operation, only if the filesystem is aborted by a forced umount or through the fusectl interface. This could simplify userspace code somewhat when backward compatibility with earlier kernel versions is not required. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/fuse/dev.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c78f60e1ba5d..cc6c2908fb12 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -273,28 +273,41 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
273 queue_interrupt(fc, req); 273 queue_interrupt(fc, req);
274 } 274 }
275 275
276 if (req->force) { 276 if (!req->force) {
277 spin_unlock(&fc->lock);
278 wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
279 spin_lock(&fc->lock);
280 } else {
281 sigset_t oldset; 277 sigset_t oldset;
282 278
283 /* Only fatal signals may interrupt this */ 279 /* Only fatal signals may interrupt this */
284 block_sigs(&oldset); 280 block_sigs(&oldset);
285 wait_answer_interruptible(fc, req); 281 wait_answer_interruptible(fc, req);
286 restore_sigs(&oldset); 282 restore_sigs(&oldset);
283
284 if (req->aborted)
285 goto aborted;
286 if (req->state == FUSE_REQ_FINISHED)
287 return;
288
289 /* Request is not yet in userspace, bail out */
290 if (req->state == FUSE_REQ_PENDING) {
291 list_del(&req->list);
292 __fuse_put_request(req);
293 req->out.h.error = -EINTR;
294 return;
295 }
287 } 296 }
288 297
289 if (req->aborted) 298 /*
290 goto aborted; 299 * Either request is already in userspace, or it was forced.
291 if (req->state == FUSE_REQ_FINISHED) 300 * Wait it out.
292 return; 301 */
302 spin_unlock(&fc->lock);
303 wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
304 spin_lock(&fc->lock);
293 305
294 req->out.h.error = -EINTR; 306 if (!req->aborted)
295 req->aborted = 1; 307 return;
296 308
297 aborted: 309 aborted:
310 BUG_ON(req->state != FUSE_REQ_FINISHED);
298 if (req->locked) { 311 if (req->locked) {
299 /* This is uninterruptible sleep, because data is 312 /* This is uninterruptible sleep, because data is
300 being copied to/from the buffers of req. During 313 being copied to/from the buffers of req. During
@@ -305,14 +318,6 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
305 wait_event(req->waitq, !req->locked); 318 wait_event(req->waitq, !req->locked);
306 spin_lock(&fc->lock); 319 spin_lock(&fc->lock);
307 } 320 }
308 if (req->state == FUSE_REQ_PENDING) {
309 list_del(&req->list);
310 __fuse_put_request(req);
311 } else if (req->state == FUSE_REQ_SENT) {
312 spin_unlock(&fc->lock);
313 wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
314 spin_lock(&fc->lock);
315 }
316} 321}
317 322
318static unsigned len_args(unsigned numargs, struct fuse_arg *args) 323static unsigned len_args(unsigned numargs, struct fuse_arg *args)