From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <f.weber@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id 8ECA291A16
 for <pve-devel@lists.proxmox.com>; Tue, 30 Jan 2024 18:11:30 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id 656B6317C4
 for <pve-devel@lists.proxmox.com>; Tue, 30 Jan 2024 18:11:30 +0100 (CET)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS
 for <pve-devel@lists.proxmox.com>; Tue, 30 Jan 2024 18:11:29 +0100 (CET)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id EA9254936D
 for <pve-devel@lists.proxmox.com>; Tue, 30 Jan 2024 18:11:28 +0100 (CET)
From: Friedrich Weber <f.weber@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Tue, 30 Jan 2024 18:10:53 +0100
Message-Id: <20240130171057.438025-3-f.weber@proxmox.com>
X-Mailer: git-send-email 2.39.2
In-Reply-To: <20240130171057.438025-1-f.weber@proxmox.com>
References: <20240130171057.438025-1-f.weber@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL -0.090 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
 T_SCC_BODY_TEXT_LINE    -0.01 -
Subject: [pve-devel] [PATCH container v2 2/6] api: status: move config
 locking from API handler into worker
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Tue, 30 Jan 2024 17:11:30 -0000

Previously, container start/stop/shutdown/suspend would try to acquire
the config lock in the API handler prior to forking a worker. If the
lock was currently held elsewhere, this would block the API handler
and thus the pvedaemon worker thread until the 10s timeout expired (or
the lock could be acquired).

To avoid blocking the API handler, immediately fork off a worker
process and try to acquire the config lock in that worker.

Patch best viewed with `git show -w`.

Suggested-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Friedrich Weber <f.weber@proxmox.com>
---

Notes:
    The diff is somewhat messy without `-w` -- couldn't come up with a
    better way.
    
    new in v2

 src/PVE/API2/LXC/Status.pm | 91 ++++++++++++++++++--------------------
 1 file changed, 42 insertions(+), 49 deletions(-)

diff --git a/src/PVE/API2/LXC/Status.pm b/src/PVE/API2/LXC/Status.pm
index f7e3128..7741374 100644
--- a/src/PVE/API2/LXC/Status.pm
+++ b/src/PVE/API2/LXC/Status.pm
@@ -176,32 +176,31 @@ __PACKAGE__->register_method({
 	    my $realcmd = sub {
 		my $upid = shift;
 
-		syslog('info', "starting CT $vmid: $upid\n");
+		PVE::LXC::Config->lock_config($vmid, sub {
+		    syslog('info', "starting CT $vmid: $upid\n");
 
-		my $conf = PVE::LXC::Config->load_config($vmid);
-
-		die "you can't start a CT if it's a template\n"
-		    if PVE::LXC::Config->is_template($conf);
+		    my $conf = PVE::LXC::Config->load_config($vmid);
 
-		if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
-		    PVE::LXC::Config->check_lock($conf);
-		}
+		    die "you can't start a CT if it's a template\n"
+			if PVE::LXC::Config->is_template($conf);
 
-		if ($conf->{unprivileged}) {
-		    PVE::LXC::Config->foreach_volume($conf, sub {
-			my ($ms, $mountpoint) = @_;
-			die "Quotas are not supported by unprivileged containers.\n" if $mountpoint->{quota};
-		    });
-		}
+		    if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
+			PVE::LXC::Config->check_lock($conf);
+		    }
 
-		PVE::LXC::vm_start($vmid, $conf, $skiplock, $param->{debug});
-	    };
+		    if ($conf->{unprivileged}) {
+			PVE::LXC::Config->foreach_volume($conf, sub {
+			    my ($ms, $mountpoint) = @_;
+			    die "Quotas are not supported by unprivileged containers.\n"
+				if $mountpoint->{quota};
+			});
+		    }
 
-	    my $lockcmd = sub {
-		return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
+		    PVE::LXC::vm_start($vmid, $conf, $skiplock, $param->{debug});
+		});
 	    };
 
-	    return PVE::LXC::Config->lock_config($vmid, $lockcmd);
+	    return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
 	}
     }});
 
@@ -258,21 +257,19 @@ __PACKAGE__->register_method({
 	    my $realcmd = sub {
 		my $upid = shift;
 
-		syslog('info', "stopping CT $vmid: $upid\n");
+		PVE::LXC::Config->lock_config($vmid, sub {
+		    syslog('info', "stopping CT $vmid: $upid\n");
 
-		my $conf = PVE::LXC::Config->load_config($vmid);
-		if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
-		    PVE::LXC::Config->check_lock($conf);
-		}
+		    my $conf = PVE::LXC::Config->load_config($vmid);
+		    if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
+			PVE::LXC::Config->check_lock($conf);
+		    }
 
-		PVE::LXC::vm_stop($vmid, 1);
+		    PVE::LXC::vm_stop($vmid, 1);
+		});
 	    };
 
-	    my $lockcmd = sub {
-		return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
-	    };
-
-	    return PVE::LXC::Config->lock_config($vmid, $lockcmd);
+	    return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
 	}
     }});
 
@@ -339,19 +336,17 @@ __PACKAGE__->register_method({
 	my $realcmd = sub {
 	    my $upid = shift;
 
-	    syslog('info', "shutdown CT $vmid: $upid\n");
-
-	    my $conf = PVE::LXC::Config->load_config($vmid);
-	    PVE::LXC::Config->check_lock($conf);
+	    PVE::LXC::Config->lock_config($vmid, sub {
+		syslog('info', "shutdown CT $vmid: $upid\n");
 
-	    PVE::LXC::vm_stop($vmid, 0, $timeout, $param->{forceStop});
-	};
+		my $conf = PVE::LXC::Config->load_config($vmid);
+		PVE::LXC::Config->check_lock($conf);
 
-	my $lockcmd = sub {
-	    return $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
+		PVE::LXC::vm_stop($vmid, 0, $timeout, $param->{forceStop});
+	    });
 	};
 
-	return PVE::LXC::Config->lock_config($vmid, $lockcmd);
+	return $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
     }});
 
 __PACKAGE__->register_method({
@@ -388,20 +383,18 @@ __PACKAGE__->register_method({
 	my $realcmd = sub {
 	    my $upid = shift;
 
-	    syslog('info', "suspend CT $vmid: $upid\n");
-
-	    my $conf = PVE::LXC::Config->load_config($vmid);
-	    PVE::LXC::Config->check_lock($conf);
+	    PVE::LXC::Config->lock_config($vmid, sub {
+		syslog('info', "suspend CT $vmid: $upid\n");
 
-	    my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
-	    run_command($cmd);
-	};
+		my $conf = PVE::LXC::Config->load_config($vmid);
+		PVE::LXC::Config->check_lock($conf);
 
-	my $lockcmd = sub {
-	    return $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
+		my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
+		run_command($cmd);
+	    });
 	};
 
-	return PVE::LXC::Config->lock_config($vmid, $lockcmd);
+	return $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
     }});
 
 __PACKAGE__->register_method({
-- 
2.39.2