Merge tag 'dma-rename-4.18' of git://git.infradead.org/users/hch/dma-mapping
[sfrench/cifs-2.6.git] / fs / cifs / inode.c
index 3c371f7f5963e7933ae507df3f40ee5475a56ead..a2cfb33e85c1f8cb25a2d32a52bb5d60c93b79f1 100644 (file)
@@ -95,6 +95,7 @@ static void
 cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+       struct timespec ts;
 
        cifs_dbg(FYI, "%s: revalidating inode %llu\n",
                 __func__, cifs_i->uniqueid);
@@ -113,7 +114,8 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
        }
 
         /* revalidate if mtime or size have changed */
-       if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
+       ts = timespec64_to_timespec(inode->i_mtime);
+       if (timespec_equal(&ts, &fattr->cf_mtime) &&
            cifs_i->server_eof == fattr->cf_eof) {
                cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
                         __func__, cifs_i->uniqueid);
@@ -162,9 +164,9 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
        cifs_revalidate_cache(inode, fattr);
 
        spin_lock(&inode->i_lock);
-       inode->i_atime = fattr->cf_atime;
-       inode->i_mtime = fattr->cf_mtime;
-       inode->i_ctime = fattr->cf_ctime;
+       inode->i_atime = timespec_to_timespec64(fattr->cf_atime);
+       inode->i_mtime = timespec_to_timespec64(fattr->cf_mtime);
+       inode->i_ctime = timespec_to_timespec64(fattr->cf_ctime);
        inode->i_rdev = fattr->cf_rdev;
        cifs_nlink_fattr_to_inode(inode, fattr);
        inode->i_uid = fattr->cf_uid;
@@ -746,7 +748,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
        cifs_dbg(FYI, "Getting info on %s\n", full_path);
 
        if ((data == NULL) && (*inode != NULL)) {
-               if (CIFS_CACHE_READ(CIFS_I(*inode))) {
+               if (CIFS_CACHE_READ(CIFS_I(*inode)) &&
+                   CIFS_I(*inode)->time != 0) {
                        cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
                        goto cgii_exit;
                }
@@ -1122,14 +1125,14 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
        if (attrs->ia_valid & ATTR_ATIME) {
                set_time = true;
                info_buf.LastAccessTime =
-                       cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
+                       cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime)));
        } else
                info_buf.LastAccessTime = 0;
 
        if (attrs->ia_valid & ATTR_MTIME) {
                set_time = true;
                info_buf.LastWriteTime =
-                   cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+                   cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime)));
        } else
                info_buf.LastWriteTime = 0;
 
@@ -1142,7 +1145,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
        if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
                cifs_dbg(FYI, "CIFS - CTIME changed\n");
                info_buf.ChangeTime =
-                   cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+                   cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime)));
        } else
                info_buf.ChangeTime = 0;
 
@@ -1572,6 +1575,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
                goto mkdir_out;
        }
 
+       server = tcon->ses->server;
+
+#ifdef CONFIG_CIFS_SMB311
+       if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
+               rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
+                                             cifs_sb);
+               d_drop(direntry); /* for time being always refresh inode info */
+               goto mkdir_out;
+       }
+#endif /* SMB311 */
+
        if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                                le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
@@ -1580,8 +1594,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
                        goto mkdir_out;
        }
 
-       server = tcon->ses->server;
-
        if (!server->ops->mkdir) {
                rc = -ENOSYS;
                goto mkdir_out;
@@ -1791,7 +1803,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
                 * with unix extensions enabled.
                 */
                info_buf_source =
-                       kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
+                       kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
                                        GFP_KERNEL);
                if (info_buf_source == NULL) {
                        rc = -ENOMEM;
@@ -1857,15 +1869,15 @@ cifs_inode_needs_reval(struct inode *inode)
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
+       if (cifs_i->time == 0)
+               return true;
+
        if (CIFS_CACHE_READ(cifs_i))
                return false;
 
        if (!lookupCacheEnabled)
                return true;
 
-       if (cifs_i->time == 0)
-               return true;
-
        if (!cifs_sb->actimeo)
                return true;
 
@@ -2059,8 +2071,8 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
        /* old CIFS Unix Extensions doesn't return create time */
        if (CIFS_I(inode)->createtime) {
                stat->result_mask |= STATX_BTIME;
-               stat->btime =
-                     cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
+               stat->btime = timespec_to_timespec64(
+                     cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime)));
        }
 
        stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
@@ -2104,10 +2116,14 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
 
 static void cifs_setsize(struct inode *inode, loff_t offset)
 {
+       struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+
        spin_lock(&inode->i_lock);
        i_size_write(inode, offset);
        spin_unlock(&inode->i_lock);
 
+       /* Cached inode must be refreshed on truncate */
+       cifs_i->time = 0;
        truncate_pagecache(inode, offset);
 }
 
@@ -2262,17 +2278,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
                args->gid = INVALID_GID; /* no change */
 
        if (attrs->ia_valid & ATTR_ATIME)
-               args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
+               args->atime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime));
        else
                args->atime = NO_CHANGE_64;
 
        if (attrs->ia_valid & ATTR_MTIME)
-               args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
+               args->mtime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime));
        else
                args->mtime = NO_CHANGE_64;
 
        if (attrs->ia_valid & ATTR_CTIME)
-               args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
+               args->ctime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime));
        else
                args->ctime = NO_CHANGE_64;