Whamcloud - gitweb
LU-5937 lfs: ensure a valid directory size in lfs find 56/13456/4
authorJohn L. Hammond <john.hammond@intel.com>
Sun, 18 Jan 2015 02:31:59 +0000 (18:31 -0800)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 3 Mar 2015 16:56:18 +0000 (16:56 +0000)
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 <john.hammond@intel.com>
Signed-off-by: Di Wang <di.wang@intel.com>
Change-Id: Iddb9aa8e6664a09ff866a3995741cae17e1c9962
Reviewed-on: http://review.whamcloud.com/13456
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre/lustre_user.h
lustre/tests/sanity.sh
lustre/utils/liblustreapi.c

index bb808e8..9b65dba 100644 (file)
     defined(__craynv) || defined(__mips64__) || defined(__powerpc64__)
 typedef struct stat    lstat_t;
 # define lstat_f       lstat
     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 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
 
 # define HAVE_LOV_USER_MDS_DATA
 #endif
 
index 573844b..4deb81c 100644 (file)
@@ -5035,6 +5035,19 @@ test_56z() { # LU-4824
 }
 run_test 56z "lfs find should continue after an error"
 
 }
 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
 test_57a() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        # note test will not do anything if MDS is not local
index e74cf70..719de6f 100644 (file)
@@ -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) {
         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);
                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) {
         }
 
         if (ret) {
@@ -3196,26 +3202,26 @@ obd_matches:
            param->fp_lmd->lmd_lmm.lmm_stripe_count)
                 decision = 0;
 
            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. */
                 /* 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 (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);
                        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);
                        ret = ioctl(dirfd(parent), IOC_LOV_GETINFO,
                                    (void *)param->fp_lmd);
-               }
 
                 if (ret) {
                         if (errno == ENOENT) {
 
                 if (ret) {
                         if (errno == ENOENT) {
@@ -3236,8 +3242,6 @@ obd_matches:
                 decision = find_time_check(st, param, 0);
                 if (decision == -1)
                         goto decided;
                 decision = find_time_check(st, param, 0);
                 if (decision == -1)
                         goto decided;
-
-                break;
         }
 
        if (param->fp_check_size)
         }
 
        if (param->fp_check_size)