Whamcloud - gitweb
file netpoll-core.pc was initially added on branch b_devel.
[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 int              printed_UUIDs;
49
50 void    init();
51 void    usage(FILE *stream);
52 void    errMsg(char *fmt, ...);
53 void    processPath(char *path);
54
55 int 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                                 printf("obd '%s' already specified: '%s'\n",
65                                         obduuid->uuid, 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                         printf("Internal error. Valid '%s' unrecognized\n",
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 init()
109 {
110         int datalen, desclen;
111
112         datalen = size_round(sizeof(data));
113         desclen = size_round(sizeof(desc));
114         uuidslen = size_round(max_ost_count * sizeof(*uuids));
115         cfglen = datalen + desclen + uuidslen;
116         lmmlen = lov_mds_md_size(max_ost_count);
117         if (cfglen > lmmlen)
118                 buflen = cfglen;
119         else
120                 buflen = lmmlen;
121
122         /* XXX max ioctl buffer size currently hardcoded to 8192 */
123         if (buflen > 8192) {
124                 int nuuids, remaining, nluoinfos;
125
126                 buflen = 8192;
127                 nuuids = (buflen - datalen - desclen) / sizeof(*uuids);
128                 uuidslen = size_round(nuuids * sizeof(*uuids));
129                 remaining = nuuids * sizeof(*uuids);
130                 if (uuidslen > remaining)
131                         nuuids--;
132                 nluoinfos = (buflen - sizeof(*lmm)) / sizeof(*lmm->lmm_objects);
133                 if (nuuids > nluoinfos)
134                         max_ost_count = nluoinfos;
135                 else
136                         max_ost_count = nuuids;
137
138                 cfglen = datalen + desclen + uuidslen;
139                 lmmlen = lov_mds_md_size(max_ost_count);
140         }
141
142         if ((buf = malloc(buflen)) == NULL) {
143                 errMsg("Unable to allocate %d bytes of memory for ioctl's");
144                 exit(1);
145         }
146
147         lmm = (struct lov_mds_md *)buf;
148         uuids = (struct obd_uuid *)buf;
149 }
150
151 void usage(FILE *stream)
152 {
153         fprintf(stream, "usage: %s %s\n", cmd, usageMsg);
154 }
155
156 void errMsg(char *fmt, ...)
157 {
158         va_list args;
159         int tmp_errno = errno;
160
161         fprintf(stderr, "%s: ", cmd);
162         va_start(args, fmt);
163         vfprintf(stderr, fmt, args);
164         va_end(args);
165         fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
166 }
167
168 void processPath(char *path)
169 {
170         int fd;
171         int rc;
172         int i;
173         int obdindex = OBD_NOT_FOUND;
174         int obdcount;
175         struct obd_uuid *uuidp;
176         char *fname, *dirname;
177
178         if ((query || verbose) && !obduuid) {
179                 printf("%s\n", path);
180         }
181
182         fname = strrchr(path, '/');
183         if (fname != NULL && fname[1] != '\0') {
184                 *fname = '\0';
185                 fname++;
186                 dirname = path;
187         } else if (fname != NULL && fname[1] == '\0') {
188                 printf("need getdents support\n");
189                 return;
190         } else {
191                 dirname = ".";
192                 fname = path;
193         }
194
195         if ((fd = open(dirname, O_RDONLY)) < 0) {
196                 errMsg("open \"%.20s\" failed", dirname);
197                 return;
198         }
199
200         if (!printed_UUIDs) {
201                 memset(&data, 0, sizeof(data));
202                 data.ioc_inllen1 = sizeof(desc);
203                 data.ioc_inlbuf1 = (char *)&desc;
204                 data.ioc_inllen2 = uuidslen;
205                 data.ioc_inlbuf2 = (char *)uuids;
206
207                 memset(&desc, 0, sizeof(desc));
208                 desc.ld_tgt_count = max_ost_count;
209
210                 if (obd_ioctl_pack(&data, &buf, buflen)) {
211                         errMsg("internal buffering error");
212                         exit(1);
213                 }
214
215                 rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
216                 if (rc) {
217                         if (errno == ENOTTY) {
218                                 if (!obduuid) {
219                                         errMsg("error getting LOV config");
220                                 }
221                                 return;
222                         }
223                         errMsg("OBD_IOC_LOV_GET_CONFIG ioctl failed: %s");
224                         exit(1);
225                 }
226
227                 if (obd_ioctl_unpack(&data, buf, buflen)) {
228                         errMsg("Invalid reply from ioctl");
229                         exit(1);
230                 }
231
232                 obdcount = desc.ld_tgt_count;
233                 if (obdcount == 0)
234                         return;
235
236                 obdindex = OBD_NOT_FOUND;
237
238                 if (obduuid) {
239                         for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
240                                 if (strncmp((char *)obduuid, (char *)uuidp,
241                                         sizeof(*uuidp)) == 0) {
242                                         obdindex = i;
243                                 }
244                         }
245
246                         if (obdindex == OBD_NOT_FOUND)
247                                 return;
248                 } else if (query || verbose) {
249                         printf("OBDS:\n");
250                         for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
251                                 printf("%4d: %s\n", i, (char *)uuidp);
252                 }
253                 printed_UUIDs = 1;
254         }
255
256         strcpy((char *)lmm, fname);
257         rc = ioctl(fd, IOC_MDC_GETSTRIPE, (void *)lmm);
258         if (rc) {
259                 if (errno == ENODATA) {
260                         if (!obduuid)
261                                 printf("Has no stripe information.\n");
262                 }
263                 else {
264                         errMsg("IOC_MDC_GETSTRIPE ioctl failed");
265                 }
266                 return;
267         }
268
269         close(fd);
270
271         if (obduuid && lmm->lmm_objects[obdindex].l_object_id)
272                 printf("%s\n", path);
273
274         if (verbose) {
275                 printf("lmm_magic:          0x%x\n", lmm->lmm_magic);
276                 printf("lmm_object_id:      "LPX64"\n", lmm->lmm_object_id);
277                 printf("lmm_stripe_offset:  %u\n", (int)lmm->lmm_stripe_offset);
278                 printf("lmm_stripe_count:   %u\n", (int)lmm->lmm_stripe_count);
279                 printf("lmm_stripe_size:    %u\n", (int)lmm->lmm_stripe_size);
280                 printf("lmm_ost_count:      %u\n", lmm->lmm_ost_count);
281                 printf("lmm_stripe_pattern: %d\n", lmm->lmm_magic & 0xf);
282         }
283
284         if (query || verbose) {
285                 long long oid;
286                 int ost = lmm->lmm_stripe_offset;
287                 int header = 1;
288
289                 for (i = 0; i < lmm->lmm_ost_count; i++, ost++) {
290                         ost %= lmm->lmm_ost_count;
291                         if ((oid = lmm->lmm_objects[ost].l_object_id)) {
292                                 if (header) {
293                                         printf("\tobdidx\t   objid\n");
294                                         header = 0;
295                                 }
296                                 printf("\t%6u\t%8llu%s\n",
297                                        ost, oid, obdindex == ost ? " *" : "");
298                         }
299                 }
300                 printf("\n");
301         }
302 }