diff options
-rw-r--r-- | arch/s390/include/uapi/asm/dasd.h | 4 | ||||
-rw-r--r-- | drivers/s390/block/dasd.c | 13 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 3 | ||||
-rw-r--r-- | 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 38eca3ba40e2..5812a3b2df9e 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 { | |||
261 | #define BIODASDQUIESCE _IO(DASD_IOCTL_LETTER,6) | 261 | #define BIODASDQUIESCE _IO(DASD_IOCTL_LETTER,6) |
262 | /* Resume IO on device */ | 262 | /* Resume IO on device */ |
263 | #define BIODASDRESUME _IO(DASD_IOCTL_LETTER,7) | 263 | #define BIODASDRESUME _IO(DASD_IOCTL_LETTER,7) |
264 | /* Abort all I/O on a device */ | ||
265 | #define BIODASDABORTIO _IO(DASD_IOCTL_LETTER, 240) | ||
266 | /* Allow I/O on a device */ | ||
267 | #define BIODASDALLOWIO _IO(DASD_IOCTL_LETTER, 241) | ||
264 | 268 | ||
265 | 269 | ||
266 | /* retrieve API version number */ | 270 | /* retrieve API version number */ |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 54f4bb8060c1..17150a778984 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -38,9 +38,6 @@ | |||
38 | */ | 38 | */ |
39 | #define DASD_CHANQ_MAX_SIZE 4 | 39 | #define DASD_CHANQ_MAX_SIZE 4 |
40 | 40 | ||
41 | #define DASD_SLEEPON_START_TAG (void *) 1 | ||
42 | #define DASD_SLEEPON_END_TAG (void *) 2 | ||
43 | |||
44 | /* | 41 | /* |
45 | * SECTION: exported variables of dasd.c | 42 | * SECTION: exported variables of dasd.c |
46 | */ | 43 | */ |
@@ -2535,6 +2532,16 @@ static void __dasd_process_request_queue(struct dasd_block *block) | |||
2535 | __blk_end_request_all(req, -EIO); | 2532 | __blk_end_request_all(req, -EIO); |
2536 | continue; | 2533 | continue; |
2537 | } | 2534 | } |
2535 | if (test_bit(DASD_FLAG_ABORTALL, &basedev->flags) && | ||
2536 | (basedev->features & DASD_FEATURE_FAILFAST || | ||
2537 | blk_noretry_request(req))) { | ||
2538 | DBF_DEV_EVENT(DBF_ERR, basedev, | ||
2539 | "Rejecting failfast request %p", | ||
2540 | req); | ||
2541 | blk_start_request(req); | ||
2542 | __blk_end_request_all(req, -ETIMEDOUT); | ||
2543 | continue; | ||
2544 | } | ||
2538 | cqr = basedev->discipline->build_cp(basedev, block, req); | 2545 | cqr = basedev->discipline->build_cp(basedev, block, req); |
2539 | if (IS_ERR(cqr)) { | 2546 | if (IS_ERR(cqr)) { |
2540 | if (PTR_ERR(cqr) == -EBUSY) | 2547 | if (PTR_ERR(cqr) == -EBUSY) |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 2bd03f45a72e..690001af0d09 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -524,7 +524,10 @@ struct dasd_block { | |||
524 | #define DASD_FLAG_SUSPENDED 9 /* The device was suspended */ | 524 | #define DASD_FLAG_SUSPENDED 9 /* The device was suspended */ |
525 | #define DASD_FLAG_SAFE_OFFLINE 10 /* safe offline processing requested*/ | 525 | #define DASD_FLAG_SAFE_OFFLINE 10 /* safe offline processing requested*/ |
526 | #define DASD_FLAG_SAFE_OFFLINE_RUNNING 11 /* safe offline running */ | 526 | #define DASD_FLAG_SAFE_OFFLINE_RUNNING 11 /* safe offline running */ |
527 | #define DASD_FLAG_ABORTALL 12 /* Abort all noretry requests */ | ||
527 | 528 | ||
529 | #define DASD_SLEEPON_START_TAG ((void *) 1) | ||
530 | #define DASD_SLEEPON_END_TAG ((void *) 2) | ||
528 | 531 | ||
529 | void dasd_put_device_wake(struct dasd_device *); | 532 | void dasd_put_device_wake(struct dasd_device *); |
530 | 533 | ||
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 8be1b51e9311..25a0f2f8b0b9 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) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * Abort all failfast I/O on a device. | ||
145 | */ | ||
146 | static int dasd_ioctl_abortio(struct dasd_block *block) | ||
147 | { | ||
148 | unsigned long flags; | ||
149 | struct dasd_device *base; | ||
150 | struct dasd_ccw_req *cqr, *n; | ||
151 | |||
152 | base = block->base; | ||
153 | if (!capable(CAP_SYS_ADMIN)) | ||
154 | return -EACCES; | ||
155 | |||
156 | if (test_and_set_bit(DASD_FLAG_ABORTALL, &base->flags)) | ||
157 | return 0; | ||
158 | DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag set"); | ||
159 | |||
160 | spin_lock_irqsave(&block->request_queue_lock, flags); | ||
161 | spin_lock(&block->queue_lock); | ||
162 | list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) { | ||
163 | if (test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && | ||
164 | cqr->callback_data && | ||
165 | cqr->callback_data != DASD_SLEEPON_START_TAG && | ||
166 | cqr->callback_data != DASD_SLEEPON_END_TAG) { | ||
167 | spin_unlock(&block->queue_lock); | ||
168 | blk_abort_request(cqr->callback_data); | ||
169 | spin_lock(&block->queue_lock); | ||
170 | } | ||
171 | } | ||
172 | spin_unlock(&block->queue_lock); | ||
173 | spin_unlock_irqrestore(&block->request_queue_lock, flags); | ||
174 | |||
175 | dasd_schedule_block_bh(block); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Allow I/O on a device | ||
181 | */ | ||
182 | static int dasd_ioctl_allowio(struct dasd_block *block) | ||
183 | { | ||
184 | struct dasd_device *base; | ||
185 | |||
186 | base = block->base; | ||
187 | if (!capable(CAP_SYS_ADMIN)) | ||
188 | return -EACCES; | ||
189 | |||
190 | if (test_and_clear_bit(DASD_FLAG_ABORTALL, &base->flags)) | ||
191 | DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag unset"); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* | ||
144 | * performs formatting of _device_ according to _fdata_ | 197 | * performs formatting of _device_ according to _fdata_ |
145 | * Note: The discipline's format_function is assumed to deliver formatting | 198 | * Note: The discipline's format_function is assumed to deliver formatting |
146 | * commands to format multiple units of the device. In terms of the ECKD | 199 | * 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, | |||
458 | case BIODASDRESUME: | 511 | case BIODASDRESUME: |
459 | rc = dasd_ioctl_resume(block); | 512 | rc = dasd_ioctl_resume(block); |
460 | break; | 513 | break; |
514 | case BIODASDABORTIO: | ||
515 | rc = dasd_ioctl_abortio(block); | ||
516 | break; | ||
517 | case BIODASDALLOWIO: | ||
518 | rc = dasd_ioctl_allowio(block); | ||
519 | break; | ||
461 | case BIODASDFMT: | 520 | case BIODASDFMT: |
462 | rc = dasd_ioctl_format(bdev, argp); | 521 | rc = dasd_ioctl_format(bdev, argp); |
463 | break; | 522 | break; |