[lvm-devel] [patch] Fix for handling simultaneous failure of mirrored-log devices

Petr Rockai prockai at redhat.com
Thu Oct 14 19:16:22 UTC 2010


Hi,

we had those changes re-invented when Jon realized that this code
already existed at some point. The below changes correspond to what we
ended up doing to make the code behave correctly. I believe the result
is correct. As Jon mentions, we have a semi-automated test, which I will
try to convert to a fully automated one, but I wouldn't block the patch
on that. It's been sufficiently hand-checked for now.

Green for checking this in.

> Signed-off-by: Jonathan Brassow <jbrassow at redhat.com>
Reviewed-by: Petr Rockai <prockai at redhat.com>

Jonathan Brassow <jbrassow at redhat.com> writes:
> Index: LVM2/lib/metadata/lv_manip.c
> ===================================================================
> --- LVM2.orig/lib/metadata/lv_manip.c
> +++ LVM2/lib/metadata/lv_manip.c
> @@ -462,6 +462,15 @@ int replace_lv_with_error_segment(struct
>  	if (!lv_empty(lv))
>  		return_0;
>  
> +	/*
> +	 * Since we are replacing the whatever-was-there with
> +	 * an error segment, we should also clear any flags
> +	 * that suggest it is anything other than "error".
> +	 */
> +	lv->status &= ~MIRRORED;
> +
> +	/* FIXME: Should we bug if we find a log_lv attached? */
> +
>  	if (!lv_add_virtual_segment(lv, 0, len,
>  				    get_segtype_from_string(lv->vg->cmd,
>  							    "error")))
> Index: LVM2/lib/metadata/mirror.c
> ===================================================================
> --- LVM2.orig/lib/metadata/mirror.c
> +++ LVM2/lib/metadata/mirror.c
> @@ -896,18 +896,40 @@ static int _remove_mirror_images(struct 
>  	 */
>  	if (detached_log_lv && lv_is_mirrored(detached_log_lv) &&
>  	    (detached_log_lv->status & PARTIAL_LV)) {
> +		struct lv_segment *seg = first_seg(detached_log_lv);
> +
>  		log_very_verbose("%s being removed due to failures",
>  				 detached_log_lv->name);
>  
> +		/*
> +		 * We are going to replace the mirror with an
> +		 * error segment, but before we do, we must remember
> +		 * all of the LVs that must be deleted later (i.e.
> +		 * the sub-lv's)
> +		 */
> +		for (m = 0; m < seg->area_count; m++) {
> +			seg_lv(seg, m)->status &= ~MIRROR_IMAGE;
> +			lv_set_visible(seg_lv(seg, m));
> +			if (!(lvl = dm_pool_alloc(lv->vg->cmd->mem,
> +						  sizeof(*lvl)))) {
> +				log_error("dm_pool_alloc failed");
> +				return 0;
> +			}
> +			lvl->lv = seg_lv(seg, m);
> +			dm_list_add(&tmp_orphan_lvs, &lvl->list);
> +		}
> +
>  		if (!replace_lv_with_error_segment(detached_log_lv)) {
>  			log_error("Failed error target substitution for %s",
>  				  detached_log_lv->name);
>  			return 0;
>  		}
>  
> -		/*
> -		 * Flush all I/Os held by mirrored log.
> -		 */
> +		if (!vg_write(detached_log_lv->vg)) {
> +			log_error("intermediate VG write failed.");
> +			return 0;
> +		}
> +
>  		if (!suspend_lv(detached_log_lv->vg->cmd,
>  				detached_log_lv)) {
>  			log_error("Failed to suspend %s",
> @@ -915,8 +937,14 @@ static int _remove_mirror_images(struct 
>  			return 0;
>   		}
>  
> -		if (!resume_lv(detached_log_lv->vg->cmd,
> -			       detached_log_lv)) {
> +		if (!vg_commit(detached_log_lv->vg)) {
> +			if (!resume_lv(detached_log_lv->vg->cmd,
> +				       detached_log_lv))
> +				stack;
> +			return_0;
> +		}
> +
> +		if (!resume_lv(detached_log_lv->vg->cmd, detached_log_lv)) {
>  			log_error("Failed to resume %s",
>  				  detached_log_lv->name);
>  			return_0;




More information about the lvm-devel mailing list