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

Petr Rockai <[email protected]>
Newsgroups dev.linux.lists.lvm-devel
Message-ID <[email protected].>
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 <[email protected]>
Reviewed-by: Petr Rockai <[email protected]>

Jonathan Brassow <[email protected]> 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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.