Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
/*
 * 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;
}
Beispiel #4
0
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;
}
Beispiel #5
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);
}
Beispiel #6
0
/*
 * 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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}