dnode: allow storage class to be overridden by object type

spa_preferred_class() selects a storage class based on (among other
things) the DMU object type. This only works for old-style object types
that match only one specific kind of thing. For DMU_OTN_ types we need
another way to signal the storage class.

This commit allows the object type to be overridden in the IO policy for
the purposes of choosing a storage class. It then adds the ability to
set the storage type on a dnode hold, such that all writes generated
under that hold will get it.

This method has two shortcomings:

- it would be better if we could "name" a set of storage class
  preferences rather than it being implied by the object type.
- it would be better if this info were stored in the dnode on disk.

In the absence of those things, this seems like the smallest possible
change.

Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
Sponsored-by: Klara, Inc.
Sponsored-by: iXsystems, Inc.
Closes #15894
This commit is contained in:
Rob Norris
2023-06-27 12:50:18 +10:00
committed by Brian Behlendorf
parent e26b3771ee
commit d54d0fff39
6 changed files with 35 additions and 2 deletions
+17
View File
@@ -543,6 +543,17 @@ dnode_setbonus_type(dnode_t *dn, dmu_object_type_t newtype, dmu_tx_t *tx)
rw_exit(&dn->dn_struct_rwlock);
}
void
dnode_set_storage_type(dnode_t *dn, dmu_object_type_t newtype)
{
/*
* This is not in the dnode_phys, but it should be, and perhaps one day
* will. For now we require it be set after taking a hold.
*/
ASSERT3U(zfs_refcount_count(&dn->dn_holds), >=, 1);
dn->dn_storage_type = newtype;
}
void
dnode_rm_spill(dnode_t *dn, dmu_tx_t *tx)
{
@@ -604,6 +615,8 @@ dnode_create(objset_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
dn->dn_have_spill = ((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) != 0);
dn->dn_id_flags = 0;
dn->dn_storage_type = DMU_OT_NONE;
dmu_zfetch_init(&dn->dn_zfetch, dn);
ASSERT(DMU_OT_IS_VALID(dn->dn_phys->dn_type));
@@ -687,6 +700,8 @@ dnode_destroy(dnode_t *dn)
dn->dn_newprojid = ZFS_DEFAULT_PROJID;
dn->dn_id_flags = 0;
dn->dn_storage_type = DMU_OT_NONE;
dmu_zfetch_fini(&dn->dn_zfetch);
kmem_cache_free(dnode_cache, dn);
arc_space_return(sizeof (dnode_t), ARC_SPACE_DNODE);
@@ -946,6 +961,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
ndn->dn_newgid = odn->dn_newgid;
ndn->dn_newprojid = odn->dn_newprojid;
ndn->dn_id_flags = odn->dn_id_flags;
ndn->dn_storage_type = odn->dn_storage_type;
dmu_zfetch_init(&ndn->dn_zfetch, ndn);
/*
@@ -1004,6 +1020,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
odn->dn_newgid = 0;
odn->dn_newprojid = ZFS_DEFAULT_PROJID;
odn->dn_id_flags = 0;
odn->dn_storage_type = DMU_OT_NONE;
/*
* Mark the dnode.