diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index e62ab839d165..94a353a617e7 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2406,9 +2406,9 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb, ext4_fsblk_t ext4_inode_to_goal_block(struct inode *); #ifdef CONFIG_UNICODE -extern int ext4_fname_setup_ci_filename(struct inode *dir, +extern void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, - struct ext4_filename *fname); + struct fscrypt_str *fname); #endif #ifdef CONFIG_FS_ENCRYPTION @@ -2439,9 +2439,9 @@ static inline int ext4_fname_setup_filename(struct inode *dir, ext4_fname_from_fscrypt_name(fname, &name); #ifdef CONFIG_UNICODE - err = ext4_fname_setup_ci_filename(dir, iname, fname); + ext4_fname_setup_ci_filename(dir, iname, &fname->cf_name); #endif - return err; + return 0; } static inline int ext4_fname_prepare_lookup(struct inode *dir, @@ -2458,9 +2458,9 @@ static inline int ext4_fname_prepare_lookup(struct inode *dir, ext4_fname_from_fscrypt_name(fname, &name); #ifdef CONFIG_UNICODE - err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname); + ext4_fname_setup_ci_filename(dir, &dentry->d_name, &fname->cf_name); #endif - return err; + return 0; } static inline void ext4_fname_free_filename(struct ext4_filename *fname) @@ -2485,16 +2485,15 @@ static inline int ext4_fname_setup_filename(struct inode *dir, int lookup, struct ext4_filename *fname) { - int err = 0; fname->usr_fname = iname; fname->disk_name.name = (unsigned char *) iname->name; fname->disk_name.len = iname->len; #ifdef CONFIG_UNICODE - err = ext4_fname_setup_ci_filename(dir, iname, fname); + ext4_fname_setup_ci_filename(dir, iname, &fname->cf_name); #endif - return err; + return 0; } static inline int ext4_fname_prepare_lookup(struct inode *dir, diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 7b7f1e40c1e9..95d3d38b145d 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -799,9 +799,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir, if (hinfo->hash_version <= DX_HASH_TEA) hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; - /* hash is already computed for encrypted casefolded directory */ - if (fname && fname_name(fname) && - !(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir))) + if (fname && fname_name(fname)) ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), hinfo); hash = hinfo->hash; @@ -1383,21 +1381,19 @@ out: return ret; } -int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, - struct ext4_filename *name) +void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, + struct fscrypt_str *cf_name) { - struct fscrypt_str *cf_name = &name->cf_name; - struct dx_hash_info *hinfo = &name->hinfo; int len; if (!needs_casefold(dir)) { cf_name->name = NULL; - return 0; + return; } cf_name->name = kmalloc(EXT4_NAME_LEN, GFP_NOFS); if (!cf_name->name) - return -ENOMEM; + return; len = utf8_casefold(dir->i_sb->s_encoding, iname, cf_name->name, @@ -1405,18 +1401,10 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, if (len <= 0) { kfree(cf_name->name); cf_name->name = NULL; + return; } cf_name->len = (unsigned) len; - if (!IS_ENCRYPTED(dir)) - return 0; - hinfo->hash_version = DX_HASH_SIPHASH; - hinfo->seed = NULL; - if (cf_name->name) - ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo); - else - ext4fs_dirhash(dir, iname->name, iname->len, hinfo); - return 0; } #endif @@ -1446,12 +1434,16 @@ static bool ext4_match(struct inode *parent, struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len}; if (IS_ENCRYPTED(parent)) { - if (fname->hinfo.hash != EXT4_DIRENT_HASH(de) || - fname->hinfo.minor_hash != - EXT4_DIRENT_MINOR_HASH(de)) { + struct dx_hash_info hinfo; + hinfo.hash_version = DX_HASH_SIPHASH; + hinfo.seed = NULL; + ext4fs_dirhash(parent, fname->cf_name.name, + fname_len(fname), &hinfo); + if (hinfo.hash != EXT4_DIRENT_HASH(de) || + hinfo.minor_hash != + EXT4_DIRENT_MINOR_HASH(de)) return 0; - } } return !ext4_ci_compare(parent, &cf, de->name, de->name_len, true); @@ -2086,11 +2078,15 @@ void ext4_insert_dentry(struct inode *dir, de->name_len = fname_len(fname); memcpy(de->name, fname_name(fname), fname_len(fname)); if (ext4_hash_in_dirent(dir)) { - struct dx_hash_info *hinfo = &fname->hinfo; + struct dx_hash_info hinfo; - EXT4_DIRENT_HASHES(de)->hash = cpu_to_le32(hinfo->hash); + hinfo.hash_version = DX_HASH_SIPHASH; + hinfo.seed = NULL; + ext4fs_dirhash(dir, fname_usr_name(fname), + fname_len(fname), &hinfo); + EXT4_DIRENT_HASHES(de)->hash = cpu_to_le32(hinfo.hash); EXT4_DIRENT_HASHES(de)->minor_hash = - cpu_to_le32(hinfo->minor_hash); + cpu_to_le32(hinfo.minor_hash); } } @@ -2241,9 +2237,10 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname, if (fname->hinfo.hash_version <= DX_HASH_TEA) fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; - - /* casefolded encrypted hashes are computed on fname setup */ - if (!ext4_hash_in_dirent(dir)) + if (ext4_hash_in_dirent(dir)) + ext4fs_dirhash(dir, fname_usr_name(fname), + fname_len(fname), &fname->hinfo); + else ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), &fname->hinfo);