From patchwork Thu Feb 10 11:07:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Cervesato X-Patchwork-Id: 1590968 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=wtR/u4qG; dkim=fail reason="signature verification failed" header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=LsjUg1w6; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JvYr92VSkz9s9c for ; Thu, 10 Feb 2022 22:07:53 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 990953C9EA6 for ; Thu, 10 Feb 2022 12:07:50 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [217.194.8.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by picard.linux.it (Postfix) with ESMTPS id 80BC03C9EA7 for ; Thu, 10 Feb 2022 12:07:15 +0100 (CET) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id 89BC1100037C for ; Thu, 10 Feb 2022 12:07:14 +0100 (CET) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 9D8971F391; Thu, 10 Feb 2022 11:07:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1644491233; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vzoLMwpFvg3y9FN8HNv0fdCW/yeREM85Wm0xwCByJg4=; b=wtR/u4qG2rDEgwsPJ47r4THcy/T+XrkUBY16JMih8W4IxfZj33WPmbij8OqfHCO+ZPEDeL V4UohZ/EA3HYjVV5EXOj4S0dUuf5QgzvW+j0F8yC7uUTFh62btkoxtVBLYjzvdM66xjN6O AUfYSXUseedAvw0KoX33jfpEcaCn+2w= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1644491233; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vzoLMwpFvg3y9FN8HNv0fdCW/yeREM85Wm0xwCByJg4=; b=LsjUg1w6aUehg+mFjZV8DFPp2TfZxwcTf9QVz5kPIwc1wHC1PUQgjiO92VZe4L4xrb+p7Z a01NuQtmCQr4/RAw== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 76FD013B43; Thu, 10 Feb 2022 11:07:13 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id CGnsGuHxBGIYAwAAMHmgww (envelope-from ); Thu, 10 Feb 2022 11:07:13 +0000 From: Andrea Cervesato To: ltp@lists.linux.it Date: Thu, 10 Feb 2022 12:07:09 +0100 Message-Id: <20220210110712.23596-2-andrea.cervesato@suse.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220210110712.23596-1-andrea.cervesato@suse.de> References: <20220210110712.23596-1-andrea.cervesato@suse.de> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.102.4 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=disabled version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on in-4.smtp.seeweb.it Subject: [LTP] [PATCH v2 1/3] Rewrite process_vm_readv02.c test with new LTP API X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Removed pipe and replaced with shared memory. Replaced TST_CHECKPOINT_INIT usage with .needs_checkpoints from the new LTP API. Signed-off-by: Andrea Cervesato --- .../kernel/syscalls/cma/process_vm_readv02.c | 215 +++++++----------- 1 file changed, 84 insertions(+), 131 deletions(-) diff --git a/testcases/kernel/syscalls/cma/process_vm_readv02.c b/testcases/kernel/syscalls/cma/process_vm_readv02.c index b705b946b..b11cffca1 100644 --- a/testcases/kernel/syscalls/cma/process_vm_readv02.c +++ b/testcases/kernel/syscalls/cma/process_vm_readv02.c @@ -1,164 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2012 * Copyright (c) Linux Test Project, 2012 + * Copyright (C) 2021 SUSE LLC Andrea Cervesato + */ + +/*\ + * [Description] * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Fork two children, one child allocates memory and initializes it; + * then the other one calls process_vm_readv and reads from the same + * memory location, it then verifies if process_vm_readv returns + * correct data. */ -#define _GNU_SOURCE +#include #include -#include #include -#include -#include -#include -#include -#include - -#include "test.h" -#include "safe_macros.h" +#include "tst_test.h" #include "lapi/syscalls.h" -char *TCID = "process_vm_readv02"; -int TST_TOTAL = 1; - -static char *tst_string = "THIS IS A TEST"; -static int len; -static int pipe_fd[2]; -static pid_t pids[2]; - -static void child_alloc(void); -static void child_invoke(void); -static void setup(void); -static void cleanup(void); +static uintptr_t *data_ptr; -int main(int argc, char **argv) -{ - int lc, status; - - tst_parse_opts(argc, argv, NULL, NULL); - - setup(); - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - len = strlen(tst_string); - - SAFE_PIPE(cleanup, pipe_fd); - - /* the start of child_alloc and child_invoke is already - * synchronized via pipe */ - pids[0] = fork(); - switch (pids[0]) { - case -1: - tst_brkm(TBROK | TERRNO, cleanup, "fork #0"); - case 0: - child_alloc(); - exit(0); - } - - pids[1] = fork(); - switch (pids[1]) { - case -1: - tst_brkm(TBROK | TERRNO, cleanup, "fork #1"); - case 0: - child_invoke(); - exit(0); - } - - /* wait until child_invoke reads from child_alloc's VM */ - SAFE_WAITPID(cleanup, pids[1], &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - tst_resm(TFAIL, "child 1 returns %d", status); - - /* child_alloc is free to exit now */ - TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); - - SAFE_WAITPID(cleanup, pids[0], &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - tst_resm(TFAIL, "child 0 returns %d", status); - } - - cleanup(); - tst_exit(); -} - -static void child_alloc(void) +static void child_alloc(const char *data) { char *foo; - char buf[BUFSIZ]; - foo = SAFE_MALLOC(tst_exit, len + 1); - strncpy(foo, tst_string, len); - foo[len] = '\0'; - tst_resm(TINFO, "child 0: memory allocated and initialized."); + foo = strdup(data); + *data_ptr = (uintptr_t)foo; - /* passing addr of string "foo" via pipe */ - SAFE_CLOSE(tst_exit, pipe_fd[0]); - snprintf(buf, BUFSIZ, "%p", foo); - SAFE_WRITE(tst_exit, 1, pipe_fd[1], buf, strlen(buf) + 1); - SAFE_CLOSE(tst_exit, pipe_fd[1]); + tst_res(TINFO, "child 0: memory allocated and initialized"); - /* wait until child_invoke is done reading from our VM */ - TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); + TST_CHECKPOINT_WAKE_AND_WAIT(0); } -static void child_invoke(void) +static void child_invoke(const char *data, int length, pid_t pid_alloc) { - char *lp, *rp; - char buf[BUFSIZ]; + char *lp; struct iovec local, remote; - /* get addr from pipe */ - SAFE_CLOSE(tst_exit, pipe_fd[1]); - SAFE_READ(tst_exit, 0, pipe_fd[0], buf, BUFSIZ); - SAFE_CLOSE(tst_exit, pipe_fd[0]); - if (sscanf(buf, "%p", &rp) != 1) - tst_brkm(TBROK | TERRNO, tst_exit, "sscanf"); - - lp = SAFE_MALLOC(tst_exit, len + 1); + lp = SAFE_MALLOC(length); local.iov_base = lp; - local.iov_len = len; - remote.iov_base = rp; - remote.iov_len = len; - - tst_resm(TINFO, "child 1: reading string from same memory location."); - TEST(tst_syscall(__NR_process_vm_readv, pids[0], - &local, 1UL, &remote, 1UL, 0UL)); - if (TEST_RETURN != len) - tst_brkm(TFAIL | TTERRNO, tst_exit, "process_vm_readv"); - if (strncmp(lp, tst_string, len) != 0) - tst_brkm(TFAIL, tst_exit, "child 1: expected string: %s, " - "received string: %256s", tst_string, lp); - else - tst_resm(TPASS, "expected string received."); + local.iov_len = length; + remote.iov_base = (void *)*data_ptr; + remote.iov_len = length; + + tst_res(TINFO, "child 1: reading string from same memory location"); + + TST_EXP_POSITIVE(tst_syscall(__NR_process_vm_readv, pid_alloc, &local, + 1UL, &remote, 1UL, 0UL)); + + if (TST_RET != length) + tst_brk(TBROK, "process_vm_readv: %s", tst_strerrno(TST_ERR)); + + if (strncmp(lp, data, length) != 0) { + tst_res(TFAIL, "child 1: expected string: %s, received string: %256s", + data, lp); + } else { + tst_res(TPASS, "expected string received"); + } } static void setup(void) { - tst_require_root(); - - /* Just a sanity check of the existence of syscall */ tst_syscall(__NR_process_vm_readv, getpid(), NULL, 0UL, NULL, 0UL, 0UL); - tst_tmpdir(); - TST_CHECKPOINT_INIT(cleanup); - - TEST_PAUSE; + data_ptr = SAFE_MMAP(NULL, sizeof(uintptr_t), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); } static void cleanup(void) { - tst_rmdir(); + if (data_ptr) + SAFE_MUNMAP(data_ptr, sizeof(uintptr_t)); +} + +static void run(void) +{ + const char *data = "test"; + pid_t pid_alloc; + pid_t pid_invoke; + int length; + int status; + + length = strlen(data); + + pid_alloc = SAFE_FORK(); + if (!pid_alloc) { + child_alloc(data); + return; + } + + TST_CHECKPOINT_WAIT(0); + + pid_invoke = SAFE_FORK(); + if (!pid_invoke) { + child_invoke(data, length, pid_alloc); + return; + } + + SAFE_WAITPID(pid_invoke, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_res(TFAIL, "child 1: %s", tst_strstatus(status)); + + TST_CHECKPOINT_WAKE(0); + + SAFE_WAITPID(pid_alloc, &status, 0); } + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .forks_child = 1, + .needs_checkpoints = 1, +}; From patchwork Thu Feb 10 11:07:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Cervesato X-Patchwork-Id: 1590967 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=rpwmHRS0; dkim=fail reason="signature verification failed" header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=2Pf3QngO; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JvYqv41fxz9s9c for ; Thu, 10 Feb 2022 22:07:39 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 0D2F03C9E96 for ; Thu, 10 Feb 2022 12:07:37 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-3.smtp.seeweb.it (in-3.smtp.seeweb.it [IPv6:2001:4b78:1:20::3]) (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 picard.linux.it (Postfix) with ESMTPS id BFD283C6D9E for ; Thu, 10 Feb 2022 12:07:15 +0100 (CET) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by in-3.smtp.seeweb.it (Postfix) with ESMTPS id 7F2B11A01441 for ; Thu, 10 Feb 2022 12:07:14 +0100 (CET) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id D2DDD1F39E; Thu, 10 Feb 2022 11:07:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1644491233; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XjbduYkzmQMXD6UTCKB0sIWR7OZyZ+dn0JR4xeO02GA=; b=rpwmHRS0nqroSKjtGj/yOP1JgXOA5w0gNL2GiN4z4/DqD7zuvCggC4XXtT+Bt8d3xLyCAA 95qr9Pyk5xJYZngN/tsp2pdYuOIKeBbHR0T3V05pGbvB8m3IErC9iuZUBZFLRg6tmAhMS+ LX/LD9TtaYKi3XehG4EBk69YuPZwFes= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1644491233; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XjbduYkzmQMXD6UTCKB0sIWR7OZyZ+dn0JR4xeO02GA=; b=2Pf3QngOsjAfGoRIjNVisjhTzNkpNhJxwifLVEuQ+X5GN5fB7Y8u8hIVQGVHo60VQQb3LO BOVwYPp9ez7yZQBQ== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id A9E6A13B43; Thu, 10 Feb 2022 11:07:13 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 2DdpJ+HxBGIYAwAAMHmgww (envelope-from ); Thu, 10 Feb 2022 11:07:13 +0000 From: Andrea Cervesato To: ltp@lists.linux.it Date: Thu, 10 Feb 2022 12:07:10 +0100 Message-Id: <20220210110712.23596-3-andrea.cervesato@suse.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220210110712.23596-1-andrea.cervesato@suse.de> References: <20220210110712.23596-1-andrea.cervesato@suse.de> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.102.4 at in-3.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=disabled version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on in-3.smtp.seeweb.it Subject: [LTP] [PATCH v2 2/3] Rewrite process_vm_readv03.c test with new LTP API X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Removed pipe and replaced it with shared memory. Replaced TST_CHECKPOINT_INIT usage with .needs_checkpoints from the new LTP API. Signed-off-by: Andrea Cervesato --- .../kernel/syscalls/cma/process_vm_readv03.c | 349 ++++++++---------- 1 file changed, 146 insertions(+), 203 deletions(-) diff --git a/testcases/kernel/syscalls/cma/process_vm_readv03.c b/testcases/kernel/syscalls/cma/process_vm_readv03.c index 2333f7fd6..91961770f 100644 --- a/testcases/kernel/syscalls/cma/process_vm_readv03.c +++ b/testcases/kernel/syscalls/cma/process_vm_readv03.c @@ -1,274 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2012 * Copyright (c) Linux Test Project, 2012 + * Copyright (C) 2021 SUSE LLC Andrea Cervesato + */ + +/*\ + * [Description] * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Fork two children, one child mallocs randomly sized trunks of memory + * and initializes them; the other child calls process_vm_readv with + * the remote iovecs initialized to the original process memory + * locations and the local iovecs initialized to randomly sized and + * allocated local memory locations. The second child then verifies + * that the data copied is correct. */ -#define _GNU_SOURCE -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include - -#include "test.h" -#include "safe_macros.h" +#include +#include +#include "tst_test.h" #include "lapi/syscalls.h" -char *TCID = "process_vm_readv03"; -int TST_TOTAL = 1; - -#define NUM_LOCAL_VECS 4 - -static int nflag, sflag; -static char *nr_opt, *sz_opt; -static option_t options[] = { - {"n:", &nflag, &nr_opt}, - {"s:", &sflag, &sz_opt}, - {NULL, NULL, NULL} +static struct tcase { + int bufsize; + int remote_iovecs; + int local_iovecs; +} testcases[] = { + { .bufsize = 1024, .remote_iovecs = 1024, .local_iovecs = 8 }, + { .bufsize = 1024, .remote_iovecs = 512, .local_iovecs = 16 }, + { .bufsize = 1024, .remote_iovecs = 256, .local_iovecs = 32 }, + { .bufsize = 1024, .remote_iovecs = 128, .local_iovecs = 64 }, + { .bufsize = 1024, .remote_iovecs = 64, .local_iovecs = 128 }, + { .bufsize = 1024, .remote_iovecs = 32, .local_iovecs = 256 }, + { .bufsize = 1024, .remote_iovecs = 16, .local_iovecs = 512 }, + { .bufsize = 1024, .remote_iovecs = 8, .local_iovecs = 1024 }, + + { .bufsize = 131072, .remote_iovecs = 1024, .local_iovecs = 8 }, + { .bufsize = 131072, .remote_iovecs = 512, .local_iovecs = 16 }, + { .bufsize = 131072, .remote_iovecs = 256, .local_iovecs = 32 }, + { .bufsize = 131072, .remote_iovecs = 128, .local_iovecs = 64 }, + { .bufsize = 131072, .remote_iovecs = 64, .local_iovecs = 128 }, + { .bufsize = 131072, .remote_iovecs = 32, .local_iovecs = 256 }, + { .bufsize = 131072, .remote_iovecs = 16, .local_iovecs = 512 }, + { .bufsize = 131072, .remote_iovecs = 8, .local_iovecs = 1024 }, }; -static int nr_iovecs; -static long bufsz; -static int pipe_fd[2]; -static pid_t pids[2]; - -static void gen_random_arr(int *arr, int arr_sz); -static void child_alloc(int *bufsz_arr); -static void child_invoke(int *bufsz_arr); -static long *fetch_remote_addrs(void); -static void setup(void); -static void cleanup(void); -static void help(void); - -int main(int argc, char **argv) -{ - int lc, status; - int *bufsz_arr; - - tst_parse_opts(argc, argv, options, &help); - - setup(); - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - SAFE_PIPE(cleanup, pipe_fd); - - bufsz_arr = SAFE_MALLOC(cleanup, nr_iovecs * sizeof(int)); - gen_random_arr(bufsz_arr, nr_iovecs); - - /* the start of child_alloc and child_invoke is already - * synchronized via pipe */ - pids[0] = fork(); - switch (pids[0]) { - case -1: - tst_brkm(TBROK | TERRNO, cleanup, "fork #0"); - case 0: - child_alloc(bufsz_arr); - exit(0); - } - - pids[1] = fork(); - switch (pids[1]) { - case -1: - tst_brkm(TBROK | TERRNO, cleanup, "fork #1"); - case 0: - child_invoke(bufsz_arr); - exit(0); - } - - /* wait until child_invoke reads from child_alloc's VM */ - SAFE_WAITPID(cleanup, pids[1], &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - tst_resm(TFAIL, "child 1 returns %d", status); - - /* child_alloc is free to exit now */ - TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); - - SAFE_WAITPID(cleanup, pids[0], &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - tst_resm(TFAIL, "child 0 returns %d", status); - - free(bufsz_arr); - } - - cleanup(); - tst_exit(); -} +static uintptr_t *data_ptr; +static long *addr_ptr; -static void gen_random_arr(int *arr, int arr_sz) +static void create_data_size(int *arr, int arr_sz, int buffsize) { - long bufsz_left, bufsz_single; + long bufsz_left; int i; - bufsz_left = bufsz; + bufsz_left = buffsize; for (i = 0; i < arr_sz - 1; i++) { - bufsz_single = rand() % (bufsz_left / 2) + 1; - arr[i] = bufsz_single; - bufsz_left -= bufsz_single; + int mod = MAX(1, (bufsz_left - arr_sz) / 2); + + arr[i] = rand() % mod + 1; + bufsz_left -= arr[i]; } + arr[arr_sz - 1] = bufsz_left; } -static void child_alloc(int *bufsz_arr) +static void child_alloc(const int *sizes, int nr_iovecs) { char **foo; int i, j; - char buf[BUFSIZ]; long count; - foo = SAFE_MALLOC(tst_exit, nr_iovecs * sizeof(char *)); + foo = SAFE_MALLOC(nr_iovecs * sizeof(char *)); count = 0; for (i = 0; i < nr_iovecs; i++) { - foo[i] = SAFE_MALLOC(tst_exit, bufsz_arr[i]); - for (j = 0; j < bufsz_arr[i]; j++) { + foo[i] = SAFE_MALLOC(sizes[i]); + addr_ptr[i] = (long)foo[i]; + + for (j = 0; j < sizes[i]; j++) { foo[i][j] = count % 256; count++; } } - tst_resm(TINFO, "child 0: %d iovecs allocated and initialized.", - nr_iovecs); - /* passing addr via pipe */ - SAFE_CLOSE(tst_exit, pipe_fd[0]); - snprintf(buf, BUFSIZ, "%p", (void *)foo); - SAFE_WRITE(tst_exit, 1, pipe_fd[1], buf, strlen(buf) + 1); - SAFE_CLOSE(tst_exit, pipe_fd[1]); + *data_ptr = (uintptr_t)foo; - /* wait until child_invoke is done reading from our VM */ - TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); -} + tst_res(TINFO, "child 0: memory allocated and initialized"); -static long *fetch_remote_addrs(void) -{ - long *foo, *bar; - char buf[BUFSIZ]; - long len; - struct iovec local, remote; - - /* get addr from pipe */ - SAFE_CLOSE(tst_exit, pipe_fd[1]); - SAFE_READ(tst_exit, 0, pipe_fd[0], buf, BUFSIZ); - SAFE_CLOSE(tst_exit, pipe_fd[0]); - if (sscanf(buf, "%p", &foo) != 1) - tst_brkm(TBROK | TERRNO, tst_exit, "sscanf"); - - len = nr_iovecs * sizeof(long); - bar = SAFE_MALLOC(tst_exit, len); - local.iov_base = bar; - local.iov_len = len; - remote.iov_base = foo; - remote.iov_len = len; - - TEST(tst_syscall(__NR_process_vm_readv, pids[0], &local, - 1UL, &remote, 1UL, 0UL)); - if (TEST_RETURN != len) - tst_brkm(TFAIL | TTERRNO, tst_exit, "process_vm_readv"); - - return local.iov_base; + TST_CHECKPOINT_WAKE_AND_WAIT(0); } -static void child_invoke(int *bufsz_arr) +static void child_invoke(const int *sizes, int local_iovecs, int remote_iovecs, + pid_t pid_alloc, int buffsize) { - int i, j, count, nr_error; + struct iovec local[local_iovecs]; + struct iovec remote[remote_iovecs]; + int i, j; + int count; + int nr_error; + int *local_sizes; unsigned char expect, actual; - long *addrs; - struct iovec local[NUM_LOCAL_VECS], *remote; - int rcv_arr[NUM_LOCAL_VECS]; - addrs = fetch_remote_addrs(); - - remote = SAFE_MALLOC(tst_exit, nr_iovecs * sizeof(struct iovec)); - for (i = 0; i < nr_iovecs; i++) { - remote[i].iov_base = (void *)addrs[i]; - remote[i].iov_len = bufsz_arr[i]; + for (i = 0; i < remote_iovecs; i++) { + remote[i].iov_base = (void *)addr_ptr[i]; + remote[i].iov_len = sizes[i]; } - tst_resm(TINFO, "child 1: %d remote iovecs received.", nr_iovecs); - gen_random_arr(rcv_arr, NUM_LOCAL_VECS); - for (i = 0; i < NUM_LOCAL_VECS; i++) { - local[i].iov_base = SAFE_MALLOC(tst_exit, rcv_arr[i]); - local[i].iov_len = rcv_arr[i]; + local_sizes = SAFE_MALLOC(local_iovecs * sizeof(int)); + create_data_size(local_sizes, local_iovecs, buffsize); + for (i = 0; i < local_iovecs; i++) { + local[i].iov_base = SAFE_MALLOC(local_sizes[i]); + local[i].iov_len = local_sizes[i]; } - tst_resm(TINFO, "child 1: %d local iovecs initialized.", - NUM_LOCAL_VECS); - TEST(tst_syscall(__NR_process_vm_readv, pids[0], local, - (unsigned long)NUM_LOCAL_VECS, remote, - (unsigned long)nr_iovecs, 0UL)); - if (TEST_RETURN != bufsz) - tst_brkm(TBROK | TTERRNO, tst_exit, "process_vm_readv"); + tst_res(TINFO, "child 1: reading string from same memory location"); + + TST_EXP_POSITIVE(tst_syscall(__NR_process_vm_readv, pid_alloc, local, + local_iovecs, remote, remote_iovecs, 0UL)); + + if (TST_RET != buffsize) { + tst_brk(TBROK, "process_vm_readv: expected %d bytes but got %ld", + buffsize, TST_RET); + } - /* verify every byte */ count = 0; nr_error = 0; - for (i = 0; i < NUM_LOCAL_VECS; i++) { + for (i = 0; i < local_iovecs; i++) { for (j = 0; j < (int)local[i].iov_len; j++) { expect = count % 256; actual = ((unsigned char *)local[i].iov_base)[j]; - if (expect != actual) { -#if DEBUG - tst_resm(TFAIL, "child 1: expected %i, got %i " - "for byte seq %d", - expect, actual, count); -#endif + if (expect != actual) nr_error++; - } + count++; } } + if (nr_error) - tst_brkm(TFAIL, tst_exit, "child 1: %d incorrect bytes " - "received.", nr_error); + tst_brk(TFAIL, "child 1: %d incorrect bytes received", nr_error); else - tst_resm(TPASS, "child 1: all bytes are correctly received."); + tst_res(TPASS, "child 1: all bytes are correctly received"); } static void setup(void) { - tst_require_root(); - - /* Just a sanity check of the existence of syscall */ tst_syscall(__NR_process_vm_readv, getpid(), NULL, 0UL, NULL, 0UL, 0UL); - nr_iovecs = nflag ? SAFE_STRTOL(NULL, nr_opt, 1, IOV_MAX) : 10; - bufsz = sflag ? SAFE_STRTOL(NULL, sz_opt, NUM_LOCAL_VECS, LONG_MAX) - : 100000; - - tst_tmpdir(); - TST_CHECKPOINT_INIT(cleanup); - srand(time(NULL)); - - TEST_PAUSE; + data_ptr = SAFE_MMAP(NULL, sizeof(uintptr_t), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); } static void cleanup(void) { - tst_rmdir(); + if (data_ptr) + SAFE_MUNMAP(data_ptr, sizeof(uintptr_t)); + + if (addr_ptr) + SAFE_MUNMAP(addr_ptr, sizeof(uintptr_t)); } -static void help(void) +static void run(unsigned int i) { - printf(" -n NUM Set the number of iovecs to be allocated.\n"); - printf(" -s NUM Set the size of total buffer size.\n"); + int bufsize = testcases[i].bufsize; + int remote_iovecs = testcases[i].remote_iovecs; + int local_iovecs = testcases[i].local_iovecs; + pid_t pid_alloc; + pid_t pid_invoke; + int status; + int *sizes; + + tst_res(TINFO, "bufsize=%d, remote_iovecs=%d, local_iovecs=%d", bufsize, + remote_iovecs, local_iovecs); + + addr_ptr = SAFE_MMAP(NULL, sizeof(long) * remote_iovecs, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + + sizes = SAFE_MALLOC(remote_iovecs * sizeof(int)); + create_data_size(sizes, remote_iovecs, bufsize); + + pid_alloc = SAFE_FORK(); + if (!pid_alloc) { + child_alloc(sizes, remote_iovecs); + return; + } + + TST_CHECKPOINT_WAIT(0); + + pid_invoke = SAFE_FORK(); + if (!pid_invoke) { + child_invoke(sizes, local_iovecs, remote_iovecs, pid_alloc, bufsize); + return; + } + + SAFE_WAITPID(pid_invoke, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_res(TFAIL, "child 1: returns %s", tst_strstatus(status)); + + TST_CHECKPOINT_WAKE(0); + + SAFE_WAITPID(pid_alloc, &status, 0); + + if (addr_ptr) + SAFE_MUNMAP(addr_ptr, sizeof(uintptr_t)); } + +static struct tst_test test = { + .test = run, + .setup = setup, + .cleanup = cleanup, + .forks_child = 1, + .needs_checkpoints = 1, + .tcnt = ARRAY_SIZE(testcases), + .min_kver = "2.0", +}; From patchwork Thu Feb 10 11:07:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Cervesato X-Patchwork-Id: 1590966 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=VRlhNXnc; dkim=fail reason="signature verification failed" header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=XqoSLOc6; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JvYql56fsz9s9c for ; Thu, 10 Feb 2022 22:07:31 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 7EE6C3C9E24 for ; Thu, 10 Feb 2022 12:07:27 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-5.smtp.seeweb.it (in-5.smtp.seeweb.it [IPv6:2001:4b78:1:20::5]) (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 picard.linux.it (Postfix) with ESMTPS id 4F44A3C9C7F for ; Thu, 10 Feb 2022 12:07:15 +0100 (CET) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by in-5.smtp.seeweb.it (Postfix) with ESMTPS id 8911D600079 for ; Thu, 10 Feb 2022 12:07:14 +0100 (CET) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 151D21F3A1; Thu, 10 Feb 2022 11:07:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1644491234; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hyfWoK/8+T/qTmCW7DqKa2UkFf7kHYXSUEMK+mJkXm4=; b=VRlhNXnc/S8y7jIE7yfDggCSLaoZ2nNlO+LY0oYvvAYTa0CVFG3HM6zALXAU2K3RDbZsIp LvFLAdp3LcDXKU913kkxq9vYtP12dT2yzOTXGLU6nxesEcFkpx1NEljpFdyn8q7GRNvBA5 tfXF5loN2E3mwF09tBgsfYVeoIDcKDc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1644491234; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hyfWoK/8+T/qTmCW7DqKa2UkFf7kHYXSUEMK+mJkXm4=; b=XqoSLOc6iBp9sZjwuLtLEhzkkikTGTQXj67BdTAdyd9bOolsR1LtgctbLFvMXF0Khm06H/ lv7zGKmAQna62RAA== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id DF0FC13B43; Thu, 10 Feb 2022 11:07:13 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 6FRwNOHxBGIYAwAAMHmgww (envelope-from ); Thu, 10 Feb 2022 11:07:13 +0000 From: Andrea Cervesato To: ltp@lists.linux.it Date: Thu, 10 Feb 2022 12:07:11 +0100 Message-Id: <20220210110712.23596-4-andrea.cervesato@suse.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220210110712.23596-1-andrea.cervesato@suse.de> References: <20220210110712.23596-1-andrea.cervesato@suse.de> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.102.4 at in-5.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=disabled version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on in-5.smtp.seeweb.it Subject: [LTP] [PATCH v2 3/3] Rewrite process_vm_writev02.c using new LTP API X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Removed pipe and replaced it with shared memory. Replaced TST_CHECKPOINT_INIT usage with .needs_checkpoints from the new LTP API. Signed-off-by: Andrea Cervesato --- .../kernel/syscalls/cma/process_vm_writev02.c | 263 +++++++----------- 1 file changed, 94 insertions(+), 169 deletions(-) diff --git a/testcases/kernel/syscalls/cma/process_vm_writev02.c b/testcases/kernel/syscalls/cma/process_vm_writev02.c index e70ead4ed..b535a8ff1 100644 --- a/testcases/kernel/syscalls/cma/process_vm_writev02.c +++ b/testcases/kernel/syscalls/cma/process_vm_writev02.c @@ -1,205 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2012 * Copyright (c) Linux Test Project, 2012 + * Copyright (C) 2021 SUSE LLC Andrea Cervesato + */ + +/*\ + * [Description] * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Fork two children, the first one allocates a chunk of memory and the + * other one call process_vm_writev to write known data into the first + * child. Then first child verifies that the data is as expected. */ -#define _GNU_SOURCE +#include #include #include -#include -#include -#include -#include -#include -#include -#include - -#include "test.h" -#include "safe_macros.h" +#include "tst_test.h" #include "lapi/syscalls.h" -char *TCID = "process_vm_writev02"; -int TST_TOTAL = 1; - -#define PADDING_SIZE 10 -#define DEFAULT_CHAR 53 +static uintptr_t *data_ptr; +static char *str_buffsize; +static int bufsize = 100000; -static int sflag; -static char *sz_opt; -static option_t options[] = { - {"s:", &sflag, &sz_opt}, - {NULL, NULL, NULL} -}; +static void child_alloc_and_verify(int buffsize) +{ + char foo[buffsize]; + int i; + int err; -static long bufsz; -static int pipe_fd[2]; -static pid_t pids[2]; + tst_res(TINFO, "child 0: allocate memory"); -static void child_init_and_verify(void); -static void child_write(void); -static void setup(void); -static void cleanup(void); -static void help(void); + memset(foo, 'a', buffsize); + *data_ptr = (uintptr_t)foo; -int main(int argc, char **argv) -{ - int lc, status; - - tst_parse_opts(argc, argv, options, &help); - - setup(); - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - SAFE_PIPE(cleanup, pipe_fd); - - /* the start of child_init_and_verify and child_write is - * already synchronized via pipe */ - pids[0] = fork(); - switch (pids[0]) { - case -1: - tst_brkm(TBROK | TERRNO, cleanup, "fork #0"); - case 0: - child_init_and_verify(); - exit(0); - default: - break; - } - - pids[1] = fork(); - switch (pids[1]) { - case -1: - tst_brkm(TBROK | TERRNO, cleanup, "fork #1"); - case 0: - child_write(); - exit(0); - } - - /* wait until child_write writes into - * child_init_and_verify's VM */ - SAFE_WAITPID(cleanup, pids[1], &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - tst_resm(TFAIL, "child 1 returns %d", status); - - /* signal child_init_and_verify to verify its VM now */ - TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); - - SAFE_WAITPID(cleanup, pids[0], &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - tst_resm(TFAIL, "child 0 returns %d", status); - } + TST_CHECKPOINT_WAKE_AND_WAIT(0); - cleanup(); - tst_exit(); -} + err = 0; + for (i = 0; i < buffsize; i++) + if (foo[i] != 'w') + err++; -static void child_init_and_verify(void) -{ - unsigned char *foo; - char buf[bufsz]; - long i, nr_err; - - foo = SAFE_MALLOC(tst_exit, bufsz); - for (i = 0; i < bufsz; i++) - foo[i] = DEFAULT_CHAR; - tst_resm(TINFO, "child 0: memory allocated."); - - /* passing addr of string "foo" via pipe */ - SAFE_CLOSE(tst_exit, pipe_fd[0]); - snprintf(buf, bufsz, "%p", foo); - SAFE_WRITE(tst_exit, 1, pipe_fd[1], buf, strlen(buf) + 1); - SAFE_CLOSE(tst_exit, pipe_fd[1]); - - /* wait until child_write() is done writing to our VM */ - TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); - - nr_err = 0; - for (i = 0; i < bufsz; i++) { - if (foo[i] != i % 256) { -#if DEBUG - tst_resm(TFAIL, "child 0: expected %i, got %i for " - "byte seq %ld", i % 256, foo[i], i); -#endif - nr_err++; - } - } - if (nr_err) - tst_brkm(TFAIL, tst_exit, "child 0: got %ld incorrect bytes.", - nr_err); + if (err) + tst_res(TFAIL, "child 0: found %d differences from expected data", err); else - tst_resm(TPASS, "child 0: all bytes are expected."); + tst_res(TPASS, "child 0: read back expected data"); } -static void child_write(void) +static void child_write(int buffsize, pid_t pid_alloc) { - unsigned char *lp, *rp; - char buf[bufsz]; + char lp[buffsize]; struct iovec local, remote; - long i; - - /* get addr from pipe */ - SAFE_CLOSE(tst_exit, pipe_fd[1]); - SAFE_READ(tst_exit, 0, pipe_fd[0], buf, bufsz); - SAFE_CLOSE(tst_exit, pipe_fd[0]); - if (sscanf(buf, "%p", &rp) != 1) - tst_brkm(TBROK | TERRNO, tst_exit, "sscanf"); - - lp = SAFE_MALLOC(tst_exit, bufsz + PADDING_SIZE * 2); - - for (i = 0; i < bufsz + PADDING_SIZE * 2; i++) - lp[i] = DEFAULT_CHAR; - for (i = 0; i < bufsz; i++) - lp[i + PADDING_SIZE] = i % 256; - - local.iov_base = lp + PADDING_SIZE; - local.iov_len = bufsz; - remote.iov_base = rp; - remote.iov_len = bufsz; - - tst_resm(TINFO, "child 2: write to the same memory location."); - TEST(tst_syscall(__NR_process_vm_writev, pids[0], &local, - 1UL, &remote, 1UL, 0UL)); - if (TEST_RETURN != bufsz) - tst_brkm(TFAIL | TTERRNO, tst_exit, "process_vm_readv"); + + tst_res(TINFO, "child 1: write to the same memory location"); + + memset(lp, 'w', buffsize); + + local.iov_base = lp; + local.iov_len = buffsize; + remote.iov_base = (void *)*data_ptr; + remote.iov_len = buffsize; + + TST_EXP_POSITIVE(tst_syscall(__NR_process_vm_writev, pid_alloc, &local, + 1UL, &remote, 1UL, 0UL)); + + if (TST_RET != buffsize) { + tst_brk(TBROK, "process_vm_writev: expected %d bytes but got %ld", + buffsize, TST_RET); + } } static void setup(void) { - tst_require_root(); - - /* Just a sanity check of the existence of syscall */ tst_syscall(__NR_process_vm_writev, getpid(), NULL, 0UL, NULL, 0UL, 0UL); - bufsz = - sflag ? SAFE_STRTOL(NULL, sz_opt, 1, LONG_MAX - PADDING_SIZE * 2) - : 100000; + if (tst_parse_int(str_buffsize, &bufsize, 1, INT_MAX)) + tst_brk(TBROK, "Invalid buffer size '%s'", str_buffsize); - tst_tmpdir(); - TST_CHECKPOINT_INIT(cleanup); - - TEST_PAUSE; + data_ptr = SAFE_MMAP(NULL, sizeof(uintptr_t), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); } static void cleanup(void) { - tst_rmdir(); + if (data_ptr) + SAFE_MUNMAP(data_ptr, sizeof(uintptr_t)); } -static void help(void) +static void run(void) { - printf(" -s NUM Set the size of total buffer size.\n"); + pid_t pid_alloc; + pid_t pid_write; + int status; + + pid_alloc = SAFE_FORK(); + if (!pid_alloc) { + child_alloc_and_verify(bufsize); + return; + } + + TST_CHECKPOINT_WAIT(0); + + pid_write = SAFE_FORK(); + if (!pid_write) { + child_write(bufsize, pid_alloc); + return; + } + + SAFE_WAITPID(pid_write, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_res(TFAIL, "child 1: returns %s", tst_strstatus(status)); + + TST_CHECKPOINT_WAKE(0); + + SAFE_WAITPID(pid_alloc, &status, 0); } + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .forks_child = 1, + .needs_checkpoints = 1, + .options = + (struct tst_option[]){ + { "s:", &str_buffsize, "Total buffer size (default 100000)" }, + {}, + }, +};