// SPDX-License-Identifier: GPL-2.0-or-later /* FS-Cache interface to CacheFiles * * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
/* * Adjust the size of a cache file if necessary to match the DIO size. We keep * the EOF marker a multiple of DIO blocks so that we don't fall back to doing * non-DIO for a partial block straddling the EOF, but we also have to be * careful of someone expanding the file and accidentally accreting the * padding.
*/ staticint cachefiles_adjust_size(struct cachefiles_object *object)
{ struct iattr newattrs; struct file *file = object->file;
uint64_t ni_size;
loff_t oi_size; int ret;
oi_size = i_size_read(file_inode(file)); if (oi_size == ni_size) return 0;
inode_lock(file_inode(file));
/* if there's an extension to a partial page at the end of the backing * file, we need to discard the partial page so that we pick up new
* data after it */ if (oi_size & ~PAGE_MASK && ni_size > oi_size) {
_debug("discard tail %llx", oi_size);
newattrs.ia_valid = ATTR_SIZE;
newattrs.ia_size = oi_size & PAGE_MASK;
ret = cachefiles_inject_remove_error(); if (ret == 0)
ret = notify_change(&nop_mnt_idmap, file->f_path.dentry,
&newattrs, NULL); if (ret < 0) goto truncate_failed;
}
newattrs.ia_valid = ATTR_SIZE;
newattrs.ia_size = ni_size;
ret = cachefiles_inject_write_error(); if (ret == 0)
ret = notify_change(&nop_mnt_idmap, file->f_path.dentry,
&newattrs, NULL);
truncate_failed:
inode_unlock(file_inode(file));
if (ret < 0)
trace_cachefiles_io_error(NULL, file_inode(file), ret,
cachefiles_trace_notify_change_error); if (ret == -EIO) {
cachefiles_io_error_obj(object, "Size set failed");
ret = -ENOBUFS;
}
_leave(" = %d", ret); return ret;
}
/* * Attempt to look up the nominated node in this cache
*/ staticbool cachefiles_lookup_cookie(struct fscache_cookie *cookie)
{ struct cachefiles_object *object; struct cachefiles_cache *cache = cookie->volume->cache->cache_priv; conststruct cred *saved_cred; bool success;
object = cachefiles_alloc_object(cookie); if (!object) goto fail;
_enter("{OBJ%x}", object->debug_id);
if (!cachefiles_cook_key(object)) goto fail_put;
cookie->cache_priv = object;
cachefiles_begin_secure(cache, &saved_cred);
success = cachefiles_look_up_object(object); if (!success) goto fail_withdraw;
fail_withdraw:
cachefiles_end_secure(cache, saved_cred);
cachefiles_see_object(object, cachefiles_obj_see_lookup_failed);
fscache_caching_failed(cookie);
_debug("failed c=%08x o=%08x", cookie->debug_id, object->debug_id); /* The caller holds an access count on the cookie, so we need them to * drop it before we can withdraw the object.
*/ returnfalse;
/* The file is being expanded. We don't need to do anything * particularly. cookie->initial_size doesn't change and so the point * at which we have to download before doesn't change.
*/
cookie->object_size = new_size;
}
/* * Commit changes to the object as we drop it.
*/ staticvoid cachefiles_commit_object(struct cachefiles_object *object, struct cachefiles_cache *cache)
{ bool update = false;
if (test_and_clear_bit(FSCACHE_COOKIE_LOCAL_WRITE, &object->cookie->flags))
update = true; if (test_and_clear_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags))
update = true; if (update)
cachefiles_set_object_xattr(object);
if (test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags))
cachefiles_commit_tmpfile(cache, object);
}
/* * Finalise and object and close the VFS structs that we have.
*/ staticvoid cachefiles_clean_up_object(struct cachefiles_object *object, struct cachefiles_cache *cache)
{ struct file *file;
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.