summaryrefslogtreecommitdiff
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2021-03-19 08:05:48 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-25 11:04:09 +0300
commit04eb2b2fa12ff6023a92d5199275255e9b82011b (patch)
tree43fec2834d3994cd88a47869b5b251af935ec6b7 /fs/cifs
parentbb2e41e65c33a40502c9d876c7a337984d665a30 (diff)
downloadlinux-04eb2b2fa12ff6023a92d5199275255e9b82011b.tar.xz
cifs: fix allocation size on newly created files
commit 65af8f0166f4d15e61c63db498ec7981acdd897f upstream. Applications that create and extend and write to a file do not expect to see 0 allocation size. When file is extended, set its allocation size to a plausible value until we have a chance to query the server for it. When the file is cached this will prevent showing an impossible number of allocated blocks (like 0). This fixes e.g. xfstests 614 which does 1) create a file and set its size to 64K 2) mmap write 64K to the file 3) stat -c %b for the file (to query the number of allocated blocks) It was failing because we returned 0 blocks. Even though we would return the correct cached file size, we returned an impossible allocation size. Signed-off-by: Steve French <stfrench@microsoft.com> CC: <stable@vger.kernel.org> Reviewed-by: Aurelien Aptel <aaptel@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/inode.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 9ee5f304592f..b1f0c05d6eaf 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -2375,7 +2375,7 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
* We need to be sure that all dirty pages are written and the server
* has actual ctime, mtime and file length.
*/
- if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
+ if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE | STATX_BLOCKS)) &&
!CIFS_CACHE_READ(CIFS_I(inode)) &&
inode->i_mapping && inode->i_mapping->nrpages != 0) {
rc = filemap_fdatawait(inode->i_mapping);
@@ -2565,6 +2565,14 @@ set_size_out:
if (rc == 0) {
cifsInode->server_eof = attrs->ia_size;
cifs_setsize(inode, attrs->ia_size);
+ /*
+ * i_blocks is not related to (i_size / i_blksize), but instead
+ * 512 byte (2**9) size is required for calculating num blocks.
+ * Until we can query the server for actual allocation size,
+ * this is best estimate we have for blocks allocated for a file
+ * Number of blocks must be rounded up so size 1 is not 0 blocks
+ */
+ inode->i_blocks = (512 - 1 + attrs->ia_size) >> 9;
/*
* The man page of truncate says if the size changed,