aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 467c586e2439..bb28f9782bdd 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -20,9 +20,9 @@
20#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
21#include <linux/log2.h> 21#include <linux/log2.h>
22#include <linux/dm-kcopyd.h> 22#include <linux/dm-kcopyd.h>
23#include <linux/workqueue.h>
23 24
24#include "dm-exception-store.h" 25#include "dm-exception-store.h"
25#include "dm-snap.h"
26#include "dm-bio-list.h" 26#include "dm-bio-list.h"
27 27
28#define DM_MSG_PREFIX "snapshots" 28#define DM_MSG_PREFIX "snapshots"
@@ -47,9 +47,79 @@
47 */ 47 */
48#define MIN_IOS 256 48#define MIN_IOS 256
49 49
50#define DM_TRACKED_CHUNK_HASH_SIZE 16
51#define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \
52 (DM_TRACKED_CHUNK_HASH_SIZE - 1))
53
54struct exception_table {
55 uint32_t hash_mask;
56 unsigned hash_shift;
57 struct list_head *table;
58};
59
60struct dm_snapshot {
61 struct rw_semaphore lock;
62
63 struct dm_dev *origin;
64
65 /* List of snapshots per Origin */
66 struct list_head list;
67
68 /* You can't use a snapshot if this is 0 (e.g. if full) */
69 int valid;
70
71 /* Origin writes don't trigger exceptions until this is set */
72 int active;
73
74 /* Used for display of table */
75 char type;
76
77 mempool_t *pending_pool;
78
79 atomic_t pending_exceptions_count;
80
81 struct exception_table pending;
82 struct exception_table complete;
83
84 /*
85 * pe_lock protects all pending_exception operations and access
86 * as well as the snapshot_bios list.
87 */
88 spinlock_t pe_lock;
89
90 /* The on disk metadata handler */
91 struct dm_exception_store *store;
92
93 struct dm_kcopyd_client *kcopyd_client;
94
95 /* Queue of snapshot writes for ksnapd to flush */
96 struct bio_list queued_bios;
97 struct work_struct queued_bios_work;
98
99 /* Chunks with outstanding reads */
100 mempool_t *tracked_chunk_pool;
101 spinlock_t tracked_chunk_lock;
102 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
103};
104
50static struct workqueue_struct *ksnapd; 105static struct workqueue_struct *ksnapd;
51static void flush_queued_bios(struct work_struct *work); 106static void flush_queued_bios(struct work_struct *work);
52 107
108static sector_t chunk_to_sector(struct dm_exception_store *store,
109 chunk_t chunk)
110{
111 return chunk << store->chunk_shift;
112}
113
114static int bdev_equal(struct block_device *lhs, struct block_device *rhs)
115{
116 /*
117 * There is only ever one instance of a particular block
118 * device so we can compare pointers safely.
119 */
120 return lhs == rhs;
121}
122
53struct dm_snap_pending_exception { 123struct dm_snap_pending_exception {
54 struct dm_snap_exception e; 124 struct dm_snap_exception e;
55 125