diff options
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 73 |
1 files changed, 13 insertions, 60 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index e4ada021d087..d4c869c6d01b 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -103,20 +103,9 @@ static struct fuse_req *do_get_request(struct fuse_conn *fc) | |||
103 | return req; | 103 | return req; |
104 | } | 104 | } |
105 | 105 | ||
106 | /* This can return NULL, but only in case it's interrupted by a SIGKILL */ | ||
106 | struct fuse_req *fuse_get_request(struct fuse_conn *fc) | 107 | struct fuse_req *fuse_get_request(struct fuse_conn *fc) |
107 | { | 108 | { |
108 | if (down_interruptible(&fc->outstanding_sem)) | ||
109 | return NULL; | ||
110 | return do_get_request(fc); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Non-interruptible version of the above function is for operations | ||
115 | * which can't legally return -ERESTART{SYS,NOINTR}. This can still | ||
116 | * return NULL, but only in case the signal is SIGKILL. | ||
117 | */ | ||
118 | struct fuse_req *fuse_get_request_nonint(struct fuse_conn *fc) | ||
119 | { | ||
120 | int intr; | 109 | int intr; |
121 | sigset_t oldset; | 110 | sigset_t oldset; |
122 | 111 | ||
@@ -241,43 +230,20 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req) | |||
241 | get_file(req->file); | 230 | get_file(req->file); |
242 | } | 231 | } |
243 | 232 | ||
244 | static int request_wait_answer_nonint(struct fuse_req *req) | ||
245 | { | ||
246 | int err; | ||
247 | sigset_t oldset; | ||
248 | block_sigs(&oldset); | ||
249 | err = wait_event_interruptible(req->waitq, req->finished); | ||
250 | restore_sigs(&oldset); | ||
251 | return err; | ||
252 | } | ||
253 | |||
254 | /* Called with fuse_lock held. Releases, and then reacquires it. */ | 233 | /* Called with fuse_lock held. Releases, and then reacquires it. */ |
255 | static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req, | 234 | static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) |
256 | int interruptible) | ||
257 | { | 235 | { |
258 | int intr; | 236 | sigset_t oldset; |
259 | 237 | ||
260 | spin_unlock(&fuse_lock); | 238 | spin_unlock(&fuse_lock); |
261 | if (interruptible) | 239 | block_sigs(&oldset); |
262 | intr = wait_event_interruptible(req->waitq, req->finished); | 240 | wait_event_interruptible(req->waitq, req->finished); |
263 | else | 241 | restore_sigs(&oldset); |
264 | intr = request_wait_answer_nonint(req); | ||
265 | spin_lock(&fuse_lock); | 242 | spin_lock(&fuse_lock); |
266 | if (intr && interruptible && req->sent) { | 243 | if (req->finished) |
267 | /* If request is already in userspace, only allow KILL | ||
268 | signal to interrupt */ | ||
269 | spin_unlock(&fuse_lock); | ||
270 | intr = request_wait_answer_nonint(req); | ||
271 | spin_lock(&fuse_lock); | ||
272 | } | ||
273 | if (!intr) | ||
274 | return; | 244 | return; |
275 | 245 | ||
276 | if (!interruptible || req->sent) | 246 | req->out.h.error = -EINTR; |
277 | req->out.h.error = -EINTR; | ||
278 | else | ||
279 | req->out.h.error = -ERESTARTNOINTR; | ||
280 | |||
281 | req->interrupted = 1; | 247 | req->interrupted = 1; |
282 | if (req->locked) { | 248 | if (req->locked) { |
283 | /* This is uninterruptible sleep, because data is | 249 | /* This is uninterruptible sleep, because data is |
@@ -330,8 +296,10 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req) | |||
330 | wake_up(&fc->waitq); | 296 | wake_up(&fc->waitq); |
331 | } | 297 | } |
332 | 298 | ||
333 | static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req, | 299 | /* |
334 | int interruptible) | 300 | * This can only be interrupted by a SIGKILL |
301 | */ | ||
302 | void request_send(struct fuse_conn *fc, struct fuse_req *req) | ||
335 | { | 303 | { |
336 | req->isreply = 1; | 304 | req->isreply = 1; |
337 | spin_lock(&fuse_lock); | 305 | spin_lock(&fuse_lock); |
@@ -345,26 +313,11 @@ static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req, | |||
345 | after request_end() */ | 313 | after request_end() */ |
346 | __fuse_get_request(req); | 314 | __fuse_get_request(req); |
347 | 315 | ||
348 | request_wait_answer(fc, req, interruptible); | 316 | request_wait_answer(fc, req); |
349 | } | 317 | } |
350 | spin_unlock(&fuse_lock); | 318 | spin_unlock(&fuse_lock); |
351 | } | 319 | } |
352 | 320 | ||
353 | void request_send(struct fuse_conn *fc, struct fuse_req *req) | ||
354 | { | ||
355 | request_send_wait(fc, req, 1); | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * Non-interruptible version of the above function is for operations | ||
360 | * which can't legally return -ERESTART{SYS,NOINTR}. This can still | ||
361 | * be interrupted but only with SIGKILL. | ||
362 | */ | ||
363 | void request_send_nonint(struct fuse_conn *fc, struct fuse_req *req) | ||
364 | { | ||
365 | request_send_wait(fc, req, 0); | ||
366 | } | ||
367 | |||
368 | static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) | 321 | static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) |
369 | { | 322 | { |
370 | spin_lock(&fuse_lock); | 323 | spin_lock(&fuse_lock); |