Skip to content

Commit 4b52f05

Browse files
author
Miklos Szeredi
committed
fuse: add cache_mask
If writeback_cache is enabled, then the size, mtime and ctime attributes of regular files are always valid in the kernel's cache. They are retrieved from userspace only when the inode is freshly looked up. Add a more generic "cache_mask", that indicates which attributes are currently valid in cache. This patch doesn't change behavior. Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 04d82db commit 4b52f05

File tree

3 files changed

+29
-9
lines changed

3 files changed

+29
-9
lines changed

fs/fuse/dir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1667,7 +1667,8 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
16671667
}
16681668

16691669
fuse_change_attributes_common(inode, &outarg.attr,
1670-
attr_timeout(&outarg));
1670+
attr_timeout(&outarg),
1671+
fuse_get_cache_mask(inode));
16711672
oldsize = inode->i_size;
16721673
/* see the comment in fuse_change_attributes() */
16731674
if (!is_wb || is_truncate)

fs/fuse/fuse_i.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,9 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
10311031
u64 attr_valid, u64 attr_version);
10321032

10331033
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
1034-
u64 attr_valid);
1034+
u64 attr_valid, u32 cache_mask);
1035+
1036+
u32 fuse_get_cache_mask(struct inode *inode);
10351037

10361038
/**
10371039
* Initialize the client device

fs/fuse/inode.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ static ino_t fuse_squash_ino(u64 ino64)
164164
}
165165

166166
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
167-
u64 attr_valid)
167+
u64 attr_valid, u32 cache_mask)
168168
{
169169
struct fuse_conn *fc = get_fuse_conn(inode);
170170
struct fuse_inode *fi = get_fuse_inode(inode);
@@ -184,9 +184,11 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
184184
inode->i_atime.tv_sec = attr->atime;
185185
inode->i_atime.tv_nsec = attr->atimensec;
186186
/* mtime from server may be stale due to local buffered write */
187-
if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) {
187+
if (!(cache_mask & STATX_MTIME)) {
188188
inode->i_mtime.tv_sec = attr->mtime;
189189
inode->i_mtime.tv_nsec = attr->mtimensec;
190+
}
191+
if (!(cache_mask & STATX_CTIME)) {
190192
inode->i_ctime.tv_sec = attr->ctime;
191193
inode->i_ctime.tv_nsec = attr->ctimensec;
192194
}
@@ -218,12 +220,22 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
218220
inode->i_flags &= ~S_NOSEC;
219221
}
220222

223+
u32 fuse_get_cache_mask(struct inode *inode)
224+
{
225+
struct fuse_conn *fc = get_fuse_conn(inode);
226+
227+
if (!fc->writeback_cache || !S_ISREG(inode->i_mode))
228+
return 0;
229+
230+
return STATX_MTIME | STATX_CTIME | STATX_SIZE;
231+
}
232+
221233
void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
222234
u64 attr_valid, u64 attr_version)
223235
{
224236
struct fuse_conn *fc = get_fuse_conn(inode);
225237
struct fuse_inode *fi = get_fuse_inode(inode);
226-
bool is_wb = fc->writeback_cache && S_ISREG(inode->i_mode);
238+
u32 cache_mask;
227239
loff_t oldsize;
228240
struct timespec64 old_mtime;
229241

@@ -233,10 +245,15 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
233245
* may update i_size. In these cases trust the cached value in the
234246
* inode.
235247
*/
236-
if (is_wb) {
248+
cache_mask = fuse_get_cache_mask(inode);
249+
if (cache_mask & STATX_SIZE)
237250
attr->size = i_size_read(inode);
251+
252+
if (cache_mask & STATX_MTIME) {
238253
attr->mtime = inode->i_mtime.tv_sec;
239254
attr->mtimensec = inode->i_mtime.tv_nsec;
255+
}
256+
if (cache_mask & STATX_CTIME) {
240257
attr->ctime = inode->i_ctime.tv_sec;
241258
attr->ctimensec = inode->i_ctime.tv_nsec;
242259
}
@@ -248,19 +265,19 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
248265
}
249266

250267
old_mtime = inode->i_mtime;
251-
fuse_change_attributes_common(inode, attr, attr_valid);
268+
fuse_change_attributes_common(inode, attr, attr_valid, cache_mask);
252269

253270
oldsize = inode->i_size;
254271
/*
255272
* In case of writeback_cache enabled, the cached writes beyond EOF
256273
* extend local i_size without keeping userspace server in sync. So,
257274
* attr->size coming from server can be stale. We cannot trust it.
258275
*/
259-
if (!is_wb)
276+
if (!(cache_mask & STATX_SIZE))
260277
i_size_write(inode, attr->size);
261278
spin_unlock(&fi->lock);
262279

263-
if (!is_wb && S_ISREG(inode->i_mode)) {
280+
if (!cache_mask && S_ISREG(inode->i_mode)) {
264281
bool inval = false;
265282

266283
if (oldsize != attr->size) {

0 commit comments

Comments
 (0)