mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-04 09:18:36 +03:00
lvconvert: merge polling fixes for lockd
. the poll check will eventually call finish which will write the VG, so an ex VG lock is needed from lvmlockd. . fix missing unlock on poll error path . remove the lockd locking while monitoring the progress of the command, as suggested by the earlier FIXME comment, as it's not needed.
This commit is contained in:
parent
8bfcefe11a
commit
27e6aee390
@ -3410,10 +3410,7 @@ static int lvconvert_single(struct cmd_context *cmd, struct lvconvert_params *lp
|
|||||||
cmd->handles_missing_pvs = 1;
|
cmd->handles_missing_pvs = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Unlock on error paths not required, it's automatic when command exits. */
|
||||||
* The VG lock will be released when the command exits.
|
|
||||||
* Commands that poll the LV will reacquire the VG lock.
|
|
||||||
*/
|
|
||||||
if (!lockd_vg(cmd, lp->vg_name, "ex", 0, &lockd_state))
|
if (!lockd_vg(cmd, lp->vg_name, "ex", 0, &lockd_state))
|
||||||
goto_out;
|
goto_out;
|
||||||
|
|
||||||
@ -3461,10 +3458,7 @@ static int lvconvert_single(struct cmd_context *cmd, struct lvconvert_params *lp
|
|||||||
bad:
|
bad:
|
||||||
unlock_vg(cmd, lp->vg_name);
|
unlock_vg(cmd, lp->vg_name);
|
||||||
|
|
||||||
/*
|
/* Unlock here so it's not held during polling. */
|
||||||
* The command may sit and monitor progress for some time,
|
|
||||||
* and we do not need or want the VG lock held during that.
|
|
||||||
*/
|
|
||||||
lockd_vg(cmd, lp->vg_name, "un", 0, &lockd_state);
|
lockd_vg(cmd, lp->vg_name, "un", 0, &lockd_state);
|
||||||
|
|
||||||
release_vg(vg);
|
release_vg(vg);
|
||||||
|
@ -136,17 +136,22 @@ static void _sleep_and_rescan_devices(struct daemon_parms *parms)
|
|||||||
int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
||||||
struct daemon_parms *parms)
|
struct daemon_parms *parms)
|
||||||
{
|
{
|
||||||
struct volume_group *vg;
|
struct volume_group *vg = NULL;
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
int finished = 0;
|
int finished = 0;
|
||||||
uint32_t lockd_state = 0;
|
uint32_t lockd_state = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Poll for completion */
|
/* Poll for completion */
|
||||||
while (!finished) {
|
while (!finished) {
|
||||||
if (parms->wait_before_testing)
|
if (parms->wait_before_testing)
|
||||||
_sleep_and_rescan_devices(parms);
|
_sleep_and_rescan_devices(parms);
|
||||||
|
|
||||||
if (!lockd_vg(cmd, id->vg_name, "sh", 0, &lockd_state)) {
|
/*
|
||||||
|
* An ex VG lock is needed because the check can call finish_copy
|
||||||
|
* which writes the VG.
|
||||||
|
*/
|
||||||
|
if (!lockd_vg(cmd, id->vg_name, "ex", 0, &lockd_state)) {
|
||||||
log_error("ABORTING: Can't lock VG for %s.", id->display_name);
|
log_error("ABORTING: Can't lock VG for %s.", id->display_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -154,10 +159,12 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
|||||||
/* Locks the (possibly renamed) VG again */
|
/* Locks the (possibly renamed) VG again */
|
||||||
vg = vg_read(cmd, id->vg_name, NULL, READ_FOR_UPDATE, lockd_state);
|
vg = vg_read(cmd, id->vg_name, NULL, READ_FOR_UPDATE, lockd_state);
|
||||||
if (vg_read_error(vg)) {
|
if (vg_read_error(vg)) {
|
||||||
release_vg(vg);
|
|
||||||
log_error("ABORTING: Can't reread VG for %s.", id->display_name);
|
|
||||||
/* What more could we do here? */
|
/* What more could we do here? */
|
||||||
return 0;
|
log_error("ABORTING: Can't reread VG for %s.", id->display_name);
|
||||||
|
release_vg(vg);
|
||||||
|
vg = NULL;
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv = find_lv(vg, id->lv_name);
|
lv = find_lv(vg, id->lv_name);
|
||||||
@ -174,9 +181,8 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
|||||||
else
|
else
|
||||||
log_print_unless_silent("Can't find LV in %s for %s.",
|
log_print_unless_silent("Can't find LV in %s for %s.",
|
||||||
vg->name, id->display_name);
|
vg->name, id->display_name);
|
||||||
|
ret = 1;
|
||||||
unlock_and_release_vg(cmd, vg, vg->name);
|
goto out;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -185,13 +191,13 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
|||||||
*/
|
*/
|
||||||
if (!lv_is_active_locally(lv)) {
|
if (!lv_is_active_locally(lv)) {
|
||||||
log_print_unless_silent("%s: Interrupted: No longer active.", id->display_name);
|
log_print_unless_silent("%s: Interrupted: No longer active.", id->display_name);
|
||||||
unlock_and_release_vg(cmd, vg, vg->name);
|
ret = 1;
|
||||||
return 1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_check_lv_status(cmd, vg, lv, id->display_name, parms, &finished)) {
|
if (!_check_lv_status(cmd, vg, lv, id->display_name, parms, &finished)) {
|
||||||
unlock_and_release_vg(cmd, vg, vg->name);
|
ret = 0;
|
||||||
return_0;
|
goto_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_and_release_vg(cmd, vg, vg->name);
|
unlock_and_release_vg(cmd, vg, vg->name);
|
||||||
@ -215,6 +221,12 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (vg)
|
||||||
|
unlock_and_release_vg(cmd, vg, vg->name);
|
||||||
|
lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct poll_id_list {
|
struct poll_id_list {
|
||||||
@ -373,21 +385,17 @@ static int report_progress(struct cmd_context *cmd, struct poll_operation_id *id
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: we don't really need to take the vg lock here,
|
* It's reasonable to expect a lockd_vg("sh") here, but it should
|
||||||
* because we only report the progress on the same host
|
* not actually be needed, because we only report the progress on
|
||||||
* where the pvmove/lvconvert is happening. This means
|
* the same host where the pvmove/lvconvert is happening. This means
|
||||||
* that the local pvmove/lvconvert/lvpoll commands are
|
* that the local pvmove/lvconvert/lvpoll commands are updating the
|
||||||
* updating the local lvmetad with the latest info they
|
* local lvmetad with the latest info they have, and we just need to
|
||||||
* have, and we just need to read the latest info that
|
* read the latest info that they have put into lvmetad about their
|
||||||
* they have put into lvmetad about their progress.
|
* progress. No VG lock is needed to protect anything here (we're
|
||||||
* No VG lock is needed to protect anything here
|
* just reading the VG), and no VG lock is needed to force a VG read
|
||||||
* (we're just reading the VG), and no VG lock is
|
* from disk to get changes from other hosts, because the only change
|
||||||
* needed to force a VG read from disk to get changes
|
* to the VG we're interested in is the change done locally.
|
||||||
* from other hosts, because the only change to the VG
|
|
||||||
* we're interested in is the change done locally.
|
|
||||||
*/
|
*/
|
||||||
if (!lockd_vg(cmd, id->vg_name, "sh", 0, &lockd_state))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
vg = vg_read(cmd, id->vg_name, NULL, 0, lockd_state);
|
vg = vg_read(cmd, id->vg_name, NULL, 0, lockd_state);
|
||||||
if (vg_read_error(vg)) {
|
if (vg_read_error(vg)) {
|
||||||
@ -431,7 +439,6 @@ static int report_progress(struct cmd_context *cmd, struct poll_operation_id *id
|
|||||||
out:
|
out:
|
||||||
unlock_and_release_vg(cmd, vg, vg->name);
|
unlock_and_release_vg(cmd, vg, vg->name);
|
||||||
out_ret:
|
out_ret:
|
||||||
lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user