]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
xfs: fix access to upper inodes without inode64
authorChristoph Hellwig <hch@infradead.org>
Fri, 28 May 2010 19:03:10 +0000 (19:03 +0000)
committerAlex Elder <aelder@sgi.com>
Fri, 28 May 2010 20:19:56 +0000 (15:19 -0500)
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>
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/xfs_ag.h
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_mount.c

index 3884e20bc14e523276e855a51e97167ba3f68cbc..ef7f0218bccb45779157128139ab552e8b423832 100644 (file)
@@ -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);
@@ -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);
                }
index 401f364ad36ce52022cabf6ccafa9d58de39dcd2..4917d4eed4edaeac56edffc1d65e4b7bc92acaa7 100644 (file)
@@ -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 */
index 6845db90818f2223cf9fdbc735ed8a423b9338bc..f44a367907a8e88601f60ab2498559a6e3cf3e17 100644 (file)
@@ -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:
index 8cd6e8d8fe9c452e1d7c995d216a4f5745c61f53..6ba7765026f6f92a6c7b41f9d31546ee2bc16578 100644 (file)
@@ -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 *);
index ef1233b096836726c4de05ede15dc6737c674e3a..d59f4e8bedcf2bfaadf2151c829605646c80e745 100644 (file)
@@ -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,
@@ -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
@@ -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();
@@ -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;
@@ -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;