On Thu, Oct 8, 2026 at 1:20 PM Miklos Szeredi <[email protected]> wrote:
>
> Add support for server allocated 64-bit backing IDs alongside the
> existing kernel allocated 32-bit IDs.
>
> Opened with FUSE_DEV_IOC_BACKING_CREATE, the backing ID sent via
> fuse_backing_create_in.backing_id.
>
> Closed with FUSE_NOTIFY_BACKING_REMOVE.  Since close only provides the
> backing ID, not the file descriptor, it doesn't have to be done with an
> ioctl.
>
> Backing ID can take any 64 bit value other than zero.
>
> Signed-off-by: Miklos Szeredi <[email protected]>
> ---
>  fs/file.c                 |   1 +
>  fs/fuse/backing.c         | 178 ++++++++++++++++++++++++++++----------
>  fs/fuse/dev.c             |  54 +++++++++---
>  fs/fuse/dev.h             |   3 +
>  fs/fuse/fuse_i.h          |  21 ++++-
>  fs/fuse/inode.c           |   8 +-
>  fs/fuse/notify.c          |  28 ++++++
>  fs/fuse/passthrough.c     |   3 +
>  include/uapi/linux/fuse.h |  22 ++++-
>  9 files changed, 252 insertions(+), 66 deletions(-)
>
[...]

