提交 12c3f05c 编写于 作者: E Eric Sandeen 提交者: Dave Chinner

xfs: fix up inode32/64 (re)mount handling

inode32/inode64 allocator behavior with respect to mount, remount
and growfs is a little tricky.

The inode32 mount option should only enable the inode32 allocator
heuristics if the filesystem is large enough for 64-bit inodes to
exist.  Today, it has this behavior on the initial mount, but a
remount with inode32 unconditionally changes the allocation
heuristics, even for a small fs.

Also, an inode32 mounted small filesystem should transition to the
inode32 allocator if the filesystem is subsequently grown to a
sufficient size.  Today that does not happen.

This patch consolidates xfs_set_inode32 and xfs_set_inode64 into a
single new function, and moves the "is the maximum inode number big
enough to matter" test into that function, so it doesn't rely on the
caller to get it right - which remount did not do, previously.
Signed-off-by: NEric Sandeen <sandeen@redhat.com>
Reviewed-by: NBrian Foster <bfoster@redhat.com>
Signed-off-by: NDave Chinner <david@fromorbit.com>
上级 5d518bd6
...@@ -185,9 +185,6 @@ xfs_initialize_perag( ...@@ -185,9 +185,6 @@ xfs_initialize_perag(
xfs_agnumber_t index; xfs_agnumber_t index;
xfs_agnumber_t first_initialised = 0; xfs_agnumber_t first_initialised = 0;
xfs_perag_t *pag; xfs_perag_t *pag;
xfs_agino_t agino;
xfs_ino_t ino;
xfs_sb_t *sbp = &mp->m_sb;
int error = -ENOMEM; int error = -ENOMEM;
/* /*
...@@ -230,22 +227,7 @@ xfs_initialize_perag( ...@@ -230,22 +227,7 @@ xfs_initialize_perag(
radix_tree_preload_end(); radix_tree_preload_end();
} }
/* index = xfs_set_inode_alloc(mp, agcount);
* If we mount with the inode64 option, or no inode overflows
* the legacy 32-bit address space clear the inode32 option.
*/
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
mp->m_flags |= XFS_MOUNT_32BITINODES;
else
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
if (mp->m_flags & XFS_MOUNT_32BITINODES)
index = xfs_set_inode32(mp, agcount);
else
index = xfs_set_inode64(mp, agcount);
if (maxagi) if (maxagi)
*maxagi = index; *maxagi = index;
......
...@@ -166,9 +166,8 @@ typedef struct xfs_mount { ...@@ -166,9 +166,8 @@ typedef struct xfs_mount {
#define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */ #define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */
#define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */ #define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */
#define XFS_MOUNT_DFLT_IOSIZE (1ULL << 12) /* set default i/o size */ #define XFS_MOUNT_DFLT_IOSIZE (1ULL << 12) /* set default i/o size */
#define XFS_MOUNT_32BITINODES (1ULL << 14) /* do not create inodes above #define XFS_MOUNT_SMALL_INUMS (1ULL << 14) /* user wants 32bit inodes */
* 32 bits in size */ #define XFS_MOUNT_32BITINODES (1ULL << 15) /* inode32 allocator active */
#define XFS_MOUNT_SMALL_INUMS (1ULL << 15) /* users wants 32bit inodes */
#define XFS_MOUNT_NOUUID (1ULL << 16) /* ignore uuid during mount */ #define XFS_MOUNT_NOUUID (1ULL << 16) /* ignore uuid during mount */
#define XFS_MOUNT_BARRIER (1ULL << 17) #define XFS_MOUNT_BARRIER (1ULL << 17)
#define XFS_MOUNT_IKEEP (1ULL << 18) /* keep empty inode clusters*/ #define XFS_MOUNT_IKEEP (1ULL << 18) /* keep empty inode clusters*/
......
...@@ -580,23 +580,35 @@ xfs_max_file_offset( ...@@ -580,23 +580,35 @@ xfs_max_file_offset(
} }
/* /*
* xfs_set_inode32() and xfs_set_inode64() are passed an agcount * Set parameters for inode allocation heuristics, taking into account
* because in the growfs case, mp->m_sb.sb_agcount is not updated * filesystem size and inode32/inode64 mount options; i.e. specifically
* yet to the potentially higher ag count. * whether or not XFS_MOUNT_SMALL_INUMS is set.
*
* Inode allocation patterns are altered only if inode32 is requested
* (XFS_MOUNT_SMALL_INUMS), and the filesystem is sufficiently large.
* If altered, XFS_MOUNT_32BITINODES is set as well.
*
* An agcount independent of that in the mount structure is provided
* because in the growfs case, mp->m_sb.sb_agcount is not yet updated
* to the potentially higher ag count.
*
* Returns the maximum AG index which may contain inodes.
*/ */
xfs_agnumber_t xfs_agnumber_t
xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount) xfs_set_inode_alloc(
struct xfs_mount *mp,
xfs_agnumber_t agcount)
{ {
xfs_agnumber_t index = 0; xfs_agnumber_t index;
xfs_agnumber_t maxagi = 0; xfs_agnumber_t maxagi = 0;
xfs_sb_t *sbp = &mp->m_sb; xfs_sb_t *sbp = &mp->m_sb;
xfs_agnumber_t max_metadata; xfs_agnumber_t max_metadata;
xfs_agino_t agino; xfs_agino_t agino;
xfs_ino_t ino; xfs_ino_t ino;
xfs_perag_t *pag;
/* Calculate how much should be reserved for inodes to meet /*
* the max inode percentage. * Calculate how much should be reserved for inodes to meet
* the max inode percentage. Used only for inode32.
*/ */
if (mp->m_maxicount) { if (mp->m_maxicount) {
__uint64_t icount; __uint64_t icount;
...@@ -610,54 +622,48 @@ xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount) ...@@ -610,54 +622,48 @@ xfs_set_inode32(struct xfs_mount *mp, xfs_agnumber_t agcount)
max_metadata = agcount; max_metadata = agcount;
} }
/* Get the last possible inode in the filesystem */
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
/*
* If user asked for no more than 32-bit inodes, and the fs is
* sufficiently large, set XFS_MOUNT_32BITINODES if we must alter
* the allocator to accommodate the request.
*/
if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
mp->m_flags |= XFS_MOUNT_32BITINODES;
else
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
for (index = 0; index < agcount; index++) { for (index = 0; index < agcount; index++) {
ino = XFS_AGINO_TO_INO(mp, index, agino); struct xfs_perag *pag;
if (ino > XFS_MAXINUMBER_32) { ino = XFS_AGINO_TO_INO(mp, index, agino);
pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 0;
pag->pagf_metadata = 0;
xfs_perag_put(pag);
continue;
}
pag = xfs_perag_get(mp, index); pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 1;
maxagi++;
if (index < max_metadata)
pag->pagf_metadata = 1;
xfs_perag_put(pag);
}
mp->m_flags |= (XFS_MOUNT_32BITINODES |
XFS_MOUNT_SMALL_INUMS);
return maxagi; if (mp->m_flags & XFS_MOUNT_32BITINODES) {
} if (ino > XFS_MAXINUMBER_32) {
pag->pagi_inodeok = 0;
xfs_agnumber_t pag->pagf_metadata = 0;
xfs_set_inode64(struct xfs_mount *mp, xfs_agnumber_t agcount) } else {
{ pag->pagi_inodeok = 1;
xfs_agnumber_t index = 0; maxagi++;
if (index < max_metadata)
for (index = 0; index < agcount; index++) { pag->pagf_metadata = 1;
struct xfs_perag *pag; else
pag->pagf_metadata = 0;
}
} else {
pag->pagi_inodeok = 1;
pag->pagf_metadata = 0;
}
pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 1;
pag->pagf_metadata = 0;
xfs_perag_put(pag); xfs_perag_put(pag);
} }
/* There is no need for lock protection on m_flags, return (mp->m_flags & XFS_MOUNT_32BITINODES) ? maxagi : agcount;
* the rw_semaphore of the VFS superblock is locked
* during mount/umount/remount operations, so this is
* enough to avoid concurency on the m_flags field
*/
mp->m_flags &= ~(XFS_MOUNT_32BITINODES |
XFS_MOUNT_SMALL_INUMS);
return index;
} }
STATIC int STATIC int
...@@ -1227,10 +1233,12 @@ xfs_fs_remount( ...@@ -1227,10 +1233,12 @@ xfs_fs_remount(
mp->m_flags &= ~XFS_MOUNT_BARRIER; mp->m_flags &= ~XFS_MOUNT_BARRIER;
break; break;
case Opt_inode64: case Opt_inode64:
mp->m_maxagi = xfs_set_inode64(mp, sbp->sb_agcount); mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
break; break;
case Opt_inode32: case Opt_inode32:
mp->m_maxagi = xfs_set_inode32(mp, sbp->sb_agcount); mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
break; break;
default: default:
/* /*
......
...@@ -65,8 +65,8 @@ extern __uint64_t xfs_max_file_offset(unsigned int); ...@@ -65,8 +65,8 @@ extern __uint64_t xfs_max_file_offset(unsigned int);
extern void xfs_flush_inodes(struct xfs_mount *mp); extern void xfs_flush_inodes(struct xfs_mount *mp);
extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
extern xfs_agnumber_t xfs_set_inode32(struct xfs_mount *, xfs_agnumber_t agcount); extern xfs_agnumber_t xfs_set_inode_alloc(struct xfs_mount *,
extern xfs_agnumber_t xfs_set_inode64(struct xfs_mount *, xfs_agnumber_t agcount); xfs_agnumber_t agcount);
extern const struct export_operations xfs_export_operations; extern const struct export_operations xfs_export_operations;
extern const struct xattr_handler *xfs_xattr_handlers[]; extern const struct xattr_handler *xfs_xattr_handlers[];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册