... so that they can be copied with struct assignment (which generates better code) and accessed word-by-word. swap_names() used to do the latter already, using casts, etc.; now that can be done cleanly. Both dentry->d_iname and name_snapshot->inline_name got such treatment. Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- fs/dcache.c | 19 +++++++------------ include/linux/dcache.h | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index ea0f0bea511b..007e582c3e68 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -334,8 +334,7 @@ void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry if (unlikely(dname_external(dentry))) { atomic_inc(&external_name(dentry)->u.count); } else { - memcpy(name->inline_name, dentry->d_iname, - dentry->d_name.len + 1); + name->inline_name_words = dentry->d_iname_words; name->name.name = name->inline_name; } spin_unlock(&dentry->d_lock); @@ -2729,9 +2728,8 @@ static void swap_names(struct dentry *dentry, struct dentry *target) * dentry:internal, target:external. Steal target's * storage and make target internal. */ - memcpy(target->d_iname, dentry->d_name.name, - dentry->d_name.len + 1); dentry->d_name.name = target->d_name.name; + target->d_iname_words = dentry->d_iname_words; target->d_name.name = target->d_iname; } } else { @@ -2740,18 +2738,16 @@ static void swap_names(struct dentry *dentry, struct dentry *target) * dentry:external, target:internal. Give dentry's * storage to target and make dentry internal */ - memcpy(dentry->d_iname, target->d_name.name, - target->d_name.len + 1); target->d_name.name = dentry->d_name.name; + dentry->d_iname_words = target->d_iname_words; dentry->d_name.name = dentry->d_iname; } else { /* * Both are internal. */ - for (int i = 0; i < DNAME_INLINE_WORDS; i++) { - swap(((long *) &dentry->d_iname)[i], - ((long *) &target->d_iname)[i]); - } + for (int i = 0; i < DNAME_INLINE_WORDS; i++) + swap(dentry->d_iname_words.words[i], + target->d_iname_words.words[i]); } } swap(dentry->d_name.hash_len, target->d_name.hash_len); @@ -2766,8 +2762,7 @@ static void copy_name(struct dentry *dentry, struct dentry *target) atomic_inc(&external_name(target)->u.count); dentry->d_name = target->d_name; } else { - memcpy(dentry->d_iname, target->d_name.name, - target->d_name.len + 1); + dentry->d_iname_words = target->d_iname_words; dentry->d_name.name = dentry->d_iname; dentry->d_name.hash_len = target->d_name.hash_len; } diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 42dd89beaf4e..766a9156836e 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -79,6 +79,10 @@ extern const struct qstr dotdot_name; #define DNAME_INLINE_LEN (DNAME_INLINE_WORDS*sizeof(unsigned long)) +struct shortname_store { + unsigned long words[DNAME_INLINE_WORDS]; +}; + #define d_lock d_lockref.lock struct dentry { @@ -90,7 +94,10 @@ struct dentry { struct qstr d_name; struct inode *d_inode; /* Where the name belongs to - NULL is * negative */ - unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ + union { + unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ + struct shortname_store d_iname_words; + }; /* --- cacheline 1 boundary (64 bytes) was 32 bytes ago --- */ /* Ref lookup also touches following */ @@ -591,7 +598,10 @@ static inline struct inode *d_real_inode(const struct dentry *dentry) struct name_snapshot { struct qstr name; - unsigned char inline_name[DNAME_INLINE_LEN]; + union { + unsigned char inline_name[DNAME_INLINE_LEN]; + struct shortname_store inline_name_words; + }; }; void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *); void release_dentry_name_snapshot(struct name_snapshot *); -- 2.39.5