aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/uapi/asm/dasd.h4
-rw-r--r--drivers/s390/block/dasd.c13
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c59
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
529void dasd_put_device_wake(struct dasd_device *); 532void 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 */
146static 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 */
182static 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;