// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2018-2023 Oracle. All Rights Reserved. * Author: Darrick J. Wong <[email protected]> */ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "scrub/scrub.h" #include "scrub/xfile.h" #include "scrub/xfarray.h" #include "scrub/trace.h" #include <linux/shmem_fs.h> /* * Swappable Temporary Memory * ========================== * * Online checking sometimes needs to be able to stage a large amount of data * in memory. This information might not fit in the available memory and it * doesn't all need to be accessible at all times. In other words, we want an * indexed data buffer to store data that can be paged out. * * When CONFIG_TMPFS=y, shmemfs is enough of a filesystem to meet those * requirements. Therefore, the xfile 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 * xfile must be freed with xfile_destroy. * * xfiles 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. */ /* * xfiles must not be exposed to userspace and require upper layers to * coordinate access to the one handle returned by the constructor, so * establish a separate lock class for xfiles to avoid confusing lockdep. */ static struct lock_class_key xfile_i_mutex_key; /* * Create an xfile of the given size. The description will be used in the * trace output. */ int xfile_create( const char *description, loff_t isize, struct xfile **xfilep) { … } /* Close the file and release all resources. */ void xfile_destroy( struct xfile *xf) { … } /* * Load an object. Since we're treating this file as "memory", any error or * short IO is treated as a failure to allocate memory. */ int xfile_load( struct xfile *xf, void *buf, size_t count, loff_t pos) { … } /* * Store an object. Since we're treating this file as "memory", any error or * short IO is treated as a failure to allocate memory. */ int xfile_store( struct xfile *xf, const void *buf, size_t count, loff_t pos) { … } /* Find the next written area in the xfile data for a given offset. */ loff_t xfile_seek_data( struct xfile *xf, loff_t pos) { … } /* * Grab the (locked) folio for a memory object. The object cannot span a folio * boundary. Returns the locked folio if successful, NULL if there was no * folio or it didn't cover the range requested, or an ERR_PTR on failure. */ struct folio * xfile_get_folio( struct xfile *xf, loff_t pos, size_t len, unsigned int flags) { … } /* * Release the (locked) folio for a memory object. */ void xfile_put_folio( struct xfile *xf, struct folio *folio) { … } /* Discard the page cache that's backing a range of the xfile. */ void xfile_discard( struct xfile *xf, loff_t pos, u64 count) { … }