X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_sa.c;h=f35f6f64cc41487c40ff0db58c6c6d0d14510d8f;hb=ec2626ad3f695a2ced3946c4197ef64cbcac4959;hp=324e9b96c271c020bed7d496b3a3e3a680b83ed0;hpb=e45aa452988f721e458fa3abe54669bdf9377352;p=zfs.git diff --git a/module/zfs/zfs_sa.c b/module/zfs/zfs_sa.c index 324e9b9..f35f6f6 100644 --- a/module/zfs/zfs_sa.c +++ b/module/zfs/zfs_sa.c @@ -63,6 +63,7 @@ sa_attr_reg_t zfs_attr_table[ZPL_END+1] = { {"ZPL_SYMLINK", 0, SA_UINT8_ARRAY, 0}, {"ZPL_SCANSTAMP", 32, SA_UINT8_ARRAY, 0}, {"ZPL_DACL_ACES", 0, SA_ACL, 0}, + {"ZPL_DXATTR", 0, SA_UINT8_ARRAY, 0}, {NULL, 0, 0, 0} }; @@ -183,6 +184,106 @@ zfs_sa_set_scanstamp(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) } } +int +zfs_sa_get_xattr(znode_t *zp) +{ + zfs_sb_t *zsb = ZTOZSB(zp); + sa_handle_t *sa; + char *obj; + int size; + int error; + + ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock)); + ASSERT(!zp->z_xattr_cached); + ASSERT(zp->z_is_sa); + + error = sa_handle_get(zsb->z_os, zp->z_id, NULL, SA_HDL_PRIVATE, &sa); + if (error) + return (error); + + error = sa_size(sa, SA_ZPL_DXATTR(zsb), &size); + if (error) { + sa_handle_destroy(sa); + + if (error == ENOENT) + return nvlist_alloc(&zp->z_xattr_cached, + NV_UNIQUE_NAME, KM_SLEEP); + else + return (error); + } + + obj = sa_spill_alloc(KM_SLEEP); + + error = sa_lookup(sa, SA_ZPL_DXATTR(zsb), obj, size); + if (error == 0) + error = nvlist_unpack(obj, size, &zp->z_xattr_cached, KM_SLEEP); + + sa_spill_free(obj); + sa_handle_destroy(sa); + + return (error); +} + +int +zfs_sa_set_xattr(znode_t *zp) +{ + zfs_sb_t *zsb = ZTOZSB(zp); + sa_handle_t *sa; + dmu_tx_t *tx; + char *obj; + size_t size; + int error; + + ASSERT(RW_WRITE_HELD(&zp->z_xattr_lock)); + ASSERT(zp->z_xattr_cached); + ASSERT(zp->z_is_sa); + + error = nvlist_size(zp->z_xattr_cached, &size, NV_ENCODE_XDR); + if (error) + goto out; + + obj = sa_spill_alloc(KM_SLEEP); + + error = nvlist_pack(zp->z_xattr_cached, &obj, &size, + NV_ENCODE_XDR, KM_SLEEP); + if (error) + goto out_free; + + /* + * A private SA handle must be used to ensure we can drop the hold + * on the spill block prior to calling dmu_tx_commit(). If we call + * dmu_tx_commit() before sa_handle_destroy(), then our hold will + * trigger a copy of the buffer at txg sync time. This is done to + * prevent data from leaking in to the syncing txg. As a result + * the original dirty spill block will be remain dirty in the arc + * while the copy is written and laundered. + */ + error = sa_handle_get(zsb->z_os, zp->z_id, NULL, SA_HDL_PRIVATE, &sa); + if (error) + goto out_free; + + tx = dmu_tx_create(zsb->z_os); + dmu_tx_hold_sa_create(tx, size); + dmu_tx_hold_sa(tx, sa, B_TRUE); + + error = dmu_tx_assign(tx, TXG_WAIT); + if (error) { + dmu_tx_abort(tx); + sa_handle_destroy(sa); + } else { + error = sa_update(sa, SA_ZPL_DXATTR(zsb), obj, size, tx); + sa_handle_destroy(sa); + if (error) + dmu_tx_abort(tx); + else + dmu_tx_commit(tx); + } +out_free: + sa_spill_free(obj); +out: + return (error); +} + /* * I'm not convinced we should do any of this upgrade. * since the SA code can read both old/new znode formats @@ -334,10 +435,13 @@ zfs_sa_upgrade_txholds(dmu_tx_t *tx, znode_t *zp) } } +EXPORT_SYMBOL(zfs_attr_table); EXPORT_SYMBOL(zfs_sa_readlink); EXPORT_SYMBOL(zfs_sa_symlink); EXPORT_SYMBOL(zfs_sa_get_scanstamp); EXPORT_SYMBOL(zfs_sa_set_scanstamp); +EXPORT_SYMBOL(zfs_sa_get_xattr); +EXPORT_SYMBOL(zfs_sa_set_xattr); EXPORT_SYMBOL(zfs_sa_upgrade); EXPORT_SYMBOL(zfs_sa_upgrade_txholds);