// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2023-2024 Oracle. All Rights Reserved. * Author: Darrick J. Wong <[email protected]> */ #include "xfs.h" #include "xfs_fs.h" #include "xfs_buf.h" #include "xfs_buf_mem.h" #include "xfs_trace.h" #include <linux/shmem_fs.h> #include "xfs_log_format.h" #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_error.h" /* * Buffer Cache for In-Memory Files * ================================ * * Online fsck wants to create ephemeral ordered recordsets. The existing * btree infrastructure can do this, but we need the buffer cache to target * memory instead of block devices. * * When CONFIG_TMPFS=y, shmemfs is enough of a filesystem to meet those * requirements. Therefore, the xmbuf mechanism uses an unlinked shmem file to * store our staging data. This file is not installed in the file descriptor * table so that user programs cannot access the data, which means that the * xmbuf must be freed with xmbuf_destroy. * * xmbufs assume that the caller will handle all required concurrency * management; standard vfs locks (freezer and inode) are not taken. Reads * and writes are satisfied directly from the page cache. * * The only supported block size is PAGE_SIZE, and we cannot use highmem. */ /* * shmem files used to back an in-memory buffer cache must not be exposed to * userspace. Upper layers must coordinate access to the one handle returned * by the constructor, so establish a separate lock class for xmbufs to avoid * confusing lockdep. */ static struct lock_class_key xmbuf_i_mutex_key; /* * Allocate a buffer cache target for a memory-backed file and set up the * buffer target. */ int xmbuf_alloc( struct xfs_mount *mp, const char *descr, struct xfs_buftarg **btpp) { … } /* Free a buffer cache target for a memory-backed buffer cache. */ void xmbuf_free( struct xfs_buftarg *btp) { … } /* Directly map a shmem page into the buffer cache. */ int xmbuf_map_page( struct xfs_buf *bp) { … } /* Unmap a shmem page that was mapped into the buffer cache. */ void xmbuf_unmap_page( struct xfs_buf *bp) { … } /* Is this a valid daddr within the buftarg? */ bool xmbuf_verify_daddr( struct xfs_buftarg *btp, xfs_daddr_t daddr) { … } /* Discard the page backing this buffer. */ static void xmbuf_stale( struct xfs_buf *bp) { … } /* * Finalize a buffer -- discard the backing page if it's stale, or run the * write verifier to detect problems. */ int xmbuf_finalize( struct xfs_buf *bp) { … } /* * Detach this xmbuf buffer from the transaction by any means necessary. * All buffers are direct-mapped, so they do not need bwrite. */ void xmbuf_trans_bdetach( struct xfs_trans *tp, struct xfs_buf *bp) { … }