block-5.18-2022-05-06
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmJ10nMQHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgpmkYD/9vfbQhyxrDH/GfKua18QmfQARphw6Ihegc NSVjJ38dohNiLekNKgTmquWtVl/s6g/roa0+zzUF66eML/6SnKRoVZHh6cJ5Vopk lpj6Pzb6COu+Vo7lWysDHCT4g2iYr6MaAgKKFrsVG6PkQ1vSxx2w6nQwInDHY2hG 4YL+NM8ID5SHzmfr9XYpAkDu6XoU1rVpq+JnZPzejWHUUwxMYMcNmLjZio/ysE6G 0NrW4LXmu1gJxv4+9betVjNin5CU7LLhxdigSTs/nGlqi9I9lq02tWLhUw7swTD3 xWReoxsKWzRzLB2Nb5lsERrv37XKSghkLuQkoa+gtr7wTfvUCZKePBrZ/BE0VzYf bnXaFA0gOa/H4P2AB68ZB8WaNhxtYZsW2PXDei4ramUFlPkyKstwAKxF2ViiBHKC VrR2aQ82VUm2b3iY1QnbxVAuiPLGT/t4RFJyaiFbA5dzEyd3ofMUTTz7m62K4khQ HlQLwl4jN+vVmDsvNr5zb1N1xZaChiyDJPGqofGAWbAWjdBsEuTt644mnn341/3r VluH+Eswkvi6SMn990QbI3TmqWWmyzUc7DafrK2V3mKlUu9swch34fFV5arU0xSJ 7bJ+vL75U5A8NWCOOLML2BPX9L4gVIpaKg0PHQ+Rhlc0/STQdaXa0TgrUVNB8YMS O4ubYf/raA== =zQyX -----END PGP SIGNATURE----- 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"
This commit is contained in:
commit
8967605e7d
|
@ -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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
* 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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
} 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
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)
|
||||||
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 {
|
||||||
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 {
|
||||||
|
|
||||||
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)
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue