xfs: refactor remote attr value buffer invalidation
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 8 Jan 2020 17:08:07 +0000 (09:08 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 16 Jan 2020 16:07:23 +0000 (08:07 -0800)
Hoist the code that invalidates remote extended attribute value buffers
into a separate helper function.  This prepares us for a memory
corruption fix in the next patch.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_attr_remote.c
fs/xfs/libxfs/xfs_attr_remote.h

index a6ef5df42669921dc89a200860cbd16e9b345c38..df1ab05694817d7f4f342f4a955d511877b23148 100644 (file)
@@ -552,6 +552,33 @@ xfs_attr_rmtval_set(
        return 0;
 }
 
+/* Mark stale any incore buffers for the remote value. */
+int
+xfs_attr_rmtval_stale(
+       struct xfs_inode        *ip,
+       struct xfs_bmbt_irec    *map,
+       xfs_buf_flags_t         incore_flags)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_buf          *bp;
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+       if (XFS_IS_CORRUPT(mp, map->br_startblock == DELAYSTARTBLOCK) ||
+           XFS_IS_CORRUPT(mp, map->br_startblock == HOLESTARTBLOCK))
+               return -EFSCORRUPTED;
+
+       bp = xfs_buf_incore(mp->m_ddev_targp,
+                       XFS_FSB_TO_DADDR(mp, map->br_startblock),
+                       XFS_FSB_TO_BB(mp, map->br_blockcount), incore_flags);
+       if (bp) {
+               xfs_buf_stale(bp);
+               xfs_buf_relse(bp);
+       }
+
+       return 0;
+}
+
 /*
  * Remove the value associated with an attribute by deleting the
  * out-of-line buffer that it is stored on.
@@ -560,7 +587,6 @@ int
 xfs_attr_rmtval_remove(
        struct xfs_da_args      *args)
 {
-       struct xfs_mount        *mp = args->dp->i_mount;
        xfs_dablk_t             lblkno;
        int                     blkcnt;
        int                     error;
@@ -575,9 +601,6 @@ xfs_attr_rmtval_remove(
        blkcnt = args->rmtblkcnt;
        while (blkcnt > 0) {
                struct xfs_bmbt_irec    map;
-               struct xfs_buf          *bp;
-               xfs_daddr_t             dblkno;
-               int                     dblkcnt;
                int                     nmap;
 
                /*
@@ -588,22 +611,11 @@ xfs_attr_rmtval_remove(
                                       blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
                if (error)
                        return error;
-               ASSERT(nmap == 1);
-               ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
-                      (map.br_startblock != HOLESTARTBLOCK));
-
-               dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
-               dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
-
-               /*
-                * If the "remote" value is in the cache, remove it.
-                */
-               bp = xfs_buf_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
-               if (bp) {
-                       xfs_buf_stale(bp);
-                       xfs_buf_relse(bp);
-                       bp = NULL;
-               }
+               if (XFS_IS_CORRUPT(args->dp->i_mount, nmap != 1))
+                       return -EFSCORRUPTED;
+               error = xfs_attr_rmtval_stale(args->dp, &map, XBF_TRYLOCK);
+               if (error)
+                       return error;
 
                lblkno += map.br_blockcount;
                blkcnt -= map.br_blockcount;
index 9d20b66ad379e776e70fd420f88af77d0b69d435..6fb4572845ce8ef7482cd9890c2f71e54172929e 100644 (file)
@@ -11,5 +11,7 @@ int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
 int xfs_attr_rmtval_get(struct xfs_da_args *args);
 int xfs_attr_rmtval_set(struct xfs_da_args *args);
 int xfs_attr_rmtval_remove(struct xfs_da_args *args);
+int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map,
+               xfs_buf_flags_t incore_flags);
 
 #endif /* __XFS_ATTR_REMOTE_H__ */