From patchwork Fri Mar 12 12:02:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yang Xu X-Patchwork-Id: 1451950 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 ozlabs.org (Postfix) with ESMTPS id 4DxkwX5fwNz9sS8 for ; Fri, 12 Mar 2021 23:03:08 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 6C5B23C685A for ; Fri, 12 Mar 2021 13:03:05 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-7.smtp.seeweb.it (in-7.smtp.seeweb.it [217.194.8.7]) by picard.linux.it (Postfix) with ESMTP id 6518F3C682A for ; Fri, 12 Mar 2021 13:03:03 +0100 (CET) Received: from heian.cn.fujitsu.com (mail.cn.fujitsu.com [183.91.158.132]) by in-7.smtp.seeweb.it (Postfix) with ESMTP id 50DC1200B00 for ; Fri, 12 Mar 2021 13:03:00 +0100 (CET) IronPort-HdrOrdr: A9a23:C6lAramweEcd2t7WUrpEPvXT4i3pDfLM3DAbvn1ZSRFFG/GwvcaogfgdyFvImC8cMUtQ/eyoFYuhZTfn9ZBz6ZQMJrvKZmTbkUahMY0K1+Xf6hLtFyD0/uRekYdMGpIVNPTeFl5/5Pya3CCdM/INhOaK67qpg+C29QYJcShPZ7t75wl0Tia3e3cGJzVuPpYyGJqC6scvnVPJFkg/VNixBXUOQoH41r/2va/hCCRnOzcXrCGKjR6NrIXxCgWk2H4lOA9n8PMP9nfknmXCipmejw== X-IronPort-AV: E=Sophos;i="5.81,243,1610380800"; d="scan'208";a="105549603" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 12 Mar 2021 20:02:59 +0800 Received: from G08CNEXMBPEKD04.g08.fujitsu.local (unknown [10.167.33.201]) by cn.fujitsu.com (Postfix) with ESMTP id CA3D34CEA98A for ; Fri, 12 Mar 2021 20:02:58 +0800 (CST) Received: from localhost.localdomain (10.167.220.84) by G08CNEXMBPEKD04.g08.fujitsu.local (10.167.33.201) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 12 Mar 2021 20:02:59 +0800 From: Yang Xu To: Date: Fri, 12 Mar 2021 20:02:20 +0800 Message-ID: <1615550541-21714-4-git-send-email-xuyang2018.jy@cn.fujitsu.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1615550541-21714-1-git-send-email-xuyang2018.jy@cn.fujitsu.com> References: <20201111163114.GB23576@yuki.lan> <1615550541-21714-1-git-send-email-xuyang2018.jy@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.220.84] X-ClientProxiedBy: G08CNEXCHPEKD06.g08.fujitsu.local (10.167.33.205) To G08CNEXMBPEKD04.g08.fujitsu.local (10.167.33.201) X-yoursite-MailScanner-ID: CA3D34CEA98A.A3C36 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: xuyang2018.jy@cn.fujitsu.com X-Spam-Status: No, score=0.1 required=7.0 tests=KHOP_HELO_FCRDNS, SPF_HELO_NONE, SPF_NONE autolearn=disabled version=3.4.4 X-Virus-Scanned: clamav-milter 0.102.4 at in-7.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on in-7.smtp.seeweb.it Subject: [LTP] [PATCH v4 4/5] sycalls/msgstress04: Convert into new 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" It also missed process num check according to available memory. Signed-off-by: Yang Xu --- .../kernel/syscalls/ipc/msgstress/Makefile | 5 +- .../syscalls/ipc/msgstress/msgstress04.c | 489 +++++------------- 2 files changed, 142 insertions(+), 352 deletions(-) diff --git a/testcases/kernel/syscalls/ipc/msgstress/Makefile b/testcases/kernel/syscalls/ipc/msgstress/Makefile index d80d0bf98..b1201281d 100644 --- a/testcases/kernel/syscalls/ipc/msgstress/Makefile +++ b/testcases/kernel/syscalls/ipc/msgstress/Makefile @@ -3,11 +3,10 @@ top_srcdir ?= ../../../../.. -LTPLIBS = ltpipc ltpnewipc +LTPLIBS = ltpnewipc include $(top_srcdir)/include/mk/testcases.mk -msgstress01 msgstress02: LTPLDLIBS = -lltpnewipc -msgstress04: LTPLDLIBS = -lltpipc +LTPLDLIBS = -lltpnewipc include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c index f1c124990..b6536e349 100644 --- a/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c +++ b/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c @@ -1,30 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2002 * - * 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 - * * 06/30/2001 Port to Linux nsharoff@us.ibm.com * 11/11/2002 Port to LTP dbarrera@us.ibm.com + * 03/12/2021 Convert to new api xuyang2018.jy@cn.fujitsu.com */ -/* +/*\ + * [DESCRIPTION] + * * Get and manipulate a message queue. - * Same as msgstress02 but gets the actual msgmni value under procfs. - */ + * Fork a number of processes, each of which will create a message queue + * with several (nkids) reader/writer pairs which will read and write a + * number (iterations) of random length messages with specific values (keys). + * We do not fork more than maxnprocs at a time and we fork until all the + * message queues get used. +\*/ -#define _XOPEN_SOURCE 500 #include #include #include @@ -36,415 +29,213 @@ #include #include #include -#include "test.h" -#include "ipcmsg.h" -#include "libmsgctl.h" - -char *TCID = "msgstress04"; -int TST_TOTAL = 1; +#include "tst_test.h" +#include "libnewipc.h" +#include "tst_safe_sysv_ipc.h" -#define MAXNREPS 1000 -#ifndef CONFIG_COLDFIRE -#define MAXNPROCS 1000000 /* This value is set to an arbitrary high limit. */ -#else -#define MAXNPROCS 100000 /* Coldfire can't deal with 1000000 */ -#endif #define MAXNKIDS 10 -#define DEFNKIDS 2 -static int maxnkids = MAXNKIDS; /* Used if pid_max is exceeded */ -static key_t keyarray[MAXNPROCS]; -static int pidarray[MAXNPROCS]; static int rkidarray[MAXNKIDS]; static int wkidarray[MAXNKIDS]; -static int tid; -static int nprocs, nreps, nkids, MSGMNI; -static int maxnprocs; -static int procstat; - -void setup(void); -void cleanup(void); - -static void term(int); -static int dotest(key_t, int); -static void dotest_iteration(int off); -static void cleanup_msgqueue(int i, int tid); - +static int tid[MAXNPROCS]; +static int maxnprocs = MAXNPROCS; +static int nreps = 1000; +static int nkids = MAXNKIDS; +static int MSGMNI, nprocs; static char *opt_maxnprocs; static char *opt_nkids; static char *opt_nreps; -static option_t options[] = { - {"n:", NULL, &opt_maxnprocs}, - {"c:", NULL, &opt_nkids}, - {"l:", NULL, &opt_nreps}, - {NULL, NULL, NULL}, +static struct tst_option options[] = { + {"n:", &opt_maxnprocs, "-n N Number of processes"}, + {"c:", &opt_nkids, "-c -N Number of read/write child pairs"}, + {"l:", &opt_nreps, "-l N Number of iterations"}, + {NULL, NULL, NULL} }; -static void usage(void) -{ - printf(" -n Number of processes\n"); - printf(" -c Number of read/write child pairs\n"); - printf(" -l Number of iterations\n"); -} - - -int main(int argc, char **argv) -{ - int i, j, ok; - - tst_parse_opts(argc, argv, options, usage); - - setup(); - - nreps = MAXNREPS; - nkids = MAXNKIDS; - - if (opt_nreps) { - nreps = atoi(opt_nreps); - if (nreps > MAXNREPS) { - tst_resm(TINFO, - "Requested number of iterations too large, " - "setting to Max. of %d", MAXNREPS); - nreps = MAXNREPS; - } - } - - if (opt_nkids) { - nkids = atoi(opt_nkids); - if (nkids > MAXNKIDS) { - tst_resm(TINFO, - "Requested number of read/write pairs too " - "large, setting to Max. of %d", MAXNKIDS); - nkids = MAXNKIDS; - } - } - - - if (opt_maxnprocs) { - if (atoi(opt_maxnprocs) > maxnprocs) { - tst_resm(TINFO, - "Requested number of processes too large, " - "setting to Max. of %d", MSGMNI); - } else { - maxnprocs = atoi(opt_maxnprocs); - } - } - - procstat = 0; - srand48((unsigned)getpid() + (unsigned)(getppid() << 16)); - tid = -1; - - /* Setup signal handling routine */ - if (sigset(SIGTERM, term) == SIG_ERR) - tst_brkm(TFAIL, cleanup, "Sigset SIGTERM failed"); - - /* Set up array of unique keys for use in allocating message - * queues - */ - for (i = 0; i < MSGMNI; i++) { - ok = 1; - do { - /* Get random key */ - keyarray[i] = (key_t) lrand48(); - /* Make sure key is unique and not private */ - if (keyarray[i] == IPC_PRIVATE) { - ok = 0; - continue; - } - for (j = 0; j < i; j++) { - if (keyarray[j] == keyarray[i]) { - ok = 0; - break; - } - ok = 1; - } - } while (ok == 0); - } - /* Fork a number of processes, each of which will - * create a message queue with several (nkids) reader/writer - * pairs which will read and write a number (iterations) - * of random length messages with specific values (keys). - * - * We do not fork more than maxnprocs at a time and - * we fork until all the message queues get used. - */ - - if (MSGMNI <= maxnprocs) { - nprocs = MSGMNI; - dotest_iteration(0); - } else { - for (i = 0; i < (MSGMNI / maxnprocs); i++) { - nprocs = maxnprocs; - dotest_iteration(i * maxnprocs); - } - - nprocs = MSGMNI % maxnprocs; - dotest_iteration(i * maxnprocs); - } - - tst_resm(TPASS, "Test ran successfully!"); - - cleanup(); - tst_exit(); -} - -static void dotest_iteration(int off) -{ - key_t key; - int i, count, status; - pid_t pid; - - memset(pidarray, 0, sizeof(pidarray)); - - for (i = 0; i < nprocs; i++) { - key = keyarray[off + i]; - - if ((pid = FORK_OR_VFORK()) < 0) - tst_brkm(TFAIL, cleanup, - "Fork failed (may be OK if under stress)"); - - /* Child does this */ - if (pid == 0) { - procstat = 1; - exit(dotest(key, i)); - } - pidarray[i] = pid; - } - - count = 0; - while (1) { - if ((wait(&status)) > 0) { - if (status >> 8 != PASS) - tst_brkm(TFAIL, cleanup, - "Child exit status = %d", status >> 8); - count++; - } else { - if (errno != EINTR) { - break; - } -#ifdef DEBUG - tst_resm(TINFO, "Signal detected during wait"); -#endif - } - } - /* Make sure proper number of children exited */ - if (count != nprocs) - tst_brkm(TFAIL, cleanup, - "Wrong number of children exited, Saw %d, Expected %d", - count, nprocs); -} - -static void cleanup_msgqueue(int i, int tid) +static void cleanup_msgqueue(int i, int id) { /* - * Decrease the value of i by 1 because it - * is getting incremented even if the fork - * is failing. + * Decrease the value of i by 1 because it is getting incremented + * even if the fork is failing. */ - i--; - /* - * Kill all children & free message queue. - */ + /* Kill all children & free message queue. */ for (; i >= 0; i--) { (void)kill(rkidarray[i], SIGKILL); (void)kill(wkidarray[i], SIGKILL); } - - if (msgctl(tid, IPC_RMID, 0) < 0) { - printf("Msgctl error in cleanup_msgqueue %d\n", errno); - exit(FAIL); - } + SAFE_MSGCTL(id, IPC_RMID, 0); } -static int dotest(key_t key, int child_process) +static void dotest(key_t key, int child_process, int id) { - int id, pid; - int i, count, status, exit_status; - - sighold(SIGTERM); - if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) { - printf("msgget() error in child %d: %s\n", - child_process, strerror(errno)); - return FAIL; - } - tid = id; - sigrelse(SIGTERM); - - exit_status = PASS; + int pid; + int i, count; for (i = 0; i < nkids; i++) { - if ((pid = FORK_OR_VFORK()) < 0) { - printf("Fork failure in the first child of child group %d\n", + pid = fork(); + if (pid < 0) { + tst_res(TFAIL, + "Fork failure in the first child of child group %d\n", child_process); - cleanup_msgqueue(i, tid); - return FAIL; + cleanup_msgqueue(i, id); + return; } /* First child does this */ if (pid == 0) { - procstat = 2; - exit(doreader(key, tid, getpid(), - child_process, nreps)); + msg_do_reader(key, id, getpid(), child_process, nreps); + exit(0); } rkidarray[i] = pid; - if ((pid = FORK_OR_VFORK()) < 0) { - printf("Fork failure in the second child of child group %d\n", + pid = fork(); + if (pid < 0) { + tst_res(TFAIL, + "Fork failure in the first child of child group %d\n", child_process); - /* - * Kill the reader child process - */ - (void)kill(rkidarray[i], SIGKILL); - - cleanup_msgqueue(i, tid); - return FAIL; + cleanup_msgqueue(i, id); + return; } /* Second child does this */ if (pid == 0) { - procstat = 2; - exit(dowriter(key, tid, rkidarray[i], - child_process, nreps)); + msg_do_writer(key, id, rkidarray[i], child_process, nreps); + exit(0); } wkidarray[i] = pid; } /* Parent does this */ count = 0; while (1) { - if ((wait(&status)) > 0) { - if (status >> 8 != PASS) { - printf("Child exit status = %d from child group %d\n", - status >> 8, child_process); - for (i = 0; i < nkids; i++) { - kill(rkidarray[i], SIGTERM); - kill(wkidarray[i], SIGTERM); - } - if (msgctl(tid, IPC_RMID, 0) < 0) { - printf("msgctl() error: %s\n", - strerror(errno)); - } - return FAIL; - } + if (wait(NULL) > 0) { count++; } else { - if (errno != EINTR) { + if (errno != EINTR) break; - } } } /* Make sure proper number of children exited */ if (count != (nkids * 2)) { - printf("Wrong number of children exited in child group %d, saw %d, expected %d\n", + tst_res(TFAIL, + "Wrong number of children exited in child group %d, saw %d, expected %d\n", child_process, count, (nkids * 2)); - if (msgctl(tid, IPC_RMID, 0) < 0) { - printf("msgctl() error: %s\n", strerror(errno)); - } - return FAIL; } - if (msgctl(id, IPC_RMID, 0) < 0) { - printf("msgctl() failure in child group %d: %s\n", - child_process, strerror(errno)); - return FAIL; - } - return exit_status; + SAFE_MSGCTL(id, IPC_RMID, NULL); } -/* ARGSUSED */ -static void term(int sig LTP_ATTRIBUTE_UNUSED) +static void dotest_iteration(int off) { - int i; + key_t key; + int i, count; + pid_t pid; - if (procstat == 0) { -#ifdef DEBUG - tst_resm(TINFO, "SIGTERM signal received, test killing kids"); -#endif - for (i = 0; i < nprocs; i++) { - if (pidarray[i] > 0) { - if (kill(pidarray[i], SIGTERM) < 0) { - tst_resm(TBROK, - "Kill failed to kill child %d", - i); - exit(FAIL); - } - } - } - return; - } + memset(pidarray, 0, sizeof(pidarray)); + + for (i = 0; i < nprocs; i++) { + key = keyarray[off + i]; + tid[i] = SAFE_MSGGET(key, IPC_CREAT | S_IRUSR | S_IWUSR); + pid = SAFE_FORK(); - if (procstat == 2) { - exit(PASS); + /* Child does this */ + if (pid == 0) { + dotest(key, i, tid[i]); + exit(0); + } + pidarray[i] = pid; } - if (tid == -1) { - exit(FAIL); + count = 0; + while (1) { + if (wait(NULL) > 0) { + count++; + } else { + if (errno != EINTR) + break; + } } - for (i = 0; i < nkids; i++) { - if (rkidarray[i] > 0) - kill(rkidarray[i], SIGTERM); - if (wkidarray[i] > 0) - kill(wkidarray[i], SIGTERM); + /* Make sure proper number of children exited */ + if (count != nprocs) { + tst_brk(TFAIL, + "Wrong number of children exited, Saw %d, Expected %d", + count, nprocs); } } -void setup(void) +static void verify_msgstress(void) { - int nr_msgqs, free_pids; + int i; - tst_tmpdir(); - /* You will want to enable some signal handling so you can capture - * unexpected signals like SIGSEGV. + /* + * Set up array of unique keys for use in allocating message + * queues. */ - tst_sig(FORK, DEF_HANDLER, cleanup); + setup_msg_key_array(MSGMNI); - /* One cavet that hasn't been fixed yet. TEST_PAUSE contains the code to - * fork the test with the -c option. You want to make sure you do this - * before you create your temporary directory. - */ - TEST_PAUSE; + if (MSGMNI <= maxnprocs) { + nprocs = MSGMNI; + dotest_iteration(0); + } else { + for (i = 0; i < (MSGMNI / maxnprocs); i++) { + nprocs = maxnprocs; + dotest_iteration(i * maxnprocs); + } - nr_msgqs = get_max_msgqueues(); - if (nr_msgqs < 0) - tst_brkm(TBROK, cleanup, "get_max_msgqueues() failed"); + nprocs = MSGMNI % maxnprocs; + dotest_iteration(i * maxnprocs); + } - MSGMNI = nr_msgqs - get_used_msgqueues(); - if (MSGMNI <= 0) - tst_brkm(TBROK, cleanup, - "Max number of message queues already used, cannot create more."); + tst_res(TPASS, "Test ran successfully!"); +} - tst_resm(TINFO, "Found %d available message queues", MSGMNI); +static void setup(void) +{ + int free_pids; - free_pids = tst_get_free_pids(cleanup); + MSGMNI = GET_AVAIL_QUEUES(); + if (MSGMNI <= 0) + tst_brk(TCONF, "Max message queues is used, cannot create more."); + tst_res(TINFO, "Found %d available message queues", MSGMNI); + + free_pids = tst_get_free_pids(); if (free_pids < 0) { - tst_brkm(TBROK, cleanup, "Can't obtain free_pid count"); + tst_brk(TBROK, "Can't obtain free_pid count"); } else if (!free_pids) { - tst_brkm(TBROK, cleanup, "No free pids"); + tst_brk(TBROK, "No free pids"); } + if (opt_nreps) + nreps = SAFE_STRTOL(opt_nreps, 1, MAXNREPS); + + if (opt_nkids) + nkids = SAFE_STRTOL(opt_nkids, 1, MAXNKIDS); + + if (opt_maxnprocs) + maxnprocs = SAFE_STRTOL(opt_maxnprocs, 1, MAXNPROCS); + /* We don't use more than a half of available pids. * For each child we fork up to 2*maxnkids grandchildren. */ - maxnprocs = (free_pids / 2) / (1 + 2 * maxnkids); - + maxnprocs = (free_pids / 2) / (1 + 2 * nkids); if (!maxnprocs) - tst_brkm(TBROK, cleanup, "Not enough free pids"); + tst_brk(TBROK, "Not enough free pids"); - tst_resm(TINFO, "Using upto %d pids", free_pids / 2); + SAFE_SIGNAL(SIGTERM, SIG_IGN); + tst_res(TINFO, + "Using upto %d pids, total %d processes, per %d processs %d read/write pairs, %d repeats ", + free_pids/2, MSGMNI, maxnprocs, nkids, nreps); } -void cleanup(void) +static void cleanup(void) { - int status; - - /* - * Remove the message queue from the system - */ -#ifdef DEBUG - tst_resm(TINFO, "Removing the message queue"); -#endif - (void)msgctl(tid, IPC_RMID, NULL); - if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) { - (void)msgctl(tid, IPC_RMID, NULL); - tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed"); + int i = 0; - } - - tst_rmdir(); + for (i = 0; i < nprocs; i++) + msgctl(tid[i], IPC_RMID, NULL); } + +static struct tst_test test = { + .needs_tmpdir = 1, + .options = options, + .setup = setup, + .cleanup = cleanup, + .forks_child = 1, + .test_all = verify_msgstress, +};