Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'vfs-6.11.casefold' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs casefolding updates from Christian Brauner:
"This contains some work to simplify the handling of casefolded names:

- Simplify the handling of casefolded names in f2fs and ext4 by
keeping the names as a qstr to avoiding unnecessary conversions

- Introduce a new generic_ci_match() libfs case-insensitive lookup
helper and use it in both f2fs and ext4 allowing to remove the
filesystem specific implementations

- Remove a bunch of ifdefs by making the unicode build checks part of
the code flow"

* tag 'vfs-6.11.casefold' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
f2fs: Move CONFIG_UNICODE defguards into the code flow
ext4: Move CONFIG_UNICODE defguards into the code flow
f2fs: Reuse generic_ci_match for ci comparisons
ext4: Reuse generic_ci_match for ci comparisons
libfs: Introduce case-insensitive string comparison helper
f2fs: Simplify the handling of cached casefolded names
ext4: Simplify the handling of cached casefolded names

+194 -201
+2 -8
fs/ext4/crypto.c
··· 31 31 32 32 ext4_fname_from_fscrypt_name(fname, &name); 33 33 34 - #if IS_ENABLED(CONFIG_UNICODE) 35 34 err = ext4_fname_setup_ci_filename(dir, iname, fname); 36 35 if (err) 37 36 ext4_fname_free_filename(fname); 38 - #endif 37 + 39 38 return err; 40 39 } 41 40 ··· 50 51 51 52 ext4_fname_from_fscrypt_name(fname, &name); 52 53 53 - #if IS_ENABLED(CONFIG_UNICODE) 54 54 err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname); 55 55 if (err) 56 56 ext4_fname_free_filename(fname); 57 - #endif 58 57 return err; 59 58 } 60 59 ··· 67 70 fname->usr_fname = NULL; 68 71 fname->disk_name.name = NULL; 69 72 70 - #if IS_ENABLED(CONFIG_UNICODE) 71 - kfree(fname->cf_name.name); 72 - fname->cf_name.name = NULL; 73 - #endif 73 + ext4_fname_free_ci_filename(fname); 74 74 } 75 75 76 76 static bool uuid_is_zero(__u8 u[16])
+22 -13
fs/ext4/ext4.h
··· 2511 2511 struct fscrypt_str crypto_buf; 2512 2512 #endif 2513 2513 #if IS_ENABLED(CONFIG_UNICODE) 2514 - struct fscrypt_str cf_name; 2514 + struct qstr cf_name; 2515 2515 #endif 2516 2516 }; 2517 2517 ··· 2745 2745 2746 2746 #if IS_ENABLED(CONFIG_UNICODE) 2747 2747 extern int ext4_fname_setup_ci_filename(struct inode *dir, 2748 - const struct qstr *iname, 2749 - struct ext4_filename *fname); 2748 + const struct qstr *iname, 2749 + struct ext4_filename *fname); 2750 + 2751 + static inline void ext4_fname_free_ci_filename(struct ext4_filename *fname) 2752 + { 2753 + kfree(fname->cf_name.name); 2754 + fname->cf_name.name = NULL; 2755 + } 2756 + #else 2757 + static inline int ext4_fname_setup_ci_filename(struct inode *dir, 2758 + const struct qstr *iname, 2759 + struct ext4_filename *fname) 2760 + { 2761 + return 0; 2762 + } 2763 + 2764 + static inline void ext4_fname_free_ci_filename(struct ext4_filename *fname) 2765 + { 2766 + } 2750 2767 #endif 2751 2768 2752 2769 /* ext4 encryption related stuff goes here crypto.c */ ··· 2786 2769 int lookup, 2787 2770 struct ext4_filename *fname) 2788 2771 { 2789 - int err = 0; 2790 2772 fname->usr_fname = iname; 2791 2773 fname->disk_name.name = (unsigned char *) iname->name; 2792 2774 fname->disk_name.len = iname->len; 2793 2775 2794 - #if IS_ENABLED(CONFIG_UNICODE) 2795 - err = ext4_fname_setup_ci_filename(dir, iname, fname); 2796 - #endif 2797 - 2798 - return err; 2776 + return ext4_fname_setup_ci_filename(dir, iname, fname); 2799 2777 } 2800 2778 2801 2779 static inline int ext4_fname_prepare_lookup(struct inode *dir, ··· 2802 2790 2803 2791 static inline void ext4_fname_free_filename(struct ext4_filename *fname) 2804 2792 { 2805 - #if IS_ENABLED(CONFIG_UNICODE) 2806 - kfree(fname->cf_name.name); 2807 - fname->cf_name.name = NULL; 2808 - #endif 2793 + ext4_fname_free_ci_filename(fname); 2809 2794 } 2810 2795 2811 2796 static inline int ext4_ioctl_get_encryption_pwsalt(struct file *filp,
+36 -84
fs/ext4/namei.c
··· 1390 1390 } 1391 1391 1392 1392 #if IS_ENABLED(CONFIG_UNICODE) 1393 - /* 1394 - * Test whether a case-insensitive directory entry matches the filename 1395 - * being searched for. If quick is set, assume the name being looked up 1396 - * is already in the casefolded form. 1397 - * 1398 - * Returns: 0 if the directory entry matches, more than 0 if it 1399 - * doesn't match or less than zero on error. 1400 - */ 1401 - static int ext4_ci_compare(const struct inode *parent, const struct qstr *name, 1402 - u8 *de_name, size_t de_name_len, bool quick) 1403 - { 1404 - const struct super_block *sb = parent->i_sb; 1405 - const struct unicode_map *um = sb->s_encoding; 1406 - struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len); 1407 - struct qstr entry = QSTR_INIT(de_name, de_name_len); 1408 - int ret; 1409 - 1410 - if (IS_ENCRYPTED(parent)) { 1411 - const struct fscrypt_str encrypted_name = 1412 - FSTR_INIT(de_name, de_name_len); 1413 - 1414 - decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL); 1415 - if (!decrypted_name.name) 1416 - return -ENOMEM; 1417 - ret = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name, 1418 - &decrypted_name); 1419 - if (ret < 0) 1420 - goto out; 1421 - entry.name = decrypted_name.name; 1422 - entry.len = decrypted_name.len; 1423 - } 1424 - 1425 - if (quick) 1426 - ret = utf8_strncasecmp_folded(um, name, &entry); 1427 - else 1428 - ret = utf8_strncasecmp(um, name, &entry); 1429 - if (ret < 0) { 1430 - /* Handle invalid character sequence as either an error 1431 - * or as an opaque byte sequence. 1432 - */ 1433 - if (sb_has_strict_encoding(sb)) 1434 - ret = -EINVAL; 1435 - else if (name->len != entry.len) 1436 - ret = 1; 1437 - else 1438 - ret = !!memcmp(name->name, entry.name, entry.len); 1439 - } 1440 - out: 1441 - kfree(decrypted_name.name); 1442 - return ret; 1443 - } 1444 - 1445 1393 int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, 1446 1394 struct ext4_filename *name) 1447 1395 { 1448 - struct fscrypt_str *cf_name = &name->cf_name; 1396 + struct qstr *cf_name = &name->cf_name; 1397 + unsigned char *buf; 1449 1398 struct dx_hash_info *hinfo = &name->hinfo; 1450 1399 int len; 1451 1400 ··· 1404 1455 return 0; 1405 1456 } 1406 1457 1407 - cf_name->name = kmalloc(EXT4_NAME_LEN, GFP_NOFS); 1408 - if (!cf_name->name) 1458 + buf = kmalloc(EXT4_NAME_LEN, GFP_NOFS); 1459 + if (!buf) 1409 1460 return -ENOMEM; 1410 1461 1411 - len = utf8_casefold(dir->i_sb->s_encoding, 1412 - iname, cf_name->name, 1413 - EXT4_NAME_LEN); 1462 + len = utf8_casefold(dir->i_sb->s_encoding, iname, buf, EXT4_NAME_LEN); 1414 1463 if (len <= 0) { 1415 - kfree(cf_name->name); 1416 - cf_name->name = NULL; 1464 + kfree(buf); 1465 + buf = NULL; 1417 1466 } 1467 + cf_name->name = buf; 1418 1468 cf_name->len = (unsigned) len; 1469 + 1419 1470 if (!IS_ENCRYPTED(dir)) 1420 1471 return 0; 1421 1472 ··· 1451 1502 #if IS_ENABLED(CONFIG_UNICODE) 1452 1503 if (IS_CASEFOLDED(parent) && 1453 1504 (!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) { 1454 - if (fname->cf_name.name) { 1455 - struct qstr cf = {.name = fname->cf_name.name, 1456 - .len = fname->cf_name.len}; 1457 - if (IS_ENCRYPTED(parent)) { 1458 - if (fname->hinfo.hash != EXT4_DIRENT_HASH(de) || 1459 - fname->hinfo.minor_hash != 1460 - EXT4_DIRENT_MINOR_HASH(de)) { 1505 + /* 1506 + * Just checking IS_ENCRYPTED(parent) below is not 1507 + * sufficient to decide whether one can use the hash for 1508 + * skipping the string comparison, because the key might 1509 + * have been added right after 1510 + * ext4_fname_setup_ci_filename(). In this case, a hash 1511 + * mismatch will be a false negative. Therefore, make 1512 + * sure cf_name was properly initialized before 1513 + * considering the calculated hash. 1514 + */ 1515 + if (IS_ENCRYPTED(parent) && fname->cf_name.name && 1516 + (fname->hinfo.hash != EXT4_DIRENT_HASH(de) || 1517 + fname->hinfo.minor_hash != EXT4_DIRENT_MINOR_HASH(de))) 1518 + return false; 1519 + /* 1520 + * Treat comparison errors as not a match. The 1521 + * only case where it happens is on a disk 1522 + * corruption or ENOMEM. 1523 + */ 1461 1524 1462 - return false; 1463 - } 1464 - } 1465 - return !ext4_ci_compare(parent, &cf, de->name, 1466 - de->name_len, true); 1467 - } 1468 - return !ext4_ci_compare(parent, fname->usr_fname, de->name, 1469 - de->name_len, false); 1525 + return generic_ci_match(parent, fname->usr_fname, 1526 + &fname->cf_name, de->name, 1527 + de->name_len) > 0; 1470 1528 } 1471 1529 #endif 1472 1530 ··· 1825 1869 } 1826 1870 } 1827 1871 1828 - #if IS_ENABLED(CONFIG_UNICODE) 1829 - if (!inode && IS_CASEFOLDED(dir)) { 1872 + if (IS_ENABLED(CONFIG_UNICODE) && !inode && IS_CASEFOLDED(dir)) { 1830 1873 /* Eventually we want to call d_add_ci(dentry, NULL) 1831 1874 * for negative dentries in the encoding case as 1832 1875 * well. For now, prevent the negative dentry ··· 1833 1878 */ 1834 1879 return NULL; 1835 1880 } 1836 - #endif 1881 + 1837 1882 return d_splice_alias(inode, dentry); 1838 1883 } 1839 1884 ··· 3163 3208 ext4_fc_track_unlink(handle, dentry); 3164 3209 retval = ext4_mark_inode_dirty(handle, dir); 3165 3210 3166 - #if IS_ENABLED(CONFIG_UNICODE) 3167 3211 /* VFS negative dentries are incompatible with Encoding and 3168 3212 * Case-insensitiveness. Eventually we'll want avoid 3169 3213 * invalidating the dentries here, alongside with returning the 3170 3214 * negative dentries at ext4_lookup(), when it is better 3171 3215 * supported by the VFS for the CI case. 3172 3216 */ 3173 - if (IS_CASEFOLDED(dir)) 3217 + if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir)) 3174 3218 d_invalidate(dentry); 3175 - #endif 3176 3219 3177 3220 end_rmdir: 3178 3221 brelse(bh); ··· 3272 3319 goto out_trace; 3273 3320 3274 3321 retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry), dentry); 3275 - #if IS_ENABLED(CONFIG_UNICODE) 3322 + 3276 3323 /* VFS negative dentries are incompatible with Encoding and 3277 3324 * Case-insensitiveness. Eventually we'll want avoid 3278 3325 * invalidating the dentries here, alongside with returning the 3279 3326 * negative dentries at ext4_lookup(), when it is better 3280 3327 * supported by the VFS for the CI case. 3281 3328 */ 3282 - if (IS_CASEFOLDED(dir)) 3329 + if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir)) 3283 3330 d_invalidate(dentry); 3284 - #endif 3285 3331 3286 3332 out_trace: 3287 3333 trace_ext4_unlink_exit(dentry, retval);
+1 -3
fs/ext4/super.c
··· 3586 3586 return 0; 3587 3587 } 3588 3588 3589 - #if !IS_ENABLED(CONFIG_UNICODE) 3590 - if (ext4_has_feature_casefold(sb)) { 3589 + if (!IS_ENABLED(CONFIG_UNICODE) && ext4_has_feature_casefold(sb)) { 3591 3590 ext4_msg(sb, KERN_ERR, 3592 3591 "Filesystem with casefold feature cannot be " 3593 3592 "mounted without CONFIG_UNICODE"); 3594 3593 return 0; 3595 3594 } 3596 - #endif 3597 3595 3598 3596 if (readonly) 3599 3597 return 1;
+31 -74
fs/f2fs/dir.c
··· 42 42 return 4; 43 43 } 44 44 45 + #if IS_ENABLED(CONFIG_UNICODE) 45 46 /* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */ 46 47 int f2fs_init_casefolded_name(const struct inode *dir, 47 48 struct f2fs_filename *fname) 48 49 { 49 - #if IS_ENABLED(CONFIG_UNICODE) 50 50 struct super_block *sb = dir->i_sb; 51 + unsigned char *buf; 52 + int len; 51 53 52 54 if (IS_CASEFOLDED(dir) && 53 55 !is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) { 54 - fname->cf_name.name = f2fs_kmem_cache_alloc(f2fs_cf_name_slab, 55 - GFP_NOFS, false, F2FS_SB(sb)); 56 - if (!fname->cf_name.name) 56 + buf = f2fs_kmem_cache_alloc(f2fs_cf_name_slab, 57 + GFP_NOFS, false, F2FS_SB(sb)); 58 + if (!buf) 57 59 return -ENOMEM; 58 - fname->cf_name.len = utf8_casefold(sb->s_encoding, 59 - fname->usr_fname, 60 - fname->cf_name.name, 61 - F2FS_NAME_LEN); 62 - if ((int)fname->cf_name.len <= 0) { 63 - kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name); 64 - fname->cf_name.name = NULL; 60 + 61 + len = utf8_casefold(sb->s_encoding, fname->usr_fname, 62 + buf, F2FS_NAME_LEN); 63 + if (len <= 0) { 64 + kmem_cache_free(f2fs_cf_name_slab, buf); 65 65 if (sb_has_strict_encoding(sb)) 66 66 return -EINVAL; 67 67 /* fall back to treating name as opaque byte sequence */ 68 + return 0; 68 69 } 70 + fname->cf_name.name = buf; 71 + fname->cf_name.len = len; 69 72 } 70 - #endif 73 + 71 74 return 0; 72 75 } 76 + 77 + void f2fs_free_casefolded_name(struct f2fs_filename *fname) 78 + { 79 + unsigned char *buf = (unsigned char *)fname->cf_name.name; 80 + 81 + if (buf) { 82 + kmem_cache_free(f2fs_cf_name_slab, buf); 83 + fname->cf_name.name = NULL; 84 + } 85 + } 86 + #endif /* CONFIG_UNICODE */ 73 87 74 88 static int __f2fs_setup_filename(const struct inode *dir, 75 89 const struct fscrypt_name *crypt_name, ··· 156 142 kfree(fname->crypto_buf.name); 157 143 fname->crypto_buf.name = NULL; 158 144 #endif 159 - #if IS_ENABLED(CONFIG_UNICODE) 160 - if (fname->cf_name.name) { 161 - kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name); 162 - fname->cf_name.name = NULL; 163 - } 164 - #endif 145 + f2fs_free_casefolded_name(fname); 165 146 } 166 147 167 148 static unsigned long dir_block_index(unsigned int level, ··· 185 176 return f2fs_find_target_dentry(&d, fname, max_slots); 186 177 } 187 178 188 - #if IS_ENABLED(CONFIG_UNICODE) 189 - /* 190 - * Test whether a case-insensitive directory entry matches the filename 191 - * being searched for. 192 - * 193 - * Returns 1 for a match, 0 for no match, and -errno on an error. 194 - */ 195 - static int f2fs_match_ci_name(const struct inode *dir, const struct qstr *name, 196 - const u8 *de_name, u32 de_name_len) 197 - { 198 - const struct super_block *sb = dir->i_sb; 199 - const struct unicode_map *um = sb->s_encoding; 200 - struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len); 201 - struct qstr entry = QSTR_INIT(de_name, de_name_len); 202 - int res; 203 - 204 - if (IS_ENCRYPTED(dir)) { 205 - const struct fscrypt_str encrypted_name = 206 - FSTR_INIT((u8 *)de_name, de_name_len); 207 - 208 - if (WARN_ON_ONCE(!fscrypt_has_encryption_key(dir))) 209 - return -EINVAL; 210 - 211 - decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL); 212 - if (!decrypted_name.name) 213 - return -ENOMEM; 214 - res = fscrypt_fname_disk_to_usr(dir, 0, 0, &encrypted_name, 215 - &decrypted_name); 216 - if (res < 0) 217 - goto out; 218 - entry.name = decrypted_name.name; 219 - entry.len = decrypted_name.len; 220 - } 221 - 222 - res = utf8_strncasecmp_folded(um, name, &entry); 223 - /* 224 - * In strict mode, ignore invalid names. In non-strict mode, 225 - * fall back to treating them as opaque byte sequences. 226 - */ 227 - if (res < 0 && !sb_has_strict_encoding(sb)) { 228 - res = name->len == entry.len && 229 - memcmp(name->name, entry.name, name->len) == 0; 230 - } else { 231 - /* utf8_strncasecmp_folded returns 0 on match */ 232 - res = (res == 0); 233 - } 234 - out: 235 - kfree(decrypted_name.name); 236 - return res; 237 - } 238 - #endif /* CONFIG_UNICODE */ 239 - 240 179 static inline int f2fs_match_name(const struct inode *dir, 241 180 const struct f2fs_filename *fname, 242 181 const u8 *de_name, u32 de_name_len) ··· 192 235 struct fscrypt_name f; 193 236 194 237 #if IS_ENABLED(CONFIG_UNICODE) 195 - if (fname->cf_name.name) { 196 - struct qstr cf = FSTR_TO_QSTR(&fname->cf_name); 238 + if (fname->cf_name.name) 239 + return generic_ci_match(dir, fname->usr_fname, 240 + &fname->cf_name, 241 + de_name, de_name_len); 197 242 198 - return f2fs_match_ci_name(dir, &cf, de_name, de_name_len); 199 - } 200 243 #endif 201 244 f.usr_fname = fname->usr_fname; 202 245 f.disk_name = fname->disk_name;
+15 -1
fs/f2fs/f2fs.h
··· 531 531 * internal operation where usr_fname is also NULL. In all these cases 532 532 * we fall back to treating the name as an opaque byte sequence. 533 533 */ 534 - struct fscrypt_str cf_name; 534 + struct qstr cf_name; 535 535 #endif 536 536 }; 537 537 ··· 3533 3533 /* 3534 3534 * dir.c 3535 3535 */ 3536 + #if IS_ENABLED(CONFIG_UNICODE) 3536 3537 int f2fs_init_casefolded_name(const struct inode *dir, 3537 3538 struct f2fs_filename *fname); 3539 + void f2fs_free_casefolded_name(struct f2fs_filename *fname); 3540 + #else 3541 + static inline int f2fs_init_casefolded_name(const struct inode *dir, 3542 + struct f2fs_filename *fname) 3543 + { 3544 + return 0; 3545 + } 3546 + 3547 + static inline void f2fs_free_casefolded_name(struct f2fs_filename *fname) 3548 + { 3549 + } 3550 + #endif /* CONFIG_UNICODE */ 3551 + 3538 3552 int f2fs_setup_filename(struct inode *dir, const struct qstr *iname, 3539 3553 int lookup, struct f2fs_filename *fname); 3540 3554 int f2fs_prepare_lookup(struct inode *dir, struct dentry *dentry,
+4 -6
fs/f2fs/namei.c
··· 576 576 goto out_iput; 577 577 } 578 578 out_splice: 579 - #if IS_ENABLED(CONFIG_UNICODE) 580 - if (!inode && IS_CASEFOLDED(dir)) { 579 + if (IS_ENABLED(CONFIG_UNICODE) && !inode && IS_CASEFOLDED(dir)) { 581 580 /* Eventually we want to call d_add_ci(dentry, NULL) 582 581 * for negative dentries in the encoding case as 583 582 * well. For now, prevent the negative dentry ··· 585 586 trace_f2fs_lookup_end(dir, dentry, ino, err); 586 587 return NULL; 587 588 } 588 - #endif 589 + 589 590 new = d_splice_alias(inode, dentry); 590 591 trace_f2fs_lookup_end(dir, !IS_ERR_OR_NULL(new) ? new : dentry, 591 592 ino, IS_ERR(new) ? PTR_ERR(new) : err); ··· 638 639 f2fs_delete_entry(de, page, dir, inode); 639 640 f2fs_unlock_op(sbi); 640 641 641 - #if IS_ENABLED(CONFIG_UNICODE) 642 642 /* VFS negative dentries are incompatible with Encoding and 643 643 * Case-insensitiveness. Eventually we'll want avoid 644 644 * invalidating the dentries here, alongside with returning the 645 645 * negative dentries at f2fs_lookup(), when it is better 646 646 * supported by the VFS for the CI case. 647 647 */ 648 - if (IS_CASEFOLDED(dir)) 648 + if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir)) 649 649 d_invalidate(dentry); 650 - #endif 650 + 651 651 if (IS_DIRSYNC(dir)) 652 652 f2fs_sync_fs(sbi->sb, 1); 653 653 fail:
+1 -8
fs/f2fs/recovery.c
··· 46 46 47 47 static struct kmem_cache *fsync_entry_slab; 48 48 49 - #if IS_ENABLED(CONFIG_UNICODE) 50 - extern struct kmem_cache *f2fs_cf_name_slab; 51 - #endif 52 - 53 49 bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi) 54 50 { 55 51 s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count); ··· 149 153 if (err) 150 154 return err; 151 155 f2fs_hash_filename(dir, fname); 152 - #if IS_ENABLED(CONFIG_UNICODE) 153 156 /* Case-sensitive match is fine for recovery */ 154 - kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name); 155 - fname->cf_name.name = NULL; 156 - #endif 157 + f2fs_free_casefolded_name(fname); 157 158 } else { 158 159 f2fs_hash_filename(dir, fname); 159 160 }
+4 -4
fs/f2fs/super.c
··· 321 321 static int __init f2fs_create_casefold_cache(void) 322 322 { 323 323 f2fs_cf_name_slab = f2fs_kmem_cache_create("f2fs_casefolded_name", 324 - F2FS_NAME_LEN); 324 + F2FS_NAME_LEN); 325 325 return f2fs_cf_name_slab ? 0 : -ENOMEM; 326 326 } 327 327 ··· 1326 1326 return -EINVAL; 1327 1327 } 1328 1328 #endif 1329 - #if !IS_ENABLED(CONFIG_UNICODE) 1330 - if (f2fs_sb_has_casefold(sbi)) { 1329 + 1330 + if (!IS_ENABLED(CONFIG_UNICODE) && f2fs_sb_has_casefold(sbi)) { 1331 1331 f2fs_err(sbi, 1332 1332 "Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE"); 1333 1333 return -EINVAL; 1334 1334 } 1335 - #endif 1335 + 1336 1336 /* 1337 1337 * The BLKZONED feature indicates that the drive was formatted with 1338 1338 * zone alignment optimization. This is optional for host-aware
+74
fs/libfs.c
··· 1854 1854 .d_revalidate = fscrypt_d_revalidate, 1855 1855 #endif 1856 1856 }; 1857 + 1858 + /** 1859 + * generic_ci_match() - Match a name (case-insensitively) with a dirent. 1860 + * This is a filesystem helper for comparison with directory entries. 1861 + * generic_ci_d_compare should be used in VFS' ->d_compare instead. 1862 + * 1863 + * @parent: Inode of the parent of the dirent under comparison 1864 + * @name: name under lookup. 1865 + * @folded_name: Optional pre-folded name under lookup 1866 + * @de_name: Dirent name. 1867 + * @de_name_len: dirent name length. 1868 + * 1869 + * Test whether a case-insensitive directory entry matches the filename 1870 + * being searched. If @folded_name is provided, it is used instead of 1871 + * recalculating the casefold of @name. 1872 + * 1873 + * Return: > 0 if the directory entry matches, 0 if it doesn't match, or 1874 + * < 0 on error. 1875 + */ 1876 + int generic_ci_match(const struct inode *parent, 1877 + const struct qstr *name, 1878 + const struct qstr *folded_name, 1879 + const u8 *de_name, u32 de_name_len) 1880 + { 1881 + const struct super_block *sb = parent->i_sb; 1882 + const struct unicode_map *um = sb->s_encoding; 1883 + struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len); 1884 + struct qstr dirent = QSTR_INIT(de_name, de_name_len); 1885 + int res = 0; 1886 + 1887 + if (IS_ENCRYPTED(parent)) { 1888 + const struct fscrypt_str encrypted_name = 1889 + FSTR_INIT((u8 *) de_name, de_name_len); 1890 + 1891 + if (WARN_ON_ONCE(!fscrypt_has_encryption_key(parent))) 1892 + return -EINVAL; 1893 + 1894 + decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL); 1895 + if (!decrypted_name.name) 1896 + return -ENOMEM; 1897 + res = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name, 1898 + &decrypted_name); 1899 + if (res < 0) { 1900 + kfree(decrypted_name.name); 1901 + return res; 1902 + } 1903 + dirent.name = decrypted_name.name; 1904 + dirent.len = decrypted_name.len; 1905 + } 1906 + 1907 + /* 1908 + * Attempt a case-sensitive match first. It is cheaper and 1909 + * should cover most lookups, including all the sane 1910 + * applications that expect a case-sensitive filesystem. 1911 + */ 1912 + 1913 + if (dirent.len == name->len && 1914 + !memcmp(name->name, dirent.name, dirent.len)) 1915 + goto out; 1916 + 1917 + if (folded_name->name) 1918 + res = utf8_strncasecmp_folded(um, folded_name, &dirent); 1919 + else 1920 + res = utf8_strncasecmp(um, name, &dirent); 1921 + 1922 + out: 1923 + kfree(decrypted_name.name); 1924 + if (res < 0 && sb_has_strict_encoding(sb)) { 1925 + pr_err_ratelimited("Directory contains filename that is invalid UTF-8"); 1926 + return 0; 1927 + } 1928 + return !res; 1929 + } 1930 + EXPORT_SYMBOL(generic_ci_match); 1857 1931 #endif 1858 1932 1859 1933 #ifdef CONFIG_FS_ENCRYPTION
+4
include/linux/fs.h
··· 3369 3369 extern int generic_check_addressable(unsigned, u64); 3370 3370 3371 3371 extern void generic_set_sb_d_ops(struct super_block *sb); 3372 + extern int generic_ci_match(const struct inode *parent, 3373 + const struct qstr *name, 3374 + const struct qstr *folded_name, 3375 + const u8 *de_name, u32 de_name_len); 3372 3376 3373 3377 static inline bool sb_has_encoding(const struct super_block *sb) 3374 3378 {