On Thu, 2025-01-16 at 05:23 +0000, Al Viro wrote: > Currently get_fscrypt_altname() requires ->r_dentry->d_name to be stable > and it gets that in almost all cases. The only exception is ->d_revalidate(), > where we have a stable name, but it's passed separately - dentry->d_name > is not stable there. > > Propagate it down to get_fscrypt_altname() as a new field of struct > ceph_mds_request - ->r_dname, to be used instead ->r_dentry->d_name > when non-NULL. > > Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> > --- > fs/ceph/dir.c | 2 ++ > fs/ceph/mds_client.c | 9 ++++++--- > fs/ceph/mds_client.h | 2 ++ > 3 files changed, 10 insertions(+), 3 deletions(-) > > diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c > index dc5f55bebad7..62e99e65250d 100644 > --- a/fs/ceph/dir.c > +++ b/fs/ceph/dir.c > @@ -1998,6 +1998,8 @@ static int ceph_d_revalidate(struct inode *dir, const struct qstr *name, > req->r_parent = dir; > ihold(dir); > > + req->r_dname = name; > + > mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED; > if (ceph_security_xattr_wanted(dir)) > mask |= CEPH_CAP_XATTR_SHARED; > diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c > index 219a2cc2bf3c..3b766b984713 100644 > --- a/fs/ceph/mds_client.c > +++ b/fs/ceph/mds_client.c > @@ -2621,6 +2621,7 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen) > { > struct inode *dir = req->r_parent; > struct dentry *dentry = req->r_dentry; > + const struct qstr *name = req->r_dname; > u8 *cryptbuf = NULL; > u32 len = 0; > int ret = 0; > @@ -2641,8 +2642,10 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen) > if (!fscrypt_has_encryption_key(dir)) > goto success; > > - if (!fscrypt_fname_encrypted_size(dir, dentry->d_name.len, NAME_MAX, > - &len)) { > + if (!name) > + name = &dentry->d_name; > + > + if (!fscrypt_fname_encrypted_size(dir, name->len, NAME_MAX, &len)) { > WARN_ON_ONCE(1); > return ERR_PTR(-ENAMETOOLONG); > } > @@ -2657,7 +2660,7 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen) > if (!cryptbuf) > return ERR_PTR(-ENOMEM); > > - ret = fscrypt_fname_encrypt(dir, &dentry->d_name, cryptbuf, len); > + ret = fscrypt_fname_encrypt(dir, name, cryptbuf, len); > if (ret) { > kfree(cryptbuf); > return ERR_PTR(ret); > diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h > index 38bb7e0d2d79..7c9fee9e80d4 100644 > --- a/fs/ceph/mds_client.h > +++ b/fs/ceph/mds_client.h > @@ -299,6 +299,8 @@ struct ceph_mds_request { > struct inode *r_target_inode; /* resulting inode */ > struct inode *r_new_inode; /* new inode (for creates) */ > > + const struct qstr *r_dname; /* stable name (for ->d_revalidate) */ > + > #define CEPH_MDS_R_DIRECT_IS_HASH (1) /* r_direct_hash is valid */ > #define CEPH_MDS_R_ABORTED (2) /* call was aborted */ > #define CEPH_MDS_R_GOT_UNSAFE (3) /* got an unsafe reply */ Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>