[Devel] [libvzctl PATCH] fast stop: suppress SUNRPC per task

Stanislav Kinsburskiy skinsbursky at virtuozzo.com
Mon Aug 21 16:18:23 MSK 2017


It solves two issues.
First, it allows to kill tasks in nested namespaces (rare, but possible case).
Second, is allows to kill CT with exited child reaper (when it's almost dead,
but waiting for it's children), because in this case SUNRPC can't be supressed
via child reapers proc dentries (/proc/pid/net is not available anymore).

https://jira.sw.ru/browse/PSBM-70437

Note: this patch reverts (replaces) commit
f8e953f5d683aa6f04dcc2b5634444b98d6e9ee3

Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
---
 lib/env_nsops.c |   81 +++++++++++++++++++++++++------------------------------
 1 file changed, 37 insertions(+), 44 deletions(-)

diff --git a/lib/env_nsops.c b/lib/env_nsops.c
index e5b662d..a565c69 100644
--- a/lib/env_nsops.c
+++ b/lib/env_nsops.c
@@ -1058,6 +1058,36 @@ static int ns_env_exec_fn(struct vzctl_env_handle *h, execFn fn, void *data,
 	return 0;
 }
 
+static int write_sunrpc_kill(pid_t pid, unsigned value)
+{
+	int fd;
+	ssize_t res;
+	char path[PATH_MAX];
+	char *val = value ? "1" : "0";

+	snprintf(path, sizeof(path), "/proc/%d/net/rpc/kill-tasks", pid);
+
+	if (access(path, F_OK))
+		return 0;
+
+	fd = open(path, O_WRONLY);
+	if (fd == -1) {
+		if (errno == ENOENT)
+			return 0;
+		return vzctl_err(-1, errno, "Failed to open %s: %s",
+				path, strerror(errno));
+	}
+
+	res = write(fd, val, strlen(val) + 1);
+	close(fd);
+
+	if (res != strlen(val) + 1)
+		return vzctl_err(-1, errno, "Unable to %s SUNRPC traffic",
+				value ? "suppress" : "release");
+
+	return 1;
+}
+
 static int ns_env_kill(struct vzctl_env_handle *h)
 {
 	int ret;
@@ -1076,6 +1106,8 @@ static int ns_env_kill(struct vzctl_env_handle *h)
 			continue;
 		}
 
+		write_sunrpc_kill(pid, 1);
+
 		logger(5, 0, "kill CT process pid %lu", pid);
 		if (kill(pid, SIGKILL) && errno != ESRCH)
 			vzctl_err(-1, errno, "Failed to kill CT pid=%lu", pid);
@@ -1086,70 +1118,31 @@ static int ns_env_kill(struct vzctl_env_handle *h)
 	return 0;
 }
 
-static int write_sunrpc_kill(struct vzctl_env_handle *h, unsigned value)
-{
-	pid_t pid;
-	int fd;
-	ssize_t res;
-	char path[PATH_MAX];
-	char *val = value ? "1" : "0";
-
-	if (cg_env_get_init_pid(h->ctid, &pid))
-		return -1;
-
-	snprintf(path, sizeof(path), "/proc/%d/net/rpc/kill-tasks", pid);
-
-	if (access(path, F_OK))
-		return 0;
-
-	fd = open(path, O_WRONLY);
-	if (fd == -1)
-		return vzctl_err(-1, errno, "Failed to open %s: %s",
-				path, strerror(errno));
-
-	res = write(fd, val, strlen(val) + 1);
-	close(fd);
-
-	if (res != strlen(val) + 1)
-		return vzctl_err(-1, errno, "Unable to %s SUNRPC traffic",
-				value ? "suppress" : "release");
-	return 1;
-}
-
 static int ns_env_stop_force(struct vzctl_env_handle *h)
 {
-	int ret, rc, sunrpc_suppressed;
-
-	sunrpc_suppressed = write_sunrpc_kill(h, 1);
+	int ret, rc;
 
 	logger(0, 0, "Forcibly stop the Container...");
 
 	ret = ns_env_kill(h);
 	if (ret)
-		goto release_sunrpc;
+		return ret;
 
 	ret = cg_freezer_cmd(EID(h), VZCTL_CMD_FREEZE);
 	if (ret)
-		goto release_sunrpc;
+		return ret;
 
 	rc = ns_env_kill(h);
 
 	/* Unfreeze unconditionally */
 	ret = cg_freezer_cmd(EID(h), VZCTL_CMD_RESUME);
-	if (ret || rc) {
-		ret = ret ?: rc;
-		goto release_sunrpc;
-	}
+	if (ret || rc)
+		return ret ?: rc;
 
 	if (wait_env_state(h, VZCTL_ENV_STOPPED, MAX_SHTD_TM))
 		return vzctl_err(-1, 0, "Failed to stop Container:"
 				" operation timed out");
 	return 0;
-
-release_sunrpc:
-	if (sunrpc_suppressed > 0)
-		(void) write_sunrpc_kill(h, 0);
-	return ret;
 }
 
 static int ns_env_cleanup(struct vzctl_env_handle *h, int flags)



More information about the Devel mailing list