mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 04:30:52 +07:00
new helper: lookup_positive_unlocked()
Most of the callers of lookup_one_len_unlocked() treat negatives are ERR_PTR(-ENOENT). Provide a helper that would do just that. Note that a pinned positive dentry remains positive - it's ->d_inode is stable, etc.; a pinned _negative_ dentry can become positive at any point as long as you are not holding its parent at least shared. So using lookup_one_len_unlocked() needs to be careful; lookup_positive_unlocked() is safer and that's what the callers end up open-coding anyway. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
d41efb522e
commit
6c2d4798a8
@ -719,11 +719,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
|
|||||||
struct inode *dir = d_inode(dentry);
|
struct inode *dir = d_inode(dentry);
|
||||||
struct dentry *child;
|
struct dentry *child;
|
||||||
|
|
||||||
if (!dir) {
|
|
||||||
dput(dentry);
|
|
||||||
dentry = ERR_PTR(-ENOENT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!S_ISDIR(dir->i_mode)) {
|
if (!S_ISDIR(dir->i_mode)) {
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
dentry = ERR_PTR(-ENOTDIR);
|
dentry = ERR_PTR(-ENOTDIR);
|
||||||
@ -740,7 +735,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
|
|||||||
while (*s && *s != sep)
|
while (*s && *s != sep)
|
||||||
s++;
|
s++;
|
||||||
|
|
||||||
child = lookup_one_len_unlocked(p, dentry, s - p);
|
child = lookup_positive_unlocked(p, dentry, s - p);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
dentry = child;
|
dentry = child;
|
||||||
} while (!IS_ERR(dentry));
|
} while (!IS_ERR(dentry));
|
||||||
|
@ -299,13 +299,9 @@ struct dentry *debugfs_lookup(const char *name, struct dentry *parent)
|
|||||||
if (!parent)
|
if (!parent)
|
||||||
parent = debugfs_mount->mnt_root;
|
parent = debugfs_mount->mnt_root;
|
||||||
|
|
||||||
dentry = lookup_one_len_unlocked(name, parent, strlen(name));
|
dentry = lookup_positive_unlocked(name, parent, strlen(name));
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!d_really_is_positive(dentry)) {
|
|
||||||
dput(dentry);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debugfs_lookup);
|
EXPORT_SYMBOL_GPL(debugfs_lookup);
|
||||||
|
@ -200,7 +200,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
|
|||||||
dput(dentry);
|
dput(dentry);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
dtmp = lookup_one_len_unlocked(kntmp->name, dentry,
|
dtmp = lookup_positive_unlocked(kntmp->name, dentry,
|
||||||
strlen(kntmp->name));
|
strlen(kntmp->name));
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
if (IS_ERR(dtmp))
|
if (IS_ERR(dtmp))
|
||||||
|
20
fs/namei.c
20
fs/namei.c
@ -2557,6 +2557,26 @@ struct dentry *lookup_one_len_unlocked(const char *name,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(lookup_one_len_unlocked);
|
EXPORT_SYMBOL(lookup_one_len_unlocked);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like lookup_one_len_unlocked(), except that it yields ERR_PTR(-ENOENT)
|
||||||
|
* on negatives. Returns known positive or ERR_PTR(); that's what
|
||||||
|
* most of the users want. Note that pinned negative with unlocked parent
|
||||||
|
* _can_ become positive at any time, so callers of lookup_one_len_unlocked()
|
||||||
|
* need to be very careful; pinned positives have ->d_inode stable, so
|
||||||
|
* this one avoids such problems.
|
||||||
|
*/
|
||||||
|
struct dentry *lookup_positive_unlocked(const char *name,
|
||||||
|
struct dentry *base, int len)
|
||||||
|
{
|
||||||
|
struct dentry *ret = lookup_one_len_unlocked(name, base, len);
|
||||||
|
if (!IS_ERR(ret) && d_is_negative(ret)) {
|
||||||
|
dput(ret);
|
||||||
|
ret = ERR_PTR(-ENOENT);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lookup_positive_unlocked);
|
||||||
|
|
||||||
#ifdef CONFIG_UNIX98_PTYS
|
#ifdef CONFIG_UNIX98_PTYS
|
||||||
int path_pts(struct path *path)
|
int path_pts(struct path *path)
|
||||||
{
|
{
|
||||||
|
@ -863,13 +863,11 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
|
|||||||
} else
|
} else
|
||||||
dchild = dget(dparent);
|
dchild = dget(dparent);
|
||||||
} else
|
} else
|
||||||
dchild = lookup_one_len_unlocked(name, dparent, namlen);
|
dchild = lookup_positive_unlocked(name, dparent, namlen);
|
||||||
if (IS_ERR(dchild))
|
if (IS_ERR(dchild))
|
||||||
return rv;
|
return rv;
|
||||||
if (d_mountpoint(dchild))
|
if (d_mountpoint(dchild))
|
||||||
goto out;
|
goto out;
|
||||||
if (d_really_is_negative(dchild))
|
|
||||||
goto out;
|
|
||||||
if (dchild->d_inode->i_ino != ino)
|
if (dchild->d_inode->i_ino != ino)
|
||||||
goto out;
|
goto out;
|
||||||
rv = fh_compose(fhp, exp, dchild, &cd->fh);
|
rv = fh_compose(fhp, exp, dchild, &cd->fh);
|
||||||
|
@ -2991,18 +2991,9 @@ nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd,
|
|||||||
__be32 nfserr;
|
__be32 nfserr;
|
||||||
int ignore_crossmnt = 0;
|
int ignore_crossmnt = 0;
|
||||||
|
|
||||||
dentry = lookup_one_len_unlocked(name, cd->rd_fhp->fh_dentry, namlen);
|
dentry = lookup_positive_unlocked(name, cd->rd_fhp->fh_dentry, namlen);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return nfserrno(PTR_ERR(dentry));
|
return nfserrno(PTR_ERR(dentry));
|
||||||
if (d_really_is_negative(dentry)) {
|
|
||||||
/*
|
|
||||||
* we're not holding the i_mutex here, so there's
|
|
||||||
* a window where this directory entry could have gone
|
|
||||||
* away.
|
|
||||||
*/
|
|
||||||
dput(dentry);
|
|
||||||
return nfserr_noent;
|
|
||||||
}
|
|
||||||
|
|
||||||
exp_get(exp);
|
exp_get(exp);
|
||||||
/*
|
/*
|
||||||
|
@ -200,7 +200,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
|||||||
int err;
|
int err;
|
||||||
bool last_element = !post[0];
|
bool last_element = !post[0];
|
||||||
|
|
||||||
this = lookup_one_len_unlocked(name, base, namelen);
|
this = lookup_positive_unlocked(name, base, namelen);
|
||||||
if (IS_ERR(this)) {
|
if (IS_ERR(this)) {
|
||||||
err = PTR_ERR(this);
|
err = PTR_ERR(this);
|
||||||
this = NULL;
|
this = NULL;
|
||||||
@ -208,8 +208,6 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
|||||||
goto out;
|
goto out;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
if (!this->d_inode)
|
|
||||||
goto put_and_out;
|
|
||||||
|
|
||||||
if (ovl_dentry_weird(this)) {
|
if (ovl_dentry_weird(this)) {
|
||||||
/* Don't support traversing automounts and other weirdness */
|
/* Don't support traversing automounts and other weirdness */
|
||||||
@ -651,7 +649,7 @@ struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh)
|
|||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len);
|
index = lookup_positive_unlocked(name.name, ofs->indexdir, name.len);
|
||||||
kfree(name.name);
|
kfree(name.name);
|
||||||
if (IS_ERR(index)) {
|
if (IS_ERR(index)) {
|
||||||
if (PTR_ERR(index) == -ENOENT)
|
if (PTR_ERR(index) == -ENOENT)
|
||||||
@ -659,9 +657,7 @@ struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d_is_negative(index))
|
if (ovl_is_whiteout(index))
|
||||||
err = 0;
|
|
||||||
else if (ovl_is_whiteout(index))
|
|
||||||
err = -ESTALE;
|
err = -ESTALE;
|
||||||
else if (ovl_dentry_weird(index))
|
else if (ovl_dentry_weird(index))
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
@ -685,7 +681,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
|
|||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len);
|
index = lookup_positive_unlocked(name.name, ofs->indexdir, name.len);
|
||||||
if (IS_ERR(index)) {
|
if (IS_ERR(index)) {
|
||||||
err = PTR_ERR(index);
|
err = PTR_ERR(index);
|
||||||
if (err == -ENOENT) {
|
if (err == -ENOENT) {
|
||||||
@ -700,9 +696,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inode = d_inode(index);
|
inode = d_inode(index);
|
||||||
if (d_is_negative(index)) {
|
if (ovl_is_whiteout(index) && !verify) {
|
||||||
goto out_dput;
|
|
||||||
} else if (ovl_is_whiteout(index) && !verify) {
|
|
||||||
/*
|
/*
|
||||||
* When index lookup is called with !verify for decoding an
|
* When index lookup is called with !verify for decoding an
|
||||||
* overlay file handle, a whiteout index implies that decode
|
* overlay file handle, a whiteout index implies that decode
|
||||||
@ -1131,7 +1125,7 @@ bool ovl_lower_positive(struct dentry *dentry)
|
|||||||
struct dentry *this;
|
struct dentry *this;
|
||||||
struct dentry *lowerdir = poe->lowerstack[i].dentry;
|
struct dentry *lowerdir = poe->lowerstack[i].dentry;
|
||||||
|
|
||||||
this = lookup_one_len_unlocked(name->name, lowerdir,
|
this = lookup_positive_unlocked(name->name, lowerdir,
|
||||||
name->len);
|
name->len);
|
||||||
if (IS_ERR(this)) {
|
if (IS_ERR(this)) {
|
||||||
switch (PTR_ERR(this)) {
|
switch (PTR_ERR(this)) {
|
||||||
@ -1148,10 +1142,8 @@ bool ovl_lower_positive(struct dentry *dentry)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this->d_inode) {
|
positive = !ovl_is_whiteout(this);
|
||||||
positive = !ovl_is_whiteout(this);
|
done = true;
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
dput(this);
|
dput(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2507,15 +2507,10 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
|
|||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
dentry = lookup_one_len_unlocked(qf_name, sb->s_root, strlen(qf_name));
|
dentry = lookup_positive_unlocked(qf_name, sb->s_root, strlen(qf_name));
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
if (d_really_is_negative(dentry)) {
|
|
||||||
error = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = security_quota_on(dentry);
|
error = security_quota_on(dentry);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = vfs_load_quota_inode(d_inode(dentry), type, format_id,
|
error = vfs_load_quota_inode(d_inode(dentry), type, format_id,
|
||||||
|
@ -60,6 +60,7 @@ extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int);
|
|||||||
extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
|
extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
|
||||||
extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
|
extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
|
||||||
extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int);
|
extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int);
|
||||||
|
extern struct dentry *lookup_positive_unlocked(const char *, struct dentry *, int);
|
||||||
|
|
||||||
extern int follow_down_one(struct path *);
|
extern int follow_down_one(struct path *);
|
||||||
extern int follow_down(struct path *);
|
extern int follow_down(struct path *);
|
||||||
|
Loading…
Reference in New Issue
Block a user