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

Commit 0273eb90 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dm snapshot: disallow the COW and origin devices from being identical"

parents 2a3d894d 6f82fb72
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1099,6 +1099,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
	int i;
	int r = -EINVAL;
	char *origin_path, *cow_path;
	dev_t origin_dev, cow_dev;
	unsigned args_used, num_flush_bios = 1;
	fmode_t origin_mode = FMODE_READ;

@@ -1129,11 +1130,19 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
		ti->error = "Cannot get origin device";
		goto bad_origin;
	}
	origin_dev = s->origin->bdev->bd_dev;

	cow_path = argv[0];
	argv++;
	argc--;

	cow_dev = dm_get_dev_t(cow_path);
	if (cow_dev && cow_dev == origin_dev) {
		ti->error = "COW device cannot be the same as origin device";
		r = -EINVAL;
		goto bad_cow;
	}

	r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
	if (r) {
		ti->error = "Cannot get COW device";
+24 −17
Original line number Diff line number Diff line
@@ -363,6 +363,26 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
	return 0;
}

/*
 * Convert the path to a device
 */
dev_t dm_get_dev_t(const char *path)
{
	dev_t uninitialized_var(dev);
	struct block_device *bdev;

	bdev = lookup_bdev(path);
	if (IS_ERR(bdev))
		dev = name_to_dev_t(path);
	else {
		dev = bdev->bd_dev;
		bdput(bdev);
	}

	return dev;
}
EXPORT_SYMBOL_GPL(dm_get_dev_t);

/*
 * Add a device to the list, or just increment the usage count if
 * it's already present.
@@ -371,28 +391,15 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
		  struct dm_dev **result)
{
	int r;
	dev_t uninitialized_var(dev);
	dev_t dev;
	struct dm_dev_internal *dd;
	unsigned int major, minor;
	struct dm_table *t = ti->table;
	char dummy;

	BUG_ON(!t);

	if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
		/* Extract the major/minor numbers */
		dev = MKDEV(major, minor);
		if (MAJOR(dev) != major || MINOR(dev) != minor)
			return -EOVERFLOW;
	} else {
		/* convert the path to a device */
		struct block_device *bdev = lookup_bdev(path);

		if (IS_ERR(bdev))
			return PTR_ERR(bdev);
		dev = bdev->bd_dev;
		bdput(bdev);
	}
	dev = dm_get_dev_t(path);
	if (!dev)
		return -ENODEV;

	dd = find_device(&t->devices, dev);
	if (!dd) {
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@ struct dm_dev {
	char name[16];
};

dev_t dm_get_dev_t(const char *path);

/*
 * Constructors should call these functions to ensure destination devices
 * are opened/closed correctly.