mirror of https://gitee.com/openkylin/linux.git
kernfs: don't set dentry->d_fsdata
When working on adding exportfs operations in kernfs, I found it's hard to initialize dentry->d_fsdata in the exportfs operations. Looks there is no way to do it without race condition. Look at the kernfs code closely, there is no point to set dentry->d_fsdata. inode->i_private already points to kernfs_node, and we can get inode from a dentry. So this patch just delete the d_fsdata usage. Acked-by: Tejun Heo <tj@kernel.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Shaohua Li <shli@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
ba16b2846a
commit
319ba91d35
|
@ -566,7 +566,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
if (d_really_is_negative(dentry))
|
if (d_really_is_negative(dentry))
|
||||||
goto out_bad_unlocked;
|
goto out_bad_unlocked;
|
||||||
|
|
||||||
kn = dentry->d_fsdata;
|
kn = kernfs_dentry_node(dentry);
|
||||||
mutex_lock(&kernfs_mutex);
|
mutex_lock(&kernfs_mutex);
|
||||||
|
|
||||||
/* The kernfs node has been deactivated */
|
/* The kernfs node has been deactivated */
|
||||||
|
@ -574,7 +574,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
goto out_bad;
|
goto out_bad;
|
||||||
|
|
||||||
/* The kernfs node has been moved? */
|
/* The kernfs node has been moved? */
|
||||||
if (dentry->d_parent->d_fsdata != kn->parent)
|
if (kernfs_dentry_node(dentry->d_parent) != kn->parent)
|
||||||
goto out_bad;
|
goto out_bad;
|
||||||
|
|
||||||
/* The kernfs node has been renamed */
|
/* The kernfs node has been renamed */
|
||||||
|
@ -594,14 +594,8 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kernfs_dop_release(struct dentry *dentry)
|
|
||||||
{
|
|
||||||
kernfs_put(dentry->d_fsdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct dentry_operations kernfs_dops = {
|
const struct dentry_operations kernfs_dops = {
|
||||||
.d_revalidate = kernfs_dop_revalidate,
|
.d_revalidate = kernfs_dop_revalidate,
|
||||||
.d_release = kernfs_dop_release,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -617,8 +611,9 @@ const struct dentry_operations kernfs_dops = {
|
||||||
*/
|
*/
|
||||||
struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
|
struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
if (dentry->d_sb->s_op == &kernfs_sops)
|
if (dentry->d_sb->s_op == &kernfs_sops &&
|
||||||
return dentry->d_fsdata;
|
!d_really_is_negative(dentry))
|
||||||
|
return kernfs_dentry_node(dentry);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,7 +1051,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct dentry *ret;
|
struct dentry *ret;
|
||||||
struct kernfs_node *parent = dentry->d_parent->d_fsdata;
|
struct kernfs_node *parent = dir->i_private;
|
||||||
struct kernfs_node *kn;
|
struct kernfs_node *kn;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
const void *ns = NULL;
|
const void *ns = NULL;
|
||||||
|
@ -1073,8 +1068,6 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
kernfs_get(kn);
|
|
||||||
dentry->d_fsdata = kn;
|
|
||||||
|
|
||||||
/* attach dentry and inode */
|
/* attach dentry and inode */
|
||||||
inode = kernfs_get_inode(dir->i_sb, kn);
|
inode = kernfs_get_inode(dir->i_sb, kn);
|
||||||
|
@ -1111,7 +1104,7 @@ static int kernfs_iop_mkdir(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
|
static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = dentry->d_fsdata;
|
struct kernfs_node *kn = kernfs_dentry_node(dentry);
|
||||||
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
|
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1131,7 +1124,7 @@ static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||||
struct inode *new_dir, struct dentry *new_dentry,
|
struct inode *new_dir, struct dentry *new_dentry,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = old_dentry->d_fsdata;
|
struct kernfs_node *kn = kernfs_dentry_node(old_dentry);
|
||||||
struct kernfs_node *new_parent = new_dir->i_private;
|
struct kernfs_node *new_parent = new_dir->i_private;
|
||||||
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
|
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1644,7 +1637,7 @@ static struct kernfs_node *kernfs_dir_next_pos(const void *ns,
|
||||||
static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
|
static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
|
||||||
{
|
{
|
||||||
struct dentry *dentry = file->f_path.dentry;
|
struct dentry *dentry = file->f_path.dentry;
|
||||||
struct kernfs_node *parent = dentry->d_fsdata;
|
struct kernfs_node *parent = kernfs_dentry_node(dentry);
|
||||||
struct kernfs_node *pos = file->private_data;
|
struct kernfs_node *pos = file->private_data;
|
||||||
const void *ns = NULL;
|
const void *ns = NULL;
|
||||||
|
|
||||||
|
|
|
@ -616,7 +616,7 @@ static void kernfs_put_open_node(struct kernfs_node *kn,
|
||||||
|
|
||||||
static int kernfs_fop_open(struct inode *inode, struct file *file)
|
static int kernfs_fop_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = file->f_path.dentry->d_fsdata;
|
struct kernfs_node *kn = inode->i_private;
|
||||||
struct kernfs_root *root = kernfs_root(kn);
|
struct kernfs_root *root = kernfs_root(kn);
|
||||||
const struct kernfs_ops *ops;
|
const struct kernfs_ops *ops;
|
||||||
struct kernfs_open_file *of;
|
struct kernfs_open_file *of;
|
||||||
|
@ -768,7 +768,7 @@ static void kernfs_release_file(struct kernfs_node *kn,
|
||||||
|
|
||||||
static int kernfs_fop_release(struct inode *inode, struct file *filp)
|
static int kernfs_fop_release(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = filp->f_path.dentry->d_fsdata;
|
struct kernfs_node *kn = inode->i_private;
|
||||||
struct kernfs_open_file *of = kernfs_of(filp);
|
struct kernfs_open_file *of = kernfs_of(filp);
|
||||||
|
|
||||||
if (kn->flags & KERNFS_HAS_RELEASE) {
|
if (kn->flags & KERNFS_HAS_RELEASE) {
|
||||||
|
@ -835,7 +835,7 @@ void kernfs_drain_open_files(struct kernfs_node *kn)
|
||||||
static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
|
static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
|
||||||
{
|
{
|
||||||
struct kernfs_open_file *of = kernfs_of(filp);
|
struct kernfs_open_file *of = kernfs_of(filp);
|
||||||
struct kernfs_node *kn = filp->f_path.dentry->d_fsdata;
|
struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry);
|
||||||
struct kernfs_open_node *on = kn->attr.open;
|
struct kernfs_open_node *on = kn->attr.open;
|
||||||
|
|
||||||
if (!kernfs_get_active(kn))
|
if (!kernfs_get_active(kn))
|
||||||
|
|
|
@ -112,7 +112,7 @@ int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
|
||||||
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
|
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||||
{
|
{
|
||||||
struct inode *inode = d_inode(dentry);
|
struct inode *inode = d_inode(dentry);
|
||||||
struct kernfs_node *kn = dentry->d_fsdata;
|
struct kernfs_node *kn = inode->i_private;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!kn)
|
if (!kn)
|
||||||
|
@ -154,7 +154,7 @@ static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
|
||||||
|
|
||||||
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = dentry->d_fsdata;
|
struct kernfs_node *kn = kernfs_dentry_node(dentry);
|
||||||
struct kernfs_iattrs *attrs;
|
struct kernfs_iattrs *attrs;
|
||||||
|
|
||||||
attrs = kernfs_iattrs(kn);
|
attrs = kernfs_iattrs(kn);
|
||||||
|
@ -203,8 +203,8 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
|
||||||
int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
|
int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
|
||||||
u32 request_mask, unsigned int query_flags)
|
u32 request_mask, unsigned int query_flags)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = path->dentry->d_fsdata;
|
|
||||||
struct inode *inode = d_inode(path->dentry);
|
struct inode *inode = d_inode(path->dentry);
|
||||||
|
struct kernfs_node *kn = inode->i_private;
|
||||||
|
|
||||||
mutex_lock(&kernfs_mutex);
|
mutex_lock(&kernfs_mutex);
|
||||||
kernfs_refresh_inode(kn, inode);
|
kernfs_refresh_inode(kn, inode);
|
||||||
|
|
|
@ -70,6 +70,13 @@ struct kernfs_super_info {
|
||||||
};
|
};
|
||||||
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
|
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
|
||||||
|
|
||||||
|
static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry)
|
||||||
|
{
|
||||||
|
if (d_really_is_negative(dentry))
|
||||||
|
return NULL;
|
||||||
|
return d_inode(dentry)->i_private;
|
||||||
|
}
|
||||||
|
|
||||||
extern const struct super_operations kernfs_sops;
|
extern const struct super_operations kernfs_sops;
|
||||||
extern struct kmem_cache *kernfs_node_cache;
|
extern struct kmem_cache *kernfs_node_cache;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ static int kernfs_sop_remount_fs(struct super_block *sb, int *flags, char *data)
|
||||||
|
|
||||||
static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
|
static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct kernfs_root *root = kernfs_root(dentry->d_fsdata);
|
struct kernfs_root *root = kernfs_root(kernfs_dentry_node(dentry));
|
||||||
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
||||||
|
|
||||||
if (scops && scops->show_options)
|
if (scops && scops->show_options)
|
||||||
|
@ -43,7 +43,7 @@ static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
|
||||||
|
|
||||||
static int kernfs_sop_show_path(struct seq_file *sf, struct dentry *dentry)
|
static int kernfs_sop_show_path(struct seq_file *sf, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct kernfs_node *node = dentry->d_fsdata;
|
struct kernfs_node *node = kernfs_dentry_node(dentry);
|
||||||
struct kernfs_root *root = kernfs_root(node);
|
struct kernfs_root *root = kernfs_root(node);
|
||||||
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
||||||
|
|
||||||
|
@ -176,8 +176,6 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
||||||
pr_debug("%s: could not get root dentry!\n", __func__);
|
pr_debug("%s: could not get root dentry!\n", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
kernfs_get(info->root->kn);
|
|
||||||
root->d_fsdata = info->root->kn;
|
|
||||||
sb->s_root = root;
|
sb->s_root = root;
|
||||||
sb->s_d_op = &kernfs_dops;
|
sb->s_d_op = &kernfs_dops;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -283,7 +281,6 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
||||||
void kernfs_kill_sb(struct super_block *sb)
|
void kernfs_kill_sb(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct kernfs_super_info *info = kernfs_info(sb);
|
struct kernfs_super_info *info = kernfs_info(sb);
|
||||||
struct kernfs_node *root_kn = sb->s_root->d_fsdata;
|
|
||||||
|
|
||||||
mutex_lock(&kernfs_mutex);
|
mutex_lock(&kernfs_mutex);
|
||||||
list_del(&info->node);
|
list_del(&info->node);
|
||||||
|
@ -295,7 +292,6 @@ void kernfs_kill_sb(struct super_block *sb)
|
||||||
*/
|
*/
|
||||||
kill_anon_super(sb);
|
kill_anon_super(sb);
|
||||||
kfree(info);
|
kfree(info);
|
||||||
kernfs_put(root_kn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -98,9 +98,9 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kernfs_getlink(struct dentry *dentry, char *path)
|
static int kernfs_getlink(struct inode *inode, char *path)
|
||||||
{
|
{
|
||||||
struct kernfs_node *kn = dentry->d_fsdata;
|
struct kernfs_node *kn = inode->i_private;
|
||||||
struct kernfs_node *parent = kn->parent;
|
struct kernfs_node *parent = kn->parent;
|
||||||
struct kernfs_node *target = kn->symlink.target_kn;
|
struct kernfs_node *target = kn->symlink.target_kn;
|
||||||
int error;
|
int error;
|
||||||
|
@ -124,7 +124,7 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
|
||||||
body = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
body = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||||
if (!body)
|
if (!body)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
error = kernfs_getlink(dentry, body);
|
error = kernfs_getlink(inode, body);
|
||||||
if (unlikely(error < 0)) {
|
if (unlikely(error < 0)) {
|
||||||
kfree(body);
|
kfree(body);
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
|
|
Loading…
Reference in New Issue