epoll: convert internal api to timespec64
[linux-2.6-microblaze.git] / fs / xfs / xfs_rtalloc.c
index 5b89c12..ede1baf 100644 (file)
@@ -18,7 +18,7 @@
 #include "xfs_trans_space.h"
 #include "xfs_icache.h"
 #include "xfs_rtalloc.h"
-
+#include "xfs_sb.h"
 
 /*
  * Read and return the summary information for a given extent size,
@@ -778,8 +778,14 @@ xfs_growfs_rt_alloc(
        struct xfs_bmbt_irec    map;            /* block map output */
        int                     nmap;           /* number of block maps */
        int                     resblks;        /* space reservation */
+       enum xfs_blft           buf_type;
        struct xfs_trans        *tp;
 
+       if (ip == mp->m_rsumip)
+               buf_type = XFS_BLFT_RTSUMMARY_BUF;
+       else
+               buf_type = XFS_BLFT_RTBITMAP_BUF;
+
        /*
         * Allocate space to the file, as necessary.
         */
@@ -841,6 +847,9 @@ xfs_growfs_rt_alloc(
                                        mp->m_bsize, 0, &bp);
                        if (error)
                                goto out_trans_cancel;
+
+                       xfs_trans_buf_set_type(tp, bp, buf_type);
+                       bp->b_ops = &xfs_rtbuf_ops;
                        memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
                        xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
                        /*
@@ -1015,23 +1024,29 @@ xfs_growfs_rt(
                /*
                 * Lock out other callers by grabbing the bitmap inode lock.
                 */
-               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
                xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
                /*
-                * Update the bitmap inode's size.
+                * Update the bitmap inode's size ondisk and incore.  We need
+                * to update the incore size so that inode inactivation won't
+                * punch what it thinks are "posteof" blocks.
                 */
                mp->m_rbmip->i_d.di_size =
                        nsbp->sb_rbmblocks * nsbp->sb_blocksize;
+               i_size_write(VFS_I(mp->m_rbmip), mp->m_rbmip->i_d.di_size);
                xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
                /*
                 * Get the summary inode into the transaction.
                 */
-               xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
+               xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM);
                xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
                /*
-                * Update the summary inode's size.
+                * Update the summary inode's size.  We need to update the
+                * incore size so that inode inactivation won't punch what it
+                * thinks are "posteof" blocks.
                 */
                mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
+               i_size_write(VFS_I(mp->m_rsumip), mp->m_rsumip->i_d.di_size);
                xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
                /*
                 * Copy summary data from old to new sizes.
@@ -1087,7 +1102,13 @@ error_cancel:
                if (error)
                        break;
        }
+       if (error)
+               goto out_free;
+
+       /* Update secondary superblocks now the physical grow has completed */
+       error = xfs_update_secondary_sbs(mp);
 
+out_free:
        /*
         * Free the fake mp structure.
         */