From patchwork Wed Oct 23 12:52:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206725 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B5EC2112B for ; Wed, 23 Oct 2019 12:53:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 94C5C21928 for ; Wed, 23 Oct 2019 12:53:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391828AbfJWMxL (ORCPT ); Wed, 23 Oct 2019 08:53:11 -0400 Received: from mx2.suse.de ([195.135.220.15]:49286 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391001AbfJWMxL (ORCPT ); Wed, 23 Oct 2019 08:53:11 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 475E4B679; Wed, 23 Oct 2019 12:53:09 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 1/8] cdrom: add poll_event_interruptible Date: Wed, 23 Oct 2019 14:52:40 +0200 Message-Id: <7fc0315de16d99ba29b4ffc565996188d290fac9.1571834862.git.msuchanek@suse.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Add convenience macro for polling an event that does not have a waitqueue. Signed-off-by: Michal Suchanek --- drivers/cdrom/cdrom.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index ac42ae4651ce..2ad6b73482fe 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -282,10 +282,24 @@ #include #include #include +#include #include +#include #include #include +#define poll_event_interruptible(event, interval) ({ \ + int ret = 0; \ + while (!(event)) { \ + if (signal_pending(current)) { \ + ret = -ERESTARTSYS; \ + break; \ + } \ + msleep_interruptible(interval); \ + } \ + ret; \ +}) + /* used to tell the module to turn on full debugging messages */ static bool debug; /* default compatibility mode */ From patchwork Wed Oct 23 12:52:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206719 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 57311112B for ; Wed, 23 Oct 2019 12:53:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 40D5921928 for ; Wed, 23 Oct 2019 12:53:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391855AbfJWMxN (ORCPT ); Wed, 23 Oct 2019 08:53:13 -0400 Received: from mx2.suse.de ([195.135.220.15]:49314 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391046AbfJWMxN (ORCPT ); Wed, 23 Oct 2019 08:53:13 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 161F5B670; Wed, 23 Oct 2019 12:53:10 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 2/8] cdrom: factor out common open_for_* code Date: Wed, 23 Oct 2019 14:52:41 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org The open_for_audio and open_for_data copies are bitrotten in different ways already and will need to update the autoclose logic in both. Signed-off-by: Michal Suchanek --- drivers/cdrom/cdrom.c | 96 +++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 62 deletions(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 2ad6b73482fe..f504ca70f93f 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1046,12 +1046,12 @@ static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks) } static -int open_for_data(struct cdrom_device_info *cdi) +int open_for_common(struct cdrom_device_info *cdi, tracktype *tracks) { int ret; const struct cdrom_device_ops *cdo = cdi->ops; - tracktype tracks; - cd_dbg(CD_OPEN, "entering open_for_data\n"); + + cd_dbg(CD_OPEN, "entering open_for_common\n"); /* Check if the driver can report drive status. If it can, we can do clever things. If it can't, well, we at least tried! */ if (cdo->drive_status != NULL) { @@ -1071,37 +1071,45 @@ int open_for_data(struct cdrom_device_info *cdi) couldn't close the tray. We only care that there is no disc in the drive, since that is the _REAL_ problem here.*/ - ret=-ENOMEDIUM; - goto clean_up_and_return; + return -ENOMEDIUM; } } else { cd_dbg(CD_OPEN, "bummer. this drive can't close the tray.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; + return -ENOMEDIUM; } /* Ok, the door should be closed now.. Check again */ ret = cdo->drive_status(cdi, CDSL_CURRENT); if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n"); cd_dbg(CD_OPEN, "tray might not contain a medium\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; + return -ENOMEDIUM; } cd_dbg(CD_OPEN, "the tray is now closed\n"); } - /* the door should be closed now, check for the disc */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if (ret!=CDS_DISC_OK) { - ret = -ENOMEDIUM; - goto clean_up_and_return; - } + if (ret != CDS_DISC_OK) + return -ENOMEDIUM; } - cdrom_count_tracks(cdi, &tracks); - if (tracks.error == CDS_NO_DISC) { + cdrom_count_tracks(cdi, tracks); + if (tracks->error == CDS_NO_DISC) { cd_dbg(CD_OPEN, "bummer. no disc.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; + return -ENOMEDIUM; } + + return 0; +} + +static +int open_for_data(struct cdrom_device_info *cdi) +{ + int ret; + const struct cdrom_device_ops *cdo = cdi->ops; + tracktype tracks; + + cd_dbg(CD_OPEN, "entering open_for_data\n"); + ret = open_for_common(cdi, &tracks); + if (ret) + goto clean_up_and_return; + /* CD-Players which don't use O_NONBLOCK, workman * for example, need bit CDO_CHECK_TYPE cleared! */ if (tracks.data==0) { @@ -1208,53 +1216,17 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, /* This code is similar to that in open_for_data. The routine is called whenever an audio play operation is requested. */ -static int check_for_audio_disc(struct cdrom_device_info *cdi, - const struct cdrom_device_ops *cdo) +static int check_for_audio_disc(struct cdrom_device_info *cdi) { int ret; tracktype tracks; cd_dbg(CD_OPEN, "entering check_for_audio_disc\n"); if (!(cdi->options & CDO_CHECK_TYPE)) return 0; - if (cdo->drive_status != NULL) { - ret = cdo->drive_status(cdi, CDSL_CURRENT); - cd_dbg(CD_OPEN, "drive_status=%d\n", ret); - if (ret == CDS_TRAY_OPEN) { - cd_dbg(CD_OPEN, "the tray is open...\n"); - /* can/may i close it? */ - if (CDROM_CAN(CDC_CLOSE_TRAY) && - cdi->options & CDO_AUTO_CLOSE) { - cd_dbg(CD_OPEN, "trying to close the tray\n"); - ret=cdo->tray_move(cdi,0); - if (ret) { - cd_dbg(CD_OPEN, "bummer. tried to close tray but failed.\n"); - /* Ignore the error from the low - level driver. We don't care why it - couldn't close the tray. We only care - that there is no disc in the drive, - since that is the _REAL_ problem here.*/ - return -ENOMEDIUM; - } - } else { - cd_dbg(CD_OPEN, "bummer. this driver can't close the tray.\n"); - return -ENOMEDIUM; - } - /* Ok, the door should be closed now.. Check again */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { - cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n"); - return -ENOMEDIUM; - } - if (ret!=CDS_DISC_OK) { - cd_dbg(CD_OPEN, "bummer. disc isn't ready.\n"); - return -EIO; - } - cd_dbg(CD_OPEN, "the tray is now closed\n"); - } - } - cdrom_count_tracks(cdi, &tracks); - if (tracks.error) - return(tracks.error); + + ret = open_for_common(cdi, &tracks); + if (ret) + return ret; if (tracks.audio==0) return -EMEDIUMTYPE; @@ -2725,7 +2697,7 @@ static int cdrom_ioctl_play_trkind(struct cdrom_device_info *cdi, if (copy_from_user(&ti, argp, sizeof(ti))) return -EFAULT; - ret = check_for_audio_disc(cdi, cdi->ops); + ret = check_for_audio_disc(cdi); if (ret) return ret; return cdi->ops->audio_ioctl(cdi, CDROMPLAYTRKIND, &ti); @@ -2773,7 +2745,7 @@ static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; - ret = check_for_audio_disc(cdi, cdi->ops); + ret = check_for_audio_disc(cdi); if (ret) return ret; return cdi->ops->audio_ioctl(cdi, cmd, NULL); From patchwork Wed Oct 23 12:52:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206699 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 395031920 for ; Wed, 23 Oct 2019 12:53:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 22F4D21928 for ; Wed, 23 Oct 2019 12:53:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391888AbfJWMxQ (ORCPT ); Wed, 23 Oct 2019 08:53:16 -0400 Received: from mx2.suse.de ([195.135.220.15]:49342 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391871AbfJWMxQ (ORCPT ); Wed, 23 Oct 2019 08:53:16 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id D14C3B676; Wed, 23 Oct 2019 12:53:10 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 3/8] cdrom: wait for the tray to close Date: Wed, 23 Oct 2019 14:52:42 +0200 Message-Id: <1696675e9998df6eee537908903628abf666e3fd.1571834862.git.msuchanek@suse.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org The scsi command to close the tray only starts the motor and does not wait for the tray to close. Wait until the state chages from TRAY_OPEN so users do not race with the tray closing. This looks like inifinte wait but unless the drive is broken it either closes the tray shortly or reports an error when it detects the tray is blocked. At worst the wait can be interrupted by the user. Also wait for the drive to become ready once the tray closes. Signed-off-by: Michal Suchanek --- v2: - check drive_status exists before using it - rename tray_close -> cdrom_tray_close - also wait for drive to become ready after tray closes - do not wait in cdrom_ioctl_closetray --- drivers/cdrom/cdrom.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index f504ca70f93f..c0fc9a02b70c 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1045,6 +1045,18 @@ static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks) tracks->cdi, tracks->xa); } +static int cdrom_tray_close(struct cdrom_device_info *cdi) +{ + int ret; + + ret = cdi->ops->tray_move(cdi, 0); + if (ret || !cdi->ops->drive_status) + return ret; + + return poll_event_interruptible(CDS_TRAY_OPEN != + cdi->ops->drive_status(cdi, CDSL_CURRENT), 500); +} + static int open_for_common(struct cdrom_device_info *cdi, tracktype *tracks) { @@ -1063,7 +1075,9 @@ int open_for_common(struct cdrom_device_info *cdi, tracktype *tracks) if (CDROM_CAN(CDC_CLOSE_TRAY) && cdi->options & CDO_AUTO_CLOSE) { cd_dbg(CD_OPEN, "trying to close the tray\n"); - ret=cdo->tray_move(cdi,0); + ret = cdrom_tray_close(cdi); + if (ret == -ERESTARTSYS) + return ret; if (ret) { cd_dbg(CD_OPEN, "bummer. tried to close the tray but failed.\n"); /* Ignore the error from the low @@ -1086,6 +1100,15 @@ int open_for_common(struct cdrom_device_info *cdi, tracktype *tracks) } cd_dbg(CD_OPEN, "the tray is now closed\n"); } + /* the door should be closed now, check for the disc */ + if (ret == CDS_DRIVE_NOT_READY) { + int poll_res = poll_event_interruptible( + CDS_DRIVE_NOT_READY != + (ret = cdo->drive_status(cdi, CDSL_CURRENT)), + 500); + if (poll_res == -ERESTARTSYS) + return poll_res; + } if (ret != CDS_DISC_OK) return -ENOMEDIUM; } From patchwork Wed Oct 23 12:52:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206713 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 528CB112B for ; Wed, 23 Oct 2019 12:53:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 316FC2173B for ; Wed, 23 Oct 2019 12:53:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391951AbfJWMxj (ORCPT ); Wed, 23 Oct 2019 08:53:39 -0400 Received: from mx2.suse.de ([195.135.220.15]:49374 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2390962AbfJWMxO (ORCPT ); Wed, 23 Oct 2019 08:53:14 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id A3F2AB67B; Wed, 23 Oct 2019 12:53:11 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 4/8] cdrom: separate autoclose into an IOCTL Date: Wed, 23 Oct 2019 14:52:43 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org This allows the sr driver to call it separately without blocking other processes accessing the device. This solves a issue with process waiting in open() on broken drive to close the tray blocking out all access to the device, including nonblocking access to determine drive status. Signed-off-by: Michal Suchanek --- drivers/cdrom/cdrom.c | 83 +++++++++++++++++++++----------------- include/uapi/linux/cdrom.h | 1 + 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index c0fc9a02b70c..bd8813b5afdb 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1071,46 +1071,16 @@ int open_for_common(struct cdrom_device_info *cdi, tracktype *tracks) cd_dbg(CD_OPEN, "drive_status=%d\n", ret); if (ret == CDS_TRAY_OPEN) { cd_dbg(CD_OPEN, "the tray is open...\n"); - /* can/may i close it? */ - if (CDROM_CAN(CDC_CLOSE_TRAY) && - cdi->options & CDO_AUTO_CLOSE) { - cd_dbg(CD_OPEN, "trying to close the tray\n"); - ret = cdrom_tray_close(cdi); - if (ret == -ERESTARTSYS) - return ret; - if (ret) { - cd_dbg(CD_OPEN, "bummer. tried to close the tray but failed.\n"); - /* Ignore the error from the low - level driver. We don't care why it - couldn't close the tray. We only care - that there is no disc in the drive, - since that is the _REAL_ problem here.*/ - return -ENOMEDIUM; - } - } else { - cd_dbg(CD_OPEN, "bummer. this drive can't close the tray.\n"); - return -ENOMEDIUM; - } - /* Ok, the door should be closed now.. Check again */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { - cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n"); - cd_dbg(CD_OPEN, "tray might not contain a medium\n"); - return -ENOMEDIUM; - } - cd_dbg(CD_OPEN, "the tray is now closed\n"); + return -ENOMEDIUM; } - /* the door should be closed now, check for the disc */ if (ret == CDS_DRIVE_NOT_READY) { - int poll_res = poll_event_interruptible( - CDS_DRIVE_NOT_READY != - (ret = cdo->drive_status(cdi, CDSL_CURRENT)), - 500); - if (poll_res == -ERESTARTSYS) - return poll_res; + cd_dbg(CD_OPEN, "the drive is not ready...\n"); + return -ENOMEDIUM; } - if (ret != CDS_DISC_OK) + if (ret != CDS_DISC_OK) { + cd_dbg(CD_OPEN, "drive returned status %i...\n", ret); return -ENOMEDIUM; + } } cdrom_count_tracks(cdi, tracks); if (tracks->error == CDS_NO_DISC) { @@ -2353,6 +2323,45 @@ static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi) return cdi->ops->tray_move(cdi, 0); } +static int cdrom_ioctl_autoclose(struct cdrom_device_info *cdi) +{ + const struct cdrom_device_ops *cdo = cdi->ops; + int ret; + + if (!cdo->drive_status) + return -ENXIO; + + ret = cdo->drive_status(cdi, CDSL_CURRENT); + + if ((ret == CDS_TRAY_OPEN) && CDROM_CAN(CDC_CLOSE_TRAY) && + (cdi->options & CDO_AUTO_CLOSE)) { + cd_dbg(CD_DO_IOCTL, "trying to close the tray...\n"); + ret = cdrom_tray_close(cdi); + if (ret == -ERESTARTSYS) + return ret; + if (ret) { + cd_dbg(CD_DO_IOCTL, "bummer. tried to close the tray but failed.\n"); + return -ENOMEDIUM; + ret = cdo->drive_status(cdi, CDSL_CURRENT); + } + ret = cdo->drive_status(cdi, CDSL_CURRENT); + } + + if (ret == CDS_DRIVE_NOT_READY) { + int poll_res; + + cd_dbg(CD_DO_IOCTL, "waiting for drive to become ready...\n"); + poll_res = poll_event_interruptible(CDS_DRIVE_NOT_READY != + (ret = cdo->drive_status(cdi, CDSL_CURRENT)), 50); + if (poll_res == -ERESTARTSYS) + return poll_res; + } + if (ret != CDS_DISC_OK) + return -ENOMEDIUM; + + return 0; +} + static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi, unsigned long arg) { @@ -3365,6 +3374,8 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, return cdrom_ioctl_debug(cdi, arg); case CDROM_GET_CAPABILITY: return cdrom_ioctl_get_capability(cdi); + case CDROM_AUTOCLOSE: + return cdrom_ioctl_autoclose(cdi); case CDROM_GET_MCN: return cdrom_ioctl_get_mcn(cdi, argp); case CDROM_DRIVE_STATUS: diff --git a/include/uapi/linux/cdrom.h b/include/uapi/linux/cdrom.h index 2817230148fd..6493d8c593ee 100644 --- a/include/uapi/linux/cdrom.h +++ b/include/uapi/linux/cdrom.h @@ -129,6 +129,7 @@ #define CDROM_LOCKDOOR 0x5329 /* lock or unlock door */ #define CDROM_DEBUG 0x5330 /* Turn debug messages on/off */ #define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ +#define CDROM_AUTOCLOSE 0x5332 /* If autoclose enabled close tray */ /* Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386. * Future CDROM ioctls should be kept below 0x537F From patchwork Wed Oct 23 12:52:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206709 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2BC7A1515 for ; Wed, 23 Oct 2019 12:53:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 13FF320640 for ; Wed, 23 Oct 2019 12:53:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391877AbfJWMxP (ORCPT ); Wed, 23 Oct 2019 08:53:15 -0400 Received: from mx2.suse.de ([195.135.220.15]:49390 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391852AbfJWMxO (ORCPT ); Wed, 23 Oct 2019 08:53:14 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 76FE6B67A; Wed, 23 Oct 2019 12:53:12 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 5/8] docs: cdrom: Add autoclose IOCTL Date: Wed, 23 Oct 2019 14:52:44 +0200 Message-Id: <50579dae04d209c6fec62388c596d0e459fe56de.1571834862.git.msuchanek@suse.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org This IOCTL will be used internally by the sr driver but there is no reason to not document it for userspace. Signed-off-by: Michal Suchanek --- Documentation/ioctl/cdrom.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Documentation/ioctl/cdrom.rst b/Documentation/ioctl/cdrom.rst index 3b4c0506de46..9372ff1b2b47 100644 --- a/Documentation/ioctl/cdrom.rst +++ b/Documentation/ioctl/cdrom.rst @@ -60,6 +60,7 @@ are as follows: CDROM_LOCKDOOR lock or unlock door CDROM_DEBUG Turn debug messages on/off CDROM_GET_CAPABILITY get capabilities + CDROM_AUTOCLOSE If autoclose enabled close the tray CDROMAUDIOBUFSIZ set the audio buffer size DVD_READ_STRUCT Read structure DVD_WRITE_STRUCT Write structure @@ -1056,6 +1057,30 @@ CDROM_GET_CAPABILITY +CDROM_AUTOCLOSE + Close the tray if the device has one, and autoclose is enabled. + Wait for drive to become ready. + + + usage:: + + ioctl(fd, CDROM_AUTOCLOSE, 0); + + + inputs: + none + + + outputs: + The ioctl return value is 0 or an error code. + + + error return: + - ENOMEDIUM No medium found or drive error. + - ERESTARTSYS Received a signal while waiting for drive to become ready. + + + CDROMAUDIOBUFSIZ set the audio buffer size From patchwork Wed Oct 23 12:52:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206705 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5B270112B for ; Wed, 23 Oct 2019 12:53:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4444B2173B for ; Wed, 23 Oct 2019 12:53:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391933AbfJWMxb (ORCPT ); Wed, 23 Oct 2019 08:53:31 -0400 Received: from mx2.suse.de ([195.135.220.15]:49414 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391863AbfJWMxP (ORCPT ); Wed, 23 Oct 2019 08:53:15 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 3ECD4B67C; Wed, 23 Oct 2019 12:53:13 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 6/8] bdev: add open_finish. Date: Wed, 23 Oct 2019 14:52:45 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Opening a block device may require a long operation such as waiting for the cdrom tray to close. Performing this operation with locks held locks out other attempts to open the device. These processes waiting to open the device are not killable. To avoid this issue and still be able to perform time-consuming checks at open() time the block device driver can provide open_finish(). If it does opening the device proceeds even when an error is returned from open(), bd_mutex is released and open_finish() is called. If open_finish() succeeds the device is now open, if it fails release() is called. When -ERESTARTSYS is returned from open() blkdev_get may loop without calling open_finish(). On -ERESTARTSYS open_finish() is not called. Move a ret = 0 assignment up in the if/else branching to avoid returning -ENXIO. Previously the return value was ignored on the unhandled branch. Signed-off-by: Michal Suchanek --- Documentation/filesystems/locking.rst | 2 ++ fs/block_dev.c | 21 +++++++++++++++++---- include/linux/blkdev.h | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst index fc3a0704553c..2471ced5a8cf 100644 --- a/Documentation/filesystems/locking.rst +++ b/Documentation/filesystems/locking.rst @@ -456,6 +456,7 @@ block_device_operations prototypes:: int (*open) (struct block_device *, fmode_t); + int (*open_finish) (struct block_device *, fmode_t, int); int (*release) (struct gendisk *, fmode_t); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); @@ -473,6 +474,7 @@ locking rules: ops bd_mutex ======================= =================== open: yes +open_finish: no release: yes ioctl: no compat_ioctl: no diff --git a/fs/block_dev.c b/fs/block_dev.c index 9c073dbdc1b0..009b5dedb1f7 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1526,6 +1526,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) int partno; int perm = 0; bool first_open = false; + bool need_finish = false; if (mode & FMODE_READ) perm |= MAY_READ; @@ -1581,6 +1582,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) put_disk_and_module(disk); goto restart; } + if (bdev->bd_disk->fops->open_finish) + need_finish = true; } if (!ret) { @@ -1601,7 +1604,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) invalidate_partitions(disk, bdev); } - if (ret) + if (ret && !need_finish) goto out_clear; } else { struct block_device *whole; @@ -1627,10 +1630,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (bdev->bd_bdi == &noop_backing_dev_info) bdev->bd_bdi = bdi_get(disk->queue->backing_dev_info); } else { + ret = 0; if (bdev->bd_contains == bdev) { - ret = 0; - if (bdev->bd_disk->fops->open) + if (bdev->bd_disk->fops->open) { ret = bdev->bd_disk->fops->open(bdev, mode); + if ((ret != -ERESTARTSYS) && + bdev->bd_disk->fops->open_finish) + need_finish = true; + } /* the same as first opener case, read comment there */ if (bdev->bd_invalidated) { if (!ret) @@ -1638,7 +1645,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) else if (ret == -ENOMEDIUM) invalidate_partitions(bdev->bd_disk, bdev); } - if (ret) + if (ret && !need_finish) goto out_unlock_bdev; } } @@ -1650,6 +1657,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) /* only one opener holds refs to the module and disk */ if (!first_open) put_disk_and_module(disk); + if (ret && need_finish) + ret = bdev->bd_disk->fops->open_finish(bdev, mode, ret); + if (ret) { + __blkdev_put(bdev, mode, for_part); + return ret; + } return 0; out_clear: diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f3ea78b0c91c..b67e93c6afb7 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1695,6 +1695,7 @@ static inline struct bio_vec *rq_integrity_vec(struct request *rq) struct block_device_operations { int (*open) (struct block_device *, fmode_t); + int (*open_finish)(struct block_device *bdev, fmode_t mode, int ret); void (*release) (struct gendisk *, fmode_t); int (*rw_page)(struct block_device *, sector_t, struct page *, unsigned int); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); From patchwork Wed Oct 23 12:52:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206701 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 73F3D112B for ; Wed, 23 Oct 2019 12:53:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5C92D20640 for ; Wed, 23 Oct 2019 12:53:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391921AbfJWMx0 (ORCPT ); Wed, 23 Oct 2019 08:53:26 -0400 Received: from mx2.suse.de ([195.135.220.15]:49442 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391046AbfJWMxQ (ORCPT ); Wed, 23 Oct 2019 08:53:16 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 0BE11B67D; Wed, 23 Oct 2019 12:53:14 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 7/8] scsi: sr: workaround VMware ESXi cdrom emulation bug Date: Wed, 23 Oct 2019 14:52:46 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org The WMware ESXi cdrom identifies itself as: sr 0:0:0:0: [sr0] scsi3-mmc drive: vendor: "NECVMWarVMware SATA CD001.00" model: "VMware SATA CD001.00" with the following get_capabilities print in sr.c: sr_printk(KERN_INFO, cd, "scsi3-mmc drive: vendor: \"%s\" model: \"%s\"\n", cd->device->vendor, cd->device->model); So the model looks like reliable identification while vendor does not. The drive claims to have a tray and claims to be able to close it. However, the UI has no notion of a tray - when medium is ejected it is dropped in the floor and the user must select a medium again before the drive can be re-loaded. On the kernel side the tray_move call to close the tray succeeds but the drive state does not change as a result of the call. The drive does not in fact emulate the tray state. There are two ways to get the medium state. One is the SCSI status: Physical drive: Fixed format, current; Sense key: Not Ready Additional sense: Medium not present - tray open Raw sense data (in hex): 70 00 02 00 00 00 00 0a 00 00 00 00 3a 02 00 00 00 00 Fixed format, current; Sense key: Not Ready Additional sense: Medium not present - tray closed Raw sense data (in hex): 70 00 02 00 00 00 00 0a 00 00 00 00 3a 01 00 00 00 00 VMware ESXi: Fixed format, current; Sense key: Not Ready Additional sense: Medium not present Info fld=0x0 [0] Raw sense data (in hex): f0 00 02 00 00 00 00 0a 00 00 00 00 3a 00 00 00 00 00 So the tray state is not reported here. Other is medium status which the kernel prefers if available. Adding a print here gives: cdrom: get_media_event success: code = 0, door_open = 1, medium_present = 0 door_open is interpreted as open tray. This is fine so long as tray_move would close the tray when requested or report an error which never happens on VMware ESXi servers (5.5 and 6.5 tested). This is a popular virtualization platform so a workaround is worthwhile. Signed-off-by: Michal Suchanek --- drivers/scsi/sr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 4664fdf75c0f..8090c5bdec09 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -867,6 +867,7 @@ static void get_capabilities(struct scsi_cd *cd) unsigned int ms_len = 128; int rc, n; + static const char *model_vmware = "VMware"; static const char *loadmech[] = { "caddy", @@ -922,6 +923,11 @@ static void get_capabilities(struct scsi_cd *cd) buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ loadmech[buffer[n + 6] >> 5]); + if (!strncmp(cd->device->model, model_vmware, strlen(model_vmware))) { + buffer[n + 6] &= ~(0xff << 5); + sr_printk(KERN_INFO, cd, + "VMware ESXi bug workaround: tray -> caddy\n"); + } if ((buffer[n + 6] >> 5) == 0) /* caddy drives can't close tray... */ cd->cdi.mask |= CDC_CLOSE_TRAY; From patchwork Wed Oct 23 12:52:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Suchanek X-Patchwork-Id: 11206695 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CB70F112B for ; Wed, 23 Oct 2019 12:53:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B410621928 for ; Wed, 23 Oct 2019 12:53:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391898AbfJWMxR (ORCPT ); Wed, 23 Oct 2019 08:53:17 -0400 Received: from mx2.suse.de ([195.135.220.15]:49374 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391880AbfJWMxQ (ORCPT ); Wed, 23 Oct 2019 08:53:16 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id CECD2B67E; Wed, 23 Oct 2019 12:53:14 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Mauro Carvalho Chehab , Eric Biggers , "J. Bruce Fields" , Benjamin Coddington , Hannes Reinecke , Omar Sandoval , Ming Lei , Damien Le Moal , Bart Van Assche , Tejun Heo , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 8/8] scsi: sr: wait for the medium to become ready Date: Wed, 23 Oct 2019 14:52:47 +0200 Message-Id: <94dc98dc67b1d183d04c338c7978efa0556db6ac.1571834862.git.msuchanek@suse.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Use the autoclose IOCLT provided by cdrom driver to wait for drive to close in open_finish, and attempt to open once more after the door closes. Signed-off-by: Michal Suchanek Reported-by: kernel test robot --- drivers/scsi/sr.c | 54 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 8090c5bdec09..34d9a818b9e0 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -521,29 +521,58 @@ static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt) return ret; } -static int sr_block_open(struct block_device *bdev, fmode_t mode) +static int __sr_block_open(struct block_device *bdev, fmode_t mode) { - struct scsi_cd *cd; - struct scsi_device *sdev; - int ret = -ENXIO; - - cd = scsi_cd_get(bdev->bd_disk); - if (!cd) - goto out; + struct scsi_cd *cd = scsi_cd(bdev->bd_disk); + int ret; - sdev = cd->device; - scsi_autopm_get_device(sdev); check_disk_change(bdev); mutex_lock(&sr_mutex); ret = cdrom_open(&cd->cdi, bdev, mode); mutex_unlock(&sr_mutex); + return ret; +} + +static int sr_block_open(struct block_device *bdev, fmode_t mode) +{ + struct scsi_cd *cd = scsi_cd_get(bdev->bd_disk); + struct scsi_device *sdev; + int ret; + + if (!cd) + return -ENXIO; + + sdev = cd->device; + scsi_autopm_get_device(sdev); + ret = __sr_block_open(bdev, mode); scsi_autopm_put_device(sdev); - if (ret) + + if (ret == -ERESTARTSYS) scsi_cd_put(cd); -out: + return ret; +} + +static int sr_block_open_finish(struct block_device *bdev, fmode_t mode, + int ret) +{ + struct scsi_cd *cd = scsi_cd(bdev->bd_disk); + + /* wait for drive to get ready */ + if ((ret == -ENOMEDIUM) && !(mode & FMODE_NDELAY)) { + struct scsi_device *sdev = cd->device; + /* + * Cannot use sr_block_ioctl because it locks sr_mutex blocking + * out any processes trying to access the drive + */ + scsi_autopm_get_device(sdev); + cdrom_ioctl(&cd->cdi, bdev, mode, CDROM_AUTOCLOSE, 0); + ret = __sr_block_open(bdev, mode); + scsi_autopm_put_device(sdev); + } + return ret; } @@ -639,6 +668,7 @@ static const struct block_device_operations sr_bdops = { .owner = THIS_MODULE, .open = sr_block_open, + .open_finish = sr_block_open_finish, .release = sr_block_release, .ioctl = sr_block_ioctl, .check_events = sr_block_check_events,