summaryrefslogtreecommitdiff
path: root/fs/cifs/smb2ops.c
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2019-12-02 21:46:54 -0600
committerSteve French <stfrench@microsoft.com>2019-12-03 15:48:02 -0600
commit43f8a6a74ee2442b9410ed297f5d4c77e7cb5ace (patch)
tree0eabdc6fb77016e544ea32569722114e67b8a6b9 /fs/cifs/smb2ops.c
parent9e8fae2597405ab1deac8909928eb8e99876f639 (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.c49
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,