Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f1cbe07 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-5.1/dm-fixes' of...

Merge tag 'for-5.1/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:

 - Two queue_limits stacking fixes: disable discards if underlying
   driver does. And propagate BDI_CAP_STABLE_WRITES to fix sporadic
   checksum errors.

 - Fix that reverts a DM core limit that wasn't needed given that
   dm-crypt was already updated to impose an equivalent limit.

 - Fix dm-init to properly establish 'const' for __initconst array.

 - Fix deadlock in DM integrity target that occurs when overlapping IO
   is being issued to it. And two smaller fixes to the DM integrity
   target.

* tag 'for-5.1/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm integrity: fix deadlock with overlapping I/O
  dm: disable DISCARD if the underlying storage no longer supports it
  dm table: propagate BDI_CAP_STABLE_WRITES to fix sporadic checksum errors
  dm: revert 8f50e358 ("dm: limit the max bio size as BIO_MAX_PAGES * PAGE_SIZE")
  dm init: fix const confusion for dm_allowed_targets array
  dm integrity: make dm_integrity_init and dm_integrity_exit static
  dm integrity: change memcmp to strncmp in dm_integrity_ctr
parents 3e28fb0f 4ed319c6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ struct mapped_device {
	struct srcu_struct io_barrier;
};

void disable_discard(struct mapped_device *md);
void disable_write_same(struct mapped_device *md);
void disable_write_zeroes(struct mapped_device *md);

+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ struct dm_device {
	struct list_head list;
};

const char *dm_allowed_targets[] __initconst = {
const char * const dm_allowed_targets[] __initconst = {
	"crypt",
	"delay",
	"linear",
+7 −9
Original line number Diff line number Diff line
@@ -913,7 +913,7 @@ static void copy_from_journal(struct dm_integrity_c *ic, unsigned section, unsig
static bool ranges_overlap(struct dm_integrity_range *range1, struct dm_integrity_range *range2)
{
	return range1->logical_sector < range2->logical_sector + range2->n_sectors &&
	       range2->logical_sector + range2->n_sectors > range2->logical_sector;
	       range1->logical_sector + range1->n_sectors > range2->logical_sector;
}

static bool add_new_range(struct dm_integrity_c *ic, struct dm_integrity_range *new_range, bool check_waiting)
@@ -959,8 +959,6 @@ static void remove_range_unlocked(struct dm_integrity_c *ic, struct dm_integrity
		struct dm_integrity_range *last_range =
			list_first_entry(&ic->wait_list, struct dm_integrity_range, wait_entry);
		struct task_struct *last_range_task;
		if (!ranges_overlap(range, last_range))
			break;
		last_range_task = last_range->task;
		list_del(&last_range->wait_entry);
		if (!add_new_range(ic, last_range, false)) {
@@ -3185,7 +3183,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
			journal_watermark = val;
		else if (sscanf(opt_string, "commit_time:%u%c", &val, &dummy) == 1)
			sync_msec = val;
		else if (!memcmp(opt_string, "meta_device:", strlen("meta_device:"))) {
		else if (!strncmp(opt_string, "meta_device:", strlen("meta_device:"))) {
			if (ic->meta_dev) {
				dm_put_device(ti, ic->meta_dev);
				ic->meta_dev = NULL;
@@ -3204,17 +3202,17 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
				goto bad;
			}
			ic->sectors_per_block = val >> SECTOR_SHIFT;
		} else if (!memcmp(opt_string, "internal_hash:", strlen("internal_hash:"))) {
		} else if (!strncmp(opt_string, "internal_hash:", strlen("internal_hash:"))) {
			r = get_alg_and_key(opt_string, &ic->internal_hash_alg, &ti->error,
					    "Invalid internal_hash argument");
			if (r)
				goto bad;
		} else if (!memcmp(opt_string, "journal_crypt:", strlen("journal_crypt:"))) {
		} else if (!strncmp(opt_string, "journal_crypt:", strlen("journal_crypt:"))) {
			r = get_alg_and_key(opt_string, &ic->journal_crypt_alg, &ti->error,
					    "Invalid journal_crypt argument");
			if (r)
				goto bad;
		} else if (!memcmp(opt_string, "journal_mac:", strlen("journal_mac:"))) {
		} else if (!strncmp(opt_string, "journal_mac:", strlen("journal_mac:"))) {
			r = get_alg_and_key(opt_string, &ic->journal_mac_alg,  &ti->error,
					    "Invalid journal_mac argument");
			if (r)
@@ -3616,7 +3614,7 @@ static struct target_type integrity_target = {
	.io_hints		= dm_integrity_io_hints,
};

int __init dm_integrity_init(void)
static int __init dm_integrity_init(void)
{
	int r;

@@ -3635,7 +3633,7 @@ int __init dm_integrity_init(void)
	return r;
}

void dm_integrity_exit(void)
static void __exit dm_integrity_exit(void)
{
	dm_unregister_target(&integrity_target);
	kmem_cache_destroy(journal_io_cache);
+7 −4
Original line number Diff line number Diff line
@@ -222,10 +222,13 @@ static void dm_done(struct request *clone, blk_status_t error, bool mapped)
	}

	if (unlikely(error == BLK_STS_TARGET)) {
		if (req_op(clone) == REQ_OP_WRITE_SAME &&
		if (req_op(clone) == REQ_OP_DISCARD &&
		    !clone->q->limits.max_discard_sectors)
			disable_discard(tio->md);
		else if (req_op(clone) == REQ_OP_WRITE_SAME &&
			 !clone->q->limits.max_write_same_sectors)
			disable_write_same(tio->md);
		if (req_op(clone) == REQ_OP_WRITE_ZEROES &&
		else if (req_op(clone) == REQ_OP_WRITE_ZEROES &&
			 !clone->q->limits.max_write_zeroes_sectors)
			disable_write_zeroes(tio->md);
	}
+39 −0
Original line number Diff line number Diff line
@@ -1844,6 +1844,36 @@ static bool dm_table_supports_secure_erase(struct dm_table *t)
	return true;
}

static int device_requires_stable_pages(struct dm_target *ti,
					struct dm_dev *dev, sector_t start,
					sector_t len, void *data)
{
	struct request_queue *q = bdev_get_queue(dev->bdev);

	return q && bdi_cap_stable_pages_required(q->backing_dev_info);
}

/*
 * If any underlying device requires stable pages, a table must require
 * them as well.  Only targets that support iterate_devices are considered:
 * don't want error, zero, etc to require stable pages.
 */
static bool dm_table_requires_stable_pages(struct dm_table *t)
{
	struct dm_target *ti;
	unsigned i;

	for (i = 0; i < dm_table_get_num_targets(t); i++) {
		ti = dm_table_get_target(t, i);

		if (ti->type->iterate_devices &&
		    ti->type->iterate_devices(ti, device_requires_stable_pages, NULL))
			return true;
	}

	return false;
}

void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
			       struct queue_limits *limits)
{
@@ -1896,6 +1926,15 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,

	dm_table_verify_integrity(t);

	/*
	 * Some devices don't use blk_integrity but still want stable pages
	 * because they do their own checksumming.
	 */
	if (dm_table_requires_stable_pages(t))
		q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
	else
		q->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES;

	/*
	 * Determine whether or not this queue's I/O timings contribute
	 * to the entropy pool, Only request-based targets use this.
Loading