// SPDX-License-Identifier: GPL-2.0-or-later /* Manage high-level VFS aspects of a cache. * * Copyright (C) 2007, 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
cache_cookie = fscache_acquire_cache(cache->tag); if (IS_ERR(cache_cookie)) return PTR_ERR(cache_cookie);
/* we want to work under the module's security ID */
ret = cachefiles_get_security_ID(cache); if (ret < 0) goto error_getsec;
cachefiles_begin_secure(cache, &saved_cred);
/* look up the directory at the root of the cache */
ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path); if (ret < 0) goto error_open_root;
cache->mnt = path.mnt;
root = path.dentry;
ret = -EINVAL; if (is_idmapped_mnt(path.mnt)) {
pr_warn("File cache on idmapped mounts not supported"); goto error_unsupported;
}
/* Check features of the backing filesystem: * - Directories must support looking up and directory creation * - We create tmpfiles to handle invalidation * - We use xattrs to store metadata * - We need to be able to query the amount of space available * - We want to be able to sync the filesystem when stopping the cache * - We use DIO to/from pages, so the blocksize mustn't be too big.
*/
ret = -EOPNOTSUPP; if (d_is_negative(root) ||
!d_backing_inode(root)->i_op->lookup ||
!d_backing_inode(root)->i_op->mkdir ||
!d_backing_inode(root)->i_op->tmpfile ||
!(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
!root->d_sb->s_op->statfs ||
!root->d_sb->s_op->sync_fs ||
root->d_sb->s_blocksize > PAGE_SIZE) goto error_unsupported;
ret = -EROFS; if (sb_rdonly(root->d_sb)) goto error_unsupported;
/* determine the security of the on-disk cache as this governs
* security ID of files we create */
ret = cachefiles_determine_cache_security(cache, root, &saved_cred); if (ret < 0) goto error_unsupported;
/* get the cache size and blocksize */
ret = vfs_statfs(&path, &stats); if (ret < 0) goto error_unsupported;
ret = -ERANGE; if (stats.f_bsize <= 0) goto error_unsupported;
ret = -EOPNOTSUPP; if (stats.f_bsize > PAGE_SIZE) goto error_unsupported;
/* get the cache directory and check its type */
cachedir = cachefiles_get_directory(cache, root, "cache", NULL); if (IS_ERR(cachedir)) {
ret = PTR_ERR(cachedir); goto error_unsupported;
}
cache->store = cachedir;
/* get the graveyard directory */
graveyard = cachefiles_get_directory(cache, root, "graveyard", NULL); if (IS_ERR(graveyard)) {
ret = PTR_ERR(graveyard); goto error_unsupported;
}
pr_info("File cache on %s registered\n", cache_cookie->name);
/* check how much space the cache has */
cachefiles_has_space(cache, 0, 0, cachefiles_has_space_check);
cachefiles_end_secure(cache, saved_cred);
_leave(" = 0 [%px]", cache->cache); return 0;
/* * See if we have space for a number of pages and/or a number of files in the * cache
*/ int cachefiles_has_space(struct cachefiles_cache *cache, unsigned fnr, unsigned bnr, enum cachefiles_has_space_for reason)
{ struct kstatfs stats;
u64 b_avail, b_writing; int ret;
stop_and_begin_cull: switch (reason) { case cachefiles_has_space_for_write:
fscache_count_no_write_space(); break; case cachefiles_has_space_for_create:
fscache_count_no_create_space(); break; default: break;
}
begin_cull: if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) {
_debug("### CULL CACHE ###");
cachefiles_state_changed(cache);
}
_leave(" = %d", ret); return ret;
}
/* * Mark all the objects as being out of service and queue them all for cleanup.
*/ staticvoid cachefiles_withdraw_objects(struct cachefiles_cache *cache)
{ struct cachefiles_object *object; unsignedint count = 0;
/* * Sync a cache to backing disk.
*/ staticvoid cachefiles_sync_cache(struct cachefiles_cache *cache)
{ conststruct cred *saved_cred; int ret;
_enter("%s", cache->cache->name);
/* make sure all pages pinned by operations on behalf of the netfs are
* written to disc */
cachefiles_begin_secure(cache, &saved_cred);
down_read(&cache->mnt->mnt_sb->s_umount);
ret = sync_filesystem(cache->mnt->mnt_sb);
up_read(&cache->mnt->mnt_sb->s_umount);
cachefiles_end_secure(cache, saved_cred);
if (ret == -EIO)
cachefiles_io_error(cache, "Attempt to sync backing fs superblock returned error %d",
ret);
}
/* we now have to destroy all the active objects pertaining to this * cache - which we do by passing them off to thread pool to be
* disposed of */
cachefiles_withdraw_objects(cache);
fscache_wait_for_objects(fscache);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.