]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/xfs/quota/xfs_dquot.c
[XFS] Remove xfs_macros.c, xfs_macros.h, rework headers a whole lot.
[mirror_ubuntu-bionic-kernel.git] / fs / xfs / quota / xfs_dquot.c
index 46ce1e3ce1d6c04c90b93ec46d86d2e4f64651fc..5971f6f6ec78dfb6d715a0bea82a3234cb740dcb 100644 (file)
@@ -32,8 +32,9 @@
 
 #include "xfs.h"
 #include "xfs_fs.h"
-#include "xfs_inum.h"
+#include "xfs_bit.h"
 #include "xfs_log.h"
+#include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
 #include "xfs_dmapi.h"
 #include "xfs_quota.h"
 #include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_attr_sf.h"
 #include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
+#include "xfs_btree.h"
+#include "xfs_ialloc.h"
 #include "xfs_bmap.h"
-#include "xfs_bit.h"
 #include "xfs_rtalloc.h"
 #include "xfs_error.h"
 #include "xfs_itable.h"
@@ -421,7 +421,7 @@ xfs_qm_init_dquot_blk(
  */
 STATIC int
 xfs_qm_dqalloc(
-       xfs_trans_t     *tp,
+       xfs_trans_t     **tpp,
        xfs_mount_t     *mp,
        xfs_dquot_t     *dqp,
        xfs_inode_t     *quotip,
@@ -433,6 +433,7 @@ xfs_qm_dqalloc(
        xfs_bmbt_irec_t map;
        int             nmaps, error, committed;
        xfs_buf_t       *bp;
+       xfs_trans_t     *tp = *tpp;
 
        ASSERT(tp != NULL);
        xfs_dqtrace_entry(dqp, "DQALLOC");
@@ -492,10 +493,32 @@ xfs_qm_dqalloc(
        xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
                              dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
 
-       if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
+       /*
+        * xfs_bmap_finish() may commit the current transaction and
+        * start a second transaction if the freelist is not empty.
+        *
+        * Since we still want to modify this buffer, we need to
+        * ensure that the buffer is not released on commit of
+        * the first transaction and ensure the buffer is added to the
+        * second transaction.
+        *
+        * If there is only one transaction then don't stop the buffer
+        * from being released when it commits later on.
+        */
+
+       xfs_trans_bhold(tp, bp);
+
+       if ((error = xfs_bmap_finish(tpp, &flist, firstblock, &committed))) {
                goto error1;
        }
 
+       if (committed) {
+               tp = *tpp;
+               xfs_trans_bjoin(tp, bp);
+       } else {
+               xfs_trans_bhold_release(tp, bp);
+       }
+
        *O_bpp = bp;
        return 0;
 
@@ -514,7 +537,7 @@ xfs_qm_dqalloc(
  */
 STATIC int
 xfs_qm_dqtobp(
-       xfs_trans_t             *tp,
+       xfs_trans_t             **tpp,
        xfs_dquot_t             *dqp,
        xfs_disk_dquot_t        **O_ddpp,
        xfs_buf_t               **O_bpp,
@@ -528,6 +551,7 @@ xfs_qm_dqtobp(
        xfs_disk_dquot_t *ddq;
        xfs_dqid_t      id;
        boolean_t       newdquot;
+       xfs_trans_t     *tp = (tpp ? *tpp : NULL);
 
        mp = dqp->q_mount;
        id = INT_GET(dqp->q_core.d_id, ARCH_CONVERT);
@@ -539,8 +563,7 @@ xfs_qm_dqtobp(
         */
        if (dqp->q_blkno == (xfs_daddr_t) 0) {
                /* We use the id as an index */
-               dqp->q_fileoffset = (xfs_fileoff_t) ((uint)id /
-                                                    XFS_QM_DQPERBLK(mp));
+               dqp->q_fileoffset = (xfs_fileoff_t)id / XFS_QM_DQPERBLK(mp);
                nmaps = 1;
                quotip = XFS_DQ_TO_QIP(dqp);
                xfs_ilock(quotip, XFS_ILOCK_SHARED);
@@ -579,9 +602,10 @@ xfs_qm_dqtobp(
                                return (ENOENT);
 
                        ASSERT(tp);
-                       if ((error = xfs_qm_dqalloc(tp, mp, dqp, quotip,
+                       if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
                                                dqp->q_fileoffset, &bp)))
                                return (error);
+                       tp = *tpp;
                        newdquot = B_TRUE;
                } else {
                        /*
@@ -645,7 +669,7 @@ xfs_qm_dqtobp(
 /* ARGSUSED */
 STATIC int
 xfs_qm_dqread(
-       xfs_trans_t     *tp,
+       xfs_trans_t     **tpp,
        xfs_dqid_t      id,
        xfs_dquot_t     *dqp,   /* dquot to get filled in */
        uint            flags)
@@ -653,15 +677,19 @@ xfs_qm_dqread(
        xfs_disk_dquot_t *ddqp;
        xfs_buf_t        *bp;
        int              error;
+       xfs_trans_t      *tp;
+
+       ASSERT(tpp);
 
        /*
         * get a pointer to the on-disk dquot and the buffer containing it
         * dqp already knows its own type (GROUP/USER).
         */
        xfs_dqtrace_entry(dqp, "DQREAD");
-       if ((error = xfs_qm_dqtobp(tp, dqp, &ddqp, &bp, flags))) {
+       if ((error = xfs_qm_dqtobp(tpp, dqp, &ddqp, &bp, flags))) {
                return (error);
        }
+       tp = *tpp;
 
        /* copy everything from disk dquot to the incore dquot */
        memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t));
@@ -740,7 +768,7 @@ xfs_qm_idtodq(
         * Read it from disk; xfs_dqread() takes care of
         * all the necessary initialization of dquot's fields (locks, etc)
         */
-       if ((error = xfs_qm_dqread(tp, id, dqp, flags))) {
+       if ((error = xfs_qm_dqread(&tp, id, dqp, flags))) {
                /*
                 * This can happen if quotas got turned off (ESRCH),
                 * or if the dquot didn't exist on disk and we ask to