s390/dasd: Fail all requests when DASD_FLAG_ABORTIO is set
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 <hare@suse.de> Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
3d71ad3216
Коммит
5ea34a0142
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -140,6 +140,59 @@ static int dasd_ioctl_resume(struct dasd_block *block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче