Viewing: rr_alloc.c
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017, Seagate Technology LLC
*
* Author: Ashish Maurya <ashish.maurya@seagate.com>
*/
/*
* lustre/tests/mpi/rr_alloc.c
*
* DESCRIPTION
*
* This code is creating <n> files using MPI processes which depend on the
* mounted clients. Processes are running in parallel through all the client
* nodes in RR fashion starting with rank 0 and so on, and creating files.
*
* USE CASE:- If there are 20 mounted clients on 4 client nodes, 5 clients on
* each node, it will run 5 processes on each client node through each mount
* point and each process will create <n> number of files given by the user.
* Each process rank is mapped to its matching mount point on the client node
* eg:- rank 0 <-> /tmp/mnt/lustre0 ; rank 1 <-> /tmp/mnt/lustre1 etc.
*
* NOTE:- For simplicity client on /mnt/lustre is not taken into account.
*
* IMPORTANT NOTE:- If argv[1] is /mnt/dir/ash, then the program assumes that.
* /mnt0/dir/, /mnt1/dir/, etc exist.
*/
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <libgen.h>
void usage(char *prog)
{
printf("Usage: %s <filename with mount pt and test dir>", prog);
printf(" <no. of files> <no. of cli nodes>\n");
printf("Ex: mpirun -np <njobs> rr_alloc /tmp/mnt/lustre/ash 512 4\n");
exit(EXIT_FAILURE);
}
void perr_exit(int rank, int error, const char *fmt, ...)
{
va_list ap;
printf("Process rank %d exited with error code %d\n", rank, error);
va_start(ap, fmt);
vprintf(fmt, ap);
MPI_Abort(MPI_COMM_WORLD, error);
}
int main(int argc, char **argv)
{
int proc_rank = 0;
int serial_prank_per_cli = 0;
int proc_per_cli_node = 0;
int bytes = 0;
int file_no = 0;
int client_nodes = 0;
int nproc = 0;
int rc = 0;
int fd = 0;
int i = 0;
char file_path[PATH_MAX] = {0};
char mnt_path[PATH_MAX] = {0};
char *path1;
char *path2;
char *path3;
char *fname;
char *dname;
if (argc != 4)
usage(argv[0]);
if (!strchr(argv[1], '/')) {
fprintf(stderr, "Please enter filename with mount point\n");
usage(argv[0]);
}
/*
* Separating filename and mount point name. This is required for
* mapping processes to particular mount point.
*/
path1 = strdup(argv[1]);
path2 = strdup(argv[1]);
path3 = strdup(argv[1]);
fname = basename(path1);
dname = basename(dirname(path2));
/* dirname looping depends on the depth of the file from mount path */
strncpy(mnt_path, dirname(dirname(path3)), sizeof(mnt_path) - 1);
file_no = atoi(argv[2]);
if (!file_no) {
fprintf(stderr, "Number of files must not be zero\n");
usage(argv[0]);
}
client_nodes = atoi(argv[3]);
if (!client_nodes) {
fprintf(stderr, "Client nodes must not be zero\n");
usage(argv[0]);
}
rc = MPI_Init(&argc, &argv);
if (rc != MPI_SUCCESS) {
fprintf(stderr, "MPI_Init failed: %d\n", rc);
exit(EXIT_FAILURE);
}
rc = MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank);
if (rc != MPI_SUCCESS)
perr_exit(proc_rank, rc, "MPI_Comm_rank failed: %d\n", rc);
rc = MPI_Comm_size(MPI_COMM_WORLD, &nproc);
if (rc != MPI_SUCCESS)
perr_exit(proc_rank, rc, "MPI_Comm_size failed: %d\n", rc);
/*
* Make sure that each rank is processed through its respective mnt pt
* eg: job 0,1 will be executed by /tmp/mnt/lustre0, /tmp/mnt/lustre1,
* etc. on each client node.
*/
/* Number of processes on each client nodes */
proc_per_cli_node = nproc / client_nodes;
/*
* By default rank of processes is allocated in RR fashion throughout
* all the client nodes so all the processes are not in serial order on
* a particular client node. In order to map each process to a mount pt
* by its rank we need process rank in serial order on a client node
*/
serial_prank_per_cli = proc_rank % proc_per_cli_node;
rc = MPI_Barrier(MPI_COMM_WORLD);
if (rc != MPI_SUCCESS)
perr_exit(proc_rank, rc, "Prep MPI_Barrier failed: %d\n", rc);
for (i = 0; i < file_no; i++) {
bytes = snprintf(file_path, sizeof(file_path),
"%s%d/%s/%s-%d-%d", mnt_path, serial_prank_per_cli,
dname, fname, proc_rank, i);
if (bytes >= sizeof(file_path))
perr_exit(proc_rank, -ENAMETOOLONG, "Name too long\n");
fd = open(file_path, O_CREAT|O_RDWR, 0644);
if (fd < 0) {
perr_exit(proc_rank, errno, "Cannot open \"%s\": %s\n",
file_path, strerror(errno));
}
close(fd);
}
MPI_Finalize();
return 0;
}