kmod: force update attributes before updating atime

This commit is contained in:
Miroslav Crnic
2024-07-25 10:43:36 +01:00
committed by GitHub Enterprise
parent 575314956c
commit 4d1d24cc45
5 changed files with 22 additions and 13 deletions

View File

@@ -16,7 +16,7 @@ int eggsfs_dir_readdir_entry_cb(void* ptr, u64 name_hash, const char* name, int
void eggsfs_dir_drop_cache(struct eggsfs_inode* enode);
static inline int eggsfs_dir_revalidate(struct eggsfs_inode* enode) {
return eggsfs_do_getattr(enode, true);
return eggsfs_do_getattr(enode, ATTR_CACHE_DIR_TIMEOUT);
}
static inline int eggsfs_dir_needs_reval(struct eggsfs_inode* dir, struct dentry* dentry) {

View File

@@ -84,7 +84,7 @@ static int file_open(struct inode* inode, struct file* filp) {
// we might have cached data and another client updated atime.
// eggsfs_do_getattr is orders of magnitude cheaper than eggsfs_shard_set_time,
// so we might as well refresh and re-check
int err = eggsfs_do_getattr(enode, false);
int err = eggsfs_do_getattr(enode, ATTR_CACHE_NO_TIMEOUT);
if (err) {
inode_unlock(inode);
return err;
@@ -945,7 +945,7 @@ static ssize_t file_read_iter(struct kiocb* iocb, struct iov_iter* to) {
if (unlikely(iocb->ki_flags & IOCB_DIRECT)) { return -ENOSYS; }
// make sure we have size information
int err = eggsfs_do_getattr(enode, false);
int err = eggsfs_do_getattr(enode, ATTR_CACHE_NORM_TIMEOUT);
if (err) { return err; }
// Three-level loop:
@@ -1104,7 +1104,7 @@ char* eggsfs_read_link(struct eggsfs_inode* enode) {
BUG_ON(eggsfs_inode_type(enode->inode.i_ino) != EGGSFS_INODE_SYMLINK);
// make sure we have size information
int err = eggsfs_do_getattr(enode, false);
int err = eggsfs_do_getattr(enode, ATTR_CACHE_NORM_TIMEOUT);
if (err) { return ERR_PTR(err); }
BUG_ON(enode->inode.i_size > PAGE_SIZE); // for simplicity...
@@ -1163,7 +1163,7 @@ static loff_t file_lseek(struct file *file, loff_t offset, int whence) {
if (likely(smp_load_acquire(&enode->file.status) == EGGSFS_FILE_STATUS_READING)) {
// make sure we have size information
int err = eggsfs_do_getattr(enode, false);
int err = eggsfs_do_getattr(enode, ATTR_CACHE_NORM_TIMEOUT);
if (err) { return err; }
return generic_file_llseek(file, offset, whence);
}

View File

@@ -214,7 +214,7 @@ static void getattr_async_complete(struct work_struct* work) {
iput(&enode->inode);
}
int eggsfs_do_getattr(struct eggsfs_inode* enode, bool for_dir_revalidation) {
int eggsfs_do_getattr(struct eggsfs_inode* enode, int cache_timeout_type) {
int err;
s64 seqno;
@@ -229,11 +229,19 @@ int eggsfs_do_getattr(struct eggsfs_inode* enode, bool for_dir_revalidation) {
if (eggsfs_latch_try_acquire(&enode->getattr_update_latch, seqno)) {
u64 ts = get_jiffies_64();
if (for_dir_revalidation) {
switch (cache_timeout_type) {
case ATTR_CACHE_NORM_TIMEOUT:
if (smp_load_acquire(&enode->getattr_expiry) > ts) { err = 0; goto out; }
break;
case ATTR_CACHE_DIR_TIMEOUT:
BUG_ON(!S_ISDIR(enode->inode.i_mode));
if (smp_load_acquire(&enode->dir.mtime_expiry) > ts) { err = 0; goto out; }
} else {
if (smp_load_acquire(&enode->getattr_expiry) > ts) { err = 0; goto out; }
break;
case ATTR_CACHE_NO_TIMEOUT:
break;
default:
eggsfs_error("unknown cache timeout type %d", cache_timeout_type);
BUG();
}
u64 mtime;
@@ -271,7 +279,7 @@ int eggsfs_do_getattr(struct eggsfs_inode* enode, bool for_dir_revalidation) {
eggsfs_debug("updating getattr for reading file");
u64 size;
err = eggsfs_shard_getattr_file(
(struct eggsfs_fs_info*)enode->inode.i_sb->s_fs_info,
(struct eggsfs_fs_info*)enode->inode.i_sb->s_fs_info,
enode->inode.i_ino,
&mtime,
&atime,
@@ -416,7 +424,7 @@ static int eggsfs_getattr(const struct path* path, struct kstat* stat, u32 reque
// dentry refcount also protects the inode (e.g. d_delete will not turn used dentry into a negative one),
// so no need to grab anything before we start waiting for stuff
err = eggsfs_do_getattr(enode, false);
err = eggsfs_do_getattr(enode, ATTR_CACHE_NORM_TIMEOUT);
if (err) {
trace_eggsfs_vfs_getattr_exit(inode, err);
return err;

View File

@@ -222,7 +222,8 @@ void eggsfs_inode_evict(struct inode* inode);
void eggsfs_inode_free(struct inode* inode);
// inode ops
int eggsfs_do_getattr(struct eggsfs_inode* enode, bool for_dir_revalidation);
enum { ATTR_CACHE_NORM_TIMEOUT, ATTR_CACHE_DIR_TIMEOUT, ATTR_CACHE_NO_TIMEOUT };
int eggsfs_do_getattr(struct eggsfs_inode* enode, int cache_timeout_type);
// 0: not started
// 1: started
// -n: error

View File

@@ -580,7 +580,7 @@ static struct dentry* eggsfs_mount(struct file_system_type* fs_type, int flags,
struct eggsfs_inode* root_enode = EGGSFS_I(root);
err = eggsfs_do_getattr(root_enode, false);
err = eggsfs_do_getattr(root_enode, ATTR_CACHE_NORM_TIMEOUT);
if (err) { goto out_sb; }
if (!root_enode->block_policy || !root_enode->span_policy || !root_enode->stripe_policy) {