Whamcloud - gitweb
LU-1146 build: batch update copyright messages
[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  * Copyright (c) 2011, Whamcloud, Inc.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  *
38  * lustre/tests/ll_dirstripe_verify.c
39  *
40  * ll_dirstripe_verify <dir> <file>:
41  * - to verify if the file has the same lov_user_md setting as the parent dir.
42  * - if dir's offset is set -1, ll_dirstripe_verify <dir> <file1> <file2>
43  *      is used to further verify if file1 and file2's obdidx is continuous.
44  */
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <ctype.h>
50 #include <sys/ioctl.h>
51 #include <unistd.h>
52 #include <fcntl.h>
53 #include <errno.h>
54 #include <dirent.h>
55
56 #include <liblustre.h>
57 #include <obd.h>
58 #include <lustre_lib.h>
59 #include <lustre/liblustreapi.h>
60 #include <obd_lov.h>
61
62 #include <lnet/lnetctl.h>
63
64
65 #define MAX_LOV_UUID_COUNT      1000
66 union {
67         struct obd_uuid uuid;
68         char name[0];
69 } lov;
70 #define lov_uuid lov.uuid
71 #define lov_name lov.name
72
73 /* Returns bytes read on success and a negative value on failure.
74  * If zero bytes are read it will be treated as failure as such
75  * zero cannot be returned from this function.
76  */
77 int read_proc_entry(char *proc_path, char *buf, int len)
78 {
79         int rc, fd;
80
81         memset(buf, 0, len);
82
83         fd = open(proc_path, O_RDONLY);
84         if (fd == -1) {
85                 llapi_error(LLAPI_MSG_ERROR, -errno, "open('%s') failed: %s\n",
86                             proc_path);
87                 return -2;
88         }
89
90         rc = read(fd, buf, len - 1);
91         if (rc < 0) {
92                 llapi_error(LLAPI_MSG_ERROR, -errno,
93                             "read('%s') failed: %s\n", proc_path);
94                 rc = -3;
95         } else if (rc == 0) {
96                 llapi_err_noerrno(LLAPI_MSG_ERROR,
97                                   "read('%s') zero bytes\n", proc_path);
98                 rc = -4;
99         } else if (/* rc > 0 && */ buf[rc - 1] == '\n') {
100                 buf[rc - 1] = '\0'; /* Remove trailing newline */
101         }
102         close(fd);
103
104         return (rc);
105 }
106
107 int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
108             struct lov_user_md *lum_file2)
109 {
110         int stripe_count = 0, min_stripe_count = 0, def_stripe_count = 1;
111         int stripe_size = 0;
112         int stripe_offset = -1;
113         int ost_count;
114         char buf[128];
115         char lov_path[PATH_MAX];
116         char tmp_path[PATH_MAX];
117         int i;
118         FILE *fp;
119
120         fp = popen("\\ls -d  /proc/fs/lustre/lov/*clilov* | head -1", "r");
121         if (!fp) {
122                 llapi_error(LLAPI_MSG_ERROR, -errno,
123                             "open(lustre/lov/*clilov*) failed: %s\n");
124                 return 2;
125         }
126         if (fscanf(fp, "%s", lov_path) < 1) {
127                 llapi_error(LLAPI_MSG_ERROR, -EINVAL,
128                             "read(lustre/lov/*clilov*) failed: %s\n");
129                 pclose(fp);
130                 return 3;
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_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC);
251         if ((lum_dir = (struct lov_user_md *)malloc(lum_size)) == NULL) {
252                 rc = -ENOMEM;
253                 llapi_error(LLAPI_MSG_ERROR, rc,
254                             "error: can't allocate %d bytes "
255                             "for dir EA", lum_size);
256                 goto cleanup;
257         }
258
259         rc = llapi_file_get_stripe(argv[1], lum_dir);
260         if (rc) {
261                 if (rc == -ENODATA) {
262                         free(lum_dir);
263                         lum_dir = NULL;
264                 } else {
265                         llapi_error(LLAPI_MSG_ERROR, rc,
266                                     "error: can't get EA for %s\n", argv[1]);
267                         goto cleanup;
268                 }
269         }
270
271         /* XXX should be llapi_lov_getname() */
272         rc = llapi_file_get_lov_uuid(argv[1], &lov_uuid);
273         if (rc) {
274                 llapi_error(LLAPI_MSG_ERROR, rc,
275                             "error: can't get lov name for %s\n",
276                             argv[1]);
277                 return rc;
278         }
279
280         if ((lum_file1 = (struct lov_user_md *)malloc(lum_size)) == NULL) {
281                 rc = -ENOMEM;
282                 llapi_error(LLAPI_MSG_ERROR, rc,
283                             "error: can't allocate %d bytes for EA\n",
284                             lum_size);
285                 goto cleanup;
286         }
287
288         rc = llapi_file_get_stripe(argv[2], lum_file1);
289         if (rc) {
290                 llapi_error(LLAPI_MSG_ERROR, rc,
291                             "error: unable to get EA for %s\n", argv[2]);
292                 goto cleanup;
293         }
294
295         if (argc == 4) {
296                 lum_file2 = (struct lov_user_md *)malloc(lum_size);
297                 if (lum_file2 == NULL) {
298                         rc = -ENOMEM;
299                         llapi_error(LLAPI_MSG_ERROR, rc,
300                                     "error: can't allocate %d "
301                                     "bytes for file2 EA\n", lum_size);
302                         goto cleanup;
303                 }
304
305                 rc = llapi_file_get_stripe(argv[3], lum_file2);
306                 if (rc) {
307                         llapi_error(LLAPI_MSG_ERROR, rc,
308                                     "error: can't get EA for %s\n", argv[3]);
309                         goto cleanup;
310                 }
311         }
312
313         rc = compare(lum_dir, lum_file1, lum_file2);
314
315 cleanup:
316         closedir(dir);
317         if (lum_dir != NULL)
318                 free(lum_dir);
319         if (lum_file1 != NULL)
320                 free(lum_file1);
321         if (lum_file2 != NULL)
322                 free(lum_file2);
323
324         return rc;
325 }