From: "leilei.lin" <leilei.lin@xxxxxxxxxxxxxxx> locklessly and integrally copy dentry name. It will be used later for bugfix Signed-off-by: leilei.lin <leilei.lin@xxxxxxxxxxxxxxx> --- fs/dcache.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/dcache.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index 95d71ed..056249b 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -3536,6 +3536,44 @@ void d_tmpfile(struct dentry *dentry, struct inode *inode) } EXPORT_SYMBOL(d_tmpfile); +int copy_dname(struct dentry *dentry, char **name) +{ + unsigned int seq; + const char *dname; + + /* in case that dentry was being free */ + rcu_read_lock(); + + dname = dentry->d_name.name; + + if (unlikely(!dname)) { + rcu_read_unlock(); + return 0; + } + + if (unlikely(dname != dentry->d_iname)) { + *name = kstrdup(dname, GFP_ATOMIC); + rcu_read_unlock(); + if (unlikely(!*name)) + return -ENOMEM; + + return 0; + } + + rcu_read_unlock(); + *name = kmalloc(DNAME_INLINE_LEN, GFP_KERNEL); + if (unlikely(!*name)) + return -ENOMEM; + + do { + seq = read_seqcount_begin(&dentry->d_seq); + strcpy(*name, dname); + } while (read_seqcount_retry(&dentry->d_seq, seq)); + + return 0; +} +EXPORT_SYMBOL(copy_dname); + static __initdata unsigned long dhash_entries; static int __init set_dhash_entries(char *str) { diff --git a/include/linux/dcache.h b/include/linux/dcache.h index d2e38dc..a1b2aeb 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -296,6 +296,8 @@ extern char *d_path(const struct path *, char *, int); extern char *dentry_path_raw(struct dentry *, char *, int); extern char *dentry_path(struct dentry *, char *, int); +extern int copy_dname(struct dentry *dentry, char **name); + /* Allocation counts.. */ /** -- 2.8.4.31.g9ed660f