From bfb1bfced0dab2cda699c3648f43b7c05efbed4c Mon Sep 17 00:00:00 2001 From: panda Date: Wed, 2 Dec 2009 21:42:20 +0000 Subject: [PATCH] b=20101 i=Andreas Dilger i=Robert Read a=James Simmons Fixed lfs to maintain old behavior and support new functionality --- lustre/doc/lfs.1 | 12 +- lustre/include/lustre/liblustreapi.h | 4 +- lustre/tests/sanity.sh | 18 +- lustre/utils/lfs.c | 36 ++- lustre/utils/liblustreapi.c | 550 ++++++++++++++++------------------- 5 files changed, 302 insertions(+), 318 deletions(-) diff --git a/lustre/doc/lfs.1 b/lustre/doc/lfs.1 index a0a3d9b..d0e96ac 100644 --- a/lustre/doc/lfs.1 +++ b/lustre/doc/lfs.1 @@ -24,6 +24,8 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the .B lfs osts .br .B lfs getstripe [--obd|-O ] [--quiet|-q] [--verbose|-v] + \fB[--count | -c ] [--size | -s ] [--index | -i ] + \fB[--offset | -o ] [--pool | -p ] [--directory | -d ] \fB[--recursive|-r] \fR .br .B lfs setstripe [--size|-s stripe-size] [--count|-c stripe-cnt] @@ -98,8 +100,12 @@ To search the directory tree rooted at the given dir/file name for the files tha .B osts List all the OSTs for the filesystem .TP -.B getstripe -To list the striping info for a given filename or files in a directory, optionally recursively, for all files in a directory tree: \fB--quiet\fR (don't print object IDs), \fB--verbose\fR (print striping parameters), \fB--recursive\fR (recurse into subdirectories). +.B getstripe [--obd|-O ] [--quiet|-q] [--verbose|-v] + \fB[--count | -c ] [--size | -s ] [--index | -i ] + \fB[--offset | -o ] [--pool | -p ] [--directory | -d ] + \fB[--recursive|-r] \fR +.br +To list the striping information for a given filename or directory. By default the stripe count, size, and offset will be returned. If you only want specific striping information then the options of \fB--count\fR,\fB--size\fR,\fB--index\fR or \fB--offset\fR plus various combinations of these options can be used to retrieve only what you want. What pools a file belong to can also be obtained with \fB--pool\fR. In the case where you only want details about the files object id information then the \fB--quiet\fR option is used. Additional information available about striping can be displayed with \fB--verbose\fR. The default behavior of lfs getstripe used to retrieve data about a directory is to list all the contents of that directory. If you wish to inquire only about that directory then \fB--directory\fR,can be used to list directory entries instead of its contents in the same manner as ls -d. This can be expanded with \fB--recursive\fR which will recurse into all subdirectories. You can filter the search to return only files that has a object on a specific OST with \fB--obd\fR. .TP .B setstripe [--size stripe-size] [--count stripe-cnt] \fB[--offset start-ost] [--pool ]\fR @@ -198,7 +204,7 @@ Lists space usage per OST and MDT in human readable format. .B $ lfs df -i Lists inode usage per OST and MDT .TP -.B lfs df --pool [.] | +.B $ lfs df --pool [.] | List space or inode usage for a specific OST pool .TP .B $ lfs quota -u bob /mnt/lustre diff --git a/lustre/include/lustre/liblustreapi.h b/lustre/include/lustre/liblustreapi.h index 20fd103..6e4ec38 100644 --- a/lustre/include/lustre/liblustreapi.h +++ b/lustre/include/lustre/liblustreapi.h @@ -95,8 +95,9 @@ extern int llapi_file_lookup(int dirfd, const char *name); #define VERBOSE_OFFSET 0x4 #define VERBOSE_POOL 0x8 #define VERBOSE_DETAIL 0x10 +#define VERBOSE_OBJID 0x20 #define VERBOSE_ALL (VERBOSE_COUNT | VERBOSE_SIZE | VERBOSE_OFFSET | \ - VERBOSE_POOL) + VERBOSE_POOL | VERBOSE_OBJID) struct find_param { unsigned int maxdepth; @@ -151,6 +152,7 @@ struct find_param { char poolname[LOV_MAXPOOLNAME + 1]; }; +extern int llapi_ostlist(char *path, struct find_param *param); extern int llapi_uuid_match(char *real_uuid, char *search_uuid); extern int llapi_getstripe(char *path, struct find_param *param); extern int llapi_find(char *path, struct find_param *param); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index ac9f21c..45a1127 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -1200,15 +1200,15 @@ run_test 27v "skip object creation on slow OST =================" test_27w() { # bug 10997 mkdir -p $DIR/$tdir || error "mkdir failed" $LSTRIPE $DIR/$tdir/f0 -s 65536 || error "lstripe failed" - size=`$GETSTRIPE $DIR/$tdir/f0 -qs | head -n 1` + size=`$GETSTRIPE $DIR/$tdir/f0 -s` [ $size -ne 65536 ] && error "stripe size $size != 65536" || true [ "$OSTCOUNT" -lt "2" ] && skip_env "skipping multiple stripe count/offset test" && return for i in `seq 1 $OSTCOUNT`; do offset=$(($i-1)) $LSTRIPE $DIR/$tdir/f$i -c $i -i $offset || error "lstripe -c $i -i $offset failed" - count=`$GETSTRIPE -qc $DIR/$tdir/f$i | head -n 1` - index=`$GETSTRIPE -qo $DIR/$tdir/f$i | head -n 1` + count=`$GETSTRIPE -c $DIR/$tdir/f$i` + index=`$GETSTRIPE -o $DIR/$tdir/f$i` [ $count -ne $i ] && error "stripe count $count != $i" || true [ $index -ne $offset ] && error "stripe offset $index != $offset" || true done @@ -2651,12 +2651,14 @@ test_56a() { # was test_56 [ "$OSTCOUNT" -lt 2 ] && \ skip_env "skipping other lfs getstripe --obd test" && return - FILENUM=`$GETSTRIPE --recursive $DIR/d56 | sed -n '/^[ ]*1[ ]/p' | wc -l` - OBDUUID=`$GETSTRIPE --recursive $DIR/d56 | sed -n '/^[ ]*1:/p' | awk '{print $2}'` - FOUND=`$GETSTRIPE -r --obd $OBDUUID $DIR/d56 | wc -l` + OSTIDX=1 + OBDUUID=$(lfs osts | grep ${OSTIDX}": " | awk '{print $2}') + FILENUM=`$GETSTRIPE -ir $DIR/d56 | grep -x $OSTIDX | wc -l` + FOUND=`$GETSTRIPE -r --obd $OBDUUID $DIR/d56 | grep obdidx | wc -l` [ $FOUND -eq $FILENUM ] || \ error "lfs getstripe --obd wrong: found $FOUND, expected $FILENUM" - [ `$GETSTRIPE -r -v --obd $OBDUUID $DIR/d56 | sed '/^[ ]*1[ ]/d' |\ + [ `$GETSTRIPE -r -v --obd $OBDUUID $DIR/d56 | \ + sed '/^[ ]*'${OSTIDX}'[ ]/d' |\ sed -n '/^[ ]*[0-9][0-9]*[ ]/p' | wc -l` -eq 0 ] || \ error "lfs getstripe --obd wrong: should not show file on other obd" echo "lfs getstripe --obd passed." @@ -2736,7 +2738,7 @@ run_test 56h "check lfs find ! -name =============================" test_56i() { tdir=${tdir}i mkdir -p $DIR/$tdir - UUID=`$GETSTRIPE $DIR/$tdir | awk '/0: / { print $2 }'` + UUID=`$LFS osts | awk '/0: / { print $2 }'` OUT="`$LFIND -ost $UUID $DIR/$tdir`" [ "$OUT" ] && error "$LFIND returned directory '$OUT'" || true } diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 4e4228a..2457ba5 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -133,7 +133,7 @@ command_t cmdlist[] = { "directory or recursively for all files in a directory tree.\n" "usage: getstripe [--obd|-O ] [--quiet | -q] [--verbose | -v]\n" " [--count | -c ] [--size | -s ] [--index | -i ]\n" - " [--offset | -o ] [--pool | -p ]\n" + " [--offset | -o ] [--pool | -p ] [--directory | -d]\n" " [--recursive | -r] ..."}, {"pool_list", lfs_poollist, 0, "List pools or pool OSTs\n" @@ -824,14 +824,15 @@ static int lfs_getstripe(int argc, char **argv) {"offset", 0, 0, 'o'}, {"pool", 0, 0, 'p'}, {"verbose", 0, 0, 'v'}, + {"directory", 0, 0, 'd'}, {0, 0, 0, 0} }; - char short_opts[] = "hO:qrvcsiop"; int c, rc; struct find_param param = { 0 }; + param.maxdepth = 1; optind = 0; - while ((c = getopt_long(argc, argv, short_opts, + while ((c = getopt_long(argc, argv, "cdhioO:pqrsv", long_opts, NULL)) != -1) { switch (c) { case 'O': @@ -846,22 +847,33 @@ static int lfs_getstripe(int argc, char **argv) case 'q': param.quiet++; break; + case 'd': + param.maxdepth = 0; + break; case 'r': param.recursive = 1; break; case 'v': param.verbose = VERBOSE_ALL | VERBOSE_DETAIL; - param.quiet = 0; break; case 'c': - param.verbose |= VERBOSE_COUNT; + if (!(param.verbose & VERBOSE_DETAIL)) { + param.verbose |= VERBOSE_COUNT; + param.maxdepth = 0; + } break; case 's': - param.verbose |= VERBOSE_SIZE; + if (!(param.verbose & VERBOSE_DETAIL)) { + param.verbose |= VERBOSE_SIZE; + param.maxdepth = 0; + } break; case 'i': case 'o': - param.verbose |= VERBOSE_OFFSET; + if (!(param.verbose & VERBOSE_DETAIL)) { + param.verbose |= VERBOSE_OFFSET; + param.maxdepth = 0; + } break; case 'p': param.verbose |= VERBOSE_POOL; @@ -878,7 +890,13 @@ static int lfs_getstripe(int argc, char **argv) if (optind >= argc) return CMD_HELP; - param.maxdepth = param.recursive ? -1 : 1; + if (param.recursive) + param.maxdepth = -1; + + if (!param.verbose) + param.verbose = VERBOSE_ALL; + if (param.quiet) + param.verbose = VERBOSE_OBJID; do { rc = llapi_getstripe(argv[optind], ¶m); @@ -901,7 +919,7 @@ static int lfs_osts(int argc, char **argv) while (llapi_search_mounts(NULL, index++, mntdir, NULL) == 0) { memset(¶m, 0, sizeof(param)); - rc = llapi_getstripe(mntdir, ¶m); + rc = llapi_ostlist(mntdir, ¶m); if (rc) { fprintf(stderr, "error: %s: failed on %s\n", argv[0], mntdir); diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index d97c676..b62736b 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -897,6 +897,205 @@ static void find_param_fini(struct find_param *param) free(param->lmd); } +static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data, + cfs_dirent_t *de) +{ + struct find_param *param = (struct find_param *)data; + param->depth--; + return 0; +} + +static DIR *opendir_parent(char *path) +{ + DIR *parent; + char *fname; + char c; + + fname = strrchr(path, '/'); + if (fname == NULL) + return opendir("."); + + c = fname[1]; + fname[1] = '\0'; + parent = opendir(path); + fname[1] = c; + return parent; +} + +int llapi_mds_getfileinfo(char *path, DIR *parent, + struct lov_user_mds_data *lmd) +{ + lstat_t *st = &lmd->lmd_st; + char *fname = strrchr(path, '/'); + int ret = 0; + + if (parent == NULL) + return -EINVAL; + + fname = (fname == NULL ? path : fname + 1); + /* retrieve needed file info */ + strncpy((char *)lmd, fname, + lov_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC)); + ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); + + if (ret) { + if (errno == ENOTTY) { + /* ioctl is not supported, it is not a lustre fs. + * Do the regular lstat(2) instead. */ + ret = lstat_f(path, st); + if (ret) { + llapi_err(LLAPI_MSG_ERROR, + "error: %s: lstat failed for %s", + __FUNCTION__, path); + return ret; + } + } else if (errno == ENOENT) { + llapi_err(LLAPI_MSG_WARN, + "warning: %s: %s does not exist", + __FUNCTION__, path); + return -ENOENT; + } else { + llapi_err(LLAPI_MSG_ERROR, + "error: %s: IOC_MDC_GETFILEINFO failed for %s", + __FUNCTION__, path); + return ret; + } + } + + return 0; +} + +static int llapi_semantic_traverse(char *path, int size, DIR *parent, + semantic_func_t sem_init, + semantic_func_t sem_fini, void *data, + cfs_dirent_t *de) +{ + cfs_dirent_t *dent; + int len, ret; + DIR *d, *p = NULL; + + ret = 0; + len = strlen(path); + + d = opendir(path); + if (!d && errno != ENOTDIR) { + llapi_err(LLAPI_MSG_ERROR, "%s: Failed to open '%s'", + __FUNCTION__, path); + return -EINVAL; + } else if (!d && !parent) { + /* ENOTDIR. Open the parent dir. */ + p = opendir_parent(path); + if (!p) + GOTO(out, ret = -EINVAL); + } + + if (sem_init && (ret = sem_init(path, parent ?: p, d, data, de))) + goto err; + + if (!d) + GOTO(out, ret = 0); + + while ((dent = readdir64(d)) != NULL) { + ((struct find_param *)data)->have_fileinfo = 0; + + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) + continue; + + /* Don't traverse .lustre directory */ + if (!(strcmp(dent->d_name, dot_lustre_name))) + continue; + + path[len] = 0; + if ((len + dent->d_reclen + 2) > size) { + llapi_err(LLAPI_MSG_ERROR, + "error: %s: string buffer is too small", + __FUNCTION__); + break; + } + strcat(path, "/"); + strcat(path, dent->d_name); + + if (dent->d_type == DT_UNKNOWN) { + lstat_t *st = &((struct find_param *)data)->lmd->lmd_st; + + ret = llapi_mds_getfileinfo(path, d, + ((struct find_param *)data)->lmd); + if (ret == 0) { + ((struct find_param *)data)->have_fileinfo = 1; + dent->d_type = + llapi_filetype_dir_table[st->st_mode & + S_IFMT]; + } + if (ret == -ENOENT) + continue; + } + + switch (dent->d_type) { + case DT_UNKNOWN: + llapi_err(LLAPI_MSG_ERROR, + "error: %s: '%s' is UNKNOWN type %d", + __FUNCTION__, dent->d_name, dent->d_type); + break; + case DT_DIR: + ret = llapi_semantic_traverse(path, size, d, sem_init, + sem_fini, data, dent); + if (ret < 0) + goto out; + break; + default: + ret = 0; + if (sem_init) { + ret = sem_init(path, d, NULL, data, dent); + if (ret < 0) + goto out; + } + if (sem_fini && ret == 0) + sem_fini(path, d, NULL, data, dent); + } + } + +out: + path[len] = 0; + + if (sem_fini) + sem_fini(path, parent, d, data, de); +err: + if (d) + closedir(d); + if (p) + closedir(p); + return ret; +} + +static int param_callback(char *path, semantic_func_t sem_init, + semantic_func_t sem_fini, struct find_param *param) +{ + int ret, len = strlen(path); + char *buf; + + if (len > PATH_MAX) { + llapi_err(LLAPI_MSG_ERROR, "Path name '%s' is too long", path); + return -EINVAL; + } + + buf = (char *)malloc(PATH_MAX + 1); + if (!buf) + return -ENOMEM; + + ret = common_param_init(param); + if (ret) + goto out; + param->depth = 0; + + strncpy(buf, path, PATH_MAX + 1); + ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, sem_init, + sem_fini, param, NULL); +out: + find_param_fini(param); + free(buf); + return ret < 0 ? ret : 0; +} + int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_name) { int rc = ioctl(fd, OBD_IOC_GETNAME, lov_name); @@ -1016,6 +1215,9 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) FILE *fp; int rc = 0, index; + if (param->got_uuids) + return rc; + /* Get the lov name */ rc = llapi_file_fget_lov_uuid(dirfd(dir), &lov_uuid); if (rc) { @@ -1062,8 +1264,7 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) fclose(fp); - if (!param->quiet && param->obduuid && - (param->obdindex == OBD_NOT_FOUND)) { + if (param->obduuid && (param->obdindex == OBD_NOT_FOUND)) { llapi_err_noerrno(LLAPI_MSG_ERROR, "error: %s: unknown obduuid: %s", __FUNCTION__, param->obduuid->uuid); @@ -1139,14 +1340,36 @@ retry_get_uuids: return ret; } +static int cb_ostlist(char *path, DIR *parent, DIR *d, void *data, + struct dirent64 *de) +{ + struct find_param *param = (struct find_param *)data; + + LASSERT(parent != NULL || d != NULL); + + /* Prepare odb. */ + return setup_obd_uuid(d ? d : parent, path, param); +} + +int llapi_ostlist(char *path, struct find_param *param) +{ + return param_callback(path, cb_ostlist, cb_common_fini, param); +} + static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, - int is_dir, int verbose, int quiet, + int is_dir, int verbose, int depth, char *pool_name) { char *prefix = is_dir ? "" : "lmm_"; char nl = is_dir ? ' ' : '\n'; - if (verbose && path) + if (is_dir && lum->lmm_object_gr == LOV_OBJECT_GROUP_DEFAULT) { + lum->lmm_object_gr = LOV_OBJECT_GROUP_CLEAR; + if (verbose & VERBOSE_DETAIL) + llapi_printf(LLAPI_MSG_NORMAL, "(Default) "); + } + + if (depth && path && ((verbose != VERBOSE_OBJID) || !is_dir)) llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); if ((verbose & VERBOSE_DETAIL) && !is_dir) { @@ -1159,7 +1382,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, } if (verbose & VERBOSE_COUNT) { - if (!quiet) + if (verbose & ~VERBOSE_COUNT) llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_count: ", prefix); llapi_printf(LLAPI_MSG_NORMAL, "%hd%c", @@ -1167,7 +1390,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, } if (verbose & VERBOSE_SIZE) { - if (!quiet) + if (verbose & ~VERBOSE_SIZE) llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_size: ", prefix); llapi_printf(LLAPI_MSG_NORMAL, "%u%c", lum->lmm_stripe_size, @@ -1180,63 +1403,44 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, } if (verbose & VERBOSE_OFFSET) { - if (!quiet) - llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_offset: ", + if (verbose & ~VERBOSE_OFFSET) + llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_offset: ", prefix); llapi_printf(LLAPI_MSG_NORMAL, "%u%c", lum->lmm_objects[0].l_ost_idx, nl); } - if ((verbose & VERBOSE_POOL) && (pool_name != NULL)) - llapi_printf(LLAPI_MSG_NORMAL, "pool: %s%c", pool_name, nl); + if ((verbose & VERBOSE_POOL) && (pool_name != NULL)) { + llapi_printf(LLAPI_MSG_NORMAL, "pool: %s", pool_name); + is_dir = 1; + } - if (is_dir) + if (is_dir && (verbose != VERBOSE_OBJID)) llapi_printf(LLAPI_MSG_NORMAL, "\n"); } void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, struct lov_user_ost_data_v1 *objects, char *path, int is_dir, - int obdindex, int quiet, int header, int body) + int obdindex, int depth, int header) { - int i, obdstripe = 0; + int i, obdstripe = (obdindex != OBD_NOT_FOUND) ? 0 : 1; - if (obdindex != OBD_NOT_FOUND) { + if (!obdstripe) { for (i = 0; !is_dir && i < lum->lmm_stripe_count; i++) { if (obdindex == objects[i].l_ost_idx) { - llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); obdstripe = 1; break; } } - } else { - if (!quiet) - llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); - obdstripe = 1; - } - - /* if it's a directory */ - if (is_dir) { - if (obdstripe == 1) { - if (lum->lmm_object_gr == LOV_OBJECT_GROUP_DEFAULT) { - llapi_printf(LLAPI_MSG_NORMAL, "(Default) "); - lum->lmm_object_gr = LOV_OBJECT_GROUP_CLEAR; - } - /* maintain original behavior */ - if (!header) - header |= VERBOSE_ALL; - lov_dump_user_lmm_header(lum, path, is_dir, header, - quiet, pool_name); - } - return; } - if (header && (obdstripe == 1)) - lov_dump_user_lmm_header(lum, NULL, is_dir, header, quiet, + if (obdstripe == 1) + lov_dump_user_lmm_header(lum, path, is_dir, header, depth, pool_name); - if (body) { - if ((!quiet) && (obdstripe == 1)) + if (!is_dir && (header & VERBOSE_OBJID)) { + if (obdstripe == 1) llapi_printf(LLAPI_MSG_NORMAL, "\tobdidx\t\t objid\t\tobjid\t\t group\n"); @@ -1262,9 +1466,8 @@ void llapi_lov_dump_user_lmm(struct find_param *param, lov_dump_user_lmm_v1v3(¶m->lmd->lmd_lmm, NULL, param->lmd->lmd_lmm.lmm_objects, path, is_dir, - param->obdindex, param->quiet, - param->verbose, - (param->verbose || !param->obduuid)); + param->obdindex, param->maxdepth, + param->verbose); break; case LOV_USER_MAGIC_V3: { char pool_name[LOV_MAXPOOLNAME + 1]; @@ -1276,9 +1479,8 @@ void llapi_lov_dump_user_lmm(struct find_param *param, objects = lmmv3->lmm_objects; lov_dump_user_lmm_v1v3(¶m->lmd->lmd_lmm, pool_name, objects, path, is_dir, - param->obdindex, param->quiet, - param->verbose, - (param->verbose || !param->obduuid)); + param->obdindex, param->maxdepth, + param->verbose); break; } default: @@ -1358,168 +1560,6 @@ int llapi_file_lookup(int dirfd, const char *name) return ioctl(dirfd, IOC_MDC_LOOKUP, buf); } -int llapi_mds_getfileinfo(char *path, DIR *parent, - struct lov_user_mds_data *lmd) -{ - lstat_t *st = &lmd->lmd_st; - char *fname = strrchr(path, '/'); - int ret = 0; - - if (parent == NULL) - return -EINVAL; - - fname = (fname == NULL ? path : fname + 1); - /* retrieve needed file info */ - strncpy((char *)lmd, fname, - lov_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC)); - ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); - - if (ret) { - if (errno == ENOTTY) { - /* ioctl is not supported, it is not a lustre fs. - * Do the regular lstat(2) instead. */ - ret = lstat_f(path, st); - if (ret) { - llapi_err(LLAPI_MSG_ERROR, - "error: %s: lstat failed for %s", - __FUNCTION__, path); - return ret; - } - } else if (errno == ENOENT) { - llapi_err(LLAPI_MSG_WARN, - "warning: %s: %s does not exist", - __FUNCTION__, path); - return -ENOENT; - } else { - llapi_err(LLAPI_MSG_ERROR, - "error: %s: IOC_MDC_GETFILEINFO failed for %s", - __FUNCTION__, path); - return ret; - } - } - - return 0; -} - -static DIR *opendir_parent(char *path) -{ - DIR *parent; - char *fname; - char c; - - fname = strrchr(path, '/'); - if (fname == NULL) - return opendir("."); - - c = fname[1]; - fname[1] = '\0'; - parent = opendir(path); - fname[1] = c; - return parent; -} - -static int llapi_semantic_traverse(char *path, int size, DIR *parent, - semantic_func_t sem_init, - semantic_func_t sem_fini, void *data, - cfs_dirent_t *de) -{ - cfs_dirent_t *dent; - int len, ret; - DIR *d, *p = NULL; - - ret = 0; - len = strlen(path); - - d = opendir(path); - if (!d && errno != ENOTDIR) { - llapi_err(LLAPI_MSG_ERROR, "%s: Failed to open '%s'", - __FUNCTION__, path); - return -EINVAL; - } else if (!d && !parent) { - /* ENOTDIR. Open the parent dir. */ - p = opendir_parent(path); - if (!p) - GOTO(out, ret = -EINVAL); - } - - if (sem_init && (ret = sem_init(path, parent ?: p, d, data, de))) - goto err; - - if (!d) - GOTO(out, ret = 0); - - while ((dent = readdir64(d)) != NULL) { - ((struct find_param *)data)->have_fileinfo = 0; - - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) - continue; - - /* Don't traverse .lustre directory */ - if (!(strcmp(dent->d_name, dot_lustre_name))) - continue; - - path[len] = 0; - if ((len + dent->d_reclen + 2) > size) { - llapi_err(LLAPI_MSG_ERROR, - "error: %s: string buffer is too small", - __FUNCTION__); - break; - } - strcat(path, "/"); - strcat(path, dent->d_name); - - if (dent->d_type == DT_UNKNOWN) { - lstat_t *st = &((struct find_param *)data)->lmd->lmd_st; - - ret = llapi_mds_getfileinfo(path, d, - ((struct find_param *)data)->lmd); - if (ret == 0) { - ((struct find_param *)data)->have_fileinfo = 1; - dent->d_type = - llapi_filetype_dir_table[st->st_mode & - S_IFMT]; - } - if (ret == -ENOENT) - continue; - } - - switch (dent->d_type) { - case DT_UNKNOWN: - llapi_err(LLAPI_MSG_ERROR, - "error: %s: '%s' is UNKNOWN type %d", - __FUNCTION__, dent->d_name, dent->d_type); - break; - case DT_DIR: - ret = llapi_semantic_traverse(path, size, d, sem_init, - sem_fini, data, dent); - if (ret < 0) - goto out; - break; - default: - ret = 0; - if (sem_init) { - ret = sem_init(path, d, NULL, data, dent); - if (ret < 0) - goto out; - } - if (sem_fini && ret == 0) - sem_fini(path, d, NULL, data, dent); - } - } - -out: - path[len] = 0; - - if (sem_fini) - sem_fini(path, parent, d, data, de); -err: - if (d) - closedir(d); - if (p) - closedir(p); - return ret; -} - /* Check if the value matches 1 of the given criteria (e.g. --atime +/-N). * @mds indicates if this is MDS timestamps and there are attributes on OSTs. * @@ -1902,44 +1942,9 @@ decided: return 0; } -static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data, - cfs_dirent_t *de) -{ - struct find_param *param = (struct find_param *)data; - param->depth--; - return 0; -} - int llapi_find(char *path, struct find_param *param) { - char *buf; - int ret, len = strlen(path); - - if (len > PATH_MAX) { - llapi_err(LLAPI_MSG_ERROR, "%s: Path name '%s' is too long", - __FUNCTION__, path); - return -EINVAL; - } - - buf = (char *)malloc(PATH_MAX + 1); - if (!buf) - return -ENOMEM; - - ret = common_param_init(param); - if (ret) { - free(buf); - return ret; - } - - param->depth = 0; - - strncpy(buf, path, PATH_MAX + 1); - ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, cb_find_init, - cb_common_fini, param, NULL); - - find_param_fini(param); - free(buf); - return ret < 0 ? ret : 0; + return param_callback(path, cb_find_init, cb_common_fini, param); } static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, @@ -1950,8 +1955,8 @@ static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, LASSERT(parent != NULL || d != NULL); - /* Prepare odb. */ - if (!param->got_uuids) { + if (param->obduuid) { + param->quiet = 1; ret = setup_obd_uuid(d ? d : parent, path, param); if (ret) return ret; @@ -1971,7 +1976,7 @@ static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, if (ret) { if (errno == ENODATA) { - if (!param->obduuid && !param->quiet) + if (!param->obduuid) llapi_printf(LLAPI_MSG_NORMAL, "%s has no stripe info\n", path); goto out; @@ -2006,34 +2011,7 @@ out: int llapi_getstripe(char *path, struct find_param *param) { - char *buf; - int ret = 0, len = strlen(path); - - if (len > PATH_MAX) { - llapi_err(LLAPI_MSG_ERROR, - "%s: Path name '%s' is too long", - __FUNCTION__, path); - return -EINVAL; - } - - buf = (char *)malloc(PATH_MAX + 1); - if (!buf) - return -ENOMEM; - - ret = common_param_init(param); - if (ret) { - free(buf); - return ret; - } - - param->depth = 0; - - strncpy(buf, path, PATH_MAX + 1); - ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, cb_getstripe, - cb_common_fini, param, NULL); - find_param_fini(param); - free(buf); - return ret < 0 ? ret : 0; + return param_callback(path, cb_getstripe, cb_common_fini, param); } int llapi_obd_statfs(char *path, __u32 type, __u32 index, @@ -2350,35 +2328,13 @@ static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data, int llapi_quotachown(char *path, int flag) { struct find_param param; - char *buf; - int ret = 0, len = strlen(path); - - if (len > PATH_MAX) { - llapi_err(LLAPI_MSG_ERROR, "%s: Path name '%s' is too long", - __FUNCTION__, path); - return -EINVAL; - } - - buf = (char *)malloc(PATH_MAX + 1); - if (!buf) - return -ENOMEM; memset(¶m, 0, sizeof(param)); param.recursive = 1; param.verbose = 0; param.quiet = 1; - ret = common_param_init(¶m); - if (ret) - goto out; - - strncpy(buf, path, PATH_MAX + 1); - ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, cb_quotachown, - NULL, ¶m, NULL); -out: - find_param_fini(¶m); - free(buf); - return ret; + return param_callback(path, cb_quotachown, NULL, ¶m); } #include -- 1.8.3.1