Whamcloud - gitweb
b=22766 cascading_rw: take lmm_stripe_count returned by ioctl(LL_IOC_LOV_SETSTRIPE)
[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  * 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/*clilov* | head -1", "r");
118         if (!fp) {
119                 llapi_err(LLAPI_MSG_ERROR,
120                           "open(lustre/lov/*clilov*) failed: %s\n");
121                 return 2;
122         }
123         if (fscanf(fp, "%s", lov_path) < 1) {
124                 llapi_err(LLAPI_MSG_ERROR,
125                           "read(lustre/lov/*clilov*) failed: %s\n");
126                 pclose(fp);
127                 return 3;
128         }
129         pclose(fp);
130
131         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripecount",
132                  lov_path);
133         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
134                 return 5;
135         def_stripe_count = (short)atoi(buf);
136
137         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/numobd", lov_path);
138         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
139                 return 6;
140         ost_count = atoi(buf);
141
142         if (lum_dir == NULL) {
143                 stripe_count = def_stripe_count;
144                 min_stripe_count = -1;
145         } else {
146                 stripe_count = (signed short)lum_dir->lmm_stripe_count;
147                 printf("dir stripe %d, ", stripe_count);
148                 min_stripe_count = 1;
149         }
150
151         printf("default stripe %d, ost count %d\n",
152                def_stripe_count, ost_count);
153
154         if (stripe_count == 0) {
155                 min_stripe_count = -1;
156                 stripe_count = 1;
157         }
158
159         stripe_count = (stripe_count > 0 && stripe_count <= ost_count) ?
160                                                 stripe_count : ost_count;
161         min_stripe_count = min_stripe_count > 0 ? stripe_count :
162                                                 ((stripe_count + 1) / 2);
163
164         if (lum_file1->lmm_stripe_count != stripe_count ||
165             lum_file1->lmm_stripe_count < min_stripe_count) {
166                 llapi_err(LLAPI_MSG_ERROR, "file1 stripe count %d != dir %d\n",
167                           lum_file1->lmm_stripe_count, stripe_count);
168                 return 7;
169         }
170
171         if (lum_file1->lmm_stripe_count < stripe_count)
172                 llapi_err(LLAPI_MSG_WARN, "warning: file1 used fewer stripes"
173                           " %d < dir %d (likely due to bug 4900)\n",
174                           lum_file1->lmm_stripe_count, stripe_count);
175
176         if (lum_dir != NULL)
177                 stripe_size = (int)lum_dir->lmm_stripe_size;
178         if (stripe_size == 0) {
179                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripesize",
180                          lov_path);
181                 if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
182                         return 5;
183
184                 stripe_size = atoi(buf);
185         }
186
187         if (lum_file1->lmm_stripe_size != stripe_size) {
188                 llapi_err(LLAPI_MSG_ERROR, "file1 stripe size %d != dir %d\n",
189                           lum_file1->lmm_stripe_size, stripe_size);
190                 return 8;
191         }
192
193         if (lum_dir != NULL)
194                 stripe_offset = (short int)lum_dir->lmm_stripe_offset;
195         if (stripe_offset != -1) {
196                 for (i = 0; i < stripe_count; i++)
197                         if (lum_file1->lmm_objects[i].l_ost_idx !=
198                             (stripe_offset + i) % ost_count) {
199                                 llapi_err(LLAPI_MSG_WARN,
200                                           "warning: file1 non-sequential "
201                                           "stripe[%d] %d != %d\n", i,
202                                           lum_file1->lmm_objects[i].l_ost_idx,
203                                           (stripe_offset + i) % ost_count);
204                         }
205         } else if (lum_file2 != NULL) {
206                 int next, idx, stripe = stripe_count - 1;
207                 next = (lum_file1->lmm_objects[stripe].l_ost_idx + 1) %
208                        ost_count;
209                 idx = lum_file2->lmm_objects[0].l_ost_idx;
210                 if (idx != next) {
211                         llapi_err(LLAPI_MSG_WARN, "warning: non-sequential "
212                                   "file1 stripe[%d] %d != file2 stripe[0] %d\n",
213                                   stripe, lum_file1->lmm_objects[stripe].l_ost_idx,
214                                   idx);
215                 }
216         }
217
218         return 0;
219 }
220
221 int main(int argc, char **argv)
222 {
223         DIR * dir;
224         struct lov_user_md *lum_dir, *lum_file1 = NULL, *lum_file2 = NULL;
225         int rc;
226         int lum_size;
227
228         if (argc < 3) {
229                 llapi_err(LLAPI_MSG_ERROR,
230                           "Usage: %s <dirname> <filename1> [filename2]\n",
231                           argv[0]);
232                 return 1;
233         }
234
235         dir = opendir(argv[1]);
236         if (dir == NULL) {
237                 rc = errno;
238                 llapi_err(LLAPI_MSG_ERROR,
239                           "error: %s opendir failed\n", argv[1]);
240                 return rc;
241         }
242
243         lum_size = lov_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC);
244         if ((lum_dir = (struct lov_user_md *)malloc(lum_size)) == NULL) {
245                 rc = ENOMEM;
246                 llapi_err(LLAPI_MSG_ERROR, "error: can't allocate %d bytes "
247                           "for dir EA", lum_size);
248                 goto cleanup;
249         }
250
251         rc = llapi_file_get_stripe(argv[1], lum_dir);
252         if (rc) {
253                 if (errno == ENODATA) {
254                         free(lum_dir);
255                         lum_dir = NULL;
256                 } else {
257                         rc = errno;
258                         llapi_err(LLAPI_MSG_ERROR,
259                                   "error: can't get EA for %s\n", argv[1]);
260                         goto cleanup;
261                 }
262         }
263
264         /* XXX should be llapi_lov_getname() */
265         rc = llapi_file_get_lov_uuid(argv[1], &lov_uuid);
266         if (rc) {
267                 rc = errno;
268                 llapi_err(LLAPI_MSG_ERROR, "error: can't get lov name for %s\n",
269                           argv[1]);
270                 return rc;
271         }
272
273         if ((lum_file1 = (struct lov_user_md *)malloc(lum_size)) == NULL) {
274                 rc = ENOMEM;
275                 llapi_err(LLAPI_MSG_ERROR,
276                           "error: can't allocate %d bytes for EA\n", lum_size);
277                 goto cleanup;
278         }
279
280         rc = llapi_file_get_stripe(argv[2], lum_file1);
281         if (rc) {
282                 rc = errno;
283                 llapi_err(LLAPI_MSG_ERROR,
284                           "error: unable to get EA for %s\n", argv[2]);
285                 goto cleanup;
286         }
287
288         if (argc == 4) {
289                 lum_file2 = (struct lov_user_md *)malloc(lum_size);
290                 if (lum_file2 == NULL) {
291                         rc = ENOMEM;
292                         llapi_err(LLAPI_MSG_ERROR, "error: can't allocate %d "
293                                   "bytes for file2 EA\n", lum_size);
294                         goto cleanup;
295                 }
296
297                 rc = llapi_file_get_stripe(argv[3], lum_file2);
298                 if (rc) {
299                         rc = errno;
300                         llapi_err(LLAPI_MSG_ERROR,
301                                   "error: can't get EA for %s\n", argv[3]);
302                         goto cleanup;
303                 }
304         }
305
306         rc = compare(lum_dir, lum_file1, lum_file2);
307
308 cleanup:
309         closedir(dir);
310         if (lum_dir != NULL)
311                 free(lum_dir);
312         if (lum_file1 != NULL)
313                 free(lum_file1);
314         if (lum_file2 != NULL)
315                 free(lum_file2);
316
317         return rc;
318 }