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 struct dm_target *ti; 29 30 struct dm_dev *origin; 31 struct dm_dev *cow; 32 33 /* List of snapshots per Origin */ 34 struct list_head list; 35 36 /* Size of data blocks saved - must be a power of 2 */ 37 chunk_t chunk_size; 38 chunk_t chunk_mask; 39 chunk_t chunk_shift; 40 41 /* You can't use a snapshot if this is 0 (e.g. if full) */ 42 int valid; 43 44 /* Origin writes don't trigger exceptions until this is set */ 45 int active; 46 47 /* Used for display of table */ 48 char type; 49 50 mempool_t *pending_pool; 51 52 atomic_t pending_exceptions_count; 53 54 struct exception_table pending; 55 struct exception_table complete; 56 57 /* 58 * pe_lock protects all pending_exception operations and access 59 * as well as the snapshot_bios list. 60 */ 61 spinlock_t pe_lock; 62 63 /* The on disk metadata handler */ 64 struct dm_exception_store store; 65 66 struct dm_kcopyd_client *kcopyd_client; 67 68 /* Queue of snapshot writes for ksnapd to flush */ 69 struct bio_list queued_bios; 70 struct work_struct queued_bios_work; 71 72 /* Chunks with outstanding reads */ 73 mempool_t *tracked_chunk_pool; 74 spinlock_t tracked_chunk_lock; 75 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; 76 }; 77 78 /* 79 * Return the number of sectors in the device. 80 */ get_dev_size(struct block_device * bdev)81static inline sector_t get_dev_size(struct block_device *bdev) 82 { 83 return bdev->bd_inode->i_size >> SECTOR_SHIFT; 84 } 85 sector_to_chunk(struct dm_snapshot * s,sector_t sector)86static inline chunk_t sector_to_chunk(struct dm_snapshot *s, sector_t sector) 87 { 88 return (sector & ~s->chunk_mask) >> s->chunk_shift; 89 } 90 chunk_to_sector(struct dm_snapshot * s,chunk_t chunk)91static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk) 92 { 93 return chunk << s->chunk_shift; 94 } 95 bdev_equal(struct block_device * lhs,struct block_device * rhs)96static inline int bdev_equal(struct block_device *lhs, struct block_device *rhs) 97 { 98 /* 99 * There is only ever one instance of a particular block 100 * device so we can compare pointers safely. 101 */ 102 return lhs == rhs; 103 } 104 105 #endif 106