diff options
| author | Mike Snitzer <snitzer@redhat.com> | 2009-12-10 18:52:35 -0500 |
|---|---|---|
| committer | Alasdair G Kergon <agk@redhat.com> | 2009-12-10 18:52:35 -0500 |
| commit | d8ddb1cfff0070479c1f4a07c1d4a48ef8cb188e (patch) | |
| tree | 340967ea04ef1d790dfce3c324c3bfc1ce30cace | |
| parent | 8a2d528620e228ddfd0df9cec0a16e034ff8db1d (diff) | |
dm snapshot: report merge failure in status
Set 'merge_failed' flag if a snapshot fails to merge. Update
snapshot_status() to report "Merge failed" if 'merge_failed' is set.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
| -rw-r--r-- | drivers/md/dm-snap.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index bb4b733697b3..4c80e82f941c 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -71,7 +71,10 @@ struct dm_snapshot { | |||
| 71 | /* List of snapshots per Origin */ | 71 | /* List of snapshots per Origin */ |
| 72 | struct list_head list; | 72 | struct list_head list; |
| 73 | 73 | ||
| 74 | /* You can't use a snapshot if this is 0 (e.g. if full) */ | 74 | /* |
| 75 | * You can't use a snapshot if this is 0 (e.g. if full). | ||
| 76 | * A snapshot-merge target never clears this. | ||
| 77 | */ | ||
| 75 | int valid; | 78 | int valid; |
| 76 | 79 | ||
| 77 | /* Origin writes don't trigger exceptions until this is set */ | 80 | /* Origin writes don't trigger exceptions until this is set */ |
| @@ -107,6 +110,21 @@ struct dm_snapshot { | |||
| 107 | spinlock_t tracked_chunk_lock; | 110 | spinlock_t tracked_chunk_lock; |
| 108 | struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; | 111 | struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; |
| 109 | 112 | ||
| 113 | /* | ||
| 114 | * The merge operation failed if this flag is set. | ||
| 115 | * Failure modes are handled as follows: | ||
| 116 | * - I/O error reading the header | ||
| 117 | * => don't load the target; abort. | ||
| 118 | * - Header does not have "valid" flag set | ||
| 119 | * => use the origin; forget about the snapshot. | ||
| 120 | * - I/O error when reading exceptions | ||
| 121 | * => don't load the target; abort. | ||
| 122 | * (We can't use the intermediate origin state.) | ||
| 123 | * - I/O error while merging | ||
| 124 | * => stop merging; set merge_failed; process I/O normally. | ||
| 125 | */ | ||
| 126 | int merge_failed; | ||
| 127 | |||
| 110 | /* Wait for events based on state_bits */ | 128 | /* Wait for events based on state_bits */ |
| 111 | unsigned long state_bits; | 129 | unsigned long state_bits; |
| 112 | 130 | ||
| @@ -900,9 +918,13 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s) | |||
| 900 | linear_chunks = s->store->type->prepare_merge(s->store, &old_chunk, | 918 | linear_chunks = s->store->type->prepare_merge(s->store, &old_chunk, |
| 901 | &new_chunk); | 919 | &new_chunk); |
| 902 | if (linear_chunks <= 0) { | 920 | if (linear_chunks <= 0) { |
| 903 | if (linear_chunks < 0) | 921 | if (linear_chunks < 0) { |
| 904 | DMERR("Read error in exception store: " | 922 | DMERR("Read error in exception store: " |
| 905 | "shutting down merge"); | 923 | "shutting down merge"); |
| 924 | down_write(&s->lock); | ||
| 925 | s->merge_failed = 1; | ||
| 926 | up_write(&s->lock); | ||
| 927 | } | ||
| 906 | goto shut; | 928 | goto shut; |
| 907 | } | 929 | } |
| 908 | 930 | ||
| @@ -988,6 +1010,7 @@ static void merge_callback(int read_err, unsigned long write_err, void *context) | |||
| 988 | 1010 | ||
| 989 | shut: | 1011 | shut: |
| 990 | down_write(&s->lock); | 1012 | down_write(&s->lock); |
| 1013 | s->merge_failed = 1; | ||
| 991 | b = __release_queued_bios_after_merge(s); | 1014 | b = __release_queued_bios_after_merge(s); |
| 992 | up_write(&s->lock); | 1015 | up_write(&s->lock); |
| 993 | error_bios(b); | 1016 | error_bios(b); |
| @@ -1090,6 +1113,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1090 | INIT_LIST_HEAD(&s->list); | 1113 | INIT_LIST_HEAD(&s->list); |
| 1091 | spin_lock_init(&s->pe_lock); | 1114 | spin_lock_init(&s->pe_lock); |
| 1092 | s->state_bits = 0; | 1115 | s->state_bits = 0; |
| 1116 | s->merge_failed = 0; | ||
| 1093 | s->first_merging_chunk = 0; | 1117 | s->first_merging_chunk = 0; |
| 1094 | s->num_merging_chunks = 0; | 1118 | s->num_merging_chunks = 0; |
| 1095 | bio_list_init(&s->bios_queued_during_merge); | 1119 | bio_list_init(&s->bios_queued_during_merge); |
| @@ -1835,6 +1859,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, | |||
| 1835 | 1859 | ||
| 1836 | if (!snap->valid) | 1860 | if (!snap->valid) |
| 1837 | DMEMIT("Invalid"); | 1861 | DMEMIT("Invalid"); |
| 1862 | else if (snap->merge_failed) | ||
| 1863 | DMEMIT("Merge failed"); | ||
| 1838 | else { | 1864 | else { |
| 1839 | if (snap->store->type->usage) { | 1865 | if (snap->store->type->usage) { |
| 1840 | sector_t total_sectors, sectors_allocated, | 1866 | sector_t total_sectors, sectors_allocated, |
