Skip to content

Commit

Permalink
xfs: fix access to upper inodes without inode64
Browse files Browse the repository at this point in the history
If a filesystem is mounted without the inode64 mount option we
should still be able to access inodes not fitting into 32 bits, just
not created new ones.  For this to work we need to make sure the
inode cache radix tree is initialized for all allocation groups, not
just those we plan to allocate inodes from.  This patch makes sure
we initialize the inode cache radix tree for all allocation groups,
and also cleans xfs_initialize_perag up a bit to separate the
inode32 logical from the general perag structure setup.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
  • Loading branch information
Christoph Hellwig authored and Alex Elder committed May 28, 2010
1 parent 9b98b6f commit fb3b504
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 46 deletions.
9 changes: 0 additions & 9 deletions fs/xfs/linux-2.6/xfs_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,6 @@ xfs_inode_ag_iterator(
struct xfs_perag *pag;

pag = xfs_perag_get(mp, ag);
if (!pag->pag_ici_init) {
xfs_perag_put(pag);
continue;
}
error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
exclusive, &nr);
xfs_perag_put(pag);
Expand Down Expand Up @@ -867,12 +863,7 @@ xfs_reclaim_inode_shrink(
down_read(&xfs_mount_list_lock);
list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {

pag = xfs_perag_get(mp, ag);
if (!pag->pag_ici_init) {
xfs_perag_put(pag);
continue;
}
reclaimable += pag->pag_ici_reclaimable;
xfs_perag_put(pag);
}
Expand Down
1 change: 0 additions & 1 deletion fs/xfs/xfs_ag.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ typedef struct xfs_perag {

atomic_t pagf_fstrms; /* # of filestreams active in this AG */

int pag_ici_init; /* incore inode cache initialised */
rwlock_t pag_ici_lock; /* incore inode lock */
struct radix_tree_root pag_ici_root; /* incore inode cache root */
int pag_ici_reclaimable; /* reclaimable inodes */
Expand Down
3 changes: 0 additions & 3 deletions fs/xfs/xfs_iget.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,6 @@ xfs_iget(

/* get the perag structure and ensure that it's inode capable */
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
if (!pag->pagi_inodeok)
return EINVAL;
ASSERT(pag->pag_ici_init);
agino = XFS_INO_TO_AGINO(mp, ino);

again:
Expand Down
2 changes: 0 additions & 2 deletions fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2649,8 +2649,6 @@ xfs_iflush_cluster(
int i;

pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
ASSERT(pag->pagi_inodeok);
ASSERT(pag->pag_ici_init);

inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog;
ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *);
Expand Down
52 changes: 21 additions & 31 deletions fs/xfs/xfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,17 +413,6 @@ xfs_mount_validate_sb(
return 0;
}

STATIC void
xfs_initialize_perag_icache(
xfs_perag_t *pag)
{
if (!pag->pag_ici_init) {
rwlock_init(&pag->pag_ici_lock);
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
pag->pag_ici_init = 1;
}
}

int
xfs_initialize_perag(
xfs_mount_t *mp,
Expand All @@ -436,13 +425,8 @@ xfs_initialize_perag(
xfs_agino_t agino;
xfs_ino_t ino;
xfs_sb_t *sbp = &mp->m_sb;
xfs_ino_t max_inum = XFS_MAXINUMBER_32;
int error = -ENOMEM;

/* Check to see if the filesystem can overflow 32 bit inodes */
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);

/*
* Walk the current per-ag tree so we don't try to initialise AGs
* that already exist (growfs case). Allocate and insert all the
Expand All @@ -456,11 +440,18 @@ xfs_initialize_perag(
}
if (!first_initialised)
first_initialised = index;

pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
if (!pag)
goto out_unwind;
pag->pag_agno = index;
pag->pag_mount = mp;
rwlock_init(&pag->pag_ici_lock);
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);

if (radix_tree_preload(GFP_NOFS))
goto out_unwind;

spin_lock(&mp->m_perag_lock);
if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
BUG();
Expand All @@ -469,25 +460,26 @@ xfs_initialize_perag(
error = -EEXIST;
goto out_unwind;
}
pag->pag_agno = index;
pag->pag_mount = mp;
spin_unlock(&mp->m_perag_lock);
radix_tree_preload_end();
}

/* Clear the mount flag if no inode can overflow 32 bits
* on this filesystem, or if specifically requested..
/*
* If we mount with the inode64 option, or no inode overflows
* the legacy 32-bit address space clear the inode32 option.
*/
if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {
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 {
else
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
}

/* If we can overflow then setup the ag headers accordingly */
if (mp->m_flags & XFS_MOUNT_32BITINODES) {
/* 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.
*/
if (mp->m_maxicount) {
__uint64_t icount;
Expand All @@ -500,30 +492,28 @@ xfs_initialize_perag(
} else {
max_metadata = agcount;
}

for (index = 0; index < agcount; index++) {
ino = XFS_AGINO_TO_INO(mp, index, agino);
if (ino > max_inum) {
if (ino > XFS_MAXINUMBER_32) {
index++;
break;
}

/* This ag is preferred for inodes */
pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 1;
if (index < max_metadata)
pag->pagf_metadata = 1;
xfs_initialize_perag_icache(pag);
xfs_perag_put(pag);
}
} else {
/* Setup default behavior for smaller filesystems */
for (index = 0; index < agcount; index++) {
pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 1;
xfs_initialize_perag_icache(pag);
xfs_perag_put(pag);
}
}

if (maxagi)
*maxagi = index;
return 0;
Expand Down

0 comments on commit fb3b504

Please sign in to comment.