2 * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
3 * Copyright (C) 2006-2008 Red Hat GmbH
5 * This file is released under the GPL.
8 #include "dm-exception-store.h"
11 #include <linux/pagemap.h>
12 #include <linux/vmalloc.h>
13 #include <linux/export.h>
14 #include <linux/slab.h>
15 #include <linux/dm-io.h>
17 #define DM_MSG_PREFIX "transient snapshot"
19 /*-----------------------------------------------------------------
20 * Implementation of the store for non-persistent snapshots.
21 *---------------------------------------------------------------*/
26 static void transient_dtr(struct dm_exception_store
*store
)
28 kfree(store
->context
);
31 static int transient_read_metadata(struct dm_exception_store
*store
,
32 int (*callback
)(void *callback_context
,
33 chunk_t old
, chunk_t
new),
34 void *callback_context
)
39 static int transient_prepare_exception(struct dm_exception_store
*store
,
40 struct dm_exception
*e
)
42 struct transient_c
*tc
= store
->context
;
43 sector_t size
= get_dev_size(dm_snap_cow(store
->snap
)->bdev
);
45 if (size
< (tc
->next_free
+ store
->chunk_size
))
48 e
->new_chunk
= sector_to_chunk(store
, tc
->next_free
);
49 tc
->next_free
+= store
->chunk_size
;
54 static void transient_commit_exception(struct dm_exception_store
*store
,
55 struct dm_exception
*e
, int valid
,
56 void (*callback
) (void *, int success
),
57 void *callback_context
)
60 callback(callback_context
, valid
);
63 static void transient_usage(struct dm_exception_store
*store
,
64 sector_t
*total_sectors
,
65 sector_t
*sectors_allocated
,
66 sector_t
*metadata_sectors
)
68 *sectors_allocated
= ((struct transient_c
*) store
->context
)->next_free
;
69 *total_sectors
= get_dev_size(dm_snap_cow(store
->snap
)->bdev
);
70 *metadata_sectors
= 0;
73 static int transient_ctr(struct dm_exception_store
*store
,
74 unsigned argc
, char **argv
)
76 struct transient_c
*tc
;
78 tc
= kmalloc(sizeof(struct transient_c
), GFP_KERNEL
);
88 static unsigned transient_status(struct dm_exception_store
*store
,
89 status_type_t status
, char *result
,
97 case STATUSTYPE_TABLE
:
98 DMEMIT(" N %llu", (unsigned long long)store
->chunk_size
);
104 static struct dm_exception_store_type _transient_type
= {
106 .module
= THIS_MODULE
,
107 .ctr
= transient_ctr
,
108 .dtr
= transient_dtr
,
109 .read_metadata
= transient_read_metadata
,
110 .prepare_exception
= transient_prepare_exception
,
111 .commit_exception
= transient_commit_exception
,
112 .usage
= transient_usage
,
113 .status
= transient_status
,
116 static struct dm_exception_store_type _transient_compat_type
= {
118 .module
= THIS_MODULE
,
119 .ctr
= transient_ctr
,
120 .dtr
= transient_dtr
,
121 .read_metadata
= transient_read_metadata
,
122 .prepare_exception
= transient_prepare_exception
,
123 .commit_exception
= transient_commit_exception
,
124 .usage
= transient_usage
,
125 .status
= transient_status
,
128 int dm_transient_snapshot_init(void)
132 r
= dm_exception_store_type_register(&_transient_type
);
134 DMWARN("Unable to register transient exception store type");
138 r
= dm_exception_store_type_register(&_transient_compat_type
);
140 DMWARN("Unable to register old-style transient "
141 "exception store type");
142 dm_exception_store_type_unregister(&_transient_type
);
149 void dm_transient_snapshot_exit(void)
151 dm_exception_store_type_unregister(&_transient_type
);
152 dm_exception_store_type_unregister(&_transient_compat_type
);