diff options
author | Gabriel Krisman Bertazi <krisman@collabora.com> | 2019-06-19 23:45:09 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2019-06-19 23:45:09 -0400 |
commit | 3ae72562ad917df36a1b1247d749240e3b4865db (patch) | |
tree | c458ce5abc17452b19e2ecc06ce7d46841d5ec63 /fs/ext4/ext4.h | |
parent | b03755ad6f33b7b8cd7312a3596a2dbf496de6e7 (diff) |
ext4: optimize case-insensitive lookups
Temporarily cache a casefolded version of the file name under lookup in
ext4_filename, to avoid repeatedly casefolding it. I got up to 30%
speedup on lookups of large directories (>100k entries), depending on
the length of the string under lookup.
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/ext4.h')
-rw-r--r-- | fs/ext4/ext4.h | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ceb74093e138..7215a2a2a0de 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2078,6 +2078,9 @@ struct ext4_filename { | |||
2078 | #ifdef CONFIG_FS_ENCRYPTION | 2078 | #ifdef CONFIG_FS_ENCRYPTION |
2079 | struct fscrypt_str crypto_buf; | 2079 | struct fscrypt_str crypto_buf; |
2080 | #endif | 2080 | #endif |
2081 | #ifdef CONFIG_UNICODE | ||
2082 | struct fscrypt_str cf_name; | ||
2083 | #endif | ||
2081 | }; | 2084 | }; |
2082 | 2085 | ||
2083 | #define fname_name(p) ((p)->disk_name.name) | 2086 | #define fname_name(p) ((p)->disk_name.name) |
@@ -2303,6 +2306,12 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb, | |||
2303 | struct ext4_group_desc *gdp); | 2306 | struct ext4_group_desc *gdp); |
2304 | ext4_fsblk_t ext4_inode_to_goal_block(struct inode *); | 2307 | ext4_fsblk_t ext4_inode_to_goal_block(struct inode *); |
2305 | 2308 | ||
2309 | #ifdef CONFIG_UNICODE | ||
2310 | extern void ext4_fname_setup_ci_filename(struct inode *dir, | ||
2311 | const struct qstr *iname, | ||
2312 | struct fscrypt_str *fname); | ||
2313 | #endif | ||
2314 | |||
2306 | #ifdef CONFIG_FS_ENCRYPTION | 2315 | #ifdef CONFIG_FS_ENCRYPTION |
2307 | static inline void ext4_fname_from_fscrypt_name(struct ext4_filename *dst, | 2316 | static inline void ext4_fname_from_fscrypt_name(struct ext4_filename *dst, |
2308 | const struct fscrypt_name *src) | 2317 | const struct fscrypt_name *src) |
@@ -2329,6 +2338,10 @@ static inline int ext4_fname_setup_filename(struct inode *dir, | |||
2329 | return err; | 2338 | return err; |
2330 | 2339 | ||
2331 | ext4_fname_from_fscrypt_name(fname, &name); | 2340 | ext4_fname_from_fscrypt_name(fname, &name); |
2341 | |||
2342 | #ifdef CONFIG_UNICODE | ||
2343 | ext4_fname_setup_ci_filename(dir, iname, &fname->cf_name); | ||
2344 | #endif | ||
2332 | return 0; | 2345 | return 0; |
2333 | } | 2346 | } |
2334 | 2347 | ||
@@ -2344,6 +2357,10 @@ static inline int ext4_fname_prepare_lookup(struct inode *dir, | |||
2344 | return err; | 2357 | return err; |
2345 | 2358 | ||
2346 | ext4_fname_from_fscrypt_name(fname, &name); | 2359 | ext4_fname_from_fscrypt_name(fname, &name); |
2360 | |||
2361 | #ifdef CONFIG_UNICODE | ||
2362 | ext4_fname_setup_ci_filename(dir, &dentry->d_name, &fname->cf_name); | ||
2363 | #endif | ||
2347 | return 0; | 2364 | return 0; |
2348 | } | 2365 | } |
2349 | 2366 | ||
@@ -2357,6 +2374,11 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) | |||
2357 | fname->crypto_buf.name = NULL; | 2374 | fname->crypto_buf.name = NULL; |
2358 | fname->usr_fname = NULL; | 2375 | fname->usr_fname = NULL; |
2359 | fname->disk_name.name = NULL; | 2376 | fname->disk_name.name = NULL; |
2377 | |||
2378 | #ifdef CONFIG_UNICODE | ||
2379 | kfree(fname->cf_name.name); | ||
2380 | fname->cf_name.name = NULL; | ||
2381 | #endif | ||
2360 | } | 2382 | } |
2361 | #else /* !CONFIG_FS_ENCRYPTION */ | 2383 | #else /* !CONFIG_FS_ENCRYPTION */ |
2362 | static inline int ext4_fname_setup_filename(struct inode *dir, | 2384 | static inline int ext4_fname_setup_filename(struct inode *dir, |
@@ -2367,6 +2389,11 @@ static inline int ext4_fname_setup_filename(struct inode *dir, | |||
2367 | fname->usr_fname = iname; | 2389 | fname->usr_fname = iname; |
2368 | fname->disk_name.name = (unsigned char *) iname->name; | 2390 | fname->disk_name.name = (unsigned char *) iname->name; |
2369 | fname->disk_name.len = iname->len; | 2391 | fname->disk_name.len = iname->len; |
2392 | |||
2393 | #ifdef CONFIG_UNICODE | ||
2394 | ext4_fname_setup_ci_filename(dir, iname, &fname->cf_name); | ||
2395 | #endif | ||
2396 | |||
2370 | return 0; | 2397 | return 0; |
2371 | } | 2398 | } |
2372 | 2399 | ||
@@ -2377,7 +2404,13 @@ static inline int ext4_fname_prepare_lookup(struct inode *dir, | |||
2377 | return ext4_fname_setup_filename(dir, &dentry->d_name, 1, fname); | 2404 | return ext4_fname_setup_filename(dir, &dentry->d_name, 1, fname); |
2378 | } | 2405 | } |
2379 | 2406 | ||
2380 | static inline void ext4_fname_free_filename(struct ext4_filename *fname) { } | 2407 | static inline void ext4_fname_free_filename(struct ext4_filename *fname) |
2408 | { | ||
2409 | #ifdef CONFIG_UNICODE | ||
2410 | kfree(fname->cf_name.name); | ||
2411 | fname->cf_name.name = NULL; | ||
2412 | #endif | ||
2413 | } | ||
2381 | #endif /* !CONFIG_FS_ENCRYPTION */ | 2414 | #endif /* !CONFIG_FS_ENCRYPTION */ |
2382 | 2415 | ||
2383 | /* dir.c */ | 2416 | /* dir.c */ |
@@ -3120,8 +3153,8 @@ extern int ext4_handle_dirty_dirent_node(handle_t *handle, | |||
3120 | struct inode *inode, | 3153 | struct inode *inode, |
3121 | struct buffer_head *bh); | 3154 | struct buffer_head *bh); |
3122 | extern int ext4_ci_compare(const struct inode *parent, | 3155 | extern int ext4_ci_compare(const struct inode *parent, |
3123 | const struct qstr *name, | 3156 | const struct qstr *fname, |
3124 | const struct qstr *entry); | 3157 | const struct qstr *entry, bool quick); |
3125 | 3158 | ||
3126 | #define S_SHIFT 12 | 3159 | #define S_SHIFT 12 |
3127 | static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = { | 3160 | static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = { |