[lvm-devel] a bug in snapshots

Mikulas Patocka mpatocka at redhat.com
Wed Feb 10 21:39:37 UTC 2010


> Here is what I came up with.  Justification for this approach is
> explained in the dev_manager_snapshot_percent() comment below.
> 
> diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
> index 6fbc392..ab4f16c 100644
> --- a/lib/activate/dev_manager.c
> +++ b/lib/activate/dev_manager.c
> @@ -423,7 +423,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
>  			const char *target_type, int wait,
>  			const struct logical_volume *lv, float *percent,
>  			percent_range_t *overall_percent_range,
> -			uint32_t *event_nr)
> +			uint32_t *event_nr, int fail_if_percent_unsupported)
>  {
>  	int r = 0;
>  	struct dm_task *dmt;
> @@ -516,10 +516,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
>  			/* above ->target_percent() was not executed! */
>  			/* FIXME why return PERCENT_100 et. al. in this case? */
>  			*overall_percent_range = PERCENT_100;
> -			if (lv && lv_is_merging_origin(lv)) {
> -				/* must fail in snapshot-merge case */
> +			if (fail_if_percent_unsupported)
>  				goto_out;
> -			}
>  		} else
>  			*overall_percent_range = combined_percent_range;
>  	}
> @@ -535,20 +533,24 @@ static int _percent_run(struct dev_manager *dm, const char *name,
>  static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
>  		    const char *target_type, int wait,
>  		    const struct logical_volume *lv, float *percent,
> -		    percent_range_t *overall_percent_range, uint32_t *event_nr)
> +		    percent_range_t *overall_percent_range, uint32_t *event_nr,
> +		    int fail_if_percent_unsupported)
>  {
>  	if (dlid && *dlid) {
>  		if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
> -				 overall_percent_range, event_nr))
> +				 overall_percent_range, event_nr,
> +				 fail_if_percent_unsupported))
>  			return 1;
>  		else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
>  				      target_type, wait, lv, percent,
> -				      overall_percent_range, event_nr))
> +				      overall_percent_range, event_nr,
> +				      fail_if_percent_unsupported))
>  			return 1;
>  	}
>  
>  	if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
> -				 overall_percent_range, event_nr))
> +				 overall_percent_range, event_nr,
> +				 fail_if_percent_unsupported))
>  		return 1;
>  
>  	return 0;
> @@ -607,6 +609,21 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
>  {
>  	char *name;
>  	const char *dlid;
> +	int fail_if_percent_unsupported = 0;
> +
> +	if (lv_is_merging_origin(lv)) {
> +		/*
> +		 * Passing unsupported LV types to _percent will lead to a
> +		 * default successful return with percent_range as PERCENT_100.
> +		 * - For a merging origin, this will result in a polldaemon
> +		 *   that runs infinitely (because completion is PERCENT_0)
> +		 * - We unfortunately don't yet _know_ if a snapshot-merge
> +		 *   target is active (activation is deferred if dev is open);
> +		 *   so we can't short-circuit origin devices based purely on
> +		 *   existing LVM LV attributes.
> +		 */
> +		fail_if_percent_unsupported = 1;
> +	}
>  
>  	/*
>  	 * Build a name for the top layer.
> @@ -621,8 +638,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
>  	 * Try and get some info on this device.
>  	 */
>  	log_debug("Getting device status percentage for %s", name);
> -	if (!(_percent(dm, name, dlid, "snapshot", 0, lv, percent,
> -		       percent_range, NULL)))
> +	if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
> +		       percent_range, NULL, fail_if_percent_unsupported)))
>  		return_0;
>  
>  	/* FIXME dm_pool_free ? */
> @@ -657,7 +674,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
>  
>  	log_debug("Getting device mirror status percentage for %s", name);
>  	if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
> -		       percent_range, event_nr)))
> +		       percent_range, event_nr, 0)))
>  		return_0;
>  
>  	return 1;
> 

The patch is OK.

Reviewed-by: Mikulas Patocka <mpatocka at redhat.com>

Alasdair, I think you should make a new LVM release after applying this 
patch, this bug is quite serious and it should be fixed ASAP. The 
implication of the bug is that multi-segment snapshots are always being 
reported as 100% full and invalid --- it can result in data loss because 
the user may think that the snapshot is overflowed and delete it.

Mikulas




More information about the lvm-devel mailing list