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