^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2006-2008 Red Hat GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file is released under the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "dm-exception-store.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/dm-io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DM_MSG_PREFIX "transient snapshot"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*-----------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Implementation of the store for non-persistent snapshots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *---------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct transient_c {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) sector_t next_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void transient_dtr(struct dm_exception_store *store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) kfree(store->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int transient_read_metadata(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int (*callback)(void *callback_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) chunk_t old, chunk_t new),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void *callback_context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int transient_prepare_exception(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct dm_exception *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct transient_c *tc = store->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (size < (tc->next_free + store->chunk_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) e->new_chunk = sector_to_chunk(store, tc->next_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) tc->next_free += store->chunk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void transient_commit_exception(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct dm_exception *e, int valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void (*callback) (void *, int success),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void *callback_context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Just succeed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) callback(callback_context, valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void transient_usage(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) sector_t *total_sectors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) sector_t *sectors_allocated,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) sector_t *metadata_sectors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *sectors_allocated = ((struct transient_c *) store->context)->next_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *total_sectors = get_dev_size(dm_snap_cow(store->snap)->bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *metadata_sectors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int transient_ctr(struct dm_exception_store *store, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct transient_c *tc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!tc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) tc->next_free = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) store->context = tc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static unsigned transient_status(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) status_type_t status, char *result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned sz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) case STATUSTYPE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case STATUSTYPE_TABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) DMEMIT(" N %llu", (unsigned long long)store->chunk_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static struct dm_exception_store_type _transient_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .name = "transient",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .ctr = transient_ctr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .dtr = transient_dtr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .read_metadata = transient_read_metadata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .prepare_exception = transient_prepare_exception,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .commit_exception = transient_commit_exception,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .usage = transient_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .status = transient_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static struct dm_exception_store_type _transient_compat_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .name = "N",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .ctr = transient_ctr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .dtr = transient_dtr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .read_metadata = transient_read_metadata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .prepare_exception = transient_prepare_exception,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .commit_exception = transient_commit_exception,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .usage = transient_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .status = transient_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int dm_transient_snapshot_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) r = dm_exception_store_type_register(&_transient_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) DMWARN("Unable to register transient exception store type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) r = dm_exception_store_type_register(&_transient_compat_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) DMWARN("Unable to register old-style transient "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) "exception store type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dm_exception_store_type_unregister(&_transient_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) void dm_transient_snapshot_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dm_exception_store_type_unregister(&_transient_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dm_exception_store_type_unregister(&_transient_compat_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }