4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see If not, see
18 * http://www.gnu.org/licenses
20 * Please contact http://www.seagate.com/contacts/ or visit www.seagate.com
21 * if you need additional information or have any questions.
26 * Copyright (c) 2017, Seagate Technology LLC
28 * Author: Ashish Maurya <ashish.maurya@seagate.com>
31 * lustre/tests/mpi/rr_alloc.c
35 * This code is creating <n> files using MPI processes which depend on the
36 * mounted clients. Processes are running in parallel through all the client
37 * nodes in RR fashion starting with rank 0 and so on, and creating files.
39 * USE CASE:- If there are 20 mounted clients on 4 client nodes, 5 clients on
40 * each node, it will run 5 processes on each client node through each mount
41 * point and each process will create <n> number of files given by the user.
42 * Each process rank is mapped to its matching mount point on the client node
43 * eg:- rank 0 <-> /tmp/mnt/lustre0 ; rank 1 <-> /tmp/mnt/lustre1 etc.
45 * NOTE:- For simplicity client on /mnt/lustre is not taken into account.
47 * IMPORTANT NOTE:- If argv[1] is /mnt/dir/ash, then the program assumes that.
48 * /mnt0/dir/, /mnt1/dir/, etc exist.
62 void usage(char *prog)
64 printf("Usage: %s <filename with mount pt and test dir>", prog);
65 printf(" <no. of files> <no. of cli nodes>\n");
66 printf("Ex: mpirun -np <njobs> rr_alloc /tmp/mnt/lustre/ash 512 4\n");
71 void perr_exit(int rank, int error, const char *fmt, ...)
75 printf("Process rank %d exited with error code %d\n", rank, error);
79 MPI_Abort(MPI_COMM_WORLD, error);
82 int main(int argc, char **argv)
85 int serial_prank_per_cli = 0;
86 int proc_per_cli_node = 0;
94 char file_path[PATH_MAX] = {0};
95 char mnt_path[PATH_MAX] = {0};
105 if (!strchr(argv[1], '/')) {
106 fprintf(stderr, "Please enter filename with mount point\n");
111 * Separating filename and mount point name. This is required for
112 * mapping processes to particular mount point.
114 path1 = strdup(argv[1]);
115 path2 = strdup(argv[1]);
116 path3 = strdup(argv[1]);
117 fname = basename(path1);
118 dname = basename(dirname(path2));
119 /* dirname looping depends on the depth of the file from mount path */
120 strncpy(mnt_path, dirname(dirname(path3)), sizeof(mnt_path));
122 file_no = atoi(argv[2]);
124 fprintf(stderr, "Number of files must not be zero\n");
127 client_nodes = atoi(argv[3]);
129 fprintf(stderr, "Client nodes must not be zero\n");
133 rc = MPI_Init(&argc, &argv);
134 if (rc != MPI_SUCCESS) {
135 fprintf(stderr, "MPI_Init failed: %d\n", rc);
139 rc = MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank);
140 if (rc != MPI_SUCCESS)
141 perr_exit(proc_rank, rc, "MPI_Comm_rank failed: %d\n", rc);
143 rc = MPI_Comm_size(MPI_COMM_WORLD, &nproc);
144 if (rc != MPI_SUCCESS)
145 perr_exit(proc_rank, rc, "MPI_Comm_size failed: %d\n", rc);
148 * Make sure that each rank is processed through its respective mnt pt
149 * eg: job 0,1 will be executed by /tmp/mnt/lustre0, /tmp/mnt/lustre1,
150 * etc. on each client node.
152 /* Number of processes on each client nodes */
153 proc_per_cli_node = nproc / client_nodes;
156 * By default rank of processes is allocated in RR fashion throughout
157 * all the client nodes so all the processes are not in serial order on
158 * a particular client node. In order to map each process to a mount pt
159 * by its rank we need process rank in serial order on a client node
161 serial_prank_per_cli = proc_rank % proc_per_cli_node;
163 rc = MPI_Barrier(MPI_COMM_WORLD);
164 if (rc != MPI_SUCCESS)
165 perr_exit(proc_rank, rc, "Prep MPI_Barrier failed: %d\n", rc);
167 for (i = 0; i < file_no; i++) {
168 bytes = snprintf(file_path, sizeof(file_path),
169 "%s%d/%s/%s-%d-%d", mnt_path, serial_prank_per_cli,
170 dname, fname, proc_rank, i);
171 if (bytes >= sizeof(file_path))
172 perr_exit(proc_rank, -ENAMETOOLONG, "Name too long\n");
173 fd = open(file_path, O_CREAT|O_RDWR, 0644);
175 perr_exit(proc_rank, errno, "Cannot open \"%s\": %s\n",
176 file_path, strerror(errno));