Skip to content

Commit 95a4ccb

Browse files
author
Al Viro
committed
dissolve external_name.u into separate members
... and document the constraints on the layout. Kept separate from the previous commit to keep the noise separate from actual changes. The reason for explicit __aligned() on ->name[] rather than relying upon the alignment of the previous field is that the previous iteration of that commit tried to save 4 bytes on 64bit by eliminating a hole in there, which broke the assumptions in dentry_string_cmp(). Better spell it out and avoid the temptation for the future... Reviewed-by: Jeff Layton <[email protected]> Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 1c9be84 commit 95a4ccb

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

fs/dcache.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,16 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c
295295
return dentry_string_cmp(cs, ct, tcount);
296296
}
297297

298+
/*
299+
* long names are allocated separately from dentry and never modified.
300+
* Refcounted, freeing is RCU-delayed. See take_dentry_name_snapshot()
301+
* for the reason why ->count and ->head can't be combined into a union.
302+
* dentry_string_cmp() relies upon ->name[] being word-aligned.
303+
*/
298304
struct external_name {
299-
struct {
300-
atomic_t count; // ->count and ->head can't be combined
301-
struct rcu_head head; // see take_dentry_name_snapshot()
302-
} u;
303-
unsigned char name[];
305+
atomic_t count;
306+
struct rcu_head head;
307+
unsigned char name[] __aligned(sizeof(unsigned long));
304308
};
305309

306310
static inline struct external_name *external_name(struct dentry *dentry)
@@ -344,7 +348,7 @@ void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry
344348
struct external_name *p;
345349
p = container_of(s, struct external_name, name[0]);
346350
// get a valid reference
347-
if (unlikely(!atomic_inc_not_zero(&p->u.count)))
351+
if (unlikely(!atomic_inc_not_zero(&p->count)))
348352
goto retry;
349353
name->name.name = s;
350354
}
@@ -361,8 +365,8 @@ void release_dentry_name_snapshot(struct name_snapshot *name)
361365
if (unlikely(name->name.name != name->inline_name.string)) {
362366
struct external_name *p;
363367
p = container_of(name->name.name, struct external_name, name[0]);
364-
if (unlikely(atomic_dec_and_test(&p->u.count)))
365-
kfree_rcu(p, u.head);
368+
if (unlikely(atomic_dec_and_test(&p->count)))
369+
kfree_rcu(p, head);
366370
}
367371
}
368372
EXPORT_SYMBOL(release_dentry_name_snapshot);
@@ -400,7 +404,7 @@ static void dentry_free(struct dentry *dentry)
400404
WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
401405
if (unlikely(dname_external(dentry))) {
402406
struct external_name *p = external_name(dentry);
403-
if (likely(atomic_dec_and_test(&p->u.count))) {
407+
if (likely(atomic_dec_and_test(&p->count))) {
404408
call_rcu(&dentry->d_u.d_rcu, __d_free_external);
405409
return;
406410
}
@@ -1681,7 +1685,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
16811685
kmem_cache_free(dentry_cache, dentry);
16821686
return NULL;
16831687
}
1684-
atomic_set(&p->u.count, 1);
1688+
atomic_set(&p->count, 1);
16851689
dname = p->name;
16861690
} else {
16871691
dname = dentry->d_shortname.string;
@@ -2774,15 +2778,15 @@ static void copy_name(struct dentry *dentry, struct dentry *target)
27742778
if (unlikely(dname_external(dentry)))
27752779
old_name = external_name(dentry);
27762780
if (unlikely(dname_external(target))) {
2777-
atomic_inc(&external_name(target)->u.count);
2781+
atomic_inc(&external_name(target)->count);
27782782
dentry->d_name = target->d_name;
27792783
} else {
27802784
dentry->d_shortname = target->d_shortname;
27812785
dentry->d_name.name = dentry->d_shortname.string;
27822786
dentry->d_name.hash_len = target->d_name.hash_len;
27832787
}
2784-
if (old_name && likely(atomic_dec_and_test(&old_name->u.count)))
2785-
kfree_rcu(old_name, u.head);
2788+
if (old_name && likely(atomic_dec_and_test(&old_name->count)))
2789+
kfree_rcu(old_name, head);
27862790
}
27872791

27882792
/*

0 commit comments

Comments
 (0)