Skip to content

Commit

Permalink
Merge tag 'for-4.12/dm-fixes-4' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Linus Torvalds committed Jun 24, 2017
2 parents 337c6ba + feb7695 commit 7ec2f7e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
12 changes: 10 additions & 2 deletions drivers/md/dm-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/md/dm-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
21 changes: 19 additions & 2 deletions drivers/md/dm-raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.",
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down

0 comments on commit 7ec2f7e

Please sign in to comment.