Skip to content

Commit 5741909

Browse files
neilbrownbrauner
authored andcommitted
VFS: improve interface for lookup_one functions
The family of functions: lookup_one() lookup_one_unlocked() lookup_one_positive_unlocked() appear designed to be used by external clients of the filesystem rather than by filesystems acting on themselves as the lookup_one_len family are used. They are used by: btrfs/ioctl - which is a user-space interface rather than an internal activity exportfs - i.e. from nfsd or the open_by_handle_at interface overlayfs - at access the underlying filesystems smb/server - for file service They should be used by nfsd (more than just the exportfs path) and cachefs but aren't. It would help if the documentation didn't claim they should "not be called by generic code". Also the path component name is passed as "name" and "len" which are (confusingly?) separate by the "base". In some cases the len in simply "strlen" and so passing a qstr using QSTR() would make the calling clearer. Other callers do pass separate name and len which are stored in a struct. Sometimes these are already stored in a qstr, other times it easily could be. So this patch changes these three functions to receive a 'struct qstr *', and improves the documentation. QSTR_LEN() is added to make it easy to pass a QSTR containing a known len. [[email protected]: take a struct qstr pointer] Signed-off-by: NeilBrown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent 0af2f6b commit 5741909

File tree

10 files changed

+58
-58
lines changed

10 files changed

+58
-58
lines changed

Documentation/filesystems/porting.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,3 +1203,12 @@ should use d_drop();d_splice_alias() and return the result of the latter.
12031203
If a positive dentry cannot be returned for some reason, in-kernel
12041204
clients such as cachefiles, nfsd, smb/server may not perform ideally but
12051205
will fail-safe.
1206+
1207+
---
1208+
1209+
** mandatory**
1210+
1211+
lookup_one(), lookup_one_unlocked(), lookup_one_positive_unlocked() now
1212+
take a qstr instead of a name and len. These, not the "one_len"
1213+
versions, should be used whenever accessing a filesystem from outside
1214+
that filesysmtem, through a mount point - which will have a mnt_idmap.

fs/btrfs/ioctl.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ static noinline int btrfs_mksubvol(const struct path *parent,
909909
if (error == -EINTR)
910910
return error;
911911

912-
dentry = lookup_one(idmap, name, parent->dentry, namelen);
912+
dentry = lookup_one(idmap, &QSTR_LEN(name, namelen), parent->dentry);
913913
error = PTR_ERR(dentry);
914914
if (IS_ERR(dentry))
915915
goto out_unlock;
@@ -2288,7 +2288,6 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
22882288
struct btrfs_ioctl_vol_args_v2 *vol_args2 = NULL;
22892289
struct mnt_idmap *idmap = file_mnt_idmap(file);
22902290
char *subvol_name, *subvol_name_ptr = NULL;
2291-
int subvol_namelen;
22922291
int ret = 0;
22932292
bool destroy_parent = false;
22942293

@@ -2411,10 +2410,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
24112410
goto out;
24122411
}
24132412

