[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