aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2014-07-24 06:51:54 -0400
committerDave Chinner <david@fromorbit.com>2014-07-24 06:51:54 -0400
commit9de67c3ba9ea961ba420573d56479d09d33a7587 (patch)
treed173aa82969c02f0b8d275e9618d170652e0afa1 /fs/xfs
parenteb866bbf095ec68552c0583199208858618498e3 (diff)
xfs: allow inode allocations in post-growfs disk space
Today, if we perform an xfs_growfs which adds allocation groups, mp->m_maxagi is not properly updated when the growfs is complete. Therefore inodes will continue to be allocated only in the AGs which existed prior to the growfs, and the new space won't be utilized. This is because of this path in xfs_growfs_data_private(): xfs_growfs_data_private xfs_initialize_perag(mp, nagcount, &nagimax); if (mp->m_flags & XFS_MOUNT_32BITINODES) index = xfs_set_inode32(mp); else index = xfs_set_inode64(mp); if (maxagi) *maxagi = index; where xfs_set_inode* iterates over the (old) agcount in mp->m_sb.sb_agblocks, which has not yet been updated in the growfs path. So "index" will be returned based on the old agcount, not the new one, and new AGs are not available for inode allocation. Fix this by explicitly passing the proper AG count (which xfs_initialize_perag() already has) down another level, so that xfs_set_inode* can make the proper decision about acceptable AGs for inode allocation in the potentially newly-added AGs. This has been broken since 3.7, when these two xfs_set_inode* functions were added in commit 2d2194f. Prior to that, we looped over "agcount" not sb_agblocks in these calculations. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_mount.c4
-rw-r--r--fs/xfs/xfs_super.c20
-rw-r--r--fs/xfs/xfs_super.h4
3 files changed, 17 insertions, 11 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d5c44a6bdb5b..f205a2c84c7a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -250,9 +250,9 @@ xfs_initialize_perag(
250 mp->m_flags &= ~XFS_MOUNT_32BITINODES; 250 mp->m_flags &= ~XFS_MOUNT_32BITINODES;
251 251
252 if (mp->m_flags & XFS_MOUNT_32BITINODES) 252 if (mp->m_flags & XFS_MOUNT_32BITINODES)
253 index = xfs_set_inode32(mp); 253 index = xfs_set_inode32(mp, agcount);
254 else 254 else
255 index = xfs_set_inode64(mp); 255 index = xfs_set_inode64(mp, agcount);
256 256
257 if (maxagi) 257 if (maxagi)
258 *maxagi = index; 258 *maxagi = index;
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index f2e5f8a503d2..b475eb629772 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -597,8 +597,13 @@ xfs_max_file_offset(
597 return (((__uint64_t)pagefactor) << bitshift) - 1; 597 return (((__uint64_t)pagefactor) << bitshift) - 1;
598} 598}
599 599
600/*
601 * xfs_set_inode32() and xfs_set_inode64() are passed an agcount
602 * because in the growfs case, mp->m_sb.sb_agcount is not updated
603 * yet to the potentially higher ag count.
604 */
600xfs_agnumber_t 605xfs_agnumber_t
601xfs_set_inode32(struct xfs_mount *mp) 606xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount)
602{ 607{
603 xfs_agnumber_t index = 0; 608 xfs_agnumber_t index = 0;
604 xfs_agnumber_t maxagi = 0; 609 xfs_agnumber_t maxagi = 0;
@@ -620,10 +625,10 @@ xfs_set_inode32(struct xfs_mount *mp)
620 do_div(icount, sbp->sb_agblocks); 625 do_div(icount, sbp->sb_agblocks);
621 max_metadata = icount; 626 max_metadata = icount;
622 } else { 627 } else {
623 max_metadata = sbp->sb_agcount; 628 max_metadata = agcount;
624 } 629 }
625 630
626 for (index = 0; index < sbp->sb_agcount; index++) { 631 for (index = 0; index < agcount; index++) {
627 ino = XFS_AGINO_TO_INO(mp, index, agino); 632 ino = XFS_AGINO_TO_INO(mp, index, agino);
628 633
629 if (ino > XFS_MAXINUMBER_32) { 634 if (ino > XFS_MAXINUMBER_32) {
@@ -648,11 +653,11 @@ xfs_set_inode32(struct xfs_mount *mp)
648} 653}
649 654
650xfs_agnumber_t 655xfs_agnumber_t
651xfs_set_inode64(struct xfs_mount *mp) 656xfs_set_inode64(struct xfs_mount *mp, xfs_agnumber_t agcount)
652{ 657{
653 xfs_agnumber_t index = 0; 658 xfs_agnumber_t index = 0;
654 659
655 for (index = 0; index < mp->m_sb.sb_agcount; index++) { 660 for (index = 0; index < agcount; index++) {
656 struct xfs_perag *pag; 661 struct xfs_perag *pag;
657 662
658 pag = xfs_perag_get(mp, index); 663 pag = xfs_perag_get(mp, index);
@@ -1188,6 +1193,7 @@ xfs_fs_remount(
1188 char *options) 1193 char *options)
1189{ 1194{
1190 struct xfs_mount *mp = XFS_M(sb); 1195 struct xfs_mount *mp = XFS_M(sb);
1196 xfs_sb_t *sbp = &mp->m_sb;
1191 substring_t args[MAX_OPT_ARGS]; 1197 substring_t args[MAX_OPT_ARGS];
1192 char *p; 1198 char *p;
1193 int error; 1199 int error;
@@ -1208,10 +1214,10 @@ xfs_fs_remount(
1208 mp->m_flags &= ~XFS_MOUNT_BARRIER; 1214 mp->m_flags &= ~XFS_MOUNT_BARRIER;
1209 break; 1215 break;
1210 case Opt_inode64: 1216 case Opt_inode64:
1211 mp->m_maxagi = xfs_set_inode64(mp); 1217 mp->m_maxagi = xfs_set_inode64(mp, sbp->sb_agcount);
1212 break; 1218 break;
1213 case Opt_inode32: 1219 case Opt_inode32:
1214 mp->m_maxagi = xfs_set_inode32(mp); 1220 mp->m_maxagi = xfs_set_inode32(mp, sbp->sb_agcount);
1215 break; 1221 break;
1216 default: 1222 default:
1217 /* 1223 /*
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index bbe3d15a7904..b4cfe21d8fb0 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -76,8 +76,8 @@ extern __uint64_t xfs_max_file_offset(unsigned int);
76 76
77extern void xfs_flush_inodes(struct xfs_mount *mp); 77extern void xfs_flush_inodes(struct xfs_mount *mp);
78extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); 78extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
79extern xfs_agnumber_t xfs_set_inode32(struct xfs_mount *); 79extern xfs_agnumber_t xfs_set_inode32(struct xfs_mount *, xfs_agnumber_t agcount);
80extern xfs_agnumber_t xfs_set_inode64(struct xfs_mount *); 80extern xfs_agnumber_t xfs_set_inode64(struct xfs_mount *, xfs_agnumber_t agcount);
81 81
82extern const struct export_operations xfs_export_operations; 82extern const struct export_operations xfs_export_operations;
83extern const struct xattr_handler *xfs_xattr_handlers[]; 83extern const struct xattr_handler *xfs_xattr_handlers[];