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