c8a486e0ea2cb49f05075c4f7cd0eb75ef15b778
[linux-2.6-block.git] / drivers / md / dm-snap.h
1 /*
2  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
3  *
4  * This file is released under the GPL.
5  */
6
7 #ifndef DM_SNAPSHOT_H
8 #define DM_SNAPSHOT_H
9
10 #include <linux/device-mapper.h>
11 #include "dm-exception-store.h"
12 #include "dm-bio-list.h"
13 #include <linux/blkdev.h>
14 #include <linux/workqueue.h>
15
16 struct exception_table {
17         uint32_t hash_mask;
18         unsigned hash_shift;
19         struct list_head *table;
20 };
21
22 #define DM_TRACKED_CHUNK_HASH_SIZE      16
23 #define DM_TRACKED_CHUNK_HASH(x)        ((unsigned long)(x) & \
24                                          (DM_TRACKED_CHUNK_HASH_SIZE - 1))
25
26 struct dm_snapshot {
27         struct rw_semaphore lock;
28
29         struct dm_dev *origin;
30
31         /* List of snapshots per Origin */
32         struct list_head list;
33
34         /* You can't use a snapshot if this is 0 (e.g. if full) */
35         int valid;
36
37         /* Origin writes don't trigger exceptions until this is set */
38         int active;
39
40         /* Used for display of table */
41         char type;
42
43         mempool_t *pending_pool;
44
45         atomic_t pending_exceptions_count;
46
47         struct exception_table pending;
48         struct exception_table complete;
49
50         /*
51          * pe_lock protects all pending_exception operations and access
52          * as well as the snapshot_bios list.
53          */
54         spinlock_t pe_lock;
55
56         /* The on disk metadata handler */
57         struct dm_exception_store *store;
58
59         struct dm_kcopyd_client *kcopyd_client;
60
61         /* Queue of snapshot writes for ksnapd to flush */
62         struct bio_list queued_bios;
63         struct work_struct queued_bios_work;
64
65         /* Chunks with outstanding reads */
66         mempool_t *tracked_chunk_pool;
67         spinlock_t tracked_chunk_lock;
68         struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
69 };
70
71 /*
72  * Return the number of sectors in the device.
73  */
74 static inline sector_t get_dev_size(struct block_device *bdev)
75 {
76         return bdev->bd_inode->i_size >> SECTOR_SHIFT;
77 }
78
79 static inline chunk_t sector_to_chunk(struct dm_snapshot *s, sector_t sector)
80 {
81         return (sector & ~s->store->chunk_mask) >> s->store->chunk_shift;
82 }
83
84 static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk)
85 {
86         return chunk << s->store->chunk_shift;
87 }
88
89 static inline int bdev_equal(struct block_device *lhs, struct block_device *rhs)
90 {
91         /*
92          * There is only ever one instance of a particular block
93          * device so we can compare pointers safely.
94          */
95         return lhs == rhs;
96 }
97
98 #endif