Re: [PATCH 1/6] VFS: improve interface for lookup_one functions

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

 



On Sat, 22 Mar 2025, Al Viro wrote:
> On Wed, Mar 19, 2025 at 02:01:32PM +1100, NeilBrown wrote:
> 
> > -struct dentry *lookup_one(struct mnt_idmap *idmap, const char *name,
> > -			  struct dentry *base, int len)
> > +struct dentry *lookup_one(struct mnt_idmap *idmap, struct qstr name,
> > +			  struct dentry *base)
> 
> >  {
> >  	struct dentry *dentry;
> >  	struct qstr this;
> > @@ -2942,7 +2940,7 @@ struct dentry *lookup_one(struct mnt_idmap *idmap, const char *name,
> >  
> >  	WARN_ON_ONCE(!inode_is_locked(base->d_inode));
> >  
> > -	err = lookup_one_common(idmap, name, base, len, &this);
> > +	err = lookup_one_common(idmap, name.name, base, name.len, &this);
> 
> No.  Just look at what lookup_one_common() is doing as the first step.
> 
>         this->name = name;
> 	this->len = len;

This code is cleaned up in a later patch. lookup_one_common receives the
address of just one qstr which is initialised with qstr that is passed
in.
So on x86_64, the original qstr is passed in as 2 registers.  These are
stored in the stack and the address is passed to lookup_noperm_common(),
as lookup_one_common() gets inlined.

We have to put the two values onto the stack at some point, either in
the original callers, or in the lookup_one family of functions.  I think
it is cleaner in lookup_one as we don't need to put a & in front of all
the QSTR calls.  But we can change it to pass the pointer if you really
think that is better.

Thanks,
NeilBrown


> 
> You copy your argument's fields to corresponding fields of *&this.  It might make
> sense to pass a qstr, but not like that - just pass a _pointer_ to struct qstr instead.
> 
> Have lookup_one_common() do this:
> 
> static int lookup_one_common(struct mnt_idmap *idmap,
>                              struct qstr *this, struct dentry *base)
> {
> 	const unsigned char *name = this->name;
> 	int len = this->len;
>         if (!len)
>                 return -EACCES;
> 
>         this->hash = full_name_hash(base, name, len);
>         if (is_dot_dotdot(name, len))
>                 return -EACCES;
> 
>         while (len--) {
>                 unsigned int c = *name++;
>                 if (c == '/' || c == '\0')
>                         return -EACCES;
>         }
>         /*
>          * See if the low-level filesystem might want
>          * to use its own hash..
>          */
>         if (base->d_flags & DCACHE_OP_HASH) {
>                 int err = base->d_op->d_hash(base, this);
>                 if (err < 0)
>                         return err;
>         }
> 
>         return inode_permission(idmap, base->d_inode, MAY_EXEC);
> }
> 
> and adjust the callers; e.g.
> struct dentry *lookup_one(struct mnt_idmap *idmap, struct qstr *this,
> 			  struct dentry *base)
> {
>         struct dentry *dentry;
>         int err;
> 
>         WARN_ON_ONCE(!inode_is_locked(base->d_inode));
> 
>         err = lookup_one_common(idmap, this, base);
>         if (err)
>                 return ERR_PTR(err);
> 
>         dentry = lookup_dcache(this, base, 0);
>         return dentry ? dentry : __lookup_slow(this, base, 0);
> }
> 
> with callers passing idmap, &QSTR_LEN(name, len), base instead of
> idmap, name, base, len.  lookup_one_common() looks at the fields
> separately; its callers do not.
> 






[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