Commit 21d2be64 authored by Linus Torvalds's avatar Linus Torvalds

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
parents d7b3ffe2 9ea4eff4
......@@ -275,6 +275,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
loff_t i_size;
int nr_pages, i;
int ret;
loff_t remote_size = 0;
_enter("");
......@@ -289,6 +290,8 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
expand:
i_size = i_size_read(&dvnode->netfs.inode);
if (i_size < remote_size)
i_size = remote_size;
if (i_size < 2048) {
ret = afs_bad(dvnode, afs_file_error_dir_small);
goto error;
......@@ -364,6 +367,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
* buffer.
*/
up_write(&dvnode->validate_lock);
remote_size = req->file_size;
goto expand;
}
......
......@@ -230,6 +230,7 @@ static void afs_apply_status(struct afs_operation *op,
set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
}
change_size = true;
data_changed = true;
} else if (vnode->status.type == AFS_FTYPE_DIR) {
/* Expected directory change is handled elsewhere so
* 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)
0 : FSCACHE_ADV_SINGLE_CHUNK,
&key, sizeof(key),
&aux, sizeof(aux),
vnode->status.size));
i_size_read(&vnode->netfs.inode)));
#endif
}
......@@ -776,6 +777,13 @@ int afs_getattr(struct mnt_idmap *idmap, const struct path *path,
if (test_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags) &&
stat->nlink > 0)
stat->nlink -= 1;
/* Lie about the size of directories. We maintain a locally
* edited copy and may make different allocation decisions on
* it, but we need to give userspace the server's size.
*/
if (S_ISDIR(inode->i_mode))
stat->size = vnode->netfs.remote_i_size;
} while (need_seqretry(&vnode->cb_lock, seq));
done_seqretry(&vnode->cb_lock, seq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment