Whamcloud - gitweb
land b1_5 onto HEAD
[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  * ll_dirstripe_verify <dir> <file>:
5  * - to verify if the file has the same lov_user_md setting as the parent dir.
6  * - if dir's offset is set -1, ll_dirstripe_verify <dir> <file1> <file2>
7  *      is used to further verify if file1 and file2's obdidx is continuous.
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <sys/ioctl.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <dirent.h>
19
20 #include <liblustre.h>
21 #include <obd.h>
22 #include <lustre_lib.h>
23 #include <lustre/lustre_user.h>
24 #include <obd_lov.h>
25
26 #include <lnet/lnetctl.h>
27
28
29 #define MAX_LOV_UUID_COUNT      1000
30
31 /* Returns bytes read on success and a negative value on failure.
32  * If zero bytes are read it will be treated as failure as such
33  * zero cannot be returned from this function.
34  */
35 int read_proc_entry(char *proc_path, char *buf, int len)
36 {
37         int rc, fd;
38
39         memset(buf, 0, len);
40
41         fd = open(proc_path, O_RDONLY);
42         if (fd == -1) {
43                 fprintf(stderr, "open('%s') failed: %s\n",
44                         proc_path, strerror(errno));
45                 return -2;
46         }
47
48         rc = read(fd, buf, len - 1);
49         if (rc < 0) {
50                 fprintf(stderr, "read('%s') failed: %s\n",
51                         proc_path, strerror(errno));
52                 rc = -3;
53         } else if (rc == 0) {
54                 fprintf(stderr, "read('%s') zero bytes\n", proc_path);
55                 rc = -4;
56         } else if (/* rc > 0 && */ buf[rc - 1] == '\n') {
57                 buf[rc - 1] = '\0'; /* Remove trailing newline */
58         }
59         close(fd);
60
61         return (rc);
62 }
63
64 int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
65             struct lov_user_md *lum_file2)
66 {
67         int stripe_count = 0;
68         int stripe_size = 0;
69         int stripe_offset = -1;
70         int ost_count;
71         char buf[128];
72         char lov_path[PATH_MAX];
73         char tmp_path[PATH_MAX];
74         int i;
75         FILE *fp;
76
77         fp = popen("\\ls -d  /proc/fs/lustre/lov/*lov* | head -1", "r");
78         if (!fp) {
79                 fprintf(stderr, "open(lustre/lov/*lov*) failed: %s\n", 
80                         strerror(errno));
81                 return 2;
82         }
83         if (fscanf(fp, "%s", lov_path) < 1) { 
84                 fprintf(stderr, "read(lustre/lov/*lov*) failed: %s\n",
85                         strerror(errno));
86                 pclose(fp);
87                 return 3;
88         }
89         pclose(fp);
90
91         if (lum_dir == NULL) {
92                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripecount",
93                          lov_path);
94                 if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
95                         return 5;
96
97                 stripe_count = atoi(buf);
98         } else {
99                 stripe_count = (int)lum_dir->lmm_stripe_count;
100         }
101         if (stripe_count == 0)
102                 stripe_count = 1;
103
104         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/numobd", lov_path);
105         if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
106                 return 6;
107
108         ost_count = atoi(buf);
109         stripe_count = stripe_count > 0 ? stripe_count : ost_count;
110
111         if (lum_file1->lmm_stripe_count != stripe_count) {
112                 fprintf(stderr, "file1 stripe count %d != dir %d\n",
113                         lum_file1->lmm_stripe_count, stripe_count);
114                 return 7;
115         }
116
117         if (lum_dir != NULL)
118                 stripe_size = (int)lum_dir->lmm_stripe_size;
119         if (stripe_size == 0) {
120                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripesize",
121                          lov_path);
122                 if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
123                         return 5;
124
125                 stripe_size = atoi(buf);
126         }
127
128         if (lum_file1->lmm_stripe_size != stripe_size) {
129                 fprintf(stderr, "file1 stripe size %d != dir %d\n",
130                         lum_file1->lmm_stripe_size, stripe_size);
131                 return 8;
132         }
133
134         if (lum_dir != NULL)
135                 stripe_offset = (short int)lum_dir->lmm_stripe_offset;
136         if (stripe_offset != -1) {
137                 for (i = 0; i < stripe_count; i++)
138                         if (lum_file1->lmm_objects[i].l_ost_idx !=
139                             (stripe_offset + i) % ost_count) {
140                                 fprintf(stderr, "warning: file1 non-sequential "
141                                         "stripe[%d] %d != %d\n", i,
142                                         lum_file1->lmm_objects[i].l_ost_idx,
143                                         (stripe_offset + i) % ost_count);
144                         }
145         } else if (lum_file2 != NULL) {
146                 int next, idx, stripe = stripe_count - 1;
147                 next = (lum_file1->lmm_objects[stripe].l_ost_idx + 1) %
148                        ost_count;
149                 idx = lum_file2->lmm_objects[0].l_ost_idx;
150                 if (idx != next) {
151                         fprintf(stderr, "warning: non-sequential "
152                                 "file1 stripe[%d] %d != file2 stripe[0] %d\n",
153                                 stripe,
154                                 lum_file1->lmm_objects[stripe].l_ost_idx, idx);
155                 }
156         }
157
158         return 0;
159 }
160
161 int main(int argc, char **argv)
162 {
163         DIR * dir;
164         struct lov_user_md *lum_dir, *lum_file1 = NULL, *lum_file2 = NULL;
165         int rc;
166         int lum_size;
167         char *fname;
168
169         if (argc < 3) {
170                 fprintf(stderr, "Usage: %s <dirname> <filename1> [filename2]\n",
171                         argv[0]);
172                 return 1;
173         }
174
175         dir = opendir(argv[1]);
176         if (dir == NULL) {
177                 fprintf(stderr, "%s opendir failed: %s\n", argv[1], 
178                         strerror(errno));
179                 return errno;
180         }
181
182         lum_size = lov_mds_md_size(MAX_LOV_UUID_COUNT);
183         if ((lum_dir = (struct lov_user_md *)malloc(lum_size)) == NULL) {
184                 fprintf(stderr, "unable to allocate memory for ioctl's");
185                 return errno;
186         }
187
188         rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, lum_dir);
189         if (rc) {
190                 if (errno == ENODATA) {
191                         free(lum_dir);
192                         lum_dir = NULL;
193                 } else {
194                         rc = errno;
195                         goto cleanup;
196                 }
197         }
198
199         if ((lum_file1 = (struct lov_user_md *)malloc(lum_size)) == NULL) {
200                 fprintf(stderr, "unable to allocate memory for ioctl's");
201                 rc = errno;
202                 goto cleanup;
203         }
204
205         fname = strrchr(argv[2], '/');
206         fname = (fname == NULL ? argv[2] : fname + 1);
207
208         strncpy((char *)lum_file1, fname, lum_size);
209         rc = ioctl(dirfd(dir), IOC_MDC_GETFILESTRIPE, lum_file1);
210         if (rc) {
211                 rc = errno;
212                 goto cleanup;
213         }
214
215         if (argc == 4) {
216                 lum_file2 = (struct lov_user_md *)malloc(lum_size);
217                 if (lum_file2 == NULL) {
218                         fprintf(stderr,
219                                 "unable to allocate memory for ioctl's");
220                         rc = errno;
221                         goto cleanup;
222                 }
223
224                 fname = strrchr(argv[3], '/');
225                 fname = (fname == NULL ? argv[3] : fname + 1);
226                 strncpy((char *)lum_file2, fname, lum_size);
227                 rc = ioctl(dirfd(dir), IOC_MDC_GETFILESTRIPE, lum_file2);
228                 if (rc) {
229                         rc = errno;
230                         goto cleanup;
231                 }
232         }
233
234         rc = compare(lum_dir, lum_file1, lum_file2);
235
236 cleanup:
237         if (lum_dir != NULL)
238                 free(lum_dir);
239         if (lum_file1 != NULL)
240                 free(lum_file1);
241         if (lum_file2 != NULL)
242                 free(lum_file2);
243
244         return rc;
245 }