Skip to content

Commit 7d28684

Browse files
committed
vfs: link_path_walk: simplify name hash flow
This is one of those hot functions in path walking, and it's doing things in just the wrong order that causes slightly unnecessary extra work. Move the name pointer update and the setting of 'nd->last' up a bit, so that the (unlikely) filesystem-specific hashing can run on them in place, instead of having to set up a copy on the stack and copy things back and forth. Because even when the hashing is not run, it causes the stack frame of the function to be bigger to hold the unnecessary temporary copy. This also means that we never then reference the full "hashlen" field after calculating it, and can clarify the code with just using the length part. Signed-off-by: Linus Torvalds <[email protected]>
1 parent 6ba59ff commit 7d28684

File tree

1 file changed

+13
-16
lines changed

1 file changed

+13
-16
lines changed

fs/namei.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,45 +2266,42 @@ static int link_path_walk(const char *name, struct nameidata *nd)
22662266
for(;;) {
22672267
struct mnt_idmap *idmap;
22682268
const char *link;
2269-
u64 hash_len;
2269+
unsigned int len;
22702270
int type;
22712271

22722272
idmap = mnt_idmap(nd->path.mnt);
22732273
err = may_lookup(idmap, nd);
22742274
if (err)
22752275
return err;
22762276

2277-
hash_len = hash_name(nd->path.dentry, name);
2277+
nd->last.name = name;
2278+
nd->last.hash_len = hash_name(nd->path.dentry, name);
2279+
len = hashlen_len(nd->last.hash_len);
2280+
name += len;
22782281

22792282
type = LAST_NORM;
2280-
if (name[0] == '.') switch (hashlen_len(hash_len)) {
2281-
case 2:
2282-
if (name[1] == '.') {
2283+
/* We know len is at least 1, so compare against 2 */
2284+
if (len <= 2 && name[-1] == '.') {
2285+
if (len == 2) {
2286+
if (name[-2] == '.') {
22832287
type = LAST_DOTDOT;
22842288
nd->state |= ND_JUMPED;
22852289
}
2286-
break;
2287-
case 1:
2290+
} else {
22882291
type = LAST_DOT;
2292+
}
22892293
}
2294+
nd->last_type = type;
22902295
if (likely(type == LAST_NORM)) {
22912296
struct dentry *parent = nd->path.dentry;
22922297
nd->state &= ~ND_JUMPED;
22932298
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
2294-
struct qstr this = { { .hash_len = hash_len }, .name = name };
2295-
err = parent->d_op->d_hash(parent, &this);
2299+
err = parent->d_op->d_hash(parent, &nd->last);
22962300
if (err < 0)
22972301
return err;
2298-
hash_len = this.hash_len;
2299-
name = this.name;
23002302
}
23012303
}
23022304

2303-
nd->last.hash_len = hash_len;
2304-
nd->last.name = name;
2305-
nd->last_type = type;
2306-
2307-
name += hashlen_len(hash_len);
23082305
if (!*name)
23092306
goto OK;
23102307
/*

0 commit comments

Comments
 (0)