>  int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map);
>  int fuse_backing_close(struct fuse_conn *fc, int backing_id);
> +int fuse_backing_open_64(struct fuse_conn *fc, struct fuse_backing_create_in 
> *map);
> +int fuse_backing_close_64(struct fuse_conn *fc, u64 backing_id);
>
>  int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size);
>  int fuse_copy_folio(struct fuse_copy_state *cs, struct folio **foliop,
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index d9ec88028d7b..b1e450f096f6 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -32,6 +32,7 @@
>  #include <linux/pid_namespace.h>
>  #include <linux/refcount.h>
>  #include <linux/user_namespace.h>
> +#include <linux/rhashtable-types.h>
>
>  /** Default max number of pages that can be used in a single read request */
>  #define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
> @@ -92,7 +93,8 @@ struct fuse_submount_lookup {
>  struct fuse_backing {
>         struct file *file;
>         const struct cred *cred;
> -
> +       u64 backing_id;
> +       struct rhash_head hash_node;
>         /* refcount */
>         refcount_t count;
>         struct rcu_head rcu;
> @@ -713,6 +715,9 @@ struct fuse_conn {
>         /** @passthrough: Passthrough support for read/write IO */
>         unsigned int passthrough:1;
>
> +       /** @backing_id_64: Backing ID is 64 bit and allocated by the server 
> */
> +       bool backing_id_64:1;
> +
>         /** @use_pages_for_kvec_io: Use pages instead of pointer for kernel 
> I/O */
>         unsigned int use_pages_for_kvec_io:1;
>
> @@ -770,8 +775,14 @@ struct fuse_conn {
>         struct fuse_sync_bucket __rcu *curr_bucket;
>
>  #ifdef CONFIG_FUSE_PASSTHROUGH
> -       /** @backing_files_map: IDR for backing files ids */
> -       struct idr backing_files_map;
> +       /* Selected by backing_id_64 */
> +       union {
> +               /** @backing_files_map: IDR for backing files ids */
> +               struct idr backing_files_map;
> +
> +               /** @backing_64_ht: 64 bit ID lookup hash table */
> +               struct rhashtable backing_64_ht;
> +       };
>  #endif
>  };
>
> @@ -1270,7 +1281,7 @@ void fuse_file_release(struct inode *inode, struct 
> fuse_file *ff,
>  /* backing.c */
>  #ifdef CONFIG_FUSE_PASSTHROUGH
>  void fuse_backing_put(struct fuse_backing *fb);
> -struct fuse_backing *fuse_backing_lookup(struct fuse_conn *fc, int 
> backing_id);
> +
>  #else
>
>  static inline void fuse_backing_put(struct fuse_backing *fb)
> @@ -1278,7 +1289,9 @@ static inline void fuse_backing_put(struct fuse_backing 
> *fb)
>  }
>  #endif
>
> +struct fuse_backing *fuse_backing_lookup(struct fuse_conn *fc, u64 
> backing_id);
>  void fuse_backing_files_init(struct fuse_conn *fc);
> +void fuse_backing_files_init_64(struct fuse_conn *fc);
>  void fuse_backing_files_free(struct fuse_conn *fc);
>
>  /* passthrough.c */
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index cbb10e19e7e8..b69c95ebb1ad 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -1408,13 +1408,17 @@ static void process_init_reply(struct fuse_args 
> *args, int error)
>                          * them together.
>                          */
>                         if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH) &&
> -                           (flags & FUSE_PASSTHROUGH) &&
> +                           (flags & (FUSE_PASSTHROUGH | 
> FUSE_PASSTHROUGH_V2)) &&
>                             arg->max_stack_depth > 0 &&
>                             arg->max_stack_depth <= 
> FILESYSTEM_MAX_STACK_DEPTH &&
>                             !(flags & FUSE_WRITEBACK_CACHE))  {
>                                 fc->passthrough = 1;
>                                 fc->max_stack_depth = arg->max_stack_depth;
>                                 fm->sb->s_stack_depth = arg->max_stack_depth;
> +                               if (flags & FUSE_PASSTHROUGH_V2) {
> +                                       fc->backing_id_64 = true;
> +                                       fuse_backing_files_init_64(fc);
> +                               }
>                         }
>                         if (flags & FUSE_NO_EXPORT_SUPPORT)
>                                 fm->sb->s_export_op = 
> &fuse_export_fid_operations;

Much better, but I still think it is somewhat ugly to call
fuse_backing_files_init_64()
after fuse_backing_files_init() for an init of a union.

Don't you think this is cleaner?

Thanks,
Amir.

diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 330655af3bd0f..9abf6b1afef5d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -996,9 +996,6 @@ void fuse_conn_init(struct fuse_conn *fc, struct
fuse_mount *fm,
        fc->max_pages_limit = fuse_max_pages_limit;
        fc->name_max = FUSE_NAME_LOW_MAX;

-       if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
-               fuse_backing_files_init(fc);
-
        INIT_LIST_HEAD(&fc->mounts);
        list_add(&fm->fc_entry, &fc->mounts);
        fm->fc = fc;
@@ -1424,10 +1421,8 @@ static void process_init_reply(struct fuse_args
*args, int error)
                                fc->passthrough = 1;
                                fc->max_stack_depth = arg->max_stack_depth;
                                fm->sb->s_stack_depth = arg->max_stack_depth;
-                               if (flags & FUSE_PASSTHROUGH_V2) {
-                                       fc->backing_id_64 = true;
-                                       fuse_backing_files_init_64(fc);
-                               }
+                               fc->backing_id_64 = !!(flags &
FUSE_PASSTHROUGH_V2);
+                               fuse_backing_files_init(fc);
                        }
                        if (flags & FUSE_NO_EXPORT_SUPPORT)
                                fm->sb->s_export_op =
&fuse_export_fid_operations;
diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c
index c93e4a45dd6f6..6157a18b5d554 100644
--- a/fs/fuse/backing.c
+++ b/fs/fuse/backing.c
@@ -46,11 +46,6 @@ void fuse_backing_put(struct fuse_backing *fb)
                fuse_backing_free(fb);
 }

-void fuse_backing_files_init(struct fuse_conn *fc)
-{
-       idr_init(&fc->backing_files_map);
-}
-
 static int fuse_backing_id_alloc(struct fuse_conn *fc, struct fuse_backing *fb)
 {
        int id;
@@ -338,6 +333,9 @@ void fuse_backing_files_free(struct fuse_conn *fc)
        struct rhashtable_iter iter;
        struct fuse_backing *fb;

+       if (!fc->passthrough)
+               return;
+
        if (!fc->backing_id_64) {
                idr_for_each(&fc->backing_files_map,
fuse_backing_idr_free, NULL);
                idr_destroy(&fc->backing_files_map);
@@ -369,7 +367,12 @@ void fuse_backing_files_free(struct fuse_conn *fc)
        rhashtable_free_and_destroy(&fc->backing_64_ht,
fuse_backing_rht_free, NULL);
 }

-void fuse_backing_files_init_64(struct fuse_conn *fc)
+void fuse_backing_files_init(struct fuse_conn *fc)
 {
+       if (!fc->backing_id_64) {
+               idr_init(&fc->backing_files_map);
+               return;
+       }
+
        rhashtable_init(&fc->backing_64_ht, &fuse_backing_prm);
 }
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 064fed459b93c..4235b8fc669b0 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1324,7 +1324,6 @@ struct fuse_backing *fuse_backing_lookup(struct
fuse_conn *fc, u64 backing_id);
 int fuse_backing_add_64(struct fuse_conn *fc, struct fuse_backing *fb);
 bool fuse_backing_is_dax(struct fuse_backing *fb);
 void fuse_backing_files_init(struct fuse_conn *fc);
-void fuse_backing_files_init_64(struct fuse_conn *fc);
 void fuse_backing_files_free(struct fuse_conn *fc);

Reply via email to