aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-05-19 17:46:40 -0400
committerDave Chinner <david@fromorbit.com>2014-05-19 17:46:40 -0400
commit263997a6842b27a49f42bd795c5dd12242917b22 (patch)
tree200787e719da8e4e91a04d1235e47538aa4b85eb /fs
parent32bf1deae15b67839a2f0cb233254125be73fc78 (diff)
xfs: turn NLINK feature on by default
mkfs has turned on the XFS_SB_VERSION_NLINKBIT feature bit by default since November 2007. It's about time we simply made the kernel code turn it on by default and so always convert v1 inodes to v2 inodes when reading them in from disk or allocating them. This This removes needless version checks and modification when bumping link counts on inodes, and will take code out of a few common code paths. text data bss dec hex filename 783251 100867 616 884734 d7ffe fs/xfs/xfs.o.orig 782664 100867 616 884147 d7db3 fs/xfs/xfs.o.patched Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_fsops.c4
-rw-r--r--fs/xfs/xfs_ialloc.c4
-rw-r--r--fs/xfs/xfs_inode.c111
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_inode_buf.c17
-rw-r--r--fs/xfs/xfs_inode_item.c32
-rw-r--r--fs/xfs/xfs_ioctl.c9
-rw-r--r--fs/xfs/xfs_mount.c6
-rw-r--r--fs/xfs/xfs_sb.h10
9 files changed, 30 insertions, 164 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 02fb943cbf22..d49c67acabf8 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -74,11 +74,9 @@ xfs_fs_geometry(
74 } 74 }
75 if (new_version >= 3) { 75 if (new_version >= 3) {
76 geo->version = XFS_FSOP_GEOM_VERSION; 76 geo->version = XFS_FSOP_GEOM_VERSION;
77 geo->flags = 77 geo->flags = XFS_FSOP_GEOM_FLAGS_NLINK |
78 (xfs_sb_version_hasattr(&mp->m_sb) ? 78 (xfs_sb_version_hasattr(&mp->m_sb) ?
79 XFS_FSOP_GEOM_FLAGS_ATTR : 0) | 79 XFS_FSOP_GEOM_FLAGS_ATTR : 0) |
80 (xfs_sb_version_hasnlink(&mp->m_sb) ?
81 XFS_FSOP_GEOM_FLAGS_NLINK : 0) |
82 (xfs_sb_version_hasquota(&mp->m_sb) ? 80 (xfs_sb_version_hasquota(&mp->m_sb) ?
83 XFS_FSOP_GEOM_FLAGS_QUOTA : 0) | 81 XFS_FSOP_GEOM_FLAGS_QUOTA : 0) |
84 (xfs_sb_version_hasalign(&mp->m_sb) ? 82 (xfs_sb_version_hasalign(&mp->m_sb) ?
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 8f711db61a0c..449fa7b08b56 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -220,10 +220,8 @@ xfs_ialloc_inode_init(
220 if (tp) 220 if (tp)
221 xfs_icreate_log(tp, agno, agbno, mp->m_ialloc_inos, 221 xfs_icreate_log(tp, agno, agbno, mp->m_ialloc_inos,
222 mp->m_sb.sb_inodesize, length, gen); 222 mp->m_sb.sb_inodesize, length, gen);
223 } else if (xfs_sb_version_hasnlink(&mp->m_sb)) 223 } else
224 version = 2; 224 version = 2;
225 else
226 version = 1;
227 225
228 for (j = 0; j < nbufs; j++) { 226 for (j = 0; j < nbufs; j++) {
229 /* 227 /*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 768087bedbac..9731977be528 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -682,6 +682,14 @@ xfs_ialloc(
682 return error; 682 return error;
683 ASSERT(ip != NULL); 683 ASSERT(ip != NULL);
684 684
685 /*
686 * We always convert v1 inodes to v2 now - we only support filesystems
687 * with >= v2 inode capability, so there is no reason for ever leaving
688 * an inode in v1 format.
689 */
690 if (ip->i_d.di_version == 1)
691 ip->i_d.di_version = 2;
692
685 ip->i_d.di_mode = mode; 693 ip->i_d.di_mode = mode;
686 ip->i_d.di_onlink = 0; 694 ip->i_d.di_onlink = 0;
687 ip->i_d.di_nlink = nlink; 695 ip->i_d.di_nlink = nlink;
@@ -691,27 +699,6 @@ xfs_ialloc(
691 xfs_set_projid(ip, prid); 699 xfs_set_projid(ip, prid);
692 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); 700 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
693 701
694 /*
695 * If the superblock version is up to where we support new format
696 * inodes and this is currently an old format inode, then change
697 * the inode version number now. This way we only do the conversion
698 * here rather than here and in the flush/logging code.
699 */
700 if (xfs_sb_version_hasnlink(&mp->m_sb) &&
701 ip->i_d.di_version == 1) {
702 ip->i_d.di_version = 2;
703 /*
704 * We've already zeroed the old link count, the projid field,
705 * and the pad field.
706 */
707 }
708
709 /*
710 * Project ids won't be stored on disk if we are using a version 1 inode.
711 */
712 if ((prid != 0) && (ip->i_d.di_version == 1))
713 xfs_bump_ino_vers2(tp, ip);
714
715 if (pip && XFS_INHERIT_GID(pip)) { 702 if (pip && XFS_INHERIT_GID(pip)) {
716 ip->i_d.di_gid = pip->i_d.di_gid; 703 ip->i_d.di_gid = pip->i_d.di_gid;
717 if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) { 704 if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) {
@@ -1073,40 +1060,6 @@ xfs_droplink(
1073} 1060}
1074 1061
1075/* 1062/*
1076 * This gets called when the inode's version needs to be changed from 1 to 2.
1077 * Currently this happens when the nlink field overflows the old 16-bit value
1078 * or when chproj is called to change the project for the first time.
1079 * As a side effect the superblock version will also get rev'd
1080 * to contain the NLINK bit.
1081 */
1082void
1083xfs_bump_ino_vers2(
1084 xfs_trans_t *tp,
1085 xfs_inode_t *ip)
1086{
1087 xfs_mount_t *mp;
1088
1089 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
1090 ASSERT(ip->i_d.di_version == 1);
1091
1092 ip->i_d.di_version = 2;
1093 ip->i_d.di_onlink = 0;
1094 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
1095 mp = tp->t_mountp;
1096 if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
1097 spin_lock(&mp->m_sb_lock);
1098 if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
1099 xfs_sb_version_addnlink(&mp->m_sb);
1100 spin_unlock(&mp->m_sb_lock);
1101 xfs_mod_sb(tp, XFS_SB_VERSIONNUM);
1102 } else {
1103 spin_unlock(&mp->m_sb_lock);
1104 }
1105 }
1106 /* Caller must log the inode */
1107}
1108
1109/*
1110 * Increment the link count on an inode & log the change. 1063 * Increment the link count on an inode & log the change.
1111 */ 1064 */
1112int 1065int
@@ -1116,22 +1069,10 @@ xfs_bumplink(
1116{ 1069{
1117 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); 1070 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
1118 1071
1072 ASSERT(ip->i_d.di_version > 1);
1119 ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE)); 1073 ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE));
1120 ip->i_d.di_nlink++; 1074 ip->i_d.di_nlink++;
1121 inc_nlink(VFS_I(ip)); 1075 inc_nlink(VFS_I(ip));
1122 if ((ip->i_d.di_version == 1) &&
1123 (ip->i_d.di_nlink > XFS_MAXLINK_1)) {
1124 /*
1125 * The inode has increased its number of links beyond
1126 * what can fit in an old format inode. It now needs
1127 * to be converted to a version 2 inode with a 32 bit
1128 * link count. If this is the first inode in the file
1129 * system to do this, then we need to bump the superblock
1130 * version number as well.
1131 */
1132 xfs_bump_ino_vers2(tp, ip);
1133 }
1134
1135 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 1076 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1136 return 0; 1077 return 0;
1137} 1078}
@@ -3258,6 +3199,7 @@ xfs_iflush_int(
3258 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || 3199 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
3259 ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK)); 3200 ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
3260 ASSERT(iip != NULL && iip->ili_fields != 0); 3201 ASSERT(iip != NULL && iip->ili_fields != 0);
3202 ASSERT(ip->i_d.di_version > 1);
3261 3203
3262 /* set *dip = inode's place in the buffer */ 3204 /* set *dip = inode's place in the buffer */
3263 dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); 3205 dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
@@ -3318,7 +3260,7 @@ xfs_iflush_int(
3318 } 3260 }
3319 3261
3320 /* 3262 /*
3321 * Inode item log recovery for v1/v2 inodes are dependent on the 3263 * Inode item log recovery for v2 inodes are dependent on the
3322 * di_flushiter count for correct sequencing. We bump the flush 3264 * di_flushiter count for correct sequencing. We bump the flush
3323 * iteration count so we can detect flushes which postdate a log record 3265 * iteration count so we can detect flushes which postdate a log record
3324 * during recovery. This is redundant as we now log every change and 3266 * during recovery. This is redundant as we now log every change and
@@ -3341,37 +3283,6 @@ xfs_iflush_int(
3341 if (ip->i_d.di_flushiter == DI_MAX_FLUSH) 3283 if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
3342 ip->i_d.di_flushiter = 0; 3284 ip->i_d.di_flushiter = 0;
3343 3285
3344 /*
3345 * If this is really an old format inode and the superblock version
3346 * has not been updated to support only new format inodes, then
3347 * convert back to the old inode format. If the superblock version
3348 * has been updated, then make the conversion permanent.
3349 */
3350 ASSERT(ip->i_d.di_version == 1 || xfs_sb_version_hasnlink(&mp->m_sb));
3351 if (ip->i_d.di_version == 1) {
3352 if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
3353 /*
3354 * Convert it back.
3355 */
3356 ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
3357 dip->di_onlink = cpu_to_be16(ip->i_d.di_nlink);
3358 } else {
3359 /*
3360 * The superblock version has already been bumped,
3361 * so just make the conversion to the new inode
3362 * format permanent.
3363 */
3364 ip->i_d.di_version = 2;
3365 dip->di_version = 2;
3366 ip->i_d.di_onlink = 0;
3367 dip->di_onlink = 0;
3368 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
3369 memset(&(dip->di_pad[0]), 0,
3370 sizeof(dip->di_pad));
3371 ASSERT(xfs_get_projid(ip) == 0);
3372 }
3373 }
3374
3375 xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp); 3286 xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp);
3376 if (XFS_IFORK_Q(ip)) 3287 if (XFS_IFORK_Q(ip))
3377 xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp); 3288 xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index f2fcde52b66d..d331a0e040eb 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -379,7 +379,6 @@ int xfs_dir_ialloc(struct xfs_trans **, struct xfs_inode *, umode_t,
379 struct xfs_inode **, int *); 379 struct xfs_inode **, int *);
380int xfs_droplink(struct xfs_trans *, struct xfs_inode *); 380int xfs_droplink(struct xfs_trans *, struct xfs_inode *);
381int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); 381int xfs_bumplink(struct xfs_trans *, struct xfs_inode *);
382void xfs_bump_ino_vers2(struct xfs_trans *, struct xfs_inode *);
383 382
384/* from xfs_file.c */ 383/* from xfs_file.c */
385int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); 384int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c
index 24e993996bdc..cb35ae41d4a1 100644
--- a/fs/xfs/xfs_inode_buf.c
+++ b/fs/xfs/xfs_inode_buf.c
@@ -437,17 +437,16 @@ xfs_iread(
437 } 437 }
438 438
439 /* 439 /*
440 * The inode format changed when we moved the link count and 440 * Automatically convert version 1 inode formats in memory to version 2
441 * made it 32 bits long. If this is an old format inode, 441 * inode format. If the inode is modified, it will get logged and
442 * convert it in memory to look like a new one. If it gets 442 * rewritten as a version 2 inode. We can do this because we set the
443 * flushed to disk we will convert back before flushing or 443 * superblock feature bit for v2 inodes unconditionally during mount
444 * logging it. We zero out the new projid field and the old link 444 * and it means the reast of the code can assume the inode version is 2
445 * count field. We'll handle clearing the pad field (the remains 445 * or higher.
446 * of the old uuid field) when we actually convert the inode to
447 * the new format. We don't change the version number so that we
448 * can distinguish this from a real new format inode.
449 */ 446 */
450 if (ip->i_d.di_version == 1) { 447 if (ip->i_d.di_version == 1) {
448 ip->i_d.di_version = 2;
449 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
451 ip->i_d.di_nlink = ip->i_d.di_onlink; 450 ip->i_d.di_nlink = ip->i_d.di_onlink;
452 ip->i_d.di_onlink = 0; 451 ip->i_d.di_onlink = 0;
453 xfs_set_projid(ip, 0); 452 xfs_set_projid(ip, 0);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 686889b4a1e5..a640137b3573 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -145,34 +145,6 @@ xfs_inode_item_size(
145 xfs_inode_item_attr_fork_size(iip, nvecs, nbytes); 145 xfs_inode_item_attr_fork_size(iip, nvecs, nbytes);
146} 146}
147 147
148/*
149 * If this is a v1 format inode, then we need to log it as such. This means
150 * that we have to copy the link count from the new field to the old. We
151 * don't have to worry about the new fields, because nothing trusts them as
152 * long as the old inode version number is there.
153 */
154STATIC void
155xfs_inode_item_format_v1_inode(
156 struct xfs_inode *ip)
157{
158 if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) {
159 /*
160 * Convert it back.
161 */
162 ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
163 ip->i_d.di_onlink = ip->i_d.di_nlink;
164 } else {
165 /*
166 * The superblock version has already been bumped,
167 * so just make the conversion to the new inode
168 * format permanent.
169 */
170 ip->i_d.di_version = 2;
171 ip->i_d.di_onlink = 0;
172 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
173 }
174}
175
176STATIC void 148STATIC void
177xfs_inode_item_format_data_fork( 149xfs_inode_item_format_data_fork(
178 struct xfs_inode_log_item *iip, 150 struct xfs_inode_log_item *iip,
@@ -370,6 +342,8 @@ xfs_inode_item_format(
370 struct xfs_inode_log_format *ilf; 342 struct xfs_inode_log_format *ilf;
371 struct xfs_log_iovec *vecp = NULL; 343 struct xfs_log_iovec *vecp = NULL;
372 344
345 ASSERT(ip->i_d.di_version > 1);
346
373 ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT); 347 ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT);
374 ilf->ilf_type = XFS_LI_INODE; 348 ilf->ilf_type = XFS_LI_INODE;
375 ilf->ilf_ino = ip->i_ino; 349 ilf->ilf_ino = ip->i_ino;
@@ -380,8 +354,6 @@ xfs_inode_item_format(
380 ilf->ilf_size = 2; /* format + core */ 354 ilf->ilf_size = 2; /* format + core */
381 xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); 355 xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format));
382 356
383 if (ip->i_d.di_version == 1)
384 xfs_inode_item_format_v1_inode(ip);
385 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, 357 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE,
386 &ip->i_d, 358 &ip->i_d,
387 xfs_icdinode_size(ip->i_d.di_version)); 359 xfs_icdinode_size(ip->i_d.di_version));
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 0b18776b075e..f920d4200207 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1227,15 +1227,8 @@ xfs_ioctl_setattr(
1227 olddquot = xfs_qm_vop_chown(tp, ip, 1227 olddquot = xfs_qm_vop_chown(tp, ip,
1228 &ip->i_pdquot, pdqp); 1228 &ip->i_pdquot, pdqp);
1229 } 1229 }
1230 ASSERT(ip->i_d.di_version > 1);
1230 xfs_set_projid(ip, fa->fsx_projid); 1231 xfs_set_projid(ip, fa->fsx_projid);
1231
1232 /*
1233 * We may have to rev the inode as well as
1234 * the superblock version number since projids didn't
1235 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1236 */
1237 if (ip->i_d.di_version == 1)
1238 xfs_bump_ino_vers2(tp, ip);
1239 } 1232 }
1240 1233
1241 } 1234 }
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 944f3d9456a8..3f097825eff3 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -697,6 +697,12 @@ xfs_mountfs(
697 mp->m_update_flags |= XFS_SB_VERSIONNUM; 697 mp->m_update_flags |= XFS_SB_VERSIONNUM;
698 } 698 }
699 699
700 /* always use v2 inodes by default now */
701 if (!(mp->m_sb.sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {
702 mp->m_sb.sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
703 mp->m_update_flags |= XFS_SB_VERSIONNUM;
704 }
705
700 /* 706 /*
701 * Check if sb_agblocks is aligned at stripe boundary 707 * Check if sb_agblocks is aligned at stripe boundary
702 * If sb_agblocks is NOT aligned turn off m_dalign since 708 * If sb_agblocks is NOT aligned turn off m_dalign since
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index a6a76f41aad2..a2826cf57d78 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -376,16 +376,6 @@ static inline void xfs_sb_version_addattr(struct xfs_sb *sbp)
376 sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; 376 sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
377} 377}
378 378
379static inline bool xfs_sb_version_hasnlink(struct xfs_sb *sbp)
380{
381 return (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT);
382}
383
384static inline void xfs_sb_version_addnlink(struct xfs_sb *sbp)
385{
386 sbp->sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
387}
388
389static inline bool xfs_sb_version_hasquota(struct xfs_sb *sbp) 379static inline bool xfs_sb_version_hasquota(struct xfs_sb *sbp)
390{ 380{
391 return (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT); 381 return (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT);