aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2_sf.c
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 /fs/xfs/xfs_dir2_sf.c
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>
Diffstat (limited to 'fs/xfs/xfs_dir2_sf.c')
-rw-r--r--fs/xfs/xfs_dir2_sf.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index bd14e1a72c62..bb6e2848f473 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -333,6 +333,8 @@ xfs_dir2_block_to_sf(
333 memcpy(sfep->name, dep->name, dep->namelen); 333 memcpy(sfep->name, dep->name, dep->namelen);
334 xfs_dir3_sfe_put_ino(mp, sfp, sfep, 334 xfs_dir3_sfe_put_ino(mp, sfp, sfep,
335 be64_to_cpu(dep->inumber)); 335 be64_to_cpu(dep->inumber));
336 xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
337 xfs_dir3_dirent_get_ftype(mp, dep));
336 338
337 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 339 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
338 } 340 }
@@ -496,6 +498,8 @@ xfs_dir2_sf_addname_easy(
496 xfs_dir2_sf_put_offset(sfep, offset); 498 xfs_dir2_sf_put_offset(sfep, offset);
497 memcpy(sfep->name, args->name, sfep->namelen); 499 memcpy(sfep->name, args->name, sfep->namelen);
498 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, args->inumber); 500 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, args->inumber);
501 xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep, args->filetype);
502
499 /* 503 /*
500 * Update the header and inode. 504 * Update the header and inode.
501 */ 505 */
@@ -589,6 +593,7 @@ xfs_dir2_sf_addname_hard(
589 xfs_dir2_sf_put_offset(sfep, offset); 593 xfs_dir2_sf_put_offset(sfep, offset);
590 memcpy(sfep->name, args->name, sfep->namelen); 594 memcpy(sfep->name, args->name, sfep->namelen);
591 xfs_dir3_sfe_put_ino(mp, sfp, sfep, args->inumber); 595 xfs_dir3_sfe_put_ino(mp, sfp, sfep, args->inumber);
596 xfs_dir3_sfe_put_ftype(mp, sfp, sfep, args->filetype);
592 sfp->count++; 597 sfp->count++;
593#if XFS_BIG_INUMS 598#if XFS_BIG_INUMS
594 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange) 599 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -825,6 +830,7 @@ xfs_dir2_sf_lookup(
825 if (args->namelen == 1 && args->name[0] == '.') { 830 if (args->namelen == 1 && args->name[0] == '.') {
826 args->inumber = dp->i_ino; 831 args->inumber = dp->i_ino;
827 args->cmpresult = XFS_CMP_EXACT; 832 args->cmpresult = XFS_CMP_EXACT;
833 args->filetype = XFS_DIR3_FT_DIR;
828 return XFS_ERROR(EEXIST); 834 return XFS_ERROR(EEXIST);
829 } 835 }
830 /* 836 /*
@@ -834,6 +840,7 @@ xfs_dir2_sf_lookup(
834 args->name[0] == '.' && args->name[1] == '.') { 840 args->name[0] == '.' && args->name[1] == '.') {
835 args->inumber = xfs_dir2_sf_get_parent_ino(sfp); 841 args->inumber = xfs_dir2_sf_get_parent_ino(sfp);
836 args->cmpresult = XFS_CMP_EXACT; 842 args->cmpresult = XFS_CMP_EXACT;
843 args->filetype = XFS_DIR3_FT_DIR;
837 return XFS_ERROR(EEXIST); 844 return XFS_ERROR(EEXIST);
838 } 845 }
839 /* 846 /*
@@ -853,6 +860,8 @@ xfs_dir2_sf_lookup(
853 args->cmpresult = cmp; 860 args->cmpresult = cmp;
854 args->inumber = xfs_dir3_sfe_get_ino(dp->i_mount, 861 args->inumber = xfs_dir3_sfe_get_ino(dp->i_mount,
855 sfp, sfep); 862 sfp, sfep);
863 args->filetype = xfs_dir3_sfe_get_ftype(dp->i_mount,
864 sfp, sfep);
856 if (cmp == XFS_CMP_EXACT) 865 if (cmp == XFS_CMP_EXACT)
857 return XFS_ERROR(EEXIST); 866 return XFS_ERROR(EEXIST);
858 ci_sfep = sfep; 867 ci_sfep = sfep;
@@ -1052,6 +1061,8 @@ xfs_dir2_sf_replace(
1052#endif 1061#endif
1053 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, 1062 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep,
1054 args->inumber); 1063 args->inumber);
1064 xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep,
1065 args->filetype);
1055 break; 1066 break;
1056 } 1067 }
1057 } 1068 }
@@ -1118,10 +1129,12 @@ xfs_dir2_sf_toino4(
1118 int oldsize; /* old inode size */ 1129 int oldsize; /* old inode size */
1119 xfs_dir2_sf_entry_t *sfep; /* new sf entry */ 1130 xfs_dir2_sf_entry_t *sfep; /* new sf entry */
1120 xfs_dir2_sf_hdr_t *sfp; /* new sf directory */ 1131 xfs_dir2_sf_hdr_t *sfp; /* new sf directory */
1132 struct xfs_mount *mp;
1121 1133
1122 trace_xfs_dir2_sf_toino4(args); 1134 trace_xfs_dir2_sf_toino4(args);
1123 1135
1124 dp = args->dp; 1136 dp = args->dp;
1137 mp = dp->i_mount;
1125 1138
1126 /* 1139 /*
1127 * Copy the old directory to the buffer. 1140 * Copy the old directory to the buffer.
@@ -1159,13 +1172,15 @@ xfs_dir2_sf_toino4(
1159 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1172 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1160 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1173 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1161 i < sfp->count; 1174 i < sfp->count;
1162 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep), 1175 i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep),
1163 oldsfep = xfs_dir3_sf_nextentry(dp->i_mount, oldsfp, oldsfep)) { 1176 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) {
1164 sfep->namelen = oldsfep->namelen; 1177 sfep->namelen = oldsfep->namelen;
1165 sfep->offset = oldsfep->offset; 1178 sfep->offset = oldsfep->offset;
1166 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1179 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1167 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, 1180 xfs_dir3_sfe_put_ino(mp, sfp, sfep,
1168 xfs_dir3_sfe_get_ino(dp->i_mount, oldsfp, oldsfep)); 1181 xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep));
1182 xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
1183 xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep));
1169 } 1184 }
1170 /* 1185 /*
1171 * Clean up the inode. 1186 * Clean up the inode.
@@ -1193,10 +1208,12 @@ xfs_dir2_sf_toino8(
1193 int oldsize; /* old inode size */ 1208 int oldsize; /* old inode size */
1194 xfs_dir2_sf_entry_t *sfep; /* new sf entry */ 1209 xfs_dir2_sf_entry_t *sfep; /* new sf entry */
1195 xfs_dir2_sf_hdr_t *sfp; /* new sf directory */ 1210 xfs_dir2_sf_hdr_t *sfp; /* new sf directory */
1211 struct xfs_mount *mp;
1196 1212
1197 trace_xfs_dir2_sf_toino8(args); 1213 trace_xfs_dir2_sf_toino8(args);
1198 1214
1199 dp = args->dp; 1215 dp = args->dp;
1216 mp = dp->i_mount;
1200 1217
1201 /* 1218 /*
1202 * Copy the old directory to the buffer. 1219 * Copy the old directory to the buffer.
@@ -1234,13 +1251,15 @@ xfs_dir2_sf_toino8(
1234 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1251 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1235 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1252 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1236 i < sfp->count; 1253 i < sfp->count;
1237 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep), 1254 i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep),
1238 oldsfep = xfs_dir3_sf_nextentry(dp->i_mount, oldsfp, oldsfep)) { 1255 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) {
1239 sfep->namelen = oldsfep->namelen; 1256 sfep->namelen = oldsfep->namelen;
1240 sfep->offset = oldsfep->offset; 1257 sfep->offset = oldsfep->offset;
1241 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1258 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1242 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, 1259 xfs_dir3_sfe_put_ino(mp, sfp, sfep,
1243 xfs_dir3_sfe_get_ino(dp->i_mount, oldsfp, oldsfep)); 1260 xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep));
1261 xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
1262 xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep));
1244 } 1263 }
1245 /* 1264 /*
1246 * Clean up the inode. 1265 * Clean up the inode.