From: Douglas Gilbert <dgilbert@interlog.com>
To: linux-scsi@vger.kernel.org
Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de
Subject: [PATCH v17 13/45] sg: split sg_read
Date: Wed, 7 Apr 2021 21:44:59 -0400 [thread overview]
Message-ID: <20210408014531.248890-14-dgilbert@interlog.com> (raw)
In-Reply-To: <20210408014531.248890-1-dgilbert@interlog.com>
As sg_read() is getting quite long, split out the v1 and v2
processing into sg_read_v1v2(). Rename sg_new_read() to
sg_receive_v3() as the v3 interface is now older than the v4
interface which is being added in a later patch.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
drivers/scsi/sg.c | 267 +++++++++++++++++++++++-----------------------
1 file changed, 131 insertions(+), 136 deletions(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index c40d9f24cc4d..246ebed1cee4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -188,8 +188,8 @@ static ssize_t sg_submit(struct sg_fd *sfp, struct file *filp,
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, void __user *outp,
- int num_xfer);
+static int sg_read_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);
static void sg_link_reserve(struct sg_fd *sfp, struct sg_request *srp,
@@ -756,8 +756,8 @@ sg_get_rq_mark(struct sg_fd *sfp, int pack_id)
}
static ssize_t
-sg_new_read(struct sg_fd *sfp, char __user *buf, size_t count,
- struct sg_request *srp)
+sg_receive_v3(struct sg_fd *sfp, char __user *buf, size_t count,
+ struct sg_request *srp)
{
struct sg_io_hdr *hp = &srp->header;
int err = 0, err2;
@@ -811,168 +811,163 @@ srp_done(struct sg_fd *sfp, struct sg_request *srp)
return ret;
}
-static ssize_t
-sg_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+static int
+sg_read_v1v2(void __user *buf, int count, struct sg_fd *sfp,
+ struct sg_request *srp)
{
- struct sg_device *sdp;
- struct sg_fd *sfp;
- struct sg_request *srp;
- int req_pack_id = -1;
- int ret = 0;
- struct sg_io_hdr *hp;
- struct sg_header *old_hdr = NULL;
-
- /*
- * This could cause a response to be stranded. Close the associated
- * file descriptor to free up any resources being held.
- */
- ret = sg_check_file_access(filp, __func__);
- if (ret)
- return ret;
-
- sfp = filp->private_data;
- sdp = sfp->parentdp;
- SG_LOG(3, sfp, "%s: read() count=%d\n", __func__, (int)count);
- ret = sg_allow_if_err_recovery(sdp, false);
- 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)) {
- ret = -EFAULT;
- goto free_old_hdr;
- }
- if (old_hdr->reply_len < 0) {
- if (count >= SZ_SG_IO_HDR) {
- struct sg_io_hdr *new_hdr;
-
- new_hdr = kmalloc(SZ_SG_IO_HDR, GFP_KERNEL);
- if (!new_hdr) {
- ret = -ENOMEM;
- goto free_old_hdr;
- }
- ret = copy_from_user
- (new_hdr, buf, SZ_SG_IO_HDR);
- req_pack_id = new_hdr->pack_id;
- kfree(new_hdr);
- if (ret) {
- ret = -EFAULT;
- goto free_old_hdr;
- }
- }
- } else {
- req_pack_id = old_hdr->pack_id;
- }
- }
- srp = sg_get_rq_mark(sfp, req_pack_id);
- if (!srp) { /* now wait on packet to arrive */
- if (SG_IS_DETACHING(sdp)) {
- ret = -ENODEV;
- goto free_old_hdr;
- }
- if (filp->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- goto free_old_hdr;
- }
- ret = wait_event_interruptible
- (sfp->read_wait,
- (SG_IS_DETACHING(sdp) ||
- (srp = sg_get_rq_mark(sfp, req_pack_id))));
- if (SG_IS_DETACHING(sdp)) {
- ret = -ENODEV;
- goto free_old_hdr;
- }
- if (ret) {
- /* -ERESTARTSYS as signal hit process */
- goto free_old_hdr;
- }
- }
- if (srp->header.interface_id != '\0') {
- ret = sg_new_read(sfp, buf, count, srp);
- goto free_old_hdr;
- }
-
- hp = &srp->header;
- if (!old_hdr) {
- old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
- if (!old_hdr) {
- ret = -ENOMEM;
- goto free_old_hdr;
- }
- }
- memset(old_hdr, 0, SZ_SG_HEADER);
- old_hdr->reply_len = (int)hp->timeout;
- old_hdr->pack_len = old_hdr->reply_len; /* old, strange behaviour */
- old_hdr->pack_id = hp->pack_id;
- old_hdr->twelve_byte =
- ((srp->data.cmd_opcode >= 0xc0) && (hp->cmd_len == 12)) ? 1 : 0;
- old_hdr->target_status = hp->masked_status;
- old_hdr->host_status = hp->host_status;
- old_hdr->driver_status = hp->driver_status;
- if ((hp->masked_status & CHECK_CONDITION) ||
- (hp->driver_status & DRIVER_SENSE))
- memcpy(old_hdr->sense_buffer, srp->sense_b,
- sizeof(old_hdr->sense_buffer));
- switch (hp->host_status) {
+ int res = 0;
+ struct sg_io_hdr *sh3p = &srp->header;
+ struct sg_header *h2p;
+ struct sg_header a_v2hdr;
+
+ h2p = &a_v2hdr;
+ memset(h2p, 0, SZ_SG_HEADER);
+ h2p->reply_len = (int)sh3p->timeout;
+ h2p->pack_len = h2p->reply_len; /* old, strange behaviour */
+ h2p->pack_id = sh3p->pack_id;
+ h2p->twelve_byte = (srp->data.cmd_opcode >= 0xc0 &&
+ sh3p->cmd_len == 12);
+ h2p->target_status = sh3p->masked_status;
+ h2p->host_status = sh3p->host_status;
+ h2p->driver_status = sh3p->driver_status;
+ if ((CHECK_CONDITION & h2p->target_status) ||
+ (DRIVER_SENSE & sh3p->driver_status)) {
+ memcpy(h2p->sense_buffer, srp->sense_b,
+ sizeof(h2p->sense_buffer));
+ }
+ switch (h2p->host_status) {
/*
- * This setup of 'result' is for backward compatibility and is best
- * ignored by the user who should use target, host + driver status
+ * This following setting of 'result' is for backward compatibility
+ * and is best ignored by the user who should use target, host and
+ * driver status.
*/
case DID_OK:
case DID_PASSTHROUGH:
case DID_SOFT_ERROR:
- old_hdr->result = 0;
+ h2p->result = 0;
break;
case DID_NO_CONNECT:
case DID_BUS_BUSY:
case DID_TIME_OUT:
- old_hdr->result = EBUSY;
+ h2p->result = EBUSY;
break;
case DID_BAD_TARGET:
case DID_ABORT:
case DID_PARITY:
case DID_RESET:
case DID_BAD_INTR:
- old_hdr->result = EIO;
+ h2p->result = EIO;
break;
case DID_ERROR:
- old_hdr->result = (srp->sense_b[0] == 0 &&
- hp->masked_status == GOOD) ? 0 : EIO;
+ h2p->result = (h2p->target_status == GOOD) ? 0 : EIO;
break;
default:
- old_hdr->result = EIO;
+ h2p->result = EIO;
break;
}
/* Now copy the result back to the user buffer. */
if (count >= SZ_SG_HEADER) {
- if (copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
- ret = -EFAULT;
- goto free_old_hdr;
- }
+ if (copy_to_user(buf, h2p, SZ_SG_HEADER))
+ return -EFAULT;
buf += SZ_SG_HEADER;
- if (count > old_hdr->reply_len)
- count = old_hdr->reply_len;
+ if (count > h2p->reply_len)
+ count = h2p->reply_len;
if (count > SZ_SG_HEADER) {
- if (sg_rd_append(srp, buf, count - SZ_SG_HEADER)) {
- ret = -EFAULT;
- goto free_old_hdr;
- }
+ if (sg_read_append(srp, buf, count - SZ_SG_HEADER))
+ return -EFAULT;
}
} else {
- count = (old_hdr->result == 0) ? 0 : -EIO;
+ res = (h2p->result == 0) ? 0 : -EIO;
}
sg_finish_scsi_blk_rq(srp);
sg_remove_request(sfp, srp);
- ret = count;
-free_old_hdr:
- kfree(old_hdr);
- return ret;
+ return res;
+}
+
+static ssize_t
+sg_read(struct file *filp, char __user *p, size_t count, loff_t *ppos)
+{
+ bool could_be_v3;
+ bool non_block = !!(filp->f_flags & O_NONBLOCK);
+ int want_id = -1;
+ int hlen, ret;
+ struct sg_device *sdp;
+ struct sg_fd *sfp;
+ struct sg_request *srp;
+ struct sg_header *h2p = NULL;
+ struct sg_io_hdr a_sg_io_hdr;
+
+ /*
+ * This could cause a response to be stranded. Close the associated
+ * file descriptor to free up any resources being held.
+ */
+ ret = sg_check_file_access(filp, __func__);
+ if (ret)
+ return ret;
+
+ sfp = filp->private_data;
+ sdp = sfp->parentdp;
+ SG_LOG(3, sfp, "%s: read() count=%d\n", __func__, (int)count);
+ ret = sg_allow_if_err_recovery(sdp, false);
+ if (ret)
+ return ret;
+
+ could_be_v3 = (count >= SZ_SG_IO_HDR);
+ hlen = could_be_v3 ? SZ_SG_IO_HDR : SZ_SG_HEADER;
+ h2p = (struct sg_header *)&a_sg_io_hdr;
+
+ if (sfp->force_packid && count >= hlen) {
+ /*
+ * Even though this is a user space read() system call, this
+ * code is cheating to fetch the pack_id.
+ * Only need first three 32 bit ints to determine interface.
+ */
+ if (unlikely(copy_from_user(h2p, p, 3 * sizeof(int))))
+ return -EFAULT;
+ if (h2p->reply_len < 0 && could_be_v3) {
+ struct sg_io_hdr *v3_hdr = (struct sg_io_hdr *)h2p;
+
+ if (likely(v3_hdr->interface_id == 'S')) {
+ struct sg_io_hdr __user *h3_up;
+
+ h3_up = (struct sg_io_hdr __user *)p;
+ ret = get_user(want_id, &h3_up->pack_id);
+ if (unlikely(ret))
+ return ret;
+ } else if (v3_hdr->interface_id == 'Q') {
+ pr_info_once("sg: %s: v4 interface%s here\n",
+ __func__, " disallowed");
+ return -EPERM;
+ } else {
+ return -EPERM;
+ }
+ } else { /* for v1+v2 interfaces, this is the 3rd integer */
+ want_id = h2p->pack_id;
+ }
+ }
+ srp = sg_get_rq_mark(sfp, want_id);
+ if (!srp) { /* now wait on packet to arrive */
+ if (SG_IS_DETACHING(sdp))
+ return -ENODEV;
+ if (non_block) /* O_NONBLOCK or v3::flags & SGV4_FLAG_IMMED */
+ return -EAGAIN;
+ ret = wait_event_interruptible
+ (sfp->read_wait,
+ (SG_IS_DETACHING(sdp) ||
+ (srp = sg_get_rq_mark(sfp, want_id))));
+ if (SG_IS_DETACHING(sdp))
+ return -ENODEV;
+ if (ret) /* -ERESTARTSYS as signal hit process */
+ return ret;
+ }
+ if (srp->header.interface_id == '\0')
+ ret = sg_read_v1v2(p, (int)count, sfp, srp);
+ else
+ ret = sg_receive_v3(sfp, p, count, srp);
+ if (ret < 0)
+ SG_LOG(1, sfp, "%s: negated errno: %d\n", __func__, ret);
+ return ret < 0 ? ret : (int)count;
}
static int
@@ -1045,7 +1040,7 @@ sg_ctl_sg_io(struct file *filp, struct sg_device *sdp, struct sg_fd *sfp,
if (srp->done) {
srp->done = 2;
spin_unlock_irq(&sfp->rq_list_lock);
- res = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
+ res = sg_receive_v3(sfp, p, SZ_SG_IO_HDR, srp);
return (res < 0) ? res : 0;
}
srp->orphan = 1;
@@ -2182,7 +2177,7 @@ sg_remove_scat(struct sg_fd *sfp, struct sg_scatter_hold *schp)
* appended to given struct sg_header object.
*/
static int
-sg_rd_append(struct sg_request *srp, void __user *outp, int num_xfer)
+sg_read_append(struct sg_request *srp, void __user *outp, int num_xfer)
{
struct sg_scatter_hold *schp = &srp->data;
int k, num;
--
2.25.1
next prev parent reply other threads:[~2021-04-08 1:46 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-08 1:44 [PATCH v17 00/45] sg: add v4 interface Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 01/45] sg: move functions around Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 02/45] sg: remove typedefs, type+formatting cleanup Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 03/45] sg: sg_log and is_enabled Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 04/45] sg: rework sg_poll(), minor changes Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 05/45] sg: bitops in sg_device Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 06/45] sg: make open count an atomic Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 07/45] sg: move header to uapi section Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 08/45] sg: speed sg_poll and sg_get_num_waiting Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 09/45] sg: sg_allow_if_err_recovery and renames Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 10/45] sg: improve naming Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 11/45] sg: change rwlock to spinlock Douglas Gilbert
2021-04-08 1:44 ` [PATCH v17 12/45] sg: ioctl handling Douglas Gilbert
2021-04-08 1:44 ` Douglas Gilbert [this message]
2021-04-08 1:45 ` [PATCH v17 14/45] sg: sg_common_write add structure for arguments Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 15/45] sg: rework sg_vma_fault Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 16/45] sg: rework sg_mmap Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 17/45] sg: replace sg_allow_access Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 18/45] sg: rework scatter gather handling Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 19/45] sg: introduce request state machine Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 20/45] sg: sg_find_srp_by_id Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 21/45] sg: sg_fill_request_element Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 22/45] sg: printk change %p to %pK Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 23/45] sg: xarray for fds in device Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 24/45] sg: xarray for reqs in fd Douglas Gilbert
2021-04-08 8:05 ` Hannes Reinecke
2021-04-08 1:45 ` [PATCH v17 25/45] sg: replace rq array with xarray Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 26/45] sg: sense buffer rework Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 27/45] sg: add sg v4 interface support Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 28/45] sg: rework debug info Douglas Gilbert
2021-04-08 8:06 ` Hannes Reinecke
2021-04-08 1:45 ` [PATCH v17 29/45] sg: add 8 byte SCSI LUN to sg_scsi_id Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 30/45] sg: expand sg_comm_wr_t Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 31/45] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 32/45] sg: add some __must_hold macros Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 33/45] sg: move procfs objects to avoid forward decls Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 34/45] sg: protect multiple receivers Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 35/45] sg: first debugfs support Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 36/45] sg: rework mmap support Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 37/45] sg: defang allow_dio Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 38/45] sg: warn v3 write system call users Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 39/45] sg: add mmap_sz tracking Douglas Gilbert
2021-04-08 8:07 ` Hannes Reinecke
2021-04-08 1:45 ` [PATCH v17 40/45] sg: remove rcv_done request state Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 41/45] sg: track lowest inactive and await indexes Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 42/45] sg: remove unit attention check for device changed Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 43/45] sg: no_dxfer: move to/from kernel buffers Douglas Gilbert
2021-04-08 8:07 ` Hannes Reinecke
2021-04-08 1:45 ` [PATCH v17 44/45] sg: add blk_poll support Douglas Gilbert
2021-04-08 8:14 ` Hannes Reinecke
2021-04-08 16:28 ` Douglas Gilbert
2021-04-09 6:00 ` Douglas Gilbert
2021-04-08 1:45 ` [PATCH v17 45/45] sg: bump version to 4.0.12 Douglas Gilbert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210408014531.248890-14-dgilbert@interlog.com \
--to=dgilbert@interlog.com \
--cc=hare@suse.de \
--cc=jejb@linux.vnet.ibm.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox