Blame view

drivers/md/dm-snap.h 4.74 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   * dm-snapshot.c
   *
   * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
   *
   * This file is released under the GPL.
   */
  
  #ifndef DM_SNAPSHOT_H
  #define DM_SNAPSHOT_H
  
  #include "dm.h"
ca3a931fd   Alasdair G Kergon   [PATCH] dm snapsh...
13
  #include "dm-bio-list.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/blkdev.h>
ca3a931fd   Alasdair G Kergon   [PATCH] dm snapsh...
15
  #include <linux/workqueue.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
  
  struct exception_table {
  	uint32_t hash_mask;
d74f81f8a   Milan Broz   dm snapshot: comb...
19
  	unsigned hash_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
  	struct list_head *table;
  };
  
  /*
   * The snapshot code deals with largish chunks of the disk at a
d74f81f8a   Milan Broz   dm snapshot: comb...
25
   * time. Typically 32k - 512k.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
  typedef sector_t chunk_t;
  
  /*
   * An exception is used where an old chunk of data has been
   * replaced by a new one.
d74f81f8a   Milan Broz   dm snapshot: comb...
32
33
34
   * 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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
   */
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
36
  struct dm_snap_exception {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
  	struct list_head hash_list;
  
  	chunk_t old_chunk;
  	chunk_t new_chunk;
  };
  
  /*
d74f81f8a   Milan Broz   dm snapshot: comb...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
   * Funtions to manipulate consecutive chunks
   */
  #  if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
  #    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);
  }
  
  static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
  {
  	return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
  }
  
  static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
  {
  	e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
  
  	BUG_ON(!dm_consecutive_chunk_count(e));
  }
  
  #  else
  #    define DM_CHUNK_CONSECUTIVE_BITS 0
  
  static inline chunk_t dm_chunk_number(chunk_t chunk)
  {
  	return chunk;
  }
  
  static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
  {
  	return 0;
  }
  
  static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
  {
  }
  
  #  endif
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
   * Abstraction to handle the meta/layout of exception stores (the
   * COW device).
   */
  struct exception_store {
  
  	/*
  	 * Destroys this object when you've finished with it.
  	 */
  	void (*destroy) (struct exception_store *store);
  
  	/*
  	 * The target shouldn't read the COW device until this is
  	 * called.
  	 */
  	int (*read_metadata) (struct exception_store *store);
  
  	/*
  	 * Find somewhere to store the next exception.
  	 */
  	int (*prepare_exception) (struct exception_store *store,
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
107
  				  struct dm_snap_exception *e);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
  
  	/*
  	 * Update the metadata with this exception.
  	 */
  	void (*commit_exception) (struct exception_store *store,
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
113
  				  struct dm_snap_exception *e,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  				  void (*callback) (void *, int success),
  				  void *callback_context);
  
  	/*
  	 * The snapshot is invalid, note this in the metadata.
  	 */
  	void (*drop_snapshot) (struct exception_store *store);
  
  	/*
  	 * Return how full the snapshot is.
  	 */
  	void (*fraction_full) (struct exception_store *store,
  			       sector_t *numerator,
  			       sector_t *denominator);
  
  	struct dm_snapshot *snap;
  	void *context;
  };
  
  struct dm_snapshot {
  	struct rw_semaphore lock;
72727bad5   Mikulas Patocka   dm snapshot: stor...
135
  	struct dm_target *ti;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  
  	struct dm_dev *origin;
  	struct dm_dev *cow;
  
  	/* List of snapshots per Origin */
  	struct list_head list;
  
  	/* Size of data blocks saved - must be a power of 2 */
  	chunk_t chunk_size;
  	chunk_t chunk_mask;
  	chunk_t chunk_shift;
  
  	/* You can't use a snapshot if this is 0 (e.g. if full) */
  	int valid;
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
150
151
152
  
  	/* Origin writes don't trigger exceptions until this is set */
  	int active;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
161
  
  	/* Used for display of table */
  	char type;
  
  	/* The last percentage we notified */
  	int last_percent;
  
  	struct exception_table pending;
  	struct exception_table complete;
ca3a931fd   Alasdair G Kergon   [PATCH] dm snapsh...
162
163
164
165
166
  	/*
  	 * pe_lock protects all pending_exception operations and access
  	 * as well as the snapshot_bios list.
  	 */
  	spinlock_t pe_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  	/* The on disk metadata handler */
  	struct exception_store store;
eb69aca5d   Heinz Mauelshagen   dm kcopyd: clean ...
169
  	struct dm_kcopyd_client *kcopyd_client;
ca3a931fd   Alasdair G Kergon   [PATCH] dm snapsh...
170
171
172
173
  
  	/* Queue of snapshot writes for ksnapd to flush */
  	struct bio_list queued_bios;
  	struct work_struct queued_bios_work;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
180
181
182
183
184
185
  };
  
  /*
   * Used by the exception stores to load exceptions hen
   * initialising.
   */
  int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new);
  
  /*
   * Constructor and destructor for the default persistent
   * store.
   */
4c7e3bf44   Mark McLoughlin   [PATCH] dm snapsh...
186
  int dm_create_persistent(struct exception_store *store);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187

4c7e3bf44   Mark McLoughlin   [PATCH] dm snapsh...
188
  int dm_create_transient(struct exception_store *store);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  
  /*
   * Return the number of sectors in the device.
   */
  static inline sector_t get_dev_size(struct block_device *bdev)
  {
  	return bdev->bd_inode->i_size >> SECTOR_SHIFT;
  }
  
  static inline chunk_t sector_to_chunk(struct dm_snapshot *s, sector_t sector)
  {
  	return (sector & ~s->chunk_mask) >> s->chunk_shift;
  }
  
  static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk)
  {
  	return chunk << s->chunk_shift;
  }
  
  static inline int bdev_equal(struct block_device *lhs, struct block_device *rhs)
  {
  	/*
  	 * There is only ever one instance of a particular block
  	 * device so we can compare pointers safely.
  	 */
  	return lhs == rhs;
  }
  
  #endif