Whamcloud - gitweb
f13072a581e3e6070b6a6fdefe70471c518d9b69
[fs/lustre-release.git] / lustre / utils / liblustreapi.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Robert Read <rread@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27 /* for O_DIRECTORY */
28 #define _GNU_SOURCE
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stddef.h>
34 #include <sys/ioctl.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <dirent.h>
39 #include <stdarg.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #ifdef HAVE_LINUX_TYPES_H
43 #include <linux/types.h>
44 #else
45 #include "types.h"
46 #endif
47 #ifdef HAVE_LINUX_UNISTD_H
48 #include <linux/unistd.h>
49 #else
50 #include <unistd.h>
51 #endif
52 #include <liblustre.h>
53 #include <linux/obd.h>
54 #include <linux/lustre_lib.h>
55 #include <linux/lustre_acl.h>
56 #include <lustre/lustre_user.h>
57 #include <linux/obd_lov.h>
58 #include <portals/ptlctl.h>
59
60 static void err_msg(char *fmt, ...)
61 {
62         va_list args;
63         int tmp_errno = errno;
64
65         va_start(args, fmt);
66         vfprintf(stderr, fmt, args);
67         va_end(args);
68         fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
69 }
70
71 int llapi_file_create(char *name, long stripe_size, int stripe_offset,
72                       int stripe_count, int stripe_pattern)
73 {
74         struct lov_user_md lum = { 0 };
75         int fd, rc = 0;
76         int isdir = 0;
77
78         /*  Initialize IOCTL striping pattern structure  */
79         lum.lmm_magic = LOV_USER_MAGIC;
80         lum.lmm_pattern = stripe_pattern;
81         lum.lmm_stripe_size = stripe_size;
82         lum.lmm_stripe_count = stripe_count;
83         lum.lmm_stripe_offset = stripe_offset;
84
85         fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
86         if (errno == EISDIR) {
87                 fd = open(name, O_DIRECTORY | O_RDONLY);
88                 isdir++;
89         }
90
91         if (fd < 0) {
92                 err_msg("unable to open '%s'",name);
93                 rc = -errno;
94                 return rc;
95         }
96
97         /* setting stripe pattern 0 -1 0 to a dir means to delete it */
98         if (isdir) {
99                 if (stripe_size == 0 && stripe_count == 0 &&
100                     stripe_offset == -1)
101                         lum.lmm_stripe_size = -1;
102         } else {
103                 if (stripe_size == -1) {
104                         err_msg("deleting file stripe info is not allowed\n");
105                         rc = -EPERM;
106                         goto out;
107                 }
108         }
109
110         if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum)) {
111                 char *errmsg = "stripe already set";
112                 if (errno != EEXIST && errno != EALREADY)
113                         errmsg = strerror(errno);
114
115                 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
116                         name, fd, errmsg);
117                 rc = -errno;
118         }
119 out:
120         if (close(fd) < 0) {
121                 err_msg("error on close for '%s' (%d)", name, fd);
122                 if (rc == 0)
123                         rc = -errno;
124         }
125         return rc;
126 }
127
128 int op_create_dir(char *name, int stripe_count)
129 {
130         struct  ll_user_mkdir_stripe lums = { 0 };
131         int fd, rc = 0;
132         char *dot = ".";
133         char *dirname;
134
135         dirname = rindex(name, '/');
136         if (!dirname) {
137                 dirname = "name";
138                 name = dot;
139         } else {
140                 *dirname = 0;
141                 dirname++;
142         }
143         lums.lums_nstripes = stripe_count;
144         lums.lums_namelen = strlen(dirname);
145         lums.lums_name = dirname;
146         /* XXX: Probably users might want to specify permissions as well? */
147         lums.lums_mode = 0755;
148                 
149         fd = open(name, O_RDONLY|O_DIRECTORY);
150         if (name != dot)
151                 *(dirname-1) = '/';
152         if (fd < 0) {
153                 err_msg("unable to open '%s'",name);
154                 rc = -errno;
155                 return rc;
156         }
157         
158         if (ioctl(fd, LL_IOC_MDC_MKDIRSTRIPE, &lums)) {
159                 char *errmsg = strerror(errno);
160
161                 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
162                         name, fd, errmsg);
163                 rc = -errno;
164         }
165         if (close(fd) < 0) {
166                 err_msg("error on close for '%s' (%d)", name, fd);
167                 if (rc == 0)
168                         rc = -errno;
169         }
170         return rc;
171 }
172
173 /* short term backwards compat only */
174 int op_create_file(char *name, long stripe_size, int stripe_offset,
175                    int stripe_count)
176 {
177         return llapi_file_create(name, stripe_size, stripe_offset,
178                                  stripe_count, 0);
179 }
180
181 struct find_param {
182         int                 recursive;
183         int                 verbose;
184         int                 quiet;
185         int                 showfid;
186         struct obd_uuid    *obduuid;
187         int                 datalen;
188         struct lov_user_md *data;
189         int                 got_uuids;
190         int                 obdindex;
191         __u32              *obdgens;
192 };
193
194 /* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
195 #define MAX_LOV_UUID_COUNT      1000
196 #define OBD_NOT_FOUND           (-1)
197
198 static int prepare_find(struct find_param *param)
199 {
200         if (param->showfid) {
201                 param->datalen = PATH_MAX + 1;
202                 if ((param->data = malloc(param->datalen)) == NULL) {
203                         err_msg("unable to allocate %d bytes of memory for ioctl",
204                                 param->datalen);
205                         return ENOMEM;
206                 }
207         } else {
208                 param->datalen = lov_mds_md_size(MAX_LOV_UUID_COUNT);
209                 if ((param->data = malloc(param->datalen)) == NULL) {
210                         err_msg("unable to allocate %d bytes of memory for ioctl",
211                                 param->datalen);
212                         return ENOMEM;
213                 }
214         }
215         param->got_uuids = 0;
216         param->obdindex = OBD_NOT_FOUND;
217         return 0;
218 }
219
220 static void cleanup_find(struct find_param *param)
221 {
222         if (param->obduuid)
223                 free(param->obduuid);
224         if (param->data)
225                 free(param->data);
226 }
227
228 int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp,
229                         __u32 *obdgens, int *ost_count)
230 {
231         struct obd_ioctl_data data = { 0, };
232         struct lov_desc desc = { 0, };
233         char *buf = NULL;
234         int max_ost_count, rc;
235
236         max_ost_count = (OBD_MAX_IOCTL_BUFFER - size_round(sizeof(data)) -
237                          size_round(sizeof(desc))) / 
238                         (sizeof(*uuidp) + sizeof(*obdgens));
239         if (max_ost_count > *ost_count)
240                 max_ost_count = *ost_count;
241
242         data.ioc_inllen1 = sizeof(desc);
243         data.ioc_inlbuf1 = (char *)&desc;
244         data.ioc_inllen2 = size_round(max_ost_count * sizeof(*uuidp));
245         data.ioc_inlbuf2 = (char *)uuidp;
246         data.ioc_inllen3 = size_round(max_ost_count * sizeof(*obdgens));
247         data.ioc_inlbuf3 = (char *)obdgens;
248
249         desc.ld_tgt_count = max_ost_count;
250
251         if (obd_ioctl_pack(&data, &buf, OBD_MAX_IOCTL_BUFFER)) {
252                 fprintf(stderr, "internal buffer error packing\n");
253                 rc = EINVAL;
254                 goto out;
255         }
256
257         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
258         if (rc) {
259                 err_msg("error getting LOV config");
260                 rc = errno;
261                 goto out;
262         }
263
264         if (obd_ioctl_unpack(&data, buf, OBD_MAX_IOCTL_BUFFER)) {
265                 fprintf(stderr, "invalid reply from ioctl");
266                 rc = EINVAL;
267                 goto out;
268         }
269
270         *ost_count = desc.ld_tgt_count;
271 out:
272         free(buf);
273
274         return rc;
275 }
276
277 static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
278 {
279         struct obd_uuid uuids[1024], *uuidp;
280         __u32 obdgens[1024], *genp;
281         int obdcount = 1024;
282         int rc, i;
283
284         param->got_uuids = 1;
285
286         rc = llapi_lov_get_uuids(dirfd(dir), uuids, obdgens, &obdcount);
287         if (rc != 0)
288                 return (param->obduuid ? rc : 0);
289
290         if (obdcount == 0)
291                 return 0;
292
293         if (param->obduuid) {
294                 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
295                         if (strncmp((char *)param->obduuid->uuid, (char *)uuidp->uuid,
296                                     sizeof(*uuidp)) == 0) {
297                                 param->obdindex = i;
298                                 break;
299                         }
300                 }
301                 if (param->obdindex == OBD_NOT_FOUND) {
302                         printf("unknown obduuid: %s\n", param->obduuid->uuid);
303                         return EINVAL;
304                 }
305         } else if (!param->quiet) {
306
307                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
308                 uuidp = uuids;
309                 genp = obdgens;
310                 for (i = 0; i < obdcount; i++, uuidp++, genp++) {
311                         if (obd_uuid_empty(uuidp))
312                                 continue;
313                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, uuidp->uuid);
314                 }    
315         }
316         return 0;
317 }
318
319 void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname,
320                           int obdindex, int quiet, int header, int body)
321 {
322         int i, obdstripe = 0;
323
324         if (obdindex != OBD_NOT_FOUND) {
325                 for (i = 0; i < lum->lmm_stripe_count; i++) {
326                         if (obdindex == lum->lmm_objects[i].l_ost_idx) {
327                                 printf("%s/%s\n", dname, fname);
328                                 obdstripe = 1;
329                                 break;
330                         }
331                 }
332         } else if (!quiet) {
333                 printf("%s/%s\n", dname, fname);
334                 obdstripe = 1;
335         }
336
337         /* if it's a directory */
338         if (*fname == '\0') {
339                 if (header && (obdstripe == 1)) {
340                         printf("count: %d, size: %d, offset: %d\n\n",
341                                lum->lmm_stripe_count, lum->lmm_stripe_size,
342                                (short int)lum->lmm_stripe_offset);
343                 }
344                 return;
345         }
346
347         if (header && (obdstripe == 1)) {
348                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
349                 printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
350                 printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
351                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
352                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
353                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
354         }
355
356         if (body) {
357                 if ((!quiet) && (obdstripe == 1))
358                         printf("\tobdidx\t\t obdgen\t\t objid\t\tobjid\t\t group\n");
359
360                 for (i = 0; i < lum->lmm_stripe_count; i++) {
361                         int idx = lum->lmm_objects[i].l_ost_idx;
362                         long long oid = lum->lmm_objects[i].l_object_id;
363                         int gen = lum->lmm_objects[i].l_ost_gen;
364                         long long gr = lum->lmm_objects[i].l_object_gr;
365                         if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx))
366                                 printf("\t%6u\t%14u\t%14llu\t%#13llx\t%14lld%s\n",
367                                         idx, gen, oid, oid, gr,
368                                         obdindex == idx ? " *" : "");
369                 }
370                 printf("\n");
371         }
372 }
373
374 void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
375 {
376         switch(*(__u32 *)param->data) { /* lum->lmm_magic */
377         case LOV_USER_MAGIC_V1:
378                 lov_dump_user_lmm_v1(param->data, dname, fname, param->obdindex,
379                                      param->quiet, param->verbose,
380                                      (param->verbose || !param->obduuid));
381                 break;
382         default:
383                 printf("unknown lmm_magic:  0x%08X\n", *(__u32 *)param->data);
384                 return;
385         }
386 }
387
388 void llapi_dump_fid(struct find_param *param, char *dname, char *fname)
389 {
390         if (!param->quiet) {
391                 int n = 0;
392                 char path[PATH_MAX + 1];
393
394                 n = snprintf(path, PATH_MAX, "%s/%s",
395                              dname, fname);
396
397                 if (n > 40)
398                         n = 1;
399                 else
400                         n = 40 - n;
401                 
402                 printf("%s:%*s"DLID4"\n", path, n, "",
403                        OLID4((struct lustre_id *)param->data));
404         }
405 }
406
407 int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
408 {
409         char *dname, *fname;
410         int fd, rc = 0;
411
412         fname = strrchr(path, '/');
413
414         /* It should be a file (or other non-directory) */
415         if (fname == NULL) {
416                 dname = (char *)malloc(2);
417                 if (dname == NULL)
418                         return ENOMEM;
419                 strcpy(dname, ".");
420                 fname = path;
421         } else {
422                 dname = (char *)malloc(fname - path + 1);
423                 if (dname == NULL)
424                         return ENOMEM;
425                 strncpy(dname, path, fname - path);
426                 dname[fname - path] = '\0';
427                 fname++;
428         }
429
430         if ((fd = open(dname, O_RDONLY)) == -1) {
431                 free(dname);
432                 return errno;
433         }
434
435         strncpy((char *)lum, fname, sizeof(*lum));
436         if (ioctl(fd, IOC_MDC_GETSTRIPE, (void *)lum) == -1) {
437                 close(fd);
438                 free(dname);
439                 return errno;
440         }
441
442         if (close(fd) == -1)
443                 rc = errno;
444
445         free(dname);
446
447         return rc;
448 }
449
450 int llapi_file_get_fid(char *path, void *data)
451 {
452         char *dname, *fname;
453         int fd, rc = 0;
454
455         fname = strrchr(path, '/');
456
457         if (fname == NULL) {
458                 dname = (char *)malloc(2);
459                 if (dname == NULL)
460                         return ENOMEM;
461                 strcpy(dname, ".");
462                 fname = path;
463         } else {
464                 dname = (char *)malloc(fname - path + 1);
465                 if (dname == NULL)
466                         return ENOMEM;
467                 strncpy(dname, path, fname - path);
468                 dname[fname - path] = '\0';
469                 fname++;
470
471                 if (!strlen(fname))
472                         fname = ".";
473         }
474
475         if ((fd = open(dname, O_RDONLY)) == -1) {
476                 free(dname);
477                 return errno;
478         }
479
480         strncpy((char *)data, fname, strlen(fname));
481         if (ioctl(fd, IOC_MDC_SHOWFID, (void *)data) == -1) {
482                 close(fd);
483                 free(dname);
484                 return errno;
485         }
486
487         if (close(fd) == -1)
488                 rc = errno;
489
490         free(dname);
491         return rc;
492 }
493
494 /* short term backwards compat only */
495 int op_get_file_stripe(char *path, struct lov_user_md *lum)
496 {
497         return llapi_file_get_stripe(path, lum);
498 }
499
500 static int process_file(DIR *dir, char *dname, char *fname,
501                         struct find_param *param)
502 {
503         int rc;
504
505         if (param->showfid) {
506                 char path[PATH_MAX + 1];
507
508                 snprintf(path, PATH_MAX, "%s/%s", dname, fname);
509                 rc = llapi_file_get_fid(path, (void *)param->data);
510                 if (rc) {
511                         err_msg("IOC_MDC_SHOWFID ioctl failed");
512                         return rc;
513                 }
514                 llapi_dump_fid(param, dname, fname);
515         } else {
516                 strncpy((char *)param->data, fname, param->datalen);
517                 rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->data);
518                 if (rc) {
519                         if (errno == ENODATA) {
520                                 if (!param->obduuid && !param->quiet)
521                                         fprintf(stderr,
522                                                 "%s/%s has no stripe info\n",
523                                                 dname, fname);
524                                 rc = 0;
525                         } else if (errno == EISDIR) {
526                                 fprintf(stderr, "process_file on directory %s/%s!\n",
527                                         dname, fname);
528                                 /* add fname to directory list; */
529                                 rc = errno;
530                         } else {
531                                 err_msg("IOC_MDC_GETSTRIPE ioctl failed");
532                                 rc = errno;
533                         }
534                         return rc;
535                 }
536                 llapi_lov_dump_user_lmm(param, dname, fname);
537         }
538         return 0;
539 }
540
541 /* some 64bit libcs implement readdir64() by calling sys_getdents().  the
542  * kernel's sys_getdents() doesn't return d_type.  */
543 unsigned char handle_dt_unknown(char *parent, char *entry)
544 {
545         char path[PATH_MAX + 1];
546         int fd, ret;
547
548         ret = snprintf(path, PATH_MAX, "%s/%s", parent, entry);
549         if (ret >= PATH_MAX)
550                 return DT_UNKNOWN;
551
552         fd = open(path, O_DIRECTORY|O_RDONLY);
553         if (fd < 0) {
554                 if (errno == ENOTDIR)
555                         return DT_REG; /* kind of a lie */
556                 return DT_UNKNOWN;
557         }
558         close(fd);
559         return DT_DIR;
560 }
561
562 static int process_dir(DIR *dir, char *dname, struct find_param *param)
563 {
564         char path[PATH_MAX + 1];
565         struct dirent64 *dirp;
566         DIR *subdir;
567         int rc;
568
569         /* retrieve dir's stripe info */
570         if (param->showfid) {
571                 rc = llapi_file_get_fid(dname, (void *)param->data);
572                 if (rc) {
573                         err_msg("IOC_MDC_SHOWFID ioctl failed");
574                         return rc;
575                 }
576                 llapi_dump_fid(param, dname, "");
577         } else {
578                 if (!param->got_uuids) {
579                         rc = setup_obd_uuids(dir, dname, param);
580                         if (rc)
581                                 return rc;
582                 }
583
584                 strncpy((char *)param->data, dname, param->datalen);
585                 rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, (void *)param->data);
586                 if (rc) {
587                         if (errno == ENODATA) {
588                                 if (!param->obduuid && param->verbose)
589                                         printf("%s/%s has no stripe info\n", dname, "");
590                                 rc = 0;
591                         } else {
592                                 err_msg("IOC_MDC_GETSTRIPE ioctl failed");
593                                 return errno;
594                         }
595                 } else {
596                         llapi_lov_dump_user_lmm(param, dname, "");
597                 }
598         }
599
600         /* Handle the contents of the directory */
601         while ((dirp = readdir64(dir)) != NULL) {
602                 if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
603                         continue;
604
605                 if (dirp->d_type == DT_UNKNOWN)
606                         dirp->d_type = handle_dt_unknown(dname, dirp->d_name);
607
608                 switch (dirp->d_type) {
609                 case DT_UNKNOWN:
610                         err_msg("\"%s\" is UNKNOWN type %d", dirp->d_name,
611                                 dirp->d_type);
612                         /* If we cared we could stat the file to determine
613                          * type and continue on here, but we don't since we
614                          * know d_type should be valid for lustre and this
615                          * tool only makes sense for lustre filesystems. */
616                         return EINVAL;
617                 case DT_DIR:
618                         if (!param->recursive)
619                                 break;
620                         strcpy(path, dname);
621                         strcat(path, "/");
622                         strcat(path, dirp->d_name);
623                         subdir = opendir(path);
624                         if (subdir == NULL) {
625                                 err_msg("\"%.40s\" opendir failed", path);
626                                 return errno;
627                         }
628                         rc = process_dir(subdir, path, param);
629                         closedir(subdir);
630                         if (rc)
631                                 return rc;
632                         break;
633                 case DT_REG:
634                         rc = process_file(dir, dname, dirp->d_name, param);
635                         if (rc)
636                                 return rc;
637                         break;
638                 default:
639                         break;
640                 }
641         }
642
643         return 0;
644 }
645
646 static int process_path(char *path, struct find_param *param)
647 {
648         char *fname, *dname;
649         DIR *dir;
650         int rc = 0;
651
652         fname = strrchr(path, '/');
653         if (fname != NULL && fname[1] == '\0') {
654                 /* Trailing '/', it must be a dir */
655                 *fname = '\0';
656                 dir = opendir(path);
657                 if (dir == NULL) {
658                         err_msg("\"%.40s\" opendir failed", path);
659                         rc = errno;
660                 } else {
661                         rc = process_dir(dir, path, param);
662                         closedir(dir);
663                 }
664         } else if ((dir = opendir(path)) != NULL) {
665                 /* No trailing '/', but it is still a dir */
666                 rc = process_dir(dir, path, param);
667                 closedir(dir);
668         } else {
669                 /* It must be a file (or other non-directory) */
670                 if (fname == NULL) {
671                         dname = ".";
672                         fname = path;
673                 } else {
674                         *fname = '\0';
675                         fname++;
676                         dname = path;
677                 }
678                 dir = opendir(dname);
679                 if (dir == NULL) {
680                         err_msg("\"%.40s\" opendir failed", dname);
681                         rc = errno;
682                 } else {
683                         if (!param->showfid) {
684                                 if (!param->got_uuids)
685                                         rc = setup_obd_uuids(dir, dname, param);
686                         }
687                         if (rc == 0)
688                                 rc = process_file(dir, dname, fname, param);
689                         closedir(dir);
690                 }
691         }
692
693         return rc;
694 }
695
696 int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
697                int verbose, int quiet, int showfid)
698 {
699         struct find_param param;
700         int ret = 0;
701
702         memset(&param, 0, sizeof(param));
703         param.recursive = recursive;
704         param.showfid = showfid;
705         param.verbose = verbose;
706         param.quiet = quiet;
707         if (obduuid) {
708                 param.obduuid = malloc(sizeof(*obduuid));
709                 if (param.obduuid == NULL) {
710                         ret = ENOMEM;
711                         goto out;
712                 }
713                 memcpy(param.obduuid, obduuid, sizeof(*obduuid));
714         }
715
716         ret = prepare_find(&param);
717         if (ret)
718                 goto out;
719
720         process_path(path, &param);
721 out:
722         cleanup_find(&param);
723         return ret;
724 }
725
726 #define MAX_STRING_SIZE 128
727 #define DEVICES_LIST "/proc/fs/lustre/devices"
728
729 int llapi_target_check(int type_num, char **obd_type, char *dir)
730 {
731         char buf[MAX_STRING_SIZE];
732         FILE *fp = fopen(DEVICES_LIST, "r");
733         int rc = 0;
734         int i;
735
736         if (fp == NULL) {
737                 fprintf(stderr, "error: %s opening "DEVICES_LIST"\n",
738                         strerror(rc =  errno));
739                 return rc;
740         }
741
742         while (fgets(buf, sizeof(buf), fp) != NULL) {
743                 char *obd_type_name = NULL;
744                 char *obd_name = NULL;
745                 char rawbuf[OBD_MAX_IOCTL_BUFFER];
746                 char *bufl = rawbuf;
747                 char *bufp = buf;
748                 struct obd_ioctl_data datal = { 0, };
749                 struct obd_statfs osfs_buffer;
750
751                 while(bufp[0] == ' ')
752                         ++bufp;
753
754                 for(i = 0; i < 3; i++) {
755                         obd_type_name = strsep(&bufp, " ");
756                 }
757                 obd_name = strsep(&bufp, " ");
758
759                 memset(&osfs_buffer, 0, sizeof (osfs_buffer));
760
761                 memset(bufl, 0, sizeof(rawbuf));
762                 datal.ioc_pbuf1 = (char *)&osfs_buffer;
763                 datal.ioc_plen1 = sizeof(osfs_buffer);
764
765                 for (i = 0; i < type_num; i++)
766                         if (strcmp(obd_type_name, obd_type[i]) == 0) {
767                                 datal.ioc_inlbuf1 = obd_name;
768                                 datal.ioc_inllen1 = strlen(obd_name) + 1;
769
770                                 rc = obd_ioctl_pack(&datal, &bufl, OBD_MAX_IOCTL_BUFFER);
771                                 if (rc) {
772                                         fprintf(stderr, "internal buffer error packing\n");
773                                         break;
774                                 }
775
776                                 rc = ioctl(dirfd(opendir(dir)), OBD_IOC_PING,
777                                            bufl);
778
779                                 if (rc) {
780                                         fprintf(stderr, "error: check %s: %s\n",
781                                                 obd_name, strerror(rc = errno));
782                                 } else {
783                                         printf("%s active.\n",obd_name);
784                                 }
785                         }
786
787         }
788         fclose(fp);
789         return rc;
790 }
791
792 #undef MAX_STRING_SIZE
793
794 int llapi_catinfo(char *dir, char *keyword, char *node_name)
795 {
796         char raw[OBD_MAX_IOCTL_BUFFER];
797         char out[LLOG_CHUNK_SIZE];
798         char *buf = raw;
799         struct obd_ioctl_data data;
800         char key[30];
801         DIR *root;
802         int rc;
803
804         sprintf(key, "%s", keyword);
805         memset(raw, 0, sizeof(buf));
806         memset(out, 0, sizeof(out));
807         data.ioc_inlbuf1 = key;
808         data.ioc_inllen1 = strlen(key) + 1;
809         if (node_name) {
810                 data.ioc_inlbuf2 = node_name;
811                 data.ioc_inllen2 = strlen(node_name) + 1;
812         }
813         data.ioc_pbuf1 = out;
814         data.ioc_plen1 = sizeof(out);
815         rc = obd_ioctl_pack(&data, &buf, sizeof(raw));
816         if (rc)
817                 return rc;
818
819         root = opendir(dir);
820         if (root == NULL) {
821                 err_msg("open %s failed", dir);
822                 return errno;
823         }
824
825         rc = ioctl(dirfd(root), OBD_IOC_LLOG_CATINFO, buf);
826         if (rc)
827                 err_msg("ioctl OBD_IOC_CATINFO failed");
828         else
829                 fprintf(stdout, "%s", data.ioc_pbuf1);
830
831         closedir(root);
832         return rc;
833 }
834
835 int llapi_getfacl(char *dir, char *cmd)
836 {
837         struct ll_acl_ioctl_data data;
838         char out[LUSTRE_ACL_SIZE_MAX];
839         int fd, rc;
840
841         data.cmd = cmd;
842         data.cmd_len = strlen(cmd) + 1;
843         data.res = out;
844         data.res_len = sizeof(out);
845         data.status = 0;
846
847         fd = open(dir, O_RDONLY | O_DIRECTORY);
848         if (fd == -1) {
849                 err_msg("can't open dir %s", dir);
850                 return -1;
851         }
852
853         rc = ioctl(fd, LL_IOC_GETFACL, &data);
854         if (rc)
855                 err_msg("getfacl failed");
856         else {
857                 out[sizeof(out) - 1] = '\0';
858                 printf("%s", out);
859                 rc = data.status;
860         }
861
862         close(fd);
863
864         return rc;
865 }
866
867 int llapi_setfacl(char *dir, char *cmd)
868 {
869         struct ll_acl_ioctl_data data;
870         char out[LUSTRE_ACL_SIZE_MAX];
871         int fd, rc;
872
873         data.cmd = cmd;
874         data.cmd_len = strlen(cmd) + 1;
875         data.res = out;
876         data.res_len = sizeof(out);
877         data.status = 0;
878
879         fd = open(dir, O_RDONLY | O_DIRECTORY);
880         if (fd == -1) {
881                 err_msg("can't open dir %s", dir);
882                 return -1;
883         }
884
885         rc = ioctl(fd, LL_IOC_SETFACL, &data);
886         if (rc)
887                 err_msg("setfacl failed");
888         else {
889                 out[sizeof(out) - 1] = '\0';
890                 printf("%s", out);
891                 rc = data.status;
892         }
893
894         close(fd);
895
896         return rc;
897 }
898
899 int llapi_is_lustre_mnttype(char *type)
900 {
901         return (strcmp(type,"lustre") == 0 || strcmp(type,"lustre_lite") == 0);
902 }