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