From patchwork Mon Jun 17 03:39:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 10997923 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77CE21398 for ; Mon, 17 Jun 2019 03:40:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A5AB2858A for ; Mon, 17 Jun 2019 03:40:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5F3F028814; Mon, 17 Jun 2019 03:40:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E756F2858A for ; Mon, 17 Jun 2019 03:40:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727742AbfFQDkF (ORCPT ); Sun, 16 Jun 2019 23:40:05 -0400 Received: from smtp.infotech.no ([82.134.31.41]:37816 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727733AbfFQDkF (ORCPT ); Sun, 16 Jun 2019 23:40:05 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 60E52204198 for ; Mon, 17 Jun 2019 05:40:03 +0200 (CEST) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rPSR-5plOdTr for ; Mon, 17 Jun 2019 05:40:01 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-58-224-183.dyn.295.ca [45.58.224.183]) by smtp.infotech.no (Postfix) with ESMTPA id 5A07220423F for ; Mon, 17 Jun 2019 05:39:49 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Subject: [PATCH 17/18] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls Date: Sun, 16 Jun 2019 23:39:33 -0400 Message-Id: <20190617033934.5051-18-dgilbert@interlog.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190617033934.5051-1-dgilbert@interlog.com> References: <20190617033934.5051-1-dgilbert@interlog.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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__); 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: return sg_ctl_scsi_id(sdev, sfp, p); case SG_SET_FORCE_PACK_ID: diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h index db86d1ae7e29..090d4f496dc8 100644 --- a/include/uapi/scsi/sg.h +++ b/include/uapi/scsi/sg.h @@ -356,6 +356,12 @@ struct sg_header { /* Gives some v4 identifying info to driver, receives associated response */ #define SG_IORECEIVE _IOWR(SG_IOCTL_MAGIC_NUM, 0x42, struct sg_io_v4) +/* Submits a v3 interface object to driver */ +#define SG_IOSUBMIT_V3 _IOWR(SG_IOCTL_MAGIC_NUM, 0x45, struct sg_io_hdr) + +/* Gives some v3 identifying info to driver, receives associated response */ +#define SG_IORECEIVE_V3 _IOWR(SG_IOCTL_MAGIC_NUM, 0x46, struct sg_io_hdr) + /* command queuing is always on when the v3 or v4 interface is used */ #define SG_DEF_COMMAND_Q 0