From 2a91d577b1dccb9b821960e353b3add230325ca5 Mon Sep 17 00:00:00 2001 From: Ameer Hamza Date: Tue, 27 May 2025 07:11:03 +0500 Subject: [PATCH] Expose dataset encryption status via fast stat path In truenas_pylibzfs, we query list of encrypted datasets several times, which is expensive. This commit exposes a public API zfs_is_encrypted() to get encryption status from fast stat path without having to refresh the properties. Reviewed-by: Brian Behlendorf Reviewed-by: Alexander Motin Reviewed-by: Rob Norris Signed-off-by: Ameer Hamza Closes #17368 --- include/libzfs.h | 1 + include/sys/dmu.h | 6 ++++++ lib/libzfs/libzfs.abi | 8 ++++++++ lib/libzfs/libzfs_crypto.c | 11 +++++++++++ lib/libzfs_core/libzfs_core.abi | 3 +++ module/zfs/dsl_dataset.c | 3 +++ 6 files changed, 32 insertions(+) diff --git a/include/libzfs.h b/include/libzfs.h index c3b3542bc..485af7938 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -591,6 +591,7 @@ _LIBZFS_H int zfs_crypto_attempt_load_keys(libzfs_handle_t *, const char *); _LIBZFS_H int zfs_crypto_load_key(zfs_handle_t *, boolean_t, const char *); _LIBZFS_H int zfs_crypto_unload_key(zfs_handle_t *); _LIBZFS_H int zfs_crypto_rewrap(zfs_handle_t *, nvlist_t *, boolean_t); +_LIBZFS_H boolean_t zfs_is_encrypted(zfs_handle_t *); typedef struct zprop_list { int pl_prop; diff --git a/include/sys/dmu.h b/include/sys/dmu.h index 7eed5f48b..e4024178c 100644 --- a/include/sys/dmu.h +++ b/include/sys/dmu.h @@ -997,6 +997,11 @@ void dmu_object_size_from_db(dmu_buf_t *db, uint32_t *blksize, void dmu_object_dnsize_from_db(dmu_buf_t *db, int *dnsize); +typedef enum { + DDS_FLAG_ENCRYPTED = (1<<0), + DDS_FLAG_HAS_ENCRYPTED = (1<<7), +} dmu_objset_flag_t; + typedef struct dmu_objset_stats { uint64_t dds_num_clones; /* number of clones of this */ uint64_t dds_creation_txg; @@ -1006,6 +1011,7 @@ typedef struct dmu_objset_stats { uint8_t dds_inconsistent; uint8_t dds_redacted; char dds_origin[ZFS_MAX_DATASET_NAME_LEN]; + uint8_t dds_flags; /* dmu_objset_flag_t */ } dmu_objset_stats_t; /* diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 26ae5d2f1..31f3eb613 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -345,6 +345,7 @@ + @@ -1925,6 +1926,9 @@ + + + @@ -3805,6 +3809,10 @@ + + + + diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c index da1d1ee29..8907802ec 100644 --- a/lib/libzfs/libzfs_crypto.c +++ b/lib/libzfs/libzfs_crypto.c @@ -1818,3 +1818,14 @@ error: zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); return (ret); } + +boolean_t +zfs_is_encrypted(zfs_handle_t *zhp) +{ + uint8_t flags = zhp->zfs_dmustats.dds_flags; + + if (flags & DDS_FLAG_HAS_ENCRYPTED) + return ((flags & DDS_FLAG_ENCRYPTED) != 0); + + return (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF); +} diff --git a/lib/libzfs_core/libzfs_core.abi b/lib/libzfs_core/libzfs_core.abi index f6aa9a742..a90aa7acf 100644 --- a/lib/libzfs_core/libzfs_core.abi +++ b/lib/libzfs_core/libzfs_core.abi @@ -1461,6 +1461,9 @@ + + + diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index e4113c604..ae55cf8b8 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -2886,6 +2886,9 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat) stat->dds_guid = dsl_get_guid(ds); stat->dds_redacted = dsl_get_redacted(ds); stat->dds_origin[0] = '\0'; + stat->dds_flags = DDS_FLAG_HAS_ENCRYPTED; + if (ds->ds_dir->dd_crypto_obj != 0) + stat->dds_flags |= DDS_FLAG_ENCRYPTED; if (ds->ds_is_snapshot) { stat->dds_is_snapshot = B_TRUE; stat->dds_num_clones = dsl_get_numclones(ds);