linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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, bvanassche@acm.org
Subject: [PATCH v3 08/20] sg: speed sg_poll and sg_get_num_waiting
Date: Wed,  7 Aug 2019 13:42:40 +0200	[thread overview]
Message-ID: <20190807114252.2565-9-dgilbert@interlog.com> (raw)
In-Reply-To: <20190807114252.2565-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.

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 9e9470944fe3..7c9c56bda7ba 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 */
@@ -690,6 +692,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,
@@ -1096,14 +1100,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 		__put_user(-1, ip);
 		return 0;
 	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:
@@ -1255,35 +1252,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;
 }
@@ -1468,6 +1456,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
@@ -1924,6 +1914,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);
 
@@ -2220,6 +2214,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);
@@ -2593,6 +2590,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.22.0


  parent reply	other threads:[~2019-08-07 11:43 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-07 11:42 [PATCH v3 00/20] sg: add v4 interface Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 01/20] sg: move functions around Douglas Gilbert
2019-08-12 14:22   ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 02/20] sg: remove typedefs, type+formatting cleanup Douglas Gilbert
2019-08-12 14:22   ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 03/20] sg: sg_log and is_enabled Douglas Gilbert
2019-08-12 14:23   ` Christoph Hellwig
2019-08-13 22:57     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 04/20] sg: rework sg_poll(), minor changes Douglas Gilbert
2019-08-12 14:23   ` Christoph Hellwig
2019-08-13  0:35     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 05/20] sg: bitops in sg_device Douglas Gilbert
2019-08-12 14:23   ` Christoph Hellwig
2019-08-14  1:35     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 06/20] sg: make open count an atomic Douglas Gilbert
2019-08-12 14:23   ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 07/20] sg: move header to uapi section Douglas Gilbert
2019-08-12 14:24   ` Christoph Hellwig
2019-08-12 14:32     ` Greg KH
2019-08-12 14:35     ` James Bottomley
2019-08-13  0:21     ` Douglas Gilbert
2019-08-07 11:42 ` Douglas Gilbert [this message]
2019-08-12 14:31   ` [PATCH v3 08/20] sg: speed sg_poll and sg_get_num_waiting Christoph Hellwig
2019-08-12 16:31     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 09/20] sg: sg_allow_if_err_recovery and renames Douglas Gilbert
2019-08-12 14:31   ` Christoph Hellwig
2019-08-14  1:26     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 10/20] sg: remove most access_ok functions Douglas Gilbert
2019-08-12 14:32   ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 11/20] sg: replace rq array with lists Douglas Gilbert
2019-08-12 14:35   ` Christoph Hellwig
2019-08-13 23:46     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 12/20] sg: sense buffer rework Douglas Gilbert
2019-08-12 14:37   ` Christoph Hellwig
2019-08-12 16:26     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 13/20] sg: add sg v4 interface support Douglas Gilbert
2019-08-09 23:12   ` James Bottomley
2019-08-11 19:21     ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 14/20] sg: rework debug info Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 15/20] sg: add 8 byte SCSI LUN to sg_scsi_id Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 16/20] sg: expand sg_comm_wr_t Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 17/20] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls Douglas Gilbert
2019-08-09 23:15   ` James Bottomley
2019-08-12 15:37     ` Douglas Gilbert
2019-08-12 16:14       ` Tony Battersby
2019-08-12 18:46         ` James Bottomley
2019-08-12 19:37           ` Tony Battersby
2019-08-07 11:42 ` [PATCH v3 18/20] sg: add some __must_hold macros Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 19/20] sg: first debugfs support Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 20/20] sg: bump version to 4.0.03 Douglas Gilbert
2019-08-08 19:10 ` [PATCH v3 00/20] sg: add v4 interface James Bottomley
2019-08-08 21:08   ` Douglas Gilbert
2019-08-08 21:37     ` Tony Battersby
2019-08-08 22:25       ` Bart Van Assche
2019-08-09 13:28         ` Tony Battersby
2019-08-08 23:00     ` James Bottomley
2019-08-14  4:19       ` Douglas Gilbert
2019-08-15 17:30         ` Bart Van Assche
2019-08-16 15:59           ` Douglas Gilbert
2019-08-16 17:19             ` Greg KH
2019-08-16 18:10             ` Bart Van Assche
2019-08-16 18:44               ` Douglas Gilbert
2019-08-12 15:23   ` Christoph Hellwig

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=20190807114252.2565-9-dgilbert@interlog.com \
    --to=dgilbert@interlog.com \
    --cc=bvanassche@acm.org \
    --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).