From: Douglas Gilbert <dgilbert@interlog.com>
To: linux-scsi@vger.kernel.org
Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com,
hare@suse.de, Hannes Reinecke <hare@suse.com>
Subject: [PATCH v9 08/40] sg: speed sg_poll and sg_get_num_waiting
Date: Tue, 21 Apr 2020 17:52:26 -0400 [thread overview]
Message-ID: <20200421215258.14348-9-dgilbert@interlog.com> (raw)
In-Reply-To: <20200421215258.14348-1-dgilbert@interlog.com>
Track the number of submitted and waiting (for read/receive)
requests on each file descriptor with two atomic integers.
This speeds sg_poll() and ioctl(SG_GET_NUM_WAITING) which
are oft used with the asynchronous (non-blocking) interfaces.
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
drivers/scsi/sg.c | 54 +++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a0efaf505fc1..2cc20f77c303 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -142,6 +142,8 @@ struct sg_fd { /* holds the state of a file descriptor */
struct mutex f_mutex; /* protect against changes in this fd */
int timeout; /* defaults to SG_DEFAULT_TIMEOUT */
int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */
+ atomic_t submitted; /* number inflight or awaiting read */
+ atomic_t waiting; /* number of requests awaiting read */
struct sg_scatter_hold reserve; /* buffer for this file descriptor */
struct list_head rq_list; /* head of request list */
struct fasync_struct *async_qp; /* used by asynchronous notification */
@@ -679,6 +681,8 @@ sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
else
at_head = 1;
+ if (!blocking)
+ atomic_inc(&sfp->submitted);
srp->rq->timeout = timeout;
kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */
blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
@@ -1099,14 +1103,7 @@ sg_ioctl_common(struct file *filp, struct sg_device *sdp, struct sg_fd *sfp,
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
return put_user(-1, ip);
case SG_GET_NUM_WAITING:
- read_lock_irqsave(&sfp->rq_list_lock, iflags);
- val = 0;
- list_for_each_entry(srp, &sfp->rq_list, entry) {
- if ((1 == srp->done) && (!srp->sg_io_owned))
- ++val;
- }
- read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- return put_user(val, ip);
+ return put_user(atomic_read(&sfp->waiting), ip);
case SG_GET_SG_TABLESIZE:
return put_user(sdp->max_sgat_elems, ip);
case SG_SET_RESERVED_SIZE:
@@ -1278,35 +1275,26 @@ sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
}
#endif
+/*
+ * Implements the poll(2) system call for this driver. Returns various EPOLL*
+ * flags OR-ed together.
+ */
static __poll_t
sg_poll(struct file *filp, poll_table * wait)
{
__poll_t p_res = 0;
struct sg_fd *sfp = filp->private_data;
- struct sg_request *srp;
- int count = 0;
- unsigned long iflags;
- if (!sfp)
- return EPOLLERR;
poll_wait(filp, &sfp->read_wait, wait);
- read_lock_irqsave(&sfp->rq_list_lock, iflags);
- list_for_each_entry(srp, &sfp->rq_list, entry) {
- /* if any read waiting, flag it */
- if (p_res == 0 && srp->done == 1 && !srp->sg_io_owned)
- p_res = EPOLLIN | EPOLLRDNORM;
- ++count;
- }
- read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+ if (atomic_read(&sfp->waiting) > 0)
+ p_res = EPOLLIN | EPOLLRDNORM;
- if (sfp->parentdp && SG_IS_DETACHING(sfp->parentdp)) {
+ if (unlikely(SG_IS_DETACHING(sfp->parentdp)))
p_res |= EPOLLHUP;
- } else if (!sfp->cmd_q) {
- if (count == 0)
- p_res |= EPOLLOUT | EPOLLWRNORM;
- } else if (count < SG_MAX_QUEUE) {
+ else if (likely(sfp->cmd_q))
+ p_res |= EPOLLOUT | EPOLLWRNORM;
+ else if (atomic_read(&sfp->submitted) == 0)
p_res |= EPOLLOUT | EPOLLWRNORM;
- }
SG_LOG(3, sfp, "%s: p_res=0x%x\n", __func__, (__force u32)p_res);
return p_res;
}
@@ -1491,6 +1479,8 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
/* Rely on write phase to clean out srp status values, so no "else" */
+ if (!srp->sg_io_owned)
+ atomic_inc(&sfp->waiting);
/*
* Free the request as soon as it is complete so that its resources
* can be reused without waiting for userspace to read() the
@@ -1954,6 +1944,10 @@ sg_finish_rem_req(struct sg_request *srp)
SG_LOG(4, sfp, "%s: srp=0x%p%s\n", __func__, srp,
(srp->res_used) ? " rsv" : "");
+ if (!srp->sg_io_owned) {
+ atomic_dec(&sfp->submitted);
+ atomic_dec(&sfp->waiting);
+ }
if (srp->bio)
ret = blk_rq_unmap_user(srp->bio);
@@ -2251,6 +2245,9 @@ sg_add_sfp(struct sg_device *sdp)
sfp->cmd_q = SG_DEF_COMMAND_Q;
sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
sfp->parentdp = sdp;
+ atomic_set(&sfp->submitted, 0);
+ atomic_set(&sfp->waiting, 0);
+
write_lock_irqsave(&sdp->sfd_lock, iflags);
if (SG_IS_DETACHING(sdp)) {
write_unlock_irqrestore(&sdp->sfd_lock, iflags);
@@ -2622,6 +2619,9 @@ sg_proc_debug_helper(struct seq_file *s, struct sg_device *sdp)
seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
(int) fp->cmd_q, (int) fp->force_packid,
(int) fp->keep_orphan);
+ seq_printf(s, " submitted=%d waiting=%d\n",
+ atomic_read(&fp->submitted),
+ atomic_read(&fp->waiting));
list_for_each_entry(srp, &fp->rq_list, entry) {
hp = &srp->header;
new_interface = (hp->interface_id == '\0') ? 0 : 1;
--
2.26.1
next prev parent reply other threads:[~2020-04-21 21:53 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-21 21:52 [PATCH v9 00/40] sg: add v4 interface Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 01/40] sg: move functions around Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 02/40] sg: remove typedefs, type+formatting cleanup Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 03/40] sg: sg_log and is_enabled Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 04/40] sg: rework sg_poll(), minor changes Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 05/40] sg: bitops in sg_device Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 06/40] sg: make open count an atomic Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 07/40] sg: move header to uapi section Douglas Gilbert
2020-04-21 21:52 ` Douglas Gilbert [this message]
2020-04-21 21:52 ` [PATCH v9 09/40] sg: sg_allow_if_err_recovery and renames Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 10/40] sg: improve naming Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 11/40] sg: change rwlock to spinlock Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 12/40] sg: ioctl handling Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 13/40] sg: split sg_read Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 14/40] sg: sg_common_write add structure for arguments Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 15/40] sg: rework sg_vma_fault Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 16/40] sg: rework sg_mmap Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 17/40] sg: replace sg_allow_access Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 18/40] sg: rework scatter gather handling Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 19/40] sg: introduce request state machine Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 20/40] sg: sg_find_srp_by_id Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 21/40] sg: sg_fill_request_element Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 22/40] sg: printk change %p to %pK Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 23/40] sg: xarray for fds in device Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 24/40] sg: xarray for reqs in fd Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 25/40] sg: replace rq array with lists Douglas Gilbert
2020-04-24 15:21 ` kbuild test robot
2020-04-21 21:52 ` [PATCH v9 26/40] sg: sense buffer rework Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 27/40] sg: add sg v4 interface support Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 28/40] sg: rework debug info Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 29/40] sg: add 8 byte SCSI LUN to sg_scsi_id Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 30/40] sg: expand sg_comm_wr_t Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 31/40] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 32/40] sg: add some __must_hold macros Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 33/40] sg: move procfs objects to avoid forward decls Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 34/40] sg: protect multiple receivers Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 35/40] sg: first debugfs support Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 36/40] sg: rework mmap support Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 37/40] sg: defang allow_dio Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 38/40] sg: warn v3 write system call users Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 39/40] sg: add mmap_sz tracking Douglas Gilbert
2020-04-21 21:52 ` [PATCH v9 40/40] sg: bump version to 4.0.09 Douglas Gilbert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200421215258.14348-9-dgilbert@interlog.com \
--to=dgilbert@interlog.com \
--cc=hare@suse.com \
--cc=hare@suse.de \
--cc=jejb@linux.vnet.ibm.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).