Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758676Ab3FCPEi (ORCPT ); Mon, 3 Jun 2013 11:04:38 -0400 Received: from e06smtp17.uk.ibm.com ([195.75.94.113]:46824 "EHLO e06smtp17.uk.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757296Ab3FCPEX (ORCPT ); Mon, 3 Jun 2013 11:04:23 -0400 From: Martin Schwidefsky To: linux-kernel , linux-s390 , Jens Axboe Cc: Martin Schwidefsky , Hannes Reinecke , Stefan Weinhuber Subject: [PATCH 9/9] dasd: Fail all requests when DASD_FLAG_ABORTIO is set Date: Mon, 3 Jun 2013 17:03:22 +0200 Message-Id: <1370271802-30019-10-git-send-email-schwidefsky@de.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1370271802-30019-1-git-send-email-schwidefsky@de.ibm.com> References: <1370271802-30019-1-git-send-email-schwidefsky@de.ibm.com> X-TM-AS-MML: No X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13060315-0542-0000-0000-0000056F65B5 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5927 Lines: 182 From: Hannes Reinecke Whenever a DASD request encounters a timeout we might need to abort all outstanding requests on this or even other devices. This is especially useful if one wants to fail all devices on one side of a RAID10 configuration, even though only one device exhibited an error. To handle this I've introduced a new device flag DASD_FLAG_ABORTIO. This flag is evaluated in __dasd_process_request_queue() and will invoke blk_abort_request() for all outstanding requests with DASD_CQR_FLAGS_FAILFAST set. This will cause any of these requests to be aborted immediately if the blk_timeout function is activated. The DASD_FLAG_ABORTIO is also evaluated in __dasd_process_request_queue to abort all new request which would have the DASD_CQR_FLAGS_FAILFAST bit set. The flag can be set with the new ioctls 'BIODASDABORTIO' and removed with 'BIODASDALLOWIO'. Signed-off-by: Hannes Reinecke Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- arch/s390/include/uapi/asm/dasd.h | 4 +++ drivers/s390/block/dasd.c | 13 ++++++-- drivers/s390/block/dasd_int.h | 3 ++ drivers/s390/block/dasd_ioctl.c | 59 +++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/arch/s390/include/uapi/asm/dasd.h b/arch/s390/include/uapi/asm/dasd.h index 38eca3b..5812a3b 100644 --- a/arch/s390/include/uapi/asm/dasd.h +++ b/arch/s390/include/uapi/asm/dasd.h @@ -261,6 +261,10 @@ struct dasd_snid_ioctl_data { #define BIODASDQUIESCE _IO(DASD_IOCTL_LETTER,6) /* Resume IO on device */ #define BIODASDRESUME _IO(DASD_IOCTL_LETTER,7) +/* Abort all I/O on a device */ +#define BIODASDABORTIO _IO(DASD_IOCTL_LETTER, 240) +/* Allow I/O on a device */ +#define BIODASDALLOWIO _IO(DASD_IOCTL_LETTER, 241) /* retrieve API version number */ diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 54f4bb8..17150a7 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -38,9 +38,6 @@ */ #define DASD_CHANQ_MAX_SIZE 4 -#define DASD_SLEEPON_START_TAG (void *) 1 -#define DASD_SLEEPON_END_TAG (void *) 2 - /* * SECTION: exported variables of dasd.c */ @@ -2535,6 +2532,16 @@ static void __dasd_process_request_queue(struct dasd_block *block) __blk_end_request_all(req, -EIO); continue; } + if (test_bit(DASD_FLAG_ABORTALL, &basedev->flags) && + (basedev->features & DASD_FEATURE_FAILFAST || + blk_noretry_request(req))) { + DBF_DEV_EVENT(DBF_ERR, basedev, + "Rejecting failfast request %p", + req); + blk_start_request(req); + __blk_end_request_all(req, -ETIMEDOUT); + continue; + } cqr = basedev->discipline->build_cp(basedev, block, req); if (IS_ERR(cqr)) { if (PTR_ERR(cqr) == -EBUSY) diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 2bd03f4..690001a 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -524,7 +524,10 @@ struct dasd_block { #define DASD_FLAG_SUSPENDED 9 /* The device was suspended */ #define DASD_FLAG_SAFE_OFFLINE 10 /* safe offline processing requested*/ #define DASD_FLAG_SAFE_OFFLINE_RUNNING 11 /* safe offline running */ +#define DASD_FLAG_ABORTALL 12 /* Abort all noretry requests */ +#define DASD_SLEEPON_START_TAG ((void *) 1) +#define DASD_SLEEPON_END_TAG ((void *) 2) void dasd_put_device_wake(struct dasd_device *); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 8be1b51..25a0f2f 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -141,6 +141,59 @@ static int dasd_ioctl_resume(struct dasd_block *block) } /* + * Abort all failfast I/O on a device. + */ +static int dasd_ioctl_abortio(struct dasd_block *block) +{ + unsigned long flags; + struct dasd_device *base; + struct dasd_ccw_req *cqr, *n; + + base = block->base; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (test_and_set_bit(DASD_FLAG_ABORTALL, &base->flags)) + return 0; + DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag set"); + + spin_lock_irqsave(&block->request_queue_lock, flags); + spin_lock(&block->queue_lock); + list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) { + if (test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && + cqr->callback_data && + cqr->callback_data != DASD_SLEEPON_START_TAG && + cqr->callback_data != DASD_SLEEPON_END_TAG) { + spin_unlock(&block->queue_lock); + blk_abort_request(cqr->callback_data); + spin_lock(&block->queue_lock); + } + } + spin_unlock(&block->queue_lock); + spin_unlock_irqrestore(&block->request_queue_lock, flags); + + dasd_schedule_block_bh(block); + return 0; +} + +/* + * Allow I/O on a device + */ +static int dasd_ioctl_allowio(struct dasd_block *block) +{ + struct dasd_device *base; + + base = block->base; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (test_and_clear_bit(DASD_FLAG_ABORTALL, &base->flags)) + DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag unset"); + + return 0; +} + +/* * performs formatting of _device_ according to _fdata_ * Note: The discipline's format_function is assumed to deliver formatting * commands to format multiple units of the device. In terms of the ECKD @@ -458,6 +511,12 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, case BIODASDRESUME: rc = dasd_ioctl_resume(block); break; + case BIODASDABORTIO: + rc = dasd_ioctl_abortio(block); + break; + case BIODASDALLOWIO: + rc = dasd_ioctl_allowio(block); + break; case BIODASDFMT: rc = dasd_ioctl_format(bdev, argp); break; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/