]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: fix xfs_trans_alloc reservation abuse
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 4 Oct 2018 19:19:01 +0000 (14:19 -0500)
committerEric Sandeen <sandeen@redhat.com>
Thu, 4 Oct 2018 19:19:01 +0000 (14:19 -0500)
Various xfsprogs tools have been abusing the transaction reservation
system by allocating the transaction with zero reservation.  This has
always worked in the past because userspace transactions do not require
reservations.  However, once we merge deferred ops into the transaction
structure, we will need to use a permanent reservation type to set up
any transaction that can roll.  tr_itruncate has all we need, so use
that as the reservation dummy.

[sandeen: tweaks to backport before libxfs updates]
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/xfs_trans.h
libxfs/trans.c
mkfs/proto.c
mkfs/xfs_mkfs.c
repair/phase5.c
repair/phase6.c
repair/rmap.c

index 63972e4fff0f22dca583f0d8df87a540ef777df3..20cf2536cdcfd3474045ce2a8b5f72fca72acd4c 100644 (file)
@@ -82,6 +82,8 @@ int   xfs_trans_roll(struct xfs_trans **);
 int    libxfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,
                           uint blocks, uint rtextents, uint flags,
                           struct xfs_trans **tpp);
+int    libxfs_trans_alloc_rollable(struct xfs_mount *mp, uint blocks,
+                                   struct xfs_trans **tpp);
 int    libxfs_trans_alloc_empty(struct xfs_mount *mp, struct xfs_trans **tpp);
 int    libxfs_trans_commit(struct xfs_trans *);
 void   libxfs_trans_cancel(struct xfs_trans *);
index e827f0df12de7c88f6a3f95c2550cc3f10c2a7bc..3c2253efe0cd4f2906dbe702e72c7253c3f9e13c 100644 (file)
@@ -289,6 +289,21 @@ libxfs_trans_alloc_empty(
        return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp);
 }
 
+/*
+ * Allocate a transaction that can be rolled.  Since userspace doesn't have
+ * a need for log reservations, we really only tr_itruncate to get the
+ * permanent log reservation flag to avoid blowing asserts.
+ */
+int
+libxfs_trans_alloc_rollable(
+       struct xfs_mount        *mp,
+       unsigned int            blocks,
+       struct xfs_trans        **tpp)
+{
+       return libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, blocks,
+                       0, 0, tpp);
+}
+
 void
 libxfs_trans_cancel(
        struct xfs_trans        *tp)
