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; }
int zfs_sa_get_xattr(znode_t *zp) { zfs_sb_t *zsb = ZTOZSB(zp); 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_size(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb), &size); if (error) { if (error == ENOENT) return nvlist_alloc(&zp->z_xattr_cached, NV_UNIQUE_NAME, KM_SLEEP); else return (error); } obj = zio_buf_alloc(size); error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb), obj, size); if (error == 0) error = nvlist_unpack(obj, size, &zp->z_xattr_cached, KM_SLEEP); zio_buf_free(obj, size); return (error); }
/* * 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; }
int __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj, struct osd_thandle *oh) { struct lu_buf *lb = &osd_oti_get(env)->oti_xattr_lbuf; struct osd_device *osd = osd_obj2dev(obj); char *dxattr; size_t size; int rc; obj->oo_late_xattr = 0; /* Update the SA for additions, modifications, and removals. */ rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR); if (rc) return rc; lu_buf_check_and_alloc(lb, size); if (lb->lb_buf == NULL) { CERROR("%s: can't allocate buffer for xattr update\n", osd->od_svname); return -ENOMEM; } dxattr = lb->lb_buf; rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &size, NV_ENCODE_XDR, KM_SLEEP); if (rc) return rc; LASSERT(dxattr == lb->lb_buf); sa_update(obj->oo_sa_hdl, SA_ZPL_DXATTR(osd), dxattr, size, oh->ot_tx); return 0; }
/* * 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_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; }
int zfs_sa_set_xattr(znode_t *zp) { zfs_sb_t *zsb = ZTOZSB(zp); 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 = zio_buf_alloc(size); error = nvlist_pack(zp->z_xattr_cached, &obj, &size, NV_ENCODE_XDR, KM_SLEEP); if (error) goto out_free; tx = dmu_tx_create(zsb->z_os); dmu_tx_hold_sa_create(tx, size); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); } else { error = sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb), obj, size, tx); if (error) dmu_tx_abort(tx); else dmu_tx_commit(tx); } out_free: zio_buf_free(obj, size); out: return (error); }
int zfs_sa_set_xattr(znode_t *zp) { zfsvfs_t *zfsvfs = ZTOZSB(zp); 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 == 0) && (size > SA_ATTR_MAX_LEN)) error = EFBIG; if (error) goto out; obj = vmem_alloc(size, KM_SLEEP); error = nvlist_pack(zp->z_xattr_cached, &obj, &size, NV_ENCODE_XDR, KM_SLEEP); if (error) goto out_free; tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_sa_create(tx, size); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); } else { VERIFY0(sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zfsvfs), obj, size, tx)); dmu_tx_commit(tx); } out_free: vmem_free(obj, size); out: return (error); }