Implement the main msdos_format_name() filename cache. If used as a module, all memory allocated for the cache is freed when the module is de-registered. Signed-off-by: Caleb D.S. Brzezinski <calebdsb@xxxxxxxxxxxxxx> --- fs/fat/namei_msdos.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 7561674b1..f9d4f63c3 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -124,6 +124,16 @@ static int msdos_format_name(const unsigned char *name, int len, unsigned char *walk; unsigned char c; int space; + u64 hash; + struct msdos_name_node *node; + + /* check if the name is already in the cache */ + + hash = msdos_fname_hash(name); + if (find_fname_in_cache(res, hash)) + return 0; + + /* The node wasn't in the cache, so format it normally */ if (name[0] == '.') { /* dotfile because . and .. already done */ if (opts->dotsOK) { @@ -208,6 +218,18 @@ static int msdos_format_name(const unsigned char *name, int len, while (walk - res < MSDOS_NAME) *walk++ = ' '; + /* allocate memory now */ + node = kmalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + /* fill in the name cache */ + node->hash = hash; + strscpy(node->fname, res, 9); + mutex_lock(&msdos_ncache_mutex); + hash_add(msdos_ncache, &node->h_list, node->hash); + mutex_unlock(&msdos_ncache_mutex); + return 0; } @@ -677,6 +699,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, * shouldn't be serious corruption. */ int err2 = fat_remove_entries(new_dir, &sinfo); + if (corrupt) corrupt |= err2; sinfo.bh = NULL; @@ -774,6 +797,18 @@ static int __init init_msdos_fs(void) static void __exit exit_msdos_fs(void) { + int bkt; + struct msdos_name_node *c, *prev; + + prev = NULL; + /* do this one behind to prevent bad memory access */ + hash_for_each(msdos_ncache, bkt, c, h_list) { + kfree(prev); + prev = c; + } + + kfree(prev); + unregister_filesystem(&msdos_fs_type); } -- 2.32.0