Skip to content

Commit 58cf9c3

Browse files
author
Al Viro
committed
dcache: back inline names with a struct-wrapped array of unsigned long
... so that they can be copied with struct assignment (which generates better code) and accessed word-by-word. The type is union shortname_storage; it's a union of arrays of unsigned char and unsigned long. struct name_snapshot.inline_name turned into union shortname_storage; users (all in fs/dcache.c) adjusted. struct dentry.d_iname has some users outside of fs/dcache.c; to reduce the amount of noise in commit, it is replaced with union shortname_storage d_shortname and d_iname is turned into a macro that expands to d_shortname.string (similar to d_lock handling). That compat macro is temporary - most of the remaining instances will be taken out by debugfs series, and once that is merged and few others are taken care of this will go away. Reviewed-by: Jeff Layton <[email protected]> Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 61bc24a commit 58cf9c3

File tree

3 files changed

+28
-27
lines changed

3 files changed

+28
-27
lines changed

fs/dcache.c

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static void __d_free_external(struct rcu_head *head)
324324

325325
static inline int dname_external(const struct dentry *dentry)
326326
{
327-
return dentry->d_name.name != dentry->d_iname;
327+
return dentry->d_name.name != dentry->d_shortname.string;
328328
}
329329

330330
void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry)
@@ -334,17 +334,16 @@ void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry
334334
if (unlikely(dname_external(dentry))) {
335335
atomic_inc(&external_name(dentry)->u.count);
336336
} else {
337-
memcpy(name->inline_name, dentry->d_iname,
338-
dentry->d_name.len + 1);
339-
name->name.name = name->inline_name;
337+
name->inline_name = dentry->d_shortname;
338+
name->name.name = name->inline_name.string;
340339
}
341340
spin_unlock(&dentry->d_lock);
342341
}
343342
EXPORT_SYMBOL(take_dentry_name_snapshot);
344343

