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