Skip to content

Commit 8967605

Browse files
committed
Merge tag 'block-5.18-2022-05-06' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe: "A single revert for a change that isn't needed in 5.18, and a small series for s390/dasd" * tag 'block-5.18-2022-05-06' of git://git.kernel.dk/linux-block: s390/dasd: Use kzalloc instead of kmalloc/memset s390/dasd: Fix read inconsistency for ESE DASD devices s390/dasd: Fix read for ESE with blksize < 4k s390/dasd: prevent double format of tracks for ESE devices s390/dasd: fix data corruption for ESE devices Revert "block: release rq qos structures for queue without disk"
2 parents b366bd7 + f1c8781 commit 8967605

4 files changed

Lines changed: 51 additions & 18 deletions

File tree

block/blk-core.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
#include "blk-pm.h"
5151
#include "blk-cgroup.h"
5252
#include "blk-throttle.h"
53-
#include "blk-rq-qos.h"
5453

5554
struct dentry *blk_debugfs_root;
5655

@@ -315,9 +314,6 @@ void blk_cleanup_queue(struct request_queue *q)
315314
*/
316315
blk_freeze_queue(q);
317316

318-
/* cleanup rq qos structures for queue without disk */
319-
rq_qos_exit(q);
320-
321317
blk_queue_flag_set(QUEUE_FLAG_DEAD, q);
322318

323319
blk_sync_queue(q);

drivers/s390/block/dasd.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,13 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
14221422
if (!cqr->lpm)
14231423
cqr->lpm = dasd_path_get_opm(device);
14241424
}
1425+
/*
1426+
* remember the amount of formatted tracks to prevent double format on
1427+
* ESE devices
1428+
*/
1429+
if (cqr->block)
1430+
cqr->trkcount = atomic_read(&cqr->block->trkcount);
1431+
14251432
if (cqr->cpmode == 1) {
14261433
rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
14271434
(long) cqr, cqr->lpm);
@@ -1639,6 +1646,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16391646
unsigned long now;
16401647
int nrf_suppressed = 0;
16411648
int fp_suppressed = 0;
1649+
struct request *req;
16421650
u8 *sense = NULL;
16431651
int expires;
16441652

@@ -1739,7 +1747,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
17391747
}
17401748

