Re: [PATCH 06/23] fuse: add an ioctl to add new iomap devices

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

 



On Thu, Aug 21, 2025 at 2:54 AM Darrick J. Wong <djwong@xxxxxxxxxx> wrote:
>
> From: Darrick J. Wong <djwong@xxxxxxxxxx>
>
> Add an ioctl that allows fuse servers to register block devices for use
> with iomap.  This is (for now) separate from the backing file open/close
> ioctl (despite using the same struct) to keep the codepaths separate.

Is it though? I'm pretty sure this commit does not add a new ioctl
and reuses the same one (which is fine by me).

>
> Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx>
> ---
>  fs/fuse/fuse_i.h      |    9 +++++
>  fs/fuse/fuse_trace.h  |   49 ++++++++++++++++++++++++++-
>  fs/fuse/Kconfig       |    1 +
>  fs/fuse/backing.c     |   19 ++++++++---
>  fs/fuse/file_iomap.c  |   88 ++++++++++++++++++++++++++++++++++++++++++++-----
>  fs/fuse/passthrough.c |   13 +++++++
>  fs/fuse/trace.c       |    1 +
>  7 files changed, 163 insertions(+), 17 deletions(-)
>
>
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 1762517a1b99c8..f4834a02d16c98 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -100,6 +100,10 @@ struct fuse_submount_lookup {
>  struct fuse_backing {
>         struct file *file;
>         struct cred *cred;
> +       struct block_device *bdev;
> +
> +       unsigned int passthrough:1;
> +       unsigned int iomap:1;
>
>         /** refcount */
>         refcount_t count;
> @@ -1639,9 +1643,14 @@ static inline bool fuse_has_iomap(const struct inode *inode)
>  {
>         return get_fuse_conn_c(inode)->iomap;
>  }
> +
> +int fuse_iomap_backing_open(struct fuse_conn *fc, struct fuse_backing *fb);
> +int fuse_iomap_backing_close(struct fuse_conn *fc, struct fuse_backing *fb);
>  #else
>  # define fuse_iomap_enabled(...)               (false)
>  # define fuse_has_iomap(...)                   (false)
> +# define fuse_iomap_backing_open(...)          (-EOPNOTSUPP)
> +# define fuse_iomap_backing_close(...)         (-EOPNOTSUPP)
>  #endif
>
>  #endif /* _FS_FUSE_I_H */
> diff --git a/fs/fuse/fuse_trace.h b/fs/fuse/fuse_trace.h
> index 660d9b5206a175..c3671a605a32f6 100644
> --- a/fs/fuse/fuse_trace.h
> +++ b/fs/fuse/fuse_trace.h
> @@ -175,6 +175,13 @@ TRACE_EVENT(fuse_request_end,
>  );
>
>  #ifdef CONFIG_FUSE_BACKING
> +#define FUSE_BACKING_PASSTHROUGH       (1U << 0)
> +#define FUSE_BACKING_IOMAP             (1U << 1)
> +
> +#define FUSE_BACKING_FLAG_STRINGS \
> +       { FUSE_BACKING_PASSTHROUGH,             "pass" }, \
> +       { FUSE_BACKING_IOMAP,                   "iomap" }
> +
>  TRACE_EVENT(fuse_backing_class,
>         TP_PROTO(const struct fuse_conn *fc, unsigned int idx,
>                  const struct fuse_backing *fb),
> @@ -184,7 +191,9 @@ TRACE_EVENT(fuse_backing_class,
>         TP_STRUCT__entry(
>                 __field(dev_t,                  connection)
>                 __field(unsigned int,           idx)
> +               __field(unsigned int,           flags)
>                 __field(unsigned long,          ino)
> +               __field(dev_t,                  rdev)
>         ),
>
>         TP_fast_assign(
> @@ -193,12 +202,23 @@ TRACE_EVENT(fuse_backing_class,
>                 __entry->connection     =       fc->dev;
>                 __entry->idx            =       idx;
>                 __entry->ino            =       inode->i_ino;
> +               __entry->flags          =       0;
> +               if (fb->passthrough)
> +                       __entry->flags  |=      FUSE_BACKING_PASSTHROUGH;
> +               if (fb->iomap) {
> +                       __entry->rdev   =       inode->i_rdev;
> +                       __entry->flags  |=      FUSE_BACKING_IOMAP;
> +               } else {
> +                       __entry->rdev   =       0;
> +               }
>         ),
>
> -       TP_printk("connection %u idx %u ino 0x%lx",
> +       TP_printk("connection %u idx %u flags (%s) ino 0x%lx rdev %u:%u",
>                   __entry->connection,
>                   __entry->idx,
> -                 __entry->ino)
> +                 __print_flags(__entry->flags, "|", FUSE_BACKING_FLAG_STRINGS),
> +                 __entry->ino,
> +                 MAJOR(__entry->rdev), MINOR(__entry->rdev))
>  );
>  #define DEFINE_FUSE_BACKING_EVENT(name)                \
>  DEFINE_EVENT(fuse_backing_class, name,         \
> @@ -210,7 +230,6 @@ DEFINE_FUSE_BACKING_EVENT(fuse_backing_close);
>  #endif
>
>  #if IS_ENABLED(CONFIG_FUSE_IOMAP)
> -
>  /* tracepoint boilerplate so we don't have to keep doing this */
>  #define FUSE_IOMAP_OPFLAGS_FIELD \
>                 __field(unsigned,               opflags)
> @@ -452,6 +471,30 @@ TRACE_EVENT(fuse_iomap_end_error,
>                   __entry->written,
>                   __entry->error)
>  );
> +
> +TRACE_EVENT(fuse_iomap_dev_add,
> +       TP_PROTO(const struct fuse_conn *fc,
> +                const struct fuse_backing_map *map),
> +
> +       TP_ARGS(fc, map),
> +
> +       TP_STRUCT__entry(
> +               __field(dev_t,                  connection)
> +               __field(int,                    fd)
> +               __field(unsigned int,           flags)
> +       ),
> +
> +       TP_fast_assign(
> +               __entry->connection     =       fc->dev;
> +               __entry->fd             =       map->fd;
> +               __entry->flags          =       map->flags;
> +       ),
> +
> +       TP_printk("connection %u fd %d flags 0x%x",
> +                 __entry->connection,
> +                 __entry->fd,
> +                 __entry->flags)
> +);
>  #endif /* CONFIG_FUSE_IOMAP */
>
>  #endif /* _TRACE_FUSE_H */
> diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig
> index ebb9a2d76b532e..1ab3d3604c07d0 100644
> --- a/fs/fuse/Kconfig
> +++ b/fs/fuse/Kconfig
> @@ -75,6 +75,7 @@ config FUSE_IOMAP
>         depends on FUSE_FS
>         depends on BLOCK
>         select FS_IOMAP
> +       select FUSE_BACKING
>         help
>           For supported fuseblk servers, this allows the file IO path to run
>           through the kernel.
> diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c
> index c128bed95a76b8..c63990254649ca 100644
> --- a/fs/fuse/backing.c
> +++ b/fs/fuse/backing.c
> @@ -67,16 +67,19 @@ static struct fuse_backing *fuse_backing_id_remove(struct fuse_conn *fc,
>
>  static int fuse_backing_id_free(int id, void *p, void *data)
>  {
> +       struct fuse_conn *fc = data;
>         struct fuse_backing *fb = p;
>
>         WARN_ON_ONCE(refcount_read(&fb->count) != 1);
> +
> +       trace_fuse_backing_close(fc, id, fb);
>         fuse_backing_free(fb);
>         return 0;
>  }
>
>  void fuse_backing_files_free(struct fuse_conn *fc)
>  {
> -       idr_for_each(&fc->backing_files_map, fuse_backing_id_free, NULL);
> +       idr_for_each(&fc->backing_files_map, fuse_backing_id_free, fc);
>         idr_destroy(&fc->backing_files_map);
>  }
>
> @@ -84,12 +87,12 @@ int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map)
>  {
>         struct file *file = NULL;
>         struct fuse_backing *fb = NULL;
> -       int res, passthrough_res;
> +       int res, passthrough_res, iomap_res;
>
>         pr_debug("%s: fd=%d flags=0x%x\n", __func__, map->fd, map->flags);
>
>         res = -EPERM;
> -       if (!fc->passthrough)
> +       if (!fc->passthrough && !fc->iomap)
>                 goto out;
>
>         res = -EINVAL;
> @@ -125,10 +128,13 @@ int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map)
>          * default.
>          */
>         passthrough_res = fuse_passthrough_backing_open(fc, fb);
> +       iomap_res = fuse_iomap_backing_open(fc, fb);
>
>         if (refcount_read(&fb->count) < 2) {
>                 if (passthrough_res)
>                         res = passthrough_res;
> +               if (!res && iomap_res)
> +                       res = iomap_res;
>                 if (!res)
>                         res = -EPERM;
>                 goto out_fb;
> @@ -157,12 +163,12 @@ int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map)
>  int fuse_backing_close(struct fuse_conn *fc, int backing_id)
>  {
>         struct fuse_backing *fb = NULL, *test_fb;
> -       int err, passthrough_err;
> +       int err, passthrough_err, iomap_err;
>
>         pr_debug("%s: backing_id=%d\n", __func__, backing_id);
>
>         err = -EPERM;
> -       if (!fc->passthrough)
> +       if (!fc->passthrough && !fc->iomap)
>                 goto out;
>
>         err = -EINVAL;
> @@ -187,10 +193,13 @@ int fuse_backing_close(struct fuse_conn *fc, int backing_id)
>          * error code will be passed up.  EBUSY is the default.
>          */
>         passthrough_err = fuse_passthrough_backing_close(fc, fb);
> +       iomap_err = fuse_iomap_backing_close(fc, fb);
>
>         if (refcount_read(&fb->count) > 1) {
>                 if (passthrough_err)
>                         err = passthrough_err;
> +               if (!err && iomap_err)
> +                       err = iomap_err;
>                 if (!err)
>                         err = -EBUSY;
>                 goto out_fb;

Do you really think that we need to support both file passthrough and file iomap
on the same fuse filesystem?

Unless you have a specific use case in mind, it looks like over design to me
We could enforce either fc->passthrough or fc->iomap on init.

Put it in other words: unless you intend to test a combination of file
passthrough
and file iomap, I think you should leave this configuration out of the config
possibilities.

Thanks,
Amir.





[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