Received: by 2002:a25:c205:0:0:0:0:0 with SMTP id s5csp4501341ybf; Wed, 4 Mar 2020 05:17:10 -0800 (PST) X-Google-Smtp-Source: ADFU+vvGh2a48ufSfsO6oUuleDM0hUuYuUGPrjmvvyChDY6XVg3OXo9K5rxzEoh7FIXvGYOTrFe5 X-Received: by 2002:a9d:708a:: with SMTP id l10mr2327280otj.371.1583327830193; Wed, 04 Mar 2020 05:17:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1583327830; cv=none; d=google.com; s=arc-20160816; b=Qx+ee+MwYQSFnjOzmsS4p25ijU/7mRl8F+Uugzh1YUxjKzshnU/Z0EmqUutOfJ2JsV 1W8au2oWaOw+bHiKdy9915KtFOzJdZFiptGJisyK1Vb2YvVyRNGfQPq1nEOump0LoFeD n2/etdjIekpO+4N4h8qraXnWXeRgbbt5sBT65tLHIgwTBXdKIniubwDBkfHG3bLYCPmC SsQaFxxGl1IVuia4JPYGrJg4mdDK/JBsJVA6tr8rSdARh/6zJ+oRO0pOA0K97qWuVqr/ jjHTJOrEH71KmsV1yEQXg1pbvqYdvPtn8F6ctX/ZXVZyvuHCL9CegMZ8deUAJ1pxRh9v nYHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=k4NsppHUexOnTxLarLxr/xLsc9hIMTHgPPSr8BCSfpY=; b=noYPBxEc2ZG/zOseQfF9ijvchjJ+BQEWGDjpoJNfeL0Nszed6SnfgurmDYe9AaXes8 9cV9HHq8xB/uBdKJKJMJ4EJ/SVmYmufTCZCyO/LGcgu/UFW22wD9JE0sbQriUmlXO/Bq Qj8JPM2exVC4d+14OwIiD+dFGLVyRYiXEnFE9KKjri0gFwKb4CyI6iYlKFwzIr8bCqAz 9DBFBdm3z+ntZ3+SCVuhOqhXrjyXBXh+7xMTw8ZMYL+YushAZQHk/1l2tRlp+C0ZBx9L JzuYE4qbAiy3qVR5yQrHsRIp7Qk6vrGJB9yH5XGhQJ9Ar+OnN39yrnZdRPo12M0tKzpX /EGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=LuHDyfm6; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c11si1493741ots.280.2020.03.04.05.16.57; Wed, 04 Mar 2020 05:17:10 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=LuHDyfm6; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388183AbgCDNPW (ORCPT + 99 others); Wed, 4 Mar 2020 08:15:22 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36068 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387992AbgCDNPV (ORCPT ); Wed, 4 Mar 2020 08:15:21 -0500 Received: by mail-wm1-f68.google.com with SMTP id g83so1834026wme.1; Wed, 04 Mar 2020 05:15:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=k4NsppHUexOnTxLarLxr/xLsc9hIMTHgPPSr8BCSfpY=; b=LuHDyfm6gdQcURKD2ay9V1I3LG75N8yu3592y3geIM6VGblTAMO2OZu9eRwGk/QmH5 hx5C/I6uhyTtRyQ8/8gj1EIUobCoK/kzRaC/DTcla7t2OUJZx2hhWG7ngT4covPHsfyA ITLKrp+6l0u6Mdhtx+cH4oVd2VaVp1hzxeufBXypRxwxqKfmqRLhhjSC4E0PpdyzejE7 edu3fm9lGhCKNNki+IMnJ0Ph5kY7Vfk/iAC+LzaF9zaGmTaNzeEPS5yRAdqIi0TpBt83 TBbArwSEozqbd/EVId3eNxbzQrcCGA/SfVM6U683oyHhxJFDHFSqcvzdNxz48Iw4V6vQ Pbtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=k4NsppHUexOnTxLarLxr/xLsc9hIMTHgPPSr8BCSfpY=; b=d3HYWFgYLpwTnBZbaJq3n5zTOwIyGS/YmPlk6CPW+kDiZUtdZS5Em22Si1g4vjLKro 5VH51HZBjKUmrpeB6fRWmPzmjHOQcVp/9WDDg/AEfI6Z52R03cZCgFzmufGme5mCCPte aWGeSe7oqQrrbIWEQaoUUYW8OzkIeSwdi2rIvHvVnCLDV82plL6vpxyNFKZ1Tgr99+R2 t0QLRVC0A4ZV2ZM+1RXxV2bI+yCXmrYrqG8ZmisWEjE4UtECjZ5DEtLw+/ZWo304p5iR kX6tW0vDqjoARuUnWBaf4+pWZLuayeZjSYIaqxiKpSzgU3j4JSOLrnYv2vPGUOXTerJ3 QtIw== X-Gm-Message-State: ANhLgQ3O2KZ05cQ5Y9gZSRxoLSaU3Z+Bd1Brn2JB4rsXAZnIVqjyRgn2 dfm4HjtB89+MRntww7H0Wec= X-Received: by 2002:a1c:e0d6:: with SMTP id x205mr3439817wmg.29.1583327718452; Wed, 04 Mar 2020 05:15:18 -0800 (PST) Received: from localhost.localdomain ([109.126.130.242]) by smtp.gmail.com with ESMTPSA id c14sm24746746wro.36.2020.03.04.05.15.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2020 05:15:17 -0800 (PST) From: Pavel Begunkov To: Jens Axboe , io-uring@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/4] io_uring/io-wq: forward submission ref to async Date: Wed, 4 Mar 2020 16:14:12 +0300 Message-Id: <8990627d9815c320e2bd5e6181e5daf876c3dc47.1583314087.git.asml.silence@gmail.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org First it changes io-wq interfaces. It replaces {get,put}_work() with free_work(), which guaranteed to be called exactly once. It also enforces free_work() callback to be non-NULL. io_uring follows the changes and instead of putting a submission reference in io_put_req_async_completion(), it will be done in io_free_work(). As removes io_get_work() with corresponding refcount_inc(), the ref balance is maintained. Signed-off-by: Pavel Begunkov --- fs/io-wq.c | 29 ++++++++++++++--------------- fs/io-wq.h | 6 ++---- fs/io_uring.c | 31 +++++++++++-------------------- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/fs/io-wq.c b/fs/io-wq.c index 82e76011d409..eda36f997dea 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -107,8 +107,7 @@ struct io_wq { struct io_wqe **wqes; unsigned long state; - get_work_fn *get_work; - put_work_fn *put_work; + free_work_fn *free_work; struct task_struct *manager; struct user_struct *user; @@ -509,16 +508,11 @@ static void io_worker_handle_work(struct io_worker *worker) if (test_bit(IO_WQ_BIT_CANCEL, &wq->state)) work->flags |= IO_WQ_WORK_CANCEL; - if (wq->get_work) - wq->get_work(work); - old_work = work; work->func(&work); work = (old_work == work) ? NULL : work; io_assign_current_work(worker, work); - - if (wq->put_work) - wq->put_work(old_work); + wq->free_work(old_work); if (hash != -1U) { spin_lock_irq(&wqe->lock); @@ -749,14 +743,17 @@ static bool io_wq_can_queue(struct io_wqe *wqe, struct io_wqe_acct *acct, return true; } -static void io_run_cancel(struct io_wq_work *work) +static void io_run_cancel(struct io_wq_work *work, struct io_wqe *wqe) { + struct io_wq *wq = wqe->wq; + do { struct io_wq_work *old_work = work; work->flags |= IO_WQ_WORK_CANCEL; work->func(&work); work = (work == old_work) ? NULL : work; + wq->free_work(old_work); } while (work); } @@ -773,7 +770,7 @@ static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work) * It's close enough to not be an issue, fork() has the same delay. */ if (unlikely(!io_wq_can_queue(wqe, acct, work))) { - io_run_cancel(work); + io_run_cancel(work, wqe); return; } @@ -912,7 +909,7 @@ static enum io_wq_cancel io_wqe_cancel_cb_work(struct io_wqe *wqe, spin_unlock_irqrestore(&wqe->lock, flags); if (found) { - io_run_cancel(work); + io_run_cancel(work, wqe); return IO_WQ_CANCEL_OK; } @@ -987,7 +984,7 @@ static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe, spin_unlock_irqrestore(&wqe->lock, flags); if (found) { - io_run_cancel(work); + io_run_cancel(work, wqe); return IO_WQ_CANCEL_OK; } @@ -1064,6 +1061,9 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) int ret = -ENOMEM, node; struct io_wq *wq; + if (WARN_ON_ONCE(!data->free_work)) + return ERR_PTR(-EINVAL); + wq = kzalloc(sizeof(*wq), GFP_KERNEL); if (!wq) return ERR_PTR(-ENOMEM); @@ -1074,8 +1074,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) return ERR_PTR(-ENOMEM); } - wq->get_work = data->get_work; - wq->put_work = data->put_work; + wq->free_work = data->free_work; /* caller must already hold a reference to this */ wq->user = data->user; @@ -1132,7 +1131,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) bool io_wq_get(struct io_wq *wq, struct io_wq_data *data) { - if (data->get_work != wq->get_work || data->put_work != wq->put_work) + if (data->free_work != wq->free_work) return false; return refcount_inc_not_zero(&wq->use_refs); diff --git a/fs/io-wq.h b/fs/io-wq.h index a0978d6958f0..2117b9a4f161 100644 --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -81,14 +81,12 @@ struct io_wq_work { *(work) = (struct io_wq_work){ .func = _func }; \ } while (0) \ -typedef void (get_work_fn)(struct io_wq_work *); -typedef void (put_work_fn)(struct io_wq_work *); +typedef void (free_work_fn)(struct io_wq_work *); struct io_wq_data { struct user_struct *user; - get_work_fn *get_work; - put_work_fn *put_work; + free_work_fn *free_work; }; struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data); diff --git a/fs/io_uring.c b/fs/io_uring.c index 40ca9e6a5ace..0d6f4b3b8f13 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -1558,8 +1558,8 @@ static void io_put_req(struct io_kiocb *req) io_free_req(req); } -static void io_put_req_async_completion(struct io_kiocb *req, - struct io_wq_work **workptr) +static void io_steal_work(struct io_kiocb *req, + struct io_wq_work **workptr) { /* * It's in an io-wq worker, so there always should be at least @@ -1569,7 +1569,6 @@ static void io_put_req_async_completion(struct io_kiocb *req, * It also means, that if the counter dropped to 1, then there is * no asynchronous users left, so it's safe to steal the next work. */ - refcount_dec(&req->refs); if (refcount_read(&req->refs) == 1) { struct io_kiocb *nxt = NULL; @@ -2578,7 +2577,7 @@ static bool io_req_cancelled(struct io_kiocb *req) if (req->work.flags & IO_WQ_WORK_CANCEL) { req_set_fail_links(req); io_cqring_add_event(req, -ECANCELED); - io_double_put_req(req); + io_put_req(req); return true; } @@ -2606,7 +2605,7 @@ static void io_fsync_finish(struct io_wq_work **workptr) if (io_req_cancelled(req)) return; __io_fsync(req); - io_put_req_async_completion(req, workptr); + io_steal_work(req, workptr); } static int io_fsync(struct io_kiocb *req, bool force_nonblock) @@ -2639,7 +2638,7 @@ static void io_fallocate_finish(struct io_wq_work **workptr) if (io_req_cancelled(req)) return; __io_fallocate(req); - io_put_req_async_completion(req, workptr); + io_steal_work(req, workptr); } static int io_fallocate_prep(struct io_kiocb *req, @@ -3006,7 +3005,7 @@ static void io_close_finish(struct io_wq_work **workptr) /* not cancellable, don't do io_req_cancelled() */ __io_close_finish(req); - io_put_req_async_completion(req, workptr); + io_steal_work(req, workptr); } static int io_close(struct io_kiocb *req, bool force_nonblock) @@ -3452,7 +3451,7 @@ static void io_accept_finish(struct io_wq_work **workptr) if (io_req_cancelled(req)) return; __io_accept(req, false); - io_put_req_async_completion(req, workptr); + io_steal_work(req, workptr); } #endif @@ -4719,7 +4718,7 @@ static void io_wq_submit_work(struct io_wq_work **workptr) io_put_req(req); } - io_put_req_async_completion(req, workptr); + io_steal_work(req, workptr); } static int io_req_needs_file(struct io_kiocb *req, int fd) @@ -6105,21 +6104,14 @@ static int io_sqe_files_update(struct io_ring_ctx *ctx, void __user *arg, return __io_sqe_files_update(ctx, &up, nr_args); } -static void io_put_work(struct io_wq_work *work) +static void io_free_work(struct io_wq_work *work) { struct io_kiocb *req = container_of(work, struct io_kiocb, work); - /* Consider that io_put_req_async_completion() relies on this ref */ + /* Consider that io_steal_work() relies on this ref */ io_put_req(req); } -static void io_get_work(struct io_wq_work *work) -{ - struct io_kiocb *req = container_of(work, struct io_kiocb, work); - - refcount_inc(&req->refs); -} - static int io_init_wq_offload(struct io_ring_ctx *ctx, struct io_uring_params *p) { @@ -6130,8 +6122,7 @@ static int io_init_wq_offload(struct io_ring_ctx *ctx, int ret = 0; data.user = ctx->user; - data.get_work = io_get_work; - data.put_work = io_put_work; + data.free_work = io_free_work; if (!(p->flags & IORING_SETUP_ATTACH_WQ)) { /* Do QD, or 4 * CPUS, whatever is smallest */ -- 2.24.0