diff options
author | Steve French <stfrench@microsoft.com> | 2019-12-02 21:46:54 -0600 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-12-03 15:48:02 -0600 |
commit | 43f8a6a74ee2442b9410ed297f5d4c77e7cb5ace (patch) | |
tree | 0eabdc6fb77016e544ea32569722114e67b8a6b9 /fs/cifs/smb2ops.c | |
parent | 9e8fae2597405ab1deac8909928eb8e99876f639 (diff) |
smb3: query attributes on file close
Since timestamps on files on most servers can be updated at
close, and since timestamps on our dentries default to one
second we can have stale timestamps in some common cases
(e.g. open, write, close, stat, wait one second, stat - will
show different mtime for the first and second stat).
The SMB2/SMB3 protocol allows querying timestamps at close
so add the code to request timestamp and attr information
(which is cheap for the server to provide) to be returned
when a file is closed (it is not needed for the many
paths that call SMB2_close that are from compounded
query infos and close nor is it needed for some of
the cases where a directory close immediately follows a
directory open.
Signed-off-by: Steve French <stfrench@microsoft.com>
Acked-by: Ronnie Sahlberg <lsahlber@redhat.com>
Reviewed-by: Aurelien Aptel <aaptel@suse.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index a7f328f79c6f..a5c96bc522cb 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1178,7 +1178,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, memset(&close_iov, 0, sizeof(close_iov)); rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); smb2_set_related(&rqst[2]); rc = compound_send_recv(xid, ses, flags, 3, rqst, @@ -1332,6 +1332,45 @@ smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon, SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); } +static void +smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon, + struct cifsFileInfo *cfile) +{ + struct smb2_file_network_open_info file_inf; + struct inode *inode; + int rc; + + rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid, + cfile->fid.volatile_fid, &file_inf); + if (rc) + return; + + inode = d_inode(cfile->dentry); + + spin_lock(&inode->i_lock); + CIFS_I(inode)->time = jiffies; + + /* Creation time should not need to be updated on close */ + if (file_inf.LastWriteTime) + inode->i_mtime = cifs_NTtimeToUnix(file_inf.LastWriteTime); + if (file_inf.ChangeTime) + inode->i_ctime = cifs_NTtimeToUnix(file_inf.ChangeTime); + if (file_inf.LastAccessTime) + inode->i_atime = cifs_NTtimeToUnix(file_inf.LastAccessTime); + + /* + * i_blocks is not related to (i_size / i_blksize), + * but instead 512 byte (2**9) size is required for + * calculating num blocks. + */ + if (le64_to_cpu(file_inf.AllocationSize) > 4096) + inode->i_blocks = + (512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9; + + /* End of file and Attributes should not have to be updated on close */ + spin_unlock(&inode->i_lock); +} + static int SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, @@ -1512,7 +1551,7 @@ smb2_ioctl_query_info(const unsigned int xid, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto iqinf_exit; smb2_set_related(&rqst[2]); @@ -2241,7 +2280,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto qic_exit; smb2_set_related(&rqst[2]); @@ -2654,7 +2693,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto querty_exit; @@ -4707,6 +4746,7 @@ struct smb_version_operations smb30_operations = { .open = smb2_open_file, .set_fid = smb2_set_fid, .close = smb2_close_file, + .close_getattr = smb2_close_getattr, .flush = smb2_flush_file, .async_readv = smb2_async_readv, .async_writev = smb2_async_writev, @@ -4816,6 +4856,7 @@ struct smb_version_operations smb311_operations = { .open = smb2_open_file, .set_fid = smb2_set_fid, .close = smb2_close_file, + .close_getattr = smb2_close_getattr, .flush = smb2_flush_file, .async_readv = smb2_async_readv, .async_writev = smb2_async_writev, |