Whamcloud - gitweb
land b_md onto HEAD:
[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 #warning 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, 'o'},
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 #warning 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 ((obdcount == 0) && (getobdindex(path) == OBD_NOT_FOUND)) {
198                 /* terminate nftw walking this tree */
199                 return(1);
200         }
201
202         if ((fd = open(path, O_RDONLY)) < 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                 exit(1);
216         }
217
218         close(fd);
219
220         if (query || verbose)
221                 printf("\n%s:\n", path);
222
223         if (verbose) {
224                 printf("lmm_magic:          0x%x\n", lmm->lmm_magic);
225                 printf("lmm_object_id:      "LPX64"\n", lmm->lmm_object_id);
226                 printf("lmm_stripe_offset:  %d\n", lmm->lmm_stripe_offset);
227                 printf("lmm_stripe_count:   %d\n", lmm->lmm_stripe_count);
228                 printf("lmm_ost_count:      %d\n", lmm->lmm_ost_count);
229                 printf("lmm_stripe_pattern: %d\n", lmm->lmm_stripe_pattern);
230         }
231
232         count = lmm->lmm_ost_count;
233
234         if (query || verbose) {
235                 struct lov_object_id *loi;
236                 __u64 oid;
237
238                 loi = lmm->lmm_objects;
239
240                 printf("obdidx\tobjid\n");
241
242                 for (i = 0; i < count; i++, loi++)
243                         if ((oid = loi->l_object_id))
244                                 printf("%6d\t%5lld\n", i, (long long)oid);
245
246                 if (query)
247                         return(0);
248         }
249
250         if (lmm->lmm_objects[obdindex].l_object_id)
251                 printf("%s\n", path);
252
253         return(0);
254 }
255
256 __u32
257 getobdindex(const char *path)
258 {
259         obd_uuid_t *uuidp;
260         int fd;
261         int rc;
262         int i;
263
264         if ((fd = open(path, O_RDONLY)) < 0) {
265                 errMsg("open \"%.20s\" failed.", path);
266                 perror("open");
267                 exit(1);
268         }
269
270         data.ioc_inllen1 = sizeof(desc);
271         data.ioc_inlbuf1 = (char *)&desc;
272         data.ioc_inllen2 = uuidslen;
273         data.ioc_inlbuf2 = (char *)uuids;
274         data.ioc_inllen3 = 0;
275
276         memset(&desc, 0, sizeof(desc));
277         desc.ld_tgt_count = max_ost_count;
278
279         if (obd_ioctl_pack(&data, &buf, buflen)) {
280                 errMsg("internal buffering error.");
281                 exit(1);
282         }
283
284         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
285         if (rc) {
286                 errMsg("OBD_IOC_LOV_GET_CONFIG ioctl failed: %d.", errno);
287                 perror("ioctl");
288                 exit(1);
289         }
290
291         if (obd_ioctl_unpack(&data, buf, buflen)) {
292                 errMsg("Invalid reply from ioctl.");
293                 exit(1);
294         }
295
296         close(fd);
297
298         obdcount = desc.ld_tgt_count;
299
300         if (query) {
301                 printf("OBDS:\n");
302                 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
303                         printf("%4d: %s\n", i, (char *)uuidp);
304
305                 return(0);
306         }
307
308         for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
309                 rc = strncmp((const char *)obduuid, (const char *)uuidp,
310                                 sizeof(*uuidp));
311                 if (rc == 0) {
312                         obdindex = i;
313                         break;
314                 }
315         }
316
317         if (obdindex == OBD_NOT_FOUND) {
318                 errMsg("obd UUID '%s' not found.", obduuid);
319                 return(OBD_NOT_FOUND);
320         }
321
322         return(0);
323 }