Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[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 <unistd.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <dirent.h>
39 #include <stdarg.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <linux/types.h>
43 #include <linux/unistd.h>
44
45 #include <liblustre.h>
46 #include <linux/obd.h>
47 #include <linux/lustre_lib.h>
48 #include <lustre/lustre_user.h>
49 #include <linux/obd_lov.h>
50
51 #include <portals/ptlctl.h>
52
53 static void err_msg(char *fmt, ...)
54 {
55         va_list args;
56         int tmp_errno = errno;
57
58         va_start(args, fmt);
59         vfprintf(stderr, fmt, args);
60         va_end(args);
61         fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
62 }
63
64 int llapi_file_create(char *name, long stripe_size, int stripe_offset,
65                       int stripe_count, int stripe_pattern)
66 {
67         struct lov_user_md lum = { 0 };
68         int fd, rc = 0;
69
70         /*  Initialize IOCTL striping pattern structure  */
71         lum.lmm_magic = LOV_USER_MAGIC;
72         lum.lmm_pattern = stripe_pattern;
73         lum.lmm_stripe_size = stripe_size;
74         lum.lmm_stripe_count = stripe_count;
75         lum.lmm_stripe_offset = stripe_offset;
76
77         fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
78         if (errno == EISDIR)
79                 fd = open(name, O_DIRECTORY | O_RDONLY);
80
81         if (fd < 0) {
82                 err_msg("unable to open '%s'",name);
83                 rc = -errno;
84                 return rc;
85         }
86
87         if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum)) {
88                 char *errmsg = "stripe already set";
89                 if (errno != EEXIST && errno != EALREADY)
90                         errmsg = strerror(errno);
91
92                 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
93                         name, fd, errmsg);
94                 rc = -errno;
95         }
96         if (close(fd) < 0) {
97                 err_msg("error on close for '%s' (%d)", name, fd);
98                 if (rc == 0)
99                         rc = -errno;
100         }
101         return rc;
102 }
103
104 int op_create_dir(char *name, int stripe_count)
105 {
106         struct  ll_user_mkdir_stripe lums = { 0 };
107         int fd, rc = 0;
108         char *dot = ".";
109         char *dirname;
110
111         dirname = rindex(name, '/');
112         if (!dirname) {
113                 dirname = "name";
114                 name = dot;
115         } else {
116                 *dirname = 0;
117                 dirname++;
118         }
119         lums.lums_nstripes = stripe_count;
120         lums.lums_namelen = strlen(dirname);
121         lums.lums_name = dirname;
122         /* XXX: Probably users might want to specify permissions as well? */
123         lums.lums_mode = 0755;
124                 
125         fd = open(name, O_RDONLY|O_DIRECTORY);
126         if (name != dot)
127                 *(dirname-1) = '/';
128         if (fd < 0) {
129                 err_msg("unable to open '%s'",name);
130                 rc = -errno;
131                 return rc;
132         }
133         
134         if (ioctl(fd, LL_IOC_MDC_MKDIRSTRIPE, &lums)) {
135                 char *errmsg = strerror(errno);
136
137                 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
138                         name, fd, errmsg);
139                 rc = -errno;
140         }
141         if (close(fd) < 0) {
142                 err_msg("error on close for '%s' (%d)", name, fd);
143                 if (rc == 0)
144                         rc = -errno;
145         }
146         return rc;
147 }
148
149 /* short term backwards compat only */
150 int op_create_file(char *name, long stripe_size, int stripe_offset,
151                    int stripe_count)
152 {
153         return llapi_file_create(name, stripe_size, stripe_offset,
154                                  stripe_count, 0);
155 }
156
157 struct find_param {
158         int     recursive;
159         int     verbose;
160         int     quiet;
161         struct  obd_uuid        *obduuid;
162         int     lumlen;
163         struct  lov_user_md     *lum;
164         int     got_uuids;
165         int     obdindex;
166         __u32   *obdgens;
167 };
168
169 /* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
170 #define MAX_LOV_UUID_COUNT      1000
171 #define OBD_NOT_FOUND           (-1)
172
173 static int prepare_find(struct find_param *param)
174 {
175         param->lumlen = lov_mds_md_size(MAX_LOV_UUID_COUNT);
176         if ((param->lum = malloc(param->lumlen)) == NULL) {
177                 err_msg("unable to allocate %d bytes of memory for ioctl",
178                         param->lumlen);
179                 return ENOMEM;
180         }
181
182         param->got_uuids = 0;
183         param->obdindex = OBD_NOT_FOUND;
184
185         return 0;
186 }
187
188 static void cleanup_find(struct find_param *param)
189 {
190         if (param->obduuid)
191                 free(param->obduuid);
192         if (param->lum)
193                 free(param->lum);
194 }
195
196 int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, __u32 *obdgens,
197                         int *ost_count)
198 {
199         struct obd_ioctl_data data = { 0, };
200         struct lov_desc desc = { 0, };
201         char *buf = NULL;
202         int max_ost_count, rc;
203
204         max_ost_count = (OBD_MAX_IOCTL_BUFFER - size_round(sizeof(data)) -
205                          size_round(sizeof(desc))) / 
206                         (sizeof(*uuidp) + sizeof(*obdgens));
207         if (max_ost_count > *ost_count)
208                 max_ost_count = *ost_count;
209
210         data.ioc_inllen1 = sizeof(desc);
211         data.ioc_inlbuf1 = (char *)&desc;
212         data.ioc_inllen2 = size_round(max_ost_count * sizeof(*uuidp));
213         data.ioc_inlbuf2 = (char *)uuidp;
214         data.ioc_inllen3 = size_round(max_ost_count * sizeof(*obdgens));
215         data.ioc_inlbuf3 = (char *)obdgens;
216
217         desc.ld_tgt_count = max_ost_count;
218
219         if (obd_ioctl_pack(&data, &buf, OBD_MAX_IOCTL_BUFFER)) {
220                 fprintf(stderr, "internal buffer error packing\n");
221                 rc = EINVAL;
222                 goto out;
223         }
224
225         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
226         if (rc) {
227                 err_msg("error getting LOV config");
228                 rc = errno;
229                 goto out;
230         }
231
232         if (obd_ioctl_unpack(&data, buf, OBD_MAX_IOCTL_BUFFER)) {
233                 fprintf(stderr, "invalid reply from ioctl");
234                 rc = EINVAL;
235                 goto out;
236         }
237
238         *ost_count = desc.ld_tgt_count;
239 out:
240         free(buf);
241
242         return 0;
243 }
244
245 static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
246 {
247         struct obd_uuid uuids[1024], *uuidp;
248         __u32 obdgens[1024], *genp;
249         
250         int obdcount = 1024;
251         int rc, i;
252
253         param->got_uuids = 1;
254
255         rc = llapi_lov_get_uuids(dirfd(dir), uuids, obdgens, &obdcount);
256         if (rc != 0)
257                 return (param->obduuid ? rc : 0);
258
259         if (obdcount == 0)
260                 return 0;
261
262         if (param->obduuid) {
263                 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
264                         if (strncmp(param->obduuid->uuid, uuidp->uuid,
265                                     sizeof(*uuidp)) == 0) {
266                                 param->obdindex = i;
267                                 break;
268                         }
269                 }
270                 if (param->obdindex == OBD_NOT_FOUND) {
271                         printf("unknown obduuid: %s\n", param->obduuid->uuid);
272                         return EINVAL;
273                 }
274         } else if (!param->quiet) {
275
276                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
277                 uuidp = uuids;
278                 genp = obdgens;
279                 for (i = 0; i < obdcount; i++, uuidp++, genp++) {
280                         if (obd_uuid_empty(uuidp))
281                                 continue;
282                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, uuidp->uuid);
283                 }    
284         }
285         return 0;
286 }
287
288 void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname,
289                           int obdindex, int quiet, int header, int body)
290 {
291         int i, obdstripe = 0;
292
293         if (obdindex != OBD_NOT_FOUND) {
294                 for (i = 0; i < lum->lmm_stripe_count; i++) {
295                         if (obdindex == lum->lmm_objects[i].l_ost_idx) {
296                                 printf("%s/%s\n", dname, fname);
297                                 obdstripe = 1;
298                                 break;
299                         }
300                 }
301         } else if (!quiet) {
302                 printf("%s/%s\n", dname, fname);
303                 obdstripe = 1;
304         }
305
306         /* if it's a directory */
307         if (*fname == '\0') {
308                 if (header && (obdstripe == 1)) {
309                         printf("count: %d, size: %d, offset: %d\n\n",
310                                lum->lmm_stripe_count, lum->lmm_stripe_size,
311                                (short int)lum->lmm_stripe_offset);
312                 }
313                 return;
314         }
315
316         if (header && (obdstripe == 1)) {
317                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
318                 printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
319                 printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
320                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
321                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
322                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
323         }
324
325         if (body) {
326                 if ((!quiet) && (obdstripe == 1))
327                         printf("\tobdidx\t\t obdgen\t\t objid\t\tobjid\t\t group\n");
328
329                 for (i = 0; i < lum->lmm_stripe_count; i++) {
330                         int idx = lum->lmm_objects[i].l_ost_idx;
331                         long long oid = lum->lmm_objects[i].l_object_id;
332                         int gen = lum->lmm_objects[i].l_ost_gen;
333                         long long gr = lum->lmm_objects[i].l_object_gr;
334                         if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx))
335                                 printf("\t%6u\t%14u\t%14llu\t%#13llx\t%14lld%s\n",
336                                         idx, gen, oid, oid, gr,
337                                         obdindex == idx ? " *" : "");
338                 }
339                 printf("\n");
340         }
341 }
342
343 void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
344 {
345         switch(*(__u32 *)param->lum) { /* lum->lmm_magic */
346         case LOV_USER_MAGIC_V1:
347                 lov_dump_user_lmm_v1(param->lum, dname, fname, param->obdindex,
348                                      param->quiet, param->verbose,
349                                      (param->verbose || !param->obduuid));
350                 break;
351         default:
352                 printf("unknown lmm_magic:  0x%08X\n", *(__u32 *)param->lum);
353                 return;
354         }
355 }
356
357 int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
358 {
359         char *dname, *fname;
360         int fd, rc = 0;
361
362         fname = strrchr(path, '/');
363
364         /* It should be a file (or other non-directory) */
365         if (fname == NULL) {
366                 dname = (char *)malloc(2);
367                 if (dname == NULL)
368                         return ENOMEM;
369                 strcpy(dname, ".");
370                 fname = path;
371         } else {
372                 dname = (char *)malloc(fname - path + 1);
373                 if (dname == NULL)
374                         return ENOMEM;
375                 strncpy(dname, path, fname - path);
376                 dname[fname - path] = '\0';
377                 fname++;
378         }
379
380         if ((fd = open(dname, O_RDONLY)) == -1) {
381                 free(dname);
382                 return errno;
383         }
384
385         strncpy((char *)lum, fname, sizeof(*lum));
386         if (ioctl(fd, IOC_MDC_GETSTRIPE, (void *)lum) == -1) {
387                 close(fd);
388                 free(dname);
389                 return errno;
390         }
391
392         if (close(fd) == -1)
393                 rc = errno;
394
395         free(dname);
396
397         return rc;
398 }
399
400 /* short term backwards compat only */
401 int op_get_file_stripe(char *path, struct lov_user_md *lum)
402 {
403         return llapi_file_get_stripe(path, lum);
404 }
405
406 static int process_file(DIR *dir, char *dname, char *fname,
407                         struct find_param *param)
408 {
409         int rc;
410
411         strncpy((char *)param->lum, fname, param->lumlen);
412
413         rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->lum);
414         if (rc) {
415                 if (errno == ENODATA) {
416                         if (!param->obduuid && !param->quiet)
417                                 fprintf(stderr,
418                                         "%s/%s has no stripe info\n",
419                                         dname, fname);
420                         rc = 0;
421                 } else if (errno == EISDIR) {
422                         fprintf(stderr, "process_file on directory %s/%s!\n",
423                                 dname, fname);
424                         /* add fname to directory list; */
425                         rc = errno;
426                 } else {
427                         err_msg("IOC_MDC_GETSTRIPE ioctl failed");
428                         rc = errno;
429                 }
430                 return rc;
431         }
432
433         llapi_lov_dump_user_lmm(param, dname, fname);
434
435         return 0;
436 }
437
438 /* some 64bit libcs implement readdir64() by calling sys_getdents().  the
439  * kernel's sys_getdents() doesn't return d_type.  */
440 unsigned char handle_dt_unknown(char *parent, char *entry)
441 {
442         char path[PATH_MAX + 1];
443         int fd, ret;
444
445         ret = snprintf(path, PATH_MAX, "%s/%s", parent, entry);
446         if (ret >= PATH_MAX)
447                 return DT_UNKNOWN;
448
449         fd = open(path, O_DIRECTORY|O_RDONLY);
450         if (fd < 0) {
451                 if (errno == ENOTDIR)
452                         return DT_REG; /* kind of a lie */
453                 return DT_UNKNOWN;
454         }
455         close(fd);
456         return DT_DIR;
457 }
458
459 static int process_dir(DIR *dir, char *dname, struct find_param *param)
460 {
461         struct dirent64 *dirp;
462         DIR *subdir;
463         char path[1024];
464         int rc;
465
466         if (!param->got_uuids) {
467                 rc = setup_obd_uuids(dir, dname, param);
468                 if (rc)
469                         return rc;
470         }
471
472         /* retrieve dir's stripe info */
473         strncpy((char *)param->lum, dname, param->lumlen);
474         rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, (void *)param->lum);
475         if (rc) {
476                 if (errno == ENODATA) {
477                         if (!param->obduuid && param->verbose)
478                                 printf("%s/%s has no stripe info\n", dname, "");
479                         rc = 0;
480                 } else {
481                         err_msg("IOC_MDC_GETSTRIPE ioctl failed");
482                         return errno;
483                 }
484         } else {
485                llapi_lov_dump_user_lmm(param, dname, "");
486         }
487
488         /* Handle the contents of the directory */
489         while ((dirp = readdir64(dir)) != NULL) {
490                 if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
491                         continue;
492
493                 if (dirp->d_type == DT_UNKNOWN)
494                         dirp->d_type = handle_dt_unknown(dname, dirp->d_name);
495
496                 switch (dirp->d_type) {
497                 case DT_UNKNOWN:
498                         err_msg("\"%s\" is UNKNOWN type %d", dirp->d_name,
499                                 dirp->d_type);
500                         /* If we cared we could stat the file to determine
501                          * type and continue on here, but we don't since we
502                          * know d_type should be valid for lustre and this
503                          * tool only makes sense for lustre filesystems. */
504                         return EINVAL;
505                         break;
506                 case DT_DIR:
507                         if (!param->recursive)
508                                 break;
509                         strcpy(path, dname);
510                         strcat(path, "/");
511                         strcat(path, dirp->d_name);
512                         subdir = opendir(path);
513                         if (subdir == NULL) {
514                                 err_msg("\"%.40s\" opendir failed", path);
515                                 return errno;
516                         }
517                         rc = process_dir(subdir, path, param);
518                         closedir(subdir);
519                         if (rc)
520                                 return rc;
521                         break;
522                 case DT_REG:
523                         rc = process_file(dir, dname, dirp->d_name, param);
524                         if (rc)
525                                 return rc;
526                         break;
527                 default:
528                         break;
529                 }
530         }
531
532         return 0;
533 }
534
535 static int process_path(char *path, struct find_param *param)
536 {
537         char *fname, *dname;
538         DIR *dir;
539         int rc = 0;
540
541         fname = strrchr(path, '/');
542         if (fname != NULL && fname[1] == '\0') {
543                 /* Trailing '/', it must be a dir */
544                 *fname = '\0';
545                 dir = opendir(path);
546                 if (dir == NULL) {
547                         err_msg("\"%.40s\" opendir failed", path);
548                         rc = errno;
549                 } else {
550                         rc = process_dir(dir, path, param);
551                         closedir(dir);
552                 }
553         } else if ((dir = opendir(path)) != NULL) {
554                 /* No trailing '/', but it is still a dir */
555                 rc = process_dir(dir, path, param);
556                 closedir(dir);
557         } else {
558                 /* It must be a file (or other non-directory) */
559                 if (fname == NULL) {
560                         dname = ".";
561                         fname = path;
562                 } else {
563                         *fname = '\0';
564                         fname++;
565                         dname = path;
566                 }
567                 dir = opendir(dname);
568                 if (dir == NULL) {
569                         err_msg("\"%.40s\" opendir failed", dname);
570                         rc = errno;
571                 } else {
572                         if (!param->got_uuids)
573                                 rc = setup_obd_uuids(dir, dname, param);
574                         if (rc == 0)
575                                 rc = process_file(dir, dname, fname, param);
576                         closedir(dir);
577                 }
578         }
579
580         return rc;
581 }
582
583 int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
584                int verbose, int quiet)
585 {
586         struct find_param param;
587         int ret = 0;
588
589         memset(&param, 0, sizeof(param));
590         param.recursive = recursive;
591         param.verbose = verbose;
592         param.quiet = quiet;
593         if (obduuid) {
594                 param.obduuid = malloc(sizeof(*obduuid));
595                 if (param.obduuid == NULL) {
596                         ret = ENOMEM;
597                         goto out;
598                 }
599                 memcpy(param.obduuid, obduuid, sizeof(*obduuid));
600         }
601
602         ret = prepare_find(&param);
603         if (ret)
604                 goto out;
605
606         process_path(path, &param);
607 out:
608         cleanup_find(&param);
609         return ret;
610 }
611
612 #define MAX_STRING_SIZE 128
613 #define DEVICES_LIST "/proc/fs/lustre/devices"
614
615 int llapi_target_check(int type_num, char **obd_type, char *dir)
616 {
617         char buf[MAX_STRING_SIZE];
618         FILE *fp = fopen(DEVICES_LIST, "r");
619         int rc = 0;
620         int i;
621
622         if (fp == NULL) {
623                 fprintf(stderr, "error: %s opening "DEVICES_LIST"\n",
624                         strerror(rc =  errno));
625                 return rc;
626         }
627
628         while (fgets(buf, sizeof(buf), fp) != NULL) {
629                 char *obd_type_name = NULL;
630                 char *obd_name = NULL;
631                 char rawbuf[OBD_MAX_IOCTL_BUFFER];
632                 char *bufl = rawbuf;
633                 char *bufp = buf;
634                 int max = sizeof(rawbuf);
635                 struct obd_ioctl_data datal;
636                 struct obd_statfs osfs_buffer;
637
638                 while(bufp[0] == ' ')
639                         ++bufp;
640
641                 for(i = 0; i < 3; i++) {
642                         obd_type_name = strsep(&bufp, " ");
643                 }
644                 obd_name = strsep(&bufp, " ");
645
646                 memset(&osfs_buffer, 0, sizeof (osfs_buffer));
647
648                 memset(bufl, 0, sizeof(rawbuf));
649                 datal.ioc_pbuf1 = (char *)&osfs_buffer;
650                 datal.ioc_plen1 = sizeof(osfs_buffer);
651
652                 for (i = 0; i < type_num; i++)
653                         if (strcmp(obd_type_name, obd_type[i]) == 0) {
654                                 datal.ioc_inlbuf1 = obd_name;
655                                 datal.ioc_inllen1 = strlen(obd_name) + 1;
656
657                                 obd_ioctl_pack(&datal,&bufl,max);
658
659                                 rc = ioctl(dirfd(opendir(dir)), OBD_IOC_PING,
660                                            bufl);
661
662                                 if (rc) {
663                                         fprintf(stderr, "error: check %s: %s\n",
664                                                 obd_name, strerror(rc = errno));
665                                 } else {
666                                         printf("%s active.\n",obd_name);
667                                 }
668                         }
669
670         }
671         fclose(fp);
672         return rc;
673 }
674
675 #undef MAX_STRING_SIZE
676
677 int llapi_catinfo(char *dir, char *keyword, char *node_name)
678 {
679         char raw[OBD_MAX_IOCTL_BUFFER];
680         char out[LLOG_CHUNK_SIZE];
681         char *buf = raw;
682         struct obd_ioctl_data data;
683         char key[30];
684         DIR *root;
685         int rc;
686
687         sprintf(key, "%s", keyword);
688         memset(raw, 0, sizeof(buf));
689         memset(out, 0, sizeof(out));
690         data.ioc_inlbuf1 = key;
691         data.ioc_inllen1 = strlen(key) + 1;
692         if (node_name) {
693                 data.ioc_inlbuf2 = node_name;
694                 data.ioc_inllen2 = strlen(node_name) + 1;
695         }
696         data.ioc_pbuf1 = out;
697         data.ioc_plen1 = sizeof(out);
698         rc = obd_ioctl_pack(&data, &buf, sizeof(raw));
699         if (rc)
700                 return rc;
701
702         root = opendir(dir);
703         if (root == NULL) {
704                 err_msg("open %s failed", dir);
705                 return errno;
706         }
707
708         rc = ioctl(dirfd(root), OBD_IOC_LLOG_CATINFO, buf);
709         if (rc)
710                 err_msg("ioctl OBD_IOC_CATINFO failed");
711         else
712                 fprintf(stdout, "%s", data.ioc_pbuf1);
713
714         closedir(root);
715         return rc;
716 }
717
718 int llapi_is_lustre_mnttype(char *type)
719 {
720         return (strcmp(type,"lustre") == 0 || strcmp(type,"lustre_lite") == 0);
721 }