345344
void release_dentry_name_snapshot(struct name_snapshot *name)
346345
{
347-
if (unlikely(name->name.name != name->inline_name)) {
346+
if (unlikely(name->name.name != name->inline_name.string)) {
348347
struct external_name *p;
349348
p = container_of(name->name.name, struct external_name, name[0]);
350349
if (unlikely(atomic_dec_and_test(&p->u.count)))
@@ -1654,10 +1653,10 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
16541653
* will still always have a NUL at the end, even if we might
16551654
* be overwriting an internal NUL character
16561655
*/
1657-
dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
1656+
dentry->d_shortname.string[DNAME_INLINE_LEN-1] = 0;
16581657
if (unlikely(!name)) {
16591658
name = &slash_name;
1660-
dname = dentry->d_iname;
1659+
dname = dentry->d_shortname.string;
16611660
} else if (name->len > DNAME_INLINE_LEN-1) {
16621661
size_t size = offsetof(struct external_name, name[1]);
16631662
struct external_name *p = kmalloc(size + name->len,
@@ -1670,7 +1669,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
16701669
atomic_set(&p->u.count, 1);
16711670
dname = p->name;
16721671
} else {
1673-
dname = dentry->d_iname;
1672+
dname = dentry->d_shortname.string;
16741673
}
16751674

16761675
dentry->d_name.len = name->len;
@@ -2729,29 +2728,26 @@ static void swap_names(struct dentry *dentry, struct dentry *target)
27292728
* dentry:internal, target:external. Steal target's
27302729
* storage and make target internal.
27312730
*/
2732-
memcpy(target->d_iname, dentry->d_name.name,
2733-
dentry->d_name.len + 1);
27342731
dentry->d_name.name = target->d_name.name;
2735-
target->d_name.name = target->d_iname;
2732+
target->d_shortname = dentry->d_shortname;
2733+
target->d_name.name = target->d_shortname.string;
27362734
}
27372735
} else {
27382736
if (unlikely(dname_external(dentry))) {
27392737
/*
27402738
* dentry:external, target:internal. Give dentry's
27412739
* storage to target and make dentry internal
27422740
*/
2743-
memcpy(dentry->d_iname, target->d_name.name,
2744-
target->d_name.len + 1);
27452741
target->d_name.name = dentry->d_name.name;
2746-
dentry->d_name.name = dentry->d_iname;
2742+
dentry->d_shortname = target->d_shortname;
2743+
dentry->d_name.name = dentry->d_shortname.string;
27472744
} else {
27482745
/*
27492746
* Both are internal.
27502747
*/
2751-
for (int i = 0; i < DNAME_INLINE_WORDS; i++) {
2752-
swap(((long *) &dentry->d_iname)[i],
2753-
((long *) &target->d_iname)[i]);
2754-
}
2748+
for (int i = 0; i < DNAME_INLINE_WORDS; i++)
2749+
swap(dentry->d_shortname.words[i],
2750+
target->d_shortname.words[i]);
27552751
}
27562752
}
27572753
swap(dentry->d_name.hash_len, target->d_name.hash_len);
@@ -2766,9 +2762,8 @@ static void copy_name(struct dentry *dentry, struct dentry *target)
27662762
atomic_inc(&external_name(target)->u.count);
27672763
dentry->d_name = target->d_name;
27682764
} else {
2769-
memcpy(dentry->d_iname, target->d_name.name,
2770-
target->d_name.len + 1);
2771-
dentry->d_name.name = dentry->d_iname;
2765+
dentry->d_shortname = target->d_shortname;
2766+
dentry->d_name.name = dentry->d_shortname.string;
27722767
dentry->d_name.hash_len = target->d_name.hash_len;
27732768
}
27742769
if (old_name && likely(atomic_dec_and_test(&old_name->u.count)))
@@ -3101,12 +3096,12 @@ void d_mark_tmpfile(struct file *file, struct inode *inode)
31013096
{
31023097
struct dentry *dentry = file->f_path.dentry;
31033098

3104-
BUG_ON(dentry->d_name.name != dentry->d_iname ||
3099+
BUG_ON(dname_external(dentry) ||
31053100
!hlist_unhashed(&dentry->d_u.d_alias) ||
31063101
!d_unlinked(dentry));
31073102
spin_lock(&dentry->d_parent->d_lock);
31083103
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
3109-
dentry->d_name.len = sprintf(dentry->d_iname, "#%llu",
3104+
dentry->d_name.len = sprintf(dentry->d_shortname.string, "#%llu",
31103105
(unsigned long long)inode->i_ino);
31113106
spin_unlock(&dentry->d_lock);
31123107
spin_unlock(&dentry->d_parent->d_lock);
@@ -3194,7 +3189,7 @@ static void __init dcache_init(void)
31943189
*/
31953190
dentry_cache = KMEM_CACHE_USERCOPY(dentry,
31963191
SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_ACCOUNT,
3197-
d_iname);
3192+
d_shortname.string);
31983193

31993194
/* Hash may have been set up in dcache_init_early */
32003195
if (!hashdist)

include/linux/dcache.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ extern const struct qstr dotdot_name;
7979

8080
#define DNAME_INLINE_LEN (DNAME_INLINE_WORDS*sizeof(unsigned long))
8181

82+
union shortname_store {
83+
unsigned char string[DNAME_INLINE_LEN];
84+
unsigned long words[DNAME_INLINE_WORDS];
85+
};
86+
8287
#define d_lock d_lockref.lock
88+
#define d_iname d_shortname.string
8389

8490
struct dentry {
8591
/* RCU lookup touched fields */
@@ -90,7 +96,7 @@ struct dentry {
9096
struct qstr d_name;
9197
struct inode *d_inode; /* Where the name belongs to - NULL is
9298
* negative */
93-
unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
99+
union shortname_store d_shortname;
94100
/* --- cacheline 1 boundary (64 bytes) was 32 bytes ago --- */
95101

96102
/* Ref lookup also touches following */
@@ -591,7 +597,7 @@ static inline struct inode *d_real_inode(const struct dentry *dentry)
591597

592598
struct name_snapshot {
593599
struct qstr name;
594-
unsigned char inline_name[DNAME_INLINE_LEN];
600+
union shortname_store inline_name;
595601
};
596602
void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *);
597603
void release_dentry_name_snapshot(struct name_snapshot *);

tools/testing/selftests/bpf/progs/find_vma.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static long check_vma(struct task_struct *task, struct vm_area_struct *vma,
2525
{
2626
if (vma->vm_file)
2727
bpf_probe_read_kernel_str(d_iname, DNAME_INLINE_LEN - 1,
28-
vma->vm_file->f_path.dentry->d_iname);
28+
vma->vm_file->f_path.dentry->d_shortname.string);
2929

3030
/* check for VM_EXEC */
3131
if (vma->vm_flags & VM_EXEC)

0 commit comments

Comments
 (0)