@@ -164,7 +164,7 @@ static ino_t fuse_squash_ino(u64 ino64)
164
164
}
165
165
166
166
void fuse_change_attributes_common (struct inode * inode , struct fuse_attr * attr ,
167
- u64 attr_valid )
167
+ u64 attr_valid , u32 cache_mask )
168
168
{
169
169
struct fuse_conn * fc = get_fuse_conn (inode );
170
170
struct fuse_inode * fi = get_fuse_inode (inode );
@@ -184,9 +184,11 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
184
184
inode -> i_atime .tv_sec = attr -> atime ;
185
185
inode -> i_atime .tv_nsec = attr -> atimensec ;
186
186
/* 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 )) {
188
188
inode -> i_mtime .tv_sec = attr -> mtime ;
189
189
inode -> i_mtime .tv_nsec = attr -> mtimensec ;
190
+ }
191
+ if (!(cache_mask & STATX_CTIME )) {
190
192
inode -> i_ctime .tv_sec = attr -> ctime ;
191
193
inode -> i_ctime .tv_nsec = attr -> ctimensec ;
192
194
}
@@ -218,12 +220,22 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
218
220
inode -> i_flags &= ~S_NOSEC ;
219
221
}
220
222
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
+
221
233
void fuse_change_attributes (struct inode * inode , struct fuse_attr * attr ,
222
234
u64 attr_valid , u64 attr_version )
223
235
{
224
236
struct fuse_conn * fc = get_fuse_conn (inode );
225
237
struct fuse_inode * fi = get_fuse_inode (inode );
226
- bool is_wb = fc -> writeback_cache && S_ISREG ( inode -> i_mode ) ;
238
+ u32 cache_mask ;
227
239
loff_t oldsize ;
228
240
struct timespec64 old_mtime ;
229
241
@@ -233,10 +245,15 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
233
245
* may update i_size. In these cases trust the cached value in the
234
246
* inode.
235
247
*/
236
- if (is_wb ) {
248
+ cache_mask = fuse_get_cache_mask (inode );
249
+ if (cache_mask & STATX_SIZE )
237
250
attr -> size = i_size_read (inode );
251
+
252
+ if (cache_mask & STATX_MTIME ) {
238
253
attr -> mtime = inode -> i_mtime .tv_sec ;
239
254
attr -> mtimensec = inode -> i_mtime .tv_nsec ;
255
+ }
256
+ if (cache_mask & STATX_CTIME ) {
240
257
attr -> ctime = inode -> i_ctime .tv_sec ;
241
258
attr -> ctimensec = inode -> i_ctime .tv_nsec ;
242
259
}
@@ -248,19 +265,19 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
248
265
}
249
266
250
267
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 );
252
269
253
270
oldsize = inode -> i_size ;
254
271
/*
255
272
* In case of writeback_cache enabled, the cached writes beyond EOF
256
273
* extend local i_size without keeping userspace server in sync. So,
257
274
* attr->size coming from server can be stale. We cannot trust it.
258
275
*/
259
- if (!is_wb )
276
+ if (!( cache_mask & STATX_SIZE ) )
260
277
i_size_write (inode , attr -> size );
261
278
spin_unlock (& fi -> lock );
262
279
263
- if (!is_wb && S_ISREG (inode -> i_mode )) {
280
+ if (!cache_mask && S_ISREG (inode -> i_mode )) {
264
281
bool inval = false;
265
282
266
283
if (oldsize != attr -> size ) {
0 commit comments