aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-08-12 06:50:10 -0400
committerBen Myers <bpm@sgi.com>2013-08-22 09:44:49 -0400
commit1c55cece084aa4c9a3fa34ed4eecbdf18afbf05d (patch)
treeb849301088d3e21e91992ad3ccf0ed0f5f492446
parent0cb97766f2928579f1029ea7b28ae946cdd6fbe1 (diff)
xfs: Add write support for dirent filetype field
Add support to propagate and add filetype values into the on-disk directs. This involves passing the filetype into the xfs_da_args structure along with the name and namelength for direct operations, and encoding it into the dirent at the same time we write the inode number into the dirent. With write support, add the feature flag to the XFS_SB_FEAT_INCOMPAT_ALL mask so we can now mount filesystems with this feature set. Performance of directory recursion is now much improved. Parallel walk of ~50 million directory entries across hundreds of directories improves significantly. Unpatched, no CRCs: Walking via ls -R real 3m19.886s user 6m36.960s sys 28m19.087s THis is doing roughly 500 getdents() calls per second, and 250,000 inode lookups per second to determine the inode type at roughly 17,000 read IOPS. CPU usage is 90% kernel space. With dtype support patched in and the fileset recreated with CRCs enabled: Walking via ls -R real 0m31.316s user 6m32.975s sys 0m21.111s This is doing roughly 3500 getdents() calls per second at 16,000 IOPS. There are no inode lookups at all. CPU usages is almost 100% userspace. This is a big win for recursive directory walks that only need to find file names and file types. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_dir2.c3
-rw-r--r--fs/xfs/xfs_dir2_block.c7
-rw-r--r--fs/xfs/xfs_dir2_data.c2
-rw-r--r--fs/xfs/xfs_dir2_leaf.c3
-rw-r--r--fs/xfs/xfs_dir2_node.c3
-rw-r--r--fs/xfs/xfs_dir2_sf.c35
-rw-r--r--fs/xfs/xfs_sb.h3
7 files changed, 47 insertions, 9 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index f9825b125fcf..d3ff96c321f9 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -209,6 +209,7 @@ xfs_dir_createname(
209 memset(&args, 0, sizeof(xfs_da_args_t)); 209 memset(&args, 0, sizeof(xfs_da_args_t));
210 args.name = name->name; 210 args.name = name->name;
211 args.namelen = name->len; 211 args.namelen = name->len;
212 args.filetype = name->type;
212 args.hashval = dp->i_mount->m_dirnameops->hashname(name); 213 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
213 args.inumber = inum; 214 args.inumber = inum;
214 args.dp = dp; 215 args.dp = dp;
@@ -283,6 +284,7 @@ xfs_dir_lookup(
283 memset(&args, 0, sizeof(xfs_da_args_t)); 284 memset(&args, 0, sizeof(xfs_da_args_t));
284 args.name = name->name; 285 args.name = name->name;
285 args.namelen = name->len; 286 args.namelen = name->len;
287 args.filetype = name->type;
286 args.hashval = dp->i_mount->m_dirnameops->hashname(name); 288 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
287 args.dp = dp; 289 args.dp = dp;
288 args.whichfork = XFS_DATA_FORK; 290 args.whichfork = XFS_DATA_FORK;
@@ -338,6 +340,7 @@ xfs_dir_removename(
338 memset(&args, 0, sizeof(xfs_da_args_t)); 340 memset(&args, 0, sizeof(xfs_da_args_t));
339 args.name = name->name; 341 args.name = name->name;
340 args.namelen = name->len; 342 args.namelen = name->len;
343 args.filetype = name->type;
341 args.hashval = dp->i_mount->m_dirnameops->hashname(name); 344 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
342 args.inumber = ino; 345 args.inumber = ino;
343 args.dp = dp; 346 args.dp = dp;
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 1cd2f564e374..0957aa98b6c0 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -549,6 +549,7 @@ xfs_dir2_block_addname(
549 dep->inumber = cpu_to_be64(args->inumber); 549 dep->inumber = cpu_to_be64(args->inumber);
550 dep->namelen = args->namelen; 550 dep->namelen = args->namelen;
551 memcpy(dep->name, args->name, args->namelen); 551 memcpy(dep->name, args->name, args->namelen);
552 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
552 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 553 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
553 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 554 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
554 /* 555 /*
@@ -641,6 +642,7 @@ xfs_dir2_block_lookup(
641 * Fill in inode number, CI name if appropriate, release the block. 642 * Fill in inode number, CI name if appropriate, release the block.
642 */ 643 */
643 args->inumber = be64_to_cpu(dep->inumber); 644 args->inumber = be64_to_cpu(dep->inumber);
645 args->filetype = xfs_dir3_dirent_get_ftype(mp, dep);
644 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); 646 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
645 xfs_trans_brelse(args->trans, bp); 647 xfs_trans_brelse(args->trans, bp);
646 return XFS_ERROR(error); 648 return XFS_ERROR(error);
@@ -873,6 +875,7 @@ xfs_dir2_block_replace(
873 * Change the inode number to the new value. 875 * Change the inode number to the new value.
874 */ 876 */
875 dep->inumber = cpu_to_be64(args->inumber); 877 dep->inumber = cpu_to_be64(args->inumber);
878 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
876 xfs_dir2_data_log_entry(args->trans, bp, dep); 879 xfs_dir2_data_log_entry(args->trans, bp, dep);
877 xfs_dir3_data_check(dp, bp); 880 xfs_dir3_data_check(dp, bp);
878 return 0; 881 return 0;
@@ -1159,6 +1162,7 @@ xfs_dir2_sf_to_block(
1159 dep->inumber = cpu_to_be64(dp->i_ino); 1162 dep->inumber = cpu_to_be64(dp->i_ino);
1160 dep->namelen = 1; 1163 dep->namelen = 1;
1161 dep->name[0] = '.'; 1164 dep->name[0] = '.';
1165 xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
1162 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1166 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
1163 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1167 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1164 xfs_dir2_data_log_entry(tp, bp, dep); 1168 xfs_dir2_data_log_entry(tp, bp, dep);
@@ -1172,6 +1176,7 @@ xfs_dir2_sf_to_block(
1172 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); 1176 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
1173 dep->namelen = 2; 1177 dep->namelen = 2;
1174 dep->name[0] = dep->name[1] = '.'; 1178 dep->name[0] = dep->name[1] = '.';
1179 xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
1175 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1180 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
1176 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1181 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1177 xfs_dir2_data_log_entry(tp, bp, dep); 1182 xfs_dir2_data_log_entry(tp, bp, dep);
@@ -1219,6 +1224,8 @@ xfs_dir2_sf_to_block(
1219 dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); 1224 dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
1220 dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep)); 1225 dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep));
1221 dep->namelen = sfep->namelen; 1226 dep->namelen = sfep->namelen;
1227 xfs_dir3_dirent_put_ftype(mp, dep,
1228 xfs_dir3_sfe_get_ftype(mp, sfp, sfep));
1222 memcpy(dep->name, sfep->name, dep->namelen); 1229 memcpy(dep->name, sfep->name, dep->namelen);
1223 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1230 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
1224 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1231 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 1b59e43d97d9..47e1326c169a 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -149,6 +149,8 @@ __xfs_dir3_data_check(
149 XFS_WANT_CORRUPTED_RETURN( 149 XFS_WANT_CORRUPTED_RETURN(
150 be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) == 150 be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) ==
151 (char *)dep - (char *)hdr); 151 (char *)dep - (char *)hdr);
152 XFS_WANT_CORRUPTED_RETURN(
153 xfs_dir3_dirent_get_ftype(mp, dep) < XFS_DIR3_FT_MAX);
152 count++; 154 count++;
153 lastfree = 0; 155 lastfree = 0;
154 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 156 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 887b1bdec6dd..08984eeee159 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -897,6 +897,7 @@ xfs_dir2_leaf_addname(
897 dep->inumber = cpu_to_be64(args->inumber); 897 dep->inumber = cpu_to_be64(args->inumber);
898 dep->namelen = args->namelen; 898 dep->namelen = args->namelen;
899 memcpy(dep->name, args->name, dep->namelen); 899 memcpy(dep->name, args->name, dep->namelen);
900 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
900 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 901 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
901 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 902 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
902 /* 903 /*
@@ -1225,6 +1226,7 @@ xfs_dir2_leaf_lookup(
1225 * Return the found inode number & CI name if appropriate 1226 * Return the found inode number & CI name if appropriate
1226 */ 1227 */
1227 args->inumber = be64_to_cpu(dep->inumber); 1228 args->inumber = be64_to_cpu(dep->inumber);
1229 args->filetype = xfs_dir3_dirent_get_ftype(dp->i_mount, dep);
1228 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); 1230 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
1229 xfs_trans_brelse(tp, dbp); 1231 xfs_trans_brelse(tp, dbp);
1230 xfs_trans_brelse(tp, lbp); 1232 xfs_trans_brelse(tp, lbp);
@@ -1555,6 +1557,7 @@ xfs_dir2_leaf_replace(
1555 * Put the new inode number in, log it. 1557 * Put the new inode number in, log it.
1556 */ 1558 */
1557 dep->inumber = cpu_to_be64(args->inumber); 1559 dep->inumber = cpu_to_be64(args->inumber);
1560 xfs_dir3_dirent_put_ftype(dp->i_mount, dep, args->filetype);
1558 tp = args->trans; 1561 tp = args->trans;
1559 xfs_dir2_data_log_entry(tp, dbp, dep); 1562 xfs_dir2_data_log_entry(tp, dbp, dep);
1560 xfs_dir3_leaf_check(dp->i_mount, lbp); 1563 xfs_dir3_leaf_check(dp->i_mount, lbp);
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 49f1e9ed492c..4c3dba7ffb74 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -816,6 +816,7 @@ xfs_dir2_leafn_lookup_for_entry(
816 xfs_trans_brelse(tp, state->extrablk.bp); 816 xfs_trans_brelse(tp, state->extrablk.bp);
817 args->cmpresult = cmp; 817 args->cmpresult = cmp;
818 args->inumber = be64_to_cpu(dep->inumber); 818 args->inumber = be64_to_cpu(dep->inumber);
819 args->filetype = xfs_dir3_dirent_get_ftype(mp, dep);
819 *indexp = index; 820 *indexp = index;
820 state->extravalid = 1; 821 state->extravalid = 1;
821 state->extrablk.bp = curbp; 822 state->extrablk.bp = curbp;
@@ -2007,6 +2008,7 @@ xfs_dir2_node_addname_int(
2007 dep->inumber = cpu_to_be64(args->inumber); 2008 dep->inumber = cpu_to_be64(args->inumber);
2008 dep->namelen = args->namelen; 2009 dep->namelen = args->namelen;
2009 memcpy(dep->name, args->name, dep->namelen); 2010 memcpy(dep->name, args->name, dep->namelen);
2011 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
2010 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 2012 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
2011 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 2013 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
2012 xfs_dir2_data_log_entry(tp, dbp, dep); 2014 xfs_dir2_data_log_entry(tp, dbp, dep);
@@ -2227,6 +2229,7 @@ xfs_dir2_node_replace(
2227 * Fill in the new inode number and log the entry. 2229 * Fill in the new inode number and log the entry.