2414-
subvol_namelen = strlen(subvol_name);
2415-
24162413
if (strchr(subvol_name, '/') ||
2417-
strncmp(subvol_name, "..", subvol_namelen) == 0) {
2414+
strcmp(subvol_name, "..") == 0) {
24182415
ret = -EINVAL;
24192416
goto free_subvol_name;
24202417
}
@@ -2427,7 +2424,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
24272424
ret = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
24282425
if (ret == -EINTR)
24292426
goto free_subvol_name;
2430-
dentry = lookup_one(idmap, subvol_name, parent, subvol_namelen);
2427+
dentry = lookup_one(idmap, &QSTR(subvol_name), parent);
24312428
if (IS_ERR(dentry)) {
24322429
ret = PTR_ERR(dentry);
24332430
goto out_unlock_dir;

fs/exportfs/expfs.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt,
143143
if (err)
144144
goto out_err;
145145
dprintk("%s: found name: %s\n", __func__, nbuf);
146-
tmp = lookup_one_unlocked(mnt_idmap(mnt), nbuf, parent, strlen(nbuf));
146+
tmp = lookup_one_unlocked(mnt_idmap(mnt), &QSTR(nbuf), parent);
147147
if (IS_ERR(tmp)) {
148148
dprintk("lookup failed: %ld\n", PTR_ERR(tmp));
149149
err = PTR_ERR(tmp);
@@ -549,8 +549,7 @@ exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
549549
}
550550

551551
inode_lock(target_dir->d_inode);
552-
nresult = lookup_one(mnt_idmap(mnt), nbuf,
553-
target_dir, strlen(nbuf));
552+
nresult = lookup_one(mnt_idmap(mnt), &QSTR(nbuf), target_dir);
554553
if (!IS_ERR(nresult)) {
555554
if (unlikely(nresult->d_inode != result->d_inode)) {
556555
dput(nresult);

fs/namei.c

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,27 +2922,25 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
29222922
EXPORT_SYMBOL(lookup_one_len);
29232923

29242924
/**
2925-
* lookup_one - filesystem helper to lookup single pathname component
2925+
* lookup_one - lookup single pathname component
29262926
* @idmap: idmap of the mount the lookup is performed from
2927-
* @name: pathname component to lookup
2927+
* @name: qstr holding pathname component to lookup
29282928
* @base: base directory to lookup from
2929-
* @len: maximum length @len should be interpreted to
29302929
*
2931-
* Note that this routine is purely a helper for filesystem usage and should
2932-
* not be called by generic code.
2930+
* This can be used for in-kernel filesystem clients such as file servers.
29332931
*
29342932
* The caller must hold base->i_mutex.
29352933
*/
2936-
struct dentry *lookup_one(struct mnt_idmap *idmap, const char *name,
2937-
struct dentry *base, int len)
2934+
struct dentry *lookup_one(struct mnt_idmap *idmap, struct qstr *name,
2935+
struct dentry *base)
29382936
{
29392937
struct dentry *dentry;
29402938
struct qstr this;
29412939
int err;
29422940

29432941
WARN_ON_ONCE(!inode_is_locked(base->d_inode));
29442942

2945-
err = lookup_one_common(idmap, name, base, len, &this);
2943+
err = lookup_one_common(idmap, name->name, base, name->len, &this);
29462944
if (err)
29472945
return ERR_PTR(err);
29482946

@@ -2952,27 +2950,24 @@ struct dentry *lookup_one(struct mnt_idmap *idmap, const char *name,
29522950
EXPORT_SYMBOL(lookup_one);
29532951

29542952
/**
2955-
* lookup_one_unlocked - filesystem helper to lookup single pathname component
2953+
* lookup_one_unlocked - lookup single pathname component
29562954
* @idmap: idmap of the mount the lookup is performed from
2957-
* @name: pathname component to lookup
2955+
* @name: qstr olding pathname component to lookup
29582956
* @base: base directory to lookup from
2959-
* @len: maximum length @len should be interpreted to
29602957
*
2961-
* Note that this routine is purely a helper for filesystem usage and should
2962-
* not be called by generic code.
2958+
* This can be used for in-kernel filesystem clients such as file servers.
29632959
*
29642960
* Unlike lookup_one_len, it should be called without the parent
2965-
* i_mutex held, and will take the i_mutex itself if necessary.
2961+
* i_rwsem held, and will take the i_rwsem itself if necessary.
29662962
*/
29672963
struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap,
2968-
const char *name, struct dentry *base,
2969-
int len)
2964+
struct qstr *name, struct dentry *base)
29702965
{
29712966
struct qstr this;
29722967
int err;
29732968
struct dentry *ret;
29742969

2975-
err = lookup_one_common(idmap, name, base, len, &this);
2970+
err = lookup_one_common(idmap, name->name, base, name->len, &this);
29762971
if (err)
29772972
return ERR_PTR(err);
29782973

@@ -2984,12 +2979,10 @@ struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap,
29842979
EXPORT_SYMBOL(lookup_one_unlocked);
29852980

29862981
/**
2987-
* lookup_one_positive_unlocked - filesystem helper to lookup single
2988-
* pathname component
2982+
* lookup_one_positive_unlocked - lookup single pathname component
29892983
* @idmap: idmap of the mount the lookup is performed from
2990-
* @name: pathname component to lookup
2984+
* @name: qstr holding pathname component to lookup
29912985
* @base: base directory to lookup from
2992-
* @len: maximum length @len should be interpreted to
29932986
*
29942987
* This helper will yield ERR_PTR(-ENOENT) on negatives. The helper returns
29952988
* known positive or ERR_PTR(). This is what most of the users want.
@@ -2998,16 +2991,15 @@ EXPORT_SYMBOL(lookup_one_unlocked);
29982991
* time, so callers of lookup_one_unlocked() need to be very careful; pinned
29992992
* positives have >d_inode stable, so this one avoids such problems.
30002993
*
3001-
* Note that this routine is purely a helper for filesystem usage and should
3002-
* not be called by generic code.
2994+
* This can be used for in-kernel filesystem clients such as file servers.
30032995
*
3004-
* The helper should be called without i_mutex held.
2996+
* The helper should be called without i_rwsem held.
30052997
*/
30062998
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
3007-
const char *name,
3008-
struct dentry *base, int len)
2999+
struct qstr *name,
3000+
struct dentry *base)
30093001
{
3010-
struct dentry *ret = lookup_one_unlocked(idmap, name, base, len);
3002+
struct dentry *ret = lookup_one_unlocked(idmap, name, base);
30113003

30123004
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
30133005
dput(ret);
@@ -3032,7 +3024,7 @@ EXPORT_SYMBOL(lookup_one_positive_unlocked);
30323024
struct dentry *lookup_one_len_unlocked(const char *name,
30333025
struct dentry *base, int len)
30343026
{
3035-
return lookup_one_unlocked(&nop_mnt_idmap, name, base, len);
3027+
return lookup_one_unlocked(&nop_mnt_idmap, &QSTR_LEN(name, len), base);
30363028
}
30373029
EXPORT_SYMBOL(lookup_one_len_unlocked);
30383030

@@ -3047,7 +3039,8 @@ EXPORT_SYMBOL(lookup_one_len_unlocked);
30473039
struct dentry *lookup_positive_unlocked(const char *name,
30483040
struct dentry *base, int len)
30493041
{
3050-
return lookup_one_positive_unlocked(&nop_mnt_idmap, name, base, len);
3042+
return lookup_one_positive_unlocked(&nop_mnt_idmap,
3043+
&QSTR_LEN(name, len), base);
30513044
}
30523045
EXPORT_SYMBOL(lookup_positive_unlocked);
30533046

fs/overlayfs/namei.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ static struct dentry *ovl_lookup_positive_unlocked(struct ovl_lookup_data *d,
205205
struct dentry *base, int len,
206206
bool drop_negative)
207207
{
208-
struct dentry *ret = lookup_one_unlocked(mnt_idmap(d->layer->mnt), name,
209-
base, len);
208+
struct dentry *ret = lookup_one_unlocked(mnt_idmap(d->layer->mnt),
209+
&QSTR_LEN(name, len), base);
210210

211211
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
212212
if (drop_negative && ret->d_lockref.count == 1) {
@@ -789,8 +789,8 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
789789
if (err)
790790
return ERR_PTR(err);
791791

792-
index = lookup_one_positive_unlocked(ovl_upper_mnt_idmap(ofs), name.name,
793-
ofs->workdir, name.len);
792+
index = lookup_one_positive_unlocked(ovl_upper_mnt_idmap(ofs), &name,
793+
ofs->workdir);
794794
if (IS_ERR(index)) {
795795
err = PTR_ERR(index);
796796
if (err == -ENOENT) {
@@ -1371,7 +1371,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
13711371
bool ovl_lower_positive(struct dentry *dentry)
13721372
{
13731373
struct ovl_entry *poe = OVL_E(dentry->d_parent);
1374-
const struct qstr *name = &dentry->d_name;
1374+
struct qstr *name = &dentry->d_name;
13751375
const struct cred *old_cred;
13761376
unsigned int i;
13771377
bool positive = false;
@@ -1396,7 +1396,7 @@ bool ovl_lower_positive(struct dentry *dentry)
13961396

13971397
this = lookup_one_positive_unlocked(
13981398
mnt_idmap(parentpath->layer->mnt),
1399-
name->name, parentpath->dentry, name->len);
1399+
name, parentpath->dentry);
14001400
if (IS_ERR(this)) {
14011401
switch (PTR_ERR(this)) {
14021402
case -ENOENT:

fs/overlayfs/overlayfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ static inline struct dentry *ovl_lookup_upper(struct ovl_fs *ofs,
402402
const char *name,
403403
struct dentry *base, int len)
404404
{
405-
return lookup_one(ovl_upper_mnt_idmap(ofs), name, base, len);
405+
return lookup_one(ovl_upper_mnt_idmap(ofs), &QSTR_LEN(name, len), base);
406406
}
407407

408408
static inline bool ovl_open_flags_need_copy_up(int flags)

fs/overlayfs/readdir.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,6 @@ static bool ovl_fill_merge(struct dir_context *ctx, const char *name,
271271
static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data *rdd)
272272
{
273273
int err;
274-
struct ovl_cache_entry *p;
275274
struct dentry *dentry, *dir = path->dentry;
276275
const struct cred *old_cred;
277276

@@ -280,9 +279,11 @@ static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data
280279
err = down_write_killable(&dir->d_inode->i_rwsem);
281280
if (!err) {
282281
while (rdd->first_maybe_whiteout) {
283-
p = rdd->first_maybe_whiteout;
282+
struct ovl_cache_entry *p =
283+
rdd->first_maybe_whiteout;
284284
rdd->first_maybe_whiteout = p->next_maybe_whiteout;
285-
dentry = lookup_one(mnt_idmap(path->mnt), p->name, dir, p->len);
285+
dentry = lookup_one(mnt_idmap(path->mnt),
286+
&QSTR_LEN(p->name, p->len), dir);
286287
if (!IS_ERR(dentry)) {
287288
p->is_whiteout = ovl_is_whiteout(dentry);
288289
dput(dentry);
@@ -492,7 +493,7 @@ static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p,
492493
}
493494
}
494495
/* This checks also for xwhiteouts */
495-
this = lookup_one(mnt_idmap(path->mnt), p->name, dir, p->len);
496+
this = lookup_one(mnt_idmap(path->mnt), &QSTR_LEN(p->name, p->len), dir);
496497
if (IS_ERR_OR_NULL(this) || !this->d_inode) {
497498
/* Mark a stale entry */
498499
p->is_whiteout = true;

fs/smb/server/smb2pdu.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4117,9 +4117,10 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
41174117
return -EINVAL;
41184118

41194119
lock_dir(priv->dir_fp);
4120-
dent = lookup_one(idmap, priv->d_info->name,
4121-
priv->dir_fp->filp->f_path.dentry,
4122-
priv->d_info->name_len);
4120+
dent = lookup_one(idmap,
4121+
&QSTR_LEN(priv->d_info->name,
4122+
priv->d_info->name_len),
4123+
priv->dir_fp->filp->f_path.dentry);
41234124
unlock_dir(priv->dir_fp);
41244125

41254126
if (IS_ERR(dent)) {

include/linux/dcache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ struct qstr {
5757
};
5858

5959
#define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
60-
#define QSTR(n) (struct qstr)QSTR_INIT(n, strlen(n))
60+
#define QSTR_LEN(n,l) (struct qstr)QSTR_INIT(n,l)
61+
#define QSTR(n) QSTR_LEN(n, strlen(n))
6162

6263
extern const struct qstr empty_name;
6364
extern const struct qstr slash_name;

include/linux/namei.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,12 @@ extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
7373
extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
7474
extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int);
7575
extern struct dentry *lookup_positive_unlocked(const char *, struct dentry *, int);
76-
struct dentry *lookup_one(struct mnt_idmap *, const char *, struct dentry *, int);
76+
struct dentry *lookup_one(struct mnt_idmap *, struct qstr *, struct dentry *);
7777
struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap,
78-
const char *name, struct dentry *base,
79-
int len);
78+
struct qstr *name, struct dentry *base);
8079
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
81-
const char *name,
82-
struct dentry *base, int len);
80+
struct qstr *name,
81+
struct dentry *base);
8382

8483
extern int follow_down_one(struct path *);
8584
extern int follow_down(struct path *path, unsigned int flags);

0 commit comments

Comments
 (0)