aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Rosenberg2020-11-19 00:09:02 -0600
committerJaegeuk Kim2020-12-21 15:33:13 -0600
commitc35a25795ed5cbcdf1ca93959ae8e5ec49822ace (patch)
treec2aeb1a6e10dde23794e5c76d59e7e8815b31c2b
parentc60814e9fb8b99da3e31222966ea0a0934c79500 (diff)
downloadkernel-c35a25795ed5cbcdf1ca93959ae8e5ec49822ace.tar.gz
kernel-c35a25795ed5cbcdf1ca93959ae8e5ec49822ace.tar.xz
kernel-c35a25795ed5cbcdf1ca93959ae8e5ec49822ace.zip
libfs: Add generic function for setting dentry_ops
This adds a function to set dentry operations at lookup time that will work for both encrypted filenames and casefolded filenames. A filesystem that supports both features simultaneously can use this function during lookup preparations to set up its dentry operations once fscrypt no longer does that itself. Currently the casefolding dentry operation are always set if the filesystem defines an encoding because the features is toggleable on empty directories. Unlike in the encryption case, the dentry operations used come from the parent. Since we don't know what set of functions we'll eventually need, and cannot change them later, we enable the casefolding operations if the filesystem supports them at all. By splitting out the various cases, we support as few dentry operations as we can get away with, maximizing compatibility with overlayfs, which will not function if a filesystem supports certain dentry_operations. Signed-off-by: Daniel Rosenberg <drosen@google.com> Reviewed-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Gabriel Krisman Bertazi <krisman@collabora.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/libfs.c70
-rw-r--r--include/linux/fs.h1
2 files changed, 71 insertions, 0 deletions
diff --git a/fs/libfs.c b/fs/libfs.c
index 7124c2e8df2f..d1c3bade9f30 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -1451,4 +1451,74 @@ int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str)
1451 return 0; 1451 return 0;
1452} 1452}
1453EXPORT_SYMBOL(generic_ci_d_hash); 1453EXPORT_SYMBOL(generic_ci_d_hash);
1454
1455static const struct dentry_operations generic_ci_dentry_ops = {
1456 .d_hash = generic_ci_d_hash,
1457 .d_compare = generic_ci_d_compare,
1458};
1459#endif
1460
1461#ifdef CONFIG_FS_ENCRYPTION
1462static const struct dentry_operations generic_encrypted_dentry_ops = {
1463 .d_revalidate = fscrypt_d_revalidate,
1464};
1465#endif
1466
1467#if defined(CONFIG_FS_ENCRYPTION) && defined(CONFIG_UNICODE)
1468static const struct dentry_operations generic_encrypted_ci_dentry_ops = {
1469 .d_hash = generic_ci_d_hash,
1470 .d_compare = generic_ci_d_compare,
1471 .d_revalidate = fscrypt_d_revalidate,
1472};
1473#endif
1474
1475/**
1476 * generic_set_encrypted_ci_d_ops - helper for setting d_ops for given dentry
1477 * @dentry: dentry to set ops on
1478 *
1479 * Casefolded directories need d_hash and d_compare set, so that the dentries
1480 * contained in them are handled case-insensitively. Note that these operations
1481 * are needed on the parent directory rather than on the dentries in it, and
1482 * while the casefolding flag can be toggled on and off on an empty directory,
1483 * dentry_operations can't be changed later. As a result, if the filesystem has
1484 * casefolding support enabled at all, we have to give all dentries the
1485 * casefolding operations even if their inode doesn't have the casefolding flag
1486 * currently (and thus the casefolding ops would be no-ops for now).
1487 *
1488 * Encryption works differently in that the only dentry operation it needs is
1489 * d_revalidate, which it only needs on dentries that have the no-key name flag.
1490 * The no-key flag can't be set "later", so we don't have to worry about that.
1491 *
1492 * Finally, to maximize compatibility with overlayfs (which isn't compatible
1493 * with certain dentry operations) and to avoid taking an unnecessary
1494 * performance hit, we use custom dentry_operations for each possible
1495 * combination rather than always installing all operations.
1496 */
1497void generic_set_encrypted_ci_d_ops(struct dentry *dentry)
1498{
1499#ifdef CONFIG_FS_ENCRYPTION
1500 bool needs_encrypt_ops = dentry->d_flags & DCACHE_NOKEY_NAME;
1501#endif
1502#ifdef CONFIG_UNICODE
1503 bool needs_ci_ops = dentry->d_sb->s_encoding;
1504#endif
1505#if defined(CONFIG_FS_ENCRYPTION) && defined(CONFIG_UNICODE)
1506 if (needs_encrypt_ops && needs_ci_ops) {
1507 d_set_d_op(dentry, &generic_encrypted_ci_dentry_ops);
1508 return;
1509 }
1454#endif 1510#endif
1511#ifdef CONFIG_FS_ENCRYPTION
1512 if (needs_encrypt_ops) {
1513 d_set_d_op(dentry, &generic_encrypted_dentry_ops);
1514 return;
1515 }
1516#endif
1517#ifdef CONFIG_UNICODE
1518 if (needs_ci_ops) {
1519 d_set_d_op(dentry, &generic_ci_dentry_ops);
1520 return;
1521 }
1522#endif
1523}
1524EXPORT_SYMBOL(generic_set_encrypted_ci_d_ops);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8667d0cdc71e..11345e66353b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3202,6 +3202,7 @@ extern int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str);
3202extern int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, 3202extern int generic_ci_d_compare(const struct dentry *dentry, unsigned int len,
3203 const char *str, const struct qstr *name); 3203 const char *str, const struct qstr *name);
3204#endif 3204#endif
3205extern void generic_set_encrypted_ci_d_ops(struct dentry *dentry);
3205 3206
3206#ifdef CONFIG_MIGRATION 3207#ifdef CONFIG_MIGRATION
3207extern int buffer_migrate_page(struct address_space *, 3208extern int buffer_migrate_page(struct address_space *,