]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: automatic dfops inode relogging
authorBrian Foster <bfoster@redhat.com>
Fri, 5 Oct 2018 02:36:12 +0000 (21:36 -0500)
committerEric Sandeen <sandeen@redhat.com>
Fri, 5 Oct 2018 02:36:12 +0000 (21:36 -0500)
Source kernel commit: a8198666fb755e129c2fe92819774256ec26c79c

Inodes that are held across deferred operations are explicitly
joined to the dfops structure to ensure appropriate relogging.
While inodes are currently joined explicitly, we can detect the
conditions that require relogging at dfops finish time by inspecting
the transaction item list for inodes with ili_lock_flags == 0.

Replace the xfs_defer_ijoin() infrastructure with such detection and
automatic relogging of held inodes. This eliminates the need for the
per-dfops inode list, replaced by an on-stack variant in
xfs_defer_trans_roll().

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/xfs_trans.h
libxfs/libxfs_api_defs.h
libxfs/trans.c
libxfs/xfs_attr.c
libxfs/xfs_attr_remote.c
libxfs/xfs_bmap.c
libxfs/xfs_defer.c
libxfs/xfs_defer.h
mkfs/proto.c
repair/phase6.c

index a967a7ffb9705441ef2ee5cec3bfa87812bba812..a444b8717b6fdc01202d16bbe03cfce0762fe8a5 100644 (file)
@@ -30,6 +30,7 @@ typedef struct xfs_inode_log_item {
        xfs_log_item_t          ili_item;               /* common portion */
        struct xfs_inode        *ili_inode;             /* inode pointer */
        unsigned short          ili_flags;              /* misc flags */
+       unsigned short          ili_lock_flags;         /* lock flags */
        unsigned int            ili_fields;             /* fields to be logged */
        unsigned int            ili_last_fields;        /* fields when flushed*/
 } xfs_inode_log_item_t;
