Skip to content

Commit 2f1e819

Browse files
author
Miklos Szeredi
committed
fuse: allow fine grained attr cache invaldation
This patch adds the infrastructure for more fine grained attribute invalidation. Currently only 'atime' is invalidated separately. The use of this infrastructure is extended to the statx(2) interface, which for now means that if only 'atime' is invalid and STATX_ATIME is not specified in the mask argument, then no GETATTR request will be generated. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent edfa872 commit 2f1e819

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

fs/fuse/dir.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,18 @@ u64 entry_attr_timeout(struct fuse_entry_out *o)
8181
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
8282
}
8383

84+
static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
85+
{
86+
set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
87+
}
88+
8489
/*
8590
* Mark the attributes as stale, so that at the next call to
8691
* ->getattr() they will be fetched from userspace
8792
*/
8893
void fuse_invalidate_attr(struct inode *inode)
8994
{
90-
get_fuse_inode(inode)->i_time = 0;
95+
fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
9196
}
9297

9398
static void fuse_dir_changed(struct inode *dir)
@@ -103,7 +108,7 @@ static void fuse_dir_changed(struct inode *dir)
103108
void fuse_invalidate_atime(struct inode *inode)
104109
{
105110
if (!IS_RDONLY(inode))
106-
fuse_invalidate_attr(inode);
111+
fuse_invalidate_attr_mask(inode, STATX_ATIME);
107112
}
108113

109114
/*
@@ -917,7 +922,8 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
917922
}
918923

919924
static int fuse_update_get_attr(struct inode *inode, struct file *file,
920-
struct kstat *stat, unsigned int flags)
925+
struct kstat *stat, u32 request_mask,
926+
unsigned int flags)
921927
{
922928
struct fuse_inode *fi = get_fuse_inode(inode);
923929
int err = 0;
@@ -927,6 +933,8 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
927933
sync = true;
928934
else if (flags & AT_STATX_DONT_SYNC)
929935
sync = false;
936+
else if (request_mask & READ_ONCE(fi->inval_mask))
937+
sync = true;
930938
else
931939
sync = time_before64(fi->i_time, get_jiffies_64());
932940

@@ -944,7 +952,7 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
944952

945953
int fuse_update_attributes(struct inode *inode, struct file *file)
946954
{
947-
return fuse_update_get_attr(inode, file, NULL, 0);
955+
return fuse_update_get_attr(inode, file, NULL, STATX_BASIC_STATS, 0);
948956
}
949957

950958
int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
@@ -1566,7 +1574,7 @@ static int fuse_getattr(const struct path *path, struct kstat *stat,
15661574
if (!fuse_allow_current_process(fc))
15671575
return -EACCES;
15681576

1569-
return fuse_update_get_attr(inode, NULL, stat, flags);
1577+
return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
15701578
}
15711579

15721580
static const struct inode_operations fuse_dir_inode_operations = {

fs/fuse/fuse_i.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ struct fuse_inode {
8080
/** Time in jiffies until the file attributes are valid */
8181
u64 i_time;
8282

83+
/* Which attributes are invalid */
84+
u32 inval_mask;
85+
8386
/** The sticky bit in inode->i_mode may have been removed, so
8487
preserve the original mode */
8588
umode_t orig_i_mode;

fs/fuse/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
9090

9191
fi = get_fuse_inode(inode);
9292
fi->i_time = 0;
93+
fi->inval_mask = 0;
9394
fi->nodeid = 0;
9495
fi->nlookup = 0;
9596
fi->attr_version = 0;
@@ -164,6 +165,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
164165

165166
fi->attr_version = ++fc->attr_version;
166167
fi->i_time = attr_valid;
168+
WRITE_ONCE(fi->inval_mask, 0);
167169

168170
inode->i_ino = fuse_squash_ino(attr->ino);
169171
inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);

0 commit comments

Comments
 (0)