Merge tag 'fuse-update-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
[sfrench/cifs-2.6.git] / fs / fuse / inode.c
index 549358ffea8bcb3d5e689bc96620e6eaf6c599f0..2e4eb7cf26fb33363698c990a296b50a35aa792b 100644 (file)
@@ -77,7 +77,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
                return NULL;
 
        fi->i_time = 0;
-       fi->inval_mask = 0;
+       fi->inval_mask = ~0;
        fi->nodeid = 0;
        fi->nlookup = 0;
        fi->attr_version = 0;
@@ -163,6 +163,7 @@ static ino_t fuse_squash_ino(u64 ino64)
 }
 
 void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
+                                  struct fuse_statx *sx,
                                   u64 attr_valid, u32 cache_mask)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
@@ -172,7 +173,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
 
        fi->attr_version = atomic64_inc_return(&fc->attr_version);
        fi->i_time = attr_valid;
-       WRITE_ONCE(fi->inval_mask, 0);
+       /* Clear basic stats from invalid mask */
+       set_mask_bits(&fi->inval_mask, STATX_BASIC_STATS, 0);
 
        inode->i_ino     = fuse_squash_ino(attr->ino);
        inode->i_mode    = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
@@ -196,6 +198,25 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
        if (!(cache_mask & STATX_CTIME)) {
                inode_set_ctime(inode, attr->ctime, attr->ctimensec);
        }
+       if (sx) {
+               /* Sanitize nsecs */
+               sx->btime.tv_nsec =
+                       min_t(u32, sx->btime.tv_nsec, NSEC_PER_SEC - 1);
+
+               /*
+                * Btime has been queried, cache is valid (whether or not btime
+                * is available or not) so clear STATX_BTIME from inval_mask.
+                *
+                * Availability of the btime attribute is indicated in
+                * FUSE_I_BTIME
+                */
+               set_mask_bits(&fi->inval_mask, STATX_BTIME, 0);
+               if (sx->mask & STATX_BTIME) {
+                       set_bit(FUSE_I_BTIME, &fi->state);
+                       fi->i_btime.tv_sec = sx->btime.tv_sec;
+                       fi->i_btime.tv_nsec = sx->btime.tv_nsec;
+               }
+       }
 
        if (attr->blksize != 0)
                inode->i_blkbits = ilog2(attr->blksize);
@@ -235,6 +256,7 @@ u32 fuse_get_cache_mask(struct inode *inode)
 }
 
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+                           struct fuse_statx *sx,
                            u64 attr_valid, u64 attr_version)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
@@ -269,7 +291,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
        }
 
        old_mtime = inode->i_mtime;
-       fuse_change_attributes_common(inode, attr, attr_valid, cache_mask);
+       fuse_change_attributes_common(inode, attr, sx, attr_valid, cache_mask);
 
        oldsize = inode->i_size;
        /*
@@ -406,7 +428,7 @@ done:
        spin_lock(&fi->lock);
        fi->nlookup++;
        spin_unlock(&fi->lock);
-       fuse_change_attributes(inode, attr, attr_valid, attr_version);
+       fuse_change_attributes(inode, attr, NULL, attr_valid, attr_version);
 
        return inode;
 }
@@ -1210,6 +1232,8 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                                fc->init_security = 1;
                        if (flags & FUSE_CREATE_SUPP_GROUP)
                                fc->create_supp_group = 1;
+                       if (flags & FUSE_DIRECT_IO_RELAX)
+                               fc->direct_io_relax = 1;
                } else {
                        ra_pages = fc->max_read / PAGE_SIZE;
                        fc->no_lock = 1;
@@ -1256,7 +1280,7 @@ void fuse_send_init(struct fuse_mount *fm)
                FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
                FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
                FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
-               FUSE_HAS_EXPIRE_ONLY;
+               FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_RELAX;
 #ifdef CONFIG_FUSE_DAX
        if (fm->fc->dax)
                flags |= FUSE_MAP_ALIGNMENT;