int __osd_xattr_load(struct osd_device *osd, uint64_t dnode, nvlist_t **sa) { sa_handle_t *sa_hdl; char *buf; int rc, size; if (unlikely(dnode == ZFS_NO_OBJECT)) return -ENOENT; rc = -sa_handle_get(osd->od_os, dnode, NULL, SA_HDL_PRIVATE, &sa_hdl); if (rc) return rc; rc = -sa_size(sa_hdl, SA_ZPL_DXATTR(osd), &size); if (rc) { if (rc == -ENOENT) rc = -nvlist_alloc(sa, NV_UNIQUE_NAME, KM_SLEEP); goto out_sa; } buf = osd_zio_buf_alloc(size); if (buf == NULL) { rc = -ENOMEM; goto out_sa; } rc = -sa_lookup(sa_hdl, SA_ZPL_DXATTR(osd), buf, size); if (rc == 0) rc = -nvlist_unpack(buf, size, sa, KM_SLEEP); osd_zio_buf_free(buf, size); out_sa: sa_handle_destroy(sa_hdl); return rc; }
/* * 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); 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 = osd_zio_buf_alloc(sa_size); 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(osd), dxattr, sa_size, oh); out_free: osd_zio_buf_free(dxattr, sa_size); RETURN(rc); }