Whamcloud - gitweb
Merge b_md to HEAD for 0.5.19 release.
[fs/lustre-release.git] / lustre / utils / lfind.c
1 #define _XOPEN_SOURCE 500
2
3 #include <stdio.h>
4 #include <getopt.h>
5 #include <stdlib.h>
6 #include <stdarg.h>
7 #include <libgen.h>
8 #include <ftw.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <sys/ioctl.h>
13 #include <sys/types.h>
14 #define printk printf
15 #include <linux/lustre_lib.h>
16 #include <linux/lustre_lite.h>
17 #include <linux/obd_lov.h>
18
19 /* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
20 #define MAX_LOV_UUID_COUNT      1000
21 #define OBD_NOT_FOUND           ((__u32)-1)
22
23 char *          cmd;
24 struct option   longOpts[] = {
25                         {"help", 0, 0, 'h'},
26                         {"obd", 1, 0, 'o'},
27                         {"query", 0, 0, 'q'},
28                         {"verbose", 0, 0, 'v'},
29                         {0, 0, 0, 0}
30                 };
31 int             query;
32 int             verbose;
33 char *          shortOpts = "ho:qv";
34 char *          usageMsg = "[ --obd <obd uuid> | --query ] <dir|file> ...";
35
36 int             max_ost_count = MAX_LOV_UUID_COUNT;
37 obd_uuid_t *    obduuid;
38 __u32           obdcount;
39 __u32           obdindex;
40 char *          buf;
41 int             buflen;
42 struct obd_ioctl_data data;
43 struct lov_desc desc;
44 obd_uuid_t *    uuids;
45 int             uuidslen;
46 int             cfglen;
47 struct lov_mds_md *lmm;
48 int             lmmlen;
49
50 void    init();
51 void    usage(FILE *stream);
52 void    errMsg(char *fmt, ...);
53 void    processPath(char *path);
54 int     processFile(
55                 const char *path,
56                 const struct stat *sp,
57                 int flag,
58                 struct FTW *ftwp
59         );
60 __u32   getobdindex(const char *path);
61
62 int
63 main (int argc, char **argv) {
64         int c;
65
66         cmd = basename(argv[0]);
67
68         while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1) {
69                 switch (c) {
70                 case 'o':
71                         if (obduuid) {
72                                 errMsg("obd '%s' already specified: '%s'.",
73                                         obduuid, optarg);
74                                 exit(1);
75                         }
76
77                         obduuid = (obd_uuid_t *)optarg;
78                         break;
79                 case 'h':
80                         usage(stdout);
81                         exit(0);
82                 case 'q':
83                         query++;
84                         break;
85                 case 'v':
86                         verbose++;
87                         break;
88                 case '?':
89                         usage(stderr);
90                         exit(1);
91                 default:
92                         errMsg("Internal error. Valid '%s' unrecognized.",
93                                 argv[optind - 1]);
94                         usage(stderr);
95                         exit(1);
96                 }
97         }
98
99         if (optind >= argc) {
100                 usage(stderr);
101                 exit(1);
102         }
103
104         if (obduuid == NULL)
105                 query++;
106
107         init();
108
109         do {
110                 processPath(argv[optind]);
111         } while (++optind < argc);
112
113         exit (0);
114 }
115
116 void
117 init()
118 {
119         int datalen, desclen;
120
121         datalen = size_round(sizeof(data));
122         desclen = size_round(sizeof(desc));
123         uuidslen = size_round(max_ost_count * sizeof(*uuids));
124         cfglen = datalen + desclen + uuidslen;
125         lmmlen = lov_mds_md_size(max_ost_count);
126         if (cfglen > lmmlen)
127                 buflen = cfglen;
128         else
129                 buflen = lmmlen;
130
131         /* XXX max ioctl buffer size currently hardcoded to 8192 */
132         if (buflen > 8192) {
133                 int nuuids, remaining, nluoinfos;
134
135                 buflen = 8192;
136                 nuuids = (buflen - datalen - desclen) / sizeof(*uuids);
137                 uuidslen = size_round(nuuids * sizeof(*uuids));
138                 remaining = nuuids * sizeof(*uuids);
139                 if (uuidslen > remaining)
140                         nuuids--;
141                 nluoinfos = (buflen - sizeof(*lmm)) / sizeof(*lmm->lmm_objects);
142                 if (nuuids > nluoinfos)
143                         max_ost_count = nluoinfos;
144                 else
145                         max_ost_count = nuuids;
146
147                 cfglen = datalen + desclen + uuidslen;
148                 lmmlen = lov_mds_md_size(max_ost_count);
149         }
150
151         if ((buf = malloc(buflen)) == NULL) {
152                 errMsg("Unable to allocate %d bytes of memory for ioctl's.",
153                         buflen);
154                 exit(1);
155         }
156
157         lmm = (struct lov_mds_md *)buf;
158         uuids = (obd_uuid_t *)buf;
159 }
160
161 void
162 usage(FILE *stream)
163 {
164         fprintf(stream, "usage: %s %s\n", cmd, usageMsg);
165 }
166
167 void
168 errMsg(char *fmt, ...)
169 {
170         va_list args;
171
172         fprintf(stderr, "%s: ", cmd);
173         va_start(args, fmt);
174         vfprintf(stderr, fmt, args);
175         va_end(args);
176         fprintf(stderr, "\n");
177 }
178
179 void
180 processPath(char *path)
181 {
182         obdindex = OBD_NOT_FOUND;
183         nftw((const char *)path, processFile, 128, FTW_PHYS|FTW_MOUNT);
184 }
185
186 int
187 processFile(const char *path, const struct stat *sp, int flag, struct FTW *ftwp)
188 {
189         int fd;
190         int count;
191         int rc;
192         int i;
193
194         if (flag != FTW_F)
195                 return 0;
196
197         if (getobdindex(path) == OBD_NOT_FOUND && obdcount == 0) {
198                 /* terminate nftw walking this tree */
199                 return(1);
200         }
201
202         if ((fd = open(path, O_RDONLY | O_LOV_DELAY_CREATE)) < 0) {
203                 errMsg("open \"%.20s\" failed.", path);
204                 perror("open");
205                 exit(1);
206         }
207
208         memset((void *)buf, 0, buflen);
209         lmm->lmm_magic = LOV_MAGIC;
210         lmm->lmm_ost_count = max_ost_count;
211
212         if ((rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, (void *)lmm)) < 0) {
213                 errMsg("LL_IOC_LOV_GETSTRIPE ioctl failed.");
214                 perror("ioctl");
215                 return 0;
216         }
217
218         close(fd);
219
220         if (query || verbose ||
221             (obdindex != OBD_NOT_FOUND &&
222              lmm->lmm_objects[obdindex].l_object_id))
223                 printf("%s\n", path);
224
225         if (verbose) {
226                 printf("lmm_magic:          0x%x\n", lmm->lmm_magic);
227                 printf("lmm_object_id:      "LPX64"\n", lmm->lmm_object_id);
228                 printf("lmm_stripe_offset:  %u\n", (int)lmm->lmm_stripe_offset);
229                 printf("lmm_stripe_count:   %u\n", (int)lmm->lmm_stripe_count);
230                 printf("lmm_stripe_size:    %u\n", (int)lmm->lmm_stripe_size);
231                 printf("lmm_ost_count:      %u\n", lmm->lmm_ost_count);
232                 printf("lmm_stripe_pattern: %d\n", lmm->lmm_magic & 0xf);
233         }
234
235         count = lmm->lmm_ost_count;
236
237         if (query || verbose) {
238                 long long oid;
239                 int ost = lmm->lmm_stripe_offset;
240                 int header = 1;
241
242                 for (i = 0; i < count; i++, ost++) {
243                         ost %= lmm->lmm_ost_count;
244                         if ((oid = lmm->lmm_objects[ost].l_object_id)) {
245                                 if (header) {
246                                         printf("\tobdidx\t   objid\n");
247                                         header = 0;
248                                 }
249                                 printf("\t%6u\t%8llu%s\n",
250                                        ost, oid, obdindex == ost ? " *" : "");
251                         }
252                 }
253
254                 if (query)
255                         return(0);
256         }
257
258         return(0);
259 }
260
261 __u32
262 getobdindex(const char *path)
263 {
264         obd_uuid_t *uuidp;
265         int fd;
266         int rc;
267         int i;
268
269         if ((fd = open(path, O_RDONLY)) < 0) {
270                 errMsg("open \"%.20s\" failed.", path);
271                 perror("open");
272                 exit(1);
273         }
274
275         data.ioc_inllen1 = sizeof(desc);
276         data.ioc_inlbuf1 = (char *)&desc;
277         data.ioc_inllen2 = uuidslen;
278         data.ioc_inlbuf2 = (char *)uuids;
279         data.ioc_inllen3 = 0;
280
281         memset(&desc, 0, sizeof(desc));
282         desc.ld_tgt_count = max_ost_count;
283
284         if (obd_ioctl_pack(&data, &buf, buflen)) {
285                 errMsg("internal buffering error.");
286                 exit(1);
287         }
288
289         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
290         if (rc) {
291                 errMsg("OBD_IOC_LOV_GET_CONFIG ioctl failed: %d.", errno);
292                 perror("ioctl");
293                 exit(1);
294         }
295
296         if (obd_ioctl_unpack(&data, buf, buflen)) {
297                 errMsg("Invalid reply from ioctl.");
298                 exit(1);
299         }
300
301         close(fd);
302
303         obdcount = desc.ld_tgt_count;
304
305         if (query || verbose) {
306                 printf("OBDS:\n");
307                 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
308                         printf("%4d: %s\n", i, (char *)uuidp);
309
310                 return(0);
311         }
312
313         for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
314                 rc = strncmp((const char *)obduuid, (const char *)uuidp,
315                                 sizeof(*uuidp));
316                 if (rc == 0) {
317                         obdindex = i;
318                         break;
319                 }
320         }
321
322         if (obdindex == OBD_NOT_FOUND) {
323                 errMsg("obd UUID '%s' not found.", obduuid);
324                 return(OBD_NOT_FOUND);
325         }
326
327         return(0);
328 }