Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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"

+51 -18
-4
block/blk-core.c
··· 50 50 #include "blk-pm.h" 51 51 #include "blk-cgroup.h" 52 52 #include "blk-throttle.h" 53 - #include "blk-rq-qos.h" 54 53 55 54 struct dentry *blk_debugfs_root; 56 55 ··· 313 314 * after draining finished. 314 315 */ 315 316 blk_freeze_queue(q); 316 - 317 - /* cleanup rq qos structures for queue without disk */ 318 - rq_qos_exit(q); 319 317 320 318 blk_queue_flag_set(QUEUE_FLAG_DEAD, q); 321 319
+15 -3
drivers/s390/block/dasd.c
··· 1422 1422 if (!cqr->lpm) 1423 1423 cqr->lpm = dasd_path_get_opm(device); 1424 1424 } 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 + 1425 1432 if (cqr->cpmode == 1) { 1426 1433 rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, 1427 1434 (long) cqr, cqr->lpm); ··· 1646 1639 unsigned long now; 1647 1640 int nrf_suppressed = 0; 1648 1641 int fp_suppressed = 0; 1642 + struct request *req; 1649 1643 u8 *sense = NULL; 1650 1644 int expires; 1651 1645 ··· 1747 1739 } 1748 1740 1749 1741 if (dasd_ese_needs_format(cqr->block, irb)) { 1750 - if (rq_data_dir((struct request *)cqr->callback_data) == READ) { 1742 + req = dasd_get_callback_data(cqr); 1743 + if (!req) { 1744 + cqr->status = DASD_CQR_ERROR; 1745 + return; 1746 + } 1747 + if (rq_data_dir(req) == READ) { 1751 1748 device->discipline->ese_read(cqr, irb); 1752 1749 cqr->status = DASD_CQR_SUCCESS; 1753 1750 cqr->stopclk = now; ··· 2778 2765 * complete a request partially. 2779 2766 */ 2780 2767 if (proc_bytes) { 2781 - blk_update_request(req, BLK_STS_OK, 2782 - blk_rq_bytes(req) - proc_bytes); 2768 + blk_update_request(req, BLK_STS_OK, proc_bytes); 2783 2769 blk_mq_requeue_request(req, true); 2784 2770 } else if (likely(!blk_should_fake_timeout(req->q))) { 2785 2771 blk_mq_complete_request(req);
+22 -11
drivers/s390/block/dasd_eckd.c
··· 1480 1480 { 1481 1481 struct pe_handler_work_data *data; 1482 1482 1483 - data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA); 1483 + data = kzalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA); 1484 1484 if (!data) { 1485 1485 if (mutex_trylock(&dasd_pe_handler_mutex)) { 1486 1486 data = pe_handler_worker; ··· 1488 1488 } else { 1489 1489 return -ENOMEM; 1490 1490 } 1491 - } else { 1492 - memset(data, 0, sizeof(*data)); 1493 - data->isglobal = 0; 1494 1491 } 1495 1492 INIT_WORK(&data->worker, do_pe_handler_work); 1496 1493 dasd_get_device(device); ··· 3080 3083 } 3081 3084 3082 3085 static bool test_and_set_format_track(struct dasd_format_entry *to_format, 3083 - struct dasd_block *block) 3086 + struct dasd_ccw_req *cqr) 3084 3087 { 3088 + struct dasd_block *block = cqr->block; 3085 3089 struct dasd_format_entry *format; 3086 3090 unsigned long flags; 3087 3091 bool rc = false; 3088 3092 3089 3093 spin_lock_irqsave(&block->format_lock, flags); 3094 + if (cqr->trkcount != atomic_read(&block->trkcount)) { 3095 + /* 3096 + * The number of formatted tracks has changed after request 3097 + * start and we can not tell if the current track was involved. 3098 + * To avoid data corruption treat it as if the current track is 3099 + * involved 3100 + */ 3101 + rc = true; 3102 + goto out; 3103 + } 3090 3104 list_for_each_entry(format, &block->format_list, list) { 3091 3105 if (format->track == to_format->track) { 3092 3106 rc = true; ··· 3117 3109 unsigned long flags; 3118 3110 3119 3111 spin_lock_irqsave(&block->format_lock, flags); 3112 + atomic_inc(&block->trkcount); 3120 3113 list_del_init(&format->list); 3121 3114 spin_unlock_irqrestore(&block->format_lock, flags); 3122 3115 } ··· 3154 3145 sector_t curr_trk; 3155 3146 int rc; 3156 3147 3157 - req = cqr->callback_data; 3148 + req = dasd_get_callback_data(cqr); 3158 3149 block = cqr->block; 3159 3150 base = block->base; 3160 3151 private = base->private; ··· 3179 3170 } 3180 3171 format->track = curr_trk; 3181 3172 /* test if track is already in formatting by another thread */ 3182 - if (test_and_set_format_track(format, block)) 3173 + if (test_and_set_format_track(format, cqr)) { 3174 + /* this is no real error so do not count down retries */ 3175 + cqr->retries++; 3183 3176 return ERR_PTR(-EEXIST); 3177 + } 3184 3178 3185 3179 fdata.start_unit = curr_trk; 3186 3180 fdata.stop_unit = curr_trk; ··· 3282 3270 cqr->proc_bytes = blk_count * blksize; 3283 3271 return 0; 3284 3272 } 3285 - if (dst && !skip_block) { 3286 - dst += off; 3273 + if (dst && !skip_block) 3287 3274 memset(dst, 0, blksize); 3288 - } else { 3275 + else 3289 3276 skip_block--; 3290 - } 3277 + dst += blksize; 3291 3278 blk_count++; 3292 3279 } 3293 3280 }
+14
drivers/s390/block/dasd_int.h
··· 187 187 void (*callback)(struct dasd_ccw_req *, void *data); 188 188 void *callback_data; 189 189 unsigned int proc_bytes; /* bytes for partial completion */ 190 + unsigned int trkcount; /* count formatted tracks */ 190 191 }; 191 192 192 193 /* ··· 611 610 612 611 struct list_head format_list; 613 612 spinlock_t format_lock; 613 + atomic_t trkcount; 614 614 }; 615 615 616 616 struct dasd_attention_data { ··· 756 754 if (bsize < 512 || bsize > 4096 || !is_power_of_2(bsize)) 757 755 return -EMEDIUMTYPE; 758 756 return 0; 757 + } 758 + 759 + /* 760 + * return the callback data of the original request in case there are 761 + * ERP requests build on top of it 762 + */ 763 + static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr) 764 + { 765 + while (cqr->refers) 766 + cqr = cqr->refers; 767 + 768 + return cqr->callback_data; 759 769 } 760 770 761 771 /* externals in dasd.c */