aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2018-03-08 20:35:22 -0600
committerEric Sandeen <sandeen@redhat.com>2018-03-08 20:35:22 -0600
commit864028ed3ae482212b41f83d85b2be42aedb3aac (patch)
tree6bd3ccf583b2155ac9ea3cfca2c4ab86235f99fd
parentfc9f709f5beeb2b89136662013fc0bb65828ca8f (diff)
downloadxfsprogs-dev-864028ed3ae482212b41f83d85b2be42aedb3aac.tar.gz
libxfs: add function to free all buffers in bcache
libxfs_bcache_purge simply moves all "free" buffers onto the xfs_buf_freelist mru list; add a new function to actually free them when we tear everything down, so leak checkers don't go nuts about lots of unfreed xfs_bufs at exit. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--libxfs/init.c5
-rw-r--r--libxfs/libxfs_io.h1
-rw-r--r--libxfs/rdwr.c18
3 files changed, 23 insertions, 1 deletions
diff --git a/libxfs/init.c b/libxfs/init.c
index 7bde8b739e..c7d73b6685 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -888,8 +888,11 @@ libxfs_umount(xfs_mount_t *mp)
void
libxfs_destroy(void)
{
- manage_zones(1);
+ /* Free everything from the buffer cache before freeing buffer zone */
+ libxfs_bcache_purge();
+ libxfs_bcache_free();
cache_destroy(libxfs_bcache);
+ manage_zones(1);
}
int
diff --git a/libxfs/libxfs_io.h b/libxfs/libxfs_io.h
index 78b67802b1..6de6fcb5d9 100644
--- a/libxfs/libxfs_io.h
+++ b/libxfs/libxfs_io.h
@@ -188,6 +188,7 @@ extern void libxfs_readbuf_verify(struct xfs_buf *bp,
const struct xfs_buf_ops *ops);
extern xfs_buf_t *libxfs_getsb(struct xfs_mount *, int);
extern void libxfs_bcache_purge(void);
+extern void libxfs_bcache_free(void);
extern void libxfs_bcache_flush(void);
extern void libxfs_purgebuf(xfs_buf_t *);
extern int libxfs_bcache_overflowed(void);
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 3c5def2950..81701b752c 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -1275,6 +1275,24 @@ libxfs_bulkrelse(
}
/*
+ * Free everything from the xfs_buf_freelist MRU, used at final teardown
+ */
+void
+libxfs_bcache_free(void)
+{
+ struct list_head *cm_list;
+ xfs_buf_t *bp, *next;
+
+ cm_list = &xfs_buf_freelist.cm_list;
+ list_for_each_entry_safe(bp, next, cm_list, b_node.cn_mru) {
+ free(bp->b_addr);
+ if (bp->b_maps != &bp->__b_map)
+ free(bp->b_maps);
+ kmem_zone_free(xfs_buf_zone, bp);
+ }
+}
+
+/*
* When a buffer is marked dirty, the error is cleared. Hence if we are trying
* to flush a buffer prior to cache reclaim that has an error on it it means
* we've already tried to flush it and it failed. Prevent repeated corruption