0001
0002
0003
0004
0005
0006
0007
0008 #include "dm-exception-store.h"
0009
0010 #include <linux/mm.h>
0011 #include <linux/pagemap.h>
0012 #include <linux/vmalloc.h>
0013 #include <linux/export.h>
0014 #include <linux/slab.h>
0015 #include <linux/dm-io.h>
0016
0017 #define DM_MSG_PREFIX "transient snapshot"
0018
0019
0020
0021
0022 struct transient_c {
0023 sector_t next_free;
0024 };
0025
0026 static void transient_dtr(struct dm_exception_store *store)
0027 {
0028 kfree(store->context);
0029 }
0030
0031 static int transient_read_metadata(struct dm_exception_store *store,
0032 int (*callback)(void *callback_context,
0033 chunk_t old, chunk_t new),
0034 void *callback_context)
0035 {
0036 return 0;
0037 }
0038
0039 static int transient_prepare_exception(struct dm_exception_store *store,
0040 struct dm_exception *e)
0041 {
0042 struct transient_c *tc = store->context;
0043 sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
0044
0045 if (size < (tc->next_free + store->chunk_size))
0046 return -1;
0047
0048 e->new_chunk = sector_to_chunk(store, tc->next_free);
0049 tc->next_free += store->chunk_size;
0050
0051 return 0;
0052 }
0053
0054 static void transient_commit_exception(struct dm_exception_store *store,
0055 struct dm_exception *e, int valid,
0056 void (*callback) (void *, int success),
0057 void *callback_context)
0058 {
0059
0060 callback(callback_context, valid);
0061 }
0062
0063 static void transient_usage(struct dm_exception_store *store,
0064 sector_t *total_sectors,
0065 sector_t *sectors_allocated,
0066 sector_t *metadata_sectors)
0067 {
0068 *sectors_allocated = ((struct transient_c *) store->context)->next_free;
0069 *total_sectors = get_dev_size(dm_snap_cow(store->snap)->bdev);
0070 *metadata_sectors = 0;
0071 }
0072
0073 static int transient_ctr(struct dm_exception_store *store, char *options)
0074 {
0075 struct transient_c *tc;
0076
0077 tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
0078 if (!tc)
0079 return -ENOMEM;
0080
0081 tc->next_free = 0;
0082 store->context = tc;
0083
0084 return 0;
0085 }
0086
0087 static unsigned transient_status(struct dm_exception_store *store,
0088 status_type_t status, char *result,
0089 unsigned maxlen)
0090 {
0091 unsigned sz = 0;
0092
0093 switch (status) {
0094 case STATUSTYPE_INFO:
0095 break;
0096 case STATUSTYPE_TABLE:
0097 DMEMIT(" N %llu", (unsigned long long)store->chunk_size);
0098 break;
0099 case STATUSTYPE_IMA:
0100 *result = '\0';
0101 break;
0102 }
0103
0104 return sz;
0105 }
0106
0107 static struct dm_exception_store_type _transient_type = {
0108 .name = "transient",
0109 .module = THIS_MODULE,
0110 .ctr = transient_ctr,
0111 .dtr = transient_dtr,
0112 .read_metadata = transient_read_metadata,
0113 .prepare_exception = transient_prepare_exception,
0114 .commit_exception = transient_commit_exception,
0115 .usage = transient_usage,
0116 .status = transient_status,
0117 };
0118
0119 static struct dm_exception_store_type _transient_compat_type = {
0120 .name = "N",
0121 .module = THIS_MODULE,
0122 .ctr = transient_ctr,
0123 .dtr = transient_dtr,
0124 .read_metadata = transient_read_metadata,
0125 .prepare_exception = transient_prepare_exception,
0126 .commit_exception = transient_commit_exception,
0127 .usage = transient_usage,
0128 .status = transient_status,
0129 };
0130
0131 int dm_transient_snapshot_init(void)
0132 {
0133 int r;
0134
0135 r = dm_exception_store_type_register(&_transient_type);
0136 if (r) {
0137 DMWARN("Unable to register transient exception store type");
0138 return r;
0139 }
0140
0141 r = dm_exception_store_type_register(&_transient_compat_type);
0142 if (r) {
0143 DMWARN("Unable to register old-style transient "
0144 "exception store type");
0145 dm_exception_store_type_unregister(&_transient_type);
0146 return r;
0147 }
0148
0149 return r;
0150 }
0151
0152 void dm_transient_snapshot_exit(void)
0153 {
0154 dm_exception_store_type_unregister(&_transient_type);
0155 dm_exception_store_type_unregister(&_transient_compat_type);
0156 }