Commit 8967605e authored by Linus Torvalds's avatar Linus Torvalds

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"
parents b366bd7d f1c8781a
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
#include "blk-pm.h" #include "blk-pm.h"
#include "blk-cgroup.h" #include "blk-cgroup.h"
#include "blk-throttle.h" #include "blk-throttle.h"
#include "blk-rq-qos.h"
struct dentry *blk_debugfs_root; struct dentry *blk_debugfs_root;
...@@ -315,9 +314,6 @@ void blk_cleanup_queue(struct request_queue *q) ...@@ -315,9 +314,6 @@ void blk_cleanup_queue(struct request_queue *q)
*/ */
blk_freeze_queue(q); blk_freeze_queue(q);
/* cleanup rq qos structures for queue without disk */
rq_qos_exit(q);
blk_queue_flag_set(QUEUE_FLAG_DEAD, q); blk_queue_flag_set(QUEUE_FLAG_DEAD, q);
blk_sync_queue(q); blk_sync_queue(q);
......
...@@ -1422,6 +1422,13 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) ...@@ -1422,6 +1422,13 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
if (!cqr->lpm) if (!cqr->lpm)
cqr->lpm = dasd_path_get_opm(device); cqr->lpm = dasd_path_get_opm(device);
} }
/*
* remember the amount of formatted tracks to prevent double format on
* ESE devices
*/
if (cqr->block)
cqr->trkcount = atomic_read(&cqr->block->trkcount);
if (cqr->cpmode == 1) { if (cqr->cpmode == 1) {
rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
(long) cqr, cqr->lpm); (long) cqr, cqr->lpm);
...@@ -1639,6 +1646,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -1639,6 +1646,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
unsigned long now; unsigned long now;
int nrf_suppressed = 0; int nrf_suppressed = 0;
int fp_suppressed = 0; int fp_suppressed = 0;
struct request *req;
u8 *sense = NULL; u8 *sense = NULL;
int expires; int expires;
...@@ -1739,7 +1747,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -1739,7 +1747,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
} }
if (dasd_ese_needs_format(cqr->block, irb)) { if (dasd_ese_needs_format(cqr->block, irb)) {
if (rq_data_dir((struct request *)cqr->callback_data) == READ) { req = dasd_get_callback_data(cqr);
if (!req) {
cqr->status = DASD_CQR_ERROR;
return;
}
if (rq_data_dir(req) == READ) {
device->discipline->ese_read(cqr, irb); device->discipline->ese_read(cqr, irb);
cqr->status = DASD_CQR_SUCCESS; cqr->status = DASD_CQR_SUCCESS;
cqr->stopclk = now; cqr->stopclk = now;
...@@ -2765,8 +2778,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) ...@@ -2765,8 +2778,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
* complete a request partially. * complete a request partially.
*/ */
if (proc_bytes) { if (proc_bytes) {
blk_update_request(req, BLK_STS_OK, blk_update_request(req, BLK_STS_OK, proc_bytes);
blk_rq_bytes(req) - proc_bytes);
blk_mq_requeue_request(req, true); blk_mq_requeue_request(req, true);
} else if (likely(!blk_should_fake_timeout(req->q))) { } else if (likely(!blk_should_fake_timeout(req->q))) {
blk_mq_complete_request(req); blk_mq_complete_request(req);
......
...@@ -1480,7 +1480,7 @@ static int dasd_eckd_pe_handler(struct dasd_device *device, ...@@ -1480,7 +1480,7 @@ static int dasd_eckd_pe_handler(struct dasd_device *device,
{ {
struct pe_handler_work_data *data; struct pe_handler_work_data *data;
data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA); data = kzalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
if (!data) { if (!data) {
if (mutex_trylock(&dasd_pe_handler_mutex)) { if (mutex_trylock(&dasd_pe_handler_mutex)) {
data = pe_handler_worker; data = pe_handler_worker;
...@@ -1488,9 +1488,6 @@ static int dasd_eckd_pe_handler(struct dasd_device *device, ...@@ -1488,9 +1488,6 @@ static int dasd_eckd_pe_handler(struct dasd_device *device,
} else { } else {
return -ENOMEM; return -ENOMEM;
} }
} else {
memset(data, 0, sizeof(*data));
data->isglobal = 0;
} }
INIT_WORK(&data->worker, do_pe_handler_work); INIT_WORK(&data->worker, do_pe_handler_work);
dasd_get_device(device); dasd_get_device(device);
...@@ -3083,13 +3080,24 @@ static int dasd_eckd_format_device(struct dasd_device *base, ...@@ -3083,13 +3080,24 @@ static int dasd_eckd_format_device(struct dasd_device *base,
} }
static bool test_and_set_format_track(struct dasd_format_entry *to_format, static bool test_and_set_format_track(struct dasd_format_entry *to_format,
struct dasd_block *block) struct dasd_ccw_req *cqr)
{ {
struct dasd_block *block = cqr->block;
struct dasd_format_entry *format; struct dasd_format_entry *format;
unsigned long flags; unsigned long flags;
bool rc = false; bool rc = false;
spin_lock_irqsave(&block->format_lock, flags); spin_lock_irqsave(&block->format_lock, flags);
if (cqr->trkcount != atomic_read(&block->trkcount)) {
/*
* The number of formatted tracks has changed after request
* start and we can not tell if the current track was involved.
* To avoid data corruption treat it as if the current track is
* involved
*/
rc = true;
goto out;
}
list_for_each_entry(format, &block->format_list, list) { list_for_each_entry(format, &block->format_list, list) {
if (format->track == to_format->track) { if (format->track == to_format->track) {
rc = true; rc = true;
...@@ -3109,6 +3117,7 @@ static void clear_format_track(struct dasd_format_entry *format, ...@@ -3109,6 +3117,7 @@ static void clear_format_track(struct dasd_format_entry *format,
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&block->format_lock, flags); spin_lock_irqsave(&block->format_lock, flags);
atomic_inc(&block->trkcount);
list_del_init(&format->list); list_del_init(&format->list);
spin_unlock_irqrestore(&block->format_lock, flags); spin_unlock_irqrestore(&block->format_lock, flags);
} }
...@@ -3145,7 +3154,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr, ...@@ -3145,7 +3154,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
sector_t curr_trk; sector_t curr_trk;
int rc; int rc;
req = cqr->callback_data; req = dasd_get_callback_data(cqr);
block = cqr->block; block = cqr->block;
base = block->base; base = block->base;
private = base->private; private = base->private;
...@@ -3170,8 +3179,11 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr, ...@@ -3170,8 +3179,11 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
} }
format->track = curr_trk; format->track = curr_trk;
/* test if track is already in formatting by another thread */ /* test if track is already in formatting by another thread */
if (test_and_set_format_track(format, block)) if (test_and_set_format_track(format, cqr)) {
/* this is no real error so do not count down retries */
cqr->retries++;
return ERR_PTR(-EEXIST); return ERR_PTR(-EEXIST);
}
fdata.start_unit = curr_trk; fdata.start_unit = curr_trk;
fdata.stop_unit = curr_trk; fdata.stop_unit = curr_trk;
...@@ -3270,12 +3282,11 @@ static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb) ...@@ -3270,12 +3282,11 @@ static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb)
cqr->proc_bytes = blk_count * blksize; cqr->proc_bytes = blk_count * blksize;
return 0; return 0;
} }
if (dst && !skip_block) { if (dst && !skip_block)
dst += off;
memset(dst, 0, blksize); memset(dst, 0, blksize);
} else { else
skip_block--; skip_block--;
} dst += blksize;
blk_count++; blk_count++;
} }
} }
......
...@@ -187,6 +187,7 @@ struct dasd_ccw_req { ...@@ -187,6 +187,7 @@ struct dasd_ccw_req {
void (*callback)(struct dasd_ccw_req *, void *data); void (*callback)(struct dasd_ccw_req *, void *data);
void *callback_data; void *callback_data;
unsigned int proc_bytes; /* bytes for partial completion */ unsigned int proc_bytes; /* bytes for partial completion */
unsigned int trkcount; /* count formatted tracks */
}; };
/* /*
...@@ -610,6 +611,7 @@ struct dasd_block { ...@@ -610,6 +611,7 @@ struct dasd_block {
struct list_head format_list; struct list_head format_list;
spinlock_t format_lock; spinlock_t format_lock;
atomic_t trkcount;
}; };
struct dasd_attention_data { struct dasd_attention_data {
...@@ -756,6 +758,18 @@ dasd_check_blocksize(int bsize) ...@@ -756,6 +758,18 @@ dasd_check_blocksize(int bsize)
return 0; return 0;
} }
/*
* return the callback data of the original request in case there are
* ERP requests build on top of it
*/
static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr)
{
while (cqr->refers)
cqr = cqr->refers;
return cqr->callback_data;
}
/* externals in dasd.c */ /* externals in dasd.c */
#define DASD_PROFILE_OFF 0 #define DASD_PROFILE_OFF 0
#define DASD_PROFILE_ON 1 #define DASD_PROFILE_ON 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment