[dm-devel] [PATCH -next] dm snapshot: record cause of invalidating snapshot

Li Lingfeng lilingfeng3 at huawei.com
Sat Sep 9 11:09:24 UTC 2023


Friendly ping ...

Thanks

在 2023/8/10 14:44, Li Lingfeng 写道:
> The cause of invalidating snapshot will be print in log. However, if we
> lost the log, we will never get the cause. What we can get by "dmsetup
> status" is the state of "Invalid" without the cause.
>
> Record cause of invalidating snapshot in snapshot->valid, so that we can
> query the cause by "dmsetup status".
>
> Signed-off-by: Li Lingfeng <lilingfeng3 at huawei.com>
> ---
>   drivers/md/dm-snap.c | 60 +++++++++++++++++++++++++++++++++-----------
>   1 file changed, 45 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
> index 41735a25d50a..48788431e7bf 100644
> --- a/drivers/md/dm-snap.c
> +++ b/drivers/md/dm-snap.c
> @@ -39,6 +39,28 @@ static const char dm_snapshot_merge_target_name[] = "snapshot-merge";
>   #define DM_TRACKED_CHUNK_HASH(x)	((unsigned long)(x) & \
>   					 (DM_TRACKED_CHUNK_HASH_SIZE - 1))
>   
> +#define INVALID_CAUSE_BIT		16
> +#define DM_SNAPSHOT_VALID(s)		(s->valid & \
> +					((1 << INVALID_CAUSE_BIT) - 1))
> +#define DM_SNAPSHOT_INVALID_CAUSE(s)	(s->valid >> INVALID_CAUSE_BIT)
> +#define SET_INVALID_CAUSE(s, cause)	(s->valid = \
> +					(DM_SNAPSHOT_VALID(s) | \
> +					(cause << INVALID_CAUSE_BIT)))
> +
> +enum invalid_cause {
> +	INVALID_BY_METADATA = 1,
> +	INVALID_BY_HANDOVER = 2,
> +	INVALID_BY_CACELLING_HANDOVER = 3,
> +	INVALID_BY_EIO = 4,
> +	INVALID_BY_ENOMEM = 5
> +};
> +
> +char *display_invalid_cause[] = {"by METADATA",
> +				 "by HANDOVER",
> +				 "by CANCELLING HANDOVER",
> +				 "by EIO",
> +				 "by ENOMEM"};
> +
>   struct dm_exception_table {
>   	uint32_t hash_mask;
>   	unsigned hash_shift;
> @@ -1054,7 +1076,7 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s)
>   	/*
>   	 * valid flag never changes during merge, so no lock required.
>   	 */
> -	if (!s->valid) {
> +	if (!DM_SNAPSHOT_VALID(s)) {
>   		DMERR("Snapshot is invalid: can't merge");
>   		goto shut;
>   	}
> @@ -1403,6 +1425,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
>   		goto bad_read_metadata;
>   	} else if (r > 0) {
>   		s->valid = 0;
> +		SET_INVALID_CAUSE(s, INVALID_BY_METADATA);
>   		DMWARN("Snapshot is marked invalid.");
>   	}
>   
> @@ -1480,6 +1503,7 @@ static void __handover_exceptions(struct dm_snapshot *snap_src,
>   	 * Set source invalid to ensure it receives no further I/O.
>   	 */
>   	snap_src->valid = 0;
> +	SET_INVALID_CAUSE(snap_src, INVALID_BY_HANDOVER);
>   }
>   
>   static void snapshot_dtr(struct dm_target *ti)
> @@ -1496,6 +1520,7 @@ static void snapshot_dtr(struct dm_target *ti)
>   	if (snap_src && snap_dest && (s == snap_src)) {
>   		down_write(&snap_dest->lock);
>   		snap_dest->valid = 0;
> +		SET_INVALID_CAUSE(snap_dest, INVALID_BY_HANDOVER);
>   		up_write(&snap_dest->lock);
>   		DMERR("Cancelling snapshot handover.");
>   	}
> @@ -1635,18 +1660,21 @@ static void error_bios(struct bio *bio)
>   
>   static void __invalidate_snapshot(struct dm_snapshot *s, int err)
>   {
> -	if (!s->valid)
> +	if (!DM_SNAPSHOT_VALID(s))
>   		return;
>   
> -	if (err == -EIO)
> -		DMERR("Invalidating snapshot: Error reading/writing.");
> -	else if (err == -ENOMEM)
> -		DMERR("Invalidating snapshot: Unable to allocate exception.");
> -
>   	if (s->store->type->drop_snapshot)
>   		s->store->type->drop_snapshot(s->store);
>   
>   	s->valid = 0;
> +	if (err == -EIO) {
> +		SET_INVALID_CAUSE(s, INVALID_BY_EIO);
> +		DMERR("Invalidating snapshot: Error reading/writing.");
> +	} else if (err == -ENOMEM) {
> +		SET_INVALID_CAUSE(s, INVALID_BY_ENOMEM);
> +		DMERR("Invalidating snapshot: Unable to allocate exception.");
> +	}
> +
>   
>   	dm_table_event(s->ti->table);
>   }
> @@ -1692,7 +1720,7 @@ static void pending_complete(void *context, int success)
>   
>   	down_read(&s->lock);
>   	dm_exception_table_lock(&lock);
> -	if (!s->valid) {
> +	if (!DM_SNAPSHOT_VALID(s)) {
>   		up_read(&s->lock);
>   		free_completed_exception(e);
>   		error = 1;
> @@ -1984,7 +2012,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
>   
>   	/* Full snapshots are not usable */
>   	/* To get here the table must be live so s->active is always set. */
> -	if (!s->valid)
> +	if (!DM_SNAPSHOT_VALID(s))
>   		return DM_MAPIO_KILL;
>   
>   	if (bio_data_dir(bio) == WRITE) {
> @@ -1995,7 +2023,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
>   	down_read(&s->lock);
>   	dm_exception_table_lock(&lock);
>   
> -	if (!s->valid || (unlikely(s->snapshot_overflowed) &&
> +	if (!DM_SNAPSHOT_VALID(s) || (unlikely(s->snapshot_overflowed) &&
>   	    bio_data_dir(bio) == WRITE)) {
>   		r = DM_MAPIO_KILL;
>   		goto out_unlock;
> @@ -2068,7 +2096,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
>   				down_write(&s->lock);
>   
>   				if (s->store->userspace_supports_overflow) {
> -					if (s->valid && !s->snapshot_overflowed) {
> +					if (DM_SNAPSHOT_VALID(s) && !s->snapshot_overflowed) {
>   						s->snapshot_overflowed = 1;
>   						DMERR("Snapshot overflowed: Unable to allocate exception.");
>   					}
> @@ -2159,7 +2187,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
>   	down_write(&s->lock);
>   
>   	/* Full merging snapshots are redirected to the origin */
> -	if (!s->valid)
> +	if (!DM_SNAPSHOT_VALID(s))
>   		goto redirect_to_origin;
>   
>   	/* If the block is already remapped - use that */
> @@ -2344,8 +2372,10 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,
>   
>   		down_write(&snap->lock);
>   
> -		if (!snap->valid)
> -			DMEMIT("Invalid");
> +		if (!DM_SNAPSHOT_VALID(snap))
> +			DMEMIT("Invalid %s", DM_SNAPSHOT_INVALID_CAUSE(snap) ?
> +					display_invalid_cause[DM_SNAPSHOT_INVALID_CAUSE(snap) - 1] :
> +					"");
>   		else if (snap->merge_failed)
>   			DMEMIT("Merge failed");
>   		else if (snap->snapshot_overflowed)
> @@ -2477,7 +2507,7 @@ static int __origin_write(struct list_head *snapshots, sector_t sector,
>   		dm_exception_table_lock(&lock);
>   
>   		/* Only deal with valid and active snapshots */
> -		if (!snap->valid || !snap->active)
> +		if (!DM_SNAPSHOT_VALID(snap) || !snap->active)
>   			goto next_snapshot;
>   
>   		pe = __lookup_pending_exception(snap, chunk);



More information about the dm-devel mailing list