@@ -66,9 +67,6 @@ typedef struct xfs_qoff_logitem {
 struct xfs_defer_ops {
        struct list_head                dop_intake;     /* unlogged pending work */
        struct list_head                dop_pending;    /* logged pending work */
-
-       /* relog these with each roll */
-       struct xfs_inode                *dop_inodes[XFS_DEFER_OPS_NR_INODES];
 };
 
 typedef struct xfs_trans {
index 47e21d2030a35a1d9c3648019ea69c8884ba9e14..a2251968582e69e25c2be397d4d49292441930ed 100644 (file)
@@ -69,7 +69,6 @@
 #define xfs_zero_extent                        libxfs_zero_extent
 
 #define xfs_defer_init                 libxfs_defer_init
-#define xfs_defer_ijoin                        libxfs_defer_ijoin
 #define xfs_defer_finish               libxfs_defer_finish
 #define xfs_defer_cancel               libxfs_defer_cancel
 
index b58d08b5747a2ac332e62bd77bc9d48e292bd1ef..f476d14f2e88067d0c933a7312520a7af0410ad8 100644 (file)
@@ -390,6 +390,9 @@ libxfs_trans_ijoin(
        ASSERT(iip->ili_flags == 0);
        ASSERT(iip->ili_inode != NULL);
 
+       ASSERT(iip->ili_lock_flags == 0);
+       iip->ili_lock_flags = lock_flags;
+
        xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
 
        ip->i_transp = tp;
index b63f385e5f1f60a580974e6c9a443bfb85a7bdc8..0e20d56147676d211167227f11c03eaaf2feb169 100644 (file)
@@ -315,7 +315,6 @@ xfs_attr_set(
                 * buffer and run into problems with the write verifier.
                 */
                xfs_trans_bhold(args.trans, leaf_bp);
-               xfs_defer_ijoin(args.trans->t_dfops, dp);
                error = xfs_defer_finish(&args.trans);
                if (error)
                        goto out;
@@ -584,7 +583,6 @@ xfs_attr_leaf_addname(
                error = xfs_attr3_leaf_to_node(args);
                if (error)
                        goto out_defer_cancel;
-               xfs_defer_ijoin(args->trans->t_dfops, dp);
                error = xfs_defer_finish(&args->trans);
                if (error)
                        goto out_defer_cancel;
@@ -673,7 +671,6 @@ xfs_attr_leaf_addname(
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (error)
                                goto out_defer_cancel;
-                       xfs_defer_ijoin(args->trans->t_dfops, dp);
                        error = xfs_defer_finish(&args->trans);
                        if (error)
                                goto out_defer_cancel;
@@ -737,7 +734,6 @@ xfs_attr_leaf_removename(
                /* bp is gone due to xfs_da_shrink_inode */
                if (error)
                        goto out_defer_cancel;
-               xfs_defer_ijoin(args->trans->t_dfops, dp);
                error = xfs_defer_finish(&args->trans);
                if (error)
                        goto out_defer_cancel;
@@ -864,7 +860,6 @@ restart:
                        error = xfs_attr3_leaf_to_node(args);
                        if (error)
                                goto out_defer_cancel;
-                       xfs_defer_ijoin(args->trans->t_dfops, dp);
                        error = xfs_defer_finish(&args->trans);
                        if (error)
                                goto out_defer_cancel;
@@ -889,7 +884,6 @@ restart:
                error = xfs_da3_split(state);
                if (error)
                        goto out_defer_cancel;
-               xfs_defer_ijoin(args->trans->t_dfops, dp);
                error = xfs_defer_finish(&args->trans);
                if (error)
                        goto out_defer_cancel;
@@ -986,7 +980,6 @@ restart:
                        error = xfs_da3_join(state);
                        if (error)
                                goto out_defer_cancel;
-                       xfs_defer_ijoin(args->trans->t_dfops, dp);
                        error = xfs_defer_finish(&args->trans);
                        if (error)
                                goto out_defer_cancel;
@@ -1110,7 +1103,6 @@ xfs_attr_node_removename(
                error = xfs_da3_join(state);
                if (error)
                        goto out_defer_cancel;
-               xfs_defer_ijoin(args->trans->t_dfops, dp);
                error = xfs_defer_finish(&args->trans);
                if (error)
                        goto out_defer_cancel;
@@ -1142,7 +1134,6 @@ xfs_attr_node_removename(
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (error)
                                goto out_defer_cancel;
-                       xfs_defer_ijoin(args->trans->t_dfops, dp);
                        error = xfs_defer_finish(&args->trans);
                        if (error)
                                goto out_defer_cancel;
index 2c03d4dbcd6157edbf8eb6b40d714e9c0de88c55..faebeed4e5944ebcd491a956a7ce39fa1861e815 100644 (file)
@@ -481,7 +481,6 @@ xfs_attr_rmtval_set(
                                  &nmap);
                if (error)
                        goto out_defer_cancel;
-               xfs_defer_ijoin(args->trans->t_dfops, dp);
                error = xfs_defer_finish(&args->trans);
                if (error)
                        goto out_defer_cancel;
@@ -622,7 +621,6 @@ xfs_attr_rmtval_remove(
                                    XFS_BMAPI_ATTRFORK, 1, &done);
                if (error)
                        goto out_defer_cancel;
-               xfs_defer_ijoin(args->trans->t_dfops, args->dp);
                error = xfs_defer_finish(&args->trans);
                if (error)
                        goto out_defer_cancel;
index d9b790e621c0d0a11db6ba701811b0ed85b38dd3..65da6248ebffceff7f1d7fbb29e57a988a5706be 100644 (file)
@@ -1110,7 +1110,6 @@ xfs_bmap_add_attrfork(
                        xfs_log_sb(tp);
        }
 
-       xfs_defer_ijoin(tp->t_dfops, ip);
        error = xfs_trans_commit(tp);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        return error;
@@ -5978,7 +5977,6 @@ __xfs_bmap_add(
        int                             whichfork,
        struct xfs_bmbt_irec            *bmap)
 {
-       int                             error;
        struct xfs_bmap_intent          *bi;
 
        trace_xfs_bmap_defer(mp,
@@ -5997,12 +5995,6 @@ __xfs_bmap_add(
        bi->bi_whichfork = whichfork;
        bi->bi_bmap = *bmap;
 
-       error = xfs_defer_ijoin(dfops, bi->bi_owner);
-       if (error) {
-               kmem_free(bi);
-               return error;
-       }
-
        xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
        return 0;
 }
index 942bfa93070de734f60238759e45752a3ba804d5..a73b0798f742678cccbff4f362ef6fd0f3bab479 100644 (file)
@@ -14,6 +14,7 @@
 #include "xfs_mount.h"
 #include "xfs_defer.h"
 #include "xfs_trans.h"
+#include "xfs_inode.h"
 #include "xfs_trace.h"
 
 /*
@@ -229,16 +230,14 @@ xfs_defer_trans_roll(
 {
        struct xfs_defer_ops            *dop = (*tp)->t_dfops;
        struct xfs_buf_log_item         *bli;
+       struct xfs_inode_log_item       *ili;
        struct xfs_log_item             *lip;
        struct xfs_buf                  *bplist[XFS_DEFER_OPS_NR_BUFS];
-       int                             bpcount = 0;
+       struct xfs_inode                *iplist[XFS_DEFER_OPS_NR_INODES];
+       int                             bpcount = 0, ipcount = 0;
        int                             i;
        int                             error;
 
-       /* Log all the joined inodes. */
-       for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
-               xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
-
        list_for_each_entry(lip, &(*tp)->t_items, li_trans) {
                switch (lip->li_type) {
                case XFS_LI_BUF:
@@ -253,6 +252,19 @@ xfs_defer_trans_roll(
                                bplist[bpcount++] = bli->bli_buf;
                        }
                        break;
+               case XFS_LI_INODE:
+                       ili = container_of(lip, struct xfs_inode_log_item,
+                                          ili_item);
+                       if (ili->ili_lock_flags == 0) {
+                               if (ipcount >= XFS_DEFER_OPS_NR_INODES) {
+                                       ASSERT(0);
+                                       return -EFSCORRUPTED;
+                               }
+                               xfs_trans_log_inode(*tp, ili->ili_inode,
+                                                   XFS_ILOG_CORE);
+                               iplist[ipcount++] = ili->ili_inode;
+                       }
+                       break;
                default:
                        break;
                }
@@ -270,8 +282,8 @@ xfs_defer_trans_roll(
        }
 
        /* Rejoin the joined inodes. */
-       for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
-               xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
+       for (i = 0; i < ipcount; i++)
+               xfs_trans_ijoin(*tp, iplist[i], 0);
 
        /* Rejoin the buffers and dirty them so the log moves forward. */
        for (i = 0; i < bpcount; i++) {
@@ -290,30 +302,6 @@ xfs_defer_has_unfinished_work(
        return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake);
 }
 
-/*
- * Add this inode to the deferred op.  Each joined inode is relogged
- * each time we roll the transaction.
- */
-int
-xfs_defer_ijoin(
-       struct xfs_defer_ops            *dop,
-       struct xfs_inode                *ip)
-{
-       int                             i;
-
-       for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) {
-               if (dop->dop_inodes[i] == ip)
-                       return 0;
-               else if (dop->dop_inodes[i] == NULL) {
-                       dop->dop_inodes[i] = ip;
-                       return 0;
-               }
-       }
-
-       ASSERT(0);
-       return -EFSCORRUPTED;
-}
-
 /*
  * Reset an already used dfops after finish.
  */
@@ -321,11 +309,7 @@ static void
 xfs_defer_reset(
        struct xfs_trans        *tp)
 {
-       struct xfs_defer_ops    *dop = tp->t_dfops;
-
-       ASSERT(!xfs_defer_has_unfinished_work(dop));
-
-       memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
+       ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops));
 
        /*
         * Low mode state transfers across transaction rolls to mirror dfops
@@ -587,8 +571,6 @@ xfs_defer_move(
        list_splice_init(&src->dop_intake, &dst->dop_intake);
        list_splice_init(&src->dop_pending, &dst->dop_pending);
 
-       memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
-
        /*
         * Low free space mode was historically controlled by a dfops field.
         * This meant that low mode state potentially carried across multiple
index 4a8bb838adf233b4c2c5979b5831a12369b0a31c..bf1e9f78561e0741d00f266959b202006bb4a745 100644 (file)
@@ -42,7 +42,6 @@ int xfs_defer_finish(struct xfs_trans **tp);
 void xfs_defer_cancel(struct xfs_trans *);
 void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
 bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
-int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
 void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
 
 /* Description of a deferred type. */
index 3d59fbfb377bbb907ecab08013aa73a0342c219d..50a1bc54f6ca66aa80c1b2469daf825c3b730d08 100644 (file)
@@ -351,7 +351,6 @@ parseproto(
        char            *buf;
        int             error;
        int             flags;
-       struct xfs_defer_ops    dfops;
        int             fmt;
        int             i;
        xfs_inode_t     *ip;
@@ -474,8 +473,6 @@ parseproto(
                xname.type = XFS_DIR3_FT_REG_FILE;
                newdirent(mp, tp, pip, &xname, ip->i_ino);
                libxfs_trans_log_inode(tp, ip, flags);
-
-               libxfs_defer_ijoin(&dfops, ip);
                libxfs_trans_commit(tp);
                rsvfile(mp, ip, llen);
                IRELE(ip);
@@ -554,7 +551,6 @@ parseproto(
                }
                newdirectory(mp, tp, ip, pip);
                libxfs_trans_log_inode(tp, ip, flags);
-               libxfs_defer_ijoin(&dfops, ip);
                libxfs_trans_commit(tp);
                /*
                 * RT initialization.  Do this here to ensure that
@@ -578,7 +574,6 @@ parseproto(
                fail(_("Unknown format"), EINVAL);
        }
        libxfs_trans_log_inode(tp, ip, flags);
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
        IRELE(ip);
 }
@@ -603,7 +598,6 @@ rtinit(
        xfs_fileoff_t   ebno;
        xfs_bmbt_irec_t *ep;
        int             error;
-       struct xfs_defer_ops    dfops;
        int             i;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        xfs_extlen_t    nsumblocks;
@@ -680,7 +674,6 @@ rtinit(
                }
        }
 
-       libxfs_defer_ijoin(&dfops, rbmip);
        libxfs_trans_commit(tp);
 
        /*
@@ -709,7 +702,6 @@ rtinit(
                        bno += ep->br_blockcount;
                }
        }
-       libxfs_defer_ijoin(&dfops, rsumip);
        libxfs_trans_commit(tp);
 
        /*
@@ -729,7 +721,6 @@ rtinit(
                        fail(_("Error initializing the realtime space"),
                                error);
                }
-               libxfs_defer_ijoin(&dfops, rbmip);
                libxfs_trans_commit(tp);
        }
 }
index ff5110427d7d51ef26c8bd8d799bd7c55c5ad745..d6cb0a5aba344aaeb84e01b2396fe143d3ada5c3 100644 (file)
@@ -522,7 +522,6 @@ mk_rbmino(xfs_mount_t *mp)
        int             i;
        int             nmap;
        int             error;
-       struct xfs_defer_ops    dfops;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        int             vers;
@@ -605,7 +604,6 @@ mk_rbmino(xfs_mount_t *mp)
                        bno += ep->br_blockcount;
                }
        }
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
        IRELE(ip);
 }
@@ -753,7 +751,6 @@ mk_rsumino(xfs_mount_t *mp)
        int             nmap;
        int             error;
        int             nsumblocks;
-       struct xfs_defer_ops    dfops;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        int             vers;
@@ -836,7 +833,6 @@ mk_rsumino(xfs_mount_t *mp)
                        bno += ep->br_blockcount;
                }
        }
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
        IRELE(ip);
 }
@@ -925,7 +921,6 @@ mk_orphanage(xfs_mount_t *mp)
        int             ino_offset = 0;
        int             i;
        int             error;
-       struct xfs_defer_ops    dfops;
        const int       mode = 0755;
        int             nres;
        struct xfs_name xname;
@@ -1033,8 +1028,6 @@ mk_orphanage(xfs_mount_t *mp)
        libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
        libxfs_dir_init(tp, ip, pip);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
        IRELE(ip);
        IRELE(pip);
@@ -1056,7 +1049,6 @@ mv_orphanage(
        xfs_ino_t               entry_ino_num;
        xfs_inode_t             *ino_p;
        xfs_trans_t             *tp;
-       struct xfs_defer_ops    dfops;
        int                     err;
        unsigned char           fname[MAXPATHLEN + 1];
        int                     nres;
@@ -1134,8 +1126,6 @@ mv_orphanage(
 
                        inc_nlink(VFS_I(ino_p));
                        libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
-
-                       libxfs_defer_ijoin(&dfops, ino_p);
                        libxfs_trans_commit(tp);
                } else  {
                        err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename,
@@ -1176,7 +1166,6 @@ mv_orphanage(
                                                err);
                        }
 
-                       libxfs_defer_ijoin(&dfops, ino_p);
                        libxfs_trans_commit(tp);
                }
 
@@ -1208,8 +1197,6 @@ mv_orphanage(
 
                set_nlink(VFS_I(ino_p), 1);
                libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
-
-               libxfs_defer_ijoin(&dfops, ino_p);
                libxfs_trans_commit(tp);
        }
        IRELE(ino_p);
@@ -1294,7 +1281,6 @@ longform_dir2_rebuild(
        int                     nres;
        xfs_trans_t             *tp;
        xfs_fileoff_t           lastblock;
-       struct xfs_defer_ops            dfops;
        xfs_inode_t             pip;
        dir_hash_ent_t          *p;
        int                     done;
@@ -1347,7 +1333,6 @@ longform_dir2_rebuild(
                goto out_bmap_cancel;
        }
 
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
 
        if (ino == mp->m_sb.sb_rootino)
@@ -1379,7 +1364,6 @@ _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"
                        goto out_bmap_cancel;
                }
 
-               libxfs_defer_ijoin(&dfops, ip);
                libxfs_trans_commit(tp);
        }
 
@@ -1404,7 +1388,6 @@ dir2_kill_block(
 {
        xfs_da_args_t   args;
        int             error;
-       struct xfs_defer_ops    dfops;
        int             nres;
        xfs_trans_t     *tp;
 
@@ -1427,7 +1410,6 @@ dir2_kill_block(
        if (error)
                do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"),
                        ip->i_ino, da_bno);
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
 }
 
@@ -1460,7 +1442,6 @@ longform_dir2_entry_check_data(
        struct xfs_dir2_data_free *bf;
        char                    *endptr;
        int                     error;
-       struct xfs_defer_ops            dfops;
        char                    fname[MAXNAMELEN + 1];
        freetab_t               *freetab;
        int                     i;
@@ -1902,7 +1883,6 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 "
                                d, &i);
        if (needlog)
                libxfs_dir2_data_log_header(&da, bp);
-       libxfs_defer_ijoin(&dfops, ip);
        libxfs_trans_commit(tp);
 
        /* record the largest free space in the freetab for later checking */
@@ -2818,7 +2798,6 @@ process_dir_inode(
        int                     ino_offset)
 {
        xfs_ino_t               ino;
-       struct xfs_defer_ops            dfops;
        xfs_inode_t             *ip;
        xfs_trans_t             *tp;
        dir_hash_tab_t          *hashtab;
@@ -2961,8 +2940,6 @@ process_dir_inode(
        _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
 
                libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-               libxfs_defer_ijoin(&dfops, ip);
                libxfs_trans_commit(tp);
 
                need_root_dotdot = 0;
@@ -3016,8 +2993,6 @@ process_dir_inode(
                                        ino, error);
 
                        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-                       libxfs_defer_ijoin(&dfops, ip);
                        libxfs_trans_commit(tp);
                }
        }