vfs: rename parent_ino to d_parent_ino and make it use RCU
The routine is used by procfs through dir_emit_dots. The combined RCU and lock fallback implementation is too big for an inline. Given that the routine takes a dentry argument fs/dcache.c seems like the place to put it in. Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> Link: https://lore.kernel.org/r/20240627161152.802567-1-mjguzik@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
0ef625bba6
commit
f378ec4eec
28
fs/dcache.c
28
fs/dcache.c
@ -3099,6 +3099,34 @@ void d_tmpfile(struct file *file, struct inode *inode)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(d_tmpfile);
|
EXPORT_SYMBOL(d_tmpfile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain inode number of the parent dentry.
|
||||||
|
*/
|
||||||
|
ino_t d_parent_ino(struct dentry *dentry)
|
||||||
|
{
|
||||||
|
struct dentry *parent;
|
||||||
|
struct inode *iparent;
|
||||||
|
unsigned seq;
|
||||||
|
ino_t ret;
|
||||||
|
|
||||||
|
scoped_guard(rcu) {
|
||||||
|
seq = raw_seqcount_begin(&dentry->d_seq);
|
||||||
|
parent = READ_ONCE(dentry->d_parent);
|
||||||
|
iparent = d_inode_rcu(parent);
|
||||||
|
if (likely(iparent)) {
|
||||||
|
ret = iparent->i_ino;
|
||||||
|
if (!read_seqcount_retry(&dentry->d_seq, seq))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock(&dentry->d_lock);
|
||||||
|
ret = dentry->d_parent->d_inode->i_ino;
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(d_parent_ino);
|
||||||
|
|
||||||
static __initdata unsigned long dhash_entries;
|
static __initdata unsigned long dhash_entries;
|
||||||
static int __init set_dhash_entries(char *str)
|
static int __init set_dhash_entries(char *str)
|
||||||
{
|
{
|
||||||
|
@ -185,7 +185,7 @@ static int get_parent_ino(struct inode *inode, nid_t *pino)
|
|||||||
if (!dentry)
|
if (!dentry)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*pino = parent_ino(dentry);
|
*pino = d_parent_ino(dentry);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
|
|||||||
|
|
||||||
/* Directory containing the bootable system */
|
/* Directory containing the bootable system */
|
||||||
vh->finder_info[0] = bvh->finder_info[0] =
|
vh->finder_info[0] = bvh->finder_info[0] =
|
||||||
cpu_to_be32(parent_ino(dentry));
|
cpu_to_be32(d_parent_ino(dentry));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bootloader. Just using the inode here breaks in the case of
|
* Bootloader. Just using the inode here breaks in the case of
|
||||||
@ -51,7 +51,7 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
|
|||||||
|
|
||||||
/* Per spec, the OS X system folder - same as finder_info[0] here */
|
/* Per spec, the OS X system folder - same as finder_info[0] here */
|
||||||
vh->finder_info[5] = bvh->finder_info[5] =
|
vh->finder_info[5] = bvh->finder_info[5] =
|
||||||
cpu_to_be32(parent_ino(dentry));
|
cpu_to_be32(d_parent_ino(dentry));
|
||||||
|
|
||||||
mutex_unlock(&sbi->vh_mutex);
|
mutex_unlock(&sbi->vh_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -278,6 +278,8 @@ static inline unsigned d_count(const struct dentry *dentry)
|
|||||||
return dentry->d_lockref.count;
|
return dentry->d_lockref.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ino_t d_parent_ino(struct dentry *dentry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* helper function for dentry_operations.d_dname() members
|
* helper function for dentry_operations.d_dname() members
|
||||||
*/
|
*/
|
||||||
|
@ -3454,20 +3454,6 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ino_t parent_ino(struct dentry *dentry)
|
|
||||||
{
|
|
||||||
ino_t res;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't strictly need d_lock here? If the parent ino could change
|
|
||||||
* then surely we'd have a deeper race in the caller?
|
|
||||||
*/
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
res = dentry->d_parent->d_inode->i_ino;
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transaction based IO helpers */
|
/* Transaction based IO helpers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3592,7 +3578,7 @@ static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
|
|||||||
static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
|
static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
|
||||||
{
|
{
|
||||||
return ctx->actor(ctx, "..", 2, ctx->pos,
|
return ctx->actor(ctx, "..", 2, ctx->pos,
|
||||||
parent_ino(file->f_path.dentry), DT_DIR);
|
d_parent_ino(file->f_path.dentry), DT_DIR);
|
||||||
}
|
}
|
||||||
static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx)
|
static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user