Skip to content

Commit 23b5df0

Browse files
pcacjrsmfrench
authored andcommitted
smb: client: fix generic/694 due to wrong ->i_blocks
When updating ->i_size, make sure to always update ->i_blocks as well until we query new allocation size from the server. generic/694 was failing because smb3_simple_falloc() was missing the update of ->i_blocks after calling cifs_setsize(). So, fix this by updating ->i_blocks directly in cifs_setsize(), so all places that call it doesn't need to worry about updating ->i_blocks later. Reported-by: Shyam Prasad N <sprasad@microsoft.com> Closes: https://lore.kernel.org/r/CANT5p=rqgRwaADB=b_PhJkqXjtfq3SFv41SSTXSVEHnuh871pA@mail.gmail.com Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Cc: David Howells <dhowells@redhat.com> Cc: linux-cifs@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 50bfd2a commit 23b5df0

4 files changed

Lines changed: 16 additions & 32 deletions

File tree

fs/smb/client/cifsglob.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,4 +2386,10 @@ static inline int cifs_open_create_options(unsigned int oflags, int opts)
23862386
return opts;
23872387
}
23882388

2389+
/*
2390+
* The number of blocks is not related to (i_size / i_blksize), but instead
2391+
* 512 byte (2**9) size is required for calculating num blocks.
2392+
*/
2393+
#define CIFS_INO_BLOCKS(size) DIV_ROUND_UP_ULL((u64)(size), 512)
2394+
23892395
#endif /* _CIFS_GLOB_H */

fs/smb/client/file.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,6 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
993993
if (!rc) {
994994
netfs_resize_file(&cinode->netfs, 0, true);
995995
cifs_setsize(inode, 0);
996-
inode->i_blocks = 0;
997996
}
998997
}
999998
if (cfile)

fs/smb/client/inode.c

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
219219
*/
220220
if (is_size_safe_to_change(cifs_i, fattr->cf_eof, from_readdir)) {
221221
i_size_write(inode, fattr->cf_eof);
222-
223-
/*
224-
* i_blocks is not related to (i_size / i_blksize),
225-
* but instead 512 byte (2**9) size is required for
226-
* calculating num blocks.
227-
*/
228-
inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
222+
inode->i_blocks = CIFS_INO_BLOCKS(fattr->cf_bytes);
229223
}
230224

231225
if (S_ISLNK(fattr->cf_mode) && fattr->cf_symlink_target) {
@@ -3015,6 +3009,11 @@ void cifs_setsize(struct inode *inode, loff_t offset)
30153009
{
30163010
spin_lock(&inode->i_lock);
30173011
i_size_write(inode, offset);
3012+
/*
3013+
* Until we can query the server for actual allocation size,
3014+
* this is best estimate we have for blocks allocated for a file.
3015+
*/
3016+
inode->i_blocks = CIFS_INO_BLOCKS(offset);
30183017
spin_unlock(&inode->i_lock);
30193018
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
30203019
truncate_pagecache(inode, offset);
@@ -3087,14 +3086,6 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
30873086
if (rc == 0) {
30883087
netfs_resize_file(&cifsInode->netfs, size, true);
30893088
cifs_setsize(inode, size);
3090-
/*
3091-
* i_blocks is not related to (i_size / i_blksize), but instead
3092-
* 512 byte (2**9) size is required for calculating num blocks.
3093-
* Until we can query the server for actual allocation size,
3094-
* this is best estimate we have for blocks allocated for a file
3095-
* Number of blocks must be rounded up so size 1 is not 0 blocks
3096-
*/
3097-
inode->i_blocks = (512 - 1 + size) >> 9;
30983089
}
30993090

31003091
return rc;

fs/smb/client/smb2ops.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,7 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
14971497
{
14981498
struct smb2_file_network_open_info file_inf;
14991499
struct inode *inode;
1500+
u64 asize;
15001501
int rc;
15011502

15021503
rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid,
@@ -1520,14 +1521,9 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
15201521
inode_set_atime_to_ts(inode,
15211522
cifs_NTtimeToUnix(file_inf.LastAccessTime));
15221523

1523-
/*
1524-
* i_blocks is not related to (i_size / i_blksize),
1525-
* but instead 512 byte (2**9) size is required for
1526-
* calculating num blocks.
1527-
*/
1528-
if (le64_to_cpu(file_inf.AllocationSize) > 4096)
1529-
inode->i_blocks =
1530-
(512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9;
1524+
asize = le64_to_cpu(file_inf.AllocationSize);
1525+
if (asize > 4096)
1526+
inode->i_blocks = CIFS_INO_BLOCKS(asize);
15311527

15321528
/* End of file and Attributes should not have to be updated on close */
15331529
spin_unlock(&inode->i_lock);
@@ -2204,14 +2200,6 @@ smb2_duplicate_extents(const unsigned int xid,
22042200
rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
22052201
if (rc)
22062202
goto duplicate_extents_out;
2207-
2208-
/*
2209-
* Although also could set plausible allocation size (i_blocks)
2210-
* here in addition to setting the file size, in reflink
2211-
* it is likely that the target file is sparse. Its allocation
2212-
* size will be queried on next revalidate, but it is important
2213-
* to make sure that file's cached size is updated immediately
2214-
*/
22152203
netfs_resize_file(netfs_inode(inode), dest_off + len, true);
22162204
cifs_setsize(inode, dest_off + len);
22172205
}

0 commit comments

Comments
 (0)