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
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2017, Intel Corporation. All rights reserved.
28 * Use is subject to license terms.
30 * lustre/tests/mirror_io.c
32 * Lustre mirror test tool.
34 * Author: Jinshan Xiong <jinshan.xiong@intel.com>
43 #include <sys/types.h>
47 #include <lustre/lustreapi.h>
49 #define syserr(exp, str, args...) \
52 err(EXIT_FAILURE, str, ##args); \
55 #define syserrx(exp, str, args...) \
58 errx(EXIT_FAILURE, str, ##args); \
61 #define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
63 static const char *progname;
65 static void usage(void);
67 static int open_file(const char *fname)
72 if (stat(fname, &stbuf) < 0)
75 if (!S_ISREG(stbuf.st_mode))
76 errx(1, "%s: '%s' is not a regular file", progname, fname);
78 fd = open(fname, O_DIRECT | O_RDWR);
79 syserr(fd < 0, "open %s", fname);
84 static size_t get_ids(int fd, unsigned int *ids)
86 struct llapi_layout *layout;
90 layout = llapi_layout_get_by_fd(fd, 0);
91 syserrx(layout == NULL, "layout is NULL");
93 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
94 syserrx(rc < 0, "first component");
99 rc = llapi_layout_mirror_id_get(layout, &id);
100 syserrx(rc < 0, "id get");
102 if (!count || ids[count - 1] != id)
105 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
106 syserrx(rc < 0, "move to next");
109 llapi_layout_free(layout);
114 static void check_id(int fd, unsigned int id)
116 unsigned int ids[LUSTRE_MIRROR_COUNT_MAX];
121 count = get_ids(fd, ids);
122 for (i = 0; i < count; i++) {
129 syserr(!found, "cannot find the mirror id: %d", id);
132 static void mirror_dump(int argc, char *argv[])
134 const char *outfile = NULL;
139 const size_t buflen = 4 * 1024 * 1024;
144 while ((c = getopt(argc, argv, "i:o:")) != -1) {
155 errx(1, "unknown option: '%s'", argv[optind - 1]);
159 if (argc > optind + 1)
160 errx(1, "too many files");
162 errx(1, "no file name given");
164 syserrx(id < 0, "mirror id is not set");
166 fd = open_file(argv[optind]);
171 outfd = open(outfile, O_EXCL | O_WRONLY | O_CREAT, 0644);
172 syserr(outfd < 0, "open %s", outfile);
174 outfd = STDOUT_FILENO;
177 c = posix_memalign(&buf, sysconf(_SC_PAGESIZE), buflen);
178 syserr(c, "posix_memalign");
185 bytes_read = llapi_mirror_read(fd, id, buf, buflen, pos);
189 syserrx(bytes_read < 0, "mirror read");
191 written = write(outfd, buf, bytes_read);
192 syserrx(written < bytes_read, "short write");
205 static size_t add_tids(unsigned int *ids, size_t count, char *arg)
213 tmp = strchr(arg, ',');
217 id = strtol(arg, &end, 10);
218 syserrx(*end || id <= 0, "id string error: '%s'", arg);
220 for (i = 0; i < count; i++)
221 syserrx(id == ids[i], "duplicate id: %d", id);
223 ids[count++] = (unsigned int)id;
234 static void mirror_copy(int argc, char *argv[])
241 unsigned int ids[4096] = { 0 };
246 while ((c = getopt(argc, argv, "i:t:")) != -1) {
253 count = add_tids(ids, count, optarg);
257 errx(1, "unknown option: '%s'", argv[optind - 1]);
261 if (argc > optind + 1)
262 errx(1, "too many files");
264 errx(1, "no file name given");
266 syserrx(id < 0, "mirror id is not set");
268 for (i = 0; i < count; i++)
269 syserrx(id == ids[i], "src and dst have the same id");
271 fd = open_file(argv[optind]);
275 result = llapi_mirror_copy_many(fd, id, ids, count);
276 syserrx(result < 0, "copy error: %zd", result);
278 fprintf(stdout, "mirror copied successfully: ");
279 for (i = 0; i < result; i++)
280 fprintf(stdout, "%d ", ids[i]);
281 fprintf(stdout, "\n");
286 /* XXX - does not work. Leave here as place holder */
287 static void mirror_ost_lv(int argc, char *argv[])
293 __u32 layout_version;
296 while ((c = getopt(argc, argv, "i:")) != -1) {
303 errx(1, "unknown option: '%s'", argv[optind - 1]);
307 if (argc > optind + 1)
308 errx(1, "too many files");
310 errx(1, "no file name given");
312 syserrx(id < 0, "mirror id is not set");
314 fd = open_file(argv[optind]);
318 rc = llapi_mirror_set(fd, id);
319 syserr(rc < 0, "set mirror id error");
321 rc = llapi_get_ost_layout_version(fd, &layout_version);
322 syserr(rc < 0, "get ostlayoutversion error");
324 llapi_mirror_clear(fd);
327 fprintf(stdout, "ostlayoutversion: %u\n", layout_version);
330 static void usage_wrapper(int argc, char *argv[])
335 const struct subcommand {
337 void (*func)(int argc, char *argv[]);
340 { "dump", mirror_dump, "dump mirror: <-i id> [-o file] FILE" },
341 { "copy", mirror_copy, "copy mirror: <-i id> <-t id1,id2> FILE" },
342 { "data_version", mirror_ost_lv, "ost layout version: <-i id> FILE" },
343 { "help", usage_wrapper, "print helper message" },
346 static void usage(void)
350 fprintf(stdout, "%s <command> [OPTIONS] [<FILE>]\n", progname);
351 for (i = 0; i < ARRAY_SIZE(cmds); i++)
352 fprintf(stdout, "\t%s - %s\n", cmds[i].name, cmds[i].helper);
357 int main(int argc, char *argv[])
362 progname = basename(argv[0]);
366 for (i = 0; i < ARRAY_SIZE(cmds); i++) {
367 if (strcmp(cmds[i].name, argv[1]))
371 cmds[i].func(argc - 1, argv + 1);
376 syserrx(1, "unknown subcommand: '%s'", argv[1]);