index 9eb15ab03059e38ade9cd8966fc72a60c2b2d611..9eb561b34e65dd7e5f62725812311c9f73489a42 100644 (file)
@@ -123,9 +123,7 @@ getres(
        uint            r;
 
        for (i = 0, r = MKFS_BLOCKRES(blocks); r >= blocks; r--) {
-               struct xfs_trans_res    tres = {0};
-
-               i = -libxfs_trans_alloc(mp, &tres, r, 0, 0, &tp);
+               i = -libxfs_trans_alloc_rollable(mp, r, &tp);
                if (i == 0)
                        return tp;
        }
@@ -180,7 +178,6 @@ rsvfile(
 {
        int             error;
        xfs_trans_t     *tp;
-       struct xfs_trans_res tres = {0};
 
        error = -libxfs_alloc_file_space(ip, 0, llen, 1, 0);
 
@@ -192,7 +189,7 @@ rsvfile(
        /*
         * update the inode timestamp, mode, and prealloc flag bits
         */
-       error = -libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp);
+       error = -libxfs_trans_alloc_rollable(mp, 0, &tp);
        if (error)
                fail(_("allocating transaction for a file"), error);
        libxfs_trans_ijoin(tp, ip, 0);
@@ -630,18 +627,18 @@ rtinit(
        int             i;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        xfs_extlen_t    nsumblocks;
+       uint            blocks;
        int             nmap;
        xfs_inode_t     *rbmip;
        xfs_inode_t     *rsumip;
        xfs_trans_t     *tp;
        struct cred     creds;
        struct fsxattr  fsxattrs;
-       struct xfs_trans_res tres = {0};
 
        /*
         * First, allocate the inodes.
         */
-       i = -libxfs_trans_alloc(mp, &tres, MKFS_BLOCKRES_INODE, 0, 0, &tp);
+       i = -libxfs_trans_alloc_rollable(mp, MKFS_BLOCKRES_INODE, &tp);
        if (i)
                res_failed(i);
 
@@ -678,9 +675,9 @@ rtinit(
        /*
         * Next, give the bitmap file some zero-filled blocks.
         */
-       i = -libxfs_trans_alloc(mp, &tres,
-               mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1),
-                               0, 0, &tp);
+       blocks = mp->m_sb.sb_rbmblocks +
+                       XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
+       i = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
        if (i)
                res_failed(i);
 
@@ -716,9 +713,8 @@ rtinit(
         * Give the summary file some zero-filled blocks.
         */
        nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
-       i = -libxfs_trans_alloc(mp, &tres,
-                       nsumblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1),
-                               0, 0, &tp);
+       blocks = nsumblocks + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
+       i = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
        if (i)
                res_failed(i);
        libxfs_trans_ijoin(tp, rsumip, 0);
@@ -753,7 +749,8 @@ rtinit(
         * Do one transaction per bitmap block.
         */
        for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) {
-               i = -libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp);
+               i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
+                               0, 0, 0, &tp);
                if (i)
                        res_failed(i);
                libxfs_trans_ijoin(tp, rbmip, 0);
index c6ef3a710fd04c097895b021eed00da73ff16ff0..982d3871f9b98a14b76fe82d3c09b89635884c28 100644 (file)
@@ -3674,10 +3674,9 @@ initialise_ag_freespace(
 {
        struct xfs_alloc_arg    args;
        struct xfs_trans        *tp;
-       struct xfs_trans_res tres = {0};
        int                     c;
 
-       c = -libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp);
+       c = -libxfs_trans_alloc_rollable(mp, worst_freelist, &tp);
        if (c)
                res_failed(c);
 
index 64f7b6e862426f03ae1ccb9029d93304a667d595..85d1f4fbd179626e770e58965b5fe514993ef347 100644 (file)
@@ -2421,7 +2421,6 @@ inject_lost_blocks(
        struct xfs_trans        *tp = NULL;
        struct xfs_slab_cursor  *cur = NULL;
        xfs_fsblock_t           *fsb;
-       struct xfs_trans_res    tres = {0};
        struct xfs_owner_info   oinfo;
        int                     error;
 
@@ -2431,7 +2430,7 @@ inject_lost_blocks(
                return error;
 
        while ((fsb = pop_slab_cursor(cur)) != NULL) {
-               error = -libxfs_trans_alloc(mp, &tres, 16, 0, 0, &tp);
+               error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
                if (error)
                        goto out_cancel;
 
index eb59108b688d9a4781d88f9618b5f409b128b50f..6680db88e48116cc12ff9ee84ebb1f9bbbcd5dcd 100644 (file)
@@ -528,12 +528,12 @@ mk_rbmino(xfs_mount_t *mp)
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        int             vers;
        int             times;
-       struct xfs_trans_res tres = {0};
+       uint            blocks;
 
        /*
         * first set up inode
         */
-       i = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp);
+       i = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (i)
                res_failed(i);
 
@@ -581,9 +581,9 @@ mk_rbmino(xfs_mount_t *mp)
         * then allocate blocks for file and fill with zeroes (stolen
         * from mkfs)
         */
-       error = -libxfs_trans_alloc(mp, &tres,
-               mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1),
-                                  0, 0, &tp);
+       blocks = mp->m_sb.sb_rbmblocks +
+                       XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
+       error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
        if (error)
                res_failed(error);
 
@@ -631,12 +631,11 @@ fill_rbmino(xfs_mount_t *mp)
        int             error;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map;
-       struct xfs_trans_res tres = {0};
 
        bmp = btmcompute;
        bno = 0;
 
-       error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp);
+       error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (error)
                res_failed(error);
 
@@ -701,13 +700,12 @@ fill_rsumino(xfs_mount_t *mp)
        xfs_fileoff_t   bno;
        xfs_fileoff_t   end_bno;
        xfs_bmbt_irec_t map;
-       struct xfs_trans_res tres = {0};
 
        smp = sumcompute;
        bno = 0;
        end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
 
-       error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp);
+       error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (error)
                res_failed(error);
 
@@ -776,7 +774,7 @@ mk_rsumino(xfs_mount_t *mp)
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        int             vers;
        int             times;
-       struct xfs_trans_res tres = {0};
+       uint            blocks;
 
        /*
         * first set up inode
@@ -832,12 +830,8 @@ mk_rsumino(xfs_mount_t *mp)
        libxfs_defer_init(&dfops, &first);
 
        nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
-       tres.tr_logres = BBTOB(128);
-       tres.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
-       tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
-       error = -libxfs_trans_alloc(mp, &tres,
-               nsumblocks + (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1),
-                                   0, 0, &tp);
+       blocks = nsumblocks + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
+       error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
        if (error)
                res_failed(error);
 
index bffb5b61acf5003e4a27221b140d5244f6797b05..d9d086a7936e7f6e2cb44d8eea01eafd576e832a 100644 (file)
@@ -449,7 +449,6 @@ rmap_store_ag_btree_rec(
        struct xfs_buf          *agbp = NULL;
        struct xfs_buf          *agflbp = NULL;
        struct xfs_trans        *tp;
-       struct xfs_trans_res tres = {0};
        __be32                  *agfl_bno, *b;
        int                     error = 0;
        struct xfs_owner_info   oinfo;
@@ -507,7 +506,7 @@ rmap_store_ag_btree_rec(
        /* Insert rmaps into the btree one at a time */
        rm_rec = pop_slab_cursor(rm_cur);
        while (rm_rec) {
-               error = -libxfs_trans_alloc(mp, &tres, 16, 0, 0, &tp);
+               error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
                if (error)
                        goto err_slab;
 
@@ -1366,7 +1365,6 @@ fix_freelist(
 {
        xfs_alloc_arg_t         args;
        xfs_trans_t             *tp;
-       struct xfs_trans_res    tres = {0};
        int                     flags;
        int                     error;
 
@@ -1375,8 +1373,8 @@ fix_freelist(
        args.agno = agno;
        args.alignment = 1;
        args.pag = libxfs_perag_get(mp, agno);
-       error = -libxfs_trans_alloc(mp, &tres,
-                       libxfs_alloc_min_freelist(mp, args.pag), 0, 0, &tp);
+       error = -libxfs_trans_alloc_rollable(mp,
+                       libxfs_alloc_min_freelist(mp, args.pag), &tp);
        if (error)
                do_error(_("failed to fix AGFL on AG %d, error %d\n"),
                                agno, error);