xref: /OK3568_Linux_fs/kernel/drivers/md/dm-snap-transient.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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