From 7d9c948c6016b10ed0d07e20cbd7925e108b3450 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sat, 17 Jan 2015 18:31:59 -0800 Subject: [PATCH] LU-5937 lfs: ensure a valid directory size in lfs find For a striped directory (and a striped file) the size returned by LL_IOC_MDC_GETINFO may not be vaild. In cb_find_init() if the size of a directory is needed then get it by calling fstat(). Signed-off-by: John L. Hammond Signed-off-by: Di Wang Change-Id: Iddb9aa8e6664a09ff866a3995741cae17e1c9962 Reviewed-on: http://review.whamcloud.com/13456 Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustre_user.h | 2 ++ lustre/tests/sanity.sh | 13 +++++++++++++ lustre/utils/liblustreapi.c | 32 ++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/lustre/include/lustre/lustre_user.h b/lustre/include/lustre/lustre_user.h index bb808e8..9b65dba 100644 --- a/lustre/include/lustre/lustre_user.h +++ b/lustre/include/lustre/lustre_user.h @@ -65,10 +65,12 @@ defined(__craynv) || defined(__mips64__) || defined(__powerpc64__) typedef struct stat lstat_t; # define lstat_f lstat +# define fstat_f fstat # define HAVE_LOV_USER_MDS_DATA #elif defined(__USE_LARGEFILE64) || defined(__KERNEL__) typedef struct stat64 lstat_t; # define lstat_f lstat64 +# define fstat_f fstat64 # define HAVE_LOV_USER_MDS_DATA #endif diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 573844b..4deb81c 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -5035,6 +5035,19 @@ test_56z() { # LU-4824 } run_test 56z "lfs find should continue after an error" +test_56aa() { # LU-5937 + [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return + + mkdir $DIR/$tdir + $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir + + createmany -o $DIR/$tdir/striped_dir/${tfile}- 1024 + local dirs=$(lfs find --size +8k $DIR/$tdir/) + + [ -n "$dirs" ] || error "lfs find --size wrong under striped dir" +} +run_test 56aa "lfs find --size under striped dir" + test_57a() { [ $PARALLEL == "yes" ] && skip "skip parallel run" && return # note test will not do anything if MDS is not local diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index e74cf70..719de6f 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -1641,12 +1641,18 @@ static int get_lmd_info(char *path, DIR *parent, DIR *dir, if (dir) { ret = ioctl(dirfd(dir), LL_IOC_MDC_GETINFO, (void *)lmd); } else if (parent) { - char *fname = strrchr(path, '/'); + char *fname = strrchr(path, '/'); - fname = (fname == NULL ? path : fname + 1); - /* retrieve needed file info */ + /* To avoid opening, locking, and closing each file on the + * client if that is not needed. The GETFILEINFO ioctl can + * be done on the patent dir with a single open for all + * files in that directory, and it also doesn't pollute the + * client dcache with millions of dentries when traversing + * a large filesystem. */ + fname = (fname == NULL ? path : fname + 1); + /* retrieve needed file info */ strlcpy((char *)lmd, fname, lumlen); - ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); + ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); } if (ret) { @@ -3196,26 +3202,26 @@ obd_matches: param->fp_lmd->lmd_lmm.lmm_stripe_count) decision = 0; - while (!decision) { + if (param->fp_check_size && S_ISDIR(st->st_mode)) + decision = 0; + + if (!decision) { /* For regular files with the stripe the decision may have not * been taken yet if *time or size is to be checked. */ - LASSERT((S_ISREG(st->st_mode) && - param->fp_lmd->lmd_lmm.lmm_stripe_count) || - param->fp_mdt_index != OBD_NOT_FOUND); - if (param->fp_obd_index != OBD_NOT_FOUND) print_failed_tgt(param, path, LL_STATFS_LOV); if (param->fp_mdt_index != OBD_NOT_FOUND) print_failed_tgt(param, path, LL_STATFS_LMV); - if (dir) { + if (S_ISDIR(st->st_mode)) + ret = fstat_f(dirfd(dir), st); + else if (dir != NULL) ret = ioctl(dirfd(dir), IOC_LOV_GETINFO, (void *)param->fp_lmd); - } else if (parent) { + else ret = ioctl(dirfd(parent), IOC_LOV_GETINFO, (void *)param->fp_lmd); - } if (ret) { if (errno == ENOENT) { @@ -3236,8 +3242,6 @@ obd_matches: decision = find_time_check(st, param, 0); if (decision == -1) goto decided; - - break; } if (param->fp_check_size) -- 1.8.3.1