1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
4 * Copyright (C) 2006-2008 Red Hat GmbH
6 * This file is released under the GPL.
9 #include "dm-exception-store.h"
12 #include <linux/pagemap.h>
13 #include <linux/vmalloc.h>
14 #include <linux/export.h>
15 #include <linux/slab.h>
16 #include <linux/dm-io.h>
18 #define DM_MSG_PREFIX "transient snapshot"
21 *---------------------------------------------------------------
22 * Implementation of the store for non-persistent snapshots.
23 *---------------------------------------------------------------
29 static void transient_dtr(struct dm_exception_store
*store
)
31 kfree(store
->context
);
34 static int transient_read_metadata(struct dm_exception_store
*store
,
35 int (*callback
)(void *callback_context
,
36 chunk_t old
, chunk_t
new),
37 void *callback_context
)
42 static int transient_prepare_exception(struct dm_exception_store
*store
,
43 struct dm_exception
*e
)
45 struct transient_c
*tc
= store
->context
;
46 sector_t size
= get_dev_size(dm_snap_cow(store
->snap
)->bdev
);
48 if (size
< (tc
->next_free
+ store
->chunk_size
))
51 e
->new_chunk
= sector_to_chunk(store
, tc
->next_free
);
52 tc
->next_free
+= store
->chunk_size
;
57 static void transient_commit_exception(struct dm_exception_store
*store
,
58 struct dm_exception
*e
, int valid
,
59 void (*callback
)(void *, int success
),
60 void *callback_context
)
63 callback(callback_context
, valid
);
66 static void transient_usage(struct dm_exception_store
*store
,
67 sector_t
*total_sectors
,
68 sector_t
*sectors_allocated
,
69 sector_t
*metadata_sectors
)
71 *sectors_allocated
= ((struct transient_c
*) store
->context
)->next_free
;
72 *total_sectors
= get_dev_size(dm_snap_cow(store
->snap
)->bdev
);
73 *metadata_sectors
= 0;
76 static int transient_ctr(struct dm_exception_store
*store
, char *options
)
78 struct transient_c
*tc
;
80 tc
= kmalloc(sizeof(struct transient_c
), GFP_KERNEL
);
90 static unsigned int transient_status(struct dm_exception_store
*store
,
91 status_type_t status
, char *result
,
99 case STATUSTYPE_TABLE
:
100 DMEMIT(" N %llu", (unsigned long long)store
->chunk_size
);
110 static struct dm_exception_store_type _transient_type
= {
112 .module
= THIS_MODULE
,
113 .ctr
= transient_ctr
,
114 .dtr
= transient_dtr
,
115 .read_metadata
= transient_read_metadata
,
116 .prepare_exception
= transient_prepare_exception
,
117 .commit_exception
= transient_commit_exception
,
118 .usage
= transient_usage
,
119 .status
= transient_status
,
122 static struct dm_exception_store_type _transient_compat_type
= {
124 .module
= THIS_MODULE
,
125 .ctr
= transient_ctr
,
126 .dtr
= transient_dtr
,
127 .read_metadata
= transient_read_metadata
,
128 .prepare_exception
= transient_prepare_exception
,
129 .commit_exception
= transient_commit_exception
,
130 .usage
= transient_usage
,
131 .status
= transient_status
,
134 int dm_transient_snapshot_init(void)
138 r
= dm_exception_store_type_register(&_transient_type
);
140 DMWARN("Unable to register transient exception store type");
144 r
= dm_exception_store_type_register(&_transient_compat_type
);
146 DMWARN("Unable to register old-style transient exception store type");
147 dm_exception_store_type_unregister(&_transient_type
);
154 void dm_transient_snapshot_exit(void)
156 dm_exception_store_type_unregister(&_transient_type
);
157 dm_exception_store_type_unregister(&_transient_compat_type
);