@@ -164,7 +164,7 @@ static ino_t fuse_squash_ino(u64 ino64)
164164}
165165
166166void 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+
221233void 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