aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2009-12-10 18:52:35 -0500
committerAlasdair G Kergon <agk@redhat.com>2009-12-10 18:52:35 -0500
commitd8ddb1cfff0070479c1f4a07c1d4a48ef8cb188e (patch)
tree340967ea04ef1d790dfce3c324c3bfc1ce30cace /drivers/md/dm-snap.c
parent8a2d528620e228ddfd0df9cec0a16e034ff8db1d (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>
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c30
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
989shut: 1011shut:
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,