All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luis Henriques <luis@igalia.com>
To: Amir Goldstein <amir73il@gmail.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
	 "Darrick J. Wong" <djwong@kernel.org>,
	 Bernd Schubert <bschubert@ddn.com>,  Kevin Chen <kchen@ddn.com>,
	 Horst Birthelmer <hbirthelmer@ddn.com>,
	linux-fsdevel@vger.kernel.org,  linux-kernel@vger.kernel.org,
	 Matt Harvey <mharvey@jumptrading.com>,
	 kernel-dev@igalia.com
Subject: Re: [RFC PATCH v2 6/6] fuse: implementation of export_operations with FUSE_LOOKUP_HANDLE
Date: Tue, 16 Dec 2025 17:26:31 +0000	[thread overview]
Message-ID: <87zf7ibans.fsf@wotan.olymp> (raw)
In-Reply-To: <CAOQ4uxh++mVfJXpPt0UH2Xf87Y9qwhJvtTAU=bXvZk0yR0QUEQ@mail.gmail.com> (Amir Goldstein's message of "Tue, 16 Dec 2025 12:01:58 +0100")

On Tue, Dec 16 2025, Amir Goldstein wrote:

> On Fri, Dec 12, 2025 at 7:13 PM Luis Henriques <luis@igalia.com> wrote:
>>
>> This patch allows the NFS handle to use the new file handle provided by the
>> LOOKUP_HANDLE operation.  It still allows the usage of nodeid+generation as
>> an handle if this operation is not supported by the FUSE server or if no
>> handle is available for a specific inode.  I.e. it can mix both file handle
>> types FILEID_INO64_GEN{_PARENT} and FILEID_FUSE_WITH{OUT}_PARENT.
>
> Why the mix? I dont get it.

Well, my thought was that if we have a nodeid for which we don't have a
file handle (FUSE_NODE_ID is the only example I can think of), we still
need to encode it.  And the idea was to use the old FILEID_INO64_GEN in
those cases, even if all other nodeids use the new FILEID.  But I guess we
can simply use the nodeid+gen file handle with the new FILEID anyway.

>>
>> Signed-off-by: Luis Henriques <luis@igalia.com>
>> ---
>>  fs/fuse/export.c         | 162 ++++++++++++++++++++++++++++++++++++---
>>  include/linux/exportfs.h |   7 ++
>>  2 files changed, 160 insertions(+), 9 deletions(-)
>>
>> diff --git a/fs/fuse/export.c b/fs/fuse/export.c
>> index 4a9c95fe578e..b40d146a32f2 100644
>> --- a/fs/fuse/export.c
>> +++ b/fs/fuse/export.c
>> @@ -3,6 +3,7 @@
>>   * FUSE NFS export support.
>>   *
>>   * Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
>> + * Copyright (C) 2025 Jump Trading LLC, author: Luis Henriques <luis@igalia.com>
>>   */
>>
>>  #include "fuse_i.h"
>> @@ -10,7 +11,8 @@
>>
>>  struct fuse_inode_handle {
>>         u64 nodeid;
>> -       u32 generation;
>> +       u32 generation; /* XXX change to u64, and use fid->i64.ino in encode/decode? */
>> +       struct fuse_file_handle fh;
>
> If anything this should be a union
> or maybe I don't understand what you were trying to accomplish.
> Please try to explain the design better in the commit message.

As Miklos also suggested using either nodeid+gen or the new fh, I guess it
makes sense to use a union here.

>>  };
>>
>>  static struct dentry *fuse_get_dentry(struct super_block *sb,
>> @@ -67,8 +69,8 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
>>         return ERR_PTR(err);
>>  }
>>
>> -static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len,
>> -                          struct inode *parent)
>> +static int fuse_encode_gen_fh(struct inode *inode, u32 *fh, int *max_len,
>> +                             struct inode *parent)
>>  {
>>         int len = parent ? 6 : 3;
>>         u64 nodeid;
>> @@ -96,38 +98,180 @@ static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len,
>>         }
>>
>>         *max_len = len;
>> +
>>         return parent ? FILEID_INO64_GEN_PARENT : FILEID_INO64_GEN;
>>  }
>>
>> -static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
>> -               struct fid *fid, int fh_len, int fh_type)
>> +static int fuse_encode_fuse_fh(struct inode *inode, u32 *fh, int *max_len,
>> +                              struct inode *parent)
>> +{
>> +       struct fuse_inode *fi = get_fuse_inode(inode);
>> +       struct fuse_inode *fip = NULL;
>> +       struct fuse_inode_handle *handle = (void *)fh;
>> +       int type = FILEID_FUSE_WITHOUT_PARENT;
>> +       int len, lenp = 0;
>> +       int buflen = *max_len << 2; /* max_len: number of words */
>> +
>> +       len = sizeof(struct fuse_inode_handle) + fi->fh->size;
>> +       if (parent) {
>> +               fip = get_fuse_inode(parent);
>> +               if (fip->fh && fip->fh->size) {
>> +                       lenp = sizeof(struct fuse_inode_handle) +
>> +                               fip->fh->size;
>> +                       type = FILEID_FUSE_WITH_PARENT;
>> +               }
>> +       }
>> +
>> +       if (buflen < (len + lenp)) {
>> +               *max_len = (len + lenp) >> 2;
>> +               return  FILEID_INVALID;
>> +       }
>> +
>> +       handle[0].nodeid = fi->nodeid;
>> +       handle[0].generation = inode->i_generation;
>> +       memcpy(&handle[0].fh, fi->fh, len);
>> +       if (lenp) {
>> +               handle[1].nodeid = fip->nodeid;
>> +               handle[1].generation = parent->i_generation;
>> +               memcpy(&handle[1].fh, fip->fh, lenp);
>> +       }
>> +
>> +       *max_len = (len + lenp) >> 2;
>> +
>> +       return type;
>> +}
>> +
>> +static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len,
>> +                          struct inode *parent)
>> +{
>> +       struct fuse_conn *fc = get_fuse_conn(inode);
>> +       struct fuse_inode *fi = get_fuse_inode(inode);
>> +
>> +       if (fc->lookup_handle && fi->fh && fi->fh->size)
>> +               return fuse_encode_fuse_fh(inode, fh, max_len, parent);
>> +
>> +       return fuse_encode_gen_fh(inode, fh, max_len, parent);
>> +}
>> +
>> +static struct dentry *fuse_fh_gen_to_dentry(struct super_block *sb,
>> +                                           struct fid *fid, int fh_len)
>>  {
>>         struct fuse_inode_handle handle;
>>
>> -       if ((fh_type != FILEID_INO64_GEN &&
>> -            fh_type != FILEID_INO64_GEN_PARENT) || fh_len < 3)
>> +       if (fh_len < 3)
>
> I dont understand why this was changed.

The reason is because fuse_fh_to_dentry() is the only caller of this
function.  Since we already know the type is correct (fuse_fh_to_dentry()
checks it), there's not point checking it again here.

>>                 return NULL;
>>
>>         handle.nodeid = (u64) fid->raw[0] << 32;
>>         handle.nodeid |= (u64) fid->raw[1];
>>         handle.generation = fid->raw[2];
>> +
>>         return fuse_get_dentry(sb, &handle);
>>  }
>>
>> -static struct dentry *fuse_fh_to_parent(struct super_block *sb,
>> +static struct dentry *fuse_fh_fuse_to_dentry(struct super_block *sb,
>> +                                            struct fid *fid, int fh_len)
>> +{
>> +       struct fuse_inode_handle *handle;
>> +       struct dentry *dentry;
>> +       int len = sizeof(struct fuse_file_handle);
>> +
>> +       handle = (void *)fid;
>> +       len += handle->fh.size;
>> +
>> +       if ((fh_len << 2) < len)
>> +               return NULL;
>> +
>> +       handle = kzalloc(len, GFP_KERNEL);
>> +       if (!handle)
>> +               return NULL;
>> +
>> +       memcpy(handle, fid, len);
>> +
>> +       dentry = fuse_get_dentry(sb, handle);
>> +       kfree(handle);
>> +
>> +       return dentry;
>> +}
>> +
>> +static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
>>                 struct fid *fid, int fh_len, int fh_type)
>> +{
>> +       switch (fh_type) {
>> +       case FILEID_INO64_GEN:
>> +       case FILEID_INO64_GEN_PARENT:
>> +               return fuse_fh_gen_to_dentry(sb, fid, fh_len);
>> +       case FILEID_FUSE_WITHOUT_PARENT:
>> +       case FILEID_FUSE_WITH_PARENT:
>> +               return fuse_fh_fuse_to_dentry(sb, fid, fh_len);
>> +       }
>> +
>> +       return NULL;
>> +
>> +}
>> +
>> +static struct dentry *fuse_fh_gen_to_parent(struct super_block *sb,
>> +                                           struct fid *fid, int fh_len)
>>  {
>>         struct fuse_inode_handle parent;
>>
>> -       if (fh_type != FILEID_INO64_GEN_PARENT || fh_len < 6)
>> +       if (fh_len < 6)
>>                 return NULL;
>>
>>         parent.nodeid = (u64) fid->raw[3] << 32;
>>         parent.nodeid |= (u64) fid->raw[4];
>>         parent.generation = fid->raw[5];
>> +
>>         return fuse_get_dentry(sb, &parent);
>>  }
>>
>> +static struct dentry *fuse_fh_fuse_to_parent(struct super_block *sb,
>> +                                            struct fid *fid, int fh_len)
>> +{
>> +       struct fuse_inode_handle *handle;
>> +       struct dentry *dentry;
>> +       int total_len;
>> +       int len;
>> +
>> +       handle = (void *)fid;
>> +       total_len = len = sizeof(struct fuse_inode_handle) + handle->fh.size;
>> +
>> +       if ((fh_len << 2) < total_len)
>> +               return NULL;
>> +
>> +       handle = (void *)(fid + len);
>> +       len = sizeof(struct fuse_file_handle) + handle->fh.size;
>> +       total_len += len;
>> +
>> +       if ((fh_len << 2) < total_len)
>> +               return NULL;
>> +
>> +       handle = kzalloc(len, GFP_KERNEL);
>> +       if (!handle)
>> +               return NULL;
>> +
>> +       memcpy(handle, fid, len);
>> +
>> +       dentry = fuse_get_dentry(sb, handle);
>> +       kfree(handle);
>> +
>> +       return dentry;
>> +}
>> +
>> +static struct dentry *fuse_fh_to_parent(struct super_block *sb,
>> +               struct fid *fid, int fh_len, int fh_type)
>> +{
>> +       switch (fh_type) {
>> +       case FILEID_INO64_GEN:
>> +       case FILEID_INO64_GEN_PARENT:
>> +               return fuse_fh_gen_to_parent(sb, fid, fh_len);
>> +       case FILEID_FUSE_WITHOUT_PARENT:
>> +       case FILEID_FUSE_WITH_PARENT:
>> +               return fuse_fh_fuse_to_parent(sb, fid, fh_len);
>> +       }
>> +
>> +       return NULL;
>> +}
>> +
>>  static struct dentry *fuse_get_parent(struct dentry *child)
>>  {
>>         struct inode *child_inode = d_inode(child);
>> diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
>> index f0cf2714ec52..db783f6b28bc 100644
>> --- a/include/linux/exportfs.h
>> +++ b/include/linux/exportfs.h
>> @@ -110,6 +110,13 @@ enum fid_type {
>>          */
>>         FILEID_INO64_GEN_PARENT = 0x82,
>>
>> +       /*
>> +        * 64 bit nodeid number, 32 bit generation number,
>> +        * variable length handle.
>> +        */
>> +       FILEID_FUSE_WITHOUT_PARENT = 0x91,
>> +       FILEID_FUSE_WITH_PARENT = 0x92,
>> +
>
>
> Do we even need a handle with inode+gen+server specific handle?
> I didn't think we would. If we do, please explain why.

I *think* I've addressed this my other comments above.  Basically, I agree
that we don't need it.  FUSE_ROOT_ID would be the only exception, but
there's no need for this nodeid+gen+fh just because of that.  (Or maybe I
misunderstood this comment?)

(Oh, and thanks a lot everyone for the comments!  Much appreciated.)

Cheers,
-- 
Luís

  reply	other threads:[~2025-12-16 17:26 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-12 18:12 [RFC PATCH v2 0/6] fuse: LOOKUP_HANDLE operation Luis Henriques
2025-12-12 18:12 ` [RFC PATCH v2 1/6] fuse: store index of the variable length argument Luis Henriques
2025-12-12 18:12 ` [RFC PATCH v2 2/6] fuse: move fuse_entry_out structs out of the stack Luis Henriques
2025-12-15 14:03   ` Bernd Schubert
2025-12-16 10:30     ` Luis Henriques
2025-12-12 18:12 ` [RFC PATCH v2 3/6] fuse: initial infrastructure for FUSE_LOOKUP_HANDLE support Luis Henriques
2025-12-15 13:36   ` Bernd Schubert
2025-12-15 17:06     ` Amir Goldstein
2025-12-15 17:11       ` Bernd Schubert
2025-12-15 18:09         ` Amir Goldstein
2025-12-15 18:23           ` Bernd Schubert
2025-12-16 10:36           ` Luis Henriques
2025-12-16 10:19   ` Miklos Szeredi
2025-12-16 11:33     ` Luis Henriques
2025-12-16 11:46       ` Miklos Szeredi
2025-12-16 12:02         ` Luis Henriques
2025-12-12 18:12 ` [RFC PATCH v2 4/6] fuse: implementation of the FUSE_LOOKUP_HANDLE operation Luis Henriques
2025-12-15 17:39   ` Bernd Schubert
2025-12-16 11:48     ` Luis Henriques
2025-12-17 10:18       ` Amir Goldstein
2025-12-17 14:45         ` Luis Henriques
2025-12-17 15:02       ` Bernd Schubert
2025-12-17 16:53         ` Luis Henriques
2025-12-16  8:49   ` Joanne Koong
2025-12-16  8:54     ` Bernd Schubert
2025-12-17  0:32       ` Joanne Koong
2025-12-17  1:00         ` Darrick J. Wong
2025-12-17  2:48           ` Joanne Koong
2025-12-17  9:38             ` Luis Henriques
2025-12-17 10:08               ` Miklos Szeredi
2025-12-17 16:17                 ` Luis Henriques
2025-12-16 10:39   ` Miklos Szeredi
2025-12-16 10:51     ` Amir Goldstein
2025-12-16 11:07       ` Miklos Szeredi
2026-01-09 11:57     ` Luis Henriques
2026-01-09 12:38       ` Miklos Szeredi
2026-01-09 14:45         ` Luis Henriques
2026-01-09 14:56           ` Horst Birthelmer
2026-01-09 17:07             ` Luis Henriques
2026-01-12  7:43               ` Horst Birthelmer
2026-01-09 15:20           ` Miklos Szeredi
2026-01-09 15:03         ` Amir Goldstein
2026-01-09 15:37           ` Miklos Szeredi
2026-01-09 15:56             ` Bernd Schubert
2026-01-09 16:28               ` Miklos Szeredi
2026-01-09 17:16                 ` Luis Henriques
2026-01-09 18:29               ` Amir Goldstein
2026-01-09 19:01                 ` Miklos Szeredi
2026-01-09 19:28                   ` Amir Goldstein
2026-01-09 19:12                 ` Bernd Schubert
2026-01-09 19:55                   ` Horst Birthelmer
2026-01-21 17:56                     ` Luis Henriques
2026-01-21 18:16                       ` Horst Birthelmer
2026-01-21 18:28                         ` Bernd Schubert
2026-01-21 18:36                           ` Horst Birthelmer
2026-01-21 18:49                             ` Bernd Schubert
2026-01-21 19:00                               ` Horst Birthelmer
2026-01-21 19:03                                 ` Bernd Schubert
2026-01-21 19:12                                   ` Horst Birthelmer
2026-01-22  9:52                                     ` Luis Henriques
2026-01-22 10:20                                       ` Horst Birthelmer
2026-01-22 10:35                                         ` Bernd Schubert
2026-01-22 10:53                                         ` Luis Henriques
2026-01-22 10:59                                           ` Horst Birthelmer
2026-01-22 11:25                                             ` Luis Henriques
2026-01-22 11:32                                               ` Bernd Schubert
2026-01-22 12:34                                               ` Horst Birthelmer
2025-12-12 18:12 ` [RFC PATCH v2 5/6] fuse: factor out NFS export related code Luis Henriques
2025-12-14 15:13   ` Amir Goldstein
2025-12-15 12:05     ` Luis Henriques
2025-12-12 18:12 ` [RFC PATCH v2 6/6] fuse: implementation of export_operations with FUSE_LOOKUP_HANDLE Luis Henriques
2025-12-16 10:58   ` Miklos Szeredi
2025-12-16 17:06     ` Luis Henriques
2025-12-16 20:12       ` Horst Birthelmer
2025-12-17 17:02         ` Luis Henriques
2025-12-17 18:02           ` Horst Birthelmer
2025-12-16 11:01   ` Amir Goldstein
2025-12-16 17:26     ` Luis Henriques [this message]
2025-12-14 17:02 ` [RFC PATCH v2 0/6] fuse: LOOKUP_HANDLE operation Askar Safin
2025-12-15 12:08   ` Luis Henriques
2025-12-16  0:33     ` Askar Safin
2025-12-16 17:36       ` Luis Henriques
2025-12-16 18:49       ` Bernd Schubert
2025-12-16 22:45         ` Askar Safin
2025-12-25  7:42         ` Askar Safin
2026-01-04 22:38         ` Askar Safin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87zf7ibans.fsf@wotan.olymp \
    --to=luis@igalia.com \
    --cc=amir73il@gmail.com \
    --cc=bschubert@ddn.com \
    --cc=djwong@kernel.org \
    --cc=hbirthelmer@ddn.com \
    --cc=kchen@ddn.com \
    --cc=kernel-dev@igalia.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mharvey@jumptrading.com \
    --cc=miklos@szeredi.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.