cifs: do not ignore the SYNC flags in getattr
authorSteve French <stfrench@microsoft.com>
Wed, 19 Feb 2020 00:07:57 +0000 (18:07 -0600)
committerSteve French <stfrench@microsoft.com>
Mon, 23 Mar 2020 03:49:09 +0000 (22:49 -0500)
Check the AT_STATX_FORCE_SYNC flag and force an attribute
revalidation if requested by the caller, and if the caller
specificies AT_STATX_DONT_SYNC only revalidate cached attributes
if required.  In addition do not flush writes in getattr (which
can be expensive) if size or timestamps not requested by the
caller.

Reviewed-by: Aurelien Aptel <aaptel@suse.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/inode.c

index b16f8d2..aad7d2c 100644 (file)
@@ -2148,8 +2148,9 @@ 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 (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
-           inode->i_mapping->nrpages != 0) {
+       if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
+           !CIFS_CACHE_READ(CIFS_I(inode)) &&
+           inode->i_mapping && inode->i_mapping->nrpages != 0) {
                rc = filemap_fdatawait(inode->i_mapping);
                if (rc) {
                        mapping_set_error(inode->i_mapping, rc);
@@ -2157,9 +2158,20 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
                }
        }
 
-       rc = cifs_revalidate_dentry_attr(dentry);
-       if (rc)
-               return rc;
+       if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
+               CIFS_I(inode)->time = 0; /* force revalidate */
+
+       /*
+        * If the caller doesn't require syncing, only sync if
+        * necessary (e.g. due to earlier truncate or setattr
+        * invalidating the cached metadata)
+        */
+       if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
+           (CIFS_I(inode)->time == 0)) {
+               rc = cifs_revalidate_dentry_attr(dentry);
+               if (rc)
+                       return rc;
+       }
 
        generic_fillattr(inode, stat);
        stat->blksize = cifs_sb->bsize;