/* * Set an extended attribute. * This transaction must have called udmu_xattr_declare_set() first. * * Returns 0 on success or a negative error number on failure. * * No locking is done here. */ static int __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj, struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; char *dxattr; size_t sa_size; int rc; ENTRY; LASSERT(obj->oo_sa_hdl); LASSERT(obj->oo_sa_xattr); /* Update the SA for additions, modifications, and removals. */ rc = -nvlist_size(obj->oo_sa_xattr, &sa_size, NV_ENCODE_XDR); if (rc) return rc; dxattr = sa_spill_alloc(KM_SLEEP); if (dxattr == NULL) RETURN(-ENOMEM); rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size, NV_ENCODE_XDR, KM_SLEEP); if (rc) GOTO(out_free, rc); rc = osd_object_sa_update(obj, SA_ZPL_DXATTR(uos), dxattr, sa_size, oh); out_free: sa_spill_free(dxattr); RETURN(rc); }
/* * Copy an extended attribute into the buffer provided, or compute the * required buffer size. * * If buf is NULL, it computes the required buffer size. * * Returns 0 on success or a negative error number on failure. * On success, the number of bytes used / required is stored in 'size'. * * No locking is done here. */ int __osd_xattr_load(udmu_objset_t *uos, uint64_t dnode, nvlist_t **sa_xattr) { sa_handle_t *sa_hdl; char *buf; int rc, size; if (unlikely(dnode == ZFS_NO_OBJECT)) return -ENOENT; rc = -sa_handle_get(uos->os, dnode, NULL, SA_HDL_PRIVATE, &sa_hdl); if (rc) return rc; rc = -sa_size(sa_hdl, SA_ZPL_DXATTR(uos), &size); if (rc) { if (rc == -ENOENT) rc = -nvlist_alloc(sa_xattr, NV_UNIQUE_NAME, KM_SLEEP); goto out_sa; } buf = sa_spill_alloc(KM_SLEEP); if (buf == NULL) { rc = -ENOMEM; goto out_sa; } rc = -sa_lookup(sa_hdl, SA_ZPL_DXATTR(uos), buf, size); if (rc == 0) rc = -nvlist_unpack(buf, size, sa_xattr, KM_SLEEP); sa_spill_free(buf); out_sa: sa_handle_destroy(sa_hdl); return rc; }
/* * Copy an extended attribute into the buffer provided, or compute the * required buffer size. * * If buf is NULL, it computes the required buffer size. * * Returns 0 on success or a negative error number on failure. * On success, the number of bytes used / required is stored in 'size'. * * No locking is done here. */ int __osd_xattr_cache(const struct lu_env *env, struct osd_object *obj) { struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; sa_handle_t *sa_hdl; char *buf; int size; int rc; LASSERT(obj->oo_sa_xattr == NULL); LASSERT(obj->oo_db != NULL); rc = -sa_handle_get(uos->os, obj->oo_db->db_object, NULL, SA_HDL_PRIVATE, &sa_hdl); if (rc) return rc; rc = -sa_size(sa_hdl, SA_ZPL_DXATTR(uos), &size); if (rc) { if (rc == -ENOENT) rc = -nvlist_alloc(&obj->oo_sa_xattr, NV_UNIQUE_NAME, KM_SLEEP); goto out_sa; } buf = sa_spill_alloc(KM_SLEEP); if (buf == NULL) { rc = -ENOMEM; goto out_sa; } rc = -sa_lookup(sa_hdl, SA_ZPL_DXATTR(uos), buf, size); if (rc == 0) rc = -nvlist_unpack(buf, size, &obj->oo_sa_xattr, KM_SLEEP); sa_spill_free(buf); out_sa: sa_handle_destroy(sa_hdl); return rc; }