Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | |
Mikulas Patocka | 586e80e | 2008-10-21 17:44:59 +0100 | [diff] [blame] | 10 | #include <linux/device-mapper.h> |
Jonathan Brassow | aea53d9 | 2009-01-06 03:05:15 +0000 | [diff] [blame] | 11 | #include "dm-exception-store.h" |
Alasdair G Kergon | ca3a931 | 2006-10-03 01:15:30 -0700 | [diff] [blame] | 12 | #include "dm-bio-list.h" |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | #include <linux/blkdev.h> |
Alasdair G Kergon | ca3a931 | 2006-10-03 01:15:30 -0700 | [diff] [blame] | 14 | #include <linux/workqueue.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 15 | |
| 16 | struct exception_table { |
| 17 | uint32_t hash_mask; |
Milan Broz | d74f81f | 2008-02-08 02:11:27 +0000 | [diff] [blame] | 18 | unsigned hash_shift; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 19 | struct list_head *table; |
| 20 | }; |
| 21 | |
Mikulas Patocka | cd45daf | 2008-07-21 12:00:32 +0100 | [diff] [blame] | 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 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 26 | struct dm_snapshot { |
| 27 | struct rw_semaphore lock; |
Mikulas Patocka | 72727ba | 2008-04-24 21:43:11 +0100 | [diff] [blame] | 28 | struct dm_target *ti; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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; |
Alasdair G Kergon | aa14ede | 2006-02-01 03:04:50 -0800 | [diff] [blame] | 43 | |
| 44 | /* Origin writes don't trigger exceptions until this is set */ |
| 45 | int active; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | |
| 47 | /* Used for display of table */ |
| 48 | char type; |
| 49 | |
Mikulas Patocka | 92e8681 | 2008-07-21 12:00:35 +0100 | [diff] [blame] | 50 | mempool_t *pending_pool; |
| 51 | |
Mikulas Patocka | 879129d2 | 2008-10-30 13:33:16 +0000 | [diff] [blame] | 52 | atomic_t pending_exceptions_count; |
| 53 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 | struct exception_table pending; |
| 55 | struct exception_table complete; |
| 56 | |
Alasdair G Kergon | ca3a931 | 2006-10-03 01:15:30 -0700 | [diff] [blame] | 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 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 63 | /* The on disk metadata handler */ |
Jonathan Brassow | 1ae25f9 | 2009-01-06 03:05:16 +0000 | [diff] [blame] | 64 | struct dm_exception_store store; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | |
Heinz Mauelshagen | eb69aca | 2008-04-24 21:43:19 +0100 | [diff] [blame] | 66 | struct dm_kcopyd_client *kcopyd_client; |
Alasdair G Kergon | ca3a931 | 2006-10-03 01:15:30 -0700 | [diff] [blame] | 67 | |
| 68 | /* Queue of snapshot writes for ksnapd to flush */ |
| 69 | struct bio_list queued_bios; |
| 70 | struct work_struct queued_bios_work; |
Mikulas Patocka | cd45daf | 2008-07-21 12:00:32 +0100 | [diff] [blame] | 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]; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 76 | }; |
| 77 | |
| 78 | /* |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 79 | * Return the number of sectors in the device. |
| 80 | */ |
| 81 | static inline sector_t get_dev_size(struct block_device *bdev) |
| 82 | { |
| 83 | return bdev->bd_inode->i_size >> SECTOR_SHIFT; |
| 84 | } |
| 85 | |
| 86 | static 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 | |
| 91 | static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk) |
| 92 | { |
| 93 | return chunk << s->chunk_shift; |
| 94 | } |
| 95 | |
| 96 | static 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 |