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

Commit b0d3cc01 authored by Mike Snitzer's avatar Mike Snitzer
Browse files

dm snapshot: add new persistent store option to support overflow



Commit 76c44f6d introduced the possibly for "Overflow" to be reported
by the snapshot device's status.  Older userspace (e.g. lvm2) does not
handle the "Overflow" status response.

Fix this incompatibility by requiring newer userspace code, that can
cope with "Overflow", request the persistent store with overflow support
by using "PO" (Persistent with Overflow) for the snapshot store type.

Reported-by: default avatarZdenek Kabelac <zkabelac@redhat.com>
Fixes: 76c44f6d ("dm snapshot: don't invalidate on-disk image on snapshot write overflow")
Reviewed-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 2bffa150
Loading
Loading
Loading
Loading
+7 −3
Original line number Original line Diff line number Diff line
@@ -41,9 +41,13 @@ useless and be disabled, returning errors. So it is important to monitor
the amount of free space and expand the <COW device> before it fills up.
the amount of free space and expand the <COW device> before it fills up.


<persistent?> is P (Persistent) or N (Not persistent - will not survive
<persistent?> is P (Persistent) or N (Not persistent - will not survive
after reboot).
after reboot).  O (Overflow) can be added as a persistent store option
The difference is that for transient snapshots less metadata must be
to allow userspace to advertise its support for seeing "Overflow" in the
saved on disk - they can be kept in memory by the kernel.
snapshot status.  So supported store types are "P", "PO" and "N".

The difference between persistent and transient is with transient
snapshots less metadata must be saved on disk - they can be kept in
memory by the kernel.




* snapshot-merge <origin> <COW device> <persistent> <chunksize>
* snapshot-merge <origin> <COW device> <persistent> <chunksize>
+3 −3
Original line number Original line Diff line number Diff line
@@ -203,7 +203,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
		return -EINVAL;
		return -EINVAL;
	}
	}


	tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
	tmp_store = kzalloc(sizeof(*tmp_store), GFP_KERNEL);
	if (!tmp_store) {
	if (!tmp_store) {
		ti->error = "Exception store allocation failed";
		ti->error = "Exception store allocation failed";
		return -ENOMEM;
		return -ENOMEM;
@@ -215,7 +215,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
	else if (persistent == 'N')
	else if (persistent == 'N')
		type = get_type("N");
		type = get_type("N");
	else {
	else {
		ti->error = "Persistent flag is not P or N";
		ti->error = "Exception store type is not P or N";
		r = -EINVAL;
		r = -EINVAL;
		goto bad_type;
		goto bad_type;
	}
	}
@@ -233,7 +233,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
	if (r)
	if (r)
		goto bad;
		goto bad;


	r = type->ctr(tmp_store, 0, NULL);
	r = type->ctr(tmp_store, (strlen(argv[0]) > 1 ? &argv[0][1] : NULL));
	if (r) {
	if (r) {
		ti->error = "Exception store type constructor failed";
		ti->error = "Exception store type constructor failed";
		goto bad;
		goto bad;
+3 −2
Original line number Original line Diff line number Diff line
@@ -42,8 +42,7 @@ struct dm_exception_store_type {
	const char *name;
	const char *name;
	struct module *module;
	struct module *module;


	int (*ctr) (struct dm_exception_store *store,
	int (*ctr) (struct dm_exception_store *store, char *options);
		    unsigned argc, char **argv);


	/*
	/*
	 * Destroys this object when you've finished with it.
	 * Destroys this object when you've finished with it.
@@ -123,6 +122,8 @@ struct dm_exception_store {
	unsigned chunk_shift;
	unsigned chunk_shift;


	void *context;
	void *context;

	bool userspace_supports_overflow;
};
};


/*
/*
+14 −3
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@


#include "dm-exception-store.h"
#include "dm-exception-store.h"


#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
@@ -843,8 +844,7 @@ static void persistent_drop_snapshot(struct dm_exception_store *store)
		DMWARN("write header failed");
		DMWARN("write header failed");
}
}


static int persistent_ctr(struct dm_exception_store *store,
static int persistent_ctr(struct dm_exception_store *store, char *options)
			  unsigned argc, char **argv)
{
{
	struct pstore *ps;
	struct pstore *ps;


@@ -873,6 +873,16 @@ static int persistent_ctr(struct dm_exception_store *store,
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	if (options) {
		char overflow = toupper(options[0]);
		if (overflow == 'O')
			store->userspace_supports_overflow = true;
		else {
			DMERR("Unsupported persistent store option: %s", options);
			return -EINVAL;
		}
	}

	store->context = ps;
	store->context = ps;


	return 0;
	return 0;
@@ -888,7 +898,8 @@ static unsigned persistent_status(struct dm_exception_store *store,
	case STATUSTYPE_INFO:
	case STATUSTYPE_INFO:
		break;
		break;
	case STATUSTYPE_TABLE:
	case STATUSTYPE_TABLE:
		DMEMIT(" P %llu", (unsigned long long)store->chunk_size);
		DMEMIT(" %s %llu", store->userspace_supports_overflow ? "PO" : "P",
		       (unsigned long long)store->chunk_size);
	}
	}


	return sz;
	return sz;
+1 −2
Original line number Original line Diff line number Diff line
@@ -70,8 +70,7 @@ static void transient_usage(struct dm_exception_store *store,
	*metadata_sectors = 0;
	*metadata_sectors = 0;
}
}


static int transient_ctr(struct dm_exception_store *store,
static int transient_ctr(struct dm_exception_store *store, char *options)
			 unsigned argc, char **argv)
{
{
	struct transient_c *tc;
	struct transient_c *tc;


Loading