17411749
if (dasd_ese_needs_format(cqr->block, irb)) {
1742-
if (rq_data_dir((struct request *)cqr->callback_data) == READ) {
1750+
req = dasd_get_callback_data(cqr);
1751+
if (!req) {
1752+
cqr->status = DASD_CQR_ERROR;
1753+
return;
1754+
}
1755+
if (rq_data_dir(req) == READ) {
17431756
device->discipline->ese_read(cqr, irb);
17441757
cqr->status = DASD_CQR_SUCCESS;
17451758
cqr->stopclk = now;
@@ -2765,8 +2778,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
27652778
* complete a request partially.
27662779
*/
27672780
if (proc_bytes) {
2768-
blk_update_request(req, BLK_STS_OK,
2769-
blk_rq_bytes(req) - proc_bytes);
2781+
blk_update_request(req, BLK_STS_OK, proc_bytes);
27702782
blk_mq_requeue_request(req, true);
27712783
} else if (likely(!blk_should_fake_timeout(req->q))) {
27722784
blk_mq_complete_request(req);

drivers/s390/block/dasd_eckd.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,17 +1480,14 @@ static int dasd_eckd_pe_handler(struct dasd_device *device,
14801480
{
14811481
struct pe_handler_work_data *data;
14821482

1483-
data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
1483+
data = kzalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
14841484
if (!data) {
14851485
if (mutex_trylock(&dasd_pe_handler_mutex)) {
14861486
data = pe_handler_worker;
14871487
data->isglobal = 1;
14881488
} else {
14891489
return -ENOMEM;
14901490
}
1491-
} else {
1492-
memset(data, 0, sizeof(*data));
1493-
data->isglobal = 0;
14941491
}
14951492
INIT_WORK(&data->worker, do_pe_handler_work);
14961493
dasd_get_device(device);
@@ -3083,13 +3080,24 @@ static int dasd_eckd_format_device(struct dasd_device *base,
30833080
}
30843081

30853082
static bool test_and_set_format_track(struct dasd_format_entry *to_format,
3086-
struct dasd_block *block)
3083+
struct dasd_ccw_req *cqr)
30873084
{
3085+
struct dasd_block *block = cqr->block;
30883086
struct dasd_format_entry *format;
30893087
unsigned long flags;
30903088
bool rc = false;
30913089

30923090
spin_lock_irqsave(&block->format_lock, flags);
3091+
if (cqr->trkcount != atomic_read(&block->trkcount)) {
3092+
/*
3093+
* The number of formatted tracks has changed after request
3094+
* start and we can not tell if the current track was involved.
3095+
* To avoid data corruption treat it as if the current track is
3096+
* involved
3097+
*/
3098+
rc = true;
3099+
goto out;
3100+
}
30933101
list_for_each_entry(format, &block->format_list, list) {
30943102
if (format->track == to_format->track) {
30953103
rc = true;
@@ -3109,6 +3117,7 @@ static void clear_format_track(struct dasd_format_entry *format,
31093117
unsigned long flags;
31103118

31113119
spin_lock_irqsave(&block->format_lock, flags);
3120+
atomic_inc(&block->trkcount);
31123121
list_del_init(&format->list);
31133122
spin_unlock_irqrestore(&block->format_lock, flags);
31143123
}
@@ -3145,7 +3154,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
31453154
sector_t curr_trk;
31463155
int rc;
31473156

3148-
req = cqr->callback_data;
3157+
req = dasd_get_callback_data(cqr);
31493158
block = cqr->block;
31503159
base = block->base;
31513160
private = base->private;
@@ -3170,8 +3179,11 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
31703179
}
31713180
format->track = curr_trk;
31723181
/* test if track is already in formatting by another thread */
3173-
if (test_and_set_format_track(format, block))
3182+
if (test_and_set_format_track(format, cqr)) {
3183+
/* this is no real error so do not count down retries */
3184+
cqr->retries++;
31743185
return ERR_PTR(-EEXIST);
3186+
}
31753187

31763188
fdata.start_unit = curr_trk;
31773189
fdata.stop_unit = curr_trk;
@@ -3270,12 +3282,11 @@ static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb)
32703282
cqr->proc_bytes = blk_count * blksize;
32713283
return 0;
32723284
}
3273-
if (dst && !skip_block) {
3274-
dst += off;
3285+
if (dst && !skip_block)
32753286
memset(dst, 0, blksize);
3276-
} else {
3287+
else
32773288
skip_block--;
3278-
}
3289+
dst += blksize;
32793290
blk_count++;
32803291
}
32813292
}

drivers/s390/block/dasd_int.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ struct dasd_ccw_req {
187187
void (*callback)(struct dasd_ccw_req *, void *data);
188188
void *callback_data;
189189
unsigned int proc_bytes; /* bytes for partial completion */
190+
unsigned int trkcount; /* count formatted tracks */
190191
};
191192

192193
/*
@@ -610,6 +611,7 @@ struct dasd_block {
610611

611612
struct list_head format_list;
612613
spinlock_t format_lock;
614+
atomic_t trkcount;
613615
};
614616

615617
struct dasd_attention_data {
@@ -756,6 +758,18 @@ dasd_check_blocksize(int bsize)
756758
return 0;
757759
}
758760

761+
/*
762+
* return the callback data of the original request in case there are
763+
* ERP requests build on top of it
764+
*/
765+
static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr)
766+
{
767+
while (cqr->refers)
768+
cqr = cqr->refers;
769+
770+
return cqr->callback_data;
771+
}
772+
759773
/* externals in dasd.c */
760774
#define DASD_PROFILE_OFF 0
761775
#define DASD_PROFILE_ON 1

0 commit comments

Comments
 (0)