Whamcloud - gitweb
LU-233 test: Remove taring of log files in gather logs.
[fs/lustre-release.git] / lustre / tests / ll_dirstripe_verify.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) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * Copyright (c) 2011 Whamcloud, Inc.
34  */
35 /*
36  * This file is part of Lustre, http://www.lustre.org/
37  * Lustre is a trademark of Sun Microsystems, Inc.
38  *
39  * lustre/tests/ll_dirstripe_verify.c
40  *
41  * ll_dirstripe_verify <dir> <file>:
42  * - to verify if the file has the same lov_user_md setting as the parent dir.
43  * - if dir's offset is set -1, ll_dirstripe_verify <dir> <file1> <file2>
44  *      is used to further verify if file1 and file2's obdidx is continuous.
45  */
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ctype.h>
51 #include <sys/ioctl.h>
52 #include <unistd.h>
53 #include <fcntl.h>
54 #include <errno.h>
55 #include <dirent.h>
56
57 #include <liblustre.h>
58 #include <obd.h>
59 #include <lustre_lib.h>
60 #include <lustre/liblustreapi.h>
61 #include <obd_lov.h>
62
63 #include <lnet/lnetctl.h>
64
65
66 #define MAX_LOV_UUID_COUNT      1000
67 union {
68         struct obd_uuid uuid;
69         char name[0];
70 } lov;
71 #define lov_uuid lov.uuid
72 #define lov_name lov.name
73
74 /* Returns bytes read on success and a negative value on failure.
75  * If zero bytes are read it will be treated as failure as such
76  * zero cannot be returned from this function.
77  */
78 int read_proc_entry(char *proc_path, char *buf, int len)
79 {
80         int rc, fd;
81
82         memset(buf, 0, len);
83
84         fd = open(proc_path, O_RDONLY);
85         if (fd == -1) {
86                 llapi_error(LLAPI_MSG_ERROR, -errno, "open('%s') failed: %s\n",
87                             proc_path);
88                 return -2;
89         }
90
91         rc = read(fd, buf, len - 1);
92         if (rc < 0) {
93                 llapi_error(LLAPI_MSG_ERROR, -errno,
94                             "read('%s') failed: %s\n", proc_path);
95                 rc = -3;
96         } else if (rc == 0) {
97                 llapi_err_noerrno(LLAPI_MSG_ERROR,
98                                   "read('%s') zero bytes\n", proc_path);
99                 rc = -4;
100         } else if (/* rc > 0 && */ buf[rc - 1] == '\n') {
101                 buf[rc - 1] = '\0'; /* Remove trailing newline */
102         }
103         close(fd);
104
105         return (rc);
106 }
107
108 int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
109             struct lov_user_md *lum_file2)
110 {
111         int stripe_count = 0, min_stripe_count = 0, def_stripe_count = 1;
112         int stripe_size = 0;
113         int stripe_offset = -1;
114         int ost_count;
115         char buf[128];
116         char lov_path[PATH_MAX];
117         char tmp_path[PATH_MAX];
118         int i;
119         FILE *fp;
120
121         fp = popen("\\ls -d  /proc/fs/lustre/lov/*clilov* | head -1", "r");
122         if (!fp) {
123                 llapi_error(LLAPI_MSG_ERROR, -errno,
124                             "open(lustre/lov/*clilov*) failed: %s\n");
125                 return 2;
126         }
127         if (fscanf(fp, "%s", lov_path) < 1) {
128                 llapi_error(LLAPI_MSG_ERROR, -EINVAL,
129                             "read(lustre/lov/*clilov*) failed: %s\n");
130                 pclose(fp);
131                 return 3;
132         }
133         pclose(fp);
134
135         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripecount",
136                  lov_path);
137         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
138                 return 5;
139         def_stripe_count = (short)atoi(buf);
140
141         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/numobd", lov_path);
142         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
143                 return 6;
144         ost_count = atoi(buf);
145
146         if (lum_dir == NULL) {
147                 stripe_count = def_stripe_count;
148                 min_stripe_count = -1;
149         } else {
150                 stripe_count = (signed short)lum_dir->lmm_stripe_count;
151                 printf("dir stripe %d, ", stripe_count);
152                 min_stripe_count = 1;
153         }
154
155         printf("default stripe %d, ost count %d\n",
156                def_stripe_count, ost_count);
157
158         if (stripe_count == 0) {
159                 min_stripe_count = -1;
160                 stripe_count = 1;
161         }
162
163         stripe_count = (stripe_count > 0 && stripe_count <= ost_count) ?
164                                                 stripe_count : ost_count;
165         min_stripe_count = min_stripe_count > 0 ? stripe_count :
166                                                 ((stripe_count + 1) / 2);
167
168         if (lum_file1->lmm_stripe_count != stripe_count ||
169             lum_file1->lmm_stripe_count < min_stripe_count) {
170                 llapi_err_noerrno(LLAPI_MSG_ERROR,
171                                   "file1 stripe count %d != dir %d\n",
172                                   lum_file1->lmm_stripe_count, stripe_count);
173                 return 7;
174         }
175
176         if (lum_file1->lmm_stripe_count < stripe_count)
177                 llapi_err_noerrno(LLAPI_MSG_WARN,
178                                   "warning: file1 used fewer stripes"
179                                   " %d < dir %d (likely due to bug 4900)\n",
180                                   lum_file1->lmm_stripe_count, stripe_count);
181
182         if (lum_dir != NULL)
183                 stripe_size = (int)lum_dir->lmm_stripe_size;
184         if (stripe_size == 0) {
185                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripesize",
186                          lov_path);
187                 if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
188                         return 5;
189
190                 stripe_size = atoi(buf);
191         }
192
193         if (lum_file1->lmm_stripe_size != stripe_size) {
194                 llapi_err_noerrno(LLAPI_MSG_ERROR,
195                                   "file1 stripe size %d != dir %d\n",
196                                   lum_file1->lmm_stripe_size, stripe_size);
197                 return 8;
198         }
199
200         if (lum_dir != NULL)
201                 stripe_offset = (short int)lum_dir->lmm_stripe_offset;
202         if (stripe_offset != -1) {
203                 for (i = 0; i < stripe_count; i++)
204                         if (lum_file1->lmm_objects[i].l_ost_idx !=
205                             (stripe_offset + i) % ost_count) {
206                                 llapi_err_noerrno(LLAPI_MSG_WARN,
207                                           "warning: file1 non-sequential "
208                                           "stripe[%d] %d != %d\n", i,
209                                           lum_file1->lmm_objects[i].l_ost_idx,
210                                           (stripe_offset + i) % ost_count);
211                         }
212         } else if (lum_file2 != NULL) {
213                 int next, idx, stripe = stripe_count - 1;
214                 next = (lum_file1->lmm_objects[stripe].l_ost_idx + 1) %
215                        ost_count;
216                 idx = lum_file2->lmm_objects[0].l_ost_idx;
217                 if (idx != next) {
218                         llapi_err_noerrno(LLAPI_MSG_WARN,
219                                   "warning: non-sequential "
220                                   "file1 stripe[%d] %d != file2 stripe[0] %d\n",
221                                   stripe, lum_file1->lmm_objects[stripe].l_ost_idx,
222                                   idx);
223                 }
224         }
225
226         return 0;
227 }
228
229 int main(int argc, char **argv)
230 {
231         DIR * dir;
232         struct lov_user_md *lum_dir, *lum_file1 = NULL, *lum_file2 = NULL;
233         int rc;
234         int lum_size;
235
236         if (argc < 3) {
237                 llapi_err_noerrno(LLAPI_MSG_ERROR,
238                                 "Usage: %s <dirname> <filename1> [filename2]\n",
239                                 argv[0]);
240                 return 1;
241         }
242
243         dir = opendir(argv[1]);
244         if (dir == NULL) {
245                 rc = -errno;
246                 llapi_error(LLAPI_MSG_ERROR, rc,
247                             "error: %s opendir failed\n", argv[1]);
248                 return rc;
249         }
250
251         lum_size = lov_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC);
252         if ((lum_dir = (struct lov_user_md *)malloc(lum_size)) == NULL) {
253                 rc = -ENOMEM;
254                 llapi_error(LLAPI_MSG_ERROR, rc,
255                             "error: can't allocate %d bytes "
256                             "for dir EA", lum_size);
257                 goto cleanup;
258         }
259
260         rc = llapi_file_get_stripe(argv[1], lum_dir);
261         if (rc) {
262                 if (rc == -ENODATA) {
263                         free(lum_dir);
264                         lum_dir = NULL;
265                 } else {
266                         llapi_error(LLAPI_MSG_ERROR, rc,
267                                     "error: can't get EA for %s\n", argv[1]);
268                         goto cleanup;
269                 }
270         }
271
272         /* XXX should be llapi_lov_getname() */
273         rc = llapi_file_get_lov_uuid(argv[1], &lov_uuid);
274         if (rc) {
275                 llapi_error(LLAPI_MSG_ERROR, rc,
276                             "error: can't get lov name for %s\n",
277                             argv[1]);
278                 return rc;
279         }
280
281         if ((lum_file1 = (struct lov_user_md *)malloc(lum_size)) == NULL) {
282                 rc = -ENOMEM;
283                 llapi_error(LLAPI_MSG_ERROR, rc,
284                             "error: can't allocate %d bytes for EA\n",
285                             lum_size);
286                 goto cleanup;
287         }
288
289         rc = llapi_file_get_stripe(argv[2], lum_file1);
290         if (rc) {
291                 llapi_error(LLAPI_MSG_ERROR, rc,
292                             "error: unable to get EA for %s\n", argv[2]);
293                 goto cleanup;
294         }
295
296         if (argc == 4) {
297                 lum_file2 = (struct lov_user_md *)malloc(lum_size);
298                 if (lum_file2 == NULL) {
299                         rc = -ENOMEM;
300                         llapi_error(LLAPI_MSG_ERROR, rc,
301                                     "error: can't allocate %d "
302                                     "bytes for file2 EA\n", lum_size);
303                         goto cleanup;
304                 }
305
306                 rc = llapi_file_get_stripe(argv[3], lum_file2);
307                 if (rc) {
308                         llapi_error(LLAPI_MSG_ERROR, rc,
309                                     "error: can't get EA for %s\n", argv[3]);
310                         goto cleanup;
311                 }
312         }
313
314         rc = compare(lum_dir, lum_file1, lum_file2);
315
316 cleanup:
317         closedir(dir);
318         if (lum_dir != NULL)
319                 free(lum_dir);
320         if (lum_file1 != NULL)
321                 free(lum_file1);
322         if (lum_file2 != NULL)
323                 free(lum_file2);
324
325         return rc;
326 }