Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8ddb1cf authored by Mike Snitzer's avatar Mike Snitzer Committed by Alasdair G Kergon
Browse files

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: default avatarMike Snitzer <snitzer@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 8a2d5286
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -71,7 +71,10 @@ struct dm_snapshot {
	/* List of snapshots per Origin */
	struct list_head list;

	/* You can't use a snapshot if this is 0 (e.g. if full) */
	/*
	 * You can't use a snapshot if this is 0 (e.g. if full).
	 * A snapshot-merge target never clears this.
	 */
	int valid;

	/* Origin writes don't trigger exceptions until this is set */
@@ -107,6 +110,21 @@ struct dm_snapshot {
	spinlock_t tracked_chunk_lock;
	struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];

	/*
	 * The merge operation failed if this flag is set.
	 * Failure modes are handled as follows:
	 * - I/O error reading the header
	 *   	=> don't load the target; abort.
	 * - Header does not have "valid" flag set
	 *   	=> use the origin; forget about the snapshot.
	 * - I/O error when reading exceptions
	 *   	=> don't load the target; abort.
	 *         (We can't use the intermediate origin state.)
	 * - I/O error while merging
	 *	=> stop merging; set merge_failed; process I/O normally.
	 */
	int merge_failed;

	/* Wait for events based on state_bits */
	unsigned long state_bits;

@@ -900,9 +918,13 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s)
	linear_chunks = s->store->type->prepare_merge(s->store, &old_chunk,
						      &new_chunk);
	if (linear_chunks <= 0) {
		if (linear_chunks < 0)
		if (linear_chunks < 0) {
			DMERR("Read error in exception store: "
			      "shutting down merge");
			down_write(&s->lock);
			s->merge_failed = 1;
			up_write(&s->lock);
		}
		goto shut;
	}

@@ -988,6 +1010,7 @@ static void merge_callback(int read_err, unsigned long write_err, void *context)

shut:
	down_write(&s->lock);
	s->merge_failed = 1;
	b = __release_queued_bios_after_merge(s);
	up_write(&s->lock);
	error_bios(b);
@@ -1090,6 +1113,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
	INIT_LIST_HEAD(&s->list);
	spin_lock_init(&s->pe_lock);
	s->state_bits = 0;
	s->merge_failed = 0;
	s->first_merging_chunk = 0;
	s->num_merging_chunks = 0;
	bio_list_init(&s->bios_queued_during_merge);
@@ -1835,6 +1859,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,

		if (!snap->valid)
			DMEMIT("Invalid");
		else if (snap->merge_failed)
			DMEMIT("Merge failed");
		else {
			if (snap->store->type->usage) {
				sector_t total_sectors, sectors_allocated,