[PATCH 10/19] sg: add sg_ioabort ioctl

2019-05-24 Thread Douglas Gilbert
Add ioctl(SG_IOABORT) that acts as a front-end to
blk_abort_request() which is only called if the request
is "inflight". The request to abort is matched via its
pack_id and the scope of the search is the current
device.

That scope will be fine tuned in a later patch to being
either all file descriptors belonging to the current
device, or just the current file descriptor.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 158 +
 include/uapi/scsi/sg.h |   3 +
 2 files changed, 132 insertions(+), 29 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 638368ed9e11..7575dd66dbef 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -111,6 +111,7 @@ enum sg_rq_state {
 #define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
 #define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
 #define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
+#define SG_FRQ_ABORTING5   /* in process of aborting this 
cmd */
 #define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
 #define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
 
@@ -1566,6 +1567,97 @@ sg_ctl_sg_io(struct file *filp, struct sg_device *sdp, 
struct sg_fd *sfp,
return res;
 }
 
+static struct sg_request *
+sg_match_request(struct sg_fd *sfp, int id)
+{
+   bool found = false;
+   struct sg_request *srp;
+
+   if (list_empty(&sfp->rq_list))
+   return NULL;
+   if (id == SG_PACK_ID_WILDCARD)  /* both wildcards same value: -1 */
+   return list_first_entry_or_null(&sfp->rq_list,
+   struct sg_request, rq_entry);
+   list_for_each_entry(srp, &sfp->rq_list, rq_entry) {
+   if (id == srp->pack_id) {
+   found = true;
+   break;
+   }
+   }
+   return found ? srp : NULL;
+}
+
+static int
+sg_ctl_abort(struct sg_device *sdp, struct sg_fd *sfp, void __user *p)
+{
+   int res, pack_id, id;
+   unsigned long iflags;
+   struct sg_fd *o_sfp;
+   struct sg_request *srp;
+   struct sg_io_v4 io_v4;
+   struct sg_io_v4 *h4p = &io_v4;
+
+   if (copy_from_user(h4p, p, SZ_SG_IO_V4))
+   return -EFAULT;
+   if (h4p->guard != 'Q' || h4p->protocol != 0 || h4p->subprotocol != 0)
+   return -EPERM;
+   pack_id = h4p->request_extra;
+   id = pack_id;
+
+   spin_lock(&sfp->rq_list_lock);
+   srp = sg_match_request(sfp, id);
+   if (srp) {
+   spin_lock_irqsave(&srp->req_lck, iflags);
+   spin_unlock(&sfp->rq_list_lock);
+   } else {/* assume device (not just fd) scope */
+   spin_unlock(&sfp->rq_list_lock);
+   read_lock(&sdp->sfd_llock);
+   list_for_each_entry(o_sfp, &sdp->sfds, sfd_entry) {
+   if (o_sfp == sfp)
+   continue;   /* already checked */
+   spin_lock(&o_sfp->rq_list_lock);
+   srp = sg_match_request(o_sfp, id);
+   if (srp) {
+   spin_lock_irqsave(&srp->req_lck, iflags);
+   spin_unlock(&o_sfp->rq_list_lock);
+   sfp = o_sfp;
+   break;
+   }
+   spin_unlock(&o_sfp->rq_list_lock);
+   }
+   read_unlock(&sdp->sfd_llock);
+   }
+   if (!srp)
+   return -ENODATA;
+
+   set_bit(SG_FRQ_ABORTING, srp->frq_bm);
+   res = 0;
+   switch (atomic_read(&srp->rq_st)) {
+   case SG_RS_BUSY:
+   clear_bit(SG_FRQ_ABORTING, srp->frq_bm);
+   res = -EBUSY;   /* shouldn't occur often */
+   break;
+   case SG_RS_INACTIVE:/* inactive on rq_list not good */
+   clear_bit(SG_FRQ_ABORTING, srp->frq_bm);
+   res = -EPROTO;
+   break;
+   case SG_RS_AWAIT_RD:/* user should still do completion */
+   case SG_RS_DONE_RD:
+   clear_bit(SG_FRQ_ABORTING, srp->frq_bm);
+   break;  /* nothing to do here, return 0 */
+   case SG_RS_INFLIGHT:/* only attempt abort if inflight */
+   srp->rq_result |= (DRIVER_SOFT << 24);
+   if (srp->rq)
+   blk_abort_request(srp->rq);
+   break;
+   default:
+   clear_bit(SG_FRQ_ABORTING, srp->frq_bm);
+   break;
+   }
+   spin_unlock_irqrestore(&srp->req_lck, iflags);
+   return res;
+}
+
 /*
  * First normalize want_rsv_sz t

[PATCH 05/19] sg: replace rq array with lists

2019-05-24 Thread Douglas Gilbert
Remove the fixed size array of 16 request elements per file descriptor
and replace with two linked lists (per fd). One list is for active
commands, the other list is a free list. sg_request objects are now
kept, available for re-use, until their owning file descriptor is
closed. The associated block request and scsi_request objects are
released much earlier; their lifetime is the same as it was in the
v3 sg driver. The lifetime of the bio is also the same (but is
stretched in a later patch).

Add an enum for request state (sg_rq_state) and collect various flags
into bit maps: one for requests (SG_FRQ_*) and the other for file
descriptors (SG_FFD_*).

Since the above changes touch almost every function and low level
structures, this patch is big. With so many changes, the diff
utility that generates the patch sometimes loses track.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 3451 +
 1 file changed, 2231 insertions(+), 1220 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 291c278451ef..72ce51b3198c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -57,28 +57,79 @@ static char *sg_version_date = "20140603";
 
 #define SG_MAX_DEVS 32768
 
-/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
+/* Comment out the following line to compile out SCSI_LOGGING stuff */
+#define SG_DEBUG 1
+
+#if !IS_ENABLED(SG_DEBUG)
+#if IS_ENABLED(DEBUG)/* If SG_DEBUG not defined, check for DEBUG */
+#define SG_DEBUG DEBUG
+#endif
+#endif
+
+/*
+ * SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
- * than 16 bytes are "variable length" whose length is a multiple of 4
+ * than 16 bytes are "variable length" whose length is a multiple of 4, so
  */
 #define SG_MAX_CDB_SIZE 252
 
+#define uptr64(val) ((void __user *)(uintptr_t)(val))
+#define cuptr64(val) ((const void __user *)(uintptr_t)(val))
+
+/* Following enum contains the states of sg_request::rq_st */
+enum sg_rq_state {
+   SG_RS_INACTIVE = 0, /* request not in use (e.g. on fl) */
+   SG_RS_INFLIGHT, /* active: cmd/req issued, no response yet */
+   SG_RS_AWAIT_RD, /* response received, awaiting read */
+   SG_RS_DONE_RD,  /* read is ongoing or done */
+   SG_RS_BUSY, /* temporary state should rarely be seen */
+};
+
+#define SG_TIME_UNIT_MS 0  /* milliseconds */
+#define SG_DEF_TIME_UNIT SG_TIME_UNIT_MS
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
+#define SG_FD_Q_AT_HEAD 0
+#define SG_DEFAULT_Q_AT SG_FD_Q_AT_HEAD /* for backward compatibility */
+#define SG_FL_MMAP_DIRECT (SG_FLAG_MMAP_IO | SG_FLAG_DIRECT_IO)
+
+/* Only take lower 4 bits of driver byte, all host byte and sense byte */
+#define SG_ML_RESULT_MSK 0x0fff00ff/* mid-level's 32 bit result value */
+
+#define SG_SHARE_FD_UNUSED (-1)
+#define SG_SHARE_FD_MASTER (-2)/* values >= 0 imply FD_SLAVE */
+
+#define SG_PACK_ID_WILDCARD (-1)
+
+#define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
+
+/* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
+#define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
+#define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
+#define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
+#define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
+#define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
+
+/* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
+#define SG_FFD_FORCE_PACKID0   /* receive only given pack_id/tag */
+#define SG_FFD_CMD_Q   1   /* clear: only 1 active req per fd */
+#define SG_FFD_KEEP_ORPHAN 2   /* policy for this fd */
+#define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
+#define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
+
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
-/* N.B. This variable is readable and writeable via
-   /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
-   of this size (or less if there is not enough memory) will be reserved
-   for use by this file descriptor. [Deprecated usage: this variable is also
-   readable via /proc/sys/kernel/sg-big-buff if the sg driver is built into
-   the kernel (i.e. it is not a module).] */
-static int def_reserved_size = -1; /* picks up init parameter */
+/*
+ * This variable is accessible via /proc/scsi/sg/def_reserved_size . Each
+ * time sg_open() is called a sg_request of this size (or less if there is
+ * not enough memory) will be reserved for use by this file descriptor.
+ */
+static int def_reserved_size = -1;  /* picks u

[PATCH 15/19] sg: add fd sharing , change, unshare

2019-05-24 Thread Douglas Gilbert
Add the ability establish a share between any two open file
descriptors in the sg driver. Neither file descriptor can
already be part of a share. This fd share is used for two
features added and described in later patches: request
sharing and the "do_on_other" flag used when multiple
requests are issued (with a single invocation from the
user space). See the webpage at:
http://sg.danny.cz/sg/sg_v40.html
in the section titled: "5 Sharing file descriptors".

Usually two file descriptors are enough. To support the
ability to READ once and then WRITE to two or more
file descriptors (hence potentially to write the same
data to different disks) the ability to drop the
share partner file descriptor and replace it with a
new fd is also available.

Finally a share can explicitly be undone, or unshared,
by either side. In practice, close()ing either side of
a fd share has the same effect (i.e. to unshare) so
this route is the more common.

File shares maybe within a single-threaded process,
between threads in the same process, or even between
processes (on the same machine) by passing an open
file descriptor via Unix sockets to the other process.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 491 +
 include/uapi/scsi/sg.h |   3 +
 2 files changed, 404 insertions(+), 90 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6a26aa483d8e..44f09c65e0b9 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -33,6 +33,7 @@ static char *sg_version_date = "20190520";
 #include 
 #include 
 #include 
+#include /* for fget() and fput() */
 #include 
 #include 
 #include 
@@ -43,6 +44,7 @@ static char *sg_version_date = "20190520";
 #include 
 #include /* for sg_check_file_access() */
 #include 
+#include 
 #include  /* used if CONFIG_SCSI_PROC_FS */
 #include 
 
@@ -129,6 +131,7 @@ enum sg_rq_state {
 #define SG_FFD_TIME_IN_NS  4   /* set: time in nanoseconds, else ms */
 #define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
 #define SG_FFD_PREFER_TAG  7   /* prefer tag over pack_id (def) */
+#define SG_FFD_RELEASE 8   /* release (close) underway */
 #define SG_FFD_NO_DURATION 9   /* don't do command duration calc */
 #define SG_FFD_MORE_ASYNC  10  /* yield EBUSY more often */
 
@@ -234,13 +237,16 @@ struct sg_fd {/* holds the state of a file 
descriptor */
int timeout_user;   /* defaults to SG_DEFAULT_TIMEOUT_USER */
int tot_fd_thresh;  /* E2BIG if sum_of(dlen) > this, 0: ignore */
int sgat_elem_sz;   /* initialized to scatter_elem_sz */
+   int shr_fd; /* init: SG_SHARE_FD_UNUSED; master: -2 */
atomic_t sum_fd_dlens;  /* when tot_fd_thresh>0 this is sum_of(dlen) */
atomic_t submitted; /* number inflight or awaiting read */
atomic_t waiting;   /* number of requests awaiting read */
unsigned long ffd_bm[1];/* see SG_FFD_* defines above */
pid_t tid;  /* thread id when opened */
u8 next_cmd_len;/* 0: automatic, >0: use on next write() */
+   struct file *filp;  /* my identity when sharing */
struct sg_request *rsv_srp;/* one reserve request per fd */
+   struct sg_fd *share_sfp;/* master+slave shares set this, else NULL */
struct fasync_struct *async_qp; /* used by asynchronous notification */
struct kref f_ref;
struct execute_work ew_fd;  /* harvest all fd resources and lists */
@@ -273,7 +279,6 @@ struct sg_comm_wr_t {   /* arguments to 
sg_common_write() */
struct sg_io_v4 *h4p;
};
struct sg_fd *sfp;
-   struct file *filp;
const u8 __user *u_cmdp;
const u8 *cmdp;
 };
@@ -286,14 +291,15 @@ static int sg_start_req(struct sg_request *srp, struct 
sg_comm_wr_t *cwrp,
int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
-static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
-   struct sg_io_hdr *hp, bool sync,
+static int sg_v3_receive(struct sg_fd *sfp, struct sg_request *srp,
+void __user *p);
+static int sg_v3_submit(struct sg_fd *sfp, struct sg_io_hdr *hp, bool sync,
struct sg_request **o_srp);
 static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwrp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_sgat(struct sg_request *srp);
-static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
+static struct sg_fd *sg_add_sfp(struct sg_device *sdp, struct file *filp);
 static void sg_remove_sfp(struct kref *);
 static struct s

[PATCH 14/19] sg: tag and more_async

2019-05-24 Thread Douglas Gilbert
Wire up some more capabilities of ioctl(SG_SET_GET_EXTENDED). One
is to use a LLD or block layer generated tag rather than the user
provided pack_id to track requests. Tags to the user space for
an async interface may be considered as work in progress as there
doesn't seem to be a safe mechanism to get that tag. When this
driver fetches that tag it could be too early (so it should get
a default value) or too late (i.e. the request has completed, at
least internally). Well, pack_id has been in the sg since version
1 of the driver and works well ...

The more_async flag when set instructs the blk_get_request() not
to block which is does in the current driver on rare occasions
for some obscure reason. IMO it should not block in async mode
but there is backward compatibilty to consider.

Note to kernel janitors: please do not change setting like
GFP_ATOMIC to GFP_KERNEL in async code paths unless you
really understand the implications to user space programs.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 278 +
 include/uapi/scsi/sg.h |   3 +
 2 files changed, 199 insertions(+), 82 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 64e9de67ccd4..6a26aa483d8e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -44,6 +44,7 @@ static char *sg_version_date = "20190520";
 #include /* for sg_check_file_access() */
 #include 
 #include  /* used if CONFIG_SCSI_PROC_FS */
+#include 
 
 #include 
 #include 
@@ -106,6 +107,7 @@ enum sg_rq_state {
 #define SG_SHARE_FD_MASTER (-2)/* values >= 0 imply FD_SLAVE */
 
 #define SG_PACK_ID_WILDCARD (-1)
+#define SG_TAG_WILDCARD (-1)
 
 #define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
 
@@ -126,7 +128,9 @@ enum sg_rq_state {
 #define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
 #define SG_FFD_TIME_IN_NS  4   /* set: time in nanoseconds, else ms */
 #define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
+#define SG_FFD_PREFER_TAG  7   /* prefer tag over pack_id (def) */
 #define SG_FFD_NO_DURATION 9   /* don't do command duration calc */
+#define SG_FFD_MORE_ASYNC  10  /* yield EBUSY more often */
 
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
@@ -199,15 +203,16 @@ struct sg_request {   /* active SCSI command or 
inactive on free list (fl) */
struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
struct sg_slice_hdr4 s_hdr4; /* reduced size struct sg_io_v4 */
};
-   u32 duration;   /* cmd duration in milliseconds */
-   u32 rq_flags;   /* hold user supplied flags */
+   u32 duration;   /* cmd duration in milli or nano seconds */
+   u32 rq_flags;   /* flags given in v3 and v4 */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
u32 rq_result;  /* packed scsi request result from LLD */
int in_resid;   /* requested-actual byte count on data-in */
-   int pack_id;/* user provided packet identifier field */
+   int pack_id;/* v3 pack_id or in v4 request_extra field */
int sense_len;  /* actual sense buffer length (data-in) */
atomic_t rq_st; /* request state, holds a enum sg_rq_state */
u8 cmd_opcode;  /* first byte of SCSI cdb */
+   int tag;/* block layer identifier of request */
u64 start_ns;   /* starting point of command duration calc */
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
u8 *sense_bp;   /* alloc-ed sense buffer, as needed */
@@ -227,7 +232,7 @@ struct sg_fd {  /* holds the state of a file 
descriptor */
struct list_head rq_fl; /* head of sg_request free list */
int timeout;/* defaults to SG_DEFAULT_TIMEOUT  */
int timeout_user;   /* defaults to SG_DEFAULT_TIMEOUT_USER */
-   int tot_fd_thresh;  /* E2BIG if sum_of(dlen) > this, 0: ignore */
+   int tot_fd_thresh;  /* E2BIG if sum_of(dlen) > this, 0: ignore */
int sgat_elem_sz;   /* initialized to scatter_elem_sz */
atomic_t sum_fd_dlens;  /* when tot_fd_thresh>0 this is sum_of(dlen) */
atomic_t submitted; /* number inflight or awaiting read */
@@ -290,7 +295,8 @@ static int sg_rd_append(struct sg_request *srp, void __user 
*outp,
 static void sg_remove_sgat(struct sg_request *srp);
 static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
 static void sg_remove_sfp(struct kref *);
-static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id);
+static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id,
+   bool is_tag);
 static struct sg_request *sg_add_request(struct sg_comm_wr_t *cwrp,

[PATCH 12/19] sg: add sg_set_get_extended ioctl

2019-05-24 Thread Douglas Gilbert
Add ioctl(SG_SET_GET_EXTENDED) together with its interface:
struct sg_extended_info which is 96 bytes long, only half
of which is currently used. The "SET_GET" component of the
name is to stress data flows towards and back from the ioctl.

That ioctl has three sections: one for getting and setting 32
bit quantities, a second section for manipulating boolean
(bit) flags, and a final section for reading 32 bit
quantities where a well known value is written and the
corresponding value is read back. Several settings can be
made in one invocation.

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
specifically the section titled: "13 IOCTLs".

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 252 +
 include/uapi/scsi/sg.h |  67 +++
 2 files changed, 295 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a261ad2c4567..c014fb24eca1 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -41,9 +41,9 @@ static char *sg_version_date = "20190520";
 #include 
 #include 
 #include 
-#include /* for sg_check_file_access() */
+#include /* for sg_check_file_access() */
 #include 
-#include 
+#include  /* used if CONFIG_SCSI_PROC_FS */
 
 #include 
 #include 
@@ -120,7 +120,9 @@ enum sg_rq_state {
 #define SG_FFD_CMD_Q   1   /* clear: only 1 active req per fd */
 #define SG_FFD_KEEP_ORPHAN 2   /* policy for this fd */
 #define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
+#define SG_FFD_TIME_IN_NS  4   /* set: time in nanoseconds, else ms */
 #define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
+#define SG_FFD_NO_DURATION 9   /* don't do command duration calc */
 
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
@@ -271,13 +273,12 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, struct sg_comm_wr_t *cwrp,
int dxfer_dir);
-// static int sg_finish_rem_req(struct sg_request *srp);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
 static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
struct sg_io_hdr *hp, bool sync,
struct sg_request **o_srp);
-static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwp);
+static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwrp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_sgat(struct sg_request *srp);
@@ -302,6 +303,7 @@ static void sg_rep_rq_state_fail(struct sg_device *sdp,
 #define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
 #define SZ_SG_IO_V4 ((int)sizeof(struct sg_io_v4))  /* v4 header (in bsg.h) */
 #define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
+#define SZ_SG_EXTENDED_INFO ((int)sizeof(struct sg_extended_info))
 
 /* There is a assert that SZ_SG_IO_V4 >= SZ_SG_IO_HDR in first function */
 
@@ -440,11 +442,11 @@ static int
 sg_open(struct inode *inode, struct file *filp)
 {
bool o_excl, non_block;
+   int res;
int min_dev = iminor(inode);
int op_flags = filp->f_flags;
struct sg_device *sdp;
struct sg_fd *sfp;
-   int res;
 
nonseekable_open(inode, filp);
o_excl = !!(op_flags & O_EXCL);
@@ -508,7 +510,6 @@ sg_open(struct inode *inode, struct file *filp)
 
filp->private_data = sfp;
sfp->tid = (current ? current->pid : -1);
-   sfp->tid = (current ? current->pid : -1);
atomic_inc(&sdp->open_cnt);
mutex_unlock(&sdp->open_rel_lock);
 
@@ -842,7 +843,10 @@ sg_execute_cmd(struct sg_fd *sfp, struct sg_request *srp)
is_v4h = test_bit(SG_FRQ_IS_V4I, srp->frq_bm);
sync = test_bit(SG_FRQ_SYNC_INVOC, srp->frq_bm);
SG_LOG(3, sdp, "%s: is_v4h=%d\n", __func__, (int)is_v4h);
-   srp->start_ns = ktime_get_boot_ns();
+   if (test_bit(SG_FFD_NO_DURATION, sfp->ffd_bm))
+   srp->start_ns = 0;
+   else
+   srp->start_ns = ktime_get_boot_ns();/* assume always > 0 */
srp->duration = 0;
 
if (!is_v4h && srp->s_hdr3.interface_id == '\0')
@@ -1473,29 +1477,42 @@ sg_calc_sgat_param(struct sg_device *sdp)
sdp->max_sgat_sz = sz;
 }
 
+/*
+ * Returns duration since srp->start_ns (using boot time as an epoch). Unit
+ * is nanoseconds when time_in_ns==true; else it is in milliseconds.
+ * For backward compatibility the duration is placed in a 32 bit unsigned
+ * integer. This limits the maximum nanosecond duration that can be
+ * represented (without wrapping) to about 4.3 sec

[PATCH 04/19] sg: move header to uapi section

2019-05-24 Thread Douglas Gilbert
Move user interface part of scsi/sg.h into the new header file:
include/uapi/scsi/sg.h . Since scsi/sg.h includes the new header,
other code including scsi/sg.h should not be impacted.

Signed-off-by: Douglas Gilbert 
---
 include/scsi/sg.h  | 268 ++---
 include/uapi/scsi/sg.h | 329 +
 2 files changed, 338 insertions(+), 259 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index f91bcca604e4..46fc7cbffd78 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -4,271 +4,21 @@
 
 #include 
 
-/*
- * History:
- *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com), to allow user
- *   process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
- *
- * Original driver (sg.h):
- *   Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
- * Copyright (C) 1998 - 2014 Douglas Gilbert
- *
- *  Version: 3.5.36 (20140603)
- *  This version is for 2.6 and 3 series kernels.
- *
- * Documentation
- * =
- * A web site for the SG device driver can be found at:
- * http://sg.danny.cz/sg  [alternatively check the MAINTAINERS file]
- * The documentation for the sg version 3 driver can be found at:
- * http://sg.danny.cz/sg/p/sg_v3_ho.html
- * Also see: /Documentation/scsi/scsi-generic.txt
- *
- * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html
- */
-
 #ifdef __KERNEL__
 extern int sg_big_buff; /* for sysctl */
 #endif
 
+/*
+ * In version 3.9.01 of the sg driver, this file was spilt in two, with the
+ * bulk of the user space interface being placed in the file being included
+ * in the following line.
+ */
+#include 
 
-typedef struct sg_iovec /* same structure as used by readv() Linux system */
-{   /* call. It defines one scatter-gather element. */
-void __user *iov_base;  /* Starting address  */
-size_t iov_len; /* Length in bytes  */
-} sg_iovec_t;
-
-
-typedef struct sg_io_hdr
-{
-int interface_id;   /* [i] 'S' for SCSI generic (required) */
-int dxfer_direction;/* [i] data transfer direction  */
-unsigned char cmd_len;  /* [i] SCSI command length */
-unsigned char mx_sb_len;/* [i] max length to write to sbp */
-unsigned short iovec_count; /* [i] 0 implies no scatter gather */
-unsigned int dxfer_len; /* [i] byte count of data transfer */
-void __user *dxferp;   /* [i], [*io] points to data transfer memory
- or scatter gather list */
-unsigned char __user *cmdp; /* [i], [*i] points to command to perform */
-void __user *sbp;  /* [i], [*o] points to sense_buffer memory */
-unsigned int timeout;   /* [i] MAX_UINT->no timeout (unit: millisec) */
-unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */
-int pack_id;/* [i->o] unused internally (normally) */
-void __user * usr_ptr;  /* [i->o] unused internally */
-unsigned char status;   /* [o] scsi status */
-unsigned char masked_status;/* [o] shifted, masked scsi status */
-unsigned char msg_status;   /* [o] messaging level data (optional) */
-unsigned char sb_len_wr;/* [o] byte count actually written to sbp */
-unsigned short host_status; /* [o] errors from host adapter */
-unsigned short driver_status;/* [o] errors from software driver */
-int resid;  /* [o] dxfer_len - actual_transferred */
-unsigned int duration;  /* [o] time taken by cmd (unit: millisec) */
-unsigned int info;  /* [o] auxiliary information */
-} sg_io_hdr_t;  /* 64 bytes long (on i386) */
-
-#define SG_INTERFACE_ID_ORIG 'S'
-
-/* Use negative values to flag difference from original sg_header structure */
-#define SG_DXFER_NONE (-1)  /* e.g. a SCSI Test Unit Ready command */
-#define SG_DXFER_TO_DEV (-2)/* e.g. a SCSI WRITE command */
-#define SG_DXFER_FROM_DEV (-3)  /* e.g. a SCSI READ command */
-#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
-  additional property than during indirect
-  IO the user buffer is copied into the
-  kernel buffers before the transfer */
-#define SG_DXFER_UNKNOWN (-5)   /* Unknown data direction */
-
-/* following flag values can be "or"-ed together */
-#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
-#define SG_FLAG_UNUSED_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
-   /* command block (when <= SCSI_2) */
-#define SG_FLAG_MMAP_IO 4   /* request memory mapped IO */
-#define SG_FLAG_NO_DXFER 0x1 /* no transfer of kernel buffers to/from */
-   /* user space (debug indirect IO) */
-/* default

[PATCH 17/19] sg: add multiple request support

2019-05-24 Thread Douglas Gilbert
Before the write() and read() system calls were removed from
the bsg driver (around lk 4.15) bsg supported multiple SCSI
requests being submitted in a single invocation. It did this
by passing an array of struct sg_io_v4 objects to the write()
whose third argument (the size the second argument points to)
is then a multiple of sizeof(sg_io_v4).

Doing the same with ioctl(SG_IOSUBMIT) is not practical since
with an ioctl() there is no "length of passed object" argument.
Further the __IOWR macro used to generate the ioctl number for
SG_IOSUBMIT encodes the expected length of the passed object,
and that is the size of a _single_ struct sg_io_v4 object.
So an indirect approach is taken: any object passed to
ioctl(SG_IO), ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) with
SGV4_FLAG_MULTIPLE_REQS set is interpreted as a "controlling
object". It is parsed differently from other struct sg_io_v4
objects. Its data-out buffer contains an array of "normal"
struct sg_io_v4 objects.

Multiple requests can be combined with shared file
descriptors with SGV4_FLAG_DO_ON_OTHER indicating the other
file descriptor (in the share) is to be used for the
command it appears with. Multiple requests can be combined
with shared requests.

As a further optimisation, an array of SCSI commands can
be passed from the user space via the controlling object's
request "pointer". Without that, the multiple request
logic would need to visit the user space once per command
to pick up each SCSI command (cdb).

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
in the section titled: "9 Multiple requests"

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 616 -
 include/uapi/scsi/sg.h |  11 +-
 2 files changed, 624 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9adca3988c58..92a0226cabc2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -62,6 +62,7 @@ static char *sg_version_date = "20190520";
 #define SG_ALLOW_DIO_DEF 0
 
 #define SG_MAX_DEVS 32768
+#define SG_MAX_MULTI_REQ_SZ (2 * 1024 * 1024)
 
 /* Comment out the following line to compile out SCSI_LOGGING stuff */
 #define SG_DEBUG 1
@@ -132,6 +133,7 @@ enum sg_shr_var {
 #define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
 #define SG_FRQ_ABORTING5   /* in process of aborting this 
cmd */
 #define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
+#define SG_FRQ_MULTI_REQ   8   /* part of a multiple request series */
 #define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
 
 /* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
@@ -196,6 +198,7 @@ struct sg_slice_hdr4 {  /* parts of sg_io_v4 object 
needed in async usage */
s16 dir;/* data xfer direction; SG_DXFER_*  */
u16 cmd_len;/* truncated of sg_io_v4::request_len */
u16 max_sb_len; /* truncated of sg_io_v4::max_response_len */
+   u16 mrq_ind;/* position in parentfp->mrq_arr */
 };
 
 struct sg_scatter_hold { /* holding area for scsi scatter gather info */
@@ -311,6 +314,10 @@ static int sg_v3_receive(struct sg_fd *sfp, struct 
sg_request *srp,
 static int sg_v3_submit(struct sg_fd *sfp, struct sg_io_hdr *hp, bool sync,
struct sg_request **o_srp);
 static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwrp);
+static int sg_wait_event_srp(struct sg_fd *sfp, void __user *p,
+struct sg_io_v4 *h4p, struct sg_request *srp);
+static int sg_v4_receive(struct sg_fd *sfp, struct sg_request *srp,
+void __user *p, struct sg_io_v4 *h4p);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_sgat(struct sg_request *srp);
@@ -318,6 +325,7 @@ static struct sg_fd *sg_add_sfp(struct sg_device *sdp, 
struct file *filp);
 static void sg_remove_sfp(struct kref *);
 static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id,
bool is_tag);
+static bool sg_mrq_get_ready_srp(struct sg_fd *sfp, struct sg_request **srpp);
 static struct sg_request *sg_add_request(struct sg_comm_wr_t *cwrp,
 enum sg_shr_var sh_var, int dxfr_len);
 static int sg_rq_map_kern(struct sg_request *srp, struct request_queue *q,
@@ -765,6 +773,8 @@ sg_v3_submit(struct sg_fd *sfp, struct sg_io_hdr *hp, bool 
sync,
struct sg_comm_wr_t cwr;
 
/* now doing v3 blocking (sync) or non-blocking submission */
+   if (hp->flags & SGV4_FLAG_MULTIPLE_REQS)
+   return -ERANGE; /* need to use v4 interface */
if (hp->flags & SG_FLAG_MMAP_IO) {
if (!list_empty(&sfp->rq_list))
return -EBUSY; 

[PATCH 06/19] sg: sense buffer cleanup

2019-05-24 Thread Douglas Gilbert
Only a smaller percentage of SCSI commands should require a sense
buffer. Allocate as needed and delete as soon as possible.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 35 ++-
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 72ce51b3198c..a58875198c16 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -852,20 +852,21 @@ sg_copy_sense(struct sg_request *srp)
(driver_byte(srp->rq_result) & DRIVER_SENSE)) {
int sb_len = min_t(int, SCSI_SENSE_BUFFERSIZE, srp->sense_len);
int mx_sb_len;
+   u8 *sbp = srp->sense_bp;
void __user *up;
 
+   srp->sense_bp = NULL;
up = (void __user *)srp->s_hdr3.sbp;
mx_sb_len = srp->s_hdr3.mx_sb_len;
-   if (up && mx_sb_len > 0 && srp->sense_bp) {
+   if (up && mx_sb_len > 0 && sbp) {
sb_len = min_t(int, sb_len, mx_sb_len);
/* Additional sense length field */
-   sb_len_wr = 8 + (int)srp->sense_bp[7];
+   sb_len_wr = 8 + (int)sbp[7];
sb_len_wr = min_t(int, sb_len, sb_len_wr);
-   if (copy_to_user(up, srp->sense_bp, sb_len_wr))
+   if (copy_to_user(up, sbp, sb_len_wr))
sb_len_wr = -EFAULT;
}
-   kfree(srp->sense_bp);
-   srp->sense_bp = NULL;
+   kfree(sbp);
}
return sb_len_wr;
 }
@@ -972,12 +973,9 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd *sfp,
h2p->driver_status = driver_byte(rq_result);
if ((CHECK_CONDITION & status_byte(rq_result)) ||
(DRIVER_SENSE & driver_byte(rq_result))) {
-   if (srp->sense_bp) {
+   if (srp->sense_bp)
memcpy(h2p->sense_buffer, srp->sense_bp,
   sizeof(h2p->sense_buffer));
-   kfree(srp->sense_bp);
-   srp->sense_bp = NULL;
-   }
}
switch (host_byte(rq_result)) {
/*
@@ -1013,17 +1011,22 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd 
*sfp,
 
/* Now copy the result back to the user buffer.  */
if (count >= SZ_SG_HEADER) {
-   if (copy_to_user(buf, h2p, SZ_SG_HEADER))
-   return -EFAULT;
+   if (copy_to_user(buf, h2p, SZ_SG_HEADER)) {
+   res = -EFAULT;
+   goto fini;
+   }
buf += SZ_SG_HEADER;
if (count > h2p->reply_len)
count = h2p->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER))
-   return -EFAULT;
+   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER)) {
+   res = -EFAULT;
+   goto fini;
+   }
}
} else
res = (h2p->result == 0) ? 0 : -EIO;
+fini:
atomic_set(&srp->rq_st, SG_RS_DONE_RD);
sg_finish_scsi_blk_rq(srp);
sg_deact_request(sfp, srp);
@@ -2991,6 +2994,7 @@ sg_deact_request(struct sg_fd *sfp, struct sg_request 
*srp)
bool on_fl = false;
int dlen, buflen;
unsigned long iflags;
+   u8 *sbp;
struct sg_request *t_srp;
struct sg_scatter_hold *schp;
const char *cp = "head";
@@ -2999,8 +3003,11 @@ sg_deact_request(struct sg_fd *sfp, struct sg_request 
*srp)
return;
schp = &srp->sgat_h;/* make sure it is own data buffer */
spin_lock_irqsave(&sfp->rq_list_lock, iflags);
+   sbp = srp->sense_bp;
+   srp->sense_bp = NULL;
atomic_set(&srp->rq_st, SG_RS_BUSY);
list_del_rcu(&srp->rq_entry);
+   kfree(sbp); /* maybe orphaned req, thus never read */
/*
 * N.B. sg_request object is not de-allocated (freed). The contents
 * of the rq_list and rq_fl lists are de-allocated (freed) when
@@ -3145,6 +3152,7 @@ sg_remove_sfp_usercontext(struct work_struct *work)
list_del(&srp->rq_entry);
if (srp->sgat_h.buflen > 0)
sg_remove_sgat(srp);
+   kfree(srp->sense_bp);   /* abnormal close: device detached */
SG_LOG(6, sdp, "%s:%s%p --\n", __func__, cp, srp);
kfree(srp);
}
@@ -3156,6 +3164,7 @@ sg_remove_sfp_usercontext(struct work_struct *work)
list_del(&srp->fl_entry);
 

[PATCH 01/19] sg: move functions around

2019-05-24 Thread Douglas Gilbert
Move code around so it has the basic ordering: open(), close(),
write(), read(), ioctl(), other system calls (e.g. mmap()),
support code and finally debug code. The change was to put the
write() associated code before the read() code. The write()
system call is associated with submitting SCSI commands (i.e.
writing metadata to the device).  The read() system call is
associated with receiving the responses of earlier submitted
commands.

Helper functions are often placed above their caller to reduce
the number of forward function declarations needed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 493 --
 1 file changed, 258 insertions(+), 235 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index bcdc28e5ede7..e20cd0d9e27b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -13,6 +13,7 @@
 
 static int sg_version_num = 30536; /* 2 digits for each component */
 #define SG_VERSION_STR "3.5.36"
+static char *sg_version_date = "20140603";
 
 /*
  *  D. P. Gilbert (dgilb...@interlog.com), notes:
@@ -47,6 +48,7 @@ static int sg_version_num = 30536;/* 2 digits for each 
component */
 #include 
 #include 
 #include  /* for sg_check_file_access() */
+#include 
 
 #include "scsi.h"
 #include 
@@ -57,12 +59,6 @@ static int sg_version_num = 30536;   /* 2 digits for each 
component */
 
 #include "scsi_logging.h"
 
-#ifdef CONFIG_SCSI_PROC_FS
-#include 
-static char *sg_version_date = "20140603";
-
-static int sg_proc_init(void);
-#endif
 
 #define SG_ALLOW_DIO_DEF 0
 
@@ -173,11 +169,11 @@ typedef struct sg_device { /* holds the state of each 
scsi generic device */
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
+/* Declarations of other static functions used before they are defined */
+static int sg_proc_init(void);
 static int sg_start_req(Sg_request *srp, unsigned char *cmd);
 static int sg_finish_rem_req(Sg_request * srp);
 static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int 
buff_size);
-static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
-  Sg_request * srp);
 static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
const char __user *buf, size_t count, int blocking,
int read_only, int sg_io_owned, Sg_request **o_srp);
@@ -190,7 +186,6 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, 
int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
 static Sg_fd *sg_add_sfp(Sg_device * sdp);
 static void sg_remove_sfp(struct kref *);
-static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static Sg_device *sg_get_dev(int dev);
@@ -232,16 +227,6 @@ static int sg_check_file_access(struct file *filp, const 
char *caller)
return 0;
 }
 
-static int sg_allow_access(struct file *filp, unsigned char *cmd)
-{
-   struct sg_fd *sfp = filp->private_data;
-
-   if (sfp->parentdp->device->type == TYPE_SCANNER)
-   return 0;
-
-   return blk_verify_command(cmd, filp->f_mode);
-}
-
 static int
 open_wait(Sg_device *sdp, int flags)
 {
@@ -405,200 +390,12 @@ sg_release(struct inode *inode, struct file *filp)
return 0;
 }
 
-static ssize_t
-sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
-   Sg_device *sdp;
-   Sg_fd *sfp;
-   Sg_request *srp;
-   int req_pack_id = -1;
-   sg_io_hdr_t *hp;
-   struct sg_header *old_hdr = NULL;
-   int retval = 0;
-
-   /*
-* This could cause a response to be stranded. Close the associated
-* file descriptor to free up any resources being held.
-*/
-   retval = sg_check_file_access(filp, __func__);
-   if (retval)
-   return retval;
-
-   if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
-   return -ENXIO;
-   SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
- "sg_read: count=%d\n", (int) count));
-
-   if (!access_ok(buf, count))
-   return -EFAULT;
-   if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
-   old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
-   if (!old_hdr)
-   return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
-   retval = -EFAULT;
-   goto free_old_hdr;
-   }
-   if (old_hdr->reply_len < 0) {
-   if (count >= SZ_SG_IO_HDR) {
-   sg_io_hdr_t *new_hdr;
-   new_hdr = kmalloc(SZ_SG_IO_HDR, GFP_KERNEL);

[PATCH 02/19] sg: remove typedefs, type+formatting cleanup

2019-05-24 Thread Douglas Gilbert
Typedefs for structure types are discouraged so those structures
that are private to the driver have had their typedefs removed.
 This also means that most "camel" type variable names (i.e. mixed
case) have been removed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 396 +-
 1 file changed, 220 insertions(+), 176 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index e20cd0d9e27b..7be3d777dbd4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3,25 +3,18 @@
  *  History:
  *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com),
  *   to allow user process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
+ *  Development Sponsored by Killy Corp. NY NY  [1992 ??]
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
  * Version 2 and 3 extensions to driver:
- *Copyright (C) 1998 - 2014 Douglas Gilbert
+ *Copyright (C) 1998 - 2019 Douglas Gilbert
  */
 
 static int sg_version_num = 30536; /* 2 digits for each component */
 #define SG_VERSION_STR "3.5.36"
 static char *sg_version_date = "20140603";
 
-/*
- *  D. P. Gilbert (dgilb...@interlog.com), notes:
- *  - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
- *the kernel/module needs to be built with CONFIG_SCSI_LOGGING
- *(otherwise the macros compile to empty statements).
- *
- */
 #include 
 
 #include 
@@ -91,33 +84,32 @@ static int sg_add_device(struct device *, struct 
class_interface *);
 static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
-static DEFINE_RWLOCK(sg_index_lock);   /* Also used to lock
-  file descriptor list 
for device */
+static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock fd list for device */
 
 static struct class_interface sg_interface = {
.add_dev= sg_add_device,
.remove_dev = sg_remove_device,
 };
 
-typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info 
*/
-   unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
-   unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */
-   unsigned bufflen;   /* Size of (aggregate) data buffer */
+struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+   u16 k_use_sg; /* Count of kernel scatter-gather pieces */
+   unsigned int sglist_len; /* size of malloc'd scatter-gather list ++ */
+   unsigned int bufflen;   /* Size of (aggregate) data buffer */
struct page **pages;
int page_order;
char dio_in_use;/* 0->indirect IO (or mmap), 1->dio */
-   unsigned char cmd_opcode; /* first byte of command */
-} Sg_scatter_hold;
+   u8 cmd_opcode;  /* first byte of command */
+};
 
 struct sg_device;  /* forward declarations */
 struct sg_fd;
 
-typedef struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
+struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
struct list_head entry; /* list entry */
struct sg_fd *parentfp; /* NULL -> not in use */
-   Sg_scatter_hold data;   /* hold buffer, perhaps scatter list */
+   struct sg_scatter_hold data;/* hold buffer, perhaps scatter list */
sg_io_hdr_t header; /* scsi command+info, see  */
-   unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
+   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
char res_used;  /* 1 -> using reserve buffer, 0 -> not ... */
char orphan;/* 1 -> drop on sight, 0 -> normal */
char sg_io_owned;   /* 1 -> packet belongs to SG_IO */
@@ -126,9 +118,9 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests 
outstanding per file */
struct request *rq;
struct bio *bio;
struct execute_work ew;
-} Sg_request;
+};
 
-typedef struct sg_fd { /* holds the state of a file descriptor */
+struct sg_fd { /* holds the state of a file descriptor */
struct list_head sfd_siblings;  /* protected by device's sfd_lock */
struct sg_device *parentdp; /* owning device */
wait_queue_head_t read_wait;/* queue read until command done */
@@ -136,21 +128,21 @@ typedef 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 */
-   Sg_scatter_hold reserve;/* buffer held for this file descriptor 
*/
+   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

[PATCH 13/19] sg: sgat_elem_sz and sum_fd_dlens

2019-05-24 Thread Douglas Gilbert
Wire up some more capabilities of ioctl(SG_SET_GET_EXTENDED). One
is the size of each internal scatter gather list element. This
defaults to 2^15 and was fixed in previous versions of this
driver. If the user provides a value, it must be a power of
2 (bytes) and no less than PAGE_SIZE.

sum_fd_dlens provides user control over a mechanism designed to
stop the starvation of the host machine's memory. Since requests
per file descriptor are no longer limited to 16, thousands could
be queued up by a badly designed program. If each one requests
a large buffer (say 128 KB each for READs) then without this
mechanism, the OOM killer may be called on to save the machine.
The driver counts the cumulative size of data buffers
outstanding held by each file descriptor. Once that figure
exceeds a default size of 16 MB, further submissions on that
file descriptor are failed with E2BIG.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 64 +++---
 include/uapi/scsi/sg.h |  1 +
 2 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index c014fb24eca1..64e9de67ccd4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -88,7 +88,11 @@ enum sg_rq_state {
SG_RS_BUSY, /* temporary state should rarely be seen */
 };
 
+/* If sum_of(dlen) of a fd exceeds this, write() will yield E2BIG */
+#define SG_TOT_FD_THRESHOLD (32 * 1024 * 1024)
+
 #define SG_TIME_UNIT_MS 0  /* milliseconds */
+/* #define SG_TIME_UNIT_NS 1  nanoseconds */
 #define SG_DEF_TIME_UNIT SG_TIME_UNIT_MS
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
 #define SG_FD_Q_AT_HEAD 0
@@ -223,7 +227,9 @@ struct sg_fd {  /* holds the state of a file 
descriptor */
struct list_head rq_fl; /* head of sg_request free list */
int timeout;/* defaults to SG_DEFAULT_TIMEOUT  */
int timeout_user;   /* defaults to SG_DEFAULT_TIMEOUT_USER */
+   int tot_fd_thresh;  /* E2BIG if sum_of(dlen) > this, 0: ignore */
int sgat_elem_sz;   /* initialized to scatter_elem_sz */
+   atomic_t sum_fd_dlens;  /* when tot_fd_thresh>0 this is sum_of(dlen) */
atomic_t submitted; /* number inflight or awaiting read */
atomic_t waiting;   /* number of requests awaiting read */
unsigned long ffd_bm[1];/* see SG_FFD_* defines above */
@@ -1939,8 +1945,8 @@ sg_ctl_extended(struct sg_fd *sfp, void __user *p)
 {
int result = 0;
int ret = 0;
-   int s_wr_mask, s_rd_mask;
-   u32 or_masks;
+   int n, j, s_wr_mask, s_rd_mask;
+   u32 uv, or_masks;
struct sg_device *sdp = sfp->parentdp;
struct sg_extended_info *seip;
struct sg_extended_info sei;
@@ -1957,6 +1963,17 @@ sg_ctl_extended(struct sg_fd *sfp, void __user *p)
}
SG_LOG(3, sdp, "%s: wr_mask=0x%x rd_mask=0x%x\n", __func__, s_wr_mask,
   s_rd_mask);
+   /* tot_fd_thresh (u32), [raw] [sum of active cmd dlen_s] */
+   if (or_masks & SG_SEIM_TOT_FD_THRESH) {
+   if (s_wr_mask & SG_SEIM_TOT_FD_THRESH) {
+   uv = seip->tot_fd_thresh;
+   if (uv > 0 && uv < PAGE_SIZE)
+   uv = PAGE_SIZE;
+   sfp->tot_fd_thresh = uv;
+   }
+   if (s_rd_mask & SG_SEIM_TOT_FD_THRESH)
+   seip->tot_fd_thresh = sfp->tot_fd_thresh;
+   }
/* check all boolean flags for either wr or rd mask set in or_mask */
if (or_masks & SG_SEIM_CTL_FLAGS)
sg_extended_bool_flags(sfp, seip);
@@ -1971,6 +1988,23 @@ sg_ctl_extended(struct sg_fd *sfp, void __user *p)
}
if ((s_rd_mask & SG_SEIM_READ_VAL) && (s_wr_mask & SG_SEIM_READ_VAL))
sg_extended_read_value(sfp, seip);
+   /* override scatter gather element size [rbw] (def: SG_SCATTER_SZ) */
+   if (or_masks & SG_SEIM_SGAT_ELEM_SZ) {
+   n = sfp->sgat_elem_sz;
+   if (s_wr_mask & SG_SEIM_SGAT_ELEM_SZ) {
+   j = (int)seip->sgat_elem_sz;
+   if (j != (1 << ilog2(j)) || j < (int)PAGE_SIZE) {
+   SG_LOG(1, sdp, "%s: %s not power of 2, %s\n",
+  __func__, "sgat element size",
+  "or less than PAGE_SIZE");
+   ret = -EINVAL;
+   } else {
+   sfp->sgat_elem_sz = j;
+   }
+   }
+   if (s_rd_mask & SG_SEIM_SGAT_ELEM_SZ)
+   seip->sgat_elem_sz = n; /* prior value if rw */
+   }
/* reserved_sz [raw], since may be reduced by ot

[PATCH 00/19] sg: v4 interface, rq sharing + multiple rqs

2019-05-24 Thread Douglas Gilbert
This patchset extends the SCSI generic (sg) driver found in lk 5.2 .
The sg driver has a version number which is visible via an ioctl()
and is bumped from 3.5.36 to 4.0.12 by this patchset.
The additions and changes are described in some detail on this
long webpage:
http://sg.danny.cz/sg/sg_v40.html
and references are made in various patches to relevant sections in
that document.

This patchset restores some functionality that was in the v2 driver
version and has been broken by some external patch in the interim
period (20 years). That functionality (NO_DXFER) has found new
uses in request sharing. Also functionality that has been dropped
from the bsg driver over the last year is added to this driver in
this patchset (e.g. async/non-blocking v4 interface usage, and
multiple request support).

This patchset is big and can be regarded as a driver rewrite. The
number of lines increases from around 3000 to over 6000. The size
of the module doubles although that can be reduced by turning off
SCSI logging.

TODO: during development, this driver had its own version of
  tracing which has been removed from the final patchset.
  Curiously that tracing code was never used in anger for
  its intended purpose, but the revamped SG_LOG macro was
  used a lot.
  The intention is to add tracing via the 'standard' kernel
  code. The addition is somewhat invasive, both to the sg
  driver (e.g. some otherwise private structures need to
  be made public) and to the tracing subsystem.

Testing:
The sg3_utils package has several extensions in sg3_utils-1.45
beta (revision 824) to support and test the version 4 sg
driver presented in this patchset.
The new and revised testing utilities are outlined on the
same webpage as above in the second half of the section
titled: "15 Downloads and testing".

This patchset is against Martin Petersen's 5.3/scsi-queue
branch. It will also apply to lk 5.1 and probably lk 5.0 .

Douglas Gilbert (19):
  sg: move functions around
  sg: remove typedefs, type+formatting cleanup
  sg: sg_log and is_enabled
  sg: move header to uapi section
  sg: replace rq array with lists
  sg: sense buffer cleanup
  sg: add sg v4 interface support
  sg: add 8 byte SCSI LUN to sg_scsi_id
  sg: expand sg_comm_wr_t
  sg: add sg_ioabort ioctl
  sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls
  sg: add sg_set_get_extended ioctl
  sg: sgat_elem_sz and sum_fd_dlens
  sg: tag and more_async
  sg: add fd sharing , change, unshare
  sg: add shared requests
  sg: add multiple request support
  sg: add slave wait capability
  sg: table of error numbers with meanings

 drivers/scsi/sg.c  | 6790 ++--
 include/scsi/sg.h  |  268 +-
 include/uapi/scsi/sg.h |  475 +++
 3 files changed, 5682 insertions(+), 1851 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

-- 
2.17.1



[PATCH 18/19] sg: add slave wait capability

2019-05-24 Thread Douglas Gilbert
In request sharing, the slave side (i.e. the WRITEr) usually needs
to wait for the master side to complete before the slave can
issue its WRITE (or any other data-out command). This small
optimisation allows the slave WRITE to be submitted directly after
the master side submits its command (e.g. a READ).

Of course that slave command can't be executed until the data from
the master command becomes available. However the slave command
(i.e. its cdb) can be fetched and checked and the resources it
needs can be obtained. Also when the master side completes,
its callback can kick off the slave command prior to returning
to the user space with the response. No context switches
(between the user and kernel space) are saved, but the slave
request and the master response context switches are no longer
necessarily holding up IO.

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
in the section titled: "7.1 Slave waiting"

This patch adds 120 lines and an extra state in the sg_request's
state machine. It may cost more than it is worth and so has been
added (almost) last.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 147 ++---
 include/uapi/scsi/sg.h |  24 ---
 2 files changed, 154 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 92a0226cabc2..d048c1f371ce 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -12,9 +12,9 @@
  *
  */
 
-static int sg_version_num = 40001; /* 2 digits for each component */
-#define SG_VERSION_STR "4.0.01"
-static char *sg_version_date = "20190520";
+static int sg_version_num = 40012; /* 2 digits for each component */
+#define SG_VERSION_STR "4.0.12"
+static char *sg_version_date = "20190521";
 
 #include 
 
@@ -92,6 +92,7 @@ enum sg_rq_state {
SG_RS_BUSY, /* temporary state should rarely be seen */
SG_RS_SHR_SWAP, /* swap: master finished, awaiting slave */
SG_RS_SHR_SLAVE,/* master waits while slave inflight */
+   SG_RS_SHR_SWAIT,/* slave waiting for master to complete */
 };
 
 /* slave sets up sharing: ioctl(sl_fd,SG_SET_GET_EXTENDED(SHARE_FD(ma_fd))) */
@@ -132,6 +133,7 @@ enum sg_shr_var {
 #define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
 #define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
 #define SG_FRQ_ABORTING5   /* in process of aborting this 
cmd */
+#define SG_FRQ_DEFER_XFR   6   /* slave waiting will defer transfer */
 #define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
 #define SG_FRQ_MULTI_REQ   8   /* part of a multiple request series */
 #define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
@@ -1386,6 +1388,18 @@ sg_execute_cmd(struct sg_fd *sfp, struct sg_request *srp)
unsigned long iflags;
struct sg_device *sdp = sfp->parentdp;
 
+   if (unlikely(srp->sh_var == SG_SHR_SL_RQ && sfp->share_sfp)) {
+   if (test_and_clear_bit(SG_FRQ_DEFER_XFR, srp->frq_bm)) {
+   int res = sg_rq_map_kern(srp,
+sdp->device->request_queue,
+srp->rq);
+
+   SG_LOG(3, sdp, "%s: deferred xfer\n", __func__);
+   if (unlikely(res))
+   pr_warn("%s: sg_rq_map_kern() --> %d\n",
+   __func__, res);
+   }
+   }
is_v4h = test_bit(SG_FRQ_IS_V4I, srp->frq_bm);
sync = SG_IS_SYNC_INVOC(srp);
SG_LOG(3, sdp, "%s: is_v4h=%d\n", __func__, (int)is_v4h);
@@ -1438,6 +1452,56 @@ sg_rstate_chg(struct sg_request *srp, enum sg_rq_state 
old_st,
return -EPROTOTYPE;
 }
 
+/*
+ * Here when share slave request is being built and SG_FRQ_DEFER_XFR is set.
+ * Returns 0 for SWAIT (i.e. deferred execution), SZ_SG_IO_V4 (positive) for
+ * execute now, and negated errno value for error.
+ */
+static int
+sg_process_swait(struct sg_fd *sl_sfp, struct sg_request *sl_srp)
+{
+   int res = 0;
+   unsigned long iflags;
+   enum sg_rq_state ma_sr_st;
+   struct sg_fd *ma_sfp = sl_sfp->share_sfp;
+   struct sg_request *ma_rsv_srp;
+
+   if (!ma_sfp || !ma_sfp->rsv_srp)
+   return -EPROTO;
+   ma_rsv_srp = ma_sfp->rsv_srp;
+   spin_lock_irqsave(&ma_rsv_srp->req_lck, iflags);
+   ma_sr_st = atomic_read(&ma_rsv_srp->rq_st);
+   SG_LOG(3, sl_sfp->parentdp, "%s: ma_rsv_srp=0x%p, ma_sr_st: %s\n",
+  __func__, ma_rsv_srp, sg_rq_st_str(ma_sr_st, false));
+
+   switch (ma_sr_st) { /* master's state held constant by spinlock */
+   case SG_RS_INFLIGHT:
+   res = sg_r

[PATCH 16/19] sg: add shared requests

2019-05-24 Thread Douglas Gilbert
Add request sharing which is invoked on a shared file
descriptor by using SGV4_FLAG_SHARE. The file share is
asymmetric: the master side is assumed to do data-in
command (e.g. READ) first, followed by the slave side
doing a data-out command (e.g. WRITE). The master side
may also set SG_FLAG_NO_DXFER and the slave side must
set that flag. If both sides set that flag then a
single bio is used and the user space doesn't "see"
the data. If the master side does not set
SG_FLAG_NO_DXFER then the read data is copied to the
user space. And that copy to user space can displaced
by using SG_FLAG_MMAP_IO (but that adds some other
overheads).

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
in the section titled: "7 Request sharing".

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 812 +++--
 include/uapi/scsi/sg.h |   8 +
 2 files changed, 705 insertions(+), 115 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 44f09c65e0b9..9adca3988c58 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -89,6 +89,17 @@ enum sg_rq_state {
SG_RS_AWAIT_RD, /* response received, awaiting read */
SG_RS_DONE_RD,  /* read is ongoing or done */
SG_RS_BUSY, /* temporary state should rarely be seen */
+   SG_RS_SHR_SWAP, /* swap: master finished, awaiting slave */
+   SG_RS_SHR_SLAVE,/* master waits while slave inflight */
+};
+
+/* slave sets up sharing: ioctl(sl_fd,SG_SET_GET_EXTENDED(SHARE_FD(ma_fd))) */
+enum sg_shr_var {
+   SG_SHR_NONE = 0,/* no sharing on owning fd */
+   SG_SHR_MA_FD_NOT_RQ,/* master sharing on fd but not this req */
+   SG_SHR_MA_RQ,   /* master sharing on this req */
+   SG_SHR_SL_FD_NOT_RQ,/* slave sharing on fd but not this req */
+   SG_SHR_SL_RQ,   /* slave sharing on this req */
 };
 
 /* If sum_of(dlen) of a fd exceeds this, write() will yield E2BIG */
@@ -130,6 +141,7 @@ enum sg_rq_state {
 #define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
 #define SG_FFD_TIME_IN_NS  4   /* set: time in nanoseconds, else ms */
 #define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
+#define SG_FFD_MASTER_ERR  6   /* master side of share had error */
 #define SG_FFD_PREFER_TAG  7   /* prefer tag over pack_id (def) */
 #define SG_FFD_RELEASE 8   /* release (close) underway */
 #define SG_FFD_NO_DURATION 9   /* don't do command duration calc */
@@ -202,6 +214,7 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
struct list_head fl_entry;  /* member of rq_fl */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
+   struct sg_scatter_hold *sgatp;  /* ptr to prev unless slave shr req */
union {
struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
struct sg_slice_hdr4 s_hdr4; /* reduced size struct sg_io_v4 */
@@ -214,6 +227,7 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
int pack_id;/* v3 pack_id or in v4 request_extra field */
int sense_len;  /* actual sense buffer length (data-in) */
atomic_t rq_st; /* request state, holds a enum sg_rq_state */
+   enum sg_shr_var sh_var; /* sharing variety, SG_SHR_NONE=0 if none */
u8 cmd_opcode;  /* first byte of SCSI cdb */
int tag;/* block layer identifier of request */
u64 start_ns;   /* starting point of command duration calc */
@@ -246,6 +260,7 @@ struct sg_fd {  /* holds the state of a file 
descriptor */
u8 next_cmd_len;/* 0: automatic, >0: use on next write() */
struct file *filp;  /* my identity when sharing */
struct sg_request *rsv_srp;/* one reserve request per fd */
+   struct sg_request *slave_srp;   /* non-NULL when rsv SG_SHR_MA_RQ */
struct sg_fd *share_sfp;/* master+slave shares set this, else NULL */
struct fasync_struct *async_qp; /* used by asynchronous notification */
struct kref f_ref;
@@ -304,7 +319,9 @@ static void sg_remove_sfp(struct kref *);
 static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id,
bool is_tag);
 static struct sg_request *sg_add_request(struct sg_comm_wr_t *cwrp,
-int dxfr_len);
+enum sg_shr_var sh_var, int dxfr_len);
+static int sg_rq_map_kern(struct sg_request *srp, struct request_queue *q,
+ struct request *rq);
 static void sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
 static struct sg_device *sg_get_dev(int min_dev);
 static void sg_device_destroy(struct kref *kref);
@@ -312,6 +

[PATCH 07/19] sg: add sg v4 interface support

2019-05-24 Thread Douglas Gilbert
Add support for the sg v4 interface based on struct sg_io_v4 found
in include/uapi/linux/bsg.h and only previously supported by the
bsg driver. Add ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async (non-blocking) usage of the sg v4 interface. Do not accept
the v3 interface with these ioctls. Do not accept the v4
interface with this driver's existing write() and read()
system calls.

For sync (blocking) usage expand the existing ioctl(SG_IO)
to additionally accept the sg v4 interface object.

A later patch in this set adds multiple requests in a single
invocation. Multiple requests use sg v4 interface objects
exclusively.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 503 -
 include/uapi/scsi/sg.h |  37 ++-
 2 files changed, 429 insertions(+), 111 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a58875198c16..3b78b8c8304b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -7,8 +7,9 @@
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
+ * Version 2, 3 and 4 extensions to driver:
  *Copyright (C) 1998 - 2019 Douglas Gilbert
+ *
  */
 
 static int sg_version_num = 30536; /* 2 digits for each component */
@@ -40,10 +41,12 @@ static char *sg_version_date = "20140603";
 #include 
 #include 
 #include 
-#include  /* for sg_check_file_access() */
+#include /* for sg_check_file_access() */
+#include 
 #include 
 
-#include "scsi.h"
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -103,6 +106,7 @@ enum sg_rq_state {
 #define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
 
 /* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_V4I  0   /* true (set) when is v4 interface */
 #define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
 #define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
 #define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
@@ -159,6 +163,15 @@ struct sg_slice_hdr3 {
void __user *usr_ptr;
 };
 
+struct sg_slice_hdr4 { /* parts of sg_io_v4 object needed in async usage */
+   void __user *sbp;   /* derived from sg_io_v4::response */
+   u64 usr_ptr;/* hold sg_io_v4::usr_ptr as given (u64) */
+   int out_resid;
+   s16 dir;/* data xfer direction; SG_DXFER_*  */
+   u16 cmd_len;/* truncated of sg_io_v4::request_len */
+   u16 max_sb_len; /* truncated of sg_io_v4::max_response_len */
+};
+
 struct sg_scatter_hold { /* holding area for scsi scatter gather info */
struct page **pages;/* num_sgat element array of struct page* */
int buflen; /* capacity in bytes (dlen<=buflen) */
@@ -175,7 +188,10 @@ struct sg_request {/* active SCSI command or 
inactive on free list (fl) */
struct list_head fl_entry;  /* member of rq_fl */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
-   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   union {
+   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   struct sg_slice_hdr4 s_hdr4; /* reduced size struct sg_io_v4 */
+   };
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -237,7 +253,10 @@ struct sg_device { /* holds the state of each scsi generic 
device */
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
-   struct sg_io_hdr *h3p;
+   union { /* selector is frq_bm.SG_FRQ_IS_V4I */
+   struct sg_io_hdr *h3p;
+   struct sg_io_v4 *h4p;
+   };
u8 *cmnd;
 };
 
@@ -246,13 +265,13 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   int dxfer_dir);
+   struct sg_io_v4 *h4p, int dxfer_dir);
 // static int sg_finish_rem_req(struct sg_request *srp);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
-static int sg_submit(struct file *filp, struct sg_fd *sfp,
-struct sg_io_hdr *hp, bool sync,
-struct sg_request **o_srp);
+static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
+   struct sg_io_hdr *hp, bool sync,
+   struct sg_request **o_srp);
 static struct sg_request 

[PATCH 08/19] sg: add 8 byte SCSI LUN to sg_scsi_id

2019-05-24 Thread Douglas Gilbert
The existing ioctl(SG_GET_SCSI_ID) fills a object of type
struct sg_scsi_id whose last field is int unused[2]. Add
an anonymous union with u8 scsi_lun[8] sharing those last
8 bytes. This patch will place the current device's full
LUN in the scsi_lun array using T10's preferred LUN
format (i.e. an array of 8 bytes) when
ioctl(SG_GET_SCSI_ID) is called.

Note that structure already contains a 'lun' field but that
is a 32 bit integer. Users of this upgrade should choose
the scsi_lun array field henceforth but existing code
should do the same as it does with the version 3 driver.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 5 +++--
 include/uapi/scsi/sg.h | 5 -
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 3b78b8c8304b..454abfdd4f74 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1694,6 +1694,7 @@ static int
 sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_device *sdp, void __user *p)
 {
struct sg_scsi_id __user *sg_idp = p;
+   struct scsi_lun lun8b;
 
SG_LOG(3, sdp, "%s:SG_GET_SCSI_ID\n", __func__);
if (!access_ok(p, sizeof(struct sg_scsi_id)))
@@ -1711,8 +1712,8 @@ sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_device 
*sdp, void __user *p)
   &sg_idp->h_cmd_per_lun);
__put_user((short)sdev->queue_depth,
   &sg_idp->d_queue_depth);
-   __put_user(0, &sg_idp->unused[0]);
-   __put_user(0, &sg_idp->unused[1]);
+   int_to_scsilun(sdev->lun, &lun8b);
+   __copy_to_user(sg_idp->scsi_lun, lun8b.scsi_lun, 8);
return 0;
 }
 
diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h
index 7557c1be01e0..db86d1ae7e29 100644
--- a/include/uapi/scsi/sg.h
+++ b/include/uapi/scsi/sg.h
@@ -135,7 +135,10 @@ typedef struct sg_scsi_id {
int scsi_type;  /* TYPE_... defined in scsi/scsi.h */
short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
short d_queue_depth;/* device (or adapter) maximum queue length */
-   int unused[2];
+   union {
+   int unused[2];  /* as per version 3 driver */
+   __u8 scsi_lun[8];  /* full 8 byte SCSI LUN [in v4 driver] */
+   };
 } sg_scsi_id_t;
 
 /* For backward compatibility v4 driver yields at most SG_MAX_QUEUE of these */
-- 
2.17.1



[PATCH 19/19] sg: table of error numbers with meanings

2019-05-24 Thread Douglas Gilbert
Rather than having a piece of paper recording which errno
values have been used for what, the author thought why not
place then in one table in the driver code.

As a guesstimate, over half the code in this driver is dedicated
to sanity checking and reporting errors. Those errors may come
from the host machine, the SCSI HBA or its associated hardware,
or the transport or the storage device. For near end errors
some creative license is taken with errno values (e.g.
ENOTSOCK) to convey a better sense of what this driver is
objecting to.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d048c1f371ce..4fee90cca852 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -389,6 +389,48 @@ static void sg_rep_rq_state_fail(struct sg_device *sdp,
 #define SG_LOG(depth, sdp, fmt, a...)
 #endif /* end of CONFIG_SCSI_LOGGING && SG_DEBUG conditional */
 
+/*
+ * Unless otherwise noted, functions that return int will return 0 for
+ * good/successful or a negated errno value. Here is list of errno_s generated
+ * by this driver:
+ *
+ * E2BIGsum(dlen) > tot_fd_thresh ; slave dxfer_len > master dxfer_len
+ * EACCES   user (process) does not have sufficient privilege or capabilities
+ * EADDRINUSE  sharing: slave file descriptor already in share
+ * EADDRNOTAVAIL   sharing: master file descriptor already in share
+ *slave request but no preceding master request
+ * EAGAIN   [aka EWOULDBLOCK]; occurs when O_NONBLOCK set on open() or
+ * SGV4_FLAG_IMMED given, and SG_IORECEIVE (or read(2)) not ready
+ * EBUSY'Device or resource busy'; this uses open(O_NONBLOCK) but another
+ * has open(O_EXCL); reserve request in use (e.g. when mmap() called)
+ * EDOM numerical error, command queueing false and second command
+ * attempted when one already outstanding
+ * EFAULT   problem moving data to or from user space
+ * EIDRMblock request unexpectedly missing
+ * EINTRinterrupted system call (generated by kernel, not this driver)
+ * EINVAL   flags or other input information contradicts or disallowed
+ * EIO  only kept for backward compatibility, too generic to be useful
+ * ELOOPsharing: file descriptor can't share with itself
+ * EMSGSIZEcdb too long (> 252 bytes) or too short (less than 6 bytes)
+ * ENODATA  sharing: no data xfer requested; mmap or direct io problem
+ *  SG_IOABORT: no match on pack_id or tag; mrq: no active reqs
+ * ENODEV   target (SCSI) device associated with the fd has "disappeared"
+ * ENOMEM   obvious; could be some pre-allocated cache that is full
+ * ENOMSG   data transfer setup needed or (direction) disallowed (sharing)
+ * ENOSTR   slave request abandoned due to master error or state
+ * ENOTSOCK   sharing: file descriptor for sharing unassociated with sg driver
+ * ENXIO'no such device or address' SCSI mid-level processing errors
+ *  (e.g. command timeouts); also sg info not in 'file' struct
+ * EPERMnot permitted (even if has ACCES); v1+2,v3,v4 interface usage
+ * violation, opened read-only but SCSI command not listed read-only
+ * EPROTO   logic error (in driver); like "shouldn't get here"
+ * EPROTOTYPEatomic state change failed unexpectedly
+ * ERANGE   multiple requests: usually bad flag values
+ * ERESTARTSYS   should not be seen in user space, associated with an
+ *  interruptable wait; will restart system call or give EINTR
+ * EWOULDBLOCK   [aka EAGAIN]; additionally if the 'more async' flag is set
+ *  SG_IOSUBMIT may yield this error
+ */
 
 /*
  * The SCSI interfaces that use read() and write() as an asynchronous variant 
of
-- 
2.17.1



Re: [PATCH 05/19] sg: replace rq array with lists

2019-05-25 Thread Douglas Gilbert

On 2019-05-25 5:33 a.m., kbuild test robot wrote:

Hi Douglas,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on next-20190524]
[cannot apply to v5.2-rc1]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Douglas-Gilbert/sg-v4-interface-rq-sharing-multiple-rqs/20190525-161346
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: powerpc-allyesconfig (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 7.4.0
reproduce:
 wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
 chmod +x ~/bin/make.cross
 # save the attached .config to linux build tree
 GCC_VERSION=7.4.0 make.cross ARCH=powerpc

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot 

All warnings (new ones prefixed by >>):

drivers/scsi/sg.c: In function 'sg_ioctl':

drivers/scsi/sg.c:1698:1: warning: the frame size of 5824 bytes is larger than 
2048 bytes [-Wframe-larger-than=]

 }
 ^


Hi Robot,
That seems a surprisingly large stack size for that architecture. When
I do:
  make checkstack drivers/scsi/sg.o

there are over 200 other "stack hogs" larger than sg_ioctl() which clocks
in at 536 bytes ***. The is on x86_64 (i5-7200U) architecture. Even the
winners on my list are comfortably under 2048 bytes:

0x81052c11 sha1_transform_avx2 [vmlinux]:   1376
0x81054a83 _end [vmlinux]:  1376
0x0dd1 test_queue [usbtest]:1224
0x1321 test_queue [usbtest]:1224
0xaa79 ipmi_panic_request_and_wait [ipmi_msghandler]:1088
0x8121378f do_sys_poll [vmlinux]:   992
0x81213ca8 do_sys_poll [vmlinux]:   992


I could trim some more bytes (e.g. the SG_LOG() macro does a stack allocation
of 160 bytes, probably 100 would be enough) but that won't bring the
reported 5824 byte stack usage anywhere near the safe range.

Doug Gilbert

*** and sg_ioctl() is the biggest sg driver stack hog on my list, followed
by sg_read at 368 bytes.


Re: [PATCH 00/19] sg: v4 interface, rq sharing + multiple rqs

2019-06-02 Thread Douglas Gilbert

On 2019-05-26 11:49 a.m., Bart Van Assche wrote:

On 5/24/19 11:47 AM, Douglas Gilbert wrote:

This patchset restores some functionality that was in the v2 driver
version and has been broken by some external patch in the interim
period (20 years).


What is an "external patch"?


It's a patch made by someone with a first name like Christoph, Jens or
James (picking some names at random) that is applied whether or not
the maintainer of said driver approves ("ack's) or not.

IMO The maintainer should be able to restore features removed in this
fashion (I'm talking specifically about the neutering of
SG_FLAG_NO_DXFER) without review as it is in the documented interface.
Plus I know of at least one power user who was peeved to find out that
it was quietly broken.

Doug Gilbert


P.S the use case is mirrored disks: reading one disk for the actual data,
and the other disk to check if there is an IO error. So the second disk
doesn't need its data transferred to the user space (thus saving time).



Re: [PATCH 01/19] sg: move functions around

2019-06-03 Thread Douglas Gilbert

On 2019-05-26 11:46 a.m., Bart Van Assche wrote:

On 5/24/19 11:47 AM, Douglas Gilbert wrote:

Move code around so it has the basic ordering: open(), close(),
write(), read(), ioctl(), other system calls (e.g. mmap()),
support code and finally debug code. The change was to put the
write() associated code before the read() code. The write()
system call is associated with submitting SCSI commands (i.e.
writing metadata to the device).  The read() system call is
associated with receiving the responses of earlier submitted
commands.

Helper functions are often placed above their caller to reduce
the number of forward function declarations needed.


Moving helper functions in front of their caller is useful but random
reordering of functions not. Such a random reordering of code pollutes
the git history. Please don't do that.


Another reviewer accepted that open,close,submit,receive was a more
logical order than what was there previously. He suggested containing
the moves in a single patch within the patchset. It seemed best to
do that first, hence this patch (i.e. 1/19).

Over time, patches by others have blurred what started as a
coherent ordering of functions, IMO. There needs to be a way to
re-mediate that. git could have better ways of notating that
a function has moved within a source file, or to another file.
There is a drastic alternative: two patches, one to remove the
driver, another to add the rewrite.


Please rephrase artless expressions like:
  - "What makes you think that ...", (in another post) and
  - "random reordering of code pollutes"

and use more professional language. Thanks.

Douglas Gilbert


Re: [PATCH 00/19] sg: v4 interface, rq sharing + multiple rqs

2019-06-04 Thread Douglas Gilbert

On 2019-06-03 12:19 p.m., Bart Van Assche wrote:

On 5/24/19 11:47 AM, Douglas Gilbert wrote:

This patchset is big and can be regarded as a driver rewrite. The
number of lines increases from around 3000 to over 6000.


Every SCSI reviewer I know is too busy to review a patch series that involves so 
many changes. You may have to split this series into a number of smaller series 
if you want to encourage reviewers to have a look.


Cutting a patchset that touches around 1500 lines of a 3000 line
driver, then adds new functionality amounting to an extra 3000
lines of code (and comments), according to the "one change per
patch" rule would result in a patchset with hundreds of patches.

Further if they are to be bisectable then they must not only
compile and build, but run properly. Of course that is impossible
for new functionality as there is little to test the new
functionality against. Then there is the case of a driver maintainer
who wants to clean up code that has "rusted" over time, including
being weakened by hundreds of well-meaning but silly janitor type
patches. Should a maintainer be discouraged from doing that?

Looking around at current patchsets, LWN keeps a helpful list at
the bottom of this page (from last Thursday):
https://lwn.net/Articles/789234/
[non-subscribers need to wait until next Thursday to view that].
I looked at the "Device Drivers" section. Most patchsets there
had between 10 and 20 patches, one had 33. One, the SIW Infiniband
driver, is over 10,000 lines long, and contains 'only' 12 patches.
Reviewers are obviously a scarce resource, but making their live's
easier shouldn't be a goal in itself.


Further, the utility of bottom up reviews by humans reduces with
time as the automatic tools to do that get better. Of the responses
to my "version 1" patchset 10 days ago, I would regard only one of
your responses "useful", and all but one of the kbuild robot's
responses useful. By "useful" I mean that they lead to better code.

If new functionality is being proposed, surely it is better to
check that it is documented and that test code exists. Then the
design and high level details of the implementation should be
assessed. And if the code doesn't involve special hardware,
shouldn't the test code be run as part of the review process?
Code reviews have their place, but over the last 10 years, bugs in
the sg and scsi_debug drivers have been found by _using_ those
drivers. Also with those drivers I and others have found bugs in
the block layer and the SCSI mid-level. To date I have had no
feedback about design document describing this patchset:
http://sg.danny.cz/sg/sg_v40.html
even though I refer to sections of it in about half of the patches
in this patchset. Plus I have written extensive test code and made
it available; again no feedback on that.

In the article: "A ring buffer for epoll":
   https://lwn.net/Articles/789603/[May 30, 2019]
Jonathan Corbet discusses these issues in the final section
titled: "Some closing grumbles".

Doug Gilbert




Re: [PATCH 00/19] sg: v4 interface, rq sharing + multiple rqs

2019-06-06 Thread Douglas Gilbert

On 2019-06-06 10:34 a.m., Martin K. Petersen wrote:


Doug,


Cutting a patchset that touches around 1500 lines of a 3000 line
driver, then adds new functionality amounting to an extra 3000 lines
of code (and comments), according to the "one change per patch" rule
would result in a patchset with hundreds of patches.


The problem here is that you think of it as a single patch set
transitioning the driver from major version X to version Y.

Linux kernel development has moved away from that model. The kernel
release cadence is more or less fixed at 10 weeks. The release process
is not controlled by features or component versions or anything of that
nature. It is set by passing of time.

The notion that a driver or kernel component may have a version number
applied to it is orthogonal to that process. A version is something you
as a driver maintainer may decide to use to describe a certain set of
commits. But it has no meaning wrt. the Linux development process.

If you want to transition sg from what you call v3 to v4, then the
process is that you submit a handful or two of small, easily digestible
patches at a time.

It may take a few kernel releases to get to where you want to be. But
that is the process that everybody else is following to get their
changes merged.

Nobody says you can only make one submission per submission window. It's
perfectly fine to submit patches 11-20 as soon as patches 1-10 have been
reviewed and merged. As an example of this, the HBA vendors usually send
several driver updates each release cycle.


Further if they are to be bisectable then they must not only
compile and build, but run properly.


Absolutely. That's a requirement.


Of course that is impossible for new functionality as there is little
to test the new functionality against.


The burden is on you to submit patches in an order in which they make
logical sense and in which they can be reviewed, bisected, and tested.


I looked at the "Device Drivers" section. Most patchsets there
had between 10 and 20 patches, one had 33.


The "number of patches in a driver submission" as a measure is a red
herring. sg is not a new driver, it has users.


One, the SIW Infiniband driver, is over 10,000 lines long, and
contains 'only' 12 patches.


But it was presumably developed out of tree in a separate repo. And the
thousands of commits that resulted in this driver have been collapsed
into 12 patches for initial submission.

The number of lines is also a red herring. If a patch changes 10,000
lines to make one logical change that's perfectly fine. What's not fine
is a patch changing 10,000 lines and also making an entirely different
logical change.


Reviewers are obviously a scarce resource, but making their live's
easier shouldn't be a goal in itself.


Couldn't disagree more. If you want your code merged, you will have to
present it in a way that caters to the reviewers. Because without
reviews, your code won't get merged.


If new functionality is being proposed, surely it is better to check
that it is documented and that test code exists. Then the design and
high level details of the implementation should be assessed.


Testing and documentation are absolutely important. But so is
documenting what compelled a code change.

Reviews aid in verifying that the thought process outlined in the patch
description matches the code changes performed. This is where the whole
"one logical change" comes from. And when things subsequently break, it
is then easy to identify which assumptions the patch author made that
turned out not to be valid.


To date I have had no feedback about design document describing this
patchset: http://sg.danny.cz/sg/sg_v40.html


This suffers the same problem as your patch series in that it
encapsulates 26 years of thought in a single blob.

Presumably that document developed over time and didn't go from nothing
to 22K words in an instant. You need to document that process. Also,
having a design document that describes a wealth of changes after the
fact is not terribly helpful.


So tl;dr ?

And if I hid the code, would my "blob" then qualify as a design document?

Also if my sg v2/v3 documentation targetted the kernel submission
processes between 1998 and 2002, would it be much use today? I
think not.

The way C++ standards are being developed these days is interesting.
A proposer comes with an idea, code, test cases, rationale; then clang
and gcc folks implement it and then the committee looks at it seriously.
Some proposals get shunted through TS groups for a longer look.

I'm old enough to have been through the Ada debacle. So I know about
design documentation that went from the floor to the ceiling, several
times. Ada wasn't (isn't) a bad language but it was killed by its
associated documentation workflow. The Ada prophets claimed it was
a self-evident truth that almost all documentation (and test cases)
must be written before any code was cut. Ada is still used in air
traffic control, railway signalling,

[PATCH 02/18] sg: remove typedefs, type+formatting cleanup

2019-06-16 Thread Douglas Gilbert
Typedefs for structure types are discouraged so those structures
that are private to the driver have had their typedefs removed.

This also means that most "camel" type variable names (i.e. mixed
case) have been removed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 394 ++
 1 file changed, 219 insertions(+), 175 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6cd56ae93a2a..74243eb25387 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3,7 +3,7 @@
  *  History:
  *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com),
  *   to allow user process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
+ *  Development Sponsored by Killy Corp. NY NY   [1992 ??]
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
@@ -15,13 +15,6 @@ static int sg_version_num = 30901;  /* [x]xyyzz where [x] 
empty when x=0 */
 #define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
 static char *sg_version_date = "20190606";
 
-/*
- *  D. P. Gilbert (dgilb...@interlog.com), notes:
- *  - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
- *the kernel/module needs to be built with CONFIG_SCSI_LOGGING
- *(otherwise the macros compile to empty statements).
- *
- */
 #include 
 
 #include 
@@ -91,33 +84,32 @@ static int sg_add_device(struct device *, struct 
class_interface *);
 static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
-static DEFINE_RWLOCK(sg_index_lock);   /* Also used to lock
-  file descriptor list 
for device */
+static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock fd list for device */
 
 static struct class_interface sg_interface = {
.add_dev= sg_add_device,
.remove_dev = sg_remove_device,
 };
 
-typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info 
*/
-   unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
-   unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */
-   unsigned bufflen;   /* Size of (aggregate) data buffer */
+struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+   u16 k_use_sg; /* Count of kernel scatter-gather pieces */
+   unsigned int sglist_len; /* size of malloc'd scatter-gather list ++ */
+   unsigned int bufflen;   /* Size of (aggregate) data buffer */
struct page **pages;
int page_order;
char dio_in_use;/* 0->indirect IO (or mmap), 1->dio */
-   unsigned char cmd_opcode; /* first byte of command */
-} Sg_scatter_hold;
+   u8 cmd_opcode;  /* first byte of command */
+};
 
 struct sg_device;  /* forward declarations */
 struct sg_fd;
 
-typedef struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
+struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
struct list_head entry; /* list entry */
struct sg_fd *parentfp; /* NULL -> not in use */
-   Sg_scatter_hold data;   /* hold buffer, perhaps scatter list */
+   struct sg_scatter_hold data;/* hold buffer, perhaps scatter list */
sg_io_hdr_t header; /* scsi command+info, see  */
-   unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
+   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
char res_used;  /* 1 -> using reserve buffer, 0 -> not ... */
char orphan;/* 1 -> drop on sight, 0 -> normal */
char sg_io_owned;   /* 1 -> packet belongs to SG_IO */
@@ -126,9 +118,9 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests 
outstanding per file */
struct request *rq;
struct bio *bio;
struct execute_work ew;
-} Sg_request;
+};
 
-typedef struct sg_fd { /* holds the state of a file descriptor */
+struct sg_fd { /* holds the state of a file descriptor */
struct list_head sfd_siblings;  /* protected by device's sfd_lock */
struct sg_device *parentdp; /* owning device */
wait_queue_head_t read_wait;/* queue read until command done */
@@ -136,21 +128,21 @@ typedef 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 */
-   Sg_scatter_hold reserve;/* buffer held for this file descriptor 
*/
+   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 */
-   Sg_request req_arr[SG_MAX_QUEUE];   /* used as singly-lin

[PATCH 04/18] sg: rework sg_poll(), minor changes

2019-06-16 Thread Douglas Gilbert
Re-arrange code in sg_poll(). Rename sg_read_oxfer() to
sg_rd_append(). In sg_start_req() rename rw to r0w.
Plus associated changes demanded by checkpatch.pl

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 65 ++-
 1 file changed, 30 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index bc88fc594a74..28729b8d7d1f 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -177,13 +177,13 @@ static int sg_finish_rem_req(struct sg_request *srp);
 static int sg_build_indirect(struct sg_scatter_hold *schp, struct sg_fd *sfp,
 int buff_size);
 static ssize_t sg_new_write(struct sg_fd *sfp, struct file *file,
-   const char __user *buf, size_t count, int blocking,
-   int read_only, int sg_io_owned,
-   struct sg_request **o_srp);
+   const char __user *buf, size_t count, int blocking,
+   int read_only, int sg_io_owned,
+   struct sg_request **o_srp);
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
-static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
-int num_xfer);
+static int sg_rd_append(struct sg_request *srp, char __user *outp,
+   int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
 static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -918,7 +918,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
if (count > old_hdr->reply_len)
count = old_hdr->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_read_oxfer(srp, buf, count - SZ_SG_HEADER)) {
+   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER)) {
retval = -EFAULT;
goto free_old_hdr;
}
@@ -1253,38 +1253,34 @@ sg_compat_ioctl(struct file *filp, unsigned int cmd_in, 
unsigned long arg)
 static __poll_t
 sg_poll(struct file *filp, poll_table * wait)
 {
-   __poll_t res = 0;
-   struct sg_device *sdp;
-   struct sg_fd *sfp;
+   __poll_t p_res = 0;
+   struct sg_fd *sfp = filp->private_data;
struct sg_request *srp;
int count = 0;
unsigned long iflags;
 
-   sfp = filp->private_data;
if (!sfp)
return EPOLLERR;
-   sdp = sfp->parentdp;
-   if (!sdp)
-   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 ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
-   res = EPOLLIN | EPOLLRDNORM;
+   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(&sdp->detaching))
-   res |= EPOLLHUP;
-   else if (!sfp->cmd_q) {
-   if (0 == count)
-   res |= EPOLLOUT | EPOLLWRNORM;
-   } else if (count < SG_MAX_QUEUE)
-   res |= EPOLLOUT | EPOLLWRNORM;
-   SG_LOG(3, sfp, "%s: res=0x%x\n", __func__, (__force u32)res);
-   return res;
+   if (sfp->parentdp && atomic_read(&sfp->parentdp->detaching)) {
+   p_res |= EPOLLHUP;
+   } else if (!sfp->cmd_q) {
+   if (count == 0)
+   p_res |= EPOLLOUT | EPOLLWRNORM;
+   } else if (count < SG_MAX_QUEUE) {
+   p_res |= EPOLLOUT | EPOLLWRNORM;
+   }
+   SG_LOG(3, sfp, "%s: p_res=0x%x\n", __func__, (__force u32)p_res);
+   return p_res;
 }
 
 static int
@@ -1801,7 +1797,7 @@ sg_start_req(struct sg_request *srp, u8 *cmd)
struct sg_scatter_hold *rsv_schp = &sfp->reserve;
struct request_queue *q = sfp->parentdp->device->request_queue;
struct rq_map_data *md, map_data;
-   int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
+   int r0w = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
u8 *long_cmdp = NULL;
 
if (hp->cmd_len > BLK_MAX_CDB) {
@@ -1811,7 +1807,7 @@ sg_start_req(struct sg_request *srp, u8 *cmd)
SG_LOG(5, sfp, "%s: long_cmdp=0x%p ++\n", __func__, long_cmdp);
}
SG_LOG(4, sfp, "%s: dxfer_len=%d

[PATCH 08/18] sg: speed sg_poll and sg_get_num_waiting

2019-06-16 Thread Douglas Gilbert
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 
---
 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 d6414638689c..4a2b82521318 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

[PATCH 06/18] sg: make open count an atomic

2019-06-16 Thread Douglas Gilbert
Convert sg_device::open_cnt into an atomic. Also rename
sg_tablesize into the more descriptive max_sgat_elems.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 39 ---
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7d5ba080f201..d6414638689c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -162,9 +162,9 @@ struct sg_device { /* holds the state of each scsi generic 
device */
struct mutex open_rel_lock; /* held when in open() or release() */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   int max_sgat_elems; /* adapter's max sgat number of elements */
u32 index;  /* device index number */
-   int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
+   atomic_t open_cnt;  /* count of opens (perhaps < num(sfds) ) */
unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
@@ -276,11 +276,11 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
int retval = 0;
 
if (o_excl) {
-   while (sdp->open_cnt > 0) {
+   while (atomic_read(&sdp->open_cnt) > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
(SG_IS_DETACHING(sdp) ||
-!sdp->open_cnt));
+atomic_read(&sdp->open_cnt) == 0));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
@@ -355,7 +355,7 @@ sg_open(struct inode *inode, struct file *filp)
mutex_lock(&sdp->open_rel_lock);
if (op_flags & O_NONBLOCK) {
if (o_excl) {
-   if (sdp->open_cnt > 0) {
+   if (atomic_read(&sdp->open_cnt) > 0) {
retval = -EBUSY;
goto error_mutex_locked;
}
@@ -375,10 +375,10 @@ sg_open(struct inode *inode, struct file *filp)
if (o_excl)
set_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm);
 
-   if (sdp->open_cnt < 1) {  /* no existing opens */
+   if (atomic_read(&sdp->open_cnt) < 1) {  /* no existing opens */
clear_bit(SG_FDEV_LOG_SENSE, sdp->fdev_bm);
q = sdp->device->request_queue;
-   sdp->sg_tablesize = queue_max_segments(q);
+   sdp->max_sgat_elems = queue_max_segments(q);
}
sfp = sg_add_sfp(sdp);
if (IS_ERR(sfp)) {
@@ -387,10 +387,11 @@ sg_open(struct inode *inode, struct file *filp)
}
 
filp->private_data = sfp;
-   sdp->open_cnt++;
+   atomic_inc(&sdp->open_cnt);
mutex_unlock(&sdp->open_rel_lock);
SG_LOG(3, sfp, "%s: minor=%d, op_flags=0x%x; %s count prior=%d%s\n",
-  __func__, min_dev, op_flags, "device open", sdp->open_cnt,
+  __func__, min_dev, op_flags, "device open",
+  atomic_read(&sdp->open_cnt),
   ((op_flags & O_NONBLOCK) ? " O_NONBLOCK" : ""));
 
retval = 0;
@@ -423,20 +424,20 @@ sg_release(struct inode *inode, struct file *filp)
sfp = filp->private_data;
sdp = sfp->parentdp;
SG_LOG(3, sfp, "%s: device open count prior=%d\n", __func__,
-  sdp->open_cnt);
+  atomic_read(&sdp->open_cnt));
if (!sdp)
return -ENXIO;
 
mutex_lock(&sdp->open_rel_lock);
scsi_autopm_put_device(sdp->device);
kref_put(&sfp->f_ref, sg_remove_sfp);
-   sdp->open_cnt--;
+   atomic_dec(&sdp->open_cnt);
 
/* possibly many open()s waiting on exlude clearing, start many;
 * only open(O_EXCL)s wait on 0==open_cnt so only start one */
if (test_and_clear_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm))
wake_up_interruptible_all(&sdp->open_wait);
-   else if (sdp->open_cnt == 0)
+   else if (atomic_read(&sdp->open_cnt) == 0)
wake_up_interruptible(&sdp->open_wait);
mutex_unlock(&sdp->open_rel_lock);
return 0;
@@ -1104,7 +1105,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
return put_user(val, ip);
case SG_GET_SG_TABLESIZE:
- 

[PATCH 01/18] sg: move functions around

2019-06-16 Thread Douglas Gilbert
Move main entry point functions around so submission code comes
before completion code. Prior to this, the driver used the
traditional open(), close(), read(), write(), ioctl() ordering
however in this case that places completion code (i.e.
sg_read()) before submission code (i.e. sg_write()). The main
driver entry points are considered to be those named in struct
file_operations sg_fops' definition.

Helper functions are often placed above their caller to reduce
the number of forward function declarations needed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 499 --
 1 file changed, 261 insertions(+), 238 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index bcdc28e5ede7..6cd56ae93a2a 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -8,11 +8,12 @@
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
  * Version 2 and 3 extensions to driver:
- *Copyright (C) 1998 - 2014 Douglas Gilbert
+ *Copyright (C) 1998 - 2019 Douglas Gilbert
  */
 
-static int sg_version_num = 30536; /* 2 digits for each component */
-#define SG_VERSION_STR "3.5.36"
+static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
+#define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
+static char *sg_version_date = "20190606";
 
 /*
  *  D. P. Gilbert (dgilb...@interlog.com), notes:
@@ -47,6 +48,7 @@ static int sg_version_num = 30536;/* 2 digits for each 
component */
 #include 
 #include 
 #include  /* for sg_check_file_access() */
+#include 
 
 #include "scsi.h"
 #include 
@@ -57,12 +59,6 @@ static int sg_version_num = 30536;   /* 2 digits for each 
component */
 
 #include "scsi_logging.h"
 
-#ifdef CONFIG_SCSI_PROC_FS
-#include 
-static char *sg_version_date = "20140603";
-
-static int sg_proc_init(void);
-#endif
 
 #define SG_ALLOW_DIO_DEF 0
 
@@ -173,11 +169,11 @@ typedef struct sg_device { /* holds the state of each 
scsi generic device */
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
+/* Declarations of other static functions used before they are defined */
+static int sg_proc_init(void);
 static int sg_start_req(Sg_request *srp, unsigned char *cmd);
 static int sg_finish_rem_req(Sg_request * srp);
 static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int 
buff_size);
-static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
-  Sg_request * srp);
 static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
const char __user *buf, size_t count, int blocking,
int read_only, int sg_io_owned, Sg_request **o_srp);
@@ -190,7 +186,6 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, 
int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
 static Sg_fd *sg_add_sfp(Sg_device * sdp);
 static void sg_remove_sfp(struct kref *);
-static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static Sg_device *sg_get_dev(int dev);
@@ -232,16 +227,6 @@ static int sg_check_file_access(struct file *filp, const 
char *caller)
return 0;
 }
 
-static int sg_allow_access(struct file *filp, unsigned char *cmd)
-{
-   struct sg_fd *sfp = filp->private_data;
-
-   if (sfp->parentdp->device->type == TYPE_SCANNER)
-   return 0;
-
-   return blk_verify_command(cmd, filp->f_mode);
-}
-
 static int
 open_wait(Sg_device *sdp, int flags)
 {
@@ -405,200 +390,12 @@ sg_release(struct inode *inode, struct file *filp)
return 0;
 }
 
-static ssize_t
-sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
-   Sg_device *sdp;
-   Sg_fd *sfp;
-   Sg_request *srp;
-   int req_pack_id = -1;
-   sg_io_hdr_t *hp;
-   struct sg_header *old_hdr = NULL;
-   int retval = 0;
-
-   /*
-* This could cause a response to be stranded. Close the associated
-* file descriptor to free up any resources being held.
-*/
-   retval = sg_check_file_access(filp, __func__);
-   if (retval)
-   return retval;
-
-   if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
-   return -ENXIO;
-   SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
- "sg_read: count=%d\n", (int) count));
-
-   if (!access_ok(buf, count))
-   return -EFAULT;
-   if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
-   old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
-   if (!old_hdr)
-   return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
-   retval = -E

[PATCH 07/18] sg: move header to uapi section

2019-06-16 Thread Douglas Gilbert
Move user interface part of scsi/sg.h into the new header file:
include/uapi/scsi/sg.h . Since scsi/sg.h includes the new header,
other code including scsi/sg.h should not be impacted.

Signed-off-by: Douglas Gilbert 
---
 include/scsi/sg.h  | 268 ++---
 include/uapi/scsi/sg.h | 329 +
 2 files changed, 338 insertions(+), 259 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index f91bcca604e4..46fc7cbffd78 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -4,271 +4,21 @@
 
 #include 
 
-/*
- * History:
- *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com), to allow user
- *   process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
- *
- * Original driver (sg.h):
- *   Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
- * Copyright (C) 1998 - 2014 Douglas Gilbert
- *
- *  Version: 3.5.36 (20140603)
- *  This version is for 2.6 and 3 series kernels.
- *
- * Documentation
- * =
- * A web site for the SG device driver can be found at:
- * http://sg.danny.cz/sg  [alternatively check the MAINTAINERS file]
- * The documentation for the sg version 3 driver can be found at:
- * http://sg.danny.cz/sg/p/sg_v3_ho.html
- * Also see: /Documentation/scsi/scsi-generic.txt
- *
- * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html
- */
-
 #ifdef __KERNEL__
 extern int sg_big_buff; /* for sysctl */
 #endif
 
+/*
+ * In version 3.9.01 of the sg driver, this file was spilt in two, with the
+ * bulk of the user space interface being placed in the file being included
+ * in the following line.
+ */
+#include 
 
-typedef struct sg_iovec /* same structure as used by readv() Linux system */
-{   /* call. It defines one scatter-gather element. */
-void __user *iov_base;  /* Starting address  */
-size_t iov_len; /* Length in bytes  */
-} sg_iovec_t;
-
-
-typedef struct sg_io_hdr
-{
-int interface_id;   /* [i] 'S' for SCSI generic (required) */
-int dxfer_direction;/* [i] data transfer direction  */
-unsigned char cmd_len;  /* [i] SCSI command length */
-unsigned char mx_sb_len;/* [i] max length to write to sbp */
-unsigned short iovec_count; /* [i] 0 implies no scatter gather */
-unsigned int dxfer_len; /* [i] byte count of data transfer */
-void __user *dxferp;   /* [i], [*io] points to data transfer memory
- or scatter gather list */
-unsigned char __user *cmdp; /* [i], [*i] points to command to perform */
-void __user *sbp;  /* [i], [*o] points to sense_buffer memory */
-unsigned int timeout;   /* [i] MAX_UINT->no timeout (unit: millisec) */
-unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */
-int pack_id;/* [i->o] unused internally (normally) */
-void __user * usr_ptr;  /* [i->o] unused internally */
-unsigned char status;   /* [o] scsi status */
-unsigned char masked_status;/* [o] shifted, masked scsi status */
-unsigned char msg_status;   /* [o] messaging level data (optional) */
-unsigned char sb_len_wr;/* [o] byte count actually written to sbp */
-unsigned short host_status; /* [o] errors from host adapter */
-unsigned short driver_status;/* [o] errors from software driver */
-int resid;  /* [o] dxfer_len - actual_transferred */
-unsigned int duration;  /* [o] time taken by cmd (unit: millisec) */
-unsigned int info;  /* [o] auxiliary information */
-} sg_io_hdr_t;  /* 64 bytes long (on i386) */
-
-#define SG_INTERFACE_ID_ORIG 'S'
-
-/* Use negative values to flag difference from original sg_header structure */
-#define SG_DXFER_NONE (-1)  /* e.g. a SCSI Test Unit Ready command */
-#define SG_DXFER_TO_DEV (-2)/* e.g. a SCSI WRITE command */
-#define SG_DXFER_FROM_DEV (-3)  /* e.g. a SCSI READ command */
-#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
-  additional property than during indirect
-  IO the user buffer is copied into the
-  kernel buffers before the transfer */
-#define SG_DXFER_UNKNOWN (-5)   /* Unknown data direction */
-
-/* following flag values can be "or"-ed together */
-#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
-#define SG_FLAG_UNUSED_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
-   /* command block (when <= SCSI_2) */
-#define SG_FLAG_MMAP_IO 4   /* request memory mapped IO */
-#define SG_FLAG_NO_DXFER 0x1 /* no transfer of kernel buffers to/from */
-   /* user space (debug indirect IO) */
-/* default

[PATCH 00/18] sg: add v4 interface

2019-06-16 Thread Douglas Gilbert
This patchset extends the SCSI generic (sg) driver found in lk 5.3 .
The sg driver has a version number which is visible via an ioctl()
and is bumped from 3.5.36 to 4.0.03 by this patchset.
The additions and changes are described in some detail in this
long webpage:
http://sg.danny.cz/sg/sg_v40.html

Most new features described in the above webpage are not implemented
in this patchset. Features that are not included are file descriptor
sharing, request sharing, multiple requests (in one invocation) and
the extended ioctl(). A latter patchset may add those features. The
SG_IOSUMIT, SG_IOSUBMIT_V3, SG_IORECEIVE and SG_IORECEIVE_V3 ioctls
are added in this patchset.

Testing:
The sg3_utils package has several extensions in sg3_utils-1.45
beta (revision 826) to support and test the version 4 sg
driver presented in this patchset.
The new and revised testing utilities are outlined on the
same webpage as above in the second half of the section
titled: "15 Downloads and testing".

This patchset is against Martin Petersen's 5.3/scsi-queue
branch. It will also apply to lk 5.1 and probably lk 5.0 .

Douglas Gilbert (18):
  sg: move functions around
  sg: remove typedefs, type+formatting cleanup
  sg: sg_log and is_enabled
  sg: rework sg_poll(), minor changes
  sg: bitops in sg_device
  sg: make open count an atomic
  sg: move header to uapi section
  sg: speed sg_poll and sg_get_num_waiting
  sg: sg_allow_if_err_recovery and renames
  sg: remove most access_ok functions
  sg: replace rq array with lists
  sg: sense buffer rework
  sg: add sg v4 interface support
  sg: rework debug info
  sg: add 8 byte SCSI LUN to sg_scsi_id
  sg: expand sg_comm_wr_t
  sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls
  sg: bump version to 4.0.03

 drivers/scsi/sg.c  | 4373 ++--
 include/scsi/sg.h  |  268 +--
 include/uapi/scsi/sg.h |  373 
 3 files changed, 3269 insertions(+), 1745 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

-- 
2.17.1



[PATCH 10/18] sg: remove most access_ok functions

2019-06-16 Thread Douglas Gilbert
Since access_ok() has lost it direction (3rd) parameter there
seems to be no benefit in calling access_ok() before
__copy_{to|from}_user(). Simplify code by using the variant of
these functions that do not start with "__".

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 50 ---
 1 file changed, 17 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a5211b4d9bfb..dec40da5c220 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -502,11 +502,9 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
if (res)
return res;
 
-   if (!access_ok(buf, count))
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
if (count < SZ_SG_HEADER)
return -EIO;
-   if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
+   if (copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
return -EFAULT;
if (old_hdr.reply_len < 0)
return sg_submit(sfp, filp, buf, count, blocking, false, false,
@@ -561,7 +559,7 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
hp->flags = input_size; /* structure abuse ... */
hp->pack_id = old_hdr.pack_id;
hp->usr_ptr = NULL;
-   if (__copy_from_user(cmnd, buf, cmd_size))
+   if (copy_from_user(cmnd, buf, cmd_size))
return -EFAULT;
/*
 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
@@ -607,8 +605,6 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
 
if (count < SZ_SG_IO_HDR)
return -EINVAL;
-   if (!access_ok(buf, count))
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
 
sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */
if (!(srp = sg_add_request(sfp))) {
@@ -617,7 +613,7 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
}
srp->sg_io_owned = sg_io_owned;
hp = &srp->header;
-   if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
+   if (copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -645,11 +641,7 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
sg_remove_request(sfp, srp);
return -EMSGSIZE;
}
-   if (!access_ok(hp->cmdp, hp->cmd_len)) {
-   sg_remove_request(sfp, srp);
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
-   }
-   if (__copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
+   if (copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -829,13 +821,11 @@ sg_read(struct file *filp, char __user *buf, size_t 
count, loff_t *ppos)
if (ret)
return ret;
 
-   if (!access_ok(buf, count))
-   return -EFAULT;
if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
if (!old_hdr)
return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
+   if (copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
ret = -EFAULT;
goto free_old_hdr;
}
@@ -848,8 +838,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
ret = -ENOMEM;
goto free_old_hdr;
}
-   ret = __copy_from_user
-   (new_hdr, buf, SZ_SG_IO_HDR);
+   ret = copy_from_user(new_hdr, buf,
+SZ_SG_IO_HDR);
req_pack_id = new_hdr->pack_id;
kfree(new_hdr);
if (ret) {
@@ -942,7 +932,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
 
/* Now copy the result back to the user buffer.  */
if (count >= SZ_SG_HEADER) {
-   if (__copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
+   if (copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
ret = -EFAULT;
goto free_old_hdr;
}
@@ -1032,8 +1022,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
result = sg_allow_if_err_recovery(sdp, false);
if (result)
return result;
-   if (!access_ok(p, SZ_SG_IO_HDR

[PATCH 13/18] sg: add sg v4 interface support

2019-06-16 Thread Douglas Gilbert
Add support for the sg v4 interface based on struct sg_io_v4 found
in include/uapi/linux/bsg.h and only previously supported by the
bsg driver. Add ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async (non-blocking) usage of the sg v4 interface. Do not accept
the v3 interface with these ioctls. Do not accept the v4
interface with this driver's existing write() and read()
system calls.

For sync (blocking) usage expand the existing ioctl(SG_IO)
to additionally accept the sg v4 interface object.

---

A later patch in this set adds multiple requests in a single
invocation. Multiple requests use sg v4 interface objects
exclusively.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 489 -
 include/uapi/scsi/sg.h |  37 +++-
 2 files changed, 420 insertions(+), 106 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d194417b2809..4a33d67e85e6 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -7,8 +7,9 @@
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
+ * Version 2, 3 and 4 extensions to driver:
  *Copyright (C) 1998 - 2019 Douglas Gilbert
+ *
  */
 
 static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
@@ -40,10 +41,12 @@ static char *sg_version_date = "20190606";
 #include 
 #include 
 #include 
-#include  /* for sg_check_file_access() */
+#include /* for sg_check_file_access() */
+#include 
 #include 
 
-#include "scsi.h"
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -99,6 +102,7 @@ enum sg_rq_state {
 #define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
 
 /* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_V4I  0   /* true (set) when is v4 interface */
 #define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
 #define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
 #define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
@@ -159,6 +163,15 @@ struct sg_slice_hdr3 {
void __user *usr_ptr;
 };
 
+struct sg_slice_hdr4 { /* parts of sg_io_v4 object needed in async usage */
+   void __user *sbp;   /* derived from sg_io_v4::response */
+   u64 usr_ptr;/* hold sg_io_v4::usr_ptr as given (u64) */
+   int out_resid;
+   s16 dir;/* data xfer direction; SG_DXFER_*  */
+   u16 cmd_len;/* truncated of sg_io_v4::request_len */
+   u16 max_sb_len; /* truncated of sg_io_v4::max_response_len */
+};
+
 struct sg_scatter_hold { /* holding area for scsi scatter gather info */
struct page **pages;/* num_sgat element array of struct page* */
int buflen; /* capacity in bytes (dlen<=buflen) */
@@ -175,7 +188,10 @@ struct sg_request {/* active SCSI command or 
inactive on free list (fl) */
struct list_head fl_entry;  /* member of rq_fl */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
-   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   union {
+   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   struct sg_slice_hdr4 s_hdr4; /* reduced size struct sg_io_v4 */
+   };
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -235,7 +251,10 @@ struct sg_device { /* holds the state of each scsi generic 
device */
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
-   struct sg_io_hdr *h3p;
+   union { /* selector is frq_bm.SG_FRQ_IS_V4I */
+   struct sg_io_hdr *h3p;
+   struct sg_io_v4 *h4p;
+   };
u8 *cmnd;
 };
 
@@ -244,12 +263,12 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   int dxfer_dir);
+   struct sg_io_v4 *h4p, int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
-static int sg_submit(struct file *filp, struct sg_fd *sfp,
-struct sg_io_hdr *hp, bool sync,
-struct sg_request **o_srp);
+static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
+   struct sg_io_hdr *hp, bool sync,
+   struct sg_request **o_srp);
 static struct sg_request *sg_common_write(struct sg_fd *sfp,
  

[PATCH 17/18] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls

2019-06-16 Thread Douglas Gilbert
Add ioctl(SG_IOSUBMIT_V3) and ioctl(SG_IORECEIVE_V3). These ioctls
are meant to be (almost) drop-in replacements for the write()/read()
async version 3 interface. They only accept the version 3 interface.

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
specifically the table in the section titled: "12 SG interface
support changes".

If sgv3 is a struct sg_io_hdr object, suitably configured, then
res = write(sg_fd, &sgv3, sizeof(sgv3));
and
res = ioctl(sg_fd, SG_IOSUBMIT_V3, &sgv3);
are equivalent. Dito for read() and ioctl(SG_IORECEIVE_V3).

---

Note this inconsistency: for async/non-blocking usage, only
the v4 interface objects can use ioctl(SG_IOSUBMIT) and
(SG_IORECEIVE) while only v3 interface objects can use
ioctl(SG_IOSUBMIT_V3) and (SG_IORECEIVE_V3). However with
the sync usage both v3 and v4 interface objects can use
ioctl(SG_IO). The former action is preferred but existing
practice for sync usage (i.e. the current sg driver
supporting the v3 interface object with ioctl(SG_IO) while
the bsg driver continues to support the v4 interface object
with ioctl(SG_IO)) dictates the dual nature of ioctl(SG_IO).

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 75 ++
 include/uapi/scsi/sg.h |  6 
 2 files changed, 81 insertions(+)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index f0c4176551d8..0d93c6a92978 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -804,6 +804,24 @@ sg_ctl_iosubmit(struct file *filp, struct sg_fd *sfp, void 
__user *p)
return -EPERM;
 }
 
+static int
+sg_ctl_iosubmit_v3(struct file *filp, struct sg_fd *sfp, void __user *p)
+{
+   int res;
+   u8 hdr_store[SZ_SG_IO_V4];  /* max(v3interface, v4interface) */
+   struct sg_io_hdr *h3p = (struct sg_io_hdr *)hdr_store;
+   struct sg_device *sdp = sfp->parentdp;
+
+   res = sg_allow_if_err_recovery(sdp, (filp->f_flags & O_NONBLOCK));
+   if (unlikely(res))
+   return res;
+   if (copy_from_user(h3p, p, SZ_SG_IO_HDR))
+   return -EFAULT;
+   if (h3p->interface_id == 'S')
+   return sg_v3_submit(filp, sfp, h3p, false, NULL);
+   return -EPERM;
+}
+
 static void
 sg_execute_cmd(struct sg_fd *sfp, struct sg_request *srp)
 {
@@ -1168,6 +1186,57 @@ sg_ctl_ioreceive(struct file *filp, struct sg_fd *sfp, 
void __user *p)
return sg_v4_receive(sfp, srp, p, h4p);
 }
 
+/*
+ * Called when ioctl(SG_IORECEIVE_V3) received. Expects a v3 interface.
+ * Checks if O_NONBLOCK file flag given, if not checks given flags field
+ * to see if SGV4_FLAG_IMMED is set. Either of these implies non blocking.
+ * When non-blocking and there is no request waiting, yields EAGAIN;
+ * otherwise it waits.
+ */
+static int
+sg_ctl_ioreceive_v3(struct file *filp, struct sg_fd *sfp, void __user *p)
+{
+   bool non_block = !!(filp->f_flags & O_NONBLOCK);
+   int res;
+   int pack_id = SG_PACK_ID_WILDCARD;
+   u8 v3_holder[SZ_SG_IO_HDR];
+   struct sg_io_hdr *h3p = (struct sg_io_hdr *)v3_holder;
+   struct sg_device *sdp = sfp->parentdp;
+   struct sg_request *srp;
+
+   res = sg_allow_if_err_recovery(sdp, non_block);
+   if (unlikely(res))
+   return res;
+   /* Get first three 32 bit integers: guard, proto+subproto */
+   if (copy_from_user(h3p, p, SZ_SG_IO_HDR))
+   return -EFAULT;
+   /* for v3: interface_id=='S' (in a 32 bit int) */
+   if (h3p->interface_id != 'S')
+   return -EPERM;
+   if (h3p->flags & SGV4_FLAG_IMMED)
+   non_block = true;   /* set by either this or O_NONBLOCK */
+   SG_LOG(3, sfp, "%s: non_block(+IMMED)=%d\n", __func__, non_block);
+
+   if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm))
+   pack_id = h3p->pack_id;
+
+   srp = sg_find_srp_by_id(sfp, pack_id);
+   if (!srp) { /* nothing available so wait on packet or */
+   if (unlikely(SG_IS_DETACHING(sdp)))
+   return -ENODEV;
+   if (non_block)
+   return -EAGAIN;
+   res = wait_event_interruptible
+   (sfp->read_wait,
+sg_get_ready_srp(sfp, &srp, pack_id));
+   if (unlikely(SG_IS_DETACHING(sdp)))
+   return -ENODEV;
+   if (unlikely(res))
+   return res; /* signal --> -ERESTARTSYS */
+   }   /* now srp should be valid */
+   return sg_v3_receive(sfp, srp, p);
+}
+
 static int
 sg_rd_v1v2(void __user *buf, int count, struct sg_fd *sfp,
   struct sg_request *srp)
@@ -1726,9 +1795,15 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, 
unsigned long arg)
case SG_IOSUBMIT:
SG_LOG(3, sfp, "%s:SG_IOSUBMIT\n", __func__);

[PATCH 15/18] sg: add 8 byte SCSI LUN to sg_scsi_id

2019-06-16 Thread Douglas Gilbert
The existing ioctl(SG_GET_SCSI_ID) fills a object of type
struct sg_scsi_id whose last field is int unused[2]. Add
an anonymous union with u8 scsi_lun[8] sharing those last
8 bytes. This patch will place the current device's full
LUN in the scsi_lun array using T10's preferred LUN
format (i.e. an array of 8 bytes) when
ioctl(SG_GET_SCSI_ID) is called.

Note that structure already contains a 'lun' field but that
is a 32 bit integer. Users of this upgrade should choose
the scsi_lun array field henceforth but existing code
can remain as it is and will get the same 'lun' value with
the version 3 or version 4 driver.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 5 +++--
 include/uapi/scsi/sg.h | 5 -
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 82a2fe25d916..a244ea7d436f 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1679,6 +1679,7 @@ static int
 sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_fd *sfp, void __user *p)
 {
struct sg_scsi_id __user *sg_idp = p;
+   struct scsi_lun lun8b;
 
SG_LOG(3, sfp, "%s:SG_GET_SCSI_ID\n", __func__);
if (!access_ok(p, sizeof(struct sg_scsi_id)))
@@ -1696,8 +1697,8 @@ sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_fd 
*sfp, void __user *p)
   &sg_idp->h_cmd_per_lun);
__put_user((short)sdev->queue_depth,
   &sg_idp->d_queue_depth);
-   __put_user(0, &sg_idp->unused[0]);
-   __put_user(0, &sg_idp->unused[1]);
+   int_to_scsilun(sdev->lun, &lun8b);
+   __copy_to_user(sg_idp->scsi_lun, lun8b.scsi_lun, 8);
return 0;
 }
 
diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h
index 7557c1be01e0..db86d1ae7e29 100644
--- a/include/uapi/scsi/sg.h
+++ b/include/uapi/scsi/sg.h
@@ -135,7 +135,10 @@ typedef struct sg_scsi_id {
int scsi_type;  /* TYPE_... defined in scsi/scsi.h */
short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
short d_queue_depth;/* device (or adapter) maximum queue length */
-   int unused[2];
+   union {
+   int unused[2];  /* as per version 3 driver */
+   __u8 scsi_lun[8];  /* full 8 byte SCSI LUN [in v4 driver] */
+   };
 } sg_scsi_id_t;
 
 /* For backward compatibility v4 driver yields at most SG_MAX_QUEUE of these */
-- 
2.17.1



[PATCH 05/18] sg: bitops in sg_device

2019-06-16 Thread Douglas Gilbert
Introduce bitops in sg_device to replace an atomic, a bool and a
char. That char (sgdebug) had been reduced to only two states.
Add some associated macros to make the code a little clearer.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 104 +++---
 1 file changed, 53 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 28729b8d7d1f..7d5ba080f201 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -74,6 +74,11 @@ static char *sg_version_date = "20190606";
 
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
 
+/* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
+#define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
+#define SG_FDEV_DETACHING  1   /* may be unexpected device removal */
+#define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
+
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
 /* N.B. This variable is readable and writeable via
/proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
@@ -155,14 +160,12 @@ 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 */
struct mutex open_rel_lock; /* held when in open() or release() */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
-   u32 index;  /* device index number */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   atomic_t detaching; /* 0->device usable, 1->device detaching */
-   bool exclude;   /* 1->open(O_EXCL) succeeded and is active */
+   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   u32 index;  /* device index number */
int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
-   char sgdebug;   /* 0->off, 1->sense, 9->dump dev, 10-> all devs 
*/
+   unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
struct kref d_ref;
@@ -200,6 +203,9 @@ static void sg_device_destroy(struct kref *kref);
 #define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
 #define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
 
+#define SG_IS_DETACHING(sdp) test_bit(SG_FDEV_DETACHING, (sdp)->fdev_bm)
+#define SG_HAVE_EXCLUDE(sdp) test_bit(SG_FDEV_EXCLUDE, (sdp)->fdev_bm)
+
 /*
  * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
  * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
@@ -273,26 +279,26 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
while (sdp->open_cnt > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
+   (SG_IS_DETACHING(sdp) ||
 !sdp->open_cnt));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
-   while (sdp->exclude) {
+   while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
-!sdp->exclude));
+   (SG_IS_DETACHING(sdp) ||
+!SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
}
@@ -354,7 +360,7 @@ sg_open(struct inode *inode, struct file *filp)
goto error_mutex_locked;
}
} else {
-   if (sdp->exclude) {
+   if (SG_HAVE_EXCLUDE(sdp)) {
retval = -EBUSY;
goto error_mutex_locked;
}
@@ -367,10 +373,10 @@ sg_open(struct inode *in

[PATCH 14/18] sg: rework debug info

2019-06-16 Thread Douglas Gilbert
Since the version 2 driver, the state of the driver can be found
with 'cat /proc/scsi/sg/debug'. As the driver becomes more
threaded and IO faster (e.g. scsi_debug with a command timer
of 5 microseconds), the existing state dump can become
misleading as the state can change during the "snapshot". The
new approach in this patch is to allocate a buffer of
SG_PROC_DEBUG_SZ bytes and use scnprintf() to populate it. Only
when the whole state is captured (or the buffer fills) is the
output to the caller's terminal performed. The previous
approach was line based: assemble a line of information and
then output it.

Locks are taken as required for short periods and should not
interfere with a disk IO intensive program. Operations
such as closing a sg file descriptor or removing a sg device
may be held up for a short while (microseconds).

---

SG_PROC_DEBUG_SZ is currently fixed at 8192 bytes. Later patches
will allow a user to change this value via an ioctl.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 238 +++---
 1 file changed, 160 insertions(+), 78 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 4a33d67e85e6..82a2fe25d916 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3740,115 +3740,197 @@ sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
return 0;
 }
 
-/* must be called while holding sg_index_lock */
-static void
-sg_proc_debug_helper(struct seq_file *s, struct sg_device *sdp)
+/* Writes debug info for one sg_request in obp buffer */
+static int
+sg_proc_debug_sreq(struct sg_request *srp, int to, char *obp, int len)
+   __must_hold(&srp->req_lck)
 {
-   int k;
+   bool is_v3v4, v4, is_dur;
+   int n = 0;
+   u32 dur;
+   enum sg_rq_state rq_st;
+   const char *cp;
+
+   if (len < 1)
+   return 0;
+   v4 = test_bit(SG_FRQ_IS_V4I, srp->frq_bm);
+   is_v3v4 = v4 ? true : (srp->s_hdr3.interface_id != '\0');
+   if (srp->parentfp->rsv_srp == srp)
+   cp = (is_v3v4 && (srp->rq_flags & SG_FLAG_MMAP_IO)) ?
+   " mmap>> " : " rsv>> ";
+   else
+   cp = (srp->rq_info & SG_INFO_DIRECT_IO_MASK) ?
+   " dio>> " : " ";
+   rq_st = atomic_read(&srp->rq_st);
+   dur = sg_get_dur(srp, &rq_st, &is_dur);
+   n += scnprintf(obp + n, len - n, "%s%s: dlen=%d/%d id=%d", cp,
+  sg_rq_st_str(rq_st, false), srp->sgat_h.dlen,
+  srp->sgat_h.buflen, (int)srp->pack_id);
+   if (is_dur) /* cmd/req has completed, waiting for ... */
+   n += scnprintf(obp + n, len - n, " dur=%ums", dur);
+   else if (dur < U32_MAX) /* in-flight or busy (so ongoing) */
+   n += scnprintf(obp + n, len - n, " t_o/elap=%us/%ums",
+  to / 1000, dur);
+   n += scnprintf(obp + n, len - n, " sgat=%d op=0x%02x\n",
+  srp->sgat_h.num_sgat, srp->cmd_opcode);
+   return n;
+}
+
+/* Writes debug info for one sg fd (including its sg requests) in obp buffer */
+static int
+sg_proc_debug_fd(struct sg_fd *fp, char *obp, int len)
+   __must_hold(&sfp->rq_list_lock)
+{
+   bool first_fl;
+   int n = 0;
+   int to;
struct sg_request *srp;
-   struct sg_fd *fp;
-   const char * cp;
-   unsigned int ms;
 
-   k = 0;
-   list_for_each_entry(fp, &sdp->sfds, sfd_entry) {
-   k++;
-   spin_lock(&fp->rq_list_lock); /* irqs already disabled */
-   seq_printf(s, "   FD(%d): timeout=%dms bufflen=%d "
-  "(res)sgat=%d low_dma=%d\n", k,
-  jiffies_to_msecs(fp->timeout),
-  fp->rsv_srp->sgat_h.buflen,
-  (int)fp->rsv_srp->sgat_h.num_sgat,
-  (int) sdp->device->host->unchecked_isa_dma);
-   seq_printf(s, "   cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
-  (int)test_bit(SG_FFD_CMD_Q, fp->ffd_bm),
-  (int)test_bit(SG_FFD_FORCE_PACKID, fp->ffd_bm),
-  (int)test_bit(SG_FFD_KEEP_ORPHAN, fp->ffd_bm));
-   seq_printf(s, "   submitted=%d waiting=%d\n",
-  atomic_read(&fp->submitted),
-  atomic_read(&fp->waiting));
-   list_for_each_entry(srp, &fp->rq_list, rq_entry) {
-   const struct sg_slice_hdr3 *sh3p = &srp->s_hdr3;
-   bool is_v3 = (sh3p->interface_id != '\0');
-  

[PATCH 18/18] sg: bump version to 4.0.03

2019-06-16 Thread Douglas Gilbert
Now that the sg version 4 interface is supported:
  - with ioctl(SG_IO) for synchronous/blocking use
  - with ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async/non-blocking use
Plus new ioctl(SG_IOSUBMIT_V3) and ioctl(SG_IORECEIVE_V3)
potentially replace write() and read() for the sg
version 3 interface. Bump major driver version number
from 3 to 4.

The main new feature is the removal of the fixed 16 element
array of requests per file descriptor. It is replaced by
two lists: one for active (inflight) requests and a free
list. Also sg_requests objects are not freed until the
owning file descriptor is closed; rather these objects
are re-used when multiple commands are sent to the same
file descriptor.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 0d93c6a92978..06e29e5f9f48 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -12,9 +12,9 @@
  *
  */
 
-static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
-#define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
-static char *sg_version_date = "20190606";
+static int sg_version_num = 40003;  /* [x]xyyzz where [x] empty when x=0 */
+#define SG_VERSION_STR "4.0.03"/* [x]x.[y]y.zz */
+static char *sg_version_date = "20190612";
 
 #include 
 
-- 
2.17.1



[PATCH 12/18] sg: sense buffer rework

2019-06-16 Thread Douglas Gilbert
The biggest single item in the sg_request object is the sense
buffer array which is SCSI_SENSE_BUFFERSIZE bytes long. That
constant started out at 18 bytes 20 years ago and is 96 bytes
now and might grow in the future. On the other hand the sense
buffer is only used by a small number of SCSI commands: those
that fail and those that want to return more information
other than a SCSI status of GOOD.

Allocate sense buffer as needed on the heap and delete as soon as
possible.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 47 +++
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 05acb6ee0ad0..d194417b2809 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -176,7 +176,6 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
-   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -188,6 +187,7 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
u8 cmd_opcode;  /* first byte of SCSI cdb */
u64 start_ns;   /* starting point of command duration calc */
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
+   u8 *sense_bp;   /* alloc-ed sense buffer, as needed */
struct sg_fd *parentfp; /* pointer to owning fd, even when on fl */
struct request *rq; /* released in sg_rq_end_io(), bio kept */
struct bio *bio;/* kept until this req -->SG_RS_INACTIVE */
@@ -845,18 +845,21 @@ sg_copy_sense(struct sg_request *srp)
(driver_byte(srp->rq_result) & DRIVER_SENSE)) {
int sb_len = min_t(int, SCSI_SENSE_BUFFERSIZE, srp->sense_len);
int mx_sb_len;
+   u8 *sbp = srp->sense_bp;
void __user *up;
 
+   srp->sense_bp = NULL;
up = (void __user *)srp->s_hdr3.sbp;
mx_sb_len = srp->s_hdr3.mx_sb_len;
-   if (up && mx_sb_len > 0) {
+   if (up && mx_sb_len > 0 && sbp) {
sb_len = min_t(int, sb_len, mx_sb_len);
/* Additional sense length field */
-   sb_len_wr = 8 + (int)srp->sense_b[7];
+   sb_len_wr = 8 + (int)sbp[7];
sb_len_wr = min_t(int, sb_len, sb_len_wr);
-   if (copy_to_user(up, srp->sense_b, sb_len_wr))
+   if (copy_to_user(up, sbp, sb_len_wr))
sb_len_wr = -EFAULT;
}
+   kfree(sbp);
}
return sb_len_wr;
 }
@@ -963,8 +966,9 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd *sfp,
h2p->driver_status = driver_byte(rq_result);
if ((CHECK_CONDITION & status_byte(rq_result)) ||
(DRIVER_SENSE & driver_byte(rq_result))) {
-   memcpy(h2p->sense_buffer, srp->sense_b,
-  sizeof(h2p->sense_buffer));
+   if (srp->sense_bp)
+   memcpy(h2p->sense_buffer, srp->sense_bp,
+  sizeof(h2p->sense_buffer));
}
switch (host_byte(rq_result)) {
/*
@@ -999,17 +1003,21 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd 
*sfp,
 
/* Now copy the result back to the user buffer.  */
if (count >= SZ_SG_HEADER) {
-   if (copy_to_user(buf, h2p, SZ_SG_HEADER))
-   return -EFAULT;
+   if (copy_to_user(buf, h2p, SZ_SG_HEADER)) {
+   res = -EFAULT;
+   goto fini;
+   }
buf += SZ_SG_HEADER;
if (count > h2p->reply_len)
count = h2p->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER))
-   return -EFAULT;
+   res = sg_rd_append(srp, buf, count - SZ_SG_HEADER);
+   if (res)
+   goto fini;
}
} else
res = (h2p->result == 0) ? 0 : -EIO;
+fini:
atomic_set(&srp->rq_st, SG_RS_DONE_RD);
sg_finish_scsi_blk_rq(srp);
sg_deact_request(sfp, srp);
@@ -1977,8 +1985,17 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
srp->duration = sg_calc_rq_dur(srp);
if (unlikely((srp->rq_result & SG_ML_RESULT_MSK) 

[PATCH 09/18] sg: sg_allow_if_err_recovery and renames

2019-06-16 Thread Douglas Gilbert
Add sg_allow_if_err_recover() to do checks common to several entry
points. Replace retval with either res or ret. Rename
sg_finish_rem_req() to sg_finish_scsi_blk_rq(). Rename
sg_new_write() to sg_submit(). Other cleanups triggered by
checkpatch.pl .

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 245 +-
 1 file changed, 133 insertions(+), 112 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 4a2b82521318..a5211b4d9bfb 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -68,7 +68,7 @@ static char *sg_version_date = "20190606";
 
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
- * than 16 bytes are "variable length" whose length is a multiple of 4
+ * than 16 bytes are "variable length" whose length is a multiple of 4, so:
  */
 #define SG_MAX_CDB_SIZE 252
 
@@ -178,16 +178,16 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd);
-static int sg_finish_rem_req(struct sg_request *srp);
+static int sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_build_indirect(struct sg_scatter_hold *schp, struct sg_fd *sfp,
 int buff_size);
-static ssize_t sg_new_write(struct sg_fd *sfp, struct file *file,
-   const char __user *buf, size_t count, int blocking,
-   int read_only, int sg_io_owned,
-   struct sg_request **o_srp);
+static ssize_t sg_submit(struct sg_fd *sfp, struct file *filp,
+const char __user *buf, size_t count, bool blocking,
+bool read_only, bool sg_io_owned,
+struct sg_request **o_srp);
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
-static int sg_rd_append(struct sg_request *srp, char __user *outp,
+static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
@@ -275,37 +275,60 @@ sg_check_file_access(struct file *filp, const char 
*caller)
 static int
 sg_wait_open_event(struct sg_device *sdp, bool o_excl)
 {
-   int retval = 0;
+   int res = 0;
 
if (o_excl) {
while (atomic_read(&sdp->open_cnt) > 0) {
mutex_unlock(&sdp->open_rel_lock);
-   retval = wait_event_interruptible(sdp->open_wait,
-   (SG_IS_DETACHING(sdp) ||
-atomic_read(&sdp->open_cnt) == 0));
+   res = wait_event_interruptible
+   (sdp->open_wait,
+(SG_IS_DETACHING(sdp) ||
+ atomic_read(&sdp->open_cnt) == 0));
mutex_lock(&sdp->open_rel_lock);
 
-   if (retval) /* -ERESTARTSYS */
-   return retval;
+   if (res) /* -ERESTARTSYS */
+   return res;
if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
-   retval = wait_event_interruptible(sdp->open_wait,
-   (SG_IS_DETACHING(sdp) ||
-!SG_HAVE_EXCLUDE(sdp)));
+   res = wait_event_interruptible
+   (sdp->open_wait,
+(SG_IS_DETACHING(sdp) ||
+ !SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock);
 
-   if (retval) /* -ERESTARTSYS */
-   return retval;
+   if (res) /* -ERESTARTSYS */
+   return res;
if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
}
 
-   return retval;
+   return res;
+}
+
+/*
+ * scsi_block_when_processing_errors() returns 0 when dev was taken offline by
+ * error recovery, 1 otherwise (i.e. okay). Even if in error recovery, let
+ * user continue if O_NONBLOCK set. Permits SCSI commands to be issued during
+ * error recovery. Tread carefully.
+ * Ret

[PATCH 03/18] sg: sg_log and is_enabled

2019-06-16 Thread Douglas Gilbert
Replace SCSI_LOG_TIMEOUT macros with SG_LOG macros across the driver.
The definition of SG_LOG calls SCSI_LOG_TIMEOUT if given and derived
pointers are non-zero, calls pr_info otherwise. SG_LOGS additionally
prints the sg device name and the thread id. The thread id is very
useful, even in single threaded invocations because the driver not
only uses the invocer's thread but also uses work queues and the
main callback (i.e. sg_rq_end_io()) may hit any thread. Some
interesting cases arise when the callback hits its invocer's
thread.

SG_LOGS takes 48 bytes on the stack to build this printf format
string: "sg%u: tid=%d" whose size is clearly bounded above by
the maximum size of those two integers.
Protecting against the 'current' pointer being zero is for safety
and the case where the boot device is SCSI and the sg driver is
built into the kernel. Also when debugging, getting a message
from a compromised kernel can be very useful in pinpointing the
location of the failure.

The simple fact that the SG_LOG macro is shorter than
SCSI_LOG_TIMEOUT macro allow more error message "payload" per line.

Also replace #if and #ifdef conditional compilations with
the IS_ENABLED macro.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 252 +++---
 1 file changed, 125 insertions(+), 127 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 74243eb25387..bc88fc594a74 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -57,6 +57,15 @@ static char *sg_version_date = "20190606";
 
 #define SG_MAX_DEVS 32768
 
+/* Comment out the following line to compile out SCSI_LOGGING stuff */
+#define SG_DEBUG 1
+
+#if !IS_ENABLED(SG_DEBUG)
+#if IS_ENABLED(DEBUG)  /* If SG_DEBUG not defined, check for DEBUG */
+#define SG_DEBUG DEBUG
+#endif
+#endif
+
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
  * than 16 bytes are "variable length" whose length is a multiple of 4
@@ -174,7 +183,7 @@ static ssize_t sg_new_write(struct sg_fd *sfp, struct file 
*file,
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
 static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
-int num_read_xfer);
+int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
 static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -187,14 +196,45 @@ static int sg_remove_request(struct sg_fd *sfp, struct 
sg_request *srp);
 static struct sg_device *sg_get_dev(int dev);
 static void sg_device_destroy(struct kref *kref);
 
-#define SZ_SG_HEADER sizeof(struct sg_header)
-#define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
-#define SZ_SG_IOVEC sizeof(sg_iovec_t)
-#define SZ_SG_REQ_INFO sizeof(sg_req_info_t)
+#define SZ_SG_HEADER ((int)sizeof(struct sg_header))   /* v1 and v2 header */
+#define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
+#define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
+
+/*
+ * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
+ * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
+ * information). All messages are logged as informational (KERN_INFO). In
+ * the unexpected situation where sfp or sdp is NULL the macro reverts to
+ * a pr_info and ignores SCSI_LOG_TIMEOUT and always prints to the log.
+ * Example: this invocation: 'scsi_logging_level -s -T 3' will print
+ * depth (aka level) 1 and 2 SG_LOG() messages.
+ */
+
+#define SG_PROC_DEBUG_SZ 8192
+
+#if IS_ENABLED(CONFIG_SCSI_LOGGING) && IS_ENABLED(SG_DEBUG)
+#define SG_LOG_BUFF_SZ 48
+
+#define SG_LOG(depth, sfp, fmt, a...)  \
+   do {\
+   char _b[SG_LOG_BUFF_SZ];\
+   int _tid = (current ? current->pid : -1);   \
+   struct sg_fd *_fp = sfp;\
+   struct sg_device *_sdp = _fp ? _fp->parentdp : NULL;\
+   \
+   if (likely(_sdp && _sdp->disk)) {   \
+   snprintf(_b, sizeof(_b), "sg%u: tid=%d",\
+_sdp->index, _tid);\
+   SCSI_LOG_TIMEOUT(depth, \
+sdev_prefix_printk(KERN_INFO,  \
+_sdp->device, _b, fmt, ##a));  \
+   } else  \
+

[PATCH 11/18] sg: replace rq array with lists

2019-06-16 Thread Douglas Gilbert
Remove the fixed size array of 16 request elements per file
descriptor and replace with two linked lists per file descriptor.
One list is for active commands, the other list is a free list.
sg_request objects are now kept, available for re-use, until
their owning file descriptor is closed. The sg_request deletions
are now in sg_remove_sfp_usercontext(). Each active sg_request
has associated block request and scsi_request objects which are
released much earlier; their lifetime is the same as it was in
the v3 sg driver. The lifetime of the bio is also the same (but
is stretched in a later patch).

Add an enum for request state (sg_rq_state) and collect
various flags into bit maps: one for requests (SG_FRQ_*) and
the other for file descriptors (SG_FFD_*). They join a
per sg_device bit map (SG_FDEV_*) added in an earlier
patch.

Prior to a new sg_request object being (re-)built, information
that will be placed in it uses a new struct sg_comm_wr_t
object.

Since the above changes touch almost every function and low
level structures, this patch is big. With so many changes, the
diff utility that generates the patch sometimes loses track.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 3035 +
 1 file changed, 1951 insertions(+), 1084 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index dec40da5c220..05acb6ee0ad0 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -72,7 +72,46 @@ static char *sg_version_date = "20190606";
  */
 #define SG_MAX_CDB_SIZE 252
 
+#define uptr64(val) ((void __user *)(uintptr_t)(val))
+#define cuptr64(val) ((const void __user *)(uintptr_t)(val))
+
+/* Following enum contains the states of sg_request::rq_st */
+enum sg_rq_state {
+   SG_RS_INACTIVE = 0, /* request not in use (e.g. on fl) */
+   SG_RS_INFLIGHT, /* active: cmd/req issued, no response yet */
+   SG_RS_AWAIT_RD, /* response received, awaiting read */
+   SG_RS_DONE_RD,  /* read is ongoing or done */
+   SG_RS_BUSY, /* temporary state should rarely be seen */
+};
+
+#define SG_TIME_UNIT_MS 0  /* milliseconds */
+#define SG_DEF_TIME_UNIT SG_TIME_UNIT_MS
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
+#define SG_FD_Q_AT_HEAD 0
+#define SG_DEFAULT_Q_AT SG_FD_Q_AT_HEAD /* for backward compatibility */
+#define SG_FL_MMAP_DIRECT (SG_FLAG_MMAP_IO | SG_FLAG_DIRECT_IO)
+
+/* Only take lower 4 bits of driver byte, all host byte and sense byte */
+#define SG_ML_RESULT_MSK 0x0fff00ff/* mid-level's 32 bit result value */
+
+#define SG_PACK_ID_WILDCARD (-1)
+
+#define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
+
+/* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
+#define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
+#define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
+#define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
+#define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
+#define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
+
+/* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
+#define SG_FFD_FORCE_PACKID0   /* receive only given pack_id/tag */
+#define SG_FFD_CMD_Q   1   /* clear: only 1 active req per fd */
+#define SG_FFD_KEEP_ORPHAN 2   /* policy for this fd */
+#define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
+#define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
 
 /* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
 #define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
@@ -80,19 +119,17 @@ static char *sg_version_date = "20190606";
 #define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
-/* N.B. This variable is readable and writeable via
-   /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
-   of this size (or less if there is not enough memory) will be reserved
-   for use by this file descriptor. [Deprecated usage: this variable is also
-   readable via /proc/sys/kernel/sg-big-buff if the sg driver is built into
-   the kernel (i.e. it is not a module).] */
+/*
+ * This variable is accessible via /proc/scsi/sg/def_reserved_size . Each
+ * time sg_open() is called a sg_request of this size (or less if there is
+ * not enough memory) will be reserved for use by this file descriptor.
+ */
 static int def_reserved_size = -1; /* picks up init parameter */
 static int sg_allow_dio = SG_ALLOW_DIO_DEF;
 
 static int scatter_elem_sz = SG_SCATTER_SZ;
-static int scatter_elem_sz_prev = SG_SCATTER_SZ;
 
-#define SG_SECTOR_SZ 512
+#define SG_DEF_SECTOR_SZ 512
 
 static int sg_add_device(struct d

[PATCH 16/18] sg: expand sg_comm_wr_t

2019-06-16 Thread Douglas Gilbert
The internal struct sg_comm_wr_t was added when the number of
arguments to sg_common_write() became excessive. Expand this idea
so multiple calls to sg_fetch_cmnd() can be deferred until a
scsi_request object is ready to receive the command. This saves
a 252 byte stack allocation on every submit path. Prior to this
and a few other changes, the kernel infrastructure was warning
about excessive stack usage.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 178 --
 1 file changed, 92 insertions(+), 86 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a244ea7d436f..f0c4176551d8 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -250,35 +250,37 @@ struct sg_device { /* holds the state of each scsi 
generic device */
 
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
+   int cmd_len;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
union { /* selector is frq_bm.SG_FRQ_IS_V4I */
struct sg_io_hdr *h3p;
struct sg_io_v4 *h4p;
};
-   u8 *cmnd;
+   struct sg_fd *sfp;
+   struct file *filp;
+   const u8 __user *u_cmdp;
 };
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
-static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   struct sg_io_v4 *h4p, int dxfer_dir);
+static int sg_start_req(struct sg_request *srp, struct sg_comm_wr_t *cwrp,
+   int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
 static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
struct sg_io_hdr *hp, bool sync,
struct sg_request **o_srp);
-static struct sg_request *sg_common_write(struct sg_fd *sfp,
- struct sg_comm_wr_t *cwp);
+static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_sgat(struct sg_request *srp);
 static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
 static void sg_remove_sfp(struct kref *);
 static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id);
-static struct sg_request *sg_add_request(struct sg_fd *sfp, int dxfr_len,
-struct sg_comm_wr_t *cwrp);
+static struct sg_request *sg_add_request(struct sg_comm_wr_t *cwrp,
+int dxfr_len);
 static void sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
 static struct sg_device *sg_get_dev(int min_dev);
 static void sg_device_destroy(struct kref *kref);
@@ -576,7 +578,6 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
struct sg_device *sdp;
struct sg_fd *sfp;
struct sg_request *srp;
-   u8 cmnd[SG_MAX_CDB_SIZE];
struct sg_header ov2hdr;
struct sg_io_hdr v3hdr;
struct sg_header *ohp = &ov2hdr;
@@ -661,9 +662,6 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
h3p->flags = input_size; /* structure abuse ... */
h3p->pack_id = ohp->pack_id;
h3p->usr_ptr = NULL;
-   cmnd[0] = opcode;
-   if (__copy_from_user(cmnd + 1, p + 1, cmd_size - 1))
-   return -EFAULT;
/*
 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
 * but it is possible that the app intended SG_DXFER_TO_DEV, because
@@ -674,13 +672,16 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
"%s: data in/out %d/%d bytes for SCSI command 0x%x-- 
guessing data in;\n"
"   program %s not setting count and/or reply_len 
properly\n",
__func__, ohp->reply_len - (int)SZ_SG_HEADER,
-   input_size, (unsigned int)cmnd[0], current->comm);
+   input_size, (unsigned int)opcode, current->comm);
}
-   cwr.frq_bm[0] = 0;  /* initial state clear for all req flags */
+   memset(&cwr, 0, sizeof(cwr));
cwr.h3p = h3p;
cwr.timeout = sfp->timeout;
-   cwr.cmnd = cmnd;
-   srp = sg_common_write(sfp, &cwr);
+   cwr.cmd_len = cmd_size;
+   cwr.filp = filp;
+   cwr.sfp = sfp;
+   cwr.u_cmdp = p;
+   srp = sg_common_write(&cwr);
return (IS_ERR(srp)) ? PTR_ERR(srp) : (int)count;
 }
 
@@ -709,11 +710,9 @@ static int
 sg_v3_submit(struct file *filp, struct sg_fd *sfp, struct sg_io_hdr *hp,
 bool 

Re: [PATCH 2/3] fcoe: avoid memset across pointer boundaries

2019-07-22 Thread Douglas Gilbert

On 2019-07-22 7:50 a.m., Christoph Hellwig wrote:

On Mon, Jul 22, 2019 at 08:22:30AM +0200, Hannes Reinecke wrote:

Gcc-9 complains for a memset across pointer boundaries, which happens
as the code tries to allocate a flexible array on the stack.
Turns out we cannot do this without relying on gcc-isms, so
with this patch we'll embed the fc_rport_priv structure into
fcoe_rport, can use the normal 'container_of' outcast, and
will only have to do a memset over one structure.


This looks mostly good, but:

I think the subject and changelog are a bit odd.  What you do here
is to change that way how the private data is allocated by embeddeding
the fc_rport_priv structure into the private data, so that should be
the focus of the description.  That this was triggered by the memset
warning might be worth mentioning, but probably only after explaining
what you did.


@@ -2738,10 +2736,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
  {
struct fip_header *fiph;
enum fip_vn2vn_subcode sub;
-   struct {
-   struct fc_rport_priv rdata;
-   struct fcoe_rport frport;
-   } buf;
+   struct fcoe_rport buf;


Wouldn't rport or frport be a better name for this variable?


fiph = (struct fip_header *)skb->data;
@@ -2757,7 +2752,8 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
goto drop;
}
  
-	rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);

+   memset(&buf, 0, sizeof(buf));


Instead of the memset you could do an initialization at declaration
time:

struct fcoe_rport rport = { };


https://en.cppreference.com/w/c/language/struct_initialization

"When initializing an object of struct or union type, the initializer must
be a non-empty, brace-enclosed, comma-separated list of initializers for
the members:"

Hmmm, "non-empty", is that a GNU extension?

However it is good C++11, so if that is where we a moving, great.

Doug Gilbert


-   struct {
-   struct fc_rport_priv rdata;
-   struct fcoe_rport frport;
-   } buf;
+   struct fcoe_rport buf;
int rc;
  
  	fiph = (struct fip_header *)skb->data;

sub = fiph->fip_subcode;
-   rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
+   memset(&buf, 0, sizeof(buf));


Same two comments apply here.





Re: [PATCH 14/19] sg: tag and more_async

2019-07-23 Thread Douglas Gilbert

On 2019-07-23 2:11 p.m., kbuild test robot wrote:

Hi Douglas,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on v5.3-rc1 next-20190723]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]


Hi,
Well yes, you seem to be using the wrong git tree, or at least the
wrong patchset. From the subject line above, I match that with a
patchset sent to the linux-scsi list on 20190524. It contained both
a rework of the existing driver plus new features outlined here:
  http://sg.danny.cz/sg/sg_v40.html

It was suggested that I break that patchset in two, the first one
being the existing driver rework. That patchset was sent to the
linux-scsi list on 20190616 commencing with this subject line:
"[PATCH 00/18] sg: add v4 interface". To date I have had no feedback
for the later patchset so I have no idea whether the kbuild test
robot has checked it or not. It is curious why yesterday, 6 weeks
after the second patchset, robot messages start reappearing on a
superseded patchset sent two months ago. The reported problems
have already been dealt with (i.e. fixed).

Work (mainly testing) continues on the "new features" patchset which
I have structured on top of the "add v4 interface" patchset as patches
19 through 34. I see no point in sending a follow-on patchset with
new features until the patchset sent on 20190616 is accepted.

Doug Gilbert



[PATCH v2 07/18] sg: move header to uapi section

2019-07-26 Thread Douglas Gilbert
Move user interface part of scsi/sg.h into the new header file:
include/uapi/scsi/sg.h . Since scsi/sg.h includes the new header,
other code including scsi/sg.h should not be impacted.

Signed-off-by: Douglas Gilbert 
---
 include/scsi/sg.h  | 268 ++---
 include/uapi/scsi/sg.h | 329 +
 2 files changed, 338 insertions(+), 259 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index f91bcca604e4..46fc7cbffd78 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -4,271 +4,21 @@
 
 #include 
 
-/*
- * History:
- *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com), to allow user
- *   process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
- *
- * Original driver (sg.h):
- *   Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
- * Copyright (C) 1998 - 2014 Douglas Gilbert
- *
- *  Version: 3.5.36 (20140603)
- *  This version is for 2.6 and 3 series kernels.
- *
- * Documentation
- * =
- * A web site for the SG device driver can be found at:
- * http://sg.danny.cz/sg  [alternatively check the MAINTAINERS file]
- * The documentation for the sg version 3 driver can be found at:
- * http://sg.danny.cz/sg/p/sg_v3_ho.html
- * Also see: /Documentation/scsi/scsi-generic.txt
- *
- * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html
- */
-
 #ifdef __KERNEL__
 extern int sg_big_buff; /* for sysctl */
 #endif
 
+/*
+ * In version 3.9.01 of the sg driver, this file was spilt in two, with the
+ * bulk of the user space interface being placed in the file being included
+ * in the following line.
+ */
+#include 
 
-typedef struct sg_iovec /* same structure as used by readv() Linux system */
-{   /* call. It defines one scatter-gather element. */
-void __user *iov_base;  /* Starting address  */
-size_t iov_len; /* Length in bytes  */
-} sg_iovec_t;
-
-
-typedef struct sg_io_hdr
-{
-int interface_id;   /* [i] 'S' for SCSI generic (required) */
-int dxfer_direction;/* [i] data transfer direction  */
-unsigned char cmd_len;  /* [i] SCSI command length */
-unsigned char mx_sb_len;/* [i] max length to write to sbp */
-unsigned short iovec_count; /* [i] 0 implies no scatter gather */
-unsigned int dxfer_len; /* [i] byte count of data transfer */
-void __user *dxferp;   /* [i], [*io] points to data transfer memory
- or scatter gather list */
-unsigned char __user *cmdp; /* [i], [*i] points to command to perform */
-void __user *sbp;  /* [i], [*o] points to sense_buffer memory */
-unsigned int timeout;   /* [i] MAX_UINT->no timeout (unit: millisec) */
-unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */
-int pack_id;/* [i->o] unused internally (normally) */
-void __user * usr_ptr;  /* [i->o] unused internally */
-unsigned char status;   /* [o] scsi status */
-unsigned char masked_status;/* [o] shifted, masked scsi status */
-unsigned char msg_status;   /* [o] messaging level data (optional) */
-unsigned char sb_len_wr;/* [o] byte count actually written to sbp */
-unsigned short host_status; /* [o] errors from host adapter */
-unsigned short driver_status;/* [o] errors from software driver */
-int resid;  /* [o] dxfer_len - actual_transferred */
-unsigned int duration;  /* [o] time taken by cmd (unit: millisec) */
-unsigned int info;  /* [o] auxiliary information */
-} sg_io_hdr_t;  /* 64 bytes long (on i386) */
-
-#define SG_INTERFACE_ID_ORIG 'S'
-
-/* Use negative values to flag difference from original sg_header structure */
-#define SG_DXFER_NONE (-1)  /* e.g. a SCSI Test Unit Ready command */
-#define SG_DXFER_TO_DEV (-2)/* e.g. a SCSI WRITE command */
-#define SG_DXFER_FROM_DEV (-3)  /* e.g. a SCSI READ command */
-#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
-  additional property than during indirect
-  IO the user buffer is copied into the
-  kernel buffers before the transfer */
-#define SG_DXFER_UNKNOWN (-5)   /* Unknown data direction */
-
-/* following flag values can be "or"-ed together */
-#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
-#define SG_FLAG_UNUSED_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
-   /* command block (when <= SCSI_2) */
-#define SG_FLAG_MMAP_IO 4   /* request memory mapped IO */
-#define SG_FLAG_NO_DXFER 0x1 /* no transfer of kernel buffers to/from */
-   /* user space (debug indirect IO) */
-/* default

[PATCH v2 03/18] sg: sg_log and is_enabled

2019-07-26 Thread Douglas Gilbert
Replace SCSI_LOG_TIMEOUT macros with SG_LOG macros across the driver.
The definition of SG_LOG calls SCSI_LOG_TIMEOUT if given and derived
pointers are non-zero, calls pr_info otherwise. SG_LOGS additionally
prints the sg device name and the thread id. The thread id is very
useful, even in single threaded invocations because the driver not
only uses the invocer's thread but also uses work queues and the
main callback (i.e. sg_rq_end_io()) may hit any thread. Some
interesting cases arise when the callback hits its invocer's
thread.

SG_LOGS takes 48 bytes on the stack to build this printf format
string: "sg%u: tid=%d" whose size is clearly bounded above by
the maximum size of those two integers.
Protecting against the 'current' pointer being zero is for safety
and the case where the boot device is SCSI and the sg driver is
built into the kernel. Also when debugging, getting a message
from a compromised kernel can be very useful in pinpointing the
location of the failure.

The simple fact that the SG_LOG macro is shorter than
SCSI_LOG_TIMEOUT macro allow more error message "payload" per line.

Also replace #if and #ifdef conditional compilations with
the IS_ENABLED macro.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 252 +++---
 1 file changed, 125 insertions(+), 127 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6615777931f7..d14ba4a5441c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -57,6 +57,15 @@ static char *sg_version_date = "20190606";
 
 #define SG_MAX_DEVS 32768
 
+/* Comment out the following line to compile out SCSI_LOGGING stuff */
+#define SG_DEBUG 1
+
+#if !IS_ENABLED(SG_DEBUG)
+#if IS_ENABLED(DEBUG)  /* If SG_DEBUG not defined, check for DEBUG */
+#define SG_DEBUG DEBUG
+#endif
+#endif
+
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
  * than 16 bytes are "variable length" whose length is a multiple of 4
@@ -174,7 +183,7 @@ static ssize_t sg_new_write(struct sg_fd *sfp, struct file 
*file,
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
 static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
-int num_read_xfer);
+int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
 static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -187,14 +196,45 @@ static int sg_remove_request(struct sg_fd *sfp, struct 
sg_request *srp);
 static struct sg_device *sg_get_dev(int dev);
 static void sg_device_destroy(struct kref *kref);
 
-#define SZ_SG_HEADER sizeof(struct sg_header)
-#define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
-#define SZ_SG_IOVEC sizeof(sg_iovec_t)
-#define SZ_SG_REQ_INFO sizeof(sg_req_info_t)
+#define SZ_SG_HEADER ((int)sizeof(struct sg_header))   /* v1 and v2 header */
+#define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
+#define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
+
+/*
+ * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
+ * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
+ * information). All messages are logged as informational (KERN_INFO). In
+ * the unexpected situation where sfp or sdp is NULL the macro reverts to
+ * a pr_info and ignores SCSI_LOG_TIMEOUT and always prints to the log.
+ * Example: this invocation: 'scsi_logging_level -s -T 3' will print
+ * depth (aka level) 1 and 2 SG_LOG() messages.
+ */
+
+#define SG_PROC_DEBUG_SZ 8192
+
+#if IS_ENABLED(CONFIG_SCSI_LOGGING) && IS_ENABLED(SG_DEBUG)
+#define SG_LOG_BUFF_SZ 48
+
+#define SG_LOG(depth, sfp, fmt, a...)  \
+   do {\
+   char _b[SG_LOG_BUFF_SZ];\
+   int _tid = (current ? current->pid : -1);   \
+   struct sg_fd *_fp = sfp;\
+   struct sg_device *_sdp = _fp ? _fp->parentdp : NULL;\
+   \
+   if (likely(_sdp && _sdp->disk)) {   \
+   snprintf(_b, sizeof(_b), "sg%u: tid=%d",\
+_sdp->index, _tid);\
+   SCSI_LOG_TIMEOUT(depth, \
+sdev_prefix_printk(KERN_INFO,  \
+_sdp->device, _b, fmt, ##a));  \
+   } else  \
+

[PATCH v2 11/18] sg: replace rq array with lists

2019-07-26 Thread Douglas Gilbert
Remove the fixed size array of 16 request elements per file
descriptor and replace with two linked lists per file descriptor.
One list is for active commands, the other list is a free list.
sg_request objects are now kept, available for re-use, until
their owning file descriptor is closed. The sg_request deletions
are now in sg_remove_sfp_usercontext(). Each active sg_request
has associated block request and scsi_request objects which are
released much earlier; their lifetime is the same as it was in
the v3 sg driver. The lifetime of the bio is also the same (but
is stretched in a later patch).

Add an enum for request state (sg_rq_state) and collect
various flags into bit maps: one for requests (SG_FRQ_*) and
the other for file descriptors (SG_FFD_*). They join a
per sg_device bit map (SG_FDEV_*) added in an earlier
patch.

Prior to a new sg_request object being (re-)built, information
that will be placed in it uses a new struct sg_comm_wr_t
object.

Since the above changes touch almost every function and low
level structures, this patch is big. With so many changes, the
diff utility that generates the patch sometimes loses track.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 3035 +
 1 file changed, 1951 insertions(+), 1084 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 123d8516a9a0..00b8553e0038 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -72,7 +72,46 @@ static char *sg_version_date = "20190606";
  */
 #define SG_MAX_CDB_SIZE 252
 
+#define uptr64(val) ((void __user *)(uintptr_t)(val))
+#define cuptr64(val) ((const void __user *)(uintptr_t)(val))
+
+/* Following enum contains the states of sg_request::rq_st */
+enum sg_rq_state {
+   SG_RS_INACTIVE = 0, /* request not in use (e.g. on fl) */
+   SG_RS_INFLIGHT, /* active: cmd/req issued, no response yet */
+   SG_RS_AWAIT_RD, /* response received, awaiting read */
+   SG_RS_DONE_RD,  /* read is ongoing or done */
+   SG_RS_BUSY, /* temporary state should rarely be seen */
+};
+
+#define SG_TIME_UNIT_MS 0  /* milliseconds */
+#define SG_DEF_TIME_UNIT SG_TIME_UNIT_MS
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
+#define SG_FD_Q_AT_HEAD 0
+#define SG_DEFAULT_Q_AT SG_FD_Q_AT_HEAD /* for backward compatibility */
+#define SG_FL_MMAP_DIRECT (SG_FLAG_MMAP_IO | SG_FLAG_DIRECT_IO)
+
+/* Only take lower 4 bits of driver byte, all host byte and sense byte */
+#define SG_ML_RESULT_MSK 0x0fff00ff/* mid-level's 32 bit result value */
+
+#define SG_PACK_ID_WILDCARD (-1)
+
+#define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
+
+/* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
+#define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
+#define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
+#define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
+#define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
+#define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
+
+/* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
+#define SG_FFD_FORCE_PACKID0   /* receive only given pack_id/tag */
+#define SG_FFD_CMD_Q   1   /* clear: only 1 active req per fd */
+#define SG_FFD_KEEP_ORPHAN 2   /* policy for this fd */
+#define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
+#define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
 
 /* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
 #define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
@@ -80,19 +119,17 @@ static char *sg_version_date = "20190606";
 #define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
-/* N.B. This variable is readable and writeable via
-   /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
-   of this size (or less if there is not enough memory) will be reserved
-   for use by this file descriptor. [Deprecated usage: this variable is also
-   readable via /proc/sys/kernel/sg-big-buff if the sg driver is built into
-   the kernel (i.e. it is not a module).] */
+/*
+ * This variable is accessible via /proc/scsi/sg/def_reserved_size . Each
+ * time sg_open() is called a sg_request of this size (or less if there is
+ * not enough memory) will be reserved for use by this file descriptor.
+ */
 static int def_reserved_size = -1; /* picks up init parameter */
 static int sg_allow_dio = SG_ALLOW_DIO_DEF;
 
 static int scatter_elem_sz = SG_SCATTER_SZ;
-static int scatter_elem_sz_prev = SG_SCATTER_SZ;
 
-#define SG_SECTOR_SZ 512
+#define SG_DEF_SECTOR_SZ 512
 
 static int sg_add_device(struct d

[PATCH v2 10/18] sg: remove most access_ok functions

2019-07-26 Thread Douglas Gilbert
Since access_ok() has lost it direction (3rd) parameter there
seems to be no benefit in calling access_ok() before
__copy_{to|from}_user(). Simplify code by using the variant of
these functions that do not start with "__".

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 50 ---
 1 file changed, 17 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7e188ac2f182..123d8516a9a0 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -502,11 +502,9 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
if (res)
return res;
 
-   if (!access_ok(buf, count))
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
if (count < SZ_SG_HEADER)
return -EIO;
-   if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
+   if (copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
return -EFAULT;
if (old_hdr.reply_len < 0)
return sg_submit(sfp, filp, buf, count, blocking, false, false,
@@ -561,7 +559,7 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
hp->flags = input_size; /* structure abuse ... */
hp->pack_id = old_hdr.pack_id;
hp->usr_ptr = NULL;
-   if (__copy_from_user(cmnd, buf, cmd_size))
+   if (copy_from_user(cmnd, buf, cmd_size))
return -EFAULT;
/*
 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
@@ -607,8 +605,6 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
 
if (count < SZ_SG_IO_HDR)
return -EINVAL;
-   if (!access_ok(buf, count))
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
 
sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */
if (!(srp = sg_add_request(sfp))) {
@@ -617,7 +613,7 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
}
srp->sg_io_owned = sg_io_owned;
hp = &srp->header;
-   if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
+   if (copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -645,11 +641,7 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
sg_remove_request(sfp, srp);
return -EMSGSIZE;
}
-   if (!access_ok(hp->cmdp, hp->cmd_len)) {
-   sg_remove_request(sfp, srp);
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
-   }
-   if (__copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
+   if (copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -829,13 +821,11 @@ sg_read(struct file *filp, char __user *buf, size_t 
count, loff_t *ppos)
if (ret)
return ret;
 
-   if (!access_ok(buf, count))
-   return -EFAULT;
if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
if (!old_hdr)
return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
+   if (copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
ret = -EFAULT;
goto free_old_hdr;
}
@@ -848,8 +838,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
ret = -ENOMEM;
goto free_old_hdr;
}
-   ret = __copy_from_user
-   (new_hdr, buf, SZ_SG_IO_HDR);
+   ret = copy_from_user(new_hdr, buf,
+SZ_SG_IO_HDR);
req_pack_id = new_hdr->pack_id;
kfree(new_hdr);
if (ret) {
@@ -942,7 +932,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
 
/* Now copy the result back to the user buffer.  */
if (count >= SZ_SG_HEADER) {
-   if (__copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
+   if (copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
ret = -EFAULT;
goto free_old_hdr;
}
@@ -1032,8 +1022,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
result = sg_allow_if_err_recovery(sdp, false);
if (result)
return result;
-   if (!access_ok(p, SZ_SG_IO_HDR

[PATCH v2 08/18] sg: speed sg_poll and sg_get_num_waiting

2019-07-26 Thread Douglas Gilbert
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 
---
 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

[PATCH v2 09/18] sg: sg_allow_if_err_recovery and renames

2019-07-26 Thread Douglas Gilbert
Add sg_allow_if_err_recover() to do checks common to several entry
points. Replace retval with either res or ret. Rename
sg_finish_rem_req() to sg_finish_scsi_blk_rq(). Rename
sg_new_write() to sg_submit(). Other cleanups triggered by
checkpatch.pl .

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 245 +-
 1 file changed, 133 insertions(+), 112 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7c9c56bda7ba..7e188ac2f182 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -68,7 +68,7 @@ static char *sg_version_date = "20190606";
 
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
- * than 16 bytes are "variable length" whose length is a multiple of 4
+ * than 16 bytes are "variable length" whose length is a multiple of 4, so:
  */
 #define SG_MAX_CDB_SIZE 252
 
@@ -178,16 +178,16 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd);
-static int sg_finish_rem_req(struct sg_request *srp);
+static int sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_build_indirect(struct sg_scatter_hold *schp, struct sg_fd *sfp,
 int buff_size);
-static ssize_t sg_new_write(struct sg_fd *sfp, struct file *file,
-   const char __user *buf, size_t count, int blocking,
-   int read_only, int sg_io_owned,
-   struct sg_request **o_srp);
+static ssize_t sg_submit(struct sg_fd *sfp, struct file *filp,
+const char __user *buf, size_t count, bool blocking,
+bool read_only, bool sg_io_owned,
+struct sg_request **o_srp);
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
-static int sg_rd_append(struct sg_request *srp, char __user *outp,
+static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
@@ -275,37 +275,60 @@ sg_check_file_access(struct file *filp, const char 
*caller)
 static int
 sg_wait_open_event(struct sg_device *sdp, bool o_excl)
 {
-   int retval = 0;
+   int res = 0;
 
if (o_excl) {
while (atomic_read(&sdp->open_cnt) > 0) {
mutex_unlock(&sdp->open_rel_lock);
-   retval = wait_event_interruptible(sdp->open_wait,
-   (SG_IS_DETACHING(sdp) ||
-atomic_read(&sdp->open_cnt) == 0));
+   res = wait_event_interruptible
+   (sdp->open_wait,
+(SG_IS_DETACHING(sdp) ||
+ atomic_read(&sdp->open_cnt) == 0));
mutex_lock(&sdp->open_rel_lock);
 
-   if (retval) /* -ERESTARTSYS */
-   return retval;
+   if (res) /* -ERESTARTSYS */
+   return res;
if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
-   retval = wait_event_interruptible(sdp->open_wait,
-   (SG_IS_DETACHING(sdp) ||
-!SG_HAVE_EXCLUDE(sdp)));
+   res = wait_event_interruptible
+   (sdp->open_wait,
+(SG_IS_DETACHING(sdp) ||
+ !SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock);
 
-   if (retval) /* -ERESTARTSYS */
-   return retval;
+   if (res) /* -ERESTARTSYS */
+   return res;
if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
}
 
-   return retval;
+   return res;
+}
+
+/*
+ * scsi_block_when_processing_errors() returns 0 when dev was taken offline by
+ * error recovery, 1 otherwise (i.e. okay). Even if in error recovery, let
+ * user continue if O_NONBLOCK set. Permits SCSI commands to be issued during
+ * error recovery. Tread carefully.
+ * Ret

[PATCH v2 16/18] sg: expand sg_comm_wr_t

2019-07-26 Thread Douglas Gilbert
The internal struct sg_comm_wr_t was added when the number of
arguments to sg_common_write() became excessive. Expand this idea
so multiple calls to sg_fetch_cmnd() can be deferred until a
scsi_request object is ready to receive the command. This saves
a 252 byte stack allocation on every submit path. Prior to this
and a few other changes, the kernel infrastructure was warning
about excessive stack usage.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 178 --
 1 file changed, 92 insertions(+), 86 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 8dc94ac2206a..d7ba0c27efdb 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -250,35 +250,37 @@ struct sg_device { /* holds the state of each scsi 
generic device */
 
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
+   int cmd_len;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
union { /* selector is frq_bm.SG_FRQ_IS_V4I */
struct sg_io_hdr *h3p;
struct sg_io_v4 *h4p;
};
-   u8 *cmnd;
+   struct sg_fd *sfp;
+   struct file *filp;
+   const u8 __user *u_cmdp;
 };
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
-static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   struct sg_io_v4 *h4p, int dxfer_dir);
+static int sg_start_req(struct sg_request *srp, struct sg_comm_wr_t *cwrp,
+   int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
 static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
struct sg_io_hdr *hp, bool sync,
struct sg_request **o_srp);
-static struct sg_request *sg_common_write(struct sg_fd *sfp,
- struct sg_comm_wr_t *cwp);
+static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_sgat(struct sg_request *srp);
 static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
 static void sg_remove_sfp(struct kref *);
 static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id);
-static struct sg_request *sg_add_request(struct sg_fd *sfp, int dxfr_len,
-struct sg_comm_wr_t *cwrp);
+static struct sg_request *sg_add_request(struct sg_comm_wr_t *cwrp,
+int dxfr_len);
 static void sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
 static struct sg_device *sg_get_dev(int min_dev);
 static void sg_device_destroy(struct kref *kref);
@@ -576,7 +578,6 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
struct sg_device *sdp;
struct sg_fd *sfp;
struct sg_request *srp;
-   u8 cmnd[SG_MAX_CDB_SIZE];
struct sg_header ov2hdr;
struct sg_io_hdr v3hdr;
struct sg_header *ohp = &ov2hdr;
@@ -661,9 +662,6 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
h3p->flags = input_size; /* structure abuse ... */
h3p->pack_id = ohp->pack_id;
h3p->usr_ptr = NULL;
-   cmnd[0] = opcode;
-   if (__copy_from_user(cmnd + 1, p + 1, cmd_size - 1))
-   return -EFAULT;
/*
 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
 * but it is possible that the app intended SG_DXFER_TO_DEV, because
@@ -674,13 +672,16 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
"%s: data in/out %d/%d bytes for SCSI command 0x%x-- 
guessing data in;\n"
"   program %s not setting count and/or reply_len 
properly\n",
__func__, ohp->reply_len - (int)SZ_SG_HEADER,
-   input_size, (unsigned int)cmnd[0], current->comm);
+   input_size, (unsigned int)opcode, current->comm);
}
-   cwr.frq_bm[0] = 0;  /* initial state clear for all req flags */
+   memset(&cwr, 0, sizeof(cwr));
cwr.h3p = h3p;
cwr.timeout = sfp->timeout;
-   cwr.cmnd = cmnd;
-   srp = sg_common_write(sfp, &cwr);
+   cwr.cmd_len = cmd_size;
+   cwr.filp = filp;
+   cwr.sfp = sfp;
+   cwr.u_cmdp = p;
+   srp = sg_common_write(&cwr);
return (IS_ERR(srp)) ? PTR_ERR(srp) : (int)count;
 }
 
@@ -709,11 +710,9 @@ static int
 sg_v3_submit(struct file *filp, struct sg_fd *sfp, struct sg_io_hdr *hp,
 bool 

[PATCH v2 00/18] sg: add v4 interface

2019-07-26 Thread Douglas Gilbert
This patchset extends the SCSI generic (sg) driver found in lk 5.3 .
The sg driver has a version number which is visible via
ioctl(SG_GET_VERSION_NUM) and is bumped from 3.5.36 to 4.0.03 by this
patchset. The additions and changes are described in some detail in
this long webpage:
http://sg.danny.cz/sg/sg_v40.html

Most new features described in the above webpage are not implemented
in this patchset. Features that are not included are file descriptor
sharing, request sharing, multiple requests (in one invocation) and
the extended ioctl(). A later patchset may add those features. The
SG_IOSUMIT, SG_IOSUBMIT_V3, SG_IORECEIVE and SG_IORECEIVE_V3 ioctls
are added in this patchset.

Testing:
The sg3_utils package has several extensions in sg3_utils-1.45 beta
(revision 829 (see http://sg.danny.cz/sg)) to support and test the
version 4 sg driver presented in this patchset.
The new and revised testing utilities are outlined on the
same webpage as above in the second half of the section
titled: "15 Downloads and testing".

This patchset is against Martin Petersen's 5.4/scsi-queue branch.
To apply this patchset to lk 5.2 and earlier, the ktime_get_boottime_ns()
call needs to be changed back to ktime_get_boot_ns().

Changes since v1 (sent to linux-scsi list on 20190616):
  - change ktime_get_boot_ns() to ktime_get_boottime_ns() to reflect
kernel API change first seen in lk 5.3.0-rc1


Douglas Gilbert (18):
  sg: move functions around
  sg: remove typedefs, type+formatting cleanup
  sg: sg_log and is_enabled
  sg: rework sg_poll(), minor changes
  sg: bitops in sg_device
  sg: make open count an atomic
  sg: move header to uapi section
  sg: speed sg_poll and sg_get_num_waiting
  sg: sg_allow_if_err_recovery and renames
  sg: remove most access_ok functions
  sg: replace rq array with lists
  sg: sense buffer rework
  sg: add sg v4 interface support
  sg: rework debug info
  sg: add 8 byte SCSI LUN to sg_scsi_id
  sg: expand sg_comm_wr_t
  sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls
  sg: bump version to 4.0.03

 drivers/scsi/sg.c  | 4373 ++--
 include/scsi/sg.h  |  268 +--
 include/uapi/scsi/sg.h |  373 
 3 files changed, 3269 insertions(+), 1745 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

-- 
2.17.1



[PATCH v2 01/18] sg: move functions around

2019-07-26 Thread Douglas Gilbert
Move main entry point functions around so submission code comes
before completion code. Prior to this, the driver used the
traditional open(), close(), read(), write(), ioctl() ordering
however in this case that places completion code (i.e.
sg_read()) before submission code (i.e. sg_write()). The main
driver entry points are considered to be those named in struct
file_operations sg_fops' definition.

Helper functions are often placed above their caller to reduce
the number of forward function declarations needed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 499 --
 1 file changed, 261 insertions(+), 238 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index cce757506383..9f1587761d86 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -8,11 +8,12 @@
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
  * Version 2 and 3 extensions to driver:
- *Copyright (C) 1998 - 2014 Douglas Gilbert
+ *Copyright (C) 1998 - 2019 Douglas Gilbert
  */
 
-static int sg_version_num = 30536; /* 2 digits for each component */
-#define SG_VERSION_STR "3.5.36"
+static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
+#define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
+static char *sg_version_date = "20190606";
 
 /*
  *  D. P. Gilbert (dgilb...@interlog.com), notes:
@@ -47,6 +48,7 @@ static int sg_version_num = 30536;/* 2 digits for each 
component */
 #include 
 #include 
 #include  /* for sg_check_file_access() */
+#include 
 
 #include "scsi.h"
 #include 
@@ -57,12 +59,6 @@ static int sg_version_num = 30536;   /* 2 digits for each 
component */
 
 #include "scsi_logging.h"
 
-#ifdef CONFIG_SCSI_PROC_FS
-#include 
-static char *sg_version_date = "20140603";
-
-static int sg_proc_init(void);
-#endif
 
 #define SG_ALLOW_DIO_DEF 0
 
@@ -173,11 +169,11 @@ typedef struct sg_device { /* holds the state of each 
scsi generic device */
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
+/* Declarations of other static functions used before they are defined */
+static int sg_proc_init(void);
 static int sg_start_req(Sg_request *srp, unsigned char *cmd);
 static int sg_finish_rem_req(Sg_request * srp);
 static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int 
buff_size);
-static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
-  Sg_request * srp);
 static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
const char __user *buf, size_t count, int blocking,
int read_only, int sg_io_owned, Sg_request **o_srp);
@@ -190,7 +186,6 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, 
int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
 static Sg_fd *sg_add_sfp(Sg_device * sdp);
 static void sg_remove_sfp(struct kref *);
-static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static Sg_device *sg_get_dev(int dev);
@@ -232,16 +227,6 @@ static int sg_check_file_access(struct file *filp, const 
char *caller)
return 0;
 }
 
-static int sg_allow_access(struct file *filp, unsigned char *cmd)
-{
-   struct sg_fd *sfp = filp->private_data;
-
-   if (sfp->parentdp->device->type == TYPE_SCANNER)
-   return 0;
-
-   return blk_verify_command(cmd, filp->f_mode);
-}
-
 static int
 open_wait(Sg_device *sdp, int flags)
 {
@@ -405,200 +390,12 @@ sg_release(struct inode *inode, struct file *filp)
return 0;
 }
 
-static ssize_t
-sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
-   Sg_device *sdp;
-   Sg_fd *sfp;
-   Sg_request *srp;
-   int req_pack_id = -1;
-   sg_io_hdr_t *hp;
-   struct sg_header *old_hdr = NULL;
-   int retval = 0;
-
-   /*
-* This could cause a response to be stranded. Close the associated
-* file descriptor to free up any resources being held.
-*/
-   retval = sg_check_file_access(filp, __func__);
-   if (retval)
-   return retval;
-
-   if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
-   return -ENXIO;
-   SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
- "sg_read: count=%d\n", (int) count));
-
-   if (!access_ok(buf, count))
-   return -EFAULT;
-   if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
-   old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
-   if (!old_hdr)
-   return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
-   retval = -E

[PATCH v2 05/18] sg: bitops in sg_device

2019-07-26 Thread Douglas Gilbert
Introduce bitops in sg_device to replace an atomic, a bool and a
char. That char (sgdebug) had been reduced to only two states.
Add some associated macros to make the code a little clearer.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 104 +++---
 1 file changed, 53 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9aa1b1030033..97ce84f0c51b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -74,6 +74,11 @@ static char *sg_version_date = "20190606";
 
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
 
+/* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
+#define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
+#define SG_FDEV_DETACHING  1   /* may be unexpected device removal */
+#define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
+
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
 /* N.B. This variable is readable and writeable via
/proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
@@ -155,14 +160,12 @@ 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 */
struct mutex open_rel_lock; /* held when in open() or release() */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
-   u32 index;  /* device index number */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   atomic_t detaching; /* 0->device usable, 1->device detaching */
-   bool exclude;   /* 1->open(O_EXCL) succeeded and is active */
+   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   u32 index;  /* device index number */
int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
-   char sgdebug;   /* 0->off, 1->sense, 9->dump dev, 10-> all devs 
*/
+   unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
struct kref d_ref;
@@ -200,6 +203,9 @@ static void sg_device_destroy(struct kref *kref);
 #define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
 #define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
 
+#define SG_IS_DETACHING(sdp) test_bit(SG_FDEV_DETACHING, (sdp)->fdev_bm)
+#define SG_HAVE_EXCLUDE(sdp) test_bit(SG_FDEV_EXCLUDE, (sdp)->fdev_bm)
+
 /*
  * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
  * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
@@ -273,26 +279,26 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
while (sdp->open_cnt > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
+   (SG_IS_DETACHING(sdp) ||
 !sdp->open_cnt));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
-   while (sdp->exclude) {
+   while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
-!sdp->exclude));
+   (SG_IS_DETACHING(sdp) ||
+!SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
}
@@ -354,7 +360,7 @@ sg_open(struct inode *inode, struct file *filp)
goto error_mutex_locked;
}
} else {
-   if (sdp->exclude) {
+   if (SG_HAVE_EXCLUDE(sdp)) {
retval = -EBUSY;
goto error_mutex_locked;
}
@@ -367,10 +373,10 @@ sg_open(struct inode *in

[PATCH v2 02/18] sg: remove typedefs, type+formatting cleanup

2019-07-26 Thread Douglas Gilbert
Typedefs for structure types are discouraged so those structures
that are private to the driver have had their typedefs removed.

This also means that most "camel" type variable names (i.e. mixed
case) have been removed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 394 ++
 1 file changed, 219 insertions(+), 175 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9f1587761d86..6615777931f7 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3,7 +3,7 @@
  *  History:
  *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com),
  *   to allow user process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
+ *  Development Sponsored by Killy Corp. NY NY   [1992 ??]
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
@@ -15,13 +15,6 @@ static int sg_version_num = 30901;  /* [x]xyyzz where [x] 
empty when x=0 */
 #define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
 static char *sg_version_date = "20190606";
 
-/*
- *  D. P. Gilbert (dgilb...@interlog.com), notes:
- *  - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
- *the kernel/module needs to be built with CONFIG_SCSI_LOGGING
- *(otherwise the macros compile to empty statements).
- *
- */
 #include 
 
 #include 
@@ -91,33 +84,32 @@ static int sg_add_device(struct device *, struct 
class_interface *);
 static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
-static DEFINE_RWLOCK(sg_index_lock);   /* Also used to lock
-  file descriptor list 
for device */
+static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock fd list for device */
 
 static struct class_interface sg_interface = {
.add_dev= sg_add_device,
.remove_dev = sg_remove_device,
 };
 
-typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info 
*/
-   unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
-   unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */
-   unsigned bufflen;   /* Size of (aggregate) data buffer */
+struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+   u16 k_use_sg; /* Count of kernel scatter-gather pieces */
+   unsigned int sglist_len; /* size of malloc'd scatter-gather list ++ */
+   unsigned int bufflen;   /* Size of (aggregate) data buffer */
struct page **pages;
int page_order;
char dio_in_use;/* 0->indirect IO (or mmap), 1->dio */
-   unsigned char cmd_opcode; /* first byte of command */
-} Sg_scatter_hold;
+   u8 cmd_opcode;  /* first byte of command */
+};
 
 struct sg_device;  /* forward declarations */
 struct sg_fd;
 
-typedef struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
+struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
struct list_head entry; /* list entry */
struct sg_fd *parentfp; /* NULL -> not in use */
-   Sg_scatter_hold data;   /* hold buffer, perhaps scatter list */
+   struct sg_scatter_hold data;/* hold buffer, perhaps scatter list */
sg_io_hdr_t header; /* scsi command+info, see  */
-   unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
+   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
char res_used;  /* 1 -> using reserve buffer, 0 -> not ... */
char orphan;/* 1 -> drop on sight, 0 -> normal */
char sg_io_owned;   /* 1 -> packet belongs to SG_IO */
@@ -126,9 +118,9 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests 
outstanding per file */
struct request *rq;
struct bio *bio;
struct execute_work ew;
-} Sg_request;
+};
 
-typedef struct sg_fd { /* holds the state of a file descriptor */
+struct sg_fd { /* holds the state of a file descriptor */
struct list_head sfd_siblings;  /* protected by device's sfd_lock */
struct sg_device *parentdp; /* owning device */
wait_queue_head_t read_wait;/* queue read until command done */
@@ -136,21 +128,21 @@ typedef 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 */
-   Sg_scatter_hold reserve;/* buffer held for this file descriptor 
*/
+   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 */
-   Sg_request req_arr[SG_MAX_QUEUE];   /* used as singly-lin

[PATCH v2 04/18] sg: rework sg_poll(), minor changes

2019-07-26 Thread Douglas Gilbert
Re-arrange code in sg_poll(). Rename sg_read_oxfer() to
sg_rd_append(). In sg_start_req() rename rw to r0w.
Plus associated changes demanded by checkpatch.pl

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 65 ++-
 1 file changed, 30 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d14ba4a5441c..9aa1b1030033 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -177,13 +177,13 @@ static int sg_finish_rem_req(struct sg_request *srp);
 static int sg_build_indirect(struct sg_scatter_hold *schp, struct sg_fd *sfp,
 int buff_size);
 static ssize_t sg_new_write(struct sg_fd *sfp, struct file *file,
-   const char __user *buf, size_t count, int blocking,
-   int read_only, int sg_io_owned,
-   struct sg_request **o_srp);
+   const char __user *buf, size_t count, int blocking,
+   int read_only, int sg_io_owned,
+   struct sg_request **o_srp);
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
-static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
-int num_xfer);
+static int sg_rd_append(struct sg_request *srp, char __user *outp,
+   int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
 static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -918,7 +918,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
if (count > old_hdr->reply_len)
count = old_hdr->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_read_oxfer(srp, buf, count - SZ_SG_HEADER)) {
+   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER)) {
retval = -EFAULT;
goto free_old_hdr;
}
@@ -1253,38 +1253,34 @@ sg_compat_ioctl(struct file *filp, unsigned int cmd_in, 
unsigned long arg)
 static __poll_t
 sg_poll(struct file *filp, poll_table * wait)
 {
-   __poll_t res = 0;
-   struct sg_device *sdp;
-   struct sg_fd *sfp;
+   __poll_t p_res = 0;
+   struct sg_fd *sfp = filp->private_data;
struct sg_request *srp;
int count = 0;
unsigned long iflags;
 
-   sfp = filp->private_data;
if (!sfp)
return EPOLLERR;
-   sdp = sfp->parentdp;
-   if (!sdp)
-   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 ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
-   res = EPOLLIN | EPOLLRDNORM;
+   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(&sdp->detaching))
-   res |= EPOLLHUP;
-   else if (!sfp->cmd_q) {
-   if (0 == count)
-   res |= EPOLLOUT | EPOLLWRNORM;
-   } else if (count < SG_MAX_QUEUE)
-   res |= EPOLLOUT | EPOLLWRNORM;
-   SG_LOG(3, sfp, "%s: res=0x%x\n", __func__, (__force u32)res);
-   return res;
+   if (sfp->parentdp && atomic_read(&sfp->parentdp->detaching)) {
+   p_res |= EPOLLHUP;
+   } else if (!sfp->cmd_q) {
+   if (count == 0)
+   p_res |= EPOLLOUT | EPOLLWRNORM;
+   } else if (count < SG_MAX_QUEUE) {
+   p_res |= EPOLLOUT | EPOLLWRNORM;
+   }
+   SG_LOG(3, sfp, "%s: p_res=0x%x\n", __func__, (__force u32)p_res);
+   return p_res;
 }
 
 static int
@@ -1801,7 +1797,7 @@ sg_start_req(struct sg_request *srp, u8 *cmd)
struct sg_scatter_hold *rsv_schp = &sfp->reserve;
struct request_queue *q = sfp->parentdp->device->request_queue;
struct rq_map_data *md, map_data;
-   int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
+   int r0w = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
u8 *long_cmdp = NULL;
 
if (hp->cmd_len > BLK_MAX_CDB) {
@@ -1811,7 +1807,7 @@ sg_start_req(struct sg_request *srp, u8 *cmd)
SG_LOG(5, sfp, "%s: long_cmdp=0x%p ++\n", __func__, long_cmdp);
}
SG_LOG(4, sfp, "%s: dxfer_len=%d

[PATCH v2 12/18] sg: sense buffer rework

2019-07-26 Thread Douglas Gilbert
The biggest single item in the sg_request object is the sense
buffer array which is SCSI_SENSE_BUFFERSIZE bytes long. That
constant started out at 18 bytes 20 years ago and is 96 bytes
now and might grow in the future. On the other hand the sense
buffer is only used by a small number of SCSI commands: those
that fail and those that want to return more information
other than a SCSI status of GOOD.

Allocate sense buffer as needed on the heap and delete as soon as
possible.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 47 +++
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 00b8553e0038..4d6635af7da7 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -176,7 +176,6 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
-   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -188,6 +187,7 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
u8 cmd_opcode;  /* first byte of SCSI cdb */
u64 start_ns;   /* starting point of command duration calc */
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
+   u8 *sense_bp;   /* alloc-ed sense buffer, as needed */
struct sg_fd *parentfp; /* pointer to owning fd, even when on fl */
struct request *rq; /* released in sg_rq_end_io(), bio kept */
struct bio *bio;/* kept until this req -->SG_RS_INACTIVE */
@@ -845,18 +845,21 @@ sg_copy_sense(struct sg_request *srp)
(driver_byte(srp->rq_result) & DRIVER_SENSE)) {
int sb_len = min_t(int, SCSI_SENSE_BUFFERSIZE, srp->sense_len);
int mx_sb_len;
+   u8 *sbp = srp->sense_bp;
void __user *up;
 
+   srp->sense_bp = NULL;
up = (void __user *)srp->s_hdr3.sbp;
mx_sb_len = srp->s_hdr3.mx_sb_len;
-   if (up && mx_sb_len > 0) {
+   if (up && mx_sb_len > 0 && sbp) {
sb_len = min_t(int, sb_len, mx_sb_len);
/* Additional sense length field */
-   sb_len_wr = 8 + (int)srp->sense_b[7];
+   sb_len_wr = 8 + (int)sbp[7];
sb_len_wr = min_t(int, sb_len, sb_len_wr);
-   if (copy_to_user(up, srp->sense_b, sb_len_wr))
+   if (copy_to_user(up, sbp, sb_len_wr))
sb_len_wr = -EFAULT;
}
+   kfree(sbp);
}
return sb_len_wr;
 }
@@ -963,8 +966,9 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd *sfp,
h2p->driver_status = driver_byte(rq_result);
if ((CHECK_CONDITION & status_byte(rq_result)) ||
(DRIVER_SENSE & driver_byte(rq_result))) {
-   memcpy(h2p->sense_buffer, srp->sense_b,
-  sizeof(h2p->sense_buffer));
+   if (srp->sense_bp)
+   memcpy(h2p->sense_buffer, srp->sense_bp,
+  sizeof(h2p->sense_buffer));
}
switch (host_byte(rq_result)) {
/*
@@ -999,17 +1003,21 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd 
*sfp,
 
/* Now copy the result back to the user buffer.  */
if (count >= SZ_SG_HEADER) {
-   if (copy_to_user(buf, h2p, SZ_SG_HEADER))
-   return -EFAULT;
+   if (copy_to_user(buf, h2p, SZ_SG_HEADER)) {
+   res = -EFAULT;
+   goto fini;
+   }
buf += SZ_SG_HEADER;
if (count > h2p->reply_len)
count = h2p->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER))
-   return -EFAULT;
+   res = sg_rd_append(srp, buf, count - SZ_SG_HEADER);
+   if (res)
+   goto fini;
}
} else
res = (h2p->result == 0) ? 0 : -EIO;
+fini:
atomic_set(&srp->rq_st, SG_RS_DONE_RD);
sg_finish_scsi_blk_rq(srp);
sg_deact_request(sfp, srp);
@@ -1977,8 +1985,17 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
srp->duration = sg_calc_rq_dur(srp);
if (unlikely((srp->rq_result & SG_ML_RESULT_MSK) 

[PATCH v2 14/18] sg: rework debug info

2019-07-26 Thread Douglas Gilbert
Since the version 2 driver, the state of the driver can be found
with 'cat /proc/scsi/sg/debug'. As the driver becomes more
threaded and IO faster (e.g. scsi_debug with a command timer
of 5 microseconds), the existing state dump can become
misleading as the state can change during the "snapshot". The
new approach in this patch is to allocate a buffer of
SG_PROC_DEBUG_SZ bytes and use scnprintf() to populate it. Only
when the whole state is captured (or the buffer fills) is the
output to the caller's terminal performed. The previous
approach was line based: assemble a line of information and
then output it.

Locks are taken as required for short periods and should not
interfere with a disk IO intensive program. Operations
such as closing a sg file descriptor or removing a sg device
may be held up for a short while (microseconds).

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 238 +++---
 1 file changed, 160 insertions(+), 78 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index dd779931ada4..ab7112cd4af2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3740,115 +3740,197 @@ sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
return 0;
 }
 
-/* must be called while holding sg_index_lock */
-static void
-sg_proc_debug_helper(struct seq_file *s, struct sg_device *sdp)
+/* Writes debug info for one sg_request in obp buffer */
+static int
+sg_proc_debug_sreq(struct sg_request *srp, int to, char *obp, int len)
+   __must_hold(&srp->req_lck)
 {
-   int k;
+   bool is_v3v4, v4, is_dur;
+   int n = 0;
+   u32 dur;
+   enum sg_rq_state rq_st;
+   const char *cp;
+
+   if (len < 1)
+   return 0;
+   v4 = test_bit(SG_FRQ_IS_V4I, srp->frq_bm);
+   is_v3v4 = v4 ? true : (srp->s_hdr3.interface_id != '\0');
+   if (srp->parentfp->rsv_srp == srp)
+   cp = (is_v3v4 && (srp->rq_flags & SG_FLAG_MMAP_IO)) ?
+   " mmap>> " : " rsv>> ";
+   else
+   cp = (srp->rq_info & SG_INFO_DIRECT_IO_MASK) ?
+   " dio>> " : " ";
+   rq_st = atomic_read(&srp->rq_st);
+   dur = sg_get_dur(srp, &rq_st, &is_dur);
+   n += scnprintf(obp + n, len - n, "%s%s: dlen=%d/%d id=%d", cp,
+  sg_rq_st_str(rq_st, false), srp->sgat_h.dlen,
+  srp->sgat_h.buflen, (int)srp->pack_id);
+   if (is_dur) /* cmd/req has completed, waiting for ... */
+   n += scnprintf(obp + n, len - n, " dur=%ums", dur);
+   else if (dur < U32_MAX) /* in-flight or busy (so ongoing) */
+   n += scnprintf(obp + n, len - n, " t_o/elap=%us/%ums",
+  to / 1000, dur);
+   n += scnprintf(obp + n, len - n, " sgat=%d op=0x%02x\n",
+  srp->sgat_h.num_sgat, srp->cmd_opcode);
+   return n;
+}
+
+/* Writes debug info for one sg fd (including its sg requests) in obp buffer */
+static int
+sg_proc_debug_fd(struct sg_fd *fp, char *obp, int len)
+   __must_hold(&sfp->rq_list_lock)
+{
+   bool first_fl;
+   int n = 0;
+   int to;
struct sg_request *srp;
-   struct sg_fd *fp;
-   const char * cp;
-   unsigned int ms;
 
-   k = 0;
-   list_for_each_entry(fp, &sdp->sfds, sfd_entry) {
-   k++;
-   spin_lock(&fp->rq_list_lock); /* irqs already disabled */
-   seq_printf(s, "   FD(%d): timeout=%dms bufflen=%d "
-  "(res)sgat=%d low_dma=%d\n", k,
-  jiffies_to_msecs(fp->timeout),
-  fp->rsv_srp->sgat_h.buflen,
-  (int)fp->rsv_srp->sgat_h.num_sgat,
-  (int) sdp->device->host->unchecked_isa_dma);
-   seq_printf(s, "   cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
-  (int)test_bit(SG_FFD_CMD_Q, fp->ffd_bm),
-  (int)test_bit(SG_FFD_FORCE_PACKID, fp->ffd_bm),
-  (int)test_bit(SG_FFD_KEEP_ORPHAN, fp->ffd_bm));
-   seq_printf(s, "   submitted=%d waiting=%d\n",
-  atomic_read(&fp->submitted),
-  atomic_read(&fp->waiting));
-   list_for_each_entry(srp, &fp->rq_list, rq_entry) {
-   const struct sg_slice_hdr3 *sh3p = &srp->s_hdr3;
-   bool is_v3 = (sh3p->interface_id != '\0');
-   enum sg_rq_state rq_st = atomic_read(&srp->rq_st);
-
-   if (srp->parentfp->r

[PATCH v2 17/18] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls

2019-07-26 Thread Douglas Gilbert
Add ioctl(SG_IOSUBMIT_V3) and ioctl(SG_IORECEIVE_V3). These ioctls
are meant to be (almost) drop-in replacements for the write()/read()
async version 3 interface. They only accept the version 3 interface.

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
specifically the table in the section titled: "12 SG interface
support changes".

If sgv3 is a struct sg_io_hdr object, suitably configured, then
res = write(sg_fd, &sgv3, sizeof(sgv3));
and
res = ioctl(sg_fd, SG_IOSUBMIT_V3, &sgv3);
are equivalent. Dito for read() and ioctl(SG_IORECEIVE_V3).

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 75 ++
 include/uapi/scsi/sg.h |  6 
 2 files changed, 81 insertions(+)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d7ba0c27efdb..51e28913699e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -804,6 +804,24 @@ sg_ctl_iosubmit(struct file *filp, struct sg_fd *sfp, void 
__user *p)
return -EPERM;
 }
 
+static int
+sg_ctl_iosubmit_v3(struct file *filp, struct sg_fd *sfp, void __user *p)
+{
+   int res;
+   u8 hdr_store[SZ_SG_IO_V4];  /* max(v3interface, v4interface) */
+   struct sg_io_hdr *h3p = (struct sg_io_hdr *)hdr_store;
+   struct sg_device *sdp = sfp->parentdp;
+
+   res = sg_allow_if_err_recovery(sdp, (filp->f_flags & O_NONBLOCK));
+   if (unlikely(res))
+   return res;
+   if (copy_from_user(h3p, p, SZ_SG_IO_HDR))
+   return -EFAULT;
+   if (h3p->interface_id == 'S')
+   return sg_v3_submit(filp, sfp, h3p, false, NULL);
+   return -EPERM;
+}
+
 static void
 sg_execute_cmd(struct sg_fd *sfp, struct sg_request *srp)
 {
@@ -1168,6 +1186,57 @@ sg_ctl_ioreceive(struct file *filp, struct sg_fd *sfp, 
void __user *p)
return sg_v4_receive(sfp, srp, p, h4p);
 }
 
+/*
+ * Called when ioctl(SG_IORECEIVE_V3) received. Expects a v3 interface.
+ * Checks if O_NONBLOCK file flag given, if not checks given flags field
+ * to see if SGV4_FLAG_IMMED is set. Either of these implies non blocking.
+ * When non-blocking and there is no request waiting, yields EAGAIN;
+ * otherwise it waits.
+ */
+static int
+sg_ctl_ioreceive_v3(struct file *filp, struct sg_fd *sfp, void __user *p)
+{
+   bool non_block = !!(filp->f_flags & O_NONBLOCK);
+   int res;
+   int pack_id = SG_PACK_ID_WILDCARD;
+   u8 v3_holder[SZ_SG_IO_HDR];
+   struct sg_io_hdr *h3p = (struct sg_io_hdr *)v3_holder;
+   struct sg_device *sdp = sfp->parentdp;
+   struct sg_request *srp;
+
+   res = sg_allow_if_err_recovery(sdp, non_block);
+   if (unlikely(res))
+   return res;
+   /* Get first three 32 bit integers: guard, proto+subproto */
+   if (copy_from_user(h3p, p, SZ_SG_IO_HDR))
+   return -EFAULT;
+   /* for v3: interface_id=='S' (in a 32 bit int) */
+   if (h3p->interface_id != 'S')
+   return -EPERM;
+   if (h3p->flags & SGV4_FLAG_IMMED)
+   non_block = true;   /* set by either this or O_NONBLOCK */
+   SG_LOG(3, sfp, "%s: non_block(+IMMED)=%d\n", __func__, non_block);
+
+   if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm))
+   pack_id = h3p->pack_id;
+
+   srp = sg_find_srp_by_id(sfp, pack_id);
+   if (!srp) { /* nothing available so wait on packet or */
+   if (unlikely(SG_IS_DETACHING(sdp)))
+   return -ENODEV;
+   if (non_block)
+   return -EAGAIN;
+   res = wait_event_interruptible
+   (sfp->read_wait,
+sg_get_ready_srp(sfp, &srp, pack_id));
+   if (unlikely(SG_IS_DETACHING(sdp)))
+   return -ENODEV;
+   if (unlikely(res))
+   return res; /* signal --> -ERESTARTSYS */
+   }   /* now srp should be valid */
+   return sg_v3_receive(sfp, srp, p);
+}
+
 static int
 sg_rd_v1v2(void __user *buf, int count, struct sg_fd *sfp,
   struct sg_request *srp)
@@ -1726,9 +1795,15 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, 
unsigned long arg)
case SG_IOSUBMIT:
SG_LOG(3, sfp, "%s:SG_IOSUBMIT\n", __func__);
return sg_ctl_iosubmit(filp, sfp, p);
+   case SG_IOSUBMIT_V3:
+   SG_LOG(3, sfp, "%s:SG_IOSUBMIT_V3\n", __func__);
+   return sg_ctl_iosubmit_v3(filp, sfp, p);
case SG_IORECEIVE:
SG_LOG(3, sfp, "%s:SG_IORECEIVE\n", __func__);
return sg_ctl_ioreceive(filp, sfp, p);
+   case SG_IORECEIVE_V3:
+   SG_LOG(3, sfp, "%s:SG_IORECEIVE_V3\n", __func__);
+   return sg_ctl_ioreceive_v3(filp, sfp, p);
case SG_GET_SCSI_ID:
   

[PATCH v2 18/18] sg: bump version to 4.0.03

2019-07-26 Thread Douglas Gilbert
Now that the sg version 4 interface is supported:
  - with ioctl(SG_IO) for synchronous/blocking use
  - with ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async/non-blocking use
Plus new ioctl(SG_IOSUBMIT_V3) and ioctl(SG_IORECEIVE_V3)
potentially replace write() and read() for the sg
version 3 interface. Bump major driver version number
from 3 to 4.

The main new feature is the removal of the fixed 16 element
array of requests per file descriptor. It is replaced by
two lists: one for active (inflight) requests and a free
list. Also sg_requests objects are not freed until the
owning file descriptor is closed; rather these objects
are re-used when multiple commands are sent to the same
file descriptor.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 51e28913699e..6cfe4dd9d248 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -12,9 +12,9 @@
  *
  */
 
-static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
-#define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
-static char *sg_version_date = "20190606";
+static int sg_version_num = 40003;  /* [x]xyyzz where [x] empty when x=0 */
+#define SG_VERSION_STR "4.0.03"/* [x]x.[y]y.zz */
+static char *sg_version_date = "20190612";
 
 #include 
 
-- 
2.17.1



[PATCH v2 06/18] sg: make open count an atomic

2019-07-26 Thread Douglas Gilbert
Convert sg_device::open_cnt into an atomic. Also rename
sg_tablesize into the more descriptive max_sgat_elems.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 39 ---
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 97ce84f0c51b..9e9470944fe3 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -162,9 +162,9 @@ struct sg_device { /* holds the state of each scsi generic 
device */
struct mutex open_rel_lock; /* held when in open() or release() */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   int max_sgat_elems; /* adapter's max sgat number of elements */
u32 index;  /* device index number */
-   int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
+   atomic_t open_cnt;  /* count of opens (perhaps < num(sfds) ) */
unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
@@ -276,11 +276,11 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
int retval = 0;
 
if (o_excl) {
-   while (sdp->open_cnt > 0) {
+   while (atomic_read(&sdp->open_cnt) > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
(SG_IS_DETACHING(sdp) ||
-!sdp->open_cnt));
+atomic_read(&sdp->open_cnt) == 0));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
@@ -355,7 +355,7 @@ sg_open(struct inode *inode, struct file *filp)
mutex_lock(&sdp->open_rel_lock);
if (op_flags & O_NONBLOCK) {
if (o_excl) {
-   if (sdp->open_cnt > 0) {
+   if (atomic_read(&sdp->open_cnt) > 0) {
retval = -EBUSY;
goto error_mutex_locked;
}
@@ -375,10 +375,10 @@ sg_open(struct inode *inode, struct file *filp)
if (o_excl)
set_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm);
 
-   if (sdp->open_cnt < 1) {  /* no existing opens */
+   if (atomic_read(&sdp->open_cnt) < 1) {  /* no existing opens */
clear_bit(SG_FDEV_LOG_SENSE, sdp->fdev_bm);
q = sdp->device->request_queue;
-   sdp->sg_tablesize = queue_max_segments(q);
+   sdp->max_sgat_elems = queue_max_segments(q);
}
sfp = sg_add_sfp(sdp);
if (IS_ERR(sfp)) {
@@ -387,10 +387,11 @@ sg_open(struct inode *inode, struct file *filp)
}
 
filp->private_data = sfp;
-   sdp->open_cnt++;
+   atomic_inc(&sdp->open_cnt);
mutex_unlock(&sdp->open_rel_lock);
SG_LOG(3, sfp, "%s: minor=%d, op_flags=0x%x; %s count prior=%d%s\n",
-  __func__, min_dev, op_flags, "device open", sdp->open_cnt,
+  __func__, min_dev, op_flags, "device open",
+  atomic_read(&sdp->open_cnt),
   ((op_flags & O_NONBLOCK) ? " O_NONBLOCK" : ""));
 
retval = 0;
@@ -423,20 +424,20 @@ sg_release(struct inode *inode, struct file *filp)
sfp = filp->private_data;
sdp = sfp->parentdp;
SG_LOG(3, sfp, "%s: device open count prior=%d\n", __func__,
-  sdp->open_cnt);
+  atomic_read(&sdp->open_cnt));
if (!sdp)
return -ENXIO;
 
mutex_lock(&sdp->open_rel_lock);
scsi_autopm_put_device(sdp->device);
kref_put(&sfp->f_ref, sg_remove_sfp);
-   sdp->open_cnt--;
+   atomic_dec(&sdp->open_cnt);
 
/* possibly many open()s waiting on exlude clearing, start many;
 * only open(O_EXCL)s wait on 0==open_cnt so only start one */
if (test_and_clear_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm))
wake_up_interruptible_all(&sdp->open_wait);
-   else if (sdp->open_cnt == 0)
+   else if (atomic_read(&sdp->open_cnt) == 0)
wake_up_interruptible(&sdp->open_wait);
mutex_unlock(&sdp->open_rel_lock);
return 0;
@@ -1104,7 +1105,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
return put_user(val, ip);
case SG_GET_SG_TABLESIZE:
- 

[PATCH v2 13/18] sg: add sg v4 interface support

2019-07-26 Thread Douglas Gilbert
Add support for the sg v4 interface based on struct sg_io_v4 found
in include/uapi/linux/bsg.h and only previously supported by the
bsg driver. Add ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async (non-blocking) usage of the sg v4 interface. Do not accept
the v3 interface with these ioctls. Do not accept the v4
interface with this driver's existing write() and read()
system calls.

For sync (blocking) usage expand the existing ioctl(SG_IO)
to additionally accept the sg v4 interface object.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 489 -
 include/uapi/scsi/sg.h |  37 +++-
 2 files changed, 420 insertions(+), 106 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 4d6635af7da7..dd779931ada4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -7,8 +7,9 @@
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
+ * Version 2, 3 and 4 extensions to driver:
  *Copyright (C) 1998 - 2019 Douglas Gilbert
+ *
  */
 
 static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
@@ -40,10 +41,12 @@ static char *sg_version_date = "20190606";
 #include 
 #include 
 #include 
-#include  /* for sg_check_file_access() */
+#include /* for sg_check_file_access() */
+#include 
 #include 
 
-#include "scsi.h"
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -99,6 +102,7 @@ enum sg_rq_state {
 #define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
 
 /* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_V4I  0   /* true (set) when is v4 interface */
 #define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
 #define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
 #define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
@@ -159,6 +163,15 @@ struct sg_slice_hdr3 {
void __user *usr_ptr;
 };
 
+struct sg_slice_hdr4 { /* parts of sg_io_v4 object needed in async usage */
+   void __user *sbp;   /* derived from sg_io_v4::response */
+   u64 usr_ptr;/* hold sg_io_v4::usr_ptr as given (u64) */
+   int out_resid;
+   s16 dir;/* data xfer direction; SG_DXFER_*  */
+   u16 cmd_len;/* truncated of sg_io_v4::request_len */
+   u16 max_sb_len; /* truncated of sg_io_v4::max_response_len */
+};
+
 struct sg_scatter_hold { /* holding area for scsi scatter gather info */
struct page **pages;/* num_sgat element array of struct page* */
int buflen; /* capacity in bytes (dlen<=buflen) */
@@ -175,7 +188,10 @@ struct sg_request {/* active SCSI command or 
inactive on free list (fl) */
struct list_head fl_entry;  /* member of rq_fl */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
-   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   union {
+   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   struct sg_slice_hdr4 s_hdr4; /* reduced size struct sg_io_v4 */
+   };
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -235,7 +251,10 @@ struct sg_device { /* holds the state of each scsi generic 
device */
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
-   struct sg_io_hdr *h3p;
+   union { /* selector is frq_bm.SG_FRQ_IS_V4I */
+   struct sg_io_hdr *h3p;
+   struct sg_io_v4 *h4p;
+   };
u8 *cmnd;
 };
 
@@ -244,12 +263,12 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   int dxfer_dir);
+   struct sg_io_v4 *h4p, int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
-static int sg_submit(struct file *filp, struct sg_fd *sfp,
-struct sg_io_hdr *hp, bool sync,
-struct sg_request **o_srp);
+static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
+   struct sg_io_hdr *hp, bool sync,
+   struct sg_request **o_srp);
 static struct sg_request *sg_common_write(struct sg_fd *sfp,
  struct sg_comm_wr_t *cwp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
@@ -257,11 

[PATCH v2 15/18] sg: add 8 byte SCSI LUN to sg_scsi_id

2019-07-26 Thread Douglas Gilbert
The existing ioctl(SG_GET_SCSI_ID) fills a object of type
struct sg_scsi_id whose last field is int unused[2]. Add
an anonymous union with u8 scsi_lun[8] sharing those last
8 bytes. This patch will place the current device's full
LUN in the scsi_lun array using T10's preferred LUN
format (i.e. an array of 8 bytes) when
ioctl(SG_GET_SCSI_ID) is called.

Note that structure already contains a 'lun' field but that
is a 32 bit integer. Users of this upgrade should choose
the scsi_lun array field henceforth but existing code
can remain as it is and will get the same 'lun' value with
the version 3 or version 4 driver.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 5 +++--
 include/uapi/scsi/sg.h | 5 -
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ab7112cd4af2..8dc94ac2206a 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1679,6 +1679,7 @@ static int
 sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_fd *sfp, void __user *p)
 {
struct sg_scsi_id __user *sg_idp = p;
+   struct scsi_lun lun8b;
 
SG_LOG(3, sfp, "%s:SG_GET_SCSI_ID\n", __func__);
if (!access_ok(p, sizeof(struct sg_scsi_id)))
@@ -1696,8 +1697,8 @@ sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_fd 
*sfp, void __user *p)
   &sg_idp->h_cmd_per_lun);
__put_user((short)sdev->queue_depth,
   &sg_idp->d_queue_depth);
-   __put_user(0, &sg_idp->unused[0]);
-   __put_user(0, &sg_idp->unused[1]);
+   int_to_scsilun(sdev->lun, &lun8b);
+   __copy_to_user(sg_idp->scsi_lun, lun8b.scsi_lun, 8);
return 0;
 }
 
diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h
index 7557c1be01e0..db86d1ae7e29 100644
--- a/include/uapi/scsi/sg.h
+++ b/include/uapi/scsi/sg.h
@@ -135,7 +135,10 @@ typedef struct sg_scsi_id {
int scsi_type;  /* TYPE_... defined in scsi/scsi.h */
short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
short d_queue_depth;/* device (or adapter) maximum queue length */
-   int unused[2];
+   union {
+   int unused[2];  /* as per version 3 driver */
+   __u8 scsi_lun[8];  /* full 8 byte SCSI LUN [in v4 driver] */
+   };
 } sg_scsi_id_t;
 
 /* For backward compatibility v4 driver yields at most SG_MAX_QUEUE of these */
-- 
2.17.1



Re: [PATCH v2 05/18] sg: bitops in sg_device

2019-07-29 Thread Douglas Gilbert

On 2019-07-29 1:16 p.m., Hannes Reinecke wrote:

On 7/27/19 5:37 AM, Douglas Gilbert wrote:

Introduce bitops in sg_device to replace an atomic, a bool and a
char. That char (sgdebug) had been reduced to only two states.
Add some associated macros to make the code a little clearer.

Signed-off-by: Douglas Gilbert 
---
  drivers/scsi/sg.c | 104 +++---
  1 file changed, 53 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9aa1b1030033..97ce84f0c51b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -74,6 +74,11 @@ static char *sg_version_date = "20190606";
  
  #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
  
+/* Bit positions (flags) for sg_device::fdev_bm bitmask follow */

+#define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
+#define SG_FDEV_DETACHING  1   /* may be unexpected device removal */
+#define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
+
  int sg_big_buff = SG_DEF_RESERVED_SIZE;
  /* N.B. This variable is readable and writeable via
 /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
@@ -155,14 +160,12 @@ 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 */
struct mutex open_rel_lock; /* held when in open() or release() */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
-   u32 index;  /* device index number */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   atomic_t detaching; /* 0->device usable, 1->device detaching */
-   bool exclude;   /* 1->open(O_EXCL) succeeded and is active */
+   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   u32 index;  /* device index number */
int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
-   char sgdebug;   /* 0->off, 1->sense, 9->dump dev, 10-> all devs 
*/
+   unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */


Just use 'unsigned long fdev_bm' (or maybe 'unsigned long fdev_flags').
No point in declaring a one-entry array.


The point is to make the invocations cleaner by removing the need for
"&" on the second argument of bitops.

I find it easier on the eye and less error prone to read:
set_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm);

than:
set_bit(SG_FDEV_EXCLUDE, &sdp->fdev_bm);

include/linux/fdtable.h uses the same technique with
full_fds_bits_init and full_fds_bits.

It also makes the code more robust if the number of flags became larger
than sizeof(unsigned long)*8 . That is unlikely to be the case here.


struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
struct kref d_ref;
@@ -200,6 +203,9 @@ static void sg_device_destroy(struct kref *kref);
  #define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))  /* v3 header */
  #define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
  
+#define SG_IS_DETACHING(sdp) test_bit(SG_FDEV_DETACHING, (sdp)->fdev_bm)

+#define SG_HAVE_EXCLUDE(sdp) test_bit(SG_FDEV_EXCLUDE, (sdp)->fdev_bm)
+
  /*
   * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
   * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
@@ -273,26 +279,26 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
while (sdp->open_cnt > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
+   (SG_IS_DETACHING(sdp) ||
 !sdp->open_cnt));
mutex_lock(&sdp->open_rel_lock);
  
  			if (retval) /* -ERESTARTSYS */

return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
-   while (sdp->exclude) {
+   while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
-!sdp->exclude));
+   (SG_IS_DETACHING(sdp) ||
+!SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock

Re: [PATCH v2 12/18] sg: sense buffer rework

2019-07-29 Thread Douglas Gilbert

On 2019-07-29 1:23 p.m., Hannes Reinecke wrote:

On 7/27/19 5:37 AM, Douglas Gilbert wrote:

The biggest single item in the sg_request object is the sense
buffer array which is SCSI_SENSE_BUFFERSIZE bytes long. That
constant started out at 18 bytes 20 years ago and is 96 bytes
now and might grow in the future. On the other hand the sense
buffer is only used by a small number of SCSI commands: those
that fail and those that want to return more information
other than a SCSI status of GOOD.

Allocate sense buffer as needed on the heap and delete as soon as
possible.

Signed-off-by: Douglas Gilbert 
---
  drivers/scsi/sg.c | 47 +++
  1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 00b8553e0038..4d6635af7da7 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -176,7 +176,6 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
-   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -188,6 +187,7 @@ struct sg_request { /* active SCSI command or inactive on 
free list (fl) */
u8 cmd_opcode;  /* first byte of SCSI cdb */
u64 start_ns;   /* starting point of command duration calc */
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
+   u8 *sense_bp;   /* alloc-ed sense buffer, as needed */
struct sg_fd *parentfp; /* pointer to owning fd, even when on fl */
struct request *rq; /* released in sg_rq_end_io(), bio kept */
struct bio *bio;/* kept until this req -->SG_RS_INACTIVE */
@@ -845,18 +845,21 @@ sg_copy_sense(struct sg_request *srp)
(driver_byte(srp->rq_result) & DRIVER_SENSE)) {
int sb_len = min_t(int, SCSI_SENSE_BUFFERSIZE, srp->sense_len);
int mx_sb_len;
+   u8 *sbp = srp->sense_bp;
void __user *up;
  
+		srp->sense_bp = NULL;

up = (void __user *)srp->s_hdr3.sbp;
mx_sb_len = srp->s_hdr3.mx_sb_len;
-   if (up && mx_sb_len > 0) {
+   if (up && mx_sb_len > 0 && sbp) {
sb_len = min_t(int, sb_len, mx_sb_len);
/* Additional sense length field */
-   sb_len_wr = 8 + (int)srp->sense_b[7];
+   sb_len_wr = 8 + (int)sbp[7];
sb_len_wr = min_t(int, sb_len, sb_len_wr);
-   if (copy_to_user(up, srp->sense_b, sb_len_wr))
+   if (copy_to_user(up, sbp, sb_len_wr))
sb_len_wr = -EFAULT;
}
+   kfree(sbp);
}
return sb_len_wr;
  }
@@ -963,8 +966,9 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd *sfp,
h2p->driver_status = driver_byte(rq_result);
if ((CHECK_CONDITION & status_byte(rq_result)) ||
(DRIVER_SENSE & driver_byte(rq_result))) {
-   memcpy(h2p->sense_buffer, srp->sense_b,
-  sizeof(h2p->sense_buffer));
+   if (srp->sense_bp)
+   memcpy(h2p->sense_buffer, srp->sense_bp,
+  sizeof(h2p->sense_buffer));
}
switch (host_byte(rq_result)) {
/*
@@ -999,17 +1003,21 @@ sg_rd_v1v2(void __user *buf, int count, struct sg_fd 
*sfp,
  
  	/* Now copy the result back to the user buffer.  */

if (count >= SZ_SG_HEADER) {
-   if (copy_to_user(buf, h2p, SZ_SG_HEADER))
-   return -EFAULT;
+   if (copy_to_user(buf, h2p, SZ_SG_HEADER)) {
+   res = -EFAULT;
+   goto fini;
+   }
buf += SZ_SG_HEADER;
if (count > h2p->reply_len)
count = h2p->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER))
-   return -EFAULT;
+   res = sg_rd_append(srp, buf, count - SZ_SG_HEADER);
+   if (res)
+   goto fini;
}
} else
res = (h2p->result == 0) ? 0 : -EIO;
+fini:
atomic_set(&srp->rq_st, SG_RS_DONE_RD);
sg_finish_scsi_blk_rq(srp);
sg_deact_request(sfp, srp);
@@ -1977,8 +1985,17 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
srp->duration = sg_ca

RFC: scsi_lib: export scsi_alloc_sense_buffer() and scsi_free_sense_buffer()

2019-08-05 Thread Douglas Gilbert

In a review comment to this post:
[PATCH v2 12/18] sg: sense buffer rework

Hannes said:
> Maybe it's worthwhile using a mempool here for sense buffers; frequest
> kmalloc()/kfree() really should be avoided.
>
> Also the allocation at end_io time is slightly dodgy; I'd rather have
> the sense allocated before setting up the command. Thing is, the end_io
> callback might be called at any time and in about every context
> (including from an interrupt handler), so I really would avoid having to
> do kmalloc() there.


The problem, seen from the POV of the sg driver, is to get a sense_buffer
either before, or at the time of, sg_rq_end_io(). It needs to be by the end
of that call because the inherited code for the sg driver comments that
the associated request and scsi_request object(s) will be "freed" toward
the end of sg_rq_end_io() to maximize re-use of those objects.

To get a sense_buffer _before_ sg_rq_end_io() seems an unnecessary imposition
as I would guesstimate that the sense buffer is actually needed between
1% and 0.1% of the time. Then that leaves fetching a sense_buffer within
sg_rq_end_io() _only_ when it is needed, copying the contents from either
scsi_request::sense [or scsi_cmnd::sense_buffer, which is damn confusing]
into an sg owned sense buffer before the request and associated
scsi_request (and associated scsi_cmnd) object is "freed" (actually put back
into the pool for re-use, I suspect).

Now addressing Hannes' comment: scsi_lib.c already has a sense buffer pool,
actually two of them:
   static struct kmem_cache *scsi_sense_cache;
   static struct kmem_cache *scsi_sense_isadma_cache;

So it would be good to re-use that code, as I assume it works and is
efficient. But the two needed functions:
scsi_alloc_sense_buffer() and scsi_free_sense_buffer()

are declared static and not exported.

So is that cache appropriate for the sg driver (and perhaps st and
ses drivers) and if so can those scsi_lib functions be exported?
They are a little over-constrained for what the sg driver needs.


As for the "dodgy" comment, I believe that is only in cases where
kernel janitors come along and unwisely change a gfp_mask from
GFP_ATOMIC to GFP_KERNEL. Hopefully a comment like
   ... , GFP_ATOMIC /* <-- leave */);
will catch the attention of a janitor, a reviewer, or someone debugging
broken code.

Doug Gilbert


PS: The split personalities of scsi_request and scsi_cmnd:
Here is a quick survey of ULDs in the scsi subsystem:

ULDUses
==
sd scsi_cmnd (only)
sr scsi_cmnd (only)
st scsi_request (only)
sg scsi_request (only)
ch neither
sesneither

Rationale ?





[PATCH v3 15/20] sg: add 8 byte SCSI LUN to sg_scsi_id

2019-08-07 Thread Douglas Gilbert
The existing ioctl(SG_GET_SCSI_ID) fills a object of type
struct sg_scsi_id whose last field is int unused[2]. Add
an anonymous union with u8 scsi_lun[8] sharing those last
8 bytes. This patch will place the current device's full
LUN in the scsi_lun array using T10's preferred LUN
format (i.e. an array of 8 bytes) when
ioctl(SG_GET_SCSI_ID) is called.

Note that structure already contains a 'lun' field but that
is a 32 bit integer. Users of this upgrade should choose
the scsi_lun array field henceforth but existing code
can remain as it is and will get the same 'lun' value with
the version 3 or version 4 driver.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 5 +++--
 include/uapi/scsi/sg.h | 5 -
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 694a2f50063b..fb7eeafff801 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1684,6 +1684,7 @@ static int
 sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_fd *sfp, void __user *p)
 {
struct sg_scsi_id __user *sg_idp = p;
+   struct scsi_lun lun8b;
 
SG_LOG(3, sfp, "%s:SG_GET_SCSI_ID\n", __func__);
if (!access_ok(p, sizeof(struct sg_scsi_id)))
@@ -1701,8 +1702,8 @@ sg_ctl_scsi_id(struct scsi_device *sdev, struct sg_fd 
*sfp, void __user *p)
   &sg_idp->h_cmd_per_lun);
__put_user((short)sdev->queue_depth,
   &sg_idp->d_queue_depth);
-   __put_user(0, &sg_idp->unused[0]);
-   __put_user(0, &sg_idp->unused[1]);
+   int_to_scsilun(sdev->lun, &lun8b);
+   __copy_to_user(sg_idp->scsi_lun, lun8b.scsi_lun, 8);
return 0;
 }
 
diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h
index 47eefe731a84..0d6fbf976e5c 100644
--- a/include/uapi/scsi/sg.h
+++ b/include/uapi/scsi/sg.h
@@ -135,7 +135,10 @@ typedef struct sg_scsi_id {
int scsi_type;  /* TYPE_... defined in scsi/scsi.h */
short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
short d_queue_depth;/* device (or adapter) maximum queue length */
-   int unused[2];
+   union {
+   int unused[2];  /* as per version 3 driver */
+   __u8 scsi_lun[8];  /* full 8 byte SCSI LUN [in v4 driver] */
+   };
 } sg_scsi_id_t;
 
 /* For backward compatibility v4 driver yields at most SG_MAX_QUEUE of these */
-- 
2.22.0



[PATCH v3 01/20] sg: move functions around

2019-08-07 Thread Douglas Gilbert
Move main entry point functions around so submission code comes
before completion code. Prior to this, the driver used the
traditional open(), close(), read(), write(), ioctl() ordering
however in this case that places completion code (i.e.
sg_read()) before submission code (i.e. sg_write()). The main
driver entry points are considered to be those named in struct
file_operations sg_fops' definition.

Helper functions are often placed above their caller to reduce
the number of forward function declarations needed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 499 --
 1 file changed, 261 insertions(+), 238 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index cce757506383..9f1587761d86 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -8,11 +8,12 @@
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
  * Version 2 and 3 extensions to driver:
- *Copyright (C) 1998 - 2014 Douglas Gilbert
+ *Copyright (C) 1998 - 2019 Douglas Gilbert
  */
 
-static int sg_version_num = 30536; /* 2 digits for each component */
-#define SG_VERSION_STR "3.5.36"
+static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
+#define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
+static char *sg_version_date = "20190606";
 
 /*
  *  D. P. Gilbert (dgilb...@interlog.com), notes:
@@ -47,6 +48,7 @@ static int sg_version_num = 30536;/* 2 digits for each 
component */
 #include 
 #include 
 #include  /* for sg_check_file_access() */
+#include 
 
 #include "scsi.h"
 #include 
@@ -57,12 +59,6 @@ static int sg_version_num = 30536;   /* 2 digits for each 
component */
 
 #include "scsi_logging.h"
 
-#ifdef CONFIG_SCSI_PROC_FS
-#include 
-static char *sg_version_date = "20140603";
-
-static int sg_proc_init(void);
-#endif
 
 #define SG_ALLOW_DIO_DEF 0
 
@@ -173,11 +169,11 @@ typedef struct sg_device { /* holds the state of each 
scsi generic device */
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
+/* Declarations of other static functions used before they are defined */
+static int sg_proc_init(void);
 static int sg_start_req(Sg_request *srp, unsigned char *cmd);
 static int sg_finish_rem_req(Sg_request * srp);
 static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int 
buff_size);
-static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
-  Sg_request * srp);
 static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
const char __user *buf, size_t count, int blocking,
int read_only, int sg_io_owned, Sg_request **o_srp);
@@ -190,7 +186,6 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, 
int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
 static Sg_fd *sg_add_sfp(Sg_device * sdp);
 static void sg_remove_sfp(struct kref *);
-static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static Sg_device *sg_get_dev(int dev);
@@ -232,16 +227,6 @@ static int sg_check_file_access(struct file *filp, const 
char *caller)
return 0;
 }
 
-static int sg_allow_access(struct file *filp, unsigned char *cmd)
-{
-   struct sg_fd *sfp = filp->private_data;
-
-   if (sfp->parentdp->device->type == TYPE_SCANNER)
-   return 0;
-
-   return blk_verify_command(cmd, filp->f_mode);
-}
-
 static int
 open_wait(Sg_device *sdp, int flags)
 {
@@ -405,200 +390,12 @@ sg_release(struct inode *inode, struct file *filp)
return 0;
 }
 
-static ssize_t
-sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
-   Sg_device *sdp;
-   Sg_fd *sfp;
-   Sg_request *srp;
-   int req_pack_id = -1;
-   sg_io_hdr_t *hp;
-   struct sg_header *old_hdr = NULL;
-   int retval = 0;
-
-   /*
-* This could cause a response to be stranded. Close the associated
-* file descriptor to free up any resources being held.
-*/
-   retval = sg_check_file_access(filp, __func__);
-   if (retval)
-   return retval;
-
-   if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
-   return -ENXIO;
-   SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
- "sg_read: count=%d\n", (int) count));
-
-   if (!access_ok(buf, count))
-   return -EFAULT;
-   if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
-   old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
-   if (!old_hdr)
-   return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
-   retval = -E

[PATCH v3 10/20] sg: remove most access_ok functions

2019-08-07 Thread Douglas Gilbert
Since access_ok() has lost it direction (3rd) parameter there
seems to be no benefit in calling access_ok() before
__copy_{to|from}_user(). Simplify code by using the variant of
these functions that do not start with "__".

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 50 ---
 1 file changed, 17 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7e188ac2f182..123d8516a9a0 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -502,11 +502,9 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
if (res)
return res;
 
-   if (!access_ok(buf, count))
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
if (count < SZ_SG_HEADER)
return -EIO;
-   if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
+   if (copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
return -EFAULT;
if (old_hdr.reply_len < 0)
return sg_submit(sfp, filp, buf, count, blocking, false, false,
@@ -561,7 +559,7 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
hp->flags = input_size; /* structure abuse ... */
hp->pack_id = old_hdr.pack_id;
hp->usr_ptr = NULL;
-   if (__copy_from_user(cmnd, buf, cmd_size))
+   if (copy_from_user(cmnd, buf, cmd_size))
return -EFAULT;
/*
 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
@@ -607,8 +605,6 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
 
if (count < SZ_SG_IO_HDR)
return -EINVAL;
-   if (!access_ok(buf, count))
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
 
sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */
if (!(srp = sg_add_request(sfp))) {
@@ -617,7 +613,7 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
}
srp->sg_io_owned = sg_io_owned;
hp = &srp->header;
-   if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
+   if (copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -645,11 +641,7 @@ sg_submit(struct sg_fd *sfp, struct file *filp, const char 
__user *buf,
sg_remove_request(sfp, srp);
return -EMSGSIZE;
}
-   if (!access_ok(hp->cmdp, hp->cmd_len)) {
-   sg_remove_request(sfp, srp);
-   return -EFAULT; /* protects following copy_from_user()s + 
get_user()s */
-   }
-   if (__copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
+   if (copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -829,13 +821,11 @@ sg_read(struct file *filp, char __user *buf, size_t 
count, loff_t *ppos)
if (ret)
return ret;
 
-   if (!access_ok(buf, count))
-   return -EFAULT;
if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
if (!old_hdr)
return -ENOMEM;
-   if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
+   if (copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
ret = -EFAULT;
goto free_old_hdr;
}
@@ -848,8 +838,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
ret = -ENOMEM;
goto free_old_hdr;
}
-   ret = __copy_from_user
-   (new_hdr, buf, SZ_SG_IO_HDR);
+   ret = copy_from_user(new_hdr, buf,
+SZ_SG_IO_HDR);
req_pack_id = new_hdr->pack_id;
kfree(new_hdr);
if (ret) {
@@ -942,7 +932,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
 
/* Now copy the result back to the user buffer.  */
if (count >= SZ_SG_HEADER) {
-   if (__copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
+   if (copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
ret = -EFAULT;
goto free_old_hdr;
}
@@ -1032,8 +1022,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
result = sg_allow_if_err_recovery(sdp, false);
if (result)
return result;
-   if (!access_ok(p, SZ_SG_IO_HDR

[PATCH v3 11/20] sg: replace rq array with lists

2019-08-07 Thread Douglas Gilbert
Remove the fixed size array of 16 request elements per file
descriptor and replace with two linked lists per file descriptor.
One list is for active commands, the other list is a free list.
sg_request objects are now kept, available for re-use, until
their owning file descriptor is closed. The sg_request deletions
are now in sg_remove_sfp_usercontext(). Each active sg_request
has associated block request and scsi_request objects which are
released much earlier; their lifetime is the same as it was in
the v3 sg driver. The lifetime of the bio is also the same (but
is stretched in a later patch).

Add an enum for request state (sg_rq_state) and collect
various flags into bit maps: one for requests (SG_FRQ_*) and
the other for file descriptors (SG_FFD_*). They join a
per sg_device bit map (SG_FDEV_*) added in an earlier
patch.

Prior to a new sg_request object being (re-)built, information
that will be placed in it uses a new struct sg_comm_wr_t
object.

Since the above changes touch almost every function and low
level structures, this patch is big. With so many changes, the
diff utility that generates the patch sometimes loses track.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 3033 +
 1 file changed, 1949 insertions(+), 1084 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 123d8516a9a0..75f515b3fc8c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -72,7 +72,46 @@ static char *sg_version_date = "20190606";
  */
 #define SG_MAX_CDB_SIZE 252
 
+#define uptr64(val) ((void __user *)(uintptr_t)(val))
+#define cuptr64(val) ((const void __user *)(uintptr_t)(val))
+
+/* Following enum contains the states of sg_request::rq_st */
+enum sg_rq_state {
+   SG_RS_INACTIVE = 0, /* request not in use (e.g. on fl) */
+   SG_RS_INFLIGHT, /* active: cmd/req issued, no response yet */
+   SG_RS_AWAIT_RD, /* response received, awaiting read */
+   SG_RS_DONE_RD,  /* read is ongoing or done */
+   SG_RS_BUSY, /* temporary state should rarely be seen */
+};
+
+#define SG_TIME_UNIT_MS 0  /* milliseconds */
+#define SG_DEF_TIME_UNIT SG_TIME_UNIT_MS
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
+#define SG_FD_Q_AT_HEAD 0
+#define SG_DEFAULT_Q_AT SG_FD_Q_AT_HEAD /* for backward compatibility */
+#define SG_FL_MMAP_DIRECT (SG_FLAG_MMAP_IO | SG_FLAG_DIRECT_IO)
+
+/* Only take lower 4 bits of driver byte, all host byte and sense byte */
+#define SG_ML_RESULT_MSK 0x0fff00ff/* mid-level's 32 bit result value */
+
+#define SG_PACK_ID_WILDCARD (-1)
+
+#define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
+
+/* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
+#define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
+#define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
+#define SG_FRQ_NO_US_XFER  4   /* no user space transfer of data */
+#define SG_FRQ_DEACT_ORPHAN7   /* not keeping orphan so de-activate */
+#define SG_FRQ_BLK_PUT_REQ 9   /* set when blk_put_request() called */
+
+/* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
+#define SG_FFD_FORCE_PACKID0   /* receive only given pack_id/tag */
+#define SG_FFD_CMD_Q   1   /* clear: only 1 active req per fd */
+#define SG_FFD_KEEP_ORPHAN 2   /* policy for this fd */
+#define SG_FFD_MMAP_CALLED 3   /* mmap(2) system call made on fd */
+#define SG_FFD_Q_AT_TAIL   5   /* set: queue reqs at tail of blk q */
 
 /* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
 #define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
@@ -80,19 +119,17 @@ static char *sg_version_date = "20190606";
 #define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
-/* N.B. This variable is readable and writeable via
-   /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
-   of this size (or less if there is not enough memory) will be reserved
-   for use by this file descriptor. [Deprecated usage: this variable is also
-   readable via /proc/sys/kernel/sg-big-buff if the sg driver is built into
-   the kernel (i.e. it is not a module).] */
+/*
+ * This variable is accessible via /proc/scsi/sg/def_reserved_size . Each
+ * time sg_open() is called a sg_request of this size (or less if there is
+ * not enough memory) will be reserved for use by this file descriptor.
+ */
 static int def_reserved_size = -1; /* picks up init parameter */
 static int sg_allow_dio = SG_ALLOW_DIO_DEF;
 
 static int scatter_elem_sz = SG_SCATTER_SZ;
-static int scatter_elem_sz_prev = SG_SCATTER_SZ;
 
-#define SG_SECTOR_SZ 512
+#define SG_DEF_SECTOR_SZ 512
 
 static int sg_add_device(struct d

[PATCH v3 13/20] sg: add sg v4 interface support

2019-08-07 Thread Douglas Gilbert
Add support for the sg v4 interface based on struct sg_io_v4 found
in include/uapi/linux/bsg.h and only previously supported by the
bsg driver. Add ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async (non-blocking) usage of the sg v4 interface. Do not accept
the v3 interface with these ioctls. Do not accept the v4
interface with this driver's existing write() and read()
system calls.

For sync (blocking) usage expand the existing ioctl(SG_IO)
to additionally accept the sg v4 interface object.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 487 -
 include/uapi/scsi/sg.h |  37 +++-
 2 files changed, 418 insertions(+), 106 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 8c80661b8196..b12f53851078 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -7,8 +7,9 @@
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
+ * Version 2, 3 and 4 extensions to driver:
  *Copyright (C) 1998 - 2019 Douglas Gilbert
+ *
  */
 
 static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
@@ -40,10 +41,11 @@ static char *sg_version_date = "20190606";
 #include 
 #include 
 #include 
-#include  /* for sg_check_file_access() */
+#include /* for sg_check_file_access() */
 #include 
 
-#include "scsi.h"
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -103,6 +105,7 @@ enum sg_rq_state {
 #define SG_ADD_RQ_MAX_RETRIES 40   /* to stop infinite _trylock(s) */
 
 /* Bit positions (flags) for sg_request::frq_bm bitmask follow */
+#define SG_FRQ_IS_V4I  0   /* true (set) when is v4 interface */
 #define SG_FRQ_IS_ORPHAN   1   /* owner of request gone */
 #define SG_FRQ_SYNC_INVOC  2   /* synchronous (blocking) invocation */
 #define SG_FRQ_DIO_IN_USE  3   /* false->indirect_IO,mmap; 1->dio */
@@ -163,6 +166,15 @@ struct sg_slice_hdr3 {
void __user *usr_ptr;
 };
 
+struct sg_slice_hdr4 { /* parts of sg_io_v4 object needed in async usage */
+   void __user *sbp;   /* derived from sg_io_v4::response */
+   u64 usr_ptr;/* hold sg_io_v4::usr_ptr as given (u64) */
+   int out_resid;
+   s16 dir;/* data xfer direction; SG_DXFER_*  */
+   u16 cmd_len;/* truncated of sg_io_v4::request_len */
+   u16 max_sb_len; /* truncated of sg_io_v4::max_response_len */
+};
+
 struct sg_scatter_hold { /* holding area for scsi scatter gather info */
struct page **pages;/* num_sgat element array of struct page* */
int buflen; /* capacity in bytes (dlen<=buflen) */
@@ -179,7 +191,10 @@ struct sg_request {/* active SCSI command or 
inactive on free list (fl) */
struct list_head fl_entry;  /* member of rq_fl */
spinlock_t req_lck;
struct sg_scatter_hold sgat_h;  /* hold buffer, perhaps scatter list */
-   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   union {
+   struct sg_slice_hdr3 s_hdr3;  /* subset of sg_io_hdr */
+   struct sg_slice_hdr4 s_hdr4; /* reduced size struct sg_io_v4 */
+   };
u32 duration;   /* cmd duration in milliseconds */
u32 rq_flags;   /* hold user supplied flags */
u32 rq_info;/* info supplied by v3 and v4 interfaces */
@@ -239,7 +254,10 @@ struct sg_device { /* holds the state of each scsi generic 
device */
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
-   struct sg_io_hdr *h3p;
+   union { /* selector is frq_bm.SG_FRQ_IS_V4I */
+   struct sg_io_hdr *h3p;
+   struct sg_io_v4 *h4p;
+   };
u8 *cmnd;
 };
 
@@ -248,12 +266,12 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   int dxfer_dir);
+   struct sg_io_v4 *h4p, int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
-static int sg_submit(struct file *filp, struct sg_fd *sfp,
-struct sg_io_hdr *hp, bool sync,
-struct sg_request **o_srp);
+static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
+   struct sg_io_hdr *hp, bool sync,
+   struct sg_request **o_srp);
 static struct sg_request *sg_common_write(struct sg_fd *sfp,
  struct sg_comm_wr_t *cwp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
@@ -261,11 +279,11

[PATCH v3 18/20] sg: add some __must_hold macros

2019-08-07 Thread Douglas Gilbert
In the case of sg_wait_open_event() which calls mutex_unlock on
sdp->open_rel_lock and later calls mutex_lock on the same
lock; this macro is needed to stop sparse complaining. In
other cases it is a reminder to the coder (a precondition).

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index aa3512b2cb4f..fe79f5f354f2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -379,6 +379,7 @@ sg_check_file_access(struct file *filp, const char *caller)
 
 static int
 sg_wait_open_event(struct sg_device *sdp, bool o_excl)
+   __must_hold(&sdp->open_rel_lock)
 {
int res = 0;
 
@@ -1506,6 +1507,7 @@ sg_get_dur(struct sg_request *srp, const enum sg_rq_state 
*sr_stp,
 static void
 sg_fill_request_element(struct sg_fd *sfp, struct sg_request *srp,
struct sg_req_info *rip)
+   __must_hold(&sfp->rq_list_lock)
 {
spin_lock(&srp->req_lck);
rip->duration = sg_get_dur(srp, NULL, NULL);
@@ -1627,6 +1629,7 @@ sg_ctl_sg_io(struct file *filp, struct sg_device *sdp, 
struct sg_fd *sfp,
  */
 static int
 sg_set_reserved_sz(struct sg_fd *sfp, int want_rsv_sz)
+   __must_hold(&sfp->f_mutex)
 {
bool use_new_srp = false;
int res = 0;
@@ -3550,6 +3553,7 @@ sg_remove_sfp(struct kref *kref)
 
 static int
 sg_idr_max_id(int id, void *p, void *data)
+   __must_hold(&sg_index_lock)
 {
int *k = data;
 
@@ -3858,6 +3862,7 @@ sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
 /* Writes debug info for one sg_request in obp buffer */
 static int
 sg_proc_debug_sreq(struct sg_request *srp, int to, char *obp, int len)
+   __must_hold(&sfp->rq_list_lock)
 {
bool is_v3v4, v4, is_dur;
int n = 0;
@@ -3893,6 +3898,7 @@ sg_proc_debug_sreq(struct sg_request *srp, int to, char 
*obp, int len)
 /* Writes debug info for one sg fd (including its sg requests) in obp buffer */
 static int
 sg_proc_debug_fd(struct sg_fd *fp, char *obp, int len)
+   __must_hold(&sfp->rq_list_lock)
 {
bool first_fl;
int n = 0;
@@ -3942,6 +3948,7 @@ sg_proc_debug_fd(struct sg_fd *fp, char *obp, int len)
 /* Writes debug info for one sg device (including its sg fds) in obp buffer */
 static int
 sg_proc_debug_sdev(struct sg_device *sdp, char *obp, int len, int *fd_counterp)
+   __must_hold(&sdp->sfd_lock)
 {
int n = 0;
int my_count = 0;
-- 
2.22.0



[PATCH v3 14/20] sg: rework debug info

2019-08-07 Thread Douglas Gilbert
Since the version 2 driver, the state of the driver can be found
with 'cat /proc/scsi/sg/debug'. As the driver becomes more
threaded and IO faster (e.g. scsi_debug with a command timer
of 5 microseconds), the existing state dump can become
misleading as the state can change during the "snapshot". The
new approach in this patch is to allocate a buffer of
SG_PROC_DEBUG_SZ bytes and use scnprintf() to populate it. Only
when the whole state is captured (or the buffer fills) is the
output to the caller's terminal performed. The previous
approach was line based: assemble a line of information and
then output it.

Locks are taken as required for short periods and should not
interfere with a disk IO intensive program. Operations
such as closing a sg file descriptor or removing a sg device
may be held up for a short while (microseconds).

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 235 +++---
 1 file changed, 157 insertions(+), 78 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b12f53851078..694a2f50063b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3773,115 +3773,194 @@ sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
return 0;
 }
 
-/* must be called while holding sg_index_lock */
-static void
-sg_proc_debug_helper(struct seq_file *s, struct sg_device *sdp)
+/* Writes debug info for one sg_request in obp buffer */
+static int
+sg_proc_debug_sreq(struct sg_request *srp, int to, char *obp, int len)
 {
-   int k;
+   bool is_v3v4, v4, is_dur;
+   int n = 0;
+   u32 dur;
+   enum sg_rq_state rq_st;
+   const char *cp;
+
+   if (len < 1)
+   return 0;
+   v4 = test_bit(SG_FRQ_IS_V4I, srp->frq_bm);
+   is_v3v4 = v4 ? true : (srp->s_hdr3.interface_id != '\0');
+   if (srp->parentfp->rsv_srp == srp)
+   cp = (is_v3v4 && (srp->rq_flags & SG_FLAG_MMAP_IO)) ?
+   " mmap>> " : " rsv>> ";
+   else
+   cp = (srp->rq_info & SG_INFO_DIRECT_IO_MASK) ?
+   " dio>> " : " ";
+   rq_st = atomic_read(&srp->rq_st);
+   dur = sg_get_dur(srp, &rq_st, &is_dur);
+   n += scnprintf(obp + n, len - n, "%s%s: dlen=%d/%d id=%d", cp,
+  sg_rq_st_str(rq_st, false), srp->sgat_h.dlen,
+  srp->sgat_h.buflen, (int)srp->pack_id);
+   if (is_dur) /* cmd/req has completed, waiting for ... */
+   n += scnprintf(obp + n, len - n, " dur=%ums", dur);
+   else if (dur < U32_MAX) /* in-flight or busy (so ongoing) */
+   n += scnprintf(obp + n, len - n, " t_o/elap=%us/%ums",
+  to / 1000, dur);
+   n += scnprintf(obp + n, len - n, " sgat=%d op=0x%02x\n",
+  srp->sgat_h.num_sgat, srp->cmd_opcode);
+   return n;
+}
+
+/* Writes debug info for one sg fd (including its sg requests) in obp buffer */
+static int
+sg_proc_debug_fd(struct sg_fd *fp, char *obp, int len)
+{
+   bool first_fl;
+   int n = 0;
+   int to;
struct sg_request *srp;
-   struct sg_fd *fp;
-   const char * cp;
-   unsigned int ms;
 
-   k = 0;
-   list_for_each_entry(fp, &sdp->sfds, sfd_entry) {
-   k++;
-   spin_lock(&fp->rq_list_lock); /* irqs already disabled */
-   seq_printf(s, "   FD(%d): timeout=%dms bufflen=%d "
-  "(res)sgat=%d low_dma=%d\n", k,
-  jiffies_to_msecs(fp->timeout),
-  fp->rsv_srp->sgat_h.buflen,
-  (int)fp->rsv_srp->sgat_h.num_sgat,
-  (int) sdp->device->host->unchecked_isa_dma);
-   seq_printf(s, "   cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
-  (int)test_bit(SG_FFD_CMD_Q, fp->ffd_bm),
-  (int)test_bit(SG_FFD_FORCE_PACKID, fp->ffd_bm),
-  (int)test_bit(SG_FFD_KEEP_ORPHAN, fp->ffd_bm));
-   seq_printf(s, "   submitted=%d waiting=%d\n",
-  atomic_read(&fp->submitted),
-  atomic_read(&fp->waiting));
-   list_for_each_entry(srp, &fp->rq_list, rq_entry) {
-   const struct sg_slice_hdr3 *sh3p = &srp->s_hdr3;
-   bool is_v3 = (sh3p->interface_id != '\0');
-   enum sg_rq_state rq_st = atomic_read(&srp->rq_st);
-
-   if (srp->parentfp->rsv_srp == srp) {
-   if (is_v3 && 

[PATCH v3 06/20] sg: make open count an atomic

2019-08-07 Thread Douglas Gilbert
Convert sg_device::open_cnt into an atomic. Also rename
sg_tablesize into the more descriptive max_sgat_elems.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 39 ---
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 97ce84f0c51b..9e9470944fe3 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -162,9 +162,9 @@ struct sg_device { /* holds the state of each scsi generic 
device */
struct mutex open_rel_lock; /* held when in open() or release() */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   int max_sgat_elems; /* adapter's max sgat number of elements */
u32 index;  /* device index number */
-   int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
+   atomic_t open_cnt;  /* count of opens (perhaps < num(sfds) ) */
unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
@@ -276,11 +276,11 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
int retval = 0;
 
if (o_excl) {
-   while (sdp->open_cnt > 0) {
+   while (atomic_read(&sdp->open_cnt) > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
(SG_IS_DETACHING(sdp) ||
-!sdp->open_cnt));
+atomic_read(&sdp->open_cnt) == 0));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
@@ -355,7 +355,7 @@ sg_open(struct inode *inode, struct file *filp)
mutex_lock(&sdp->open_rel_lock);
if (op_flags & O_NONBLOCK) {
if (o_excl) {
-   if (sdp->open_cnt > 0) {
+   if (atomic_read(&sdp->open_cnt) > 0) {
retval = -EBUSY;
goto error_mutex_locked;
}
@@ -375,10 +375,10 @@ sg_open(struct inode *inode, struct file *filp)
if (o_excl)
set_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm);
 
-   if (sdp->open_cnt < 1) {  /* no existing opens */
+   if (atomic_read(&sdp->open_cnt) < 1) {  /* no existing opens */
clear_bit(SG_FDEV_LOG_SENSE, sdp->fdev_bm);
q = sdp->device->request_queue;
-   sdp->sg_tablesize = queue_max_segments(q);
+   sdp->max_sgat_elems = queue_max_segments(q);
}
sfp = sg_add_sfp(sdp);
if (IS_ERR(sfp)) {
@@ -387,10 +387,11 @@ sg_open(struct inode *inode, struct file *filp)
}
 
filp->private_data = sfp;
-   sdp->open_cnt++;
+   atomic_inc(&sdp->open_cnt);
mutex_unlock(&sdp->open_rel_lock);
SG_LOG(3, sfp, "%s: minor=%d, op_flags=0x%x; %s count prior=%d%s\n",
-  __func__, min_dev, op_flags, "device open", sdp->open_cnt,
+  __func__, min_dev, op_flags, "device open",
+  atomic_read(&sdp->open_cnt),
   ((op_flags & O_NONBLOCK) ? " O_NONBLOCK" : ""));
 
retval = 0;
@@ -423,20 +424,20 @@ sg_release(struct inode *inode, struct file *filp)
sfp = filp->private_data;
sdp = sfp->parentdp;
SG_LOG(3, sfp, "%s: device open count prior=%d\n", __func__,
-  sdp->open_cnt);
+  atomic_read(&sdp->open_cnt));
if (!sdp)
return -ENXIO;
 
mutex_lock(&sdp->open_rel_lock);
scsi_autopm_put_device(sdp->device);
kref_put(&sfp->f_ref, sg_remove_sfp);
-   sdp->open_cnt--;
+   atomic_dec(&sdp->open_cnt);
 
/* possibly many open()s waiting on exlude clearing, start many;
 * only open(O_EXCL)s wait on 0==open_cnt so only start one */
if (test_and_clear_bit(SG_FDEV_EXCLUDE, sdp->fdev_bm))
wake_up_interruptible_all(&sdp->open_wait);
-   else if (sdp->open_cnt == 0)
+   else if (atomic_read(&sdp->open_cnt) == 0)
wake_up_interruptible(&sdp->open_wait);
mutex_unlock(&sdp->open_rel_lock);
return 0;
@@ -1104,7 +1105,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
return put_user(val, ip);
case SG_GET_SG_TABLESIZE:
- 

[PATCH v3 09/20] sg: sg_allow_if_err_recovery and renames

2019-08-07 Thread Douglas Gilbert
Add sg_allow_if_err_recover() to do checks common to several entry
points. Replace retval with either res or ret. Rename
sg_finish_rem_req() to sg_finish_scsi_blk_rq(). Rename
sg_new_write() to sg_submit(). Other cleanups triggered by
checkpatch.pl .

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 245 +-
 1 file changed, 133 insertions(+), 112 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7c9c56bda7ba..7e188ac2f182 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -68,7 +68,7 @@ static char *sg_version_date = "20190606";
 
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
- * than 16 bytes are "variable length" whose length is a multiple of 4
+ * than 16 bytes are "variable length" whose length is a multiple of 4, so:
  */
 #define SG_MAX_CDB_SIZE 252
 
@@ -178,16 +178,16 @@ static void sg_rq_end_io(struct request *rq, blk_status_t 
status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
 static int sg_start_req(struct sg_request *srp, u8 *cmd);
-static int sg_finish_rem_req(struct sg_request *srp);
+static int sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_build_indirect(struct sg_scatter_hold *schp, struct sg_fd *sfp,
 int buff_size);
-static ssize_t sg_new_write(struct sg_fd *sfp, struct file *file,
-   const char __user *buf, size_t count, int blocking,
-   int read_only, int sg_io_owned,
-   struct sg_request **o_srp);
+static ssize_t sg_submit(struct sg_fd *sfp, struct file *filp,
+const char __user *buf, size_t count, bool blocking,
+bool read_only, bool sg_io_owned,
+struct sg_request **o_srp);
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
-static int sg_rd_append(struct sg_request *srp, char __user *outp,
+static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
@@ -275,37 +275,60 @@ sg_check_file_access(struct file *filp, const char 
*caller)
 static int
 sg_wait_open_event(struct sg_device *sdp, bool o_excl)
 {
-   int retval = 0;
+   int res = 0;
 
if (o_excl) {
while (atomic_read(&sdp->open_cnt) > 0) {
mutex_unlock(&sdp->open_rel_lock);
-   retval = wait_event_interruptible(sdp->open_wait,
-   (SG_IS_DETACHING(sdp) ||
-atomic_read(&sdp->open_cnt) == 0));
+   res = wait_event_interruptible
+   (sdp->open_wait,
+(SG_IS_DETACHING(sdp) ||
+ atomic_read(&sdp->open_cnt) == 0));
mutex_lock(&sdp->open_rel_lock);
 
-   if (retval) /* -ERESTARTSYS */
-   return retval;
+   if (res) /* -ERESTARTSYS */
+   return res;
if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
-   retval = wait_event_interruptible(sdp->open_wait,
-   (SG_IS_DETACHING(sdp) ||
-!SG_HAVE_EXCLUDE(sdp)));
+   res = wait_event_interruptible
+   (sdp->open_wait,
+(SG_IS_DETACHING(sdp) ||
+ !SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock);
 
-   if (retval) /* -ERESTARTSYS */
-   return retval;
+   if (res) /* -ERESTARTSYS */
+   return res;
if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
}
 
-   return retval;
+   return res;
+}
+
+/*
+ * scsi_block_when_processing_errors() returns 0 when dev was taken offline by
+ * error recovery, 1 otherwise (i.e. okay). Even if in error recovery, let
+ * user continue if O_NONBLOCK set. Permits SCSI commands to be issued during
+ * error recovery. Tread carefully.
+ * Ret

[PATCH v3 00/20] sg: add v4 interface

2019-08-07 Thread Douglas Gilbert
This patchset extends the SCSI generic (sg) driver found in
lk 5.3 .  The sg driver has a version number which is visible
via ioctl(SG_GET_VERSION_NUM) and is bumped from 3.5.36 to
4.0.03 by this patchset. The additions and changes are
described in some detail in this long webpage:
http://sg.danny.cz/sg/sg_v40.html

Most new features described in the above webpage are not
implemented in this patchset. Features that are not included are
file descriptor sharing, request sharing, multiple requests (in
one invocation) and the extended ioctl(). A later patchset may add
those features. The SG_IOSUMIT, SG_IOSUBMIT_V3, SG_IORECEIVE and
SG_IORECEIVE_V3 ioctls are added in this patchset.

Testing:
The sg3_utils package has several extensions in sg3_utils-1.45 beta
(revision 829 (see http://sg.danny.cz/sg)) to support and test the
version 4 sg driver presented in this patchset.
The new and revised testing utilities are outlined on the
same webpage as above in the second half of the section
titled: "15 Downloads and testing".

This patchset is against Martin Petersen's 5.4/scsi-queue branch.
To apply this patchset to lk 5.2 and earlier, the
ktime_get_boottime_ns() call needs to be changed back to
ktime_get_boot_ns().

Changes since v2 (sent to linux-scsi list on 20190727):
  - address issues "Reported-by: kbuild test robot ".
The main one was to change the bsg header included to:
include/uapi/linux/bsg.h rather than include/linux/bsg.h
  - address some of the review comments from Hannes Reinecke;
email responses have been sent for review comments that
did not result in code changes

Changes since v1 (sent to linux-scsi list on 20190616):
  - change ktime_get_boot_ns() to ktime_get_boottime_ns() to reflect
kernel API change first seen in lk 5.3.0-rc1

Douglas Gilbert (20):
  sg: move functions around
  sg: remove typedefs, type+formatting cleanup
  sg: sg_log and is_enabled
  sg: rework sg_poll(), minor changes
  sg: bitops in sg_device
  sg: make open count an atomic
  sg: move header to uapi section
  sg: speed sg_poll and sg_get_num_waiting
  sg: sg_allow_if_err_recovery and renames
  sg: remove most access_ok functions
  sg: replace rq array with lists
  sg: sense buffer rework
  sg: add sg v4 interface support
  sg: rework debug info
  sg: add 8 byte SCSI LUN to sg_scsi_id
  sg: expand sg_comm_wr_t
  sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls
  sg: add some __must_hold macros
  sg: first debugfs support
  sg: bump version to 4.0.03

 drivers/scsi/sg.c  | 4599 ++--
 include/scsi/sg.h  |  268 +--
 include/uapi/scsi/sg.h |  373 
 3 files changed, 3433 insertions(+), 1807 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

-- 
2.22.0



[PATCH v3 19/20] sg: first debugfs support

2019-08-07 Thread Douglas Gilbert
Duplicate the semantics of 'cat /proc/scsi/sg/debug' on
'cat /sys/kernel/debug/scsi_generic/snapshot'. Make code
that generates the snapshot conditional on either
CONFIG_SCSI_PROC_FS or CONFIG_DEBUG_FS being defined.

-

Use "scsi_generic" in the debugfs path as "sg" may be
confused with scatter gather in the wider kernel.
As implemented, the snapshot is on all sg devices. If many sg
devices are in use, restricting the output to one (or a list)
of sg device numbers may declutter the output. Perhaps a
writable snapshot_devs attribute could be added that takes a
single integer, a comma separated list or integers, or '*'
which maps to -1 which is the default and means all devices.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 207 ++
 1 file changed, 136 insertions(+), 71 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index fe79f5f354f2..82c4147ba4f1 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -43,6 +43,7 @@ static char *sg_version_date = "20190606";
 #include 
 #include /* for sg_check_file_access() */
 #include 
+#include 
 
 #include 
 #include 
@@ -68,6 +69,10 @@ static char *sg_version_date = "20190606";
 #endif
 #endif
 
+#if IS_ENABLED(CONFIG_SCSI_PROC_FS) || IS_ENABLED(CONFIG_DEBUG_FS)
+#define SG_PROC_OR_DEBUG_FS 1
+#endif
+
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
  * than 16 bytes are "variable length" whose length is a multiple of 4, so:
@@ -268,6 +273,8 @@ struct sg_comm_wr_t {   /* arguments to 
sg_common_write() */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
+static void sg_dfs_init(void);
+static void sg_dfs_exit(void);
 static int sg_start_req(struct sg_request *srp, struct sg_comm_wr_t *cwrp,
int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
@@ -341,7 +348,7 @@ static void sg_rep_rq_state_fail(struct sg_fd *sfp,
pr_info("sg: sdp or sfp NULL, " fmt, ##a);  \
} while (0)
 #else
-#define SG_LOG(depth, sfp, fmt, a...)
+#define SG_LOG(depth, sfp, fmt, a...) do { } while (0)
 #endif /* end of CONFIG_SCSI_LOGGING && SG_DEBUG conditional */
 
 
@@ -2650,6 +2657,7 @@ init_sg(void)
rc = scsi_register_interface(&sg_interface);
if (rc == 0) {
sg_proc_init();
+   sg_dfs_init();
return 0;
}
class_destroy(sg_sysfs_class);
@@ -2674,6 +2682,7 @@ sg_proc_init(void)
 static void __exit
 exit_sg(void)
 {
+   sg_dfs_exit();
if (IS_ENABLED(CONFIG_SCSI_PROC_FS))
remove_proc_subtree("scsi/sg", NULL);
scsi_unregister_interface(&sg_interface);
@@ -3130,7 +3139,7 @@ sg_find_srp_by_id(struct sg_fd *sfp, int pack_id)
rcu_read_unlock();
if (IS_ENABLED(CONFIG_SCSI_PROC_FS)) {
if (search_for_1) {
-   const char *cptp = "pack_id=";
+   __maybe_unused const char *cptp = "pack_id=";
 
if (is_bad_st)
SG_LOG(1, sfp, "%s: %s%d wrong state: %s\n",
@@ -3248,7 +3257,7 @@ sg_add_request(struct sg_comm_wr_t *cwrp, int dxfr_len)
enum sg_rq_state sr_st;
struct sg_fd *fp = cwrp->sfp;
struct sg_request *r_srp = NULL;/* request to return */
-   struct sg_request *rsv_srp; /* current fd's reserve request */
+   __maybe_unused struct sg_request *rsv_srp;
__maybe_unused const char *cp;
 
spin_lock_irqsave(&fp->rq_list_lock, iflags);
@@ -3348,7 +3357,7 @@ sg_deact_request(struct sg_fd *sfp, struct sg_request 
*srp)
u8 *sbp;
struct sg_request *t_srp;
struct sg_scatter_hold *schp;
-   const char *cp = "head";
+   __maybe_unused const char *cp = "head";
 
if (WARN_ON(!sfp || !srp))
return;
@@ -3551,18 +3560,6 @@ sg_remove_sfp(struct kref *kref)
schedule_work(&sfp->ew_fd.work);
 }
 
-static int
-sg_idr_max_id(int id, void *p, void *data)
-   __must_hold(&sg_index_lock)
-{
-   int *k = data;
-
-   if (*k < id)
-   *k = id;
-
-   return 0;
-}
-
 /* must be called with sg_index_lock held */
 static struct sg_device *
 sg_lookup_dev(int dev)
@@ -3592,7 +3589,7 @@ sg_get_dev(int dev)
return sdp;
 }
 
-#if IS_ENABLED(CONFIG_SCSI_PROC_FS)
+#if IS_ENABLED(SG_PROC_OR_DEBUG_FS)
 static const char *
 sg_rq_st_str(enum sg_rq_state rq_st, bool long_str)
 {
@@ -3619,7 +3616,72 @@ sg_rq_st_str(enum sg_rq_state rq_st, bool long_str)

[PATCH v3 20/20] sg: bump version to 4.0.03

2019-08-07 Thread Douglas Gilbert
Now that the sg version 4 interface is supported:
  - with ioctl(SG_IO) for synchronous/blocking use
  - with ioctl(SG_IOSUBMIT) and ioctl(SG_IORECEIVE) for
async/non-blocking use
Plus new ioctl(SG_IOSUBMIT_V3) and ioctl(SG_IORECEIVE_V3)
potentially replace write() and read() for the sg
version 3 interface. Bump major driver version number
from 3 to 4.

The main new feature is the removal of the fixed 16 element
array of requests per file descriptor. It is replaced by
two lists: one for active (inflight) requests and a free
list. Also sg_requests objects are not freed until the
owning file descriptor is closed; rather these objects
are re-used when multiple commands are sent to the same
file descriptor.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 82c4147ba4f1..3ad88e18a5ac 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -12,9 +12,9 @@
  *
  */
 
-static int sg_version_num = 30901;  /* [x]xyyzz where [x] empty when x=0 */
-#define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
-static char *sg_version_date = "20190606";
+static int sg_version_num = 40003;  /* [x]xyyzz where [x] empty when x=0 */
+#define SG_VERSION_STR "4.0.03"/* [x]x.[y]y.zz */
+static char *sg_version_date = "20190612";
 
 #include 
 
-- 
2.22.0



[PATCH v3 05/20] sg: bitops in sg_device

2019-08-07 Thread Douglas Gilbert
Introduce bitops in sg_device to replace an atomic, a bool and a
char. That char (sgdebug) had been reduced to only two states.
Add some associated macros to make the code a little clearer.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 104 +++---
 1 file changed, 53 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9aa1b1030033..97ce84f0c51b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -74,6 +74,11 @@ static char *sg_version_date = "20190606";
 
 #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
 
+/* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
+#define SG_FDEV_EXCLUDE0   /* have fd open with O_EXCL */
+#define SG_FDEV_DETACHING  1   /* may be unexpected device removal */
+#define SG_FDEV_LOG_SENSE  2   /* set by ioctl(SG_SET_DEBUG) */
+
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
 /* N.B. This variable is readable and writeable via
/proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
@@ -155,14 +160,12 @@ 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 */
struct mutex open_rel_lock; /* held when in open() or release() */
-   int sg_tablesize;   /* adapter's max scatter-gather table size */
-   u32 index;  /* device index number */
struct list_head sfds;
rwlock_t sfd_lock;  /* protect access to sfd list */
-   atomic_t detaching; /* 0->device usable, 1->device detaching */
-   bool exclude;   /* 1->open(O_EXCL) succeeded and is active */
+   int sg_tablesize;   /* adapter's max scatter-gather table size */
+   u32 index;  /* device index number */
int open_cnt;   /* count of opens (perhaps < num(sfds) ) */
-   char sgdebug;   /* 0->off, 1->sense, 9->dump dev, 10-> all devs 
*/
+   unsigned long fdev_bm[1];   /* see SG_FDEV_* defines above */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */
struct kref d_ref;
@@ -200,6 +203,9 @@ static void sg_device_destroy(struct kref *kref);
 #define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
 #define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
 
+#define SG_IS_DETACHING(sdp) test_bit(SG_FDEV_DETACHING, (sdp)->fdev_bm)
+#define SG_HAVE_EXCLUDE(sdp) test_bit(SG_FDEV_EXCLUDE, (sdp)->fdev_bm)
+
 /*
  * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
  * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
@@ -273,26 +279,26 @@ sg_wait_open_event(struct sg_device *sdp, bool o_excl)
while (sdp->open_cnt > 0) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
+   (SG_IS_DETACHING(sdp) ||
 !sdp->open_cnt));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
} else {
-   while (sdp->exclude) {
+   while (SG_HAVE_EXCLUDE(sdp)) {
mutex_unlock(&sdp->open_rel_lock);
retval = wait_event_interruptible(sdp->open_wait,
-   (atomic_read(&sdp->detaching) ||
-!sdp->exclude));
+   (SG_IS_DETACHING(sdp) ||
+!SG_HAVE_EXCLUDE(sdp)));
mutex_lock(&sdp->open_rel_lock);
 
if (retval) /* -ERESTARTSYS */
return retval;
-   if (atomic_read(&sdp->detaching))
+   if (SG_IS_DETACHING(sdp))
return -ENODEV;
}
}
@@ -354,7 +360,7 @@ sg_open(struct inode *inode, struct file *filp)
goto error_mutex_locked;
}
} else {
-   if (sdp->exclude) {
+   if (SG_HAVE_EXCLUDE(sdp)) {
retval = -EBUSY;
goto error_mutex_locked;
}
@@ -367,10 +373,10 @@ sg_open(struct inode *in

[PATCH v3 04/20] sg: rework sg_poll(), minor changes

2019-08-07 Thread Douglas Gilbert
Re-arrange code in sg_poll(). Rename sg_read_oxfer() to
sg_rd_append(). In sg_start_req() rename rw to r0w.
Plus associated changes demanded by checkpatch.pl

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 65 ++-
 1 file changed, 30 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d14ba4a5441c..9aa1b1030033 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -177,13 +177,13 @@ static int sg_finish_rem_req(struct sg_request *srp);
 static int sg_build_indirect(struct sg_scatter_hold *schp, struct sg_fd *sfp,
 int buff_size);
 static ssize_t sg_new_write(struct sg_fd *sfp, struct file *file,
-   const char __user *buf, size_t count, int blocking,
-   int read_only, int sg_io_owned,
-   struct sg_request **o_srp);
+   const char __user *buf, size_t count, int blocking,
+   int read_only, int sg_io_owned,
+   struct sg_request **o_srp);
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
-static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
-int num_xfer);
+static int sg_rd_append(struct sg_request *srp, char __user *outp,
+   int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
 static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -918,7 +918,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t *ppos)
if (count > old_hdr->reply_len)
count = old_hdr->reply_len;
if (count > SZ_SG_HEADER) {
-   if (sg_read_oxfer(srp, buf, count - SZ_SG_HEADER)) {
+   if (sg_rd_append(srp, buf, count - SZ_SG_HEADER)) {
retval = -EFAULT;
goto free_old_hdr;
}
@@ -1253,38 +1253,34 @@ sg_compat_ioctl(struct file *filp, unsigned int cmd_in, 
unsigned long arg)
 static __poll_t
 sg_poll(struct file *filp, poll_table * wait)
 {
-   __poll_t res = 0;
-   struct sg_device *sdp;
-   struct sg_fd *sfp;
+   __poll_t p_res = 0;
+   struct sg_fd *sfp = filp->private_data;
struct sg_request *srp;
int count = 0;
unsigned long iflags;
 
-   sfp = filp->private_data;
if (!sfp)
return EPOLLERR;
-   sdp = sfp->parentdp;
-   if (!sdp)
-   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 ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
-   res = EPOLLIN | EPOLLRDNORM;
+   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(&sdp->detaching))
-   res |= EPOLLHUP;
-   else if (!sfp->cmd_q) {
-   if (0 == count)
-   res |= EPOLLOUT | EPOLLWRNORM;
-   } else if (count < SG_MAX_QUEUE)
-   res |= EPOLLOUT | EPOLLWRNORM;
-   SG_LOG(3, sfp, "%s: res=0x%x\n", __func__, (__force u32)res);
-   return res;
+   if (sfp->parentdp && atomic_read(&sfp->parentdp->detaching)) {
+   p_res |= EPOLLHUP;
+   } else if (!sfp->cmd_q) {
+   if (count == 0)
+   p_res |= EPOLLOUT | EPOLLWRNORM;
+   } else if (count < SG_MAX_QUEUE) {
+   p_res |= EPOLLOUT | EPOLLWRNORM;
+   }
+   SG_LOG(3, sfp, "%s: p_res=0x%x\n", __func__, (__force u32)p_res);
+   return p_res;
 }
 
 static int
@@ -1801,7 +1797,7 @@ sg_start_req(struct sg_request *srp, u8 *cmd)
struct sg_scatter_hold *rsv_schp = &sfp->reserve;
struct request_queue *q = sfp->parentdp->device->request_queue;
struct rq_map_data *md, map_data;
-   int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
+   int r0w = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
u8 *long_cmdp = NULL;
 
if (hp->cmd_len > BLK_MAX_CDB) {
@@ -1811,7 +1807,7 @@ sg_start_req(struct sg_request *srp, u8 *cmd)
SG_LOG(5, sfp, "%s: long_cmdp=0x%p ++\n", __func__, long_cmdp);
}
SG_LOG(4, sfp, "%s: dxfer_len=%d

[PATCH v3 16/20] sg: expand sg_comm_wr_t

2019-08-07 Thread Douglas Gilbert
The internal struct sg_comm_wr_t was added when the number of
arguments to sg_common_write() became excessive. Expand this idea
so multiple calls to sg_fetch_cmnd() can be deferred until a
scsi_request object is ready to receive the command. This saves
a 252 byte stack allocation on every submit path. Prior to this
and a few other changes, the kernel infrastructure was warning
about excessive stack usage.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 178 --
 1 file changed, 92 insertions(+), 86 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index fb7eeafff801..a60c2bcc5430 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -253,35 +253,37 @@ struct sg_device { /* holds the state of each scsi 
generic device */
 
 struct sg_comm_wr_t {  /* arguments to sg_common_write() */
int timeout;
+   int cmd_len;
unsigned long frq_bm[1];/* see SG_FRQ_* defines above */
union { /* selector is frq_bm.SG_FRQ_IS_V4I */
struct sg_io_hdr *h3p;
struct sg_io_v4 *h4p;
};
-   u8 *cmnd;
+   struct sg_fd *sfp;
+   struct file *filp;
+   const u8 __user *u_cmdp;
 };
 
 /* tasklet or soft irq callback */
 static void sg_rq_end_io(struct request *rq, blk_status_t status);
 /* Declarations of other static functions used before they are defined */
 static int sg_proc_init(void);
-static int sg_start_req(struct sg_request *srp, u8 *cmd, int cmd_len,
-   struct sg_io_v4 *h4p, int dxfer_dir);
+static int sg_start_req(struct sg_request *srp, struct sg_comm_wr_t *cwrp,
+   int dxfer_dir);
 static void sg_finish_scsi_blk_rq(struct sg_request *srp);
 static int sg_mk_sgat(struct sg_request *srp, struct sg_fd *sfp, int minlen);
 static int sg_v3_submit(struct file *filp, struct sg_fd *sfp,
struct sg_io_hdr *hp, bool sync,
struct sg_request **o_srp);
-static struct sg_request *sg_common_write(struct sg_fd *sfp,
- struct sg_comm_wr_t *cwp);
+static struct sg_request *sg_common_write(struct sg_comm_wr_t *cwp);
 static int sg_rd_append(struct sg_request *srp, void __user *outp,
int num_xfer);
 static void sg_remove_sgat(struct sg_request *srp);
 static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
 static void sg_remove_sfp(struct kref *);
 static struct sg_request *sg_find_srp_by_id(struct sg_fd *sfp, int id);
-static struct sg_request *sg_add_request(struct sg_fd *sfp, int dxfr_len,
-struct sg_comm_wr_t *cwrp);
+static struct sg_request *sg_add_request(struct sg_comm_wr_t *cwrp,
+int dxfr_len);
 static void sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
 static struct sg_device *sg_get_dev(int min_dev);
 static void sg_device_destroy(struct kref *kref);
@@ -578,7 +580,6 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
struct sg_device *sdp;
struct sg_fd *sfp;
struct sg_request *srp;
-   u8 cmnd[SG_MAX_CDB_SIZE];
struct sg_header ov2hdr;
struct sg_io_hdr v3hdr;
struct sg_header *ohp = &ov2hdr;
@@ -663,9 +664,6 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
h3p->flags = input_size; /* structure abuse ... */
h3p->pack_id = ohp->pack_id;
h3p->usr_ptr = NULL;
-   cmnd[0] = opcode;
-   if (__copy_from_user(cmnd + 1, p + 1, cmd_size - 1))
-   return -EFAULT;
/*
 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
 * but it is possible that the app intended SG_DXFER_TO_DEV, because
@@ -676,13 +674,16 @@ sg_write(struct file *filp, const char __user *p, size_t 
count, loff_t *ppos)
"%s: data in/out %d/%d bytes for SCSI command 0x%x-- 
guessing data in;\n"
"   program %s not setting count and/or reply_len 
properly\n",
__func__, ohp->reply_len - (int)SZ_SG_HEADER,
-   input_size, (unsigned int)cmnd[0], current->comm);
+   input_size, (unsigned int)opcode, current->comm);
}
-   cwr.frq_bm[0] = 0;  /* initial state clear for all req flags */
+   memset(&cwr, 0, sizeof(cwr));
cwr.h3p = h3p;
cwr.timeout = sfp->timeout;
-   cwr.cmnd = cmnd;
-   srp = sg_common_write(sfp, &cwr);
+   cwr.cmd_len = cmd_size;
+   cwr.filp = filp;
+   cwr.sfp = sfp;
+   cwr.u_cmdp = p;
+   srp = sg_common_write(&cwr);
return (IS_ERR(srp)) ? PTR_ERR(srp) : (int)count;
 }
 
@@ -711,11 +712,9 @@ static int
 sg_v3_submit(struct file *filp, struct sg_fd *sfp, struct sg_io_hdr *hp,
 bool 

[PATCH v3 03/20] sg: sg_log and is_enabled

2019-08-07 Thread Douglas Gilbert
Replace SCSI_LOG_TIMEOUT macros with SG_LOG macros across the driver.
The definition of SG_LOG calls SCSI_LOG_TIMEOUT if given and derived
pointers are non-zero, calls pr_info otherwise. SG_LOGS additionally
prints the sg device name and the thread id. The thread id is very
useful, even in single threaded invocations because the driver not
only uses the invocer's thread but also uses work queues and the
main callback (i.e. sg_rq_end_io()) may hit any thread. Some
interesting cases arise when the callback hits its invocer's
thread.

SG_LOGS takes 48 bytes on the stack to build this printf format
string: "sg%u: tid=%d" whose size is clearly bounded above by
the maximum size of those two integers.
Protecting against the 'current' pointer being zero is for safety
and the case where the boot device is SCSI and the sg driver is
built into the kernel. Also when debugging, getting a message
from a compromised kernel can be very useful in pinpointing the
location of the failure.

The simple fact that the SG_LOG macro is shorter than
SCSI_LOG_TIMEOUT macro allow more error message "payload" per line.

Also replace #if and #ifdef conditional compilations with
the IS_ENABLED macro.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 252 +++---
 1 file changed, 125 insertions(+), 127 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6615777931f7..d14ba4a5441c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -57,6 +57,15 @@ static char *sg_version_date = "20190606";
 
 #define SG_MAX_DEVS 32768
 
+/* Comment out the following line to compile out SCSI_LOGGING stuff */
+#define SG_DEBUG 1
+
+#if !IS_ENABLED(SG_DEBUG)
+#if IS_ENABLED(DEBUG)  /* If SG_DEBUG not defined, check for DEBUG */
+#define SG_DEBUG DEBUG
+#endif
+#endif
+
 /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
  * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
  * than 16 bytes are "variable length" whose length is a multiple of 4
@@ -174,7 +183,7 @@ static ssize_t sg_new_write(struct sg_fd *sfp, struct file 
*file,
 static int sg_common_write(struct sg_fd *sfp, struct sg_request *srp,
   u8 *cmnd, int timeout, int blocking);
 static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
-int num_read_xfer);
+int num_xfer);
 static void sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp);
 static void sg_build_reserve(struct sg_fd *sfp, int req_size);
 static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -187,14 +196,45 @@ static int sg_remove_request(struct sg_fd *sfp, struct 
sg_request *srp);
 static struct sg_device *sg_get_dev(int dev);
 static void sg_device_destroy(struct kref *kref);
 
-#define SZ_SG_HEADER sizeof(struct sg_header)
-#define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
-#define SZ_SG_IOVEC sizeof(sg_iovec_t)
-#define SZ_SG_REQ_INFO sizeof(sg_req_info_t)
+#define SZ_SG_HEADER ((int)sizeof(struct sg_header))   /* v1 and v2 header */
+#define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))   /* v3 header */
+#define SZ_SG_REQ_INFO ((int)sizeof(struct sg_req_info))
+
+/*
+ * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
+ * 'depth' is a number between 1 (most severe) and 7 (most noisy, most
+ * information). All messages are logged as informational (KERN_INFO). In
+ * the unexpected situation where sfp or sdp is NULL the macro reverts to
+ * a pr_info and ignores SCSI_LOG_TIMEOUT and always prints to the log.
+ * Example: this invocation: 'scsi_logging_level -s -T 3' will print
+ * depth (aka level) 1 and 2 SG_LOG() messages.
+ */
+
+#define SG_PROC_DEBUG_SZ 8192
+
+#if IS_ENABLED(CONFIG_SCSI_LOGGING) && IS_ENABLED(SG_DEBUG)
+#define SG_LOG_BUFF_SZ 48
+
+#define SG_LOG(depth, sfp, fmt, a...)  \
+   do {\
+   char _b[SG_LOG_BUFF_SZ];\
+   int _tid = (current ? current->pid : -1);   \
+   struct sg_fd *_fp = sfp;\
+   struct sg_device *_sdp = _fp ? _fp->parentdp : NULL;\
+   \
+   if (likely(_sdp && _sdp->disk)) {   \
+   snprintf(_b, sizeof(_b), "sg%u: tid=%d",\
+_sdp->index, _tid);\
+   SCSI_LOG_TIMEOUT(depth, \
+sdev_prefix_printk(KERN_INFO,  \
+_sdp->device, _b, fmt, ##a));  \
+   } else  \
+

[PATCH v3 17/20] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls

2019-08-07 Thread Douglas Gilbert
Add ioctl(SG_IOSUBMIT_V3) and ioctl(SG_IORECEIVE_V3). These ioctls
are meant to be (almost) drop-in replacements for the write()/read()
async version 3 interface. They only accept the version 3 interface.

See the webpage at: http://sg.danny.cz/sg/sg_v40.html
specifically the table in the section titled: "12 SG interface
support changes".

If sgv3 is a struct sg_io_hdr object, suitably configured, then
res = write(sg_fd, &sgv3, sizeof(sgv3));
and
res = ioctl(sg_fd, SG_IOSUBMIT_V3, &sgv3);
are equivalent. Dito for read() and ioctl(SG_IORECEIVE_V3).

Signed-off-by: Douglas Gilbert 
Reported-by: kbuild test robot 

-
kbuild had two complaints about this commit:
  - casting a pointer to u64: add intermediate cast to
unsigned long. Would only seem to be a problem if
a pointer couldn't fit in u64 in which case the
sg v4 interface would be broken and lots of other
things besides ...
  - a possible uninitialized  variable:
__maybe_unused bool is_bad_st = false;
__maybe_unused enum sg_rq_state bad_sr_st; /* <-- here */
The boolean (is_bad_st) tracks whether it has a "valid"
string or not. kbuild doesn't undrstand that. Give bad_sr_st
an initial value to keep kbuild quiet at the expense of a
    machine cycle or two.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c  | 79 --
 include/uapi/scsi/sg.h |  6 
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index a60c2bcc5430..aa3512b2cb4f 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -806,6 +806,24 @@ sg_ctl_iosubmit(struct file *filp, struct sg_fd *sfp, void 
__user *p)
return -EPERM;
 }
 
+static int
+sg_ctl_iosubmit_v3(struct file *filp, struct sg_fd *sfp, void __user *p)
+{
+   int res;
+   u8 hdr_store[SZ_SG_IO_V4];  /* max(v3interface, v4interface) */
+   struct sg_io_hdr *h3p = (struct sg_io_hdr *)hdr_store;
+   struct sg_device *sdp = sfp->parentdp;
+
+   res = sg_allow_if_err_recovery(sdp, (filp->f_flags & O_NONBLOCK));
+   if (unlikely(res))
+   return res;
+   if (copy_from_user(h3p, p, SZ_SG_IO_HDR))
+   return -EFAULT;
+   if (h3p->interface_id == 'S')
+   return sg_v3_submit(filp, sfp, h3p, false, NULL);
+   return -EPERM;
+}
+
 static void
 sg_execute_cmd(struct sg_fd *sfp, struct sg_request *srp)
 {
@@ -1107,7 +1125,7 @@ sg_v4_receive(struct sg_fd *sfp, struct sg_request *srp, 
void __user *p,
h4p->din_resid = srp->in_resid;
h4p->dout_resid = srp->s_hdr4.out_resid;
h4p->usr_ptr = srp->s_hdr4.usr_ptr;
-   h4p->response = (u64)srp->s_hdr4.sbp;
+   h4p->response = (u64)(unsigned long)srp->s_hdr4.sbp;
h4p->request_extra = srp->pack_id;
if (p) {
if (copy_to_user(p, h4p, SZ_SG_IO_V4))
@@ -1170,6 +1188,57 @@ sg_ctl_ioreceive(struct file *filp, struct sg_fd *sfp, 
void __user *p)
return sg_v4_receive(sfp, srp, p, h4p);
 }
 
+/*
+ * Called when ioctl(SG_IORECEIVE_V3) received. Expects a v3 interface.
+ * Checks if O_NONBLOCK file flag given, if not checks given flags field
+ * to see if SGV4_FLAG_IMMED is set. Either of these implies non blocking.
+ * When non-blocking and there is no request waiting, yields EAGAIN;
+ * otherwise it waits.
+ */
+static int
+sg_ctl_ioreceive_v3(struct file *filp, struct sg_fd *sfp, void __user *p)
+{
+   bool non_block = !!(filp->f_flags & O_NONBLOCK);
+   int res;
+   int pack_id = SG_PACK_ID_WILDCARD;
+   u8 v3_holder[SZ_SG_IO_HDR];
+   struct sg_io_hdr *h3p = (struct sg_io_hdr *)v3_holder;
+   struct sg_device *sdp = sfp->parentdp;
+   struct sg_request *srp;
+
+   res = sg_allow_if_err_recovery(sdp, non_block);
+   if (unlikely(res))
+   return res;
+   /* Get first three 32 bit integers: guard, proto+subproto */
+   if (copy_from_user(h3p, p, SZ_SG_IO_HDR))
+   return -EFAULT;
+   /* for v3: interface_id=='S' (in a 32 bit int) */
+   if (h3p->interface_id != 'S')
+   return -EPERM;
+   if (h3p->flags & SGV4_FLAG_IMMED)
+   non_block = true;   /* set by either this or O_NONBLOCK */
+   SG_LOG(3, sfp, "%s: non_block(+IMMED)=%d\n", __func__, non_block);
+
+   if (test_bit(SG_FFD_FORCE_PACKID, sfp->ffd_bm))
+   pack_id = h3p->pack_id;
+
+   srp = sg_find_srp_by_id(sfp, pack_id);
+   if (!srp) { /* nothing available so wait on packet or */
+   if (unlikely(SG_IS_DETACHING(sdp)))
+   return -ENODEV;
+   if (non_block)
+   return -EAGAIN;
+   res = wait_event_interruptible
+   (sfp->read_wait,
+  

[PATCH v3 07/20] sg: move header to uapi section

2019-08-07 Thread Douglas Gilbert
Move user interface part of scsi/sg.h into the new header file:
include/uapi/scsi/sg.h . Since scsi/sg.h includes the new header,
other code including scsi/sg.h should not be impacted.

Signed-off-by: Douglas Gilbert 
Reported-by: kbuild test robot 

-
kbuild noted a problem with including  in
include/uapi/scsi/sg.h that should be fixed by changing
the bsg.h include to 

Signed-off-by: Douglas Gilbert 
---
 include/scsi/sg.h  | 268 ++---
 include/uapi/scsi/sg.h | 329 +
 2 files changed, 338 insertions(+), 259 deletions(-)
 create mode 100644 include/uapi/scsi/sg.h

diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index f91bcca604e4..46fc7cbffd78 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -4,271 +4,21 @@
 
 #include 
 
-/*
- * History:
- *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com), to allow user
- *   process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
- *
- * Original driver (sg.h):
- *   Copyright (C) 1992 Lawrence Foard
- * Version 2 and 3 extensions to driver:
- * Copyright (C) 1998 - 2014 Douglas Gilbert
- *
- *  Version: 3.5.36 (20140603)
- *  This version is for 2.6 and 3 series kernels.
- *
- * Documentation
- * =
- * A web site for the SG device driver can be found at:
- * http://sg.danny.cz/sg  [alternatively check the MAINTAINERS file]
- * The documentation for the sg version 3 driver can be found at:
- * http://sg.danny.cz/sg/p/sg_v3_ho.html
- * Also see: /Documentation/scsi/scsi-generic.txt
- *
- * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html
- */
-
 #ifdef __KERNEL__
 extern int sg_big_buff; /* for sysctl */
 #endif
 
+/*
+ * In version 3.9.01 of the sg driver, this file was spilt in two, with the
+ * bulk of the user space interface being placed in the file being included
+ * in the following line.
+ */
+#include 
 
-typedef struct sg_iovec /* same structure as used by readv() Linux system */
-{   /* call. It defines one scatter-gather element. */
-void __user *iov_base;  /* Starting address  */
-size_t iov_len; /* Length in bytes  */
-} sg_iovec_t;
-
-
-typedef struct sg_io_hdr
-{
-int interface_id;   /* [i] 'S' for SCSI generic (required) */
-int dxfer_direction;/* [i] data transfer direction  */
-unsigned char cmd_len;  /* [i] SCSI command length */
-unsigned char mx_sb_len;/* [i] max length to write to sbp */
-unsigned short iovec_count; /* [i] 0 implies no scatter gather */
-unsigned int dxfer_len; /* [i] byte count of data transfer */
-void __user *dxferp;   /* [i], [*io] points to data transfer memory
- or scatter gather list */
-unsigned char __user *cmdp; /* [i], [*i] points to command to perform */
-void __user *sbp;  /* [i], [*o] points to sense_buffer memory */
-unsigned int timeout;   /* [i] MAX_UINT->no timeout (unit: millisec) */
-unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */
-int pack_id;/* [i->o] unused internally (normally) */
-void __user * usr_ptr;  /* [i->o] unused internally */
-unsigned char status;   /* [o] scsi status */
-unsigned char masked_status;/* [o] shifted, masked scsi status */
-unsigned char msg_status;   /* [o] messaging level data (optional) */
-unsigned char sb_len_wr;/* [o] byte count actually written to sbp */
-unsigned short host_status; /* [o] errors from host adapter */
-unsigned short driver_status;/* [o] errors from software driver */
-int resid;  /* [o] dxfer_len - actual_transferred */
-unsigned int duration;  /* [o] time taken by cmd (unit: millisec) */
-unsigned int info;  /* [o] auxiliary information */
-} sg_io_hdr_t;  /* 64 bytes long (on i386) */
-
-#define SG_INTERFACE_ID_ORIG 'S'
-
-/* Use negative values to flag difference from original sg_header structure */
-#define SG_DXFER_NONE (-1)  /* e.g. a SCSI Test Unit Ready command */
-#define SG_DXFER_TO_DEV (-2)/* e.g. a SCSI WRITE command */
-#define SG_DXFER_FROM_DEV (-3)  /* e.g. a SCSI READ command */
-#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
-  additional property than during indirect
-  IO the user buffer is copied into the
-  kernel buffers before the transfer */
-#define SG_DXFER_UNKNOWN (-5)   /* Unknown data direction */
-
-/* following flag values can be "or"-ed together */
-#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
-#define SG_FLAG_UNUSED_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
-   /* command block (when <= SCSI_2) */
-#define SG_FLAG_MMAP_IO 4 

[PATCH v3 08/20] sg: speed sg_poll and sg_get_num_waiting

2019-08-07 Thread Douglas Gilbert
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 
---
 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

[PATCH v3 02/20] sg: remove typedefs, type+formatting cleanup

2019-08-07 Thread Douglas Gilbert
Typedefs for structure types are discouraged so those structures
that are private to the driver have had their typedefs removed.

This also means that most "camel" type variable names (i.e. mixed
case) have been removed.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sg.c | 394 ++
 1 file changed, 219 insertions(+), 175 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9f1587761d86..6615777931f7 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -3,7 +3,7 @@
  *  History:
  *  Started: Aug 9 by Lawrence Foard (entr...@world.std.com),
  *   to allow user process control of SCSI devices.
- *  Development Sponsored by Killy Corp. NY NY
+ *  Development Sponsored by Killy Corp. NY NY   [1992 ??]
  *
  * Original driver (sg.c):
  *Copyright (C) 1992 Lawrence Foard
@@ -15,13 +15,6 @@ static int sg_version_num = 30901;  /* [x]xyyzz where [x] 
empty when x=0 */
 #define SG_VERSION_STR "3.9.01"/* [x]x.[y]y.zz */
 static char *sg_version_date = "20190606";
 
-/*
- *  D. P. Gilbert (dgilb...@interlog.com), notes:
- *  - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
- *the kernel/module needs to be built with CONFIG_SCSI_LOGGING
- *(otherwise the macros compile to empty statements).
- *
- */
 #include 
 
 #include 
@@ -91,33 +84,32 @@ static int sg_add_device(struct device *, struct 
class_interface *);
 static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
-static DEFINE_RWLOCK(sg_index_lock);   /* Also used to lock
-  file descriptor list 
for device */
+static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock fd list for device */
 
 static struct class_interface sg_interface = {
.add_dev= sg_add_device,
.remove_dev = sg_remove_device,
 };
 
-typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info 
*/
-   unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
-   unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */
-   unsigned bufflen;   /* Size of (aggregate) data buffer */
+struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+   u16 k_use_sg; /* Count of kernel scatter-gather pieces */
+   unsigned int sglist_len; /* size of malloc'd scatter-gather list ++ */
+   unsigned int bufflen;   /* Size of (aggregate) data buffer */
struct page **pages;
int page_order;
char dio_in_use;/* 0->indirect IO (or mmap), 1->dio */
-   unsigned char cmd_opcode; /* first byte of command */
-} Sg_scatter_hold;
+   u8 cmd_opcode;  /* first byte of command */
+};
 
 struct sg_device;  /* forward declarations */
 struct sg_fd;
 
-typedef struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
+struct sg_request {/* SG_MAX_QUEUE requests outstanding per file */
struct list_head entry; /* list entry */
struct sg_fd *parentfp; /* NULL -> not in use */
-   Sg_scatter_hold data;   /* hold buffer, perhaps scatter list */
+   struct sg_scatter_hold data;/* hold buffer, perhaps scatter list */
sg_io_hdr_t header; /* scsi command+info, see  */
-   unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
+   u8 sense_b[SCSI_SENSE_BUFFERSIZE];
char res_used;  /* 1 -> using reserve buffer, 0 -> not ... */
char orphan;/* 1 -> drop on sight, 0 -> normal */
char sg_io_owned;   /* 1 -> packet belongs to SG_IO */
@@ -126,9 +118,9 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests 
outstanding per file */
struct request *rq;
struct bio *bio;
struct execute_work ew;
-} Sg_request;
+};
 
-typedef struct sg_fd { /* holds the state of a file descriptor */
+struct sg_fd { /* holds the state of a file descriptor */
struct list_head sfd_siblings;  /* protected by device's sfd_lock */
struct sg_device *parentdp; /* owning device */
wait_queue_head_t read_wait;/* queue read until command done */
@@ -136,21 +128,21 @@ typedef 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 */
-   Sg_scatter_hold reserve;/* buffer held for this file descriptor 
*/
+   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 */
-   Sg_request req_arr[SG_MAX_QUEUE];   /* used as singly-lin

Re: [PATCH 13/14] megaraid_sas: NVME passthru command support

2018-01-10 Thread Douglas Gilbert

On 2018-01-10 11:22 AM, Bart Van Assche wrote:

On Tue, 2018-01-09 at 22:07 +0530, Kashyap Desai wrote:

Overall NVME support behind MR controller is really a SCSI device. On top
of that, for MegaRaid, NVME device can be part of Virtual Disk and those
drive will not be exposed to the driver. User application may like to talk
to hidden NVME devices (part of VDs). This patch will extend the existing
interface for megaraid product in the same way it is currently supported
for other protocols like SMP, SATA pass-through.


It seems to me like there is a contradiction in the above paragraph: if some
NVMe devices are not exposed to the driver, how can a user space application
ever send NVMe commands to it?


I think that he meant that the NVMe physical devices (e.g. SSDs) are not
exposed to the upper layers (e.g. the SCSI mid-layer and above). The
SCSI subsystem has a no_uld_attach device flag that lets a LLD attach
physical devices but the sd driver and hence the block layer do not
"see" them. The idea is that maintenance programs like smartmontools
can use them via the bsg or sg drivers. The Megaraid driver code does
not seem to use no_uld_attach. Does the NVMe subsystem have similar
"generic" (i.e. non-block) devices accessible to the user space?


Anyway, has it been considered to implement the NVMe support as an NVMe
transport driver? The upstream kernel already supports NVMe communication
with NVMe PCI devices, NVMe over RDMA and NVMe over FC. If communication to
the NVMe devices behind the MegaRaid controller would be implemented as an
NVMe transport driver then all functionality of the Linux NVMe driver could
be reused, including its sysfs entries.


Broadcom already sell "SAS" HBAs that have "tri-mode" phys. That is a phy
that can connect to a SAS device (e.g. a SAS expander), a SATA device or a
NVMe device. Now if I was Broadcom designing a 24 Gbps SAS-4 next generation
expander I would be thinking of using those tri-mode phys on it. But then
there is a problem, SAS currently supports 3 protocols: SSP (for SCSI
storage and enclosure management (SES)), STP (for SATA storage ) and SMP
(for expander management). The problem is how those NVMe commands, status
and data cross the wire between the OS HBA (or MegaRaid type controller) and
an expander. Solving that might need some lateral thinking.

On one hand the NVM Express folks seem to have shelved the idea of a SCSI
to NVMe Translation Layer (SNTL) and have not updated an old white paper
on the subject. Currently there is no SNTL on Linux (there was but it was
removed) or FreeBSD but there is one on Windows.

On the other hand I'm informed that recently the same body accepted the
SES-3 standard pretty much as-is. That is done with the addition of SES
Send and SES Receive commands to NVME-MI. The library under sg_ses has
already been modified to use them (by implementing a specialized SNTL).

Doug Gilbert



[PATCH 1/1] scsi_debug: delay stress fix

2018-01-10 Thread Douglas Gilbert
Introduce a state enum into sdebug_defer objects to indicate which,
if any, defer method has been used with the associated command.
Also add 2 bools to indicate which of the defer methods has been
initialized. Those objects are re-used but the initialization
only needs to be done once. This simplifies command cancellation
handling.

Now the delay associated with a deferred response of a command
cannot be changed (once started) by changing the delay (and ndelay)
parameters in sysfs. Command aborts and driver shutdown are still
honoured immediately when received.

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 72 ++-
 1 file changed, 46 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index e4f037f0f38b..f5d0098b5a6a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -263,12 +263,18 @@ struct sdebug_host_info {
 #define to_sdebug_host(d)  \
container_of(d, struct sdebug_host_info, dev)
 
+enum sdeb_defer_type {SDEB_DEFER_NONE = 0, SDEB_DEFER_HRT = 1,
+ SDEB_DEFER_WQ = 2};
+
 struct sdebug_defer {
struct hrtimer hrt;
struct execute_work ew;
int sqa_idx;/* index of sdebug_queue array */
int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */
int issuing_cpu;
+   bool init_hrt;
+   bool init_wq;
+   enum sdeb_defer_type defer_t;
 };
 
 struct sdebug_queued_cmd {
@@ -3495,6 +3501,7 @@ static void sdebug_q_cmd_complete(struct sdebug_defer 
*sd_dp)
struct scsi_cmnd *scp;
struct sdebug_dev_info *devip;
 
+   sd_dp->defer_t = SDEB_DEFER_NONE;
qc_idx = sd_dp->qc_idx;
sqp = sdebug_q_arr + sd_dp->sqa_idx;
if (sdebug_statistics) {
@@ -3678,13 +3685,14 @@ static void scsi_debug_slave_destroy(struct scsi_device 
*sdp)
}
 }
 
-static void stop_qc_helper(struct sdebug_defer *sd_dp)
+static void stop_qc_helper(struct sdebug_defer *sd_dp,
+  enum sdeb_defer_type defer_t)
 {
if (!sd_dp)
return;
-   if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0))
+   if (defer_t == SDEB_DEFER_HRT)
hrtimer_cancel(&sd_dp->hrt);
-   else if (sdebug_jdelay < 0)
+   else if (defer_t == SDEB_DEFER_WQ)
cancel_work_sync(&sd_dp->ew.work);
 }
 
@@ -3694,6 +3702,7 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
 {
unsigned long iflags;
int j, k, qmax, r_qmax;
+   enum sdeb_defer_type l_defer_t;
struct sdebug_queue *sqp;
struct sdebug_queued_cmd *sqcp;
struct sdebug_dev_info *devip;
@@ -3717,8 +3726,13 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
atomic_dec(&devip->num_in_q);
sqcp->a_cmnd = NULL;
sd_dp = sqcp->sd_dp;
+   if (sd_dp) {
+   l_defer_t = sd_dp->defer_t;
+   sd_dp->defer_t = SDEB_DEFER_NONE;
+   } else
+   l_defer_t = SDEB_DEFER_NONE;
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
-   stop_qc_helper(sd_dp);
+   stop_qc_helper(sd_dp, l_defer_t);
clear_bit(k, sqp->in_use_bm);
return true;
}
@@ -3733,6 +3747,7 @@ static void stop_all_queued(void)
 {
unsigned long iflags;
int j, k;
+   enum sdeb_defer_type l_defer_t;
struct sdebug_queue *sqp;
struct sdebug_queued_cmd *sqcp;
struct sdebug_dev_info *devip;
@@ -3751,8 +3766,13 @@ static void stop_all_queued(void)
atomic_dec(&devip->num_in_q);
sqcp->a_cmnd = NULL;
sd_dp = sqcp->sd_dp;
+   if (sd_dp) {
+   l_defer_t = sd_dp->defer_t;
+   sd_dp->defer_t = SDEB_DEFER_NONE;
+   } else
+   l_defer_t = SDEB_DEFER_NONE;
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
-   stop_qc_helper(sd_dp);
+   stop_qc_helper(sd_dp, l_defer_t);
clear_bit(k, sqp->in_use_bm);
spin_lock_irqsave(&sqp->qc_lock, iflags);
}
@@ -4003,7 +4023,7 @@ static void setup_inject(struct sdebug_queue *sqp,
  * SCSI_MLQUEUE_HOST_BUSY if temporarily out of resources.
  */
 static int 

[PATCH 0/1] scsi_debug: delay stress fix

2018-01-10 Thread Douglas Gilbert
Bart Van Assche reported that when the scsi_debug driver was being
stress tested with fio, changing the delay paremeter via sysfs
caused a cascade of oops-es. The fix presented reads the driver
wide delay values (jiffies or nanoseconds) once and remembers in
the sdebug_defer object which defer method is used and which 
method has been initialized. This simplifies handling when command
aborts occur.

This causes a minor changes in semantic: a SCSI command "in
flight" is no longer impacted by changing the delay option
after it has been scheduled (i.e. while it is waiting for a work
queue or a hr timer to exhaust).

Douglas Gilbert (1):
  scsi_debug: delay fix

 drivers/scsi/scsi_debug.c | 72 ++-
 1 file changed, 46 insertions(+), 26 deletions(-)

-- 
2.14.1



Re: scsi: memory leak in sg_start_req

2018-01-10 Thread Douglas Gilbert

On 2018-01-09 11:05 AM, Dmitry Vyukov wrote:

Hello,

syzkaller has found the following memory leak:

unreferenced object 0x88004c19 (size 8328):
   comm "syz-executor", pid 4627, jiffies 4294749150 (age 45.507s)
   hex dump (first 32 bytes):
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
 20 00 00 00 22 01 00 00 00 00 00 00 04 00 00 00   ..."...
   backtrace:
 [<5955b5a9>] kmalloc_order+0x59/0x80 mm/slab_common.c:1124
 [<43ae006e>] kmalloc_order_trace+0x1f/0x160 mm/slab_common.c:1133
 [] kmalloc_large include/linux/slab.h:433 [inline]
 [] __kmalloc+0x2c4/0x340 mm/slub.c:3751
 [] kmalloc include/linux/slab.h:504 [inline]
 [] bio_alloc_bioset+0x4d5/0x7e0 block/bio.c:450
 [] bio_kmalloc include/linux/bio.h:410 [inline]
 [] bio_copy_user_iov+0x2be/0xcb0 block/bio.c:1226
 [<1d0b79ed>] __blk_rq_map_user_iov block/blk-map.c:67 [inline]
 [<1d0b79ed>] blk_rq_map_user_iov+0x2b6/0x7d0 block/blk-map.c:136
 [<4200a869>] blk_rq_map_user+0x11e/0x170 block/blk-map.c:166
 [<8f21739e>] sg_start_req drivers/scsi/sg.c:1794 [inline]
 [<8f21739e>] sg_common_write.isra.16+0x14df/0x1ed0
drivers/scsi/sg.c:777
 [<093f61e3>] sg_write+0x8a7/0xd7b drivers/scsi/sg.c:677
 [] __vfs_write+0x10d/0x8f0 fs/read_write.c:480
 [<0638f16f>] vfs_write+0x1fd/0x570 fs/read_write.c:544
 [<6a7e6867>] SYSC_write fs/read_write.c:589 [inline]
 [<6a7e6867>] SyS_write+0xfa/0x250 fs/read_write.c:581

can be reproduced with the following program:

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include 
#include 
#include 
#include 

int main()
{
   int fd = open("/dev/sg1", O_RDWR);
   const char *data =
  "\xb6\x3d\xb8\x5e\x1e\x8d\x22\x00\x00\x00\x00\x00\x00\x08\xaf\xd6\x1d"
  "\xcc\x43\x6a\xed\x5e\xd2\xbc\x70\x18\xce\xbc\x9b\x97\xae\x21\x91\x4d"
  "\x87\x2c\x67\x8c\xe2\x2c\x9b\x16\x0e\x96\xaa\x1f\xae\x1a";
   write(fd, data, 0x30);
   return 0;
}

if executed in a loop, memory consumption grows infinitely.

on upstream commit b2cd1df66037e7c4697c7e40496bf7e4a5e16a2d


The seemingly random data that program is sending is asking for
a buffer of 2,264,314 bytes which the sg driver procures and waits
for the caller to either issue a read() or close() the file
or shutdown the program. The test program does none of those
expected operations, it simply asks for the same resources again.

In my version of your test code (attached), that happens 1,021 times
at which point the file handles in that process are exhausted and
all subsequent open()s fail with EBADF (as do the write()s). The
output from my program was this on one run:

# ./sg_syzk_grow
First errno=9 [Bad file descriptor] index=1021
done_count=5, err_count=48979, last_errno=9 [Bad file descriptor]

# lsscsi -gs
[0:0:0:0]  disk  Linux  scsi_debug  0186  /dev/sda  /dev/sg0  2.14GB

Monitoring that program with 'free' from another terminal I see
about 2.5 GBytes of ram "swallowed" almost immediately when the test
program runs. When the program exits (about 50 seconds later) as far
as I can see all that ram is given back.


If you used the same program and wrote to a regular file rather than
a sg device, then that program would eventually fill any file system,
at the rate of 48 bytes per iteration (given enough file descriptor
resources). The sg driver, using its original 1994 interface,
deprecated for around 18 years, just gets a system to resource
exhaustion quicker.

Doug Gilbert




// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static const char * sg_dev = "/dev/sg0";

int main()
{
  const char *data =
 "\xb6\x3d\xb8\x5e\x1e\x8d\x22\x00\x00\x00\x00\x00\x00\x08\xaf\xd6\x1d"
 "\xcc\x43\x6a\xed\x5e\xd2\xbc\x70\x18\xce\xbc\x9b\x97\xae\x21\x91\x4d"
 "\x87\x2c\x67\x8c\xe2\x2c\x9b\x16\x0e\x96\xaa\x1f\xae\x1a";
int k, res, first_errno, prev_errno, first_err_index;
int err_count = 0;
int done_count = 0;
bool got_1st_errno = false;

for (k = 0; k < 1; ++k) {
int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0) {
	if (! got_1st_errno) {
		got_1st_errno = true;
		first_errno = errno;
		first_err_index = done_count + k;
		printf("First errno=%d [%s] index=%d\n", first_errno,
		   strerror(first_errno), first_err_index);
	}
	++err_count;
	}
}
done_count += k;
sleep(10);
for (k = 0; k < 1; ++k) {
int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0) {
	if (! got_1st_errno) {
		got_1st_errno = true;
		first_errno = errno;
		printf("First errno=%d [%s] index=%d\n", first_errno,
		   strerror(f

[PATCH] blk_rq_map_user_iov: fix error override

2018-01-14 Thread Douglas Gilbert
During stress tests by syzkaller on the sg driver the block layer
infrequently returns EINVAL. Closer inspection shows the block
layer was trying to return ENOMEM (which is much more
understandable) but for some reason overroad that useful error.

Patch below does not show this (unchanged) line:
   ret =__blk_rq_map_user_iov(rq, map_data, &i, gfp_mask, copy);
That 'ret' was being overridden when that function failed.

Signed-off-by: Douglas Gilbert 
---
 block/blk-map.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/blk-map.c b/block/blk-map.c
index d3a94719f03f..db9373bd31ac 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -119,7 +119,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct 
request *rq,
unsigned long align = q->dma_pad_mask | queue_dma_alignment(q);
struct bio *bio = NULL;
struct iov_iter i;
-   int ret;
+   int ret = -EINVAL;
 
if (!iter_is_iovec(iter))
goto fail;
@@ -148,7 +148,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct 
request *rq,
__blk_rq_unmap_user(bio);
 fail:
rq->bio = NULL;
-   return -EINVAL;
+   return ret;
 }
 EXPORT_SYMBOL(blk_rq_map_user_iov);
 
-- 
2.14.1



Re: scsi: sg: assorted memory corruptions

2018-01-22 Thread Douglas Gilbert

On 2018-01-22 11:30 AM, Bart Van Assche wrote:

On Mon, 2018-01-22 at 12:06 +0100, Dmitry Vyukov wrote:

general protection fault:  [#1] SMP KASAN


How about the untested patch below?

Thanks,

Bart.


diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index cd9b6ebd7257..04a644b39d79 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -627,6 +627,10 @@ sg_write(struct file *filp, const char __user *buf, size_t 
count, loff_t * ppos)
mutex_unlock(&sfp->f_mutex);
SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp,
"sg_write:   scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, 
cmd_size));
+   if (cmd_size > sizeof(cmnd)) {
+   sg_remove_request(sfp, srp);
+   return -EFAULT;
+   }
/* Determine buffer size.  */
input_size = count - cmd_size;
mxsize = max(input_size, old_hdr.reply_len);



Using 'scsi_logging_level -s -T 5' on the sg driver and running the test
program provided, the cmd_size is 9, just like the ioctl() in his program
set it to. The sizeof(cmnd) is 252. So I don't know what caused the
GPF but it wasn't cmd_size being out of bounds.

As for the above patch, did you notice this check in that function:

if ((!hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof (cmnd))) {
sg_remove_request(sfp, srp);
return -EMSGSIZE;
}

As far as I remember, Dmitry has not indicated in multiple reports
over several years what /dev/sg0 is. Perhaps it misbehaves when it
gets a SCSI command in the T10 range (i.e. not vendor specific) with
a 9 byte cdb length. As far as I'm aware T10 (and the Ansi committee
before it) have never defined a cdb with an odd length.

For those that are not aware, the sg driver is a relatively thin
shim over the block layer, the SCSI mid-level, and a low-level
driver which may have another kernel driver stack underneath it
(e.g. UAS (USB attached SCSI)). The previous report from syzkaller
on the sg driver ("scsi: memory leak in sg_start_req") has resulted
in one accepted patch on the block layer with probably more to
come in the same area.

Testing the patch Dmitry gave (with some added error checks which
reported no problems) with the scsi_debug driver supplying /dev/sg0
I have not seen any problems running that test program. Again
there might be a very slow memory leak, but if there is I don't
believe it is in the sg driver.


While it's not invalid from a testing perspective, throwing total
nonsense at a pass-through mechanism, including absurd SCSI commands
at best will test error paths, but only at a very shallow level.
Setting up almost valid pass-through scenarios will test error
paths at a deeper level. Then there are lots of valid pass-through
scenarios that would be expected not to fail.

Doug Gilbert


Re: [PATCH] scsi_debug: Use scsi-mq if it has been enabled

2018-01-23 Thread Douglas Gilbert

On 2018-01-23 07:39 PM, Bart Van Assche wrote:

Since we want to remove the single queue code from the SCSI core
at the appropriate time and since scsi-mq performs better than
scsi-sq even when using only a single hardware queue, use scsi-mq
if it has been enabled.

Signed-off-by: Bart Van Assche 
Cc: Douglas Gilbert 
Cc: Hannes Reinecke 
Cc: Christoph Hellwig 


Acked: Douglas Gilbert 


---
  drivers/scsi/scsi_debug.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a5986dae9020..40df3eea72c8 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -5782,7 +5782,7 @@ static int sdebug_driver_probe(struct device * dev)
}
/* Decide whether to tell scsi subsystem that we want mq */
/* Following should give the same answer for each host */
-   sdebug_mq_active = shost_use_blk_mq(hpnt) && (submit_queues > 1);
+   sdebug_mq_active = shost_use_blk_mq(hpnt);
if (sdebug_mq_active)
hpnt->nr_hw_queues = submit_queues;
  





Mishandling SCSI status CONDITION MET

2018-01-26 Thread Douglas Gilbert

Summary: CONDITION MET is a GOOD status but the mid-level logs it as if
it were an error.

If you scan recent SPC and SBC drafts you will find only two commands that
yield the SCSI status CONDITION MET: PRE-FETCH(10) and PRE_FETCH(16).
Those commands are like READ but don't return the data instead they try
to cache it. And those commands have an IMMED bit. The idea is the
PRE-FETCH will start putting the identified LBA and the following given
number of blocks into the cache. The assumption is a following READ will
be able to fetch that data faster (from the cache rather than flash
or magnetic media).

The definition of PRE-FETCH has two situations it tries to report:
  1) the specified data will fit in the cache: report a status
 of CONDITION MET
  2) the specified data will not fit in the cache: report a status
 of GOOD

Yes, I wrote that correctly: CONDITION MET is better the GOOD!

So what happens with a current kernel (lk 4.15.0-rc9) if you send lots
of PRE-FETCH(10) commands to a disk (or a simulated one) with a big
cache (so lots of CONDITION METs)? A mess:

kernel: scsi_io_completion: 140 callbacks suppressed
kernel: sd 0:0:0:0: [sg0] tag#21 FAILED Result: hostbyte=DID_OK 
driverbyte=DRIVER_OK
kernel: sd 0:0:0:0: [sg0] tag#21 CDB: Prefetch/Read Position 34 02 00 11 22 33 
05 00 03 00

kernel: sd 0:0:0:0: [sg0] tag#21 FAILED Result: hostbyte=DID_OK 
driverbyte=DRIVER_OK
kernel: sd 0:0:0:0: [sg0] tag#21 CDB: Prefetch/Read Position 34 02 00 11 22 37 
05 00 03 00

...


Additionally there seems to be a bug (or resource problem) with that
suppression code. When I sent 1 million PRE-FETCH(10)s it should have
taken less than a minute, extrapolating from the result with smaller
numbers. I killed the job after 15 minutes.

Doug Gilbert


[PATCH] scsi_debug: implement IMMED bit

2018-01-29 Thread Douglas Gilbert
The start stop unit command takes in the order of a second to complete
on some SAS SSDs and longer on hard disks. Synchronize cache can also
take some time. Both commands have an IMMED bit for those apps that don't
want to wait. This patch introduces a long delay for those commands
when the IMMED bit is clear.

Changes:
  - add the SYNCHRONIZE CACHE(16) command
  - together with the existing START STOP UNIT and SYNCHRONIZE CACHE(10)
commands process the IMMED bit in their cdbs
  - if the IMMED bit is set, return immediately
  - if the IMMED bit is clear, treat the delay parameter as having
a unit of one second
  - in the SYNCHRONIZE CACHE processing do a bounds check

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 76 ---
 1 file changed, 65 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a5986dae9020..0996fcb8a8d2 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -6,7 +6,7 @@
  *  anything out of the ordinary is seen.
  * ^^^ Original ^^^
  *
- * Copyright (C) 2001 - 2017 Douglas Gilbert
+ * Copyright (C) 2001 - 2018 Douglas Gilbert
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -61,8 +61,8 @@
 #include "scsi_logging.h"
 
 /* make sure inq_product_rev string corresponds to this version */
-#define SDEBUG_VERSION "0187"  /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20171202";
+#define SDEBUG_VERSION "0188"  /* format to fit INQUIRY revision field */
+static const char *sdebug_version_date = "20180128";
 
 #define MY_NAME "scsi_debug"
 
@@ -234,6 +234,7 @@ static const char *sdebug_version_date = "20171202";
 #define F_INV_OP   0x200
 #define F_FAKE_RW  0x400
 #define F_M_ACCESS 0x800   /* media access */
+#define F_LONG_DELAY   0x1000
 
 #define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
 #define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW)
@@ -349,7 +350,7 @@ enum sdeb_opcode_index {
SDEB_I_XDWRITEREAD = 25,/* 10 only */
SDEB_I_WRITE_BUFFER = 26,
SDEB_I_WRITE_SAME = 27, /* 10, 16 */
-   SDEB_I_SYNC_CACHE = 28, /* 10 only */
+   SDEB_I_SYNC_CACHE = 28, /* 10, 16 */
SDEB_I_COMP_WRITE = 29,
SDEB_I_LAST_ELEMENT = 30,   /* keep this last (previous + 1) */
 };
@@ -382,7 +383,7 @@ static const unsigned char opcode_ind_arr[256] = {
 /* 0x80; 0x80->0x9f: 16 byte cdbs */
0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
-   0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
+   0, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16,
 /* 0xa0; 0xa0->0xbf: 12 byte cdbs */
SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
@@ -398,6 +399,14 @@ static const unsigned char opcode_ind_arr[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
 
+/*
+ * The following "response" functions return the SCSI mid-level's 4 byte
+ * tuple-in-an-int. To handle commands with an IMMED bit, for a faster
+ * command completion, they can mask their return value with
+ * SDEG_RES_IMMED_MASK .
+ */
+#define SDEG_RES_IMMED_MASK 0x4000
+
 static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
@@ -420,6 +429,7 @@ static int resp_write_same_16(struct scsi_cmnd *, struct 
sdebug_dev_info *);
 static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_sync_cache(struct scsi_cmnd *, struct sdebug_dev_info *);
 
 /*
  * The following are overflow arrays for cdbs that "hit" the same index in
@@ -499,6 +509,12 @@ static const struct opcode_info_t release_iarr[] = {
{6,  0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
 };
 
+static const struct opcode_info_t sync_cache_iarr[] = {
+   {0, 0x91, 0, F_LONG_DELAY | F_M_ACCESS, resp_sync_cache, NULL,
+   {16,  0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* SYNC_CACHE (16) */
+};
+
 
 /* This array is accessed via SDEB_I_* values. Make sure all are mapped,
  * plus the terminating elements for logic that scans this table such as
@@ -536,8 +552,8 @@ static const struct opcode_info_t 
opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] =

Re: [PATCH] scsi_debug: Simplify request tag decoding

2018-01-31 Thread Douglas Gilbert

On 2018-01-26 11:52 AM, Bart Van Assche wrote:

Since commit 64d513ac31bd ("scsi: use host wide tags by default")
all SCSI requests have a tag, whether or not scsi-mq is enabled.
Additionally, it is safe to use blk_mq_unique_tag() and
blk_mq_unique_tag_to_hwq() for legacy SCSI queues. Since this
means that the sdebug_mq_active variable is superfluous, remove it.

Signed-off-by: Bart Van Assche 
Cc: Douglas Gilbert 


Ack-ed by Douglas Gilbert 


Cc: Christoph Hellwig 
Cc: Hannes Reinecke 
---
  drivers/scsi/scsi_debug.c | 37 +++--
  1 file changed, 11 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a5986dae9020..7d2ce0cc915a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -649,7 +649,6 @@ static bool sdebug_any_injecting_opt;
  static bool sdebug_verbose;
  static bool have_dif_prot;
  static bool sdebug_statistics = DEF_STATISTICS;
-static bool sdebug_mq_active;
  
  static unsigned int sdebug_store_sectors;

  static sector_t sdebug_capacity;  /* in sectors */
@@ -3727,20 +3726,13 @@ static int resp_xdwriteread_10(struct scsi_cmnd *scp,
  
  static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd)

  {
-   struct sdebug_queue *sqp = sdebug_q_arr;
+   u32 tag = blk_mq_unique_tag(cmnd->request);
+   u16 hwq = blk_mq_unique_tag_to_hwq(tag);
  
-	if (sdebug_mq_active) {

-   u32 tag = blk_mq_unique_tag(cmnd->request);
-   u16 hwq = blk_mq_unique_tag_to_hwq(tag);
-
-   if (unlikely(hwq >= submit_queues)) {
-   pr_warn("Unexpected hwq=%d, apply modulo\n", hwq);
-   hwq %= submit_queues;
-   }
-   pr_debug("tag=%u, hwq=%d\n", tag, hwq);
-   return sqp + hwq;
-   } else
-   return sqp;
+   pr_debug("tag=%#x, hwq=%d\n", tag, hwq);
+   if (WARN_ON_ONCE(hwq >= submit_queues))
+   hwq = 0;
+   return sdebug_q_arr + hwq;
  }
  
  /* Queued (deferred) command completions converge here. */

@@ -4587,9 +4579,8 @@ static int scsi_debug_show_info(struct seq_file *m, 
struct Scsi_Host *host)
   num_host_resets);
seq_printf(m, "dix_reads=%d, dix_writes=%d, dif_errors=%d\n",
   dix_reads, dix_writes, dif_errors);
-   seq_printf(m, "usec_in_jiffy=%lu, %s=%d, mq_active=%d\n",
-  TICK_NSEC / 1000, "statistics", sdebug_statistics,
-  sdebug_mq_active);
+   seq_printf(m, "usec_in_jiffy=%lu, statistics=%d\n", TICK_NSEC / 1000,
+  sdebug_statistics);
seq_printf(m, "cmnd_count=%d, completions=%d, %s=%d, a_tsf=%d\n",
   atomic_read(&sdebug_cmnd_count),
   atomic_read(&sdebug_completions),
@@ -5612,13 +5603,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host 
*shost,
n += scnprintf(b + n, sb - n, "%02x ",
   (u32)cmd[k]);
}
-   if (sdebug_mq_active)
-   sdev_printk(KERN_INFO, sdp, "%s: tag=%u, cmd %s\n",
-   my_name, blk_mq_unique_tag(scp->request),
-   b);
-   else
-   sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name,
-   b);
+   sdev_printk(KERN_INFO, sdp, "%s: tag=%#x, cmd %s\n", my_name,
+   blk_mq_unique_tag(scp->request), b);
}
if (fake_host_busy(scp))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -5782,8 +5768,7 @@ static int sdebug_driver_probe(struct device * dev)
}
/* Decide whether to tell scsi subsystem that we want mq */
/* Following should give the same answer for each host */
-   sdebug_mq_active = shost_use_blk_mq(hpnt) && (submit_queues > 1);
-   if (sdebug_mq_active)
+   if (shost_use_blk_mq(hpnt))
hpnt->nr_hw_queues = submit_queues;
  
  	sdbg_host->shost = hpnt;






Re: [PATCH] scsi_debug: implement IMMED bit

2018-01-31 Thread Douglas Gilbert

On 2018-01-31 12:06 PM, Bart Van Assche wrote:

On 01/29/18 21:54, Douglas Gilbert wrote:

+static const struct opcode_info_t sync_cache_iarr[] = {
+    {0, 0x91, 0, F_LONG_DELAY | F_M_ACCESS, resp_sync_cache, NULL,
+    {16,  0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

   ^^^
Can you clarify the choice of "0x7" in the above? After having had a look at 
SBC-4 I was expecting 0x2 (the mask for the IMMED bit) since all other bits in 
that command byte are either reserved or obsolete.


As a general rule when you see "obsolete" that means that field was used
in an earlier standard (bit 0 was RELADDR and bit 2 was SYNC_NV). So
application clients complying with earlier versions of SBC might set those
bits. If they are set and the mask is being enforced I choose to not fail
the command as an illegal request. Basically accept and ignore.


-    return 0;
+    return (cmd[1] & 0x1) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */


Shouldn't the mask 0x2 be used to check for the IMMED bit?


That comment needs a little more context:

@@ -1597,7 +1614,7 @@ static int resp_start_stop(struct scsi_cmnd * scp,
}
stop = !(cmd[4] & 1);
atomic_xchg(&devip->stopped, stop);
-   return 0;
+   return (cmd[1] & 0x1) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */


For START STOP UNIT the IMMED flag is byte 1, bit 0. So that code
is correct IMO.


And for SYNCHRONIZE CACHE(10 and 16) the IMMED flag is byte 1 bit 1
so the corresponding return statement is:

+   return (cmd[1] & 0x2) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */


Doug Gilbert


Re: [PATCH] scsi_debug: implement IMMED bit

2018-01-31 Thread Douglas Gilbert

On 2018-01-31 05:05 PM, Bart Van Assche wrote:

On Wed, 2018-01-31 at 15:26 -0500, Douglas Gilbert wrote:

On 2018-01-31 12:06 PM, Bart Van Assche wrote:

On 01/29/18 21:54, Douglas Gilbert wrote:

+static const struct opcode_info_t sync_cache_iarr[] = {
+{0, 0x91, 0, F_LONG_DELAY | F_M_ACCESS, resp_sync_cache, NULL,
+{16,  0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,


^^^
Can you clarify the choice of "0x7" in the above? After having had a look at
SBC-4 I was expecting 0x2 (the mask for the IMMED bit) since all other bits in
that command byte are either reserved or obsolete.


As a general rule when you see "obsolete" that means that field was used
in an earlier standard (bit 0 was RELADDR and bit 2 was SYNC_NV). So
application clients complying with earlier versions of SBC might set those
bits. If they are set and the mask is being enforced I choose to not fail
the command as an illegal request. Basically accept and ignore.


I agree with setting bits for obsolete flags. The reason I was asking about that
mask is because I found the following in SBC-4 for byte 1 of SYNCHRONIZE 
CACHE(16):
* Bits 7..3: reserved.
* Bit 2: obsolete.
* Bit 1: IMMED.
* Bit 0: reserved.


I did see the discrepancy between byte 1 bit 0 in SYNCHRONIZE CACHE(10)
where it is "obsolete" and SYNCHRONIZE CACHE(16) where it is "reserved"
initially thinking it might be a typo. So I went for the more permissive.
I'm now guessing (because I don't have the drafts between SBC(-1) and
SBC-2 and for some reason T10 wants you to be a member to download older
drafts) that RELADDR was removed before SYNCHRONIZE CACHE(16) was added
(as there was no 64 LBA support in SBC-1). So if there never was a
publicly available draft where SYNCHRONIZE CACHE(16) had a RELADDR bit
defined, then why mark it as obsolete? Reserved means a later
draft/standard may use that bit/field.

BTW There is no requirement for a device server to enforce the mask and
most don't (from my testing). The mask is provided as an aid to the
application client and is required by the implementation of REPORT
SUPPORTED OPERATION CODES which is why I have it in scsi_debug. By default
the scsi_debug driver does not enforce the mask (but does when strict=1).

Anyway, aren't we splitting hairs here? Does this really justify a new
patch being rolled?

Doug Gilbert


-return 0;
+return (cmd[1] & 0x1) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */


Shouldn't the mask 0x2 be used to check for the IMMED bit?


That comment needs a little more context:


Sorry, I confused byte 1 of the START STOP command with that of the SYNCHRONIZE
CACHE command so please ignore the above comment.

Bart.





Re: scsi: sg: assorted memory corruptions

2018-01-31 Thread Douglas Gilbert

On 2018-01-30 07:22 AM, Dmitry Vyukov wrote:

Uh, I've answered this a week ago, but did not notice that Doug
dropped everybody from CC. Reporting to all.

On Mon, Jan 22, 2018 at 8:16 PM, Douglas Gilbert  wrote:

On 2018-01-22 02:06 PM, Dmitry Vyukov wrote:


On Mon, Jan 22, 2018 at 7:57 PM, Douglas Gilbert 

Please show me the output of 'lsscsi -g' on your test machine.
/dev/sg0 is often associated with /dev/sda which is often a SATA
SSD (or a virtualized one) that holds the root file system.
With the sg pass-through driver it is relatively easy to write
random (user provided data) over the root file system which will
almost certainly "root" the system.



This is pretty standard qemu vm started with:

qemu-system-x86_64 -hda wheezy.img -net user,host=10.0.2.10 -net nic
-nographic -kernel arch/x86/boot/bzImage -append "console=ttyS0
root=/dev/sda earlyprintk=serial " -m 2G -smp 4

# lsscsi -g
[0:0:0:0]diskATA  QEMU HARDDISK0 /dev/sda   /dev/sg0


With lk 4.15.0-rc9 I can run your test program (with some additions, see
attachment) for 30 minutes against a scsi_debug simulated disk. You can
easily replicate this test just run 'modprobe scsi_debug' and a third
line should appear in your lsscsi output. The new device will most likely
be /dev/sg2 .

With lk 4.15.0 (release) running against a SAS SSD (SEAGATE ST200FM0073),
the test has  been running 20 minutes and counting without problems. That
is using a LSI HBA with the mpt3sas driver.


[1:0:0:0]cd/dvd  QEMU QEMU DVD-ROM 2.0.  /dev/sr0   /dev/sg1

# readlink /sys/class/scsi_generic/sg0
../../devices/pci:00/:00:01.1/ata1/host0/target0:0:0/0:0:0:0/scsi_generic/sg0

# cat /sys/class/scsi_generic/sg0/device/vendor
ATA


^
That subsystem is the culprit IMO, most likely libata.

Until you can show this test failing on something other than an
ATA disk, then I will treat this issue as closed.

Doug Gilbert



Perhaps it misbehaves when it
gets a SCSI command in the T10 range (i.e. not vendor specific) with
a 9 byte cdb length. As far as I'm aware T10 (and the Ansi committee
before it) have never defined a cdb with an odd length.

For those that are not aware, the sg driver is a relatively thin
shim over the block layer, the SCSI mid-level, and a low-level
driver which may have another kernel driver stack underneath it
(e.g. UAS (USB attached SCSI)). The previous report from syzkaller
on the sg driver ("scsi: memory leak in sg_start_req") has resulted
in one accepted patch on the block layer with probably more to
come in the same area.

Testing the patch Dmitry gave (with some added error checks which
reported no problems) with the scsi_debug driver supplying /dev/sg0
I have not seen any problems running that test program. Again
there might be a very slow memory leak, but if there is I don't
believe it is in the sg driver.



Did you run it in a loop? First runs pass just fine for me too.



Is thirty minutes long enough ??



Yes, it certainly should be enough. Here is what I see:


# while ./a.out; do echo RUN; done
RUN
RUN
RUN
RUN
RUN
RUN
RUN
[  371.977266] 
==
[  371.980158] BUG: KASAN: double-free or invalid-free in
__put_task_struct+0x1e7/0x5c0



Here is full execution trace of the write call if that will be of any help:
https://gist.githubusercontent.com/dvyukov/14ae64c3e753dedf9ab2608676ecf0b9/raw/9803d52bb1e317a9228e362236d042aaf0fa9d69/gistfile1.txt

This is on upstream commit 0d665e7b109d512b7cae3ccef6e8654714887844.
Also attaching my config just in case.



// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

#define SG_NEXT_CMD_LEN 0x2283

static const char * usage = "sg_syzk_next_cdb # (e.g. '/dev/sg3') ";

int main(int argc, const char * argv[])
{
  int res, err;
  int fd;
  long len = 9;
  char* p = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x47\x00\x00\x24\x00"
"\x00\x00\x00\x00\x00\x1c\xbb\xac\x14\x00\xaa\xe0\x00\x00\x01"
"\x00\x07\x07\x00\x00\x59\x08\x00\x00\x00\x80\xfe\x7f\x00\x00\x01";
const char * dev_name;
struct stat a_stat;

if (argc < 2) {
fprintf(stderr, "Usage: %s\n", usage);
return 1;
}
dev_name = argv[1];
if (0 != stat(dev_name, &a_stat)) {
err = errno;
fprintf(stderr, "Unable to stat %s, err: %s\n", dev_name,
strerror(err));
return 1;
}
if ((a_stat.st_mode & S_IFMT) != S_IFCHR) {
fprintf(stderr, "Expected %s, to be sg device\n", dev_name);
return 1;
}
  fd = open(dev_name, O_RDWR);
  if (fd < 0) {
	err = errno;
	fprintf(stderr, "open(%s) failed: %s [%d]\n", dev_name, strerror(err),
		err);
  }
  res = ioctl(fd, SG_NEXT_CM

Re: [PATCH] scsi_debug: Add two new parameters to scsi_debug driver

2018-02-06 Thread Douglas Gilbert

On 2018-02-03 01:38 PM, Laurence Oberman wrote:

---
This patch adds two new parameters to the scsi_debug driver.
During various fault injection scenarios it would be useful to be able
to pick a specific starting sector and number of follow on sectors
where a MEDIUM ERROR for reads would be returned against a scsi-debug
device.

Right now this only works against sector 0x1234 and OPT_MEDIUM_ERR_NUM
follow on sectors.
However during testing of md-raid and other scenarios I wanted more
flexibility.

The idea is add 2 new parameters:
medium_error_start
medium_error_count

If medium_error_start is set then we don't use the default of
OPT_MEDIUM_ERR_ADDR, but use that set value.
If medium_error_count is set we use that value otherwise default to
OPT_MEDIUM_ERR_NUM.

Signed-off-by: Laurence Oberman 
Tested-by: Laurence Oberman 


Acked-by: Douglas Gilbert 



  drivers/scsi/scsi_debug.c | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a5986da..5a5aba0 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -616,6 +616,8 @@ enum sdeb_opcode_index {
  static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
  static int sdebug_max_luns = DEF_MAX_LUNS;
  static int sdebug_max_queue = SDEBUG_CANQUEUE;/* per submit queue */
+static unsigned int sdebug_medium_error_start = OPT_MEDIUM_ERR_ADDR;
+static int sdebug_medium_error_count = OPT_MEDIUM_ERR_NUM;
  static atomic_t retired_max_queue;/* if > 0 then was prior max_queue */
  static int sdebug_ndelay = DEF_NDELAY;/* if > 0 then unit is 
nanoseconds */
  static int sdebug_no_lun_0 = DEF_NO_LUN_0;
@@ -2712,8 +2714,8 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
}
  
  	if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&

-(lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
-((lba + num) > OPT_MEDIUM_ERR_ADDR))) {
+(lba <= (sdebug_medium_error_start + sdebug_medium_error_count - 
1)) &&
+((lba + num) > sdebug_medium_error_start))) {
/* claim unrecoverable read error */
mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
/* set info field and valid bit for fixed descriptor */
@@ -4440,6 +4442,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct 
sdebug_dev_info *devip,
  module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO);
  module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR);
  module_param_named(max_queue, sdebug_max_queue, int, S_IRUGO | S_IWUSR);
+module_param_named(medium_error_start, sdebug_medium_error_start, int, S_IRUGO 
| S_IWUSR);
+module_param_named(medium_error_count, sdebug_medium_error_count, int, S_IRUGO 
| S_IWUSR);
  module_param_named(ndelay, sdebug_ndelay, int, S_IRUGO | S_IWUSR);
  module_param_named(no_lun_0, sdebug_no_lun_0, int, S_IRUGO | S_IWUSR);
  module_param_named(no_uld, sdebug_no_uld, int, S_IRUGO);
@@ -4497,6 +4501,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct 
sdebug_dev_info *devip,
  MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
  MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
  MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
+MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM 
error");
+MODULE_PARM_DESC(medium_error_count, "count of sectors to return follow on MEDIUM 
error");
  MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
  MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
  MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");





[PATCH v2] scsi_debug: implement IMMED bit

2018-02-09 Thread Douglas Gilbert
The Start Stop Unit (SSU) command takes in the order of a second to
complete on some SAS SSDs and longer on hard disks. Synchronize Cache (SC)
can also take some time. Both commands have an IMMED bit in their cdbs for
those apps that don't want to wait. This patch introduces a long delay for
those commands when the IMMED bit is clear.
Since SC is a media access command then when the fake_rw option is active,
its cdb processing is skipped and it returns immediately. The SSU command
is not altered by the setting of the fake_rw option. These actions are
not changed by this patch.

Changes since v1:
  - clear the cdb mask of SYNCHRONIZE CACHE(16) cdb in byte 1, bit 0

Changes:
  - add the SYNCHRONIZE CACHE(16) command
  - together with the existing START STOP UNIT and SYNCHRONIZE CACHE(10)
commands process the IMMED bit in their cdbs
  - if the IMMED bit is set, return immediately
  - if the IMMED bit is clear, treat the delay parameter as having
a unit of one second
  - in the SYNCHRONIZE CACHE processing do a bounds check

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 76 ---
 1 file changed, 65 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a5986dae9020..828b27188f28 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -6,7 +6,7 @@
  *  anything out of the ordinary is seen.
  * ^^^ Original ^^^
  *
- * Copyright (C) 2001 - 2017 Douglas Gilbert
+ * Copyright (C) 2001 - 2018 Douglas Gilbert
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -61,8 +61,8 @@
 #include "scsi_logging.h"
 
 /* make sure inq_product_rev string corresponds to this version */
-#define SDEBUG_VERSION "0187"  /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20171202";
+#define SDEBUG_VERSION "0188"  /* format to fit INQUIRY revision field */
+static const char *sdebug_version_date = "20180128";
 
 #define MY_NAME "scsi_debug"
 
@@ -234,6 +234,7 @@ static const char *sdebug_version_date = "20171202";
 #define F_INV_OP   0x200
 #define F_FAKE_RW  0x400
 #define F_M_ACCESS 0x800   /* media access */
+#define F_LONG_DELAY   0x1000
 
 #define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
 #define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW)
@@ -349,7 +350,7 @@ enum sdeb_opcode_index {
SDEB_I_XDWRITEREAD = 25,/* 10 only */
SDEB_I_WRITE_BUFFER = 26,
SDEB_I_WRITE_SAME = 27, /* 10, 16 */
-   SDEB_I_SYNC_CACHE = 28, /* 10 only */
+   SDEB_I_SYNC_CACHE = 28, /* 10, 16 */
SDEB_I_COMP_WRITE = 29,
SDEB_I_LAST_ELEMENT = 30,   /* keep this last (previous + 1) */
 };
@@ -382,7 +383,7 @@ static const unsigned char opcode_ind_arr[256] = {
 /* 0x80; 0x80->0x9f: 16 byte cdbs */
0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
-   0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
+   0, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16,
 /* 0xa0; 0xa0->0xbf: 12 byte cdbs */
SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
@@ -398,6 +399,14 @@ static const unsigned char opcode_ind_arr[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
 
+/*
+ * The following "response" functions return the SCSI mid-level's 4 byte
+ * tuple-in-an-int. To handle commands with an IMMED bit, for a faster
+ * command completion, they can mask their return value with
+ * SDEG_RES_IMMED_MASK .
+ */
+#define SDEG_RES_IMMED_MASK 0x4000
+
 static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
@@ -420,6 +429,7 @@ static int resp_write_same_16(struct scsi_cmnd *, struct 
sdebug_dev_info *);
 static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_sync_cache(struct scsi_cmnd *, struct sdebug_dev_info *);
 
 /*
  * The following are overflow arrays for cdbs that "hit" the same index in
@@ -499,6 +509,12 @@ static const struct opcode_info_t release_iarr[] = {
{6,  0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
 };
 
+static const struct opcode_info_t sync_cache_iarr[] = {
+   {0, 0x91, 0, F_LONG_DELAY | F_M_ACCESS, resp_sync_cache, NULL,
+   {16,  0x6, 0xff, 0xff, 0xf

<    3   4   5   6   7   8   9   10   11   12   >