Re: [PATCH] fuse: add FOPEN_FETCH_ATTR flag for fetching attributes after open

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 8/14/24 5:21 AM, Joanne Koong wrote:
> Add FOPEN_FETCH_ATTR flag to indicate that attributes should be
> fetched from the server after an open.
> 
> For fuse servers that are backed by network filesystems, this is
> needed to ensure that file attributes are up to date between
> consecutive open calls.
> 
> For example, if there is a file that is opened on two fuse mounts,
> in the following scenario:
> 
> on mount A, open file.txt w/ O_APPEND, write "hi", close file
> on mount B, open file.txt w/ O_APPEND, write "world", close file
> on mount A, open file.txt w/ O_APPEND, write "123", close file
> 
> when the file is reopened on mount A, the file inode contains the old
> size and the last append will overwrite the data that was written when
> the file was opened/written on mount B.
> 
> (This corruption can be reproduced on the example libfuse passthrough_hp
> server with writeback caching disabled and nopassthrough)
> 
> Having this flag as an option enables parity with NFS's close-to-open
> consistency.

It seems a general demand for close-to-open consistency similar to NFS
when the backend store for FUSE is a NFS-like filesystem.  We have a
similar private implementation for close-to-open consistency in our
internal distribution.  Also FYI there was a similar proposal for this:

https://lore.kernel.org/linux-fsdevel/20220608104202.19461-1-zhangjiachen.jaycee@xxxxxxxxxxxxx/

> 
> Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx>
> ---
>  fs/fuse/file.c            | 7 ++++++-
>  include/uapi/linux/fuse.h | 7 ++++++-
>  2 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index f39456c65ed7..437487ce413d 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -264,7 +264,12 @@ static int fuse_open(struct inode *inode, struct file *file)
>  	err = fuse_do_open(fm, get_node_id(inode), file, false);
>  	if (!err) {
>  		ff = file->private_data;
> -		err = fuse_finish_open(inode, file);
> +		if (ff->open_flags & FOPEN_FETCH_ATTR) {
> +			fuse_invalidate_attr(inode);
> +			err = fuse_update_attributes(inode, file, STATX_BASIC_STATS);
> +		}
> +		if (!err)
> +			err = fuse_finish_open(inode, file);
>  		if (err)
>  			fuse_sync_release(fi, ff, file->f_flags);
>  		else if (is_truncate)
> diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> index d08b99d60f6f..f5d1af6fe352 100644
> --- a/include/uapi/linux/fuse.h
> +++ b/include/uapi/linux/fuse.h
> @@ -217,6 +217,9 @@
>   *  - add backing_id to fuse_open_out, add FOPEN_PASSTHROUGH open flag
>   *  - add FUSE_NO_EXPORT_SUPPORT init flag
>   *  - add FUSE_NOTIFY_RESEND, add FUSE_HAS_RESEND init flag
> + *
> + *  7.41
> + *  - add FOPEN_FETCH_ATTR
>   */
>  
>  #ifndef _LINUX_FUSE_H
> @@ -252,7 +255,7 @@
>  #define FUSE_KERNEL_VERSION 7
>  
>  /** Minor version number of this interface */
> -#define FUSE_KERNEL_MINOR_VERSION 40
> +#define FUSE_KERNEL_MINOR_VERSION 41
>  
>  /** The node ID of the root inode */
>  #define FUSE_ROOT_ID 1
> @@ -360,6 +363,7 @@ struct fuse_file_lock {
>   * FOPEN_NOFLUSH: don't flush data cache on close (unless FUSE_WRITEBACK_CACHE)
>   * FOPEN_PARALLEL_DIRECT_WRITES: Allow concurrent direct writes on the same inode
>   * FOPEN_PASSTHROUGH: passthrough read/write io for this open file
> + * FOPEN_FETCH_ATTR: attributes are fetched after file is opened
>   */
>  #define FOPEN_DIRECT_IO		(1 << 0)
>  #define FOPEN_KEEP_CACHE	(1 << 1)
> @@ -369,6 +373,7 @@ struct fuse_file_lock {
>  #define FOPEN_NOFLUSH		(1 << 5)
>  #define FOPEN_PARALLEL_DIRECT_WRITES	(1 << 6)
>  #define FOPEN_PASSTHROUGH	(1 << 7)
> +#define FOPEN_FETCH_ATTR	(1 << 8)
>  
>  /**
>   * INIT request/reply flags

Does this close-to-open consistency support writeback mode? AFAIK, the
cached ctime/mtime/size at the kernel side are always trusted while
these attributes from the server are dropped, see:

```
fuse_update_attributes
    fuse_update_get_attr
        cache_mask = fuse_get_cache_mask(inode)
            if writeback mode:
                return STATX_MTIME | STATX_CTIME | STATX_SIZE
```

Also FYI there's a similar proposal for enhancing the close-to-open
consistency in writeback mode to fix the above issue:

https://lore.kernel.org/linux-fsdevel/20220624055825.29183-1-zhangjiachen.jaycee@xxxxxxxxxxxxx/

Besides, IIUC this patch only implements the revalidate-on-open semantic
for metadata.  To fulfill the full close-to-open consistency, do you
need to disable FOPEN_KEEP_CACHE to fulfill the revalidate-on-open
semantic for data? (Though the revalidate-on-open semantic for data is
not needed in your append-only case.)

-- 
Thanks,
Jingbo




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux