mirror of https://gitee.com/openkylin/linux.git
- a revert of a DM mirror commit that has proven to make the code prone
to crash - a DM io reference count fix that resolves a NULL pointer seen when issuing discards to a DM mirror target's device whose mirror legs do not all support discards - a couple DM integrity fixes -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJZTBU6AAoJEMUj8QotnQNaDJEH/3ujmjAnN1gpB4PhMh7kGyKA i8qB476EYTEH8mPha88lvGoGoTk07cgwuWgQtulbcIlM0PbtbjcRs4lxEPCJW8sm BeBnwKnBtnd+I+INKK0RCkYNHxO1ciCv4jMe08xNvSOrcmNVI1E4HjQ5GtJX7IMO eQCEdTsDhf+ZXGnE6ErzfLVYnrazhNhk40+2jSlDFxDL8Qpd43EwMw5iHzeh0ztm Frf9+JjWlckUS6oVm1AkTygbRrS3FEJ/cM3ei61/kj6hYzFGcP4Ba95Zd/E5k1Ls 9byBw93KTW3Pi5BKeVTo/JgxITcVQUZAWn95qF7HofZn6oBLdEiHzXLHQctl9Qs= =fZVe -----END PGP SIGNATURE----- Merge tag 'for-4.12/dm-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm Pull device mapper fixes from Mike Snitzer: - a revert of a DM mirror commit that has proven to make the code prone to crash - a DM io reference count fix that resolves a NULL pointer seen when issuing discards to a DM mirror target's device whose mirror legs do not all support discards - a couple DM integrity fixes * tag 'for-4.12/dm-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm io: fix duplicate bio completion due to missing ref count dm integrity: fix to not disable/enable interrupts from interrupt context Revert "dm mirror: use all available legs on multiple failures" dm integrity: reject mappings too large for device
This commit is contained in:
commit
7ec2f7e8d9
|
@ -1105,10 +1105,13 @@ static void schedule_autocommit(struct dm_integrity_c *ic)
|
|||
static void submit_flush_bio(struct dm_integrity_c *ic, struct dm_integrity_io *dio)
|
||||
{
|
||||
struct bio *bio;
|
||||
spin_lock_irq(&ic->endio_wait.lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ic->endio_wait.lock, flags);
|
||||
bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
|
||||
bio_list_add(&ic->flush_bio_list, bio);
|
||||
spin_unlock_irq(&ic->endio_wait.lock);
|
||||
spin_unlock_irqrestore(&ic->endio_wait.lock, flags);
|
||||
|
||||
queue_work(ic->commit_wq, &ic->commit_work);
|
||||
}
|
||||
|
||||
|
@ -3040,6 +3043,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|||
ti->error = "The device is too small";
|
||||
goto bad;
|
||||
}
|
||||
if (ti->len > ic->provided_data_sectors) {
|
||||
r = -EINVAL;
|
||||
ti->error = "Not enough provided sectors for requested mapping size";
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!buffer_sectors)
|
||||
buffer_sectors = 1;
|
||||
|
|
|
@ -317,8 +317,8 @@ static void do_region(int op, int op_flags, unsigned region,
|
|||
else if (op == REQ_OP_WRITE_SAME)
|
||||
special_cmd_max_sectors = q->limits.max_write_same_sectors;
|
||||
if ((op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES ||
|
||||
op == REQ_OP_WRITE_SAME) &&
|
||||
special_cmd_max_sectors == 0) {
|
||||
op == REQ_OP_WRITE_SAME) && special_cmd_max_sectors == 0) {
|
||||
atomic_inc(&io->count);
|
||||
dec_count(io, region, -EOPNOTSUPP);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
|
|||
|
||||
struct dm_raid1_bio_record {
|
||||
struct mirror *m;
|
||||
/* if details->bi_bdev == NULL, details were not saved */
|
||||
struct dm_bio_details details;
|
||||
region_t write_region;
|
||||
};
|
||||
|
@ -1198,6 +1199,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
|
|||
struct dm_raid1_bio_record *bio_record =
|
||||
dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
|
||||
|
||||
bio_record->details.bi_bdev = NULL;
|
||||
|
||||
if (rw == WRITE) {
|
||||
/* Save region for mirror_end_io() handler */
|
||||
bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
|
||||
|
@ -1256,12 +1259,22 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
|||
}
|
||||
|
||||
if (error == -EOPNOTSUPP)
|
||||
return error;
|
||||
goto out;
|
||||
|
||||
if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
|
||||
return error;
|
||||
goto out;
|
||||
|
||||
if (unlikely(error)) {
|
||||
if (!bio_record->details.bi_bdev) {
|
||||
/*
|
||||
* There wasn't enough memory to record necessary
|
||||
* information for a retry or there was no other
|
||||
* mirror in-sync.
|
||||
*/
|
||||
DMERR_LIMIT("Mirror read failed.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
m = bio_record->m;
|
||||
|
||||
DMERR("Mirror read failed from %s. Trying alternative device.",
|
||||
|
@ -1277,6 +1290,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
|||
bd = &bio_record->details;
|
||||
|
||||
dm_bio_restore(bd, bio);
|
||||
bio_record->details.bi_bdev = NULL;
|
||||
bio->bi_error = 0;
|
||||
|
||||
queue_bio(ms, bio, rw);
|
||||
|
@ -1285,6 +1299,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
|||
DMERR("All replicated volumes dead, failing I/O");
|
||||
}
|
||||
|
||||
out:
|
||||
bio_record->details.bi_bdev = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue