Whamcloud - gitweb
LU-2675 obdclass: remove uses of lov_stripe_md
[fs/lustre-release.git] / lustre / tests / ll_dirstripe_verify.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, Intel Corporation.
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/lustreapi.h>
58
59 #include <lnet/lnetctl.h>
60
61
62 #define MAX_LOV_UUID_COUNT      1000
63 union {
64         struct obd_uuid uuid;
65         char name[0];
66 } lov;
67 #define lov_uuid lov.uuid
68 #define lov_name lov.name
69
70 /* Returns bytes read on success and a negative value on failure.
71  * If zero bytes are read it will be treated as failure as such
72  * zero cannot be returned from this function.
73  */
74 int read_proc_entry(char *proc_path, char *buf, int len)
75 {
76         int rc, fd;
77
78         memset(buf, 0, len);
79
80         fd = open(proc_path, O_RDONLY);
81         if (fd < 0) {
82                 llapi_error(LLAPI_MSG_ERROR, -errno, "cannot open '%s'",
83                             proc_path);
84                 return -2;
85         }
86
87         rc = read(fd, buf, len - 1);
88         if (rc < 0) {
89                 llapi_error(LLAPI_MSG_ERROR, -errno,
90                             "error reading from '%s'", proc_path);
91                 rc = -3;
92         } else if (rc == 0) {
93                 llapi_err_noerrno(LLAPI_MSG_ERROR,
94                                   "read zero bytes from '%s'", proc_path);
95                 rc = -4;
96         } else if (buf[rc - 1] == '\n') {
97                 buf[rc - 1] = '\0'; /* Remove trailing newline */
98         }
99
100         close(fd);
101
102         return rc;
103 }
104
105 int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
106             struct lov_user_md *lum_file2)
107 {
108         int stripe_count = 0, min_stripe_count = 0, def_stripe_count = 1;
109         int stripe_size = 0;
110         int stripe_offset = -1;
111         int ost_count;
112         char buf[128];
113         char lov_path[PATH_MAX];
114         char tmp_path[PATH_MAX];
115         int i;
116         FILE *fp;
117
118         fp = popen("\\ls -d  /proc/fs/lustre/lov/*clilov* | head -1", "r");
119         if (fp == NULL) {
120                 llapi_error(LLAPI_MSG_ERROR, -errno,
121                             "open(lustre/lov/*clilov*) failed");
122                 return 2;
123         }
124
125         if (fscanf(fp, "%s", lov_path) < 1) {
126                 llapi_error(LLAPI_MSG_ERROR, -EINVAL,
127                             "read(lustre/lov/*clilov*) failed");
128                 pclose(fp);
129                 return 3;
130         }
131
132         pclose(fp);
133
134         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripecount",
135                  lov_path);
136         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
137                 return 5;
138         def_stripe_count = (short)atoi(buf);
139
140         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/numobd", lov_path);
141         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
142                 return 6;
143         ost_count = atoi(buf);
144
145         if (lum_dir == NULL) {
146                 stripe_count = def_stripe_count;
147                 min_stripe_count = -1;
148         } else {
149                 stripe_count = (signed short)lum_dir->lmm_stripe_count;
150                 printf("dir stripe %d, ", stripe_count);
151                 min_stripe_count = 1;
152         }
153
154         printf("default stripe %d, ost count %d\n",
155                def_stripe_count, ost_count);
156
157         if (stripe_count == 0) {
158                 min_stripe_count = -1;
159                 stripe_count = 1;
160         }
161
162         stripe_count = (stripe_count > 0 && stripe_count <= ost_count) ?
163                                                 stripe_count : ost_count;
164         min_stripe_count = min_stripe_count > 0 ? stripe_count :
165                                                 ((stripe_count + 1) / 2);
166
167         if (lum_file1->lmm_stripe_count != stripe_count ||
168             lum_file1->lmm_stripe_count < min_stripe_count) {
169                 llapi_err_noerrno(LLAPI_MSG_ERROR,
170                                   "file1 stripe count %d != dir %d\n",
171                                   lum_file1->lmm_stripe_count, stripe_count);
172                 return 7;
173         }
174
175         if (lum_file1->lmm_stripe_count < stripe_count)
176                 llapi_err_noerrno(LLAPI_MSG_WARN,
177                                   "warning: file1 used fewer stripes"
178                                   " %d < dir %d (likely due to bug 4900)\n",
179                                   lum_file1->lmm_stripe_count, stripe_count);
180
181         if (lum_dir != NULL)
182                 stripe_size = (int)lum_dir->lmm_stripe_size;
183         if (stripe_size == 0) {
184                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripesize",
185                          lov_path);
186                 if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
187                         return 5;
188
189                 stripe_size = atoi(buf);
190         }
191
192         if (lum_file1->lmm_stripe_size != stripe_size) {
193                 llapi_err_noerrno(LLAPI_MSG_ERROR,
194                                   "file1 stripe size %d != dir %d\n",
195                                   lum_file1->lmm_stripe_size, stripe_size);
196                 return 8;
197         }
198
199         if (lum_dir != NULL)
200                 stripe_offset = (short int)lum_dir->lmm_stripe_offset;
201         if (stripe_offset != -1) {
202                 for (i = 0; i < stripe_count; i++)
203                         if (lum_file1->lmm_objects[i].l_ost_idx !=
204                             (stripe_offset + i) % ost_count) {
205                                 llapi_err_noerrno(LLAPI_MSG_WARN,
206                                           "warning: file1 non-sequential "
207                                           "stripe[%d] %d != %d\n", i,
208                                           lum_file1->lmm_objects[i].l_ost_idx,
209                                           (stripe_offset + i) % ost_count);
210                         }
211         } else if (lum_file2 != NULL) {
212                 int next, idx, stripe = stripe_count - 1;
213                 next = (lum_file1->lmm_objects[stripe].l_ost_idx + 1) %
214                        ost_count;
215                 idx = lum_file2->lmm_objects[0].l_ost_idx;
216                 if (idx != next) {
217                         llapi_err_noerrno(LLAPI_MSG_WARN,
218                                   "warning: non-sequential "
219                                   "file1 stripe[%d] %d != file2 stripe[0] %d\n",
220                                   stripe, lum_file1->lmm_objects[stripe].l_ost_idx,
221                                   idx);
222                 }
223         }
224
225         return 0;
226 }
227
228 int main(int argc, char **argv)
229 {
230         DIR * dir;
231         struct lov_user_md *lum_dir, *lum_file1 = NULL, *lum_file2 = NULL;
232         int rc;
233         int lum_size;
234
235         if (argc < 3) {
236                 llapi_err_noerrno(LLAPI_MSG_ERROR,
237                                 "Usage: %s <dirname> <filename1> [filename2]\n",
238                                 argv[0]);
239                 return 1;
240         }
241
242         dir = opendir(argv[1]);
243         if (dir == NULL) {
244                 rc = -errno;
245                 llapi_error(LLAPI_MSG_ERROR, rc,
246                             "error: %s opendir failed\n", argv[1]);
247                 return rc;
248         }
249
250         lum_size = lov_user_md_size(MAX_LOV_UUID_COUNT, LOV_USER_MAGIC);
251         lum_dir = (struct lov_user_md *)malloc(lum_size);
252         if (lum_dir == 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 }