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