]> sourceware.org Git - lvm2.git/commitdiff
pvcreate,pvremove: fix reacquiring global lock after prompt
authorDavid Teigland <teigland@redhat.com>
Tue, 26 Nov 2019 20:34:43 +0000 (14:34 -0600)
committerDavid Teigland <teigland@redhat.com>
Tue, 26 Nov 2019 20:34:43 +0000 (14:34 -0600)
When pvcreate/pvremove prompt the user, they first release
the global lock, then acquire it again after the prompt,
to avoid blocking other commands while waiting for a user
response.  This release/reacquire changes the locking
order with respect to the hints flock (and potentially other
locks).  So, to avoid deadlock, use a nonblocking request
when reacquiring the global lock.

lib/locking/locking.c
lib/locking/locking.h
lib/misc/lvm-flock.c
tools/toollib.c

index 3058a8ba017e04e3d25c644eed74ec3d0210fafd..65ff8c2211a3dc46e2cbbc564a242b7a00cc5829 100644 (file)
@@ -338,7 +338,7 @@ int sync_local_dev_names(struct cmd_context* cmd)
  * an explicitly acquired ex global lock to sh in process_each.
  */
 
-static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert)
+static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert, int nonblock)
 {
        uint32_t flags = 0;
        int ret;
@@ -346,6 +346,9 @@ static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert)
        if (convert)
                flags |= LCK_CONVERT;
 
+       if (nonblock)
+               flags |= LCK_NONBLOCK;
+
        if (!strcmp(mode, "ex")) {
                flags |= LCK_WRITE;
 
@@ -379,7 +382,7 @@ static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert)
 
 int lockf_global(struct cmd_context *cmd, const char *mode)
 {
-       return _lockf_global(cmd, mode, 0);
+       return _lockf_global(cmd, mode, 0, 0);
 }
 
 int lockf_global_convert(struct cmd_context *cmd, const char *mode)
@@ -388,7 +391,12 @@ int lockf_global_convert(struct cmd_context *cmd, const char *mode)
        if (cmd->lockf_global_ex && !strcmp(mode, "ex"))
                return 1;
 
-       return _lockf_global(cmd, mode, 1);
+       return _lockf_global(cmd, mode, 1, 0);
+}
+
+int lockf_global_nonblock(struct cmd_context *cmd, const char *mode)
+{
+       return _lockf_global(cmd, mode, 0, 1);
 }
 
 int lock_global(struct cmd_context *cmd, const char *mode)
index 746667a9bf1b136183ba3bcc9247a0036791cef9..3e8ae6f0c27a9c1b3b70dd67244ea4fc944d3f24 100644 (file)
@@ -75,6 +75,7 @@ int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusiv
 
 int lockf_global(struct cmd_context *cmd, const char *mode);
 int lockf_global_convert(struct cmd_context *cmd, const char *mode);
+int lockf_global_nonblock(struct cmd_context *cmd, const char *mode);
 int lock_global(struct cmd_context *cmd, const char *mode);
 int lock_global_convert(struct cmd_context *cmd, const char *mode);
 
index d65601d9404a04a1bb49240a9f6507cda8a689e7..d48ff22e19ee0a3de0619183e03af481567656df 100644 (file)
@@ -164,7 +164,7 @@ static int _do_write_priority_flock(const char *file, int *fd, int operation, ui
        strcpy(file_aux, file);
        strcat(file_aux, AUX_LOCK_SUFFIX);
 
-       if ((r = _do_flock(file_aux, &fd_aux, LOCK_EX, 0))) {
+       if ((r = _do_flock(file_aux, &fd_aux, LOCK_EX, nonblock))) {
                if (operation == LOCK_EX) {
                        r = _do_flock(file, fd, operation, nonblock);
                        _undo_flock(file_aux, fd_aux);
index ee2419b8c45baa50e8b43ed60d4d8efe8d8970b8..a5304bf63fc909f5eae90fb52a3a5b71aa37d3cb 100644 (file)
@@ -5577,10 +5577,11 @@ int pvcreate_each_device(struct cmd_context *cmd,
         * Reacquire the lock that was released above before waiting, then
         * check again that the devices can still be used.  If the second loop
         * finds them changed, or can't find them any more, then they aren't
-        * used.
+        * used.  Use a non-blocking request when reacquiring to avoid
+        * potential deadlock since this is not the normal locking sequence.
         */
 
-       if (!lockf_global(cmd, "ex")) {
+       if (!lockf_global_nonblock(cmd, "ex")) {
                log_error("Failed to reacquire global lock after prompt.");
                goto_out;
        }
This page took 0.047191 seconds and 5 git commands to generate.