Skip to content

Commit 21d2be6

Browse files
committed
Merge tag 'afs-fixes-20230502' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull AFS updates from David Howells: "Three fixes to AFS directory handling: - Make sure that afs_read_dir() sees any increase in file size if the file unexpectedly changed on the server (e.g. due to another client making a change). - Make afs_getattr() always return the server's dir file size, not the locally edited one, so that pagecache eviction doesn't cause the dir file size to change unexpectedly. - Prevent afs_read_dir() from getting into an endless loop if the server indicates that the directory file size is larger than expected" * tag 'afs-fixes-20230502' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Avoid endless loop if file is larger than expected afs: Fix getattr to report server i_size on dirs, not local size afs: Fix updating of i_size with dv jump from server
2 parents d7b3ffe + 9ea4eff commit 21d2be6

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

fs/afs/dir.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
275275
loff_t i_size;
276276
int nr_pages, i;
277277
int ret;
278+
loff_t remote_size = 0;
278279

279280
_enter("");
280281

@@ -289,6 +290,8 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
289290

290291
expand:
291292
i_size = i_size_read(&dvnode->netfs.inode);
293+
if (i_size < remote_size)
294+
i_size = remote_size;
292295
if (i_size < 2048) {
293296
ret = afs_bad(dvnode, afs_file_error_dir_small);
294297
goto error;
@@ -364,6 +367,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
364367
* buffer.
365368
*/
366369
up_write(&dvnode->validate_lock);
370+
remote_size = req->file_size;
367371
goto expand;
368372
}
369373

fs/afs/inode.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ static void afs_apply_status(struct afs_operation *op,
230230
set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
231231
}
232232
change_size = true;
233+
data_changed = true;
233234
} else if (vnode->status.type == AFS_FTYPE_DIR) {
234235
/* Expected directory change is handled elsewhere so
235236
* that we can locally edit the directory and save on a
@@ -449,7 +450,7 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
449450
0 : FSCACHE_ADV_SINGLE_CHUNK,
450451
&key, sizeof(key),
451452
&aux, sizeof(aux),
452-
vnode->status.size));
453+
i_size_read(&vnode->netfs.inode)));
453454
#endif
454455
}
455456

@@ -776,6 +777,13 @@ int afs_getattr(struct mnt_idmap *idmap, const struct path *path,
776777
if (test_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags) &&
777778
stat->nlink > 0)
778779
stat->nlink -= 1;
780+
781+
/* Lie about the size of directories. We maintain a locally
782+
* edited copy and may make different allocation decisions on
783+
* it, but we need to give userspace the server's size.
784+
*/
785+
if (S_ISDIR(inode->i_mode))
786+
stat->size = vnode->netfs.remote_i_size;
779787
} while (need_seqretry(&vnode->cb_lock, seq));
780788

781789
done_seqretry(&vnode->cb_lock, seq);

0 commit comments

Comments
 (0)