]> sourceware.org Git - lvm2.git/commitdiff
lvmlockd: make lockstart wait for existing start
authorDavid Teigland <teigland@redhat.com>
Wed, 16 Jan 2019 16:41:43 +0000 (10:41 -0600)
committerDavid Teigland <teigland@redhat.com>
Wed, 16 Jan 2019 16:49:04 +0000 (10:49 -0600)
If there are two independent scripts doing:
  vgchange --lockstart vg
  lvchange -ay vg/lv

The first vgchange to do the lockstart will wait for
the lockstart to complete before returning.
The second vgchange to do the lockstart will see that
the start is already in progress (from the first) and
will do nothing.  This means the second does not wait
for any lockstart to complete, and moves on to the
lvchange which may find the lockspace still starting
and fail.

To fix this, make the vgchange lockstart command
wait for any lockstart's in progress to complete.

daemons/lvmlockd/lvmlockd-core.c
lib/locking/lvmlockd.c
lib/locking/lvmlockd.h
tools/vgchange.c
tools/vgcreate.c

index 1ec3efd5facb9f21ad90ab8bbe3e25a6b7c9d604..60ae537e2b46cc72958e97c234d5a7b49a390113 100644 (file)
@@ -2743,6 +2743,9 @@ static int add_lockspace_thread(const char *ls_name,
                if (ls2->thread_stop) {
                        log_debug("add_lockspace_thread %s exists and stopping", ls->name);
                        rv = -EAGAIN;
+               } else if (!ls2->create_fail && !ls2->create_done) {
+                       log_debug("add_lockspace_thread %s exists and starting", ls->name);
+                       rv = -ESTARTING;
                } else {
                        log_debug("add_lockspace_thread %s exists", ls->name);
                        rv = -EEXIST;
@@ -2984,7 +2987,7 @@ static int count_lockspace_starting(uint32_t client_id)
 
        pthread_mutex_lock(&lockspaces_mutex);
        list_for_each_entry(ls, &lockspaces, list) {
-               if (ls->start_client_id != client_id)
+               if (client_id && (ls->start_client_id != client_id))
                        continue;
 
                if (!ls->create_done && !ls->create_fail) {
@@ -3389,7 +3392,7 @@ static void *worker_thread_main(void *arg_in)
                        add_client_result(act);
 
                } else if (act->op == LD_OP_START_WAIT) {
-                       act->result = count_lockspace_starting(act->client_id);
+                       act->result = count_lockspace_starting(0);
                        if (!act->result)
                                add_client_result(act);
                        else
@@ -3423,7 +3426,7 @@ static void *worker_thread_main(void *arg_in)
                list_for_each_entry_safe(act, safe, &delayed_list, list) {
                        if (act->op == LD_OP_START_WAIT) {
                                log_debug("work delayed start_wait for client %u", act->client_id);
-                               act->result = count_lockspace_starting(act->client_id);
+                               act->result = count_lockspace_starting(0);
                                if (!act->result) {
                                        list_del(&act->list);
                                        add_client_result(act);
index 9fb7b364bbf847898721aac691df2a3b23c489a0..9b2d050155e7c567ec0a7ef657f99a5cdcbad4f2 100644 (file)
@@ -1072,7 +1072,7 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
  * that the VG lockspace being started is new.
  */
 
-int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init)
+int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init, int *exists)
 {
        char uuid[64] __attribute__((aligned(8)));
        daemon_reply reply;
@@ -1147,6 +1147,12 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_i
                log_debug("VG %s start error: already started", vg->name);
                ret = 1;
                break;
+       case -ESTARTING:
+               log_debug("VG %s start error: already starting", vg->name);
+               if (exists)
+                       *exists = 1;
+               ret = 1;
+               break;
        case -EARGS:
                log_error("VG %s start failed: invalid parameters for %s", vg->name, vg->lock_type);
                break;
@@ -2668,7 +2674,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
                 * Depending on the problem that caused the rename to
                 * fail, it may make sense to not restart the VG here.
                 */
-               if (!lockd_start_vg(cmd, vg, 0))
+               if (!lockd_start_vg(cmd, vg, 0, NULL))
                        log_error("Failed to restart VG %s lockspace.", vg->name);
                return 1;
        }
@@ -2708,7 +2714,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
                }
        }
 
-       if (!lockd_start_vg(cmd, vg, 1))
+       if (!lockd_start_vg(cmd, vg, 1, NULL))
                log_error("Failed to start VG %s lockspace.", vg->name);
 
        return 1;
index 0a6ea96598cb919ee0d3e25f3554b74a45ae69f5..1fbf76531f94b6203c8255872052d45cb5b12038 100644 (file)
@@ -63,7 +63,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
 
 /* start and stop the lockspace for a vg */
 
-int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init);
+int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init, int *exists);
 int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg);
 int lockd_start_wait(struct cmd_context *cmd);
 
index bbdf2e4eb1c625de403a4fcb52bef109460ed63e..f831fd9074aaa5a63cb62115f88d91cb6c5067ec 100644 (file)
@@ -560,6 +560,7 @@ static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg
 {
        const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL);
        int auto_opt = 0;
+       int exists = 0;
        int r;
 
        if (!vg_is_shared(vg))
@@ -586,10 +587,12 @@ static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg
        }
 
 do_start:
-       r = lockd_start_vg(cmd, vg, 0);
+       r = lockd_start_vg(cmd, vg, 0, &exists);
 
        if (r)
                vp->lock_start_count++;
+       else if (exists)
+               vp->lock_start_count++;
        if (!strcmp(vg->lock_type, "sanlock"))
                vp->lock_start_sanlock = 1;
 
index c146ab776be644970ea7a389ce93efb9872a202d..f9bf10e222371931b63ee3b5128ec477b82c5fa1 100644 (file)
@@ -204,7 +204,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
        if (vg_is_shared(vg)) {
                const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL);
 
-               if (!lockd_start_vg(cmd, vg, 1)) {
+               if (!lockd_start_vg(cmd, vg, 1, NULL)) {
                        log_error("Failed to start locking");
                        goto out;
                }
This page took 0.053322 seconds and 5 git commands to generate.