Skip to content

Commit bc9dde6

Browse files
LiBaokun96brauner
authored andcommitted
cachefiles: make on-demand read killable
Replacing wait_for_completion() with wait_for_completion_killable() in cachefiles_ondemand_send_req() allows us to kill processes that might trigger a hunk_task if the daemon is abnormal. But now only CACHEFILES_OP_READ is killable, because OP_CLOSE and OP_OPEN is initiated from kworker context and the signal is prohibited in these kworker. Note that when the req in xas changes, i.e. xas_load(&xas) != req, it means that a process will complete the current request soon, so wait again for the request to be completed. In addition, add the cachefiles_ondemand_finish_req() helper function to simplify the code. Suggested-by: Hou Tao <[email protected]> Signed-off-by: Baokun Li <[email protected]> Link: https://lore.kernel.org/r/[email protected] Acked-by: Jeff Layton <[email protected]> Reviewed-by: Jia Zhu <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 85e833c commit bc9dde6

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

fs/cachefiles/ondemand.c

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,20 @@ static struct cachefiles_req *cachefiles_ondemand_select_req(struct xa_state *xa
380380
return NULL;
381381
}
382382

383+
static inline bool cachefiles_ondemand_finish_req(struct cachefiles_req *req,
384+
struct xa_state *xas, int err)
385+
{
386+
if (unlikely(!xas || !req))
387+
return false;
388+
389+
if (xa_cmpxchg(xas->xa, xas->xa_index, req, NULL, 0) != req)
390+
return false;
391+
392+
req->error = err;
393+
complete(&req->done);
394+
return true;
395+
}
396+
383397
ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
384398
char __user *_buffer, size_t buflen)
385399
{
@@ -443,16 +457,8 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
443457
out:
444458
cachefiles_put_object(req->object, cachefiles_obj_put_read_req);
445459
/* Remove error request and CLOSE request has no reply */
446-
if (ret || msg->opcode == CACHEFILES_OP_CLOSE) {
447-
xas_reset(&xas);
448-
xas_lock(&xas);
449-
if (xas_load(&xas) == req) {
450-
req->error = ret;
451-
complete(&req->done);
452-
xas_store(&xas, NULL);
453-
}
454-
xas_unlock(&xas);
455-
}
460+
if (ret || msg->opcode == CACHEFILES_OP_CLOSE)
461+
cachefiles_ondemand_finish_req(req, &xas, ret);
456462
cachefiles_req_put(req);
457463
return ret ? ret : n;
458464
}
@@ -544,8 +550,18 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
544550
goto out;
545551

546552
wake_up_all(&cache->daemon_pollwq);
547-
wait_for_completion(&req->done);
548-
ret = req->error;
553+
wait:
554+
ret = wait_for_completion_killable(&req->done);
555+
if (!ret) {
556+
ret = req->error;
557+
} else {
558+
ret = -EINTR;
559+
if (!cachefiles_ondemand_finish_req(req, &xas, ret)) {
560+
/* Someone will complete it soon. */
561+
cpu_relax();
562+
goto wait;
563+
}
564+
}
549565
cachefiles_req_put(req);
550566
return ret;
551567
out:

0 commit comments

Comments
 (0)