]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: fix uncached buffer refcounting
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 26 Sep 2019 17:46:11 +0000 (13:46 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Thu, 26 Sep 2019 17:46:11 +0000 (13:46 -0400)
Currently, uncached buffers in userspace are created with zero refcount
and are fed to cache_node_put when they're released.  This is totally
broken -- the refcount should be 1 (because the caller now holds a
reference) and we should never be dumping uncached buffers into the
cache.  Fix both of these problems.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/libxfs_io.h
libxfs/libxfs_priv.h
libxfs/rdwr.c

index 0b8d977451025506c9cb5fbc921336bbd938cf9f..7dcb4bff74a673f16bafd65f18a2b63dbd814e20 100644 (file)
@@ -227,4 +227,22 @@ xfs_buf_associate_memory(struct xfs_buf *bp, void *mem, size_t len)
        return 0;
 }
 
+/*
+ * Allocate an uncached buffer that points nowhere.  The refcount will be 1,
+ * and the cache node hash list will be empty to indicate that it's uncached.
+ */
+static inline struct xfs_buf *
+xfs_buf_get_uncached(struct xfs_buftarg *targ, size_t bblen, int flags)
+{
+       struct xfs_buf  *bp;
+
+       bp = libxfs_getbufr(targ, XFS_BUF_DADDR_NULL, bblen);
+       if (!bp)
+               return NULL;
+
+       INIT_LIST_HEAD(&bp->b_node.cn_hash);
+       bp->b_node.cn_count = 1;
+       return bp;
+}
+
 #endif /* __LIBXFS_IO_H__ */
index 96d74bfa3798af97c9058b583c9e19b4ebf7b2f2..b05e082acf60a6947b49f126bef55d6efdbf4102 100644 (file)
@@ -379,8 +379,6 @@ roundup_64(uint64_t x, uint32_t y)
        (len) = __bar; /* no set-but-unused warning */  \
        NULL;                                           \
 })
-#define xfs_buf_get_uncached(t,n,f)     \
-       libxfs_getbufr((t), XFS_BUF_DADDR_NULL, (n));
 #define xfs_buf_relse(bp)              libxfs_putbuf(bp)
 #define xfs_buf_get(devp,blkno,len)    (libxfs_getbuf((devp), (blkno), (len)))
 #define xfs_bwrite(bp)                 libxfs_writebuf((bp), 0)
index 1f2c129b7be14a6fc90c49dcb8e37e5ca86813a4..3282f6de48b8454f57d569528d027f4f68af1f79 100644 (file)
@@ -867,7 +867,10 @@ libxfs_putbuf(xfs_buf_t *bp)
                }
        }
 
-       cache_node_put(libxfs_bcache, (struct cache_node *)bp);
+       if (!list_empty(&bp->b_node.cn_hash))
+               cache_node_put(libxfs_bcache, (struct cache_node *)bp);
+       else if (--bp->b_node.cn_count == 0)
+               libxfs_putbufr(bp);
 }
 
 void