Whamcloud - gitweb
LU-224 Move fail_loc handling from lustre to libcfs
[fs/lustre-release.git] / lustre / liblustre / tests / recovery_small.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/liblustre/tests/recovery_small.c
37  *
38  * Lustre Light user test program
39  */
40
41 #define _BSD_SOURCE
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <getopt.h>
47 #include <string.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <sys/queue.h>
52 #include <getopt.h>
53 #include <sys/wait.h>
54
55 #include <sysio.h>
56 #include <mount.h>
57
58 #include "test_common.h"
59
60 #define MAX_STRING_SIZE 2048
61
62 static struct {
63         const char   *name;
64         unsigned long code;
65 } drop_arr [] =
66 {
67         {"MDS_REQUEST", 0x123},
68         {"MDS_REPLY", 0x122},
69         {NULL, 0}
70 };
71
72 static int drop_index = 0;
73
74 static char mds_server[1024] = {0, };
75 static char ssh_cmd[MAX_STRING_SIZE] = {0,};
76
77 int do_stat(const char *name, struct stat *buf)
78 {
79         struct stat stat;
80         int rc;
81
82         rc = lstat(name, &stat);
83         if (rc) {
84                 printf("error %d stat %s\n", rc, name);
85                 exit(1);
86         }
87         if (buf)
88                 memcpy(buf, &stat, sizeof(*buf));
89
90         return 0;
91 }
92
93 void prepare_reg(const char *path)
94 {
95         int fd, rc;
96
97         fd = open(path, O_RDWR|O_CREAT, 00644);
98         if (fd < 0) {
99                 printf("error %d create %s\n", fd, path);
100                 exit(1);
101         }
102
103         rc = close(fd);
104         if (rc) {
105                 printf("error %d close %s\n", rc, path);
106                 exit(1);
107         }
108 }
109
110 void cleanup_reg(const char *path)
111 {
112         int rc;
113
114         rc = unlink(path);
115         if (rc) {
116                 printf("error %d unlink %s\n", rc, path);
117                 exit(1);
118         }
119 }
120
121 void prepare_dir(const char *path)
122 {
123         int rc;
124
125         rc = mkdir(path, 00644);
126         if (rc < 0) {
127                 printf("error %d mkdir %s\n", rc, path);
128                 exit(1);
129         }
130 }
131
132 void cleanup_dir(const char *path)
133 {
134         int rc;
135
136         rc = rmdir(path);
137         if (rc) {
138                 printf("error %d unlink %s\n", rc, path);
139                 exit(1);
140         }
141 }
142
143 #define FAIL()                                                             \
144     do {                                                                   \
145         char cmd[MAX_STRING_SIZE];                                         \
146         int rc;                                                            \
147                                                                            \
148         if (drop_arr[drop_index].name) {                                   \
149             printf("server drops next %s\n", drop_arr[drop_index].name);   \
150             sprintf(cmd,                                                   \
151                     "%s %s \"lctl set_param fail_loc=%lu\"",               \
152                     ssh_cmd, mds_server, drop_arr[drop_index].code);       \
153             if ((rc = system(cmd)) != 0) {                                 \
154                 rc = WEXITSTATUS(rc);                                      \
155                 printf("error excuting remote command: %d\n", rc);         \
156                 exit(rc);                                                  \
157             }                                                              \
158         }                                                                  \
159     } while (0)
160
161 #define RECOVER()                                                          \
162     do {                                                                   \
163         char cmd[1024];                                                    \
164                                                                            \
165         if (drop_arr[drop_index].name) {                                   \
166             sprintf(cmd, "%s %s \"lctl set_param fail_loc=0\"",            \
167                     ssh_cmd, mds_server);                                  \
168             if (!system(cmd)) {}                                           \
169         }                                                                  \
170     } while (0)
171
172 #define ENTRY(str)                                                      \
173         do {                                                            \
174                 char buf[100];                                          \
175                 int len;                                                \
176                 sprintf(buf, "===== START: %s ", (str));                \
177                 len = strlen(buf);                                      \
178                 if (len < 79) {                                         \
179                         memset(buf+len, '=', 100-len);                  \
180                         buf[79] = '\n';                                 \
181                         buf[80] = 0;                                    \
182                 }                                                       \
183                 printf("%s", buf);                                      \
184         } while (0)
185
186 #define LEAVE()                                                         \
187         do {                                                            \
188                 printf("----- END TEST successfully ---");              \
189                 printf("-----------------------------");                \
190                 printf("-------------------\n");                        \
191         } while (0)
192
193
194 void t1()
195 {
196         char *path="/mnt/lustre/test_t1";
197         ENTRY("create/delete");
198
199         FAIL();
200         t_touch(path);
201         RECOVER();
202         FAIL();
203         t_unlink(path);
204         RECOVER();
205         LEAVE();
206 }
207
208 void t2()
209 {
210         char *path="/mnt/lustre/test_t2";
211         ENTRY("mkdir/rmdir");
212
213         FAIL();
214         t_mkdir(path);
215         RECOVER();
216         FAIL();
217         t_rmdir(path);
218         RECOVER();
219         LEAVE();
220 }
221
222 void t3()
223 {
224         char *path="/mnt/lustre/test_t3";
225         ENTRY("regular stat");
226
227         t_touch(path);
228         FAIL();
229         t_check_stat(path, NULL);
230         RECOVER();
231         t_unlink(path);
232         LEAVE();
233 }
234
235 void t4()
236 {
237         char *path="/mnt/lustre/test_t4";
238         ENTRY("dir stat");
239
240         t_mkdir(path);
241         FAIL();
242         t_check_stat(path, NULL);
243         RECOVER();
244         t_rmdir(path);
245         LEAVE();
246 }
247
248 void t5()
249 {
250         char *path="/mnt/lustre/test_t5";
251         const int bufsize = 4096;
252         char wbuf[bufsize], rbuf[bufsize];
253         int npages = 100;
254         int fd, rc, i;
255         ENTRY("sequential page aligned file I/O");
256
257         t_touch(path);
258
259         fd = t_open(path);
260
261         for (i = 0; i < npages; i++ ) {
262                 memset(wbuf, i, bufsize);
263                 rc = write(fd, wbuf, bufsize);
264                 if (rc != bufsize) {
265                         printf("write error %d (i = %d)\n", rc, i);
266                         exit(1);
267                 }
268         }
269         printf("succefully write %d pages\n", npages);
270
271         lseek(fd, 0, SEEK_SET);
272
273         for (i = 0; i < npages; i++ ) {
274                 memset(rbuf, 0, bufsize);
275                 rc = read(fd, rbuf, bufsize);
276                 if (rc != bufsize) {
277                         printf("read error %d (i = %d)\n", rc, i);
278                         exit(1);
279                 }
280         }
281         printf("succefully read & verified %d pages\n", npages);
282
283         t_close(fd);
284
285         t_unlink(path);
286         LEAVE();
287 }
288
289 void t6()
290 {
291         char *path="/mnt/lustre/test_t6";
292         char *path2="/mnt/lustre/test_t6_link";
293         ENTRY("symlink");
294
295         t_touch(path);
296         FAIL();
297         t_symlink(path, path2);
298         RECOVER();
299         t_check_stat(path2, NULL);
300         t_unlink(path2);
301         t_unlink(path);
302         LEAVE();
303 }
304
305 void t7()
306 {
307         char *path="/mnt/lustre/test_t7";
308         ENTRY("mknod");
309
310         FAIL();
311         t_mknod(path, S_IFCHR | 0644, 5, 4);
312         RECOVER();
313         t_check_stat(path, NULL);
314         t_unlink(path);
315         LEAVE();
316 }
317
318 extern int libcfs_debug;
319 extern int libcfs_subsystem_debug;
320
321 extern void __liblustre_setup_(void);
322 extern void __liblustre_cleanup_(void);
323
324 void usage(const char *cmd)
325 {
326         printf("Usage: \t%s -s mds_hostname --target mdsnid:/mdsname/profile\n", cmd);
327         printf("       \t%s -s mds_hostname --dumpfile dumpfile\n", cmd);
328         exit(-1);
329 }
330
331 int main(int argc, char * argv[])
332 {
333         int opt_index, c;
334         char cmd[1024];
335         static struct option long_opts[] = {
336                 {"target", 1, 0, 0},
337                 {"dumpfile", 1, 0, 0},
338                 {"ssh", 1, 0, 0},
339                 {0, 0, 0, 0}
340         };
341
342         if (argc < 3 - (getenv(ENV_LUSTRE_MNTTGT)||getenv(ENV_LUSTRE_DUMPFILE)))
343                 usage(argv[0]);
344
345         while ((c = getopt_long(argc, argv, "s:", long_opts, &opt_index)) != -1) {
346                 switch (c) {
347                 case 0: {
348                         if (!optarg[0])
349                                 usage(argv[0]);
350
351                         if (!strcmp(long_opts[opt_index].name, "target")) {
352                                 setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
353                         } else if (!strcmp(long_opts[opt_index].name, "dumpfile")) {
354                                 setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
355                         } else if (!strcmp(long_opts[opt_index].name, "ssh")) {
356                                 safe_strncpy(ssh_cmd, optarg, MAX_STRING_SIZE);
357                         } else
358                                 usage(argv[0]);
359                         break;
360                 }
361                 case 's':
362                         safe_strncpy(mds_server, optarg, MAX_STRING_SIZE);
363                         break;
364                 default:
365                         usage(argv[0]);
366                 }
367         }
368
369         if (optind != argc)
370                 usage(argv[0]);
371
372         if (strlen(mds_server) == 0)
373                 usage(argv[0]);
374
375         /* default to using ssh */
376         if (!strlen(ssh_cmd)) {
377                 safe_strncpy(ssh_cmd, "ssh", MAX_STRING_SIZE);
378         }
379
380         sprintf(cmd, "%s %s cat /dev/null", ssh_cmd, mds_server);
381         if (system(cmd)) {
382                 printf("Can't access server node: %s using method: %s\n", mds_server, ssh_cmd);
383                 exit(-1);
384         }
385
386         setenv(ENV_LUSTRE_TIMEOUT, "5", 1);
387
388         __liblustre_setup_();
389
390         while (drop_arr[drop_index].name) {
391                 t1();
392                 t2();
393                 t3();
394                 t4();
395 #if 0
396                 t5();
397 #endif
398                 t6();
399                 t7();
400
401                 drop_index++;
402         }
403
404         printf("liblustre is about shutdown\n");
405         __liblustre_cleanup_();
406
407         printf("complete successfully\n");
408         return (0);
409 }