dm-exception-store.h 5.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
 * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
 *
 * Device-mapper snapshot exception store.
 *
 * This file is released under the GPL.
 */

#ifndef _LINUX_DM_EXCEPTION_STORE
#define _LINUX_DM_EXCEPTION_STORE

#include <linux/blkdev.h>
14
#include <linux/device-mapper.h>
15 16 17 18 19 20 21 22 23 24 25 26 27 28

/*
 * The snapshot code deals with largish chunks of the disk at a
 * time. Typically 32k - 512k.
 */
typedef sector_t chunk_t;

/*
 * An exception is used where an old chunk of data has been
 * replaced by a new one.
 * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
 * of chunks that follow contiguously.  Remaining bits hold the number of the
 * chunk within the device.
 */
29
struct dm_exception {
30 31 32 33 34 35 36 37 38 39
	struct list_head hash_list;

	chunk_t old_chunk;
	chunk_t new_chunk;
};

/*
 * Abstraction to handle the meta/layout of exception stores (the
 * COW device).
 */
40 41
struct dm_exception_store;
struct dm_exception_store_type {
42 43 44
	const char *name;
	struct module *module;

45
	int (*ctr) (struct dm_exception_store *store, char *options);
46

47 48 49
	/*
	 * Destroys this object when you've finished with it.
	 */
50
	void (*dtr) (struct dm_exception_store *store);
51 52 53

	/*
	 * The target shouldn't read the COW device until this is
54 55
	 * called.  As exceptions are read from the COW, they are
	 * reported back via the callback.
56
	 */
57 58 59 60
	int (*read_metadata) (struct dm_exception_store *store,
			      int (*callback)(void *callback_context,
					      chunk_t old, chunk_t new),
			      void *callback_context);
61 62 63 64

	/*
	 * Find somewhere to store the next exception.
	 */
65
	int (*prepare_exception) (struct dm_exception_store *store,
66
				  struct dm_exception *e);
67 68 69 70

	/*
	 * Update the metadata with this exception.
	 */
71
	void (*commit_exception) (struct dm_exception_store *store,
72
				  struct dm_exception *e, int valid,
73 74 75
				  void (*callback) (void *, int success),
				  void *callback_context);

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
	/*
	 * Returns 0 if the exception store is empty.
	 *
	 * If there are exceptions still to be merged, sets
	 * *last_old_chunk and *last_new_chunk to the most recent
	 * still-to-be-merged chunk and returns the number of
	 * consecutive previous ones.
	 */
	int (*prepare_merge) (struct dm_exception_store *store,
			      chunk_t *last_old_chunk, chunk_t *last_new_chunk);

	/*
	 * Clear the last n exceptions.
	 * nr_merged must be <= the value returned by prepare_merge.
	 */
	int (*commit_merge) (struct dm_exception_store *store, int nr_merged);

93 94 95
	/*
	 * The snapshot is invalid, note this in the metadata.
	 */
96
	void (*drop_snapshot) (struct dm_exception_store *store);
97

98 99 100
	unsigned (*status) (struct dm_exception_store *store,
			    status_type_t status, char *result,
			    unsigned maxlen);
101

102 103 104
	/*
	 * Return how full the snapshot is.
	 */
105 106 107
	void (*usage) (struct dm_exception_store *store,
		       sector_t *total_sectors, sector_t *sectors_allocated,
		       sector_t *metadata_sectors);
108 109 110

	/* For internal device-mapper use only. */
	struct list_head list;
111 112
};

113 114
struct dm_snapshot;

115
struct dm_exception_store {
116
	struct dm_exception_store_type *type;
117
	struct dm_snapshot *snap;
118

119
	/* Size of data blocks saved - must be a power of 2 */
120 121 122
	unsigned chunk_size;
	unsigned chunk_mask;
	unsigned chunk_shift;
123

124
	void *context;
125 126

	bool userspace_supports_overflow;
127 128
};

129
/*
130
 * Obtain the origin or cow device used by a given snapshot.
131
 */
132
struct dm_dev *dm_snap_origin(struct dm_snapshot *snap);
133 134
struct dm_dev *dm_snap_cow(struct dm_snapshot *snap);

135 136 137
/*
 * Funtions to manipulate consecutive chunks
 */
138
#  if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64)
139 140 141 142 143 144 145 146
#    define DM_CHUNK_CONSECUTIVE_BITS 8
#    define DM_CHUNK_NUMBER_BITS 56

static inline chunk_t dm_chunk_number(chunk_t chunk)
{
	return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
}

147
static inline unsigned dm_consecutive_chunk_count(struct dm_exception *e)
148 149 150 151
{
	return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
}

152
static inline void dm_consecutive_chunk_count_inc(struct dm_exception *e)
153 154 155 156 157 158
{
	e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);

	BUG_ON(!dm_consecutive_chunk_count(e));
}

M
Mikulas Patocka 已提交
159 160 161 162 163 164 165
static inline void dm_consecutive_chunk_count_dec(struct dm_exception *e)
{
	BUG_ON(!dm_consecutive_chunk_count(e));

	e->new_chunk -= (1ULL << DM_CHUNK_NUMBER_BITS);
}

166 167 168 169 170 171 172 173
#  else
#    define DM_CHUNK_CONSECUTIVE_BITS 0

static inline chunk_t dm_chunk_number(chunk_t chunk)
{
	return chunk;
}

174
static inline unsigned dm_consecutive_chunk_count(struct dm_exception *e)
175 176 177 178
{
	return 0;
}

179
static inline void dm_consecutive_chunk_count_inc(struct dm_exception *e)
180 181 182
{
}

M
Mikulas Patocka 已提交
183 184 185 186
static inline void dm_consecutive_chunk_count_dec(struct dm_exception *e)
{
}

187 188
#  endif

189 190 191 192 193
/*
 * Return the number of sectors in the device.
 */
static inline sector_t get_dev_size(struct block_device *bdev)
{
M
Mikulas Patocka 已提交
194
	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
195 196 197 198 199
}

static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
				      sector_t sector)
{
200
	return sector >> store->chunk_shift;
201 202
}

203 204 205
int dm_exception_store_type_register(struct dm_exception_store_type *type);
int dm_exception_store_type_unregister(struct dm_exception_store_type *type);

206
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
207
				      unsigned chunk_size,
208 209
				      char **error);

210
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
211
			      struct dm_snapshot *snap,
212
			      unsigned *args_used,
213 214 215
			      struct dm_exception_store **store);
void dm_exception_store_destroy(struct dm_exception_store *store);

216 217 218
int dm_exception_store_init(void);
void dm_exception_store_exit(void);

219 220 221
/*
 * Two exception store implementations.
 */
222 223 224 225 226 227
int dm_persistent_snapshot_init(void);
void dm_persistent_snapshot_exit(void);

int dm_transient_snapshot_init(void);
void dm_transient_snapshot_exit(void);

228
#endif /* _LINUX_DM_EXCEPTION_STORE */