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