const struct lmv_stripe_md *lsm = &lso->lso_lsm;
int rc;
int i;
+ int nlink_overflow = 0;
if (!lmv_dir_striped(lso))
return 0;
(s64)inode_get_ctime_sec(inode),
(s64)inode_get_mtime_sec(inode));
- /* for slave stripe, it needs to subtract nlink for . and .. */
- if (i != 0)
- attr->cat_nlink += inode->i_nlink - 2;
- else
- attr->cat_nlink = inode->i_nlink;
+ /* nlink==1 is a special value meaning nlink overflow
+ * for directories on Ldiskfs.
+ */
+ nlink_overflow |= (inode->i_nlink == 1);
+ /* not counting . and .. for each stripe */
+ attr->cat_nlink += inode->i_nlink - 2;
attr->cat_size += i_size_read(inode);
attr->cat_blocks += inode->i_blocks;
if (attr->cat_mtime < inode_get_mtime_sec(inode))
attr->cat_mtime = inode_get_mtime_sec(inode);
}
+ if (nlink_overflow)
+ /* Indicate that nlink is not correct for a striped dir the
+ * same way it is done in Ldiskfs by setting nlink = 1.
+ */
+ attr->cat_nlink = 1;
+ else
+ /* add 2 for . and .. */
+ attr->cat_nlink += 2;
return 0;
}
# create files
createmany -d $dir/d $nrdirs || {
- unlinkmany $dir/d $nrdirs
+ unlinkmany -d $dir/d $nrdirs
error "failed to create $nrdirs subdirs in MDT$mdtidx:$dir"
}
}
run_test 51b "exceed 64k subdirectory nlink limit on create, verify unlink"
+test_51c() {
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+ local dir=$DIR/$tdir-c2
+ local nrdirs=$((65536 * 2 + 2000))
+ local mdtidx
+
+ trap cleanup_print_lfs_df EXIT
+
+ $LFS mkdir -c 2 -H fnv_1a_64 $dir
+ while read mtdidx rest; do
+ local mdtname=$FSNAME-MDT$(printf "%04x" $mdtidx)
+ local numfree=$(lctl get_param -n mdc.$mdtname*.filesfree)
+ local blkfree=$(lctl get_param -n mdc.$mdtname*.kbytesavail)
+
+ (( numfree < nrdirs / 2 || blkfree / $(fs_inode_ksize) < nrdirs / 2 )) &&
+ skip "not enough inodes or blocks for mdt$mdtidx"
+ done < <( $LFS getdirstripe $dir | awk '{ if ($2 ~ /\[0x.*:0x.*:0x.*\]/) { print $1; } }' )
+
+ createmany -d $dir/d $nrdirs ||
+ error "failed to create $nrdirs subdirs in $dir"
+ # nlink for the striped dir should be either 1
+ # (ldiskfs, nlink is overflowed at least in one stripe)
+ # or $ndirs + 2
+ local nlinks=$(stat -c %h $dir)
+ (( nlinks == 1 || nlinks == nrdirs + 2 )) ||
+ error "Wrong nlink count of $nlinks"
+
+ unlinkmany -d $dir/d $nrdirs || error "Removal of the subdirs failed"
+ rmdir $dir || error "rmdir failed"
+ cleanup_print_lfs_df
+}
+run_test 51c "exceed 64k subdirectory count per dir stripe, verify nlink count"
+
test_51d_sub() {
local stripecount=$1
local nfiles=$2