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