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
Subject: [PATCH v18 82/83] sg: pollable and non-pollable requests
Date: Tue, 27 Apr 2021 17:57:32 -0400 [thread overview]
Message-ID: <20210427215733.417746-84-dgilbert@interlog.com> (raw)
In-Reply-To: <20210427215733.417746-1-dgilbert@interlog.com>
Pollable is a new categorization of requests that implies
ioctl(SG_IORECEIVE) can be used to complete a request. This new
category displaces "sync invocation" which originally meant that
ioctl(SG_IO) had been called. However multiple requests (mrq-s)
blur the "sync invocation" picture.
Whether or not a request will complete by itself or requires
ioctl(SG_IORECEIVE) [ioctl(SG_IORECEIVE_V3) or read(2)] and
associated helpers (e.g. ioctl(SG_GET_NUM_WAITING) and poll(2)) is
better. All requests can be divided into two groups that are
termed as pollable and non-pollable. Now both groups have their
own atomic counters for requests in AWAIT_RCV state: poll_waiting
and nonp_waiting. When a user calls ioctl(SG_GET_NUM_WAITING) they
are getting the current value of poll_waiting. The nonp_waiting
value is important for the driver's internal processing (e.g. of
shared variable blocking (svb) mrq-s) but is no business of a
user doing a single async request on the same file descriptor.
Some function names where changed for clarity.
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
drivers/scsi/sg.c | 936 ++++++++++++++++++++++++----------------------
1 file changed, 487 insertions(+), 449 deletions(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 773843a14038..5328befc0893 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -110,6 +110,12 @@ enum sg_shr_var {
SG_SHR_WS_RQ, /* write-side sharing on this data carrying req */
};
+enum sg_search_srp {
+ SG_SEARCH_ANY = 0, /* searching unconstrained by pack_id or tag */
+ SG_SEARCH_BY_PACK_ID,
+ SG_SEARCH_BY_TAG,
+};
+
/* If sum_of(dlen) of a fd exceeds this, write() will yield E2BIG */
#define SG_TOT_FD_THRESHOLD (32 * 1024 * 1024)
@@ -124,10 +130,9 @@ enum sg_shr_var {
#define SG_MAX_RSV_REQS 8 /* number of svb requests done asynchronously; assume small-ish */
#define SG_PACK_ID_WILDCARD (-1)
-#define SG_TAG_WILDCARD (-1)
+#define SG_TAG_WILDCARD SG_PACK_ID_WILDCARD
#define SG_ADD_RQ_MAX_RETRIES 40 /* to stop infinite _trylock(s) */
-#define SG_DEF_BLK_POLL_LOOP_COUNT 1000 /* may allow user to tweak this */
/* Bit positions (flags) for sg_request::frq_lt_bm bitmask, lt: long term */
#define SG_FRQ_LT_RESERVED 0 /* marks a reserved request */
@@ -136,16 +141,15 @@ enum sg_shr_var {
/* Bit positions (flags) for sg_request::frq_pc_bm bitmask. pc: per command */
#define SG_FRQ_PC_IS_V4I 0 /* true (set) when is v4 interface */
#define SG_FRQ_PC_IS_ORPHAN 1 /* owner of request gone */
-#define SG_FRQ_PC_SYNC_INVOC 2 /* synchronous (blocking) invocation */
+#define SG_FRQ_PC_POLLABLE 2 /* sg_ioreceive may be called */
#define SG_FRQ_PC_US_XFER 3 /* kernel<-->user_space data transfer */
#define SG_FRQ_PC_ABORTING 4 /* in process of aborting this cmd */
#define SG_FRQ_PC_DEACT_ORPHAN 5 /* not keeping orphan so de-activate */
#define SG_FRQ_PC_RECEIVING 6 /* guard against multiple receivers */
#define SG_FRQ_PC_FOR_MMAP 7 /* request needs PAGE_SIZE elements */
-#define SG_FRQ_PC_COUNT_ACTIVE 8 /* sfp->submitted + waiting active */
-#define SG_FRQ_PC_ISSUED 9 /* blk_execute_rq_nowait() finished */
-#define SG_FRQ_POLL_SLEPT 10 /* stop re-entry of hybrid_sleep() */
-#define SG_FRQ_PC_PART_MRQ 11 /* this cmd part of mrq array */
+#define SG_FRQ_PC_ISSUED 8 /* blk_execute_rq_nowait() finished */
+#define SG_FRQ_POLL_SLEPT 9 /* stop re-entry of hybrid_sleep() */
+#define SG_FRQ_PC_PART_MRQ 10 /* this cmd part of mrq array */
/* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
#define SG_FFD_FORCE_PACKID 0 /* receive only given pack_id/tag */
@@ -164,6 +168,7 @@ enum sg_shr_var {
#define SG_FFD_SVB_ACTIVE 13 /* shared variable blocking active */
#define SG_FFD_RESHARE 14 /* reshare limits to single rsv req */
#define SG_FFD_CAN_REUSE_BIO 15 /* uniform svb --> can re-use bio_s */
+#define SG_FFD_SIG_PEND 16 /* (fatal) signal pending */
/* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
#define SG_FDEV_EXCLUDE 0 /* have fd open with O_EXCL */
@@ -294,7 +299,8 @@ struct sg_fd { /* holds the state of a file descriptor */
int low_await_idx; /* previous or lower await index */
u32 idx; /* my index within parent's sfp_arr */
atomic_t submitted; /* number inflight or awaiting receive */
- atomic_t waiting; /* number of requests awaiting receive */
+ atomic_t poll_waiting; /* # of pollable requests awaiting receive */
+ atomic_t nonp_waiting; /* # of non-pollable requests awaiting rcv */
atomic_t inactives; /* number of inactive requests */
atomic_t sum_fd_dlens; /* when tot_fd_thresh>0 this is sum_of(dlen) */
atomic_t mrq_id_abort; /* inactive when 0, else id if aborted */
@@ -314,6 +320,15 @@ struct sg_fd { /* holds the state of a file descriptor */
struct sg_request *rsv_arr[SG_MAX_RSV_REQS];
};
+struct sg_fd_pollable { /* sfp plus adds context for completions */
+ struct sg_fd *fp;
+ bool pollable; /* can async machinery find this req ? */
+ bool immed; /* immed set on ioctl(sg_ioreceive) ? */
+ bool part_mrq;
+ enum sg_search_srp find_by;
+ int pack_id_tag;
+};
+
struct sg_device { /* holds the state of each scsi generic device */
struct scsi_device *device;
wait_queue_head_t open_wait; /* queue open() when O_EXCL present */
@@ -349,9 +364,9 @@ struct sg_comm_wr_t { /* arguments to sg_common_write() */
};
struct sg_mrq_hold { /* for passing context between multiple requests (mrq) functions */
- unsigned from_sg_io:1;
unsigned chk_abort:1;
- unsigned immed:1;
+ unsigned immed:1; /* may differ between sg_iosubmit and sg_ioreceive */
+ unsigned pollable:1; /* same as immed bit during submission */
unsigned stop_if:1;
unsigned co_mmap:1;
unsigned ordered_wr:1;
@@ -393,7 +408,7 @@ static void sg_remove_srp(struct sg_request *srp);
static struct sg_fd *sg_add_sfp(struct sg_device *sdp, struct file *filp);
static void sg_remove_sfp(struct kref *);
static void sg_remove_sfp_share(struct sg_fd *sfp, bool is_rd_side);
-static struct sg_request *sg_get_srp_by_id(struct sg_fd *sfp, int id, bool is_tag, bool part_mrq);
+static struct sg_request *sg_find_srp_from(struct sg_fd_pollable *sfp_p);
static struct sg_request *sg_setup_req(struct sg_comm_wr_t *cwrp, enum sg_shr_var sh_var);
static void sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
static struct sg_device *sg_get_dev(int min_dev);
@@ -404,9 +419,8 @@ static int sg_rq_chg_state(struct sg_request *srp, enum sg_rq_state old_st,
enum sg_rq_state new_st);
static int sg_finish_rs_rq(struct sg_fd *sfp, struct sg_request *rs_srp, bool even_if_in_ws);
static void sg_rq_chg_state_force(struct sg_request *srp, enum sg_rq_state new_st);
-static int sg_sfp_blk_poll(struct sg_fd *sfp, int loop_count);
-static int sg_srp_q_blk_poll(struct sg_request *srp, struct request_queue *q,
- int loop_count);
+static int sg_sfp_blk_poll_first(struct sg_fd *sfp);
+static int sg_sfp_blk_poll_all(struct sg_fd *sfp, int loop_count);
#if IS_ENABLED(CONFIG_SCSI_LOGGING) && IS_ENABLED(SG_DEBUG)
static const char *sg_rq_st_str(enum sg_rq_state rq_st, bool long_str);
@@ -919,6 +933,7 @@ sg_write(struct file *filp, const char __user *p, size_t count, loff_t *ppos)
current->comm, "not setting count and/or reply_len properly");
}
sg_comm_wr_init(&cwr);
+ __set_bit(SG_FRQ_PC_POLLABLE, cwr.frq_pc_bm);
cwr.h3p = h3p;
cwr.dlen = h3p->dxfer_len;
cwr.timeout = sfp->timeout;
@@ -990,7 +1005,8 @@ sg_submit_v3(struct sg_fd *sfp, struct sg_io_hdr *hp, bool sync, struct sg_reque
clear_bit(SG_FFD_NO_CMD_Q, sfp->ffd_bm);
ul_timeout = msecs_to_jiffies(hp->timeout);
sg_comm_wr_init(&cwr);
- __assign_bit(SG_FRQ_PC_SYNC_INVOC, cwr.frq_pc_bm, (int)sync);
+ if (hp->flags & SGV4_FLAG_IMMED)
+ __set_bit(SG_FRQ_PC_POLLABLE, cwr.frq_pc_bm);
cwr.h3p = hp;
cwr.dlen = hp->dxfer_len;
cwr.timeout = min_t(unsigned long, ul_timeout, INT_MAX);
@@ -1152,79 +1168,17 @@ sg_side_str(struct sg_request *srp)
}
static inline int
-sg_num_waiting_maybe_acquire(struct sg_fd *sfp)
+sg_num_waiting_maybe_acquire(struct sg_fd_pollable *sfp_p)
{
- int num = atomic_read(&sfp->waiting);
+ struct sg_fd *fp = sfp_p->fp;
+ atomic_t *ap = sfp_p->pollable ? &fp->poll_waiting : &fp->nonp_waiting;
+ int num = atomic_read(ap);
if (num < 1)
- num = atomic_read_acquire(&sfp->waiting);
+ num = atomic_read_acquire(ap);
return num;
}
-/*
- * Looks for request in SG_RQ_AWAIT_RCV state on given fd that matches part_mrq. The first one
- * found is placed in SG_RQ_BUSY state and its address is returned. If none found returns NULL.
- */
-static struct sg_request *
-sg_get_any_srp(struct sg_fd *sfp, bool part_mrq)
-{
- bool second = false;
- int l_await_idx = READ_ONCE(sfp->low_await_idx);
- unsigned long idx, s_idx, end_idx;
- struct sg_request *srp;
- struct xarray *xafp = &sfp->srp_arr;
-
- s_idx = (l_await_idx < 0) ? 0 : l_await_idx;
- idx = s_idx;
- end_idx = ULONG_MAX;
-second_time:
- for (srp = xa_find(xafp, &idx, end_idx, SG_XA_RQ_AWAIT);
- srp;
- srp = xa_find_after(xafp, &idx, end_idx, SG_XA_RQ_AWAIT)) {
- if (part_mrq != test_bit(SG_FRQ_PC_PART_MRQ, srp->frq_pc_bm))
- continue;
- if (likely(sg_rq_chg_state(srp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY) == 0)) {
- WRITE_ONCE(sfp->low_await_idx, idx + 1);
- return srp;
- }
- }
- /* If not found so far, need to wrap around and search [0 ... s_idx) */
- if (!srp && !second && s_idx > 0) {
- end_idx = s_idx - 1;
- s_idx = 0;
- idx = s_idx;
- second = true;
- goto second_time;
- }
- return NULL;
-}
-
-/*
- * Returns true if a request is ready and its srp is written to *srpp . If nothing can be found
- * returns false and NULL --> *srpp . If an error is detected returns true with IS_ERR(*srpp)
- * also being true.
- */
-static bool
-sg_mrq_get_ready_srp(struct sg_fd *sfp, struct sg_request **srpp)
-{
- if (SG_IS_DETACHING(sfp->parentdp)) {
- *srpp = ERR_PTR(-ENODEV);
- return true;
- }
- if (sg_num_waiting_maybe_acquire(sfp) < 1) {
- if (test_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm)) {
- int res = sg_sfp_blk_poll(sfp, 1);
-
- if (res < 0) {
- *srpp = ERR_PTR(res);
- return true;
- }
- }
- }
- *srpp = sg_get_any_srp(sfp, true);
- return !!*srpp;
-}
-
/* N.B. After this function is completed what srp points to should be considered invalid. */
static int
sg_mrq_1complet(struct sg_mrq_hold *mhp, struct sg_request *srp)
@@ -1271,30 +1225,45 @@ sg_mrq_1complet(struct sg_mrq_hold *mhp, struct sg_request *srp)
return 0;
}
+/*
+ * This function wraps sg_find_srp_from() so it can be called as a predicate for
+ * wait_event_interruptible().
+ */
+static bool
+sg_find_srp_pred(struct sg_fd_pollable *sfp_p, struct sg_request **srpp)
+{
+ struct sg_request *srp;
+ struct sg_fd *fp = sfp_p->fp;
+
+ if (SG_IS_DETACHING(fp->parentdp))
+ srp = ERR_PTR(-ENODEV);
+ else
+ srp = sg_find_srp_from(sfp_p);
+ *srpp = srp; /* Warning: IS_ERR(srp) may also be true */
+ return !!srp;
+}
+
static int
-sg_wait_any_mrq(struct sg_fd *sfp, struct sg_mrq_hold *mhp, struct sg_request **srpp)
+sg_wait_any_mrq(struct sg_fd_pollable *sfp_p, struct sg_mrq_hold *mhp, struct sg_request **srpp)
{
- bool hipri = mhp->hipri || test_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm);
+ struct sg_fd *fp = sfp_p->fp;
+ bool hipri = mhp->hipri || test_bit(SG_FFD_HIPRI_SEEN, fp->ffd_bm);
+ int res;
if (hipri) {
long state = current->state;
struct sg_request *srp;
+ set_bit(SG_FFD_HIPRI_SEEN, fp->ffd_bm);
do {
- if (hipri) {
- int res = sg_sfp_blk_poll(sfp, SG_DEF_BLK_POLL_LOOP_COUNT);
-
- if (res < 0)
- return res;
- }
- srp = sg_get_any_srp(sfp, true);
+ srp = sg_find_srp_from(sfp_p);
if (IS_ERR(srp))
return PTR_ERR(srp);
if (srp) {
__set_current_state(TASK_RUNNING);
break;
}
- if (SG_IS_DETACHING(sfp->parentdp)) {
+ if (SG_IS_DETACHING(fp->parentdp)) {
__set_current_state(TASK_RUNNING);
return -ENODEV;
}
@@ -1307,10 +1276,20 @@ sg_wait_any_mrq(struct sg_fd *sfp, struct sg_mrq_hold *mhp, struct sg_request **
*srpp = srp;
return 0;
}
- if (test_bit(SG_FFD_EXCL_WAITQ, sfp->ffd_bm))
- return __wait_event_interruptible_exclusive(sfp->cmpl_wait,
- sg_mrq_get_ready_srp(sfp, srpp));
- return __wait_event_interruptible(sfp->cmpl_wait, sg_mrq_get_ready_srp(sfp, srpp));
+ if (test_bit(SG_FFD_EXCL_WAITQ, fp->ffd_bm))
+ res = __wait_event_interruptible_exclusive
+ (fp->cmpl_wait, sg_find_srp_pred(sfp_p, srpp));
+ else
+ res = __wait_event_interruptible(fp->cmpl_wait, sg_find_srp_pred(sfp_p, srpp));
+ if (unlikely(res)) { /* -ERESTARTSYS because signal hit thread */
+ set_bit(SG_FFD_SIG_PEND, fp->ffd_bm);
+ SG_LOG(1, fp, "%s: wait_event_interruptible(): %s[%d]\n", __func__,
+ (res == -ERESTARTSYS ? "ERESTARTSYS" : ""), res);
+ return res;
+ }
+ if (SG_IS_DETACHING(fp->parentdp))
+ return -ENODEV;
+ return 0;
}
static inline bool
@@ -1324,19 +1303,24 @@ sg_rq_landed(struct sg_device *sdp, struct sg_request *srp)
* SGV4_FLAG_HIPRI is set this functions goes into a polling loop.
*/
static int
-sg_poll_wait4_given_srp(struct sg_fd *sfp, struct sg_request *srp)
+sg_poll_wait4_given_srp(struct sg_fd_pollable *sfp_p, struct sg_request *srp)
{
int res;
- struct sg_device *sdp = sfp->parentdp;
+ struct sg_fd *fp = sfp_p->fp;
+ struct sg_device *sdp = fp->parentdp;
if (srp->rq_flags & SGV4_FLAG_HIPRI) {
long state = current->state;
+ struct request_queue *q = sdp->device->request_queue;
- SG_LOG(3, sfp, "%s: polling\n", __func__);
+ SG_LOG(3, fp, "%s: polling\n", __func__);
do {
- res = sg_srp_q_blk_poll(srp, sdp->device->request_queue,
- SG_DEF_BLK_POLL_LOOP_COUNT);
- if (res == -ENODATA || res > 0) {
+ if (atomic_read(&srp->rq_st) != SG_RQ_INFLIGHT) {
+ __set_current_state(TASK_RUNNING);
+ break;
+ }
+ res = blk_poll(q, srp->cookie, false /* do not spin */);
+ if (res > 0 && atomic_read(&srp->rq_st) == SG_RQ_AWAIT_RCV) {
__set_current_state(TASK_RUNNING);
break;
}
@@ -1355,47 +1339,55 @@ sg_poll_wait4_given_srp(struct sg_fd *sfp, struct sg_request *srp)
cpu_relax();
} while (true);
} else {
- SG_LOG(3, sfp, "%s: wait_event\n", __func__);
+ SG_LOG(3, fp, "%s: wait_event\n", __func__);
/* N.B. The SG_FFD_EXCL_WAITQ flag is ignored here. */
- res = __wait_event_interruptible(sfp->cmpl_wait, sg_rq_landed(sdp, srp));
+ res = __wait_event_interruptible(fp->cmpl_wait, sg_rq_landed(sdp, srp));
if (unlikely(res)) { /* -ERESTARTSYS because signal hit thread */
- set_bit(SG_FRQ_PC_IS_ORPHAN, srp->frq_pc_bm);
- /* orphans harvested when sfp->keep_orphan is false */
- sg_rq_chg_state_force(srp, SG_RQ_INFLIGHT);
- SG_LOG(1, sfp, "%s: wait_event_interruptible(): %s[%d]\n", __func__,
+ set_bit(SG_FFD_SIG_PEND, fp->ffd_bm);
+ /* pollable requests may be harvested */
+ SG_LOG(1, fp, "%s: wait_event_interruptible(): %s[%d]\n", __func__,
(res == -ERESTARTSYS ? "ERESTARTSYS" : ""), res);
return res;
}
}
if (atomic_read_acquire(&srp->rq_st) != SG_RQ_AWAIT_RCV)
- return (test_bit(SG_FRQ_PC_COUNT_ACTIVE, srp->frq_pc_bm) &&
- atomic_read(&sfp->submitted) < 1) ? -ENODATA : 0;
+ return (atomic_read(&fp->submitted) < 1) ? -ENODATA : 0;
return unlikely(sg_rq_chg_state(srp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY)) ? -EPROTO : 0;
detaching:
sg_rq_chg_state_force(srp, SG_RQ_INACTIVE);
- atomic_inc(&sfp->inactives);
+ atomic_inc(&fp->inactives);
return -ENODEV;
}
static struct sg_request *
-sg_mrq_poll_either(struct sg_fd *sfp, struct sg_fd *sec_sfp, bool *on_sfp)
+sg_mrq_poll_either(struct sg_fd_pollable *sfp_p, struct sg_fd *sec_sfp, bool *on_first)
{
long state = current->state;
+ struct sg_fd *fp = sfp_p->fp;
struct sg_request *srp;
+ struct sg_fd_pollable a_sfpoll = *sfp_p;
- do { /* alternating polling loop */
- if (sfp) {
- if (sg_mrq_get_ready_srp(sfp, &srp)) {
+ do { /* first poll read-side, then poll write-side */
+ if (fp) {
+ a_sfpoll.fp = fp;
+ srp = sg_find_srp_from(&a_sfpoll);
+ if (IS_ERR(srp))
+ return srp;
+ if (srp) {
__set_current_state(TASK_RUNNING);
- *on_sfp = true;
+ *on_first = true;
return srp;
}
}
- if (sec_sfp && sfp != sec_sfp) {
- if (sg_mrq_get_ready_srp(sec_sfp, &srp)) {
+ if (sec_sfp && fp != sec_sfp) {
+ a_sfpoll.fp = sec_sfp;
+ srp = sg_find_srp_from(&a_sfpoll);
+ if (IS_ERR(srp))
+ return srp;
+ if (srp) {
__set_current_state(TASK_RUNNING);
- *on_sfp = false;
+ *on_first = false;
return srp;
}
}
@@ -1412,26 +1404,36 @@ sg_mrq_poll_either(struct sg_fd *sfp, struct sg_fd *sec_sfp, bool *on_sfp)
* main fd over the secondary fd (sec_sfp). Increments cop->info for each successful completion.
*/
static int
-sg_mrq_complets(struct sg_mrq_hold *mhp, struct sg_fd *sfp, struct sg_fd *sec_sfp, int mreqs,
- int sec_reqs)
+sg_mrq_complets(struct sg_mrq_hold *mhp, struct sg_fd_pollable *sfp_p, struct sg_fd *sec_sfp,
+ int mreqs, int sec_reqs)
{
- bool on_sfp;
+ bool on_first;
int res;
struct sg_request *srp;
+ struct sg_fd *fp = sfp_p->fp;
+ struct sg_fd_pollable a_sfpoll = *sfp_p;
- SG_LOG(3, sfp, "%s: mreqs=%d, sec_reqs=%d\n", __func__, mreqs, sec_reqs);
+ SG_LOG(3, fp, "%s: mreqs=%d, sec_reqs=%d\n", __func__, mreqs, sec_reqs);
while (mreqs + sec_reqs > 0) {
- while (mreqs > 0 && sg_mrq_get_ready_srp(sfp, &srp)) {
+ while (mreqs > 0) {
+ a_sfpoll.fp = fp;
+ srp = sg_find_srp_from(&a_sfpoll);
if (IS_ERR(srp))
return PTR_ERR(srp);
+ if (!srp)
+ break;
--mreqs;
res = sg_mrq_1complet(mhp, srp);
if (unlikely(res))
return res;
}
- while (sec_reqs > 0 && sg_mrq_get_ready_srp(sec_sfp, &srp)) {
+ while (sec_reqs > 0) {
+ a_sfpoll.fp = sec_sfp;
+ srp = sg_find_srp_from(&a_sfpoll);
if (IS_ERR(srp))
return PTR_ERR(srp);
+ if (!srp)
+ break;
--sec_reqs;
res = sg_mrq_1complet(mhp, srp);
if (unlikely(res))
@@ -1442,7 +1444,8 @@ sg_mrq_complets(struct sg_mrq_hold *mhp, struct sg_fd *sfp, struct sg_fd *sec_sf
if (res)
break;
if (mreqs > 0) {
- res = sg_wait_any_mrq(sfp, mhp, &srp);
+ a_sfpoll.fp = fp;
+ res = sg_wait_any_mrq(&a_sfpoll, mhp, &srp);
if (unlikely(res))
return res; /* signal --> -ERESTARTSYS */
if (IS_ERR(srp)) {
@@ -1455,7 +1458,8 @@ sg_mrq_complets(struct sg_mrq_hold *mhp, struct sg_fd *sfp, struct sg_fd *sec_sf
}
}
if (sec_reqs > 0) {
- res = sg_wait_any_mrq(sec_sfp, mhp, &srp);
+ a_sfpoll.fp = sec_sfp;
+ res = sg_wait_any_mrq(&a_sfpoll, mhp, &srp);
if (unlikely(res))
return res; /* signal --> -ERESTARTSYS */
if (IS_ERR(srp)) {
@@ -1471,10 +1475,11 @@ sg_mrq_complets(struct sg_mrq_hold *mhp, struct sg_fd *sfp, struct sg_fd *sec_sf
return 0;
start_polling:
while (mreqs + sec_reqs > 0) {
- srp = sg_mrq_poll_either(sfp, sec_sfp, &on_sfp);
+ a_sfpoll.fp = fp;
+ srp = sg_mrq_poll_either(&a_sfpoll, sec_sfp, &on_first);
if (IS_ERR(srp))
return PTR_ERR(srp);
- if (on_sfp) {
+ if (on_first) {
--mreqs;
res = sg_mrq_1complet(mhp, srp);
if (unlikely(res))
@@ -1662,7 +1667,7 @@ sg_mrq_submit(struct sg_fd *rq_sfp, struct sg_mrq_hold *mhp, int pos_in_rq_arr,
r_cwrp->cmd_len = hp->request_len;
r_cwrp->rsv_idx = rsv_idx;
ul_timeout = msecs_to_jiffies(hp->timeout);
- __assign_bit(SG_FRQ_PC_SYNC_INVOC, r_cwrp->frq_pc_bm, (int)mhp->from_sg_io);
+ __assign_bit(SG_FRQ_PC_POLLABLE, r_cwrp->frq_pc_bm, (int)mhp->pollable);
__set_bit(SG_FRQ_PC_IS_V4I, r_cwrp->frq_pc_bm);
__set_bit(SG_FRQ_PC_PART_MRQ, r_cwrp->frq_pc_bm);
r_cwrp->h4p = hp;
@@ -1680,7 +1685,7 @@ sg_mrq_submit(struct sg_fd *rq_sfp, struct sg_mrq_hold *mhp, int pos_in_rq_arr,
* is processed in sg_process_svb_mrq().
*/
static int
-sg_process_most_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp)
+sg_process_most_mrq(struct sg_fd_pollable *sfp_p, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp)
{
int flags, j;
int num_subm = 0;
@@ -1693,6 +1698,8 @@ sg_process_most_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *m
struct sg_io_v4 *cop = mhp->cwrp->h4p;
struct sg_io_v4 *hp; /* ptr to request object in a_hds */
struct sg_request *srp;
+ struct sg_fd *fp = sfp_p->fp;
+ struct sg_fd_pollable a_sfpoll = *sfp_p;
SG_LOG(3, fp, "%s: id_of_mrq=%d, tot_reqs=%d, enter\n", __func__, mhp->id_of_mrq,
mhp->tot_reqs);
@@ -1713,14 +1720,15 @@ sg_process_most_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *m
srp->s_hdr4.mrq_ind = num_subm++;
if (mhp->chk_abort)
atomic_set(&srp->s_hdr4.pack_id_of_mrq, mhp->id_of_mrq);
- if (mhp->immed || (!(mhp->from_sg_io || (flags & shr_complet_b4)))) {
+ if (mhp->immed || !(flags & shr_complet_b4)) {
if (fp == rq_sfp)
++this_fp_sent;
else
++other_fp_sent;
continue; /* defer completion until all submitted */
}
- res = sg_poll_wait4_given_srp(rq_sfp, srp);
+ a_sfpoll.fp = rq_sfp;
+ res = sg_poll_wait4_given_srp(&a_sfpoll, srp);
if (unlikely(res)) {
mhp->s_res = res;
if (res == -ERESTARTSYS || res == -ENODEV)
@@ -1744,8 +1752,9 @@ sg_process_most_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *m
if (mhp->immed)
return res;
if (likely(res == 0 && (this_fp_sent + other_fp_sent) > 0)) {
- res = sg_mrq_complets(mhp, fp, o_sfp, this_fp_sent, other_fp_sent);
- if (res)
+ a_sfpoll.fp = fp;
+ res = sg_mrq_complets(mhp, &a_sfpoll, o_sfp, this_fp_sent, other_fp_sent);
+ if (unlikely(res))
mhp->s_res = res; /* this may leave orphans */
}
if (mhp->id_of_mrq) /* can no longer do a mrq abort */
@@ -1781,8 +1790,8 @@ sg_svb_zero_elem(struct sg_svb_elem *svb_ap, int m)
/* For multiple requests (mrq) share variable blocking (svb) with no SGV4_FLAG_ORDERED_WR */
static int
-sg_svb_mrq_first_come(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp, int ra_ind,
- int *num_submp)
+sg_svb_mrq_first_come(struct sg_fd_pollable *sfp_p, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp,
+ int ra_ind, int *num_submp)
{
bool chk_oth_first = false;
bool stop_triggered = false;
@@ -1795,6 +1804,8 @@ sg_svb_mrq_first_come(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold
struct sg_io_v4 *hp = mhp->a_hds + ra_ind;
struct sg_request *srp;
struct sg_request *rs_srp;
+ struct sg_fd *fp = sfp_p->fp;
+ struct sg_fd_pollable a_sfpoll = *sfp_p;
struct sg_svb_elem svb_arr[SG_MAX_RSV_REQS];
memset(svb_arr, 0, sizeof(svb_arr));
@@ -1842,24 +1853,35 @@ sg_svb_mrq_first_come(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold
* memory leaks. We must wait for inflight requests to complete before final cleanup.
*/
for (k = 0; k < sent; ++k) {
- if (other_fp_sent > 0 && sg_mrq_get_ready_srp(o_sfp, &srp)) {
+ a_sfpoll.fp = o_sfp;
+ if (other_fp_sent > 0) {
+ a_sfpoll.fp = o_sfp;
+ srp = sg_find_srp_from(&a_sfpoll);
if (IS_ERR(srp)) {
mhp->s_res = PTR_ERR(srp);
continue;
- }
+ } else if (srp) {
other_found:
- --other_fp_sent;
- m_ind = srp->s_hdr4.mrq_ind;
- res = sg_mrq_1complet(mhp, srp);
- if (unlikely(res || !sg_v4_cmd_good(mhp->a_hds + m_ind)))
- stop_triggered = sg_svb_err_process(mhp, m_ind, o_sfp, res, false);
- continue; /* do available submits first */
+ --other_fp_sent;
+ m_ind = srp->s_hdr4.mrq_ind;
+ res = sg_mrq_1complet(mhp, srp);
+ if (unlikely(res || !sg_v4_cmd_good(mhp->a_hds + m_ind)))
+ stop_triggered = sg_svb_err_process(mhp, m_ind, o_sfp, res,
+ false);
+ continue; /* do available submits first */
+ }
}
- if (this_fp_sent > 0 && sg_mrq_get_ready_srp(fp, &srp)) {
+ if (this_fp_sent > 0) {
+ a_sfpoll.fp = fp;
+ srp = sg_find_srp_from(&a_sfpoll);
if (IS_ERR(srp)) {
mhp->s_res = PTR_ERR(srp);
continue;
}
+ } else {
+ srp = NULL;
+ }
+ if (srp) {
this_found:
--this_fp_sent;
dir = srp->s_hdr4.dir;
@@ -1922,7 +1944,8 @@ sg_svb_mrq_first_come(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold
goto oth_first;
this_second:
if (this_fp_sent > 0) {
- res = sg_wait_any_mrq(fp, mhp, &srp);
+ a_sfpoll.fp = fp;
+ res = sg_wait_any_mrq(&a_sfpoll, mhp, &srp);
if (unlikely(res))
mhp->s_res = res;
else if (IS_ERR(srp))
@@ -1934,7 +1957,8 @@ sg_svb_mrq_first_come(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold
continue;
oth_first:
if (other_fp_sent > 0) {
- res = sg_wait_any_mrq(o_sfp, mhp, &srp);
+ a_sfpoll.fp = o_sfp;
+ res = sg_wait_any_mrq(&a_sfpoll, mhp, &srp);
if (unlikely(res))
mhp->s_res = res;
else if (IS_ERR(srp))
@@ -1954,8 +1978,8 @@ sg_svb_mrq_first_come(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold
}
static int
-sg_svb_mrq_ordered(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp, int ra_ind,
- int *num_submp)
+sg_svb_mrq_ordered(struct sg_fd_pollable *sfp_p, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp,
+ int ra_ind, int *num_submp)
{
bool stop_triggered = false;
bool rs_fail;
@@ -1966,6 +1990,8 @@ sg_svb_mrq_ordered(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mh
struct sg_io_v4 *hp = mhp->a_hds + ra_ind;
struct sg_request *srp;
struct sg_request *rs_srp;
+ struct sg_fd *fp = sfp_p->fp;
+ struct sg_fd_pollable a_sfpoll = *sfp_p;
struct sg_svb_elem svb_arr[SG_MAX_RSV_REQS];
memset(svb_arr, 0, sizeof(svb_arr));
@@ -2013,7 +2039,8 @@ sg_svb_mrq_ordered(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mh
rs_srp = svb_arr[m].rs_srp;
if (!rs_srp)
continue;
- res = sg_poll_wait4_given_srp(fp, rs_srp);
+ a_sfpoll.fp = fp;
+ res = sg_poll_wait4_given_srp(&a_sfpoll, rs_srp);
if (unlikely(res))
mhp->s_res = res;
--this_fp_sent;
@@ -2057,7 +2084,8 @@ sg_svb_mrq_ordered(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mh
}
while (this_fp_sent > 0) { /* non-data requests */
--this_fp_sent;
- res = sg_wait_any_mrq(fp, mhp, &srp);
+ a_sfpoll.fp = fp;
+ res = sg_wait_any_mrq(&a_sfpoll, mhp, &srp);
if (unlikely(res)) {
mhp->s_res = res;
continue;
@@ -2073,7 +2101,8 @@ sg_svb_mrq_ordered(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mh
}
while (other_fp_sent > 0) {
--other_fp_sent;
- res = sg_wait_any_mrq(o_sfp, mhp, &srp);
+ a_sfpoll.fp = o_sfp;
+ res = sg_wait_any_mrq(&a_sfpoll, mhp, &srp);
if (unlikely(res)) {
mhp->s_res = res;
continue;
@@ -2128,7 +2157,7 @@ sg_svb_cleanup(struct sg_fd *sfp)
* per fd" rule is enforced by the SG_FFD_SVB_ACTIVE file descriptor flag.
*/
static int
-sg_process_svb_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp)
+sg_process_svb_mrq(struct sg_fd_pollable *sfp_p, struct sg_fd *o_sfp, struct sg_mrq_hold *mhp)
{
bool aborted = false;
int j, delta_subm, subm_before, cmpl_before;
@@ -2136,6 +2165,7 @@ sg_process_svb_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mh
int num_cmpl = 0;
int res = 0;
struct sg_io_v4 *cop = mhp->cwrp->h4p;
+ struct sg_fd *fp = sfp_p->fp;
SG_LOG(3, fp, "%s: id_of_mrq=%d, tot_reqs=%d, enter\n", __func__, mhp->id_of_mrq,
mhp->tot_reqs);
@@ -2153,9 +2183,9 @@ sg_process_svb_mrq(struct sg_fd *fp, struct sg_fd *o_sfp, struct sg_mrq_hold *mh
subm_before = num_subm;
cmpl_before = cop->info;
if (mhp->ordered_wr)
- res = sg_svb_mrq_ordered(fp, o_sfp, mhp, j, &num_subm);
+ res = sg_svb_mrq_ordered(sfp_p, o_sfp, mhp, j, &num_subm);
else /* write-side request done on first come, first served basis */
- res = sg_svb_mrq_first_come(fp, o_sfp, mhp, j, &num_subm);
+ res = sg_svb_mrq_first_come(sfp_p, o_sfp, mhp, j, &num_subm);
delta_subm = num_subm - subm_before;
num_cmpl += (cop->info - cmpl_before);
if (res || delta_subm == 0) /* error or didn't make progress */
@@ -2221,8 +2251,9 @@ sg_do_multi_req(struct sg_comm_wr_t *cwrp, bool from_sg_io)
#if IS_ENABLED(SG_LOG_ACTIVE)
const char *mrq_vs;
#endif
+ struct sg_fd_pollable a_sfpoll;
- if (unlikely(SG_IS_DETACHING(fp->parentdp) || (o_sfp && SG_IS_DETACHING(o_sfp->parentdp))))
+ if (SG_IS_DETACHING(fp->parentdp) || (o_sfp && SG_IS_DETACHING(o_sfp->parentdp)))
return -ENODEV;
if (unlikely(tot_reqs == 0))
return 0;
@@ -2244,13 +2275,13 @@ sg_do_multi_req(struct sg_comm_wr_t *cwrp, bool from_sg_io)
if (unlikely(din_len > SG_MAX_MULTI_REQ_SZ || dout_len > SG_MAX_MULTI_REQ_SZ))
return -E2BIG;
mhp->cwrp = cwrp;
- mhp->from_sg_io = from_sg_io; /* false if from SG_IOSUBMIT */
#if IS_ENABLED(SG_LOG_ACTIVE)
mrq_vs = sg_mrq_var_str(from_sg_io, cop->flags);
#endif
f_non_block = !!(fp->filp->f_flags & O_NONBLOCK);
is_svb = !!(cop->flags & SGV4_FLAG_SHARE); /* via ioctl(SG_IOSUBMIT) only */
mhp->immed = !!(cop->flags & SGV4_FLAG_IMMED);
+ mhp->pollable = mhp->immed;
mhp->hipri = !!(cop->flags & SGV4_FLAG_HIPRI);
mhp->stop_if = !!(cop->flags & SGV4_FLAG_STOP_IF);
if (unlikely(mhp->immed && mhp->stop_if))
@@ -2264,6 +2295,12 @@ sg_do_multi_req(struct sg_comm_wr_t *cwrp, bool from_sg_io)
mhp->tot_reqs = tot_reqs;
mhp->s_res = 0;
mhp->dtd_errs = 0;
+ a_sfpoll.fp = fp;
+ a_sfpoll.pollable = mhp->immed;
+ a_sfpoll.immed = mhp->immed;
+ a_sfpoll.part_mrq = true;
+ a_sfpoll.find_by = SG_SEARCH_ANY;
+ a_sfpoll.pack_id_tag = -1;
if (mhp->id_of_mrq) {
int existing_id = atomic_cmpxchg(&fp->mrq_id_abort, 0, mhp->id_of_mrq);
@@ -2358,9 +2395,9 @@ sg_do_multi_req(struct sg_comm_wr_t *cwrp, bool from_sg_io)
clear_bit(SG_FFD_NO_CMD_Q, o_sfp->ffd_bm);
if (is_svb)
- res = sg_process_svb_mrq(fp, o_sfp, mhp);
+ res = sg_process_svb_mrq(&a_sfpoll, o_sfp, mhp);
else
- res = sg_process_most_mrq(fp, o_sfp, mhp);
+ res = sg_process_most_mrq(&a_sfpoll, o_sfp, mhp);
fini:
if (!mhp->immed) { /* for the blocking mrq invocations */
int rres = sg_mrq_arr_flush(mhp);
@@ -2417,8 +2454,9 @@ sg_submit_v4(struct sg_fd *sfp, void __user *p, struct sg_io_v4 *h4p, bool from_
clear_bit(SG_FFD_NO_CMD_Q, sfp->ffd_bm);
ul_timeout = msecs_to_jiffies(h4p->timeout);
cwr.sfp = sfp;
- __assign_bit(SG_FRQ_PC_SYNC_INVOC, cwr.frq_pc_bm, (int)from_sg_io);
__set_bit(SG_FRQ_PC_IS_V4I, cwr.frq_pc_bm);
+ if (h4p->flags & SGV4_FLAG_IMMED)
+ __set_bit(SG_FRQ_PC_POLLABLE, cwr.frq_pc_bm);
cwr.h4p = h4p;
cwr.timeout = min_t(unsigned long, ul_timeout, INT_MAX);
cwr.cmd_len = h4p->request_len;
@@ -2831,15 +2869,12 @@ sg_execute_cmd(struct sg_fd *sfp, struct sg_request *srp)
kref_get(&sfp->f_ref); /* put usually in: sg_rq_end_io() */
sg_rq_chg_state_force(srp, SG_RQ_INFLIGHT);
- /* >>>>>>> send cmd/req off to other levels <<<<<<<< */
- if (!test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm)) {
- atomic_inc(&sfp->submitted);
- set_bit(SG_FRQ_PC_COUNT_ACTIVE, srp->frq_pc_bm);
- }
+ atomic_inc(&sfp->submitted);
if (srp->rq_flags & SGV4_FLAG_HIPRI) {
rqq->cmd_flags |= REQ_HIPRI;
srp->cookie = request_to_qc_t(rqq->mq_hctx, rqq);
}
+ /* >>>>>>> send cmd/req off to other levels <<<<<<<< */
blk_execute_rq_nowait(sdp->disk, rqq, (int)at_head, sg_rq_end_io);
set_bit(SG_FRQ_PC_ISSUED, srp->frq_pc_bm);
}
@@ -2948,38 +2983,6 @@ sg_common_write(struct sg_comm_wr_t *cwrp)
* *********************************************************************************************
*/
-/*
- * This function is called by wait_event_interruptible in sg_read() and sg_ctl_ioreceive().
- * wait_event_interruptible will return if this one returns true (or an event like a signal (e.g.
- * control-C) occurs).
- */
-static inline bool
-sg_get_ready_srp(struct sg_fd *sfp, struct sg_request **srpp, int id, bool is_tag)
-{
- struct sg_request *srp;
-
- if (SG_IS_DETACHING(sfp->parentdp)) {
- *srpp = ERR_PTR(-ENODEV);
- return true;
- }
- srp = sg_get_srp_by_id(sfp, id, is_tag, false);
- *srpp = srp; /* Warning: IS_ERR(srp) may be true */
- return !!srp;
-}
-
-static inline bool
-sg_get_any_ready_srp(struct sg_fd *sfp, struct sg_request **srpp)
-{
- struct sg_request *srp;
-
- if (SG_IS_DETACHING(sfp->parentdp))
- srp = ERR_PTR(-ENODEV);
- else
- srp = sg_get_any_srp(sfp, false);
- *srpp = srp; /* Warning: IS_ERR(srp) may be true */
- return !!srp;
-}
-
/* Returns number of bytes copied to user space provided sense buffer or negated errno value. */
static int
sg_copy_sense(struct sg_request *srp)
@@ -3204,24 +3207,26 @@ sg_receive_v4(struct sg_fd *sfp, struct sg_request *srp, void __user *p, struct
* of elements written to rsp_arr, which may be 0 if mrqs submitted but none waiting
*/
static int
-sg_mrq_iorec_complets(struct sg_fd *sfp, struct sg_mrq_hold *mhp, bool non_block, int max_rcv)
+sg_mrq_iorec_complets(struct sg_fd_pollable *sfp_p, struct sg_mrq_hold *mhp, int max_rcv)
{
int k, idx;
int res = 0;
struct sg_request *srp;
struct sg_io_v4 *rsp_arr = mhp->a_hds;
+ struct sg_fd *fp = sfp_p->fp;
- SG_LOG(3, sfp, "%s: num_responses=%d, max_rcv=%d, hipri=%u\n", __func__,
+ SG_LOG(3, fp, "%s: num_responses=%d, max_rcv=%d, hipri=%u\n", __func__,
mhp->tot_reqs, max_rcv, mhp->hipri);
if (max_rcv == 0 || max_rcv > mhp->tot_reqs)
max_rcv = mhp->tot_reqs;
k = 0;
recheck:
for ( ; k < max_rcv; ++k) {
- if (!sg_mrq_get_ready_srp(sfp, &srp))
- break;
+ srp = sg_find_srp_from(sfp_p);
if (IS_ERR(srp))
return k ? k /* some but not all */ : PTR_ERR(srp);
+ if (!srp)
+ break;
if (srp->rq_flags & SGV4_FLAG_REC_ORDER) {
idx = srp->s_hdr4.mrq_ind;
if (idx >= mhp->tot_reqs)
@@ -3229,24 +3234,24 @@ sg_mrq_iorec_complets(struct sg_fd *sfp, struct sg_mrq_hold *mhp, bool non_block
} else {
idx = k; /* completion order */
}
- res = sg_receive_v4(sfp, srp, NULL, rsp_arr + idx);
+ res = sg_receive_v4(fp, srp, NULL, rsp_arr + idx);
if (unlikely(res))
return res;
rsp_arr[idx].info |= SG_INFO_MRQ_FINI;
}
- if (non_block || k >= max_rcv)
+ if (sfp_p->immed || k >= max_rcv)
return k;
if (mhp->hipri) {
- if (SG_IS_DETACHING(sfp->parentdp))
+ if (SG_IS_DETACHING(fp->parentdp))
return -ENODEV;
if (signal_pending(current))
return -ERESTARTSYS;
cpu_relax();
goto recheck;
}
- SG_LOG(6, sfp, "%s: received=%d, max=%d\n", __func__, k, max_rcv);
+ SG_LOG(6, fp, "%s: received=%d, max=%d\n", __func__, k, max_rcv);
for ( ; k < max_rcv; ++k) {
- res = sg_wait_any_mrq(sfp, mhp, &srp);
+ res = sg_wait_any_mrq(sfp_p, mhp, &srp);
if (unlikely(res))
return res; /* signal --> -ERESTARTSYS */
if (IS_ERR(srp))
@@ -3258,7 +3263,7 @@ sg_mrq_iorec_complets(struct sg_fd *sfp, struct sg_mrq_hold *mhp, bool non_block
} else {
idx = k;
}
- res = sg_receive_v4(sfp, srp, NULL, rsp_arr + idx);
+ res = sg_receive_v4(fp, srp, NULL, rsp_arr + idx);
if (unlikely(res))
return res;
rsp_arr[k].info |= SG_INFO_MRQ_FINI;
@@ -3272,7 +3277,7 @@ sg_mrq_iorec_complets(struct sg_fd *sfp, struct sg_mrq_hold *mhp, bool non_block
* may succeed but will get different requests).
*/
static int
-sg_mrq_ioreceive(struct sg_fd *sfp, struct sg_io_v4 *cop, void __user *p, bool non_block)
+sg_mrq_ioreceive(struct sg_fd_pollable *sfp_p, struct sg_io_v4 *cop, void __user *p)
{
int res = 0;
int max_rcv;
@@ -3281,8 +3286,10 @@ sg_mrq_ioreceive(struct sg_fd *sfp, struct sg_io_v4 *cop, void __user *p, bool n
void __user *pp;
struct sg_mrq_hold mh;
struct sg_mrq_hold *mhp = &mh;
+ struct sg_fd *fp = sfp_p->fp;
- SG_LOG(3, sfp, "%s: non_block=%d\n", __func__, !!non_block);
+ SG_LOG(3, fp, "%s: immed=%d\n", __func__, sfp_p->immed);
+ sfp_p->part_mrq = true;
n = cop->din_xfer_len;
if (unlikely(n > SG_MAX_MULTI_REQ_SZ))
return -E2BIG;
@@ -3294,8 +3301,8 @@ sg_mrq_ioreceive(struct sg_fd *sfp, struct sg_io_v4 *cop, void __user *p, bool n
len = n * SZ_SG_IO_V4;
max_rcv = cop->din_iovec_count;
mhp->hipri = !!(cop->flags & SGV4_FLAG_HIPRI);
- SG_LOG(3, sfp, "%s: %s, num_reqs=%u, max_rcv=%d\n", __func__,
- (non_block ? "IMMED" : "blocking"), n, max_rcv);
+ SG_LOG(3, fp, "%s: %s, num_reqs=%u, max_rcv=%d\n", __func__,
+ (sfp_p->immed ? "IMMED" : "blocking"), n, max_rcv);
rsp_v4_arr = kcalloc(n, SZ_SG_IO_V4, GFP_KERNEL);
if (unlikely(!rsp_v4_arr))
return -ENOMEM;
@@ -3303,7 +3310,7 @@ sg_mrq_ioreceive(struct sg_fd *sfp, struct sg_io_v4 *cop, void __user *p, bool n
sg_v4h_partial_zero(cop);
cop->din_resid = n;
mhp->a_hds = rsp_v4_arr;
- res = sg_mrq_iorec_complets(sfp, mhp, non_block, max_rcv);
+ res = sg_mrq_iorec_complets(sfp_p, mhp, max_rcv);
if (unlikely(res < 0))
goto fini;
cop->din_resid -= res;
@@ -3316,37 +3323,36 @@ sg_mrq_ioreceive(struct sg_fd *sfp, struct sg_io_v4 *cop, void __user *p, bool n
if (copy_to_user(pp, rsp_v4_arr, len))
res = -EFAULT;
} else {
- SG_LOG(1, sfp, "%s: cop->din_xferp==NULL ?_?\n", __func__);
+ SG_LOG(1, fp, "%s: cop->din_xferp==NULL ?_?\n", __func__);
}
fini:
kfree(rsp_v4_arr);
return res;
}
+/* Returns first srp that meets the constraints in sfp_p */
static struct sg_request *
-sg_poll_wait4_srp(struct sg_fd *sfp, int id, bool is_tag, bool part_mrq)
+sg_poll4_any_srp(struct sg_fd_pollable *sfp_p)
{
long state = current->state;
struct sg_request *srp;
+ struct sg_fd *fp = sfp_p->fp;
do {
- if (test_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm)) {
- int res = sg_sfp_blk_poll(sfp, SG_DEF_BLK_POLL_LOOP_COUNT);
+ if (test_bit(SG_FFD_HIPRI_SEEN, fp->ffd_bm)) {
+ int res = sg_sfp_blk_poll_first(fp);
if (res < 0)
return ERR_PTR(res);
}
- if (id == -1)
- srp = sg_get_any_srp(sfp, part_mrq);
- else
- srp = sg_get_srp_by_id(sfp, id, is_tag, part_mrq);
+ srp = sg_find_srp_from(sfp_p);
if (IS_ERR(srp))
return srp;
if (srp) {
__set_current_state(TASK_RUNNING);
return srp;
}
- if (SG_IS_DETACHING(sfp->parentdp)) {
+ if (SG_IS_DETACHING(fp->parentdp)) {
__set_current_state(TASK_RUNNING);
return ERR_PTR(-ENODEV);
}
@@ -3359,34 +3365,37 @@ sg_poll_wait4_srp(struct sg_fd *sfp, int id, bool is_tag, bool part_mrq)
}
/*
- * Called from read(), ioctl(SG_IORECEIVE) or ioctl(SG_IORECEIVE_V3). Either wait event for
- * command completion matching id ('-1': any); or poll for it if do_poll==true
+ * Called from read(), ioctl(SG_IORECEIVE) or ioctl(SG_IORECEIVE_V3). Poll or wait_event
+ * depending hipri setting.
*/
static int
-sg_wait_poll_by_id(struct sg_fd *sfp, struct sg_request **srpp, int id,
- bool is_tag, int do_poll)
+sg_poll_or_wait_ev_srp(struct sg_fd_pollable *sfp_p, struct sg_request **srpp, bool hipri)
{
- if (do_poll) {
- struct sg_request *srp = sg_poll_wait4_srp(sfp, id, is_tag, false);
+ int res;
+ struct sg_fd *fp = sfp_p->fp;
+
+ if (hipri) {
+ struct sg_request *srp = sg_poll4_any_srp(sfp_p);
if (IS_ERR(srp))
return PTR_ERR(srp);
*srpp = srp;
return 0;
}
- if (test_bit(SG_FFD_EXCL_WAITQ, sfp->ffd_bm)) {
- if (id == -1)
- return __wait_event_interruptible_exclusive
- (sfp->cmpl_wait, sg_get_any_ready_srp(sfp, srpp));
- else
- return __wait_event_interruptible_exclusive
- (sfp->cmpl_wait, sg_get_ready_srp(sfp, srpp, id, is_tag));
- }
- if (id == -1)
- return __wait_event_interruptible(sfp->cmpl_wait, sg_get_any_ready_srp(sfp, srpp));
+ if (test_bit(SG_FFD_EXCL_WAITQ, fp->ffd_bm))
+ res = __wait_event_interruptible_exclusive(fp->cmpl_wait,
+ sg_find_srp_pred(sfp_p, srpp));
else
- return __wait_event_interruptible(sfp->cmpl_wait, sg_get_ready_srp(sfp, srpp, id,
- is_tag));
+ res = __wait_event_interruptible(fp->cmpl_wait, sg_find_srp_pred(sfp_p, srpp));
+ if (unlikely(res)) { /* -ERESTARTSYS because signal hit thread */
+ set_bit(SG_FFD_SIG_PEND, fp->ffd_bm);
+ SG_LOG(1, fp, "%s: wait_event_interruptible(): %s[%d]\n", __func__,
+ (res == -ERESTARTSYS ? "ERESTARTSYS" : ""), res);
+ return res;
+ }
+ if (SG_IS_DETACHING(fp->parentdp))
+ return -ENODEV;
+ return 0;
}
/*
@@ -3399,14 +3408,12 @@ static int
sg_ctl_ioreceive(struct sg_fd *sfp, void __user *p)
{
bool non_block = SG_IS_O_NONBLOCK(sfp);
- bool use_tag = false;
- int res, id;
- int pack_id = SG_PACK_ID_WILDCARD;
- int tag = SG_TAG_WILDCARD;
+ int res;
struct sg_io_v4 h4;
struct sg_io_v4 *h4p = &h4;
struct sg_device *sdp = sfp->parentdp;
struct sg_request *srp;
+ struct sg_fd_pollable a_sfpoll;
res = sg_allow_if_err_recovery(sdp, non_block);
if (unlikely(res))
@@ -3421,29 +3428,36 @@ sg_ctl_ioreceive(struct sg_fd *sfp, void __user *p)
!!(h4p->flags & SGV4_FLAG_IMMED), !!(h4p->flags & SGV4_FLAG_HIPRI));
if (h4p->flags & SGV4_FLAG_IMMED)
non_block = true; /* set by either this or O_NONBLOCK */
+ a_sfpoll.fp = sfp;
+ a_sfpoll.pollable = true;
+ a_sfpoll.immed = non_block;
if (h4p->flags & SGV4_FLAG_MULTIPLE_REQS)
- return sg_mrq_ioreceive(sfp, h4p, p, non_block);
+ return sg_mrq_ioreceive(&a_sfpoll, h4p, p);
+ a_sfpoll.part_mrq = false;
/* read in part of v3 or v4 header for pack_id or tag based find */
if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm)) {
- use_tag = test_bit(SG_FFD_PREFER_TAG, sfp->ffd_bm);
- if (use_tag)
- tag = h4p->request_tag; /* top 32 bits ignored */
- else
- pack_id = h4p->request_extra;
+ if (test_bit(SG_FFD_PREFER_TAG, sfp->ffd_bm)) {
+ a_sfpoll.find_by = SG_SEARCH_BY_TAG;
+ a_sfpoll.pack_id_tag = h4p->request_tag;/* top 32 bits ignored */
+ } else {
+ a_sfpoll.find_by = SG_SEARCH_BY_PACK_ID;
+ a_sfpoll.pack_id_tag = h4p->request_extra;
+ }
+ } else {
+ a_sfpoll.find_by = SG_SEARCH_ANY;
+ a_sfpoll.pack_id_tag = SG_PACK_ID_WILDCARD;
}
- id = use_tag ? tag : pack_id;
try_again:
if (non_block) {
- srp = sg_get_srp_by_id(sfp, id, use_tag, false /* part_mrq */);
+ srp = sg_find_srp_from(&a_sfpoll);
if (!srp)
return SG_IS_DETACHING(sdp) ? -ENODEV : -EAGAIN;
} else {
- res = sg_wait_poll_by_id(sfp, &srp, pack_id, use_tag,
- !!(h4p->flags & SGV4_FLAG_HIPRI));
- if (IS_ERR(srp))
- return PTR_ERR(srp);
+ res = sg_poll_or_wait_ev_srp(&a_sfpoll, &srp, !!(h4p->flags & SGV4_FLAG_HIPRI));
if (unlikely(res))
return res; /* signal --> -ERESTARTSYS */
+ if (IS_ERR(srp))
+ return PTR_ERR(srp);
}
if (test_and_set_bit(SG_FRQ_PC_RECEIVING, srp->frq_pc_bm)) {
cpu_relax();
@@ -3463,11 +3477,11 @@ sg_ctl_ioreceive_v3(struct sg_fd *sfp, void __user *p)
{
bool non_block = SG_IS_O_NONBLOCK(sfp);
int res;
- int pack_id = SG_PACK_ID_WILDCARD;
struct sg_io_hdr h3;
struct sg_io_hdr *h3p = &h3;
struct sg_device *sdp = sfp->parentdp;
struct sg_request *srp;
+ struct sg_fd_pollable a_sfpoll;
res = sg_allow_if_err_recovery(sdp, non_block);
if (unlikely(res))
@@ -3480,20 +3494,28 @@ sg_ctl_ioreceive_v3(struct sg_fd *sfp, void __user *p)
return -EPERM;
if (h3p->flags & SGV4_FLAG_IMMED)
non_block = true; /* set by either this or O_NONBLOCK */
+ a_sfpoll.fp = sfp;
+ a_sfpoll.pollable = true;
+ a_sfpoll.immed = non_block;
+ a_sfpoll.part_mrq = false;
SG_LOG(3, sfp, "%s: non_block(+IMMED)=%d\n", __func__, non_block);
if (unlikely(h3p->flags & SGV4_FLAG_MULTIPLE_REQS))
return -EINVAL;
- if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm))
- pack_id = h3p->pack_id;
+ if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm)) {
+ a_sfpoll.find_by = SG_SEARCH_BY_PACK_ID;
+ a_sfpoll.pack_id_tag = h3p->pack_id;
+ } else {
+ a_sfpoll.find_by = SG_SEARCH_ANY;
+ a_sfpoll.pack_id_tag = SG_PACK_ID_WILDCARD;
+ }
try_again:
if (non_block) {
- srp = sg_get_srp_by_id(sfp, pack_id, false, false);
+ srp = sg_find_srp_from(&a_sfpoll);
if (!srp)
return SG_IS_DETACHING(sdp) ? -ENODEV : -EAGAIN;
} else {
- res = sg_wait_poll_by_id(sfp, &srp, pack_id, false,
- !!(h3p->flags & SGV4_FLAG_HIPRI));
+ res = sg_poll_or_wait_ev_srp(&a_sfpoll, &srp, !!(h3p->flags & SGV4_FLAG_HIPRI));
if (unlikely(res))
return res; /* signal --> -ERESTARTSYS */
if (IS_ERR(srp))
@@ -3597,13 +3619,13 @@ sg_read(struct file *filp, char __user *p, size_t count, loff_t *ppos)
{
bool could_be_v3;
bool non_block = !!(filp->f_flags & O_NONBLOCK);
- int want_id = SG_PACK_ID_WILDCARD;
int hlen, ret;
struct sg_device *sdp = NULL;
struct sg_fd *sfp;
struct sg_request *srp = NULL;
struct sg_header *h2p = NULL;
struct sg_io_hdr a_sg_io_hdr;
+ struct sg_fd_pollable a_sfpoll;
/*
* This could cause a response to be stranded. Close the associated file descriptor to
@@ -3623,6 +3645,9 @@ sg_read(struct file *filp, char __user *p, size_t count, loff_t *ppos)
could_be_v3 = (count >= SZ_SG_IO_HDR);
hlen = could_be_v3 ? SZ_SG_IO_HDR : SZ_SG_HEADER;
h2p = (struct sg_header *)&a_sg_io_hdr;
+ a_sfpoll.fp = sfp;
+ a_sfpoll.pollable = true;
+ a_sfpoll.part_mrq = false;
if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm) && (int)count >= hlen) {
/*
@@ -3635,6 +3660,7 @@ sg_read(struct file *filp, char __user *p, size_t count, loff_t *ppos)
struct sg_io_hdr *v3_hdr = (struct sg_io_hdr *)h2p;
if (likely(v3_hdr->interface_id == 'S')) {
+ int want_id;
struct sg_io_hdr __user *h3_up;
h3_up = (struct sg_io_hdr __user *)p;
@@ -3650,23 +3676,31 @@ sg_read(struct file *filp, char __user *p, size_t count, loff_t *ppos)
if (flgs & SGV4_FLAG_IMMED)
non_block = true;
}
+ a_sfpoll.find_by = SG_SEARCH_BY_PACK_ID;
+ a_sfpoll.pack_id_tag = want_id;
} else if (v3_hdr->interface_id == 'Q') {
pr_info_once("sg: %s: v4 interface disallowed here\n", __func__);
return -EPERM;
} else {
return -EPERM;
}
- } else { /* for v1+v2 interfaces, this is the 3rd integer */
- want_id = h2p->pack_id;
+ } else { /* for v1+v2 interfaces, pack_id is the 3rd integer */
+ a_sfpoll.find_by = SG_SEARCH_BY_PACK_ID;
+ a_sfpoll.pack_id_tag = h2p->pack_id;
}
+ } else {
+ a_sfpoll.find_by = SG_SEARCH_ANY;
+ a_sfpoll.pack_id_tag = SG_PACK_ID_WILDCARD;
}
+ a_sfpoll.immed = non_block;
+
try_again:
if (non_block) {
- srp = sg_get_srp_by_id(sfp, want_id, false, false /* part_mrq */);
+ srp = sg_find_srp_from(&a_sfpoll);
if (!srp)
return SG_IS_DETACHING(sdp) ? -ENODEV : -EAGAIN;
} else {
- ret = sg_wait_poll_by_id(sfp, &srp, want_id, false, false /* do_poll */);
+ ret = sg_poll_or_wait_ev_srp(&a_sfpoll, &srp, false);
if (unlikely(ret))
return ret; /* signal --> -ERESTARTSYS */
if (IS_ERR(srp))
@@ -4156,7 +4190,7 @@ sg_fill_request_element(struct sg_fd *sfp, struct sg_request *srp, struct sg_req
if (rip->duration == U32_MAX)
rip->duration = 0;
rip->orphan = test_bit(SG_FRQ_PC_IS_ORPHAN, srp->frq_pc_bm);
- rip->sg_io_owned = test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm);
+ rip->sg_io_owned = !test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm);
rip->problem = !sg_result_is_good(srp->rq_result);
rip->pack_id = test_bit(SG_FFD_PREFER_TAG, sfp->ffd_bm) ? srp->tag : srp->pack_id;
rip->usr_ptr = SG_IS_V4I(srp) ? uptr64(srp->s_hdr4.usr_ptr) : srp->s_hdr3.usr_ptr;
@@ -4173,6 +4207,7 @@ sg_ctl_sg_io(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
u8 hu8arr[SZ_SG_IO_V4];
struct sg_io_hdr *h3p = (struct sg_io_hdr *)hu8arr;
struct sg_io_v4 *h4p = (struct sg_io_v4 *)hu8arr;
+ struct sg_fd_pollable a_sfpoll;
SG_LOG(3, sfp, "%s: SG_IO%s\n", __func__,
(SG_IS_O_NONBLOCK(sfp) ? " O_NONBLOCK ignored" : ""));
@@ -4195,9 +4230,13 @@ sg_ctl_sg_io(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
if (copy_from_user(hu8arr + v3_len, ((u8 __user *)p) + v3_len,
SZ_SG_IO_V4 - v3_len))
return -EFAULT;
+ if (h4p->flags & SGV4_FLAG_IMMED)
+ return -EINVAL;
is_v4 = true;
res = sg_submit_v4(sfp, p, h4p, true, &srp);
} else if (h3p->interface_id == 'S') {
+ if (h3p->flags & SGV4_FLAG_IMMED)
+ return -EINVAL;
is_v4 = false;
res = sg_submit_v3(sfp, h3p, true, &srp);
} else {
@@ -4208,7 +4247,11 @@ sg_ctl_sg_io(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
return res;
if (!srp) /* mrq case: already processed all responses */
return res;
- res = sg_poll_wait4_given_srp(sfp, srp);
+ a_sfpoll.fp = sfp;
+ a_sfpoll.pollable = false;
+ a_sfpoll.immed = false;
+ a_sfpoll.part_mrq = false;
+ res = sg_poll_wait4_given_srp(&a_sfpoll, srp);
#if IS_ENABLED(SG_LOG_ACTIVE)
if (unlikely(res))
SG_LOG(1, sfp, "%s: unexpected srp=0x%pK state: %s, share: %s\n", __func__,
@@ -4229,23 +4272,24 @@ sg_ctl_sg_io(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
* returns NULL.
*/
static struct sg_request *
-sg_match_request(struct sg_fd *sfp, bool use_tag, int id)
+sg_match_request(struct sg_fd_pollable *sfp_p, bool use_tag, int id)
{
unsigned long idx;
struct sg_request *srp;
+ struct sg_fd *fp = sfp_p->fp;
- if (sg_num_waiting_maybe_acquire(sfp) < 1)
+ if (sg_num_waiting_maybe_acquire(sfp_p) < 1)
return NULL;
if (id == SG_PACK_ID_WILDCARD) {
- xa_for_each_marked(&sfp->srp_arr, idx, srp, SG_XA_RQ_AWAIT)
+ xa_for_each_marked(&fp->srp_arr, idx, srp, SG_XA_RQ_AWAIT)
return srp;
} else if (use_tag) {
- xa_for_each_marked(&sfp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
+ xa_for_each_marked(&fp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
if (id == srp->tag)
return srp;
}
} else {
- xa_for_each_marked(&sfp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
+ xa_for_each_marked(&fp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
if (id == srp->pack_id)
return srp;
}
@@ -4259,18 +4303,19 @@ sg_match_request(struct sg_fd *sfp, bool use_tag, int id)
* search restarts from the beginning of the list. If no match is found then NULL is returned.
*/
static struct sg_request *
-sg_match_first_mrq_after(struct sg_fd *sfp, int pack_id, struct sg_request *after_rp)
+sg_match_first_mrq_after(struct sg_fd_pollable *sfp_p, int pack_id, struct sg_request *after_rp)
{
bool found = false;
bool look_for_after = after_rp ? true : false;
int id;
unsigned long idx;
struct sg_request *srp;
+ struct sg_fd *fp = sfp_p->fp;
- if (sg_num_waiting_maybe_acquire(sfp) < 1)
+ if (sg_num_waiting_maybe_acquire(sfp_p) < 1)
return NULL;
once_more:
- xa_for_each_marked(&sfp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
+ xa_for_each_marked(&fp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
if (look_for_after) {
if (after_rp == srp)
look_for_after = false;
@@ -4340,18 +4385,19 @@ sg_abort_req(struct sg_fd *sfp, struct sg_request *srp)
/* Holding xa_lock_irq(&sfp->srp_arr) */
static int
-sg_mrq_abort_inflight(struct sg_fd *sfp, int pack_id)
+sg_mrq_abort_inflight(struct sg_fd_pollable *sfp_p, int pack_id)
{
bool got_ebusy = false;
int res = 0;
struct sg_request *srp;
struct sg_request *prev_srp;
+ struct sg_fd *fp = sfp_p->fp;
for (prev_srp = NULL; true; prev_srp = srp) {
- srp = sg_match_first_mrq_after(sfp, pack_id, prev_srp);
+ srp = sg_match_first_mrq_after(sfp_p, pack_id, prev_srp);
if (!srp)
break;
- res = sg_abort_req(sfp, srp);
+ res = sg_abort_req(fp, srp);
if (res == -EBUSY) /* check rest of active list */
got_ebusy = true;
else if (res)
@@ -4370,7 +4416,7 @@ sg_mrq_abort_inflight(struct sg_fd *sfp, int pack_id)
* ctl_obj.request_extra (pack_id).
*/
static int
-sg_mrq_abort(struct sg_fd *sfp, int pack_id, bool dev_scope)
+sg_mrq_abort(struct sg_fd_pollable *sfp_p, int pack_id, bool dev_scope)
__must_hold(sfp->f_mutex)
{
int existing_id;
@@ -4379,63 +4425,67 @@ sg_mrq_abort(struct sg_fd *sfp, int pack_id, bool dev_scope)
struct sg_device *sdp;
struct sg_fd *o_sfp;
struct sg_fd *s_sfp;
+ struct sg_fd *fp = sfp_p->fp;
if (pack_id != SG_PACK_ID_WILDCARD)
- SG_LOG(3, sfp, "%s: pack_id=%d, dev_scope=%s\n", __func__, pack_id,
+ SG_LOG(3, fp, "%s: pack_id=%d, dev_scope=%s\n", __func__, pack_id,
(dev_scope ? "true" : "false"));
- existing_id = atomic_read(&sfp->mrq_id_abort);
+ existing_id = atomic_read(&fp->mrq_id_abort);
if (existing_id == 0) {
if (dev_scope)
goto check_whole_dev;
- SG_LOG(1, sfp, "%s: sfp->mrq_id_abort is 0, nothing to do\n", __func__);
+ SG_LOG(1, fp, "%s: sfp->mrq_id_abort is 0, nothing to do\n", __func__);
return -EADDRNOTAVAIL;
}
if (pack_id == SG_PACK_ID_WILDCARD) {
pack_id = existing_id;
- SG_LOG(3, sfp, "%s: wildcard becomes pack_id=%d\n", __func__, pack_id);
+ SG_LOG(3, fp, "%s: wildcard becomes pack_id=%d\n", __func__, pack_id);
} else if (pack_id != existing_id) {
if (dev_scope)
goto check_whole_dev;
- SG_LOG(1, sfp, "%s: want id=%d, got sfp->mrq_id_abort=%d\n", __func__, pack_id,
+ SG_LOG(1, fp, "%s: want id=%d, got sfp->mrq_id_abort=%d\n", __func__, pack_id,
existing_id);
return -EADDRINUSE;
}
- if (test_and_set_bit(SG_FFD_MRQ_ABORT, sfp->ffd_bm))
- SG_LOG(2, sfp, "%s: repeated SG_IOABORT on mrq_id=%d\n", __func__, pack_id);
+ if (test_and_set_bit(SG_FFD_MRQ_ABORT, fp->ffd_bm))
+ SG_LOG(2, fp, "%s: repeated SG_IOABORT on mrq_id=%d\n", __func__, pack_id);
/* now look for inflight requests matching that mrq pack_id */
- xa_lock_irqsave(&sfp->srp_arr, iflags);
- res = sg_mrq_abort_inflight(sfp, pack_id);
+ xa_lock_irqsave(&fp->srp_arr, iflags);
+ res = sg_mrq_abort_inflight(sfp_p, pack_id);
if (res == -EBUSY) {
- res = sg_mrq_abort_inflight(sfp, pack_id);
+ res = sg_mrq_abort_inflight(sfp_p, pack_id);
if (res)
goto fini;
}
- s_sfp = sg_fd_share_ptr(sfp);
+ s_sfp = sg_fd_share_ptr(fp);
if (s_sfp) { /* SGV4_FLAG_DO_ON_OTHER possible */
- xa_unlock_irqrestore(&sfp->srp_arr, iflags);
- sfp = s_sfp; /* if share, switch to other fd */
- xa_lock_irqsave(&sfp->srp_arr, iflags);
- if (!sg_fd_is_shared(sfp))
+ xa_unlock_irqrestore(&fp->srp_arr, iflags);
+ fp = s_sfp; /* if share, switch to other fd */
+ xa_lock_irqsave(&fp->srp_arr, iflags);
+ if (!sg_fd_is_shared(fp))
goto fini;
/* tough luck if other fd used same mrq pack_id */
- res = sg_mrq_abort_inflight(sfp, pack_id);
+ res = sg_mrq_abort_inflight(sfp_p, pack_id);
if (res == -EBUSY)
- res = sg_mrq_abort_inflight(sfp, pack_id);
+ res = sg_mrq_abort_inflight(sfp_p, pack_id);
}
fini:
- xa_unlock_irqrestore(&sfp->srp_arr, iflags);
+ xa_unlock_irqrestore(&fp->srp_arr, iflags);
return res;
check_whole_dev:
res = -ENODATA;
- sdp = sfp->parentdp;
+ sdp = fp->parentdp;
xa_for_each(&sdp->sfp_arr, idx, o_sfp) {
- if (o_sfp == sfp)
+ struct sg_fd_pollable a_sfpoll = *sfp_p;
+
+ if (o_sfp == fp)
continue; /* already checked */
mutex_lock(&o_sfp->f_mutex);
+ a_sfpoll.fp = o_sfp;
/* recurse, dev_scope==false is stopping condition */
- res = sg_mrq_abort(o_sfp, pack_id, false);
+ res = sg_mrq_abort(&a_sfpoll, pack_id, false);
mutex_unlock(&o_sfp->f_mutex);
if (res == 0)
break;
@@ -4461,6 +4511,7 @@ sg_ctl_abort(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
struct sg_request *srp;
struct sg_io_v4 io_v4;
struct sg_io_v4 *h4p = &io_v4;
+ struct sg_fd_pollable a_sfpoll;
if (copy_from_user(h4p, p, SZ_SG_IO_V4))
return -EFAULT;
@@ -4468,17 +4519,22 @@ sg_ctl_abort(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
return -EPERM;
dev_scope = !!(h4p->flags & SGV4_FLAG_DEV_SCOPE);
pack_id = h4p->request_extra;
+ a_sfpoll.fp = sfp;
+ a_sfpoll.pollable = true;
+ a_sfpoll.immed = true;
if (h4p->flags & SGV4_FLAG_MULTIPLE_REQS) {
+ a_sfpoll.part_mrq = true;
if (pack_id == 0)
return -ENOSTR;
- res = sg_mrq_abort(sfp, pack_id, dev_scope);
+ res = sg_mrq_abort(&a_sfpoll, pack_id, dev_scope);
return res;
}
+ a_sfpoll.part_mrq = false;
xa_lock_irqsave(&sfp->srp_arr, iflags);
use_tag = test_bit(SG_FFD_PREFER_TAG, sfp->ffd_bm);
id = use_tag ? (int)h4p->request_tag : pack_id;
- srp = sg_match_request(sfp, use_tag, id);
+ srp = sg_match_request(&a_sfpoll, use_tag, id);
if (!srp) { /* assume device (not just fd) scope */
xa_unlock_irqrestore(&sfp->srp_arr, iflags);
if (!dev_scope)
@@ -4486,7 +4542,8 @@ sg_ctl_abort(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
xa_for_each(&sdp->sfp_arr, idx, o_sfp) {
if (o_sfp == sfp)
continue; /* already checked */
- srp = sg_match_request(o_sfp, use_tag, id);
+ a_sfpoll.fp = o_sfp;
+ srp = sg_match_request(&a_sfpoll, use_tag, id);
if (srp) {
sfp = o_sfp;
xa_lock_irqsave(&sfp->srp_arr, iflags);
@@ -4817,8 +4874,6 @@ sg_any_persistent_orphans(struct sg_fd *sfp)
struct sg_request *srp;
struct xarray *xafp = &sfp->srp_arr;
- if (sg_num_waiting_maybe_acquire(sfp) < 1)
- return false;
xa_for_each_marked(xafp, idx, srp, SG_XA_RQ_AWAIT) {
if (test_bit(SG_FRQ_PC_IS_ORPHAN, srp->frq_pc_bm))
return true;
@@ -5228,7 +5283,7 @@ sg_ctl_extended(struct sg_fd *sfp, void __user *p)
if (or_masks & SG_SEIM_BLK_POLL) {
n = 0;
if (s_wr_mask & SG_SEIM_BLK_POLL) {
- result = sg_sfp_blk_poll(sfp, seip->num);
+ result = sg_sfp_blk_poll_all(sfp, seip->num);
if (unlikely(result < 0)) {
if (ret == 0)
ret = result;
@@ -5368,14 +5423,14 @@ sg_ioctl_common(struct file *filp, struct sg_device *sdp, struct sg_fd *sfp, uns
case SG_GET_NUM_WAITING:
/* Want as fast as possible, with a useful result */
if (test_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm)) {
- res = sg_sfp_blk_poll(sfp, 0); /* LLD may have some ready */
+ res = sg_sfp_blk_poll_all(sfp, 1); /* LLD may have some ready */
if (unlikely(res < 0))
return res;
}
- val = atomic_read(&sfp->waiting);
+ val = atomic_read(&sfp->poll_waiting);
if (val)
return put_user(val, ip);
- return put_user(atomic_read_acquire(&sfp->waiting), ip);
+ return put_user(atomic_read_acquire(&sfp->poll_waiting), ip);
case SG_IO:
if (SG_IS_DETACHING(sdp))
return -ENODEV;
@@ -5423,18 +5478,18 @@ sg_ioctl_common(struct file *filp, struct sg_device *sdp, struct sg_fd *sfp, uns
return res;
assign_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm, !!val);
return 0;
- case SG_GET_PACK_ID: /* or tag of oldest "read"-able, -1 if none */
+ case SG_GET_PACK_ID: /* or tag of oldest pollable, -1 if none */
val = -1;
if (test_bit(SG_FFD_PREFER_TAG, sfp->ffd_bm)) {
xa_for_each_marked(&sfp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
- if (!test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm)) {
+ if (test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm)) {
val = srp->tag;
break;
}
}
} else {
xa_for_each_marked(&sfp->srp_arr, idx, srp, SG_XA_RQ_AWAIT) {
- if (!test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm)) {
+ if (test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm)) {
val = srp->pack_id;
break;
}
@@ -5637,67 +5692,56 @@ sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
#endif
/*
- * If the sg_request object is not inflight, return -ENODATA. This function
- * returns 1 if the given object was in inflight state and is in await_rcv
- * state after blk_poll() returns 1 or more. If blk_poll() fails, then that
- * (negative) value is returned. Otherwise returns 0. Note that blk_poll()
- * may complete unrelated requests that share the same q and cookie.
+ * Calls blk_poll(spin <- false) loop_count times. If loop_count is 0 then call blk_poll() once.
+ * If loop_count is negative then call blk_poll(spin <- true)) once for each request. If
+ * blk_poll() reports something other than 0 then returns at that point.
*/
static int
-sg_srp_q_blk_poll(struct sg_request *srp, struct request_queue *q, int loop_count)
+sg_sfp_blk_poll_all(struct sg_fd *sfp, int loop_count)
{
+ int res = 0;
int k, n, num;
+ unsigned long idx;
+ struct sg_request *srp;
+ struct scsi_device *sdev = sfp->parentdp->device;
+ struct request_queue *q = sdev ? sdev->request_queue : NULL;
+ if (unlikely(!q))
+ return -EINVAL;
num = (loop_count < 1) ? 1 : loop_count;
- for (k = 0; k < num; ++k) {
- if (atomic_read(&srp->rq_st) != SG_RQ_INFLIGHT)
- return -ENODATA;
- n = blk_poll(q, srp->cookie, loop_count < 0 /* spin if negative */);
- if (n > 0)
- return atomic_read(&srp->rq_st) == SG_RQ_AWAIT_RCV;
- if (n < 0)
- return n;
+ xa_for_each(&sfp->srp_arr, idx, srp) {
+ if ((srp->rq_flags & SGV4_FLAG_HIPRI) &&
+ atomic_read(&srp->rq_st) == SG_RQ_INFLIGHT &&
+ test_bit(SG_FRQ_PC_ISSUED, srp->frq_pc_bm)) {
+ for (k = 0; k < num; ++k) {
+ n = blk_poll(q, srp->cookie, loop_count < 0);
+ if (n < 0)
+ return n;
+ if (n > 0)
+ res += n;
+ }
+ }
}
- return 0;
+ return res;
}
-/*
- * Check all requests on this sfp that are both inflight and HIPRI. That check involves calling
- * blk_poll(spin<-false) loop_count times. If loop_count is 0 then call blk_poll once.
- * If loop_count is negative then call blk_poll(spin <- true)) once for each request.
- * Returns number found (could be 0) or a negated errno value.
- */
static int
-sg_sfp_blk_poll(struct sg_fd *sfp, int loop_count)
+sg_sfp_blk_poll_first(struct sg_fd *sfp)
{
- int res = 0;
- int n;
- unsigned long idx, iflags;
+ unsigned long idx;
struct sg_request *srp;
struct scsi_device *sdev = sfp->parentdp->device;
struct request_queue *q = sdev ? sdev->request_queue : NULL;
- struct xarray *xafp = &sfp->srp_arr;
if (unlikely(!q))
return -EINVAL;
- xa_lock_irqsave(xafp, iflags);
- xa_for_each(xafp, idx, srp) {
+ xa_for_each(&sfp->srp_arr, idx, srp) {
if ((srp->rq_flags & SGV4_FLAG_HIPRI) &&
- !test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm) &&
atomic_read(&srp->rq_st) == SG_RQ_INFLIGHT &&
- test_bit(SG_FRQ_PC_ISSUED, srp->frq_pc_bm)) {
- xa_unlock_irqrestore(xafp, iflags);
- n = sg_srp_q_blk_poll(srp, q, loop_count);
- if (n == -ENODATA)
- n = 0;
- if (unlikely(n < 0))
- return n;
- xa_lock_irqsave(xafp, iflags);
- res += n;
- }
+ test_bit(SG_FRQ_PC_ISSUED, srp->frq_pc_bm))
+ return blk_poll(q, srp->cookie, false);
}
- xa_unlock_irqrestore(xafp, iflags);
- return res;
+ return 0;
}
/* Implements the poll(2) system call. Returns various EPOLL* flags OR-ed together. */
@@ -5709,11 +5753,11 @@ sg_poll(struct file *filp, poll_table *wait)
struct sg_fd *sfp = filp->private_data;
if (test_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm))
- sg_sfp_blk_poll(sfp, 0); /* LLD may have some ready to push up */
- num = atomic_read(&sfp->waiting);
+ sg_sfp_blk_poll_all(sfp, 1); /* LLD may have some ready to push up */
+ num = atomic_read(&sfp->poll_waiting);
if (num < 1) {
poll_wait(filp, &sfp->cmpl_wait, wait);
- num = atomic_read(&sfp->waiting);
+ num = atomic_read(&sfp->poll_waiting);
}
if (num > 0)
p_res = EPOLLIN | EPOLLRDNORM;
@@ -5916,7 +5960,7 @@ static void
sg_rq_end_io(struct request *rqq, blk_status_t status)
{
enum sg_rq_state rqq_state = SG_RQ_AWAIT_RCV;
- int a_resid, slen;
+ int a_resid, slen, num;
u32 rq_result;
unsigned long iflags;
struct sg_request *srp = rqq->end_io_data;
@@ -5976,30 +6020,31 @@ sg_rq_end_io(struct request *rqq, blk_status_t status)
}
}
srp->sense_len = slen;
- if (unlikely(test_bit(SG_FRQ_PC_IS_ORPHAN, srp->frq_pc_bm))) {
- if (test_bit(SG_FFD_KEEP_ORPHAN, sfp->ffd_bm)) {
- __clear_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm);
- } else {
+ xa_lock_irqsave(&sfp->srp_arr, iflags);
+ if (unlikely(test_bit(SG_FFD_SIG_PEND, sfp->ffd_bm))) {
+ __set_bit(SG_FRQ_PC_IS_ORPHAN, srp->frq_pc_bm);
+ if (test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm) &&
+ (!test_bit(SG_FFD_KEEP_ORPHAN, sfp->ffd_bm))) {
rqq_state = SG_RQ_BUSY;
+ /* since ! KEEP_ORPHAN then we will harvest it */
__set_bit(SG_FRQ_PC_DEACT_ORPHAN, srp->frq_pc_bm);
}
}
- xa_lock_irqsave(&sfp->srp_arr, iflags);
__set_bit(SG_FRQ_PC_ISSUED, srp->frq_pc_bm);
sg_rq_chg_state_force_ulck(srp, rqq_state); /* normally --> SG_RQ_AWAIT_RCV */
WRITE_ONCE(srp->rqq, NULL);
- if (test_bit(SG_FRQ_PC_COUNT_ACTIVE, srp->frq_pc_bm)) {
- int num = atomic_inc_return(&sfp->waiting);
+ if (test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm))
+ num = atomic_inc_return(&sfp->poll_waiting);
+ else
+ num = atomic_inc_return(&sfp->nonp_waiting);
+ if (num < 2) {
+ WRITE_ONCE(sfp->low_await_idx, srp->rq_idx);
+ } else {
+ int l_await_idx = READ_ONCE(sfp->low_await_idx);
- if (num < 2) {
+ if (l_await_idx < 0 || srp->rq_idx < l_await_idx ||
+ !xa_get_mark(&sfp->srp_arr, l_await_idx, SG_XA_RQ_AWAIT))
WRITE_ONCE(sfp->low_await_idx, srp->rq_idx);
- } else {
- int l_await_idx = READ_ONCE(sfp->low_await_idx);
-
- if (l_await_idx < 0 || srp->rq_idx < l_await_idx ||
- !xa_get_mark(&sfp->srp_arr, l_await_idx, SG_XA_RQ_AWAIT))
- WRITE_ONCE(sfp->low_await_idx, srp->rq_idx);
- }
}
xa_unlock_irqrestore(&sfp->srp_arr, iflags);
/*
@@ -6007,7 +6052,7 @@ sg_rq_end_io(struct request *rqq, blk_status_t status)
* can be called later from user context.
*/
scsi_req_free_cmd(scsi_rp);
- blk_put_request(rqq);
+ blk_put_request(rqq); /* may want to delay this in HIPRI case */
if (unlikely(rqq_state != SG_RQ_AWAIT_RCV)) {
/* clean up orphaned request that aren't being kept */
@@ -6640,13 +6685,18 @@ sg_finish_scsi_blk_rq(struct sg_request *srp)
struct bio *bio;
__maybe_unused char b[32];
+ if (xa_get_mark(&sfp->srp_arr, srp->rq_idx, SG_XA_RQ_INACTIVE)) {
+ SG_LOG(1, sfp, "%s: warning: already inactive srp=0x%pK\n", __func__, srp);
+ return;
+ }
SG_LOG(4, sfp, "%s: srp=0x%pK%s\n", __func__, srp, sg_get_rsv_str_lck(srp, " ", "",
sizeof(b), b));
- if (test_and_clear_bit(SG_FRQ_PC_COUNT_ACTIVE, srp->frq_pc_bm)) {
- if (atomic_dec_and_test(&sfp->submitted))
- clear_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm);
- atomic_dec_return_release(&sfp->waiting);
- }
+ if (atomic_dec_and_test(&sfp->submitted))
+ clear_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm);
+ if (test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm))
+ atomic_dec_return_release(&sfp->poll_waiting);
+ else
+ atomic_dec_return_release(&sfp->nonp_waiting);
/* Expect blk_put_request(rqq) already called in sg_rq_end_io() */
if (unlikely(rqq)) {
WRITE_ONCE(srp->rqq, NULL);
@@ -6827,98 +6877,78 @@ sg_read_append(struct sg_request *srp, void __user *outp, int num_xfer)
}
/*
- * If there are many requests outstanding, the speed of this function is important. 'id' is pack_id
- * when is_tag=false, otherwise it is a tag. Both SG_PACK_ID_WILDCARD and SG_TAG_WILDCARD are -1
- * and that case is typically the fast path. This function is only used in the non-blocking cases.
- * Returns pointer to (first) matching sg_request or NULL. If found, sg_request state is moved
- * from SG_RQ_AWAIT_RCV to SG_RQ_BUSY.
+ * If there are many requests outstanding, the speed of this function is important. If the
+ * number waiting (divided into two counts: poll_waiting and nonp_waiting) is 0 then returns
+ * NULL. Otherwise it checks all the awaiting requests (after applying the constraints in
+ * sfp_p) and the first it finds, it tries to place it in busy state. If that succeeds the
+ * address of the request (a srp) is returned. If it fails, it keeps looking. If the requests
+ * are exhausted before one can be placed in busy state, then NULL is returned.
*/
static struct sg_request *
-sg_get_srp_by_id(struct sg_fd *sfp, int id, bool is_tag, bool part_mrq)
+sg_find_srp_from(struct sg_fd_pollable *sfp_p)
{
__maybe_unused bool is_bad_st = false;
- bool search_for_1 = (id != SG_TAG_WILDCARD);
+ bool search_for_any = (sfp_p->find_by == SG_SEARCH_ANY || sfp_p->pack_id_tag == -1);
bool second = false;
int res;
- int l_await_idx = READ_ONCE(sfp->low_await_idx);
unsigned long idx, s_idx;
unsigned long end_idx = ULONG_MAX;
+ struct sg_fd *fp = sfp_p->fp;
+ int l_await_idx = READ_ONCE(fp->low_await_idx);
struct sg_request *srp = NULL;
- struct xarray *xafp = &sfp->srp_arr;
+ struct xarray *xafp = &fp->srp_arr;
- if (test_bit(SG_FFD_HIPRI_SEEN, sfp->ffd_bm)) {
- res = sg_sfp_blk_poll(sfp, 0); /* LLD may have some ready to push up */
+ if (test_bit(SG_FFD_HIPRI_SEEN, fp->ffd_bm)) {
+ res = sg_sfp_blk_poll_first(fp); /* LLD may have some ready to push up */
if (unlikely(res < 0))
return ERR_PTR(res);
}
- if (sg_num_waiting_maybe_acquire(sfp) < 1)
+ if (sg_num_waiting_maybe_acquire(sfp_p) < 1)
return NULL;
s_idx = (l_await_idx < 0) ? 0 : l_await_idx;
idx = s_idx;
- if (unlikely(search_for_1)) {
-second_time_for_1:
- for (srp = xa_find(xafp, &idx, end_idx, SG_XA_RQ_AWAIT);
- srp;
- srp = xa_find_after(xafp, &idx, end_idx, SG_XA_RQ_AWAIT)) {
- if (part_mrq != test_bit(SG_FRQ_PC_PART_MRQ, srp->frq_pc_bm))
- continue;
- if (!part_mrq && test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm))
- continue;
- if (unlikely(is_tag)) {
- if (srp->tag != id)
+ /* first search from [s_idx ... end_idx) */
+second_time:
+ for (srp = xa_find(xafp, &idx, end_idx, SG_XA_RQ_AWAIT);
+ srp;
+ srp = xa_find_after(xafp, &idx, end_idx, SG_XA_RQ_AWAIT)) {
+ if (sfp_p->part_mrq != test_bit(SG_FRQ_PC_PART_MRQ, srp->frq_pc_bm))
+ continue;
+ if (sfp_p->pollable != test_bit(SG_FRQ_PC_POLLABLE, srp->frq_pc_bm))
+ continue;
+ if (unlikely(!search_for_any)) {
+ if (sfp_p->find_by == SG_SEARCH_BY_TAG) {
+ if (srp->tag != sfp_p->pack_id_tag)
continue;
} else {
- if (srp->pack_id != id)
+ if (srp->pack_id != sfp_p->pack_id_tag)
continue;
}
- res = sg_rq_chg_state(srp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY);
- if (likely(res == 0))
- goto good;
- }
- /* If not found so far, need to wrap around and search [0 ... s_idx) */
- if (!srp && !second && s_idx > 0) {
- end_idx = s_idx - 1;
- s_idx = 0;
- idx = s_idx;
- second = true;
- goto second_time_for_1;
}
- } else {
- /*
- * Searching for _any_ request is the more likely usage. Start searching with the
- * last xarray index that was used. In the case of a large-ish IO depth, it is
- * likely that the second (relative) position will be the request we want, if it
- * is ready. If there is no queuing and the "last used" has been re-used then the
- * first (relative) position will be the request we want.
- */
-second_time_for_any:
- for (srp = xa_find(xafp, &idx, end_idx, SG_XA_RQ_AWAIT);
- srp;
- srp = xa_find_after(xafp, &idx, end_idx, SG_XA_RQ_AWAIT)) {
- if (test_bit(SG_FRQ_PC_SYNC_INVOC, srp->frq_pc_bm))
- continue;
- res = sg_rq_chg_state(srp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY);
- if (likely(res == 0)) {
- WRITE_ONCE(sfp->low_await_idx, idx + 1);
- goto good;
- }
+ res = sg_rq_chg_state(srp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY);
+ if (likely(res == 0)) {
+ if (search_for_any)
+ WRITE_ONCE(fp->low_await_idx, idx + 1);
+ goto good;
+ }
#if IS_ENABLED(SG_LOG_ACTIVE)
- sg_rq_state_fail_msg(sfp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY, __func__);
+ sg_rq_state_fail_msg(fp, SG_RQ_AWAIT_RCV, SG_RQ_BUSY, __func__);
#endif
- }
- if (!srp && !second && s_idx > 0) {
- end_idx = s_idx - 1;
- s_idx = 0;
- idx = s_idx;
- second = true;
- goto second_time_for_any;
- }
+ }
+ /* If not found so far, need to wrap around and search [0 ... s_idx) */
+ if (!srp && !second && s_idx > 0) {
+ end_idx = s_idx - 1;
+ s_idx = 0;
+ idx = s_idx;
+ second = true;
+ goto second_time;
}
return NULL;
good:
- SG_LOG(5, sfp, "%s: %s%d found [srp=0x%pK]\n", __func__, (is_tag ? "tag=" : "pack_id="),
- id, srp);
+ SG_LOG(5, fp, "%s: %s%d found [srp=0x%pK]\n", __func__,
+ ((sfp_p->find_by == SG_SEARCH_BY_TAG) ? "tag=" : "pack_id="), sfp_p->pack_id_tag,
+ srp);
return srp;
}
@@ -7392,6 +7422,10 @@ sg_deact_request(struct sg_fd *sfp, struct sg_request *srp)
if (WARN_ON(!sfp || !srp))
return;
+ if (xa_get_mark(&sfp->srp_arr, srp->rq_idx, SG_XA_RQ_INACTIVE)) {
+ SG_LOG(4, sfp, "%s: warning: already inactive srp=0x%pK\n", __func__, srp);
+ return;
+ }
SG_LOG(3, sfp, "%s: srp=%pK\n", __func__, srp);
sbp = srp->sense_bp;
srp->sense_bp = NULL;
@@ -7444,7 +7478,8 @@ sg_add_sfp(struct sg_device *sdp, struct file *filp)
sfp->tot_fd_thresh = SG_TOT_FD_THRESHOLD;
atomic_set(&sfp->sum_fd_dlens, 0);
atomic_set(&sfp->submitted, 0);
- atomic_set(&sfp->waiting, 0);
+ atomic_set(&sfp->poll_waiting, 0);
+ atomic_set(&sfp->nonp_waiting, 0);
atomic_set(&sfp->inactives, 0);
/*
* SG_SCATTER_SZ initializes scatter_elem_sz but different value may be given as driver
@@ -7921,6 +7956,8 @@ sg_proc_debug_sreq(struct sg_request *srp, int to, bool t_in_ns, bool inactive,
sg_shr_str(srp->sh_var, false));
if (srp->sgatp->num_sgat > 1)
n += scnprintf(obp + n, len - n, " sgat=%d", srp->sgatp->num_sgat);
+ if (test_bit(SG_FRQ_PC_POLLABLE, srp->frq_lt_bm))
+ n += scnprintf(obp + n, len - n, " pollable");
if (test_bit(SG_FRQ_LT_REUSE_BIO, srp->frq_lt_bm))
n += scnprintf(obp + n, len - n, " re-use_bio");
cp = (srp->rq_flags & SGV4_FLAG_HIPRI) ? "hipri " : "";
@@ -7977,9 +8014,10 @@ sg_proc_debug_fd(struct sg_fd *fp, char *obp, int len, unsigned long idx, bool r
fp->mmap_sz, READ_ONCE(fp->low_used_idx), READ_ONCE(fp->low_await_idx),
atomic_read(&fp->sum_fd_dlens));
n += scnprintf(obp + n, len - n,
- " submitted=%d waiting=%d inactives=%d open thr_id=%d\n",
- atomic_read(&fp->submitted), atomic_read(&fp->waiting),
- atomic_read(&fp->inactives), fp->tid);
+ " submitted=%d poll_waiting=%d nonp_waiting=%d inactives=%d %s=%d\n",
+ atomic_read(&fp->submitted), atomic_read(&fp->poll_waiting),
+ atomic_read(&fp->nonp_waiting), atomic_read(&fp->inactives),
+ "open thr_id", fp->tid);
if (reduced)
return n;
k = 0;
--
2.25.1
next prev parent reply other threads:[~2021-04-27 22:00 UTC|newest]
Thread overview: 86+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-27 21:56 [PATCH v18 00/83] sg: add v4 interface, request sharing Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 00/45] sg: add v4 interface Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 01/83] sg: move functions around Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 02/83] sg: remove typedefs, type+formatting cleanup Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 03/83] sg: sg_log and is_enabled Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 04/83] sg: rework sg_poll(), minor changes Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 05/83] sg: bitops in sg_device Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 06/83] sg: make open count an atomic Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 07/83] sg: move header to uapi section Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 08/83] sg: speed sg_poll and sg_get_num_waiting Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 09/83] sg: sg_allow_if_err_recovery and renames Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 10/83] sg: improve naming Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 11/83] sg: change rwlock to spinlock Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 12/83] sg: ioctl handling Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 13/83] sg: split sg_read Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 14/83] sg: sg_common_write add structure for arguments Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 15/83] sg: rework sg_vma_fault Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 16/83] sg: rework sg_mmap Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 17/83] sg: replace sg_allow_access Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 18/83] sg: rework scatter gather handling Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 19/83] sg: introduce request state machine Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 20/83] sg: sg_find_srp_by_id Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 21/83] sg: sg_fill_request_element Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 22/83] sg: printk change %p to %pK Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 23/83] sg: xarray for fds in device Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 24/83] sg: xarray for reqs in fd Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 25/83] sg: replace rq array with xarray Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 26/83] sg: sense buffer rework Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 27/83] sg: add sg v4 interface support Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 28/83] sg: rework debug info Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 29/83] sg: add 8 byte SCSI LUN to sg_scsi_id Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 30/83] sg: expand sg_comm_wr_t Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 31/83] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 32/83] sg: add some __must_hold macros Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 33/83] sg: move procfs objects to avoid forward decls Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 34/83] sg: protect multiple receivers Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 35/83] sg: first debugfs support Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 36/83] sg: rework mmap support Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 37/83] sg: defang allow_dio Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 38/83] sg: warn v3 write system call users Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 39/83] sg: add mmap_sz tracking Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 40/83] sg: remove rcv_done request state Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 41/83] sg: track lowest inactive and await indexes Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 42/83] sg: remove unit attention check for device changed Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 43/83] sg: no_dxfer: move to/from kernel buffers Douglas Gilbert
2021-04-28 7:07 ` Hannes Reinecke
2021-04-27 21:56 ` [PATCH v18 44/83] sg: add blk_poll support Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 45/83] sg: bump version to 4.0.12 Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 46/83] sg: add sg_ioabort ioctl Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 47/83] sg: add sg_set_get_extended ioctl Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 48/83] sg: sgat_elem_sz and sum_fd_dlens Douglas Gilbert
2021-04-27 21:56 ` [PATCH v18 49/83] sg: tag and more_async Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 50/83] sg: add fd sharing , change, unshare Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 51/83] sg: add shared requests Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 52/83] sg: add multiple request support Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 53/83] sg: rename some mrq variables Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 54/83] sg: unlikely likely Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 55/83] sg: mrq abort Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 56/83] sg: reduce atomic operations Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 57/83] sg: add excl_wait flag Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 58/83] sg: tweak sg_find_sfp_by_fd() Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 59/83] sg: add snap_dev flag and snapped in debugfs Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 60/83] sg: compress usercontext to uc Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 61/83] sg: optionally output sg_request.frq_bm flags Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 62/83] sg: work on sg_mrq_sanity() Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 63/83] sg: shared variable blocking Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 64/83] sg: device timestamp Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 65/83] sg: condition met is not an error Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 66/83] sg: split sg_setup_req Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 67/83] sg: finish after read-side request Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 68/83] sg: keep share and dout offset flags Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 69/83] sg: add dlen to sg_comm_wr_t Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 70/83] sg: make use of struct sg_mrq_hold Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 71/83] sg: add mmap IO option for mrq metadata Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 72/83] sg: add eventfd support Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 73/83] sg: table of error number explanations Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 74/83] sg: add ordered write flag Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 75/83] sg: expand source line length to 100 characters Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 76/83] sg: add no_attach_msg parameter Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 77/83] sg: add SGV4_FLAG_REC_ORDER Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 78/83] sg: max to read for mrq sg_ioreceive Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 79/83] sg: mrq: if uniform svb then re-use bio_s Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 80/83] sg: expand bvec usage; " Douglas Gilbert
2021-04-27 21:57 ` [PATCH v18 81/83] sg: blk_poll/hipri work for mrq Douglas Gilbert
2021-04-27 21:57 ` Douglas Gilbert [this message]
2021-04-27 21:57 ` [PATCH v18 83/83] sg: bump version to 4.0.47 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=20210427215733.417746-84-dgilbert@interlog.com \
--to=dgilbert@interlog.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.