Exemple #1
0
/*
 * Convert a list of nvp_list_t's to a single nvlist
 * Used when writing the nvlist file.
 */
static int
devid_nvp2nvl(nvfd_t *nvfd, nvlist_t **ret_nvl)
{
	nvlist_t	*nvl, *sub_nvl;
	nvp_devid_t	*np;
	int		rval;

	ASSERT(modrootloaded);

	rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
	if (rval != 0) {
		KFIOERR((CE_CONT, "%s: nvlist alloc error %d\n",
			nvfd->nvf_name, rval));
		return (DDI_FAILURE);
	}

	for (np = NVF_DEVID_LIST(nvfd); np; np = NVP_DEVID_NEXT(np)) {
		if (np->nvp_devid == NULL)
		    continue;
		NVP_DEVID_DEBUG_PATH(np->nvp_devpath);
		rval = nvlist_alloc(&sub_nvl, NV_UNIQUE_NAME, KM_SLEEP);
		if (rval != 0) {
			KFIOERR((CE_CONT, "%s: nvlist alloc error %d\n",
				nvfd->nvf_name, rval));
			sub_nvl = NULL;
			goto err;
		}

		rval = nvlist_add_byte_array(sub_nvl, DP_DEVID_ID,
			(uchar_t *)np->nvp_devid,
			ddi_devid_sizeof(np->nvp_devid));
		if (rval == 0) {
			NVP_DEVID_DEBUG_DEVID(np->nvp_devid);
		} else {
			KFIOERR((CE_CONT,
			    "%s: nvlist add error %d (devid)\n",
			    nvfd->nvf_name, rval));
			goto err;
		}

		rval = nvlist_add_nvlist(nvl, np->nvp_devpath, sub_nvl);
		if (rval != 0) {
			KFIOERR((CE_CONT, "%s: nvlist add error %d (sublist)\n",
			    nvfd->nvf_name, rval));
			goto err;
		}
		nvlist_free(sub_nvl);
	}

	*ret_nvl = nvl;
	return (DDI_SUCCESS);

err:
	if (sub_nvl)
		nvlist_free(sub_nvl);
	nvlist_free(nvl);
	*ret_nvl = NULL;
	return (DDI_FAILURE);
}
Exemple #2
0
static int
zpl_xattr_set_sa(struct inode *ip, const char *name, const void *value,
    size_t size, int flags, cred_t *cr)
{
	znode_t *zp = ITOZ(ip);
	nvlist_t *nvl;
	size_t sa_size;
	int error = 0;

	mutex_enter(&zp->z_lock);
	if (zp->z_xattr_cached == NULL)
		error = -zfs_sa_get_xattr(zp);
	mutex_exit(&zp->z_lock);

	if (error)
		return (error);

	ASSERT(zp->z_xattr_cached);
	nvl = zp->z_xattr_cached;

	if (value == NULL) {
		error = -nvlist_remove(nvl, name, DATA_TYPE_BYTE_ARRAY);
		if (error == -ENOENT)
			error = zpl_xattr_set_dir(ip, name, NULL, 0, flags, cr);
	} else {
		/* Limited to 32k to keep nvpair memory allocations small */
		if (size > DXATTR_MAX_ENTRY_SIZE)
			return (-EFBIG);

		/* Prevent the DXATTR SA from consuming the entire SA region */
		error = -nvlist_size(nvl, &sa_size, NV_ENCODE_XDR);
		if (error)
			return (error);

		if (sa_size > DXATTR_MAX_SA_SIZE)
			return (-EFBIG);

		error = -nvlist_add_byte_array(nvl, name,
		    (uchar_t *)value, size);
	}

	/*
	 * Update the SA for additions, modifications, and removals. On
	 * error drop the inconsistent cached version of the nvlist, it
	 * will be reconstructed from the ARC when next accessed.
	 */
	if (error == 0)
		error = -zfs_sa_set_xattr(zp);

	if (error) {
		nvlist_free(nvl);
		zp->z_xattr_cached = NULL;
	}

	ASSERT3S(error, <=, 0);

	return (error);
}
Exemple #3
0
/*
 * Generate reply event from resource registration information
 */
static void
generate_reply_event(int error, rcm_info_t *info, nvlist_t **ret)
{
	nvlist_t *nvl = NULL;
	rcm_info_t *tmp;
	char *buf = NULL;
	size_t buflen = 0;

	rcm_log_message(RCM_TRACE4, "generating reply event\n");

	/* Allocate an empty nvlist */
	if ((errno = nvlist_alloc(&nvl, 0, 0)) > 0) {
		rcm_log_message(RCM_ERROR,
		    gettext("nvlist_alloc failed: %s\n"), strerror(errno));
		rcmd_exit(errno);
	}

	/* Encode the result of the operation in the nvlist */
	if (errno = nvlist_add_int32(nvl, RCM_RESULT, error)) {
		rcm_log_message(RCM_ERROR,
		    gettext("nvlist_add(RESULT) failed: %s\n"),
		    strerror(errno));
		rcmd_exit(errno);
	}

	/* Go through the RCM info tuples, appending them all to the nvlist */
	tmp = info;
	while (tmp) {
		if (tmp->info) {
			buf = NULL;
			buflen = 0;
			if (errno = nvlist_pack(tmp->info, &buf, &buflen,
			    NV_ENCODE_NATIVE, 0)) {
				rcm_log_message(RCM_ERROR,
				    gettext("nvlist_pack(INFO) failed: %s\n"),
				    strerror(errno));
				rcmd_exit(errno);
			}
			if (errno = nvlist_add_byte_array(nvl, RCM_RESULT_INFO,
			    (uchar_t *)buf, buflen)) {
				rcm_log_message(RCM_ERROR,
				    gettext("nvlist_add(INFO) failed: %s\n"),
				    strerror(errno));
				rcmd_exit(errno);
			}
			(void) free(buf);
			nvlist_free(tmp->info);
		}
		info = tmp->next;
		(void) free(tmp);
		tmp = info;
	}

	/* Return the nvlist (unpacked) in the return argument */
	rcm_print_nvlist(nvl);
	*ret = nvl;
}
Exemple #4
0
/*
 * define a byte array property
 */
int
devctl_ddef_byte_array(devctl_ddef_t ddef_hdl, char *name, int nelements,
    uchar_t *value)
{
	int rv;

	if (ddef_hdl == NULL || name == NULL || *name == '\0') {
		errno = EINVAL;
		return (-1);
	}

	rv = nvlist_add_byte_array((nvlist_t *)ddef_hdl, name, value,
	    nelements);

	return (rv);
}
Exemple #5
0
static int
zpl_xattr_set_sa(struct inode *ip, const char *name, const void *value,
    size_t size, int flags, cred_t *cr)
{
	znode_t *zp = ITOZ(ip);
	nvlist_t *nvl;
	size_t sa_size;
	int error;

	ASSERT(zp->z_xattr_cached);
	nvl = zp->z_xattr_cached;

	if (value == NULL) {
		error = -nvlist_remove(nvl, name, DATA_TYPE_BYTE_ARRAY);
		if (error == -ENOENT)
			error = zpl_xattr_set_dir(ip, name, NULL, 0, flags, cr);
	} else {
		/* Do not allow SA xattrs in symlinks (issue #1648) */
		if (S_ISLNK(ip->i_mode))
			return (-EMLINK);

		/* Limited to 32k to keep nvpair memory allocations small */
		if (size > DXATTR_MAX_ENTRY_SIZE)
			return (-EFBIG);

		/* Prevent the DXATTR SA from consuming the entire SA region */
		error = -nvlist_size(nvl, &sa_size, NV_ENCODE_XDR);
		if (error)
			return (error);

		if (sa_size > DXATTR_MAX_SA_SIZE)
			return (-EFBIG);

		error = -nvlist_add_byte_array(nvl, name,
		    (uchar_t *)value, size);
		if (error)
			return (error);
	}

	/* Update the SA for additions, modifications, and removals. */
	if (!error)
		error = -zfs_sa_set_xattr(zp);

	ASSERT3S(error, <=, 0);

	return (error);
}
Exemple #6
0
int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
		       const struct lu_buf *buf, const char *name, int fl,
		       struct osd_thandle *oh)
{
	dmu_buf_impl_t *db;
	uchar_t *nv_value;
	size_t  size;
	int	nv_size;
	int	rc;
	int	too_big = 0;

	LASSERT(obj->oo_sa_hdl);
	if (obj->oo_sa_xattr == NULL) {
		rc = __osd_xattr_cache(env, obj);
		if (rc)
			return rc;
	}

	LASSERT(obj->oo_sa_xattr);
	/* Limited to 32k to keep nvpair memory allocations small */
	if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
		too_big = 1;
	} else {
		/* Prevent the DXATTR SA from consuming the entire SA
		 * region */
		rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
		if (rc)
			return rc;

		if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
			too_big = 1;
	}

	/* even in case of -EFBIG we must lookup xattr and check can we
	 * rewrite it then delete from SA */
	rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
					&nv_size);
	if (rc == 0) {
		if (fl & LU_XATTR_CREATE) {
			return -EEXIST;
		} else if (too_big) {
			rc = -nvlist_remove(obj->oo_sa_xattr, name,
						DATA_TYPE_BYTE_ARRAY);
			if (rc < 0)
				return rc;
			rc = __osd_sa_xattr_schedule_update(env, obj, oh);
			return rc == 0 ? -EFBIG : rc;
		}
	} else if (rc == -ENOENT) {
		if (fl & LU_XATTR_REPLACE)
			return -ENODATA;
		else if (too_big)
			return -EFBIG;
	} else {
		return rc;
	}

	/* Ensure xattr doesn't exist in ZAP */
	if (obj->oo_xattr != ZFS_NO_OBJECT) {
		struct osd_device *osd = osd_obj2dev(obj);
		uint64_t           objid;
		rc = -zap_lookup(osd->od_os, obj->oo_xattr,
				 name, 8, 1, &objid);
		if (rc == 0) {
			rc = -dmu_object_free(osd->od_os, objid, oh->ot_tx);
			if (rc == 0)
				zap_remove(osd->od_os, obj->oo_xattr,
					   name, oh->ot_tx);
		}
	}

	rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
				    (uchar_t *)buf->lb_buf, buf->lb_len);
	if (rc)
		return rc;

	/* batch updates only for just created dnodes where we
	 * used to set number of EAs in a single transaction */
	db = (dmu_buf_impl_t *)obj->oo_db;
	if (DB_DNODE(db)->dn_allocated_txg == oh->ot_tx->tx_txg)
		rc = __osd_sa_xattr_schedule_update(env, obj, oh);
	else
		rc = __osd_sa_xattr_update(env, obj, oh);

	return rc;
}
Exemple #7
0
void
fnvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *val, uint_t n)
{
	VERIFY0(nvlist_add_byte_array(nvl, name, val, n));
}
Exemple #8
0
int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
			const struct lu_buf *buf, const char *name, int fl,
			struct osd_thandle *oh)
{
	uchar_t *nv_value;
	size_t  size;
	int	nv_size;
	int	rc;
	int	too_big = 0;

	LASSERT(obj->oo_sa_hdl);
	if (obj->oo_sa_xattr == NULL) {
		rc = __osd_xattr_cache(env, obj);
		if (rc)
			return rc;
	}

	LASSERT(obj->oo_sa_xattr);
	/* Limited to 32k to keep nvpair memory allocations small */
	if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
		too_big = 1;
	} else {
		/* Prevent the DXATTR SA from consuming the entire SA
		 * region */
		rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
		if (rc)
			return rc;

		if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
			too_big = 1;
	}

	/* even in case of -EFBIG we must lookup xattr and check can we
	 * rewrite it then delete from SA */
	rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
					&nv_size);
	if (rc == 0) {
		if (fl & LU_XATTR_CREATE) {
			return -EEXIST;
		} else if (too_big) {
			rc = -nvlist_remove(obj->oo_sa_xattr, name,
						DATA_TYPE_BYTE_ARRAY);
			if (rc < 0)
				return rc;
			rc = __osd_sa_xattr_update(env, obj, oh);
			return rc == 0 ? -EFBIG : rc;
		}
	} else if (rc == -ENOENT) {
		if (fl & LU_XATTR_REPLACE)
			return -ENODATA;
		else if (too_big)
			return -EFBIG;
	} else {
		return rc;
	}

	rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
				    (uchar_t *)buf->lb_buf, buf->lb_len);
	if (rc)
		return rc;

	rc = __osd_sa_xattr_update(env, obj, oh);
	return rc;
}
/*
 * cmd_changestate()
 *
 *	Implements the door command to initate a state change operation.
 *
 *	NOTE: requires 'modify' authorization.
 */
static int
cmd_changestate(nvlist_t *args, nvlist_t **resultsp)
{
    hp_node_t	root = NULL;
    nvlist_t	*results = NULL;
    char		*path, *connection;
    ucred_t		*uc = NULL;
    uint_t		flags;
    int		rv, state, old_state, status;

    dprintf("cmd_changestate:\n");

    /* Get arguments */
    if ((nvlist_lookup_string(args, HPD_PATH, &path) != 0) ||
            (nvlist_lookup_string(args, HPD_CONNECTION, &connection) != 0) ||
            (nvlist_lookup_int32(args, HPD_STATE, &state) != 0)) {
        dprintf("cmd_changestate: invalid arguments.\n");
        return (EINVAL);
    }
    if (nvlist_lookup_uint32(args, HPD_FLAGS, (uint32_t *)&flags) != 0)
        flags = 0;

    /* Get caller's credentials */
    if (door_ucred(&uc) != 0) {
        log_err("Cannot get door credentials (%s)\n", strerror(errno));
        return (EACCES);
    }

    /* Check authorization */
    if (check_auth(uc, HP_MODIFY_AUTH) != 0) {
        dprintf("cmd_changestate: access denied.\n");
        audit_changestate(uc, HP_MODIFY_AUTH, path, connection,
                          state, -1, ADT_FAIL_VALUE_AUTH);
        ucred_free(uc);
        return (EACCES);
    }

    /* Perform the state change operation */
    status = changestate(path, connection, state, flags, &old_state, &root);
    dprintf("cmd_changestate: changestate() == %d\n", status);

    /* Audit the operation */
    audit_changestate(uc, HP_MODIFY_AUTH, path, connection, state,
                      old_state, status);

    /* Caller's credentials no longer needed */
    ucred_free(uc);

    /*
     * Pack the results into an nvlist if there is an error snapshot.
     *
     * If any error occurs while packing the results, the original
     * error code from changestate() above is still returned.
     */
    if (root != NULL) {
        char	*buf = NULL;
        size_t	len = 0;

        dprintf("cmd_changestate: results nvlist required.\n");

        /* Pack and discard the error snapshot */
        rv = hp_pack(root, &buf, &len);
        hp_fini(root);
        if (rv != 0) {
            dprintf("cmd_changestate: hp_pack() failed (%s).\n",
                    strerror(rv));
            return (status);
        }

        /* Allocate nvlist for results */
        if (nvlist_alloc(&results, NV_UNIQUE_NAME_TYPE, 0) != 0) {
            dprintf("cmd_changestate: nvlist_alloc() failed.\n");
            free(buf);
            return (status);
        }

        /* Add the results into the nvlist */
        if ((nvlist_add_int32(results, HPD_STATUS, status) != 0) ||
                (nvlist_add_byte_array(results, HPD_INFO, (uchar_t *)buf,
                                       len) != 0)) {
            dprintf("cmd_changestate: nvlist add failed.\n");
            nvlist_free(results);
            free(buf);
            return (status);
        }

        *resultsp = results;
    }

    return (status);
}
Exemple #10
0
/*
 * cmd_getinfo()
 *
 *	Implements the door command to get a hotplug information snapshot.
 */
static int
cmd_getinfo(nvlist_t *args, nvlist_t **resultsp)
{
    hp_node_t	root;
    nvlist_t	*results;
    char		*path;
    char		*connection;
    char		*buf = NULL;
    size_t		len = 0;
    uint_t		flags;
    int		rv;

    dprintf("cmd_getinfo:\n");

    /* Get arguments */
    if (nvlist_lookup_string(args, HPD_PATH, &path) != 0) {
        dprintf("cmd_getinfo: invalid arguments.\n");
        return (EINVAL);
    }
    if (nvlist_lookup_string(args, HPD_CONNECTION, &connection) != 0)
        connection = NULL;
    if (nvlist_lookup_uint32(args, HPD_FLAGS, (uint32_t *)&flags) != 0)
        flags = 0;

    /* Get and pack the requested snapshot */
    if ((rv = getinfo(path, connection, flags, &root)) == 0) {
        rv = hp_pack(root, &buf, &len);
        hp_fini(root);
    }
    dprintf("cmd_getinfo: getinfo(): rv = %d, buf = %p.\n", rv,
            (void *)buf);

    /*
     * If the above failed or there is no snapshot,
     * then only return a status code.
     */
    if (rv != 0)
        return (rv);
    if (buf == NULL)
        return (EFAULT);

    /* Allocate nvlist for results */
    if (nvlist_alloc(&results, NV_UNIQUE_NAME_TYPE, 0) != 0) {
        dprintf("cmd_getinfo: nvlist_alloc() failed.\n");
        free(buf);
        return (ENOMEM);
    }

    /* Add snapshot and successful status to results */
    if ((nvlist_add_int32(results, HPD_STATUS, 0) != 0) ||
            (nvlist_add_byte_array(results, HPD_INFO,
                                   (uchar_t *)buf, len) != 0)) {
        dprintf("cmd_getinfo: nvlist add failure.\n");
        nvlist_free(results);
        free(buf);
        return (ENOMEM);
    }

    /* Packed snapshot no longer needed */
    free(buf);

    /* Success */
    *resultsp = results;
    return (0);
}
Exemple #11
0
/*
 * This is also called from the userland bootinfo_aux.c to initialize
 * its bootmisc data.
 */
boolean_t
bi_put_bootmisc(const char *name, const void *valbuf, size_t vallen)
{
	return (nvlist_add_byte_array(bi_nvl, (char *)name,
	    (uchar_t *)valbuf, (uint_t)vallen) == 0);
}
Exemple #12
0
/*
 * Concurrency: @dt is write locked.
 */
static int osd_object_create(const struct lu_env *env, struct dt_object *dt,
			     struct lu_attr *attr,
			     struct dt_allocation_hint *hint,
			     struct dt_object_format *dof,
			     struct thandle *th)
{
	struct osd_thread_info	*info = osd_oti_get(env);
	struct lustre_mdt_attrs	*lma = &info->oti_mdt_attrs;
	struct zpl_direntry	*zde = &info->oti_zde.lzd_reg;
	const struct lu_fid	*fid = lu_object_fid(&dt->do_lu);
	struct osd_object	*obj = osd_dt_obj(dt);
	struct osd_device	*osd = osd_obj2dev(obj);
	char			*buf = info->oti_str;
	struct osd_thandle	*oh;
	dmu_buf_t		*db = NULL;
	uint64_t		 zapid, parent = 0;
	int			 rc;

	ENTRY;

	/* concurrent create declarations should not see
	 * the object inconsistent (db, attr, etc).
	 * in regular cases acquisition should be cheap */
	down_write(&obj->oo_guard);

	if (unlikely(dt_object_exists(dt)))
		GOTO(out, rc = -EEXIST);

	LASSERT(osd_invariant(obj));
	LASSERT(dof != NULL);

	LASSERT(th != NULL);
	oh = container_of0(th, struct osd_thandle, ot_super);

	/*
	 * XXX missing: Quote handling.
	 */

	LASSERT(obj->oo_db == NULL);

	/* to follow ZFS on-disk format we need
	 * to initialize parent dnode properly */
	if (hint != NULL && hint->dah_parent != NULL &&
	    !dt_object_remote(hint->dah_parent))
		parent = osd_dt_obj(hint->dah_parent)->oo_db->db_object;

	/* we may fix some attributes, better do not change the source */
	obj->oo_attr = *attr;
	obj->oo_attr.la_valid |= LA_SIZE | LA_NLINK | LA_TYPE;

	db = osd_create_type_f(dof->dof_type)(env, obj, &obj->oo_attr, oh);
	if (IS_ERR(db)) {
		rc = PTR_ERR(db);
		db = NULL;
		GOTO(out, rc);
	}

	zde->zde_pad = 0;
	zde->zde_dnode = db->db_object;
	zde->zde_type = IFTODT(attr->la_mode & S_IFMT);

	zapid = osd_get_name_n_idx(env, osd, fid, buf, sizeof(info->oti_str));

	rc = -zap_add(osd->od_os, zapid, buf, 8, 1, zde, oh->ot_tx);
	if (rc)
		GOTO(out, rc);

	/* Now add in all of the "SA" attributes */
	rc = -sa_handle_get(osd->od_os, db->db_object, NULL,
			    SA_HDL_PRIVATE, &obj->oo_sa_hdl);
	if (rc)
		GOTO(out, rc);

	/* configure new osd object */
	obj->oo_db = db;
	parent = parent != 0 ? parent : zapid;
	rc = __osd_attr_init(env, osd, obj->oo_sa_hdl, oh->ot_tx,
			     &obj->oo_attr, parent);
	if (rc)
		GOTO(out, rc);

	/* XXX: oo_lma_flags */
	obj->oo_dt.do_lu.lo_header->loh_attr |= obj->oo_attr.la_mode & S_IFMT;
	smp_mb();
	obj->oo_dt.do_lu.lo_header->loh_attr |= LOHA_EXISTS;
	if (likely(!fid_is_acct(lu_object_fid(&obj->oo_dt.do_lu))))
		/* no body operations for accounting objects */
		obj->oo_dt.do_body_ops = &osd_body_ops;

	rc = -nvlist_alloc(&obj->oo_sa_xattr, NV_UNIQUE_NAME, KM_SLEEP);
	if (rc)
		GOTO(out, rc);

	/* initialize LMA */
	lustre_lma_init(lma, lu_object_fid(&obj->oo_dt.do_lu), 0, 0);
	lustre_lma_swab(lma);
	rc = -nvlist_add_byte_array(obj->oo_sa_xattr, XATTR_NAME_LMA,
				    (uchar_t *)lma, sizeof(*lma));
	if (rc)
		GOTO(out, rc);
	rc = __osd_sa_xattr_update(env, obj, oh);
	if (rc)
		GOTO(out, rc);

	/* Add new object to inode accounting.
	 * Errors are not considered as fatal */
	rc = -zap_increment_int(osd->od_os, osd->od_iusr_oid,
				(attr->la_valid & LA_UID) ? attr->la_uid : 0, 1,
				oh->ot_tx);
	if (rc)
		CERROR("%s: failed to add "DFID" to accounting ZAP for usr %d "
			"(%d)\n", osd->od_svname, PFID(fid), attr->la_uid, rc);
	rc = -zap_increment_int(osd->od_os, osd->od_igrp_oid,
				(attr->la_valid & LA_GID) ? attr->la_gid : 0, 1,
				oh->ot_tx);
	if (rc)
		CERROR("%s: failed to add "DFID" to accounting ZAP for grp %d "
			"(%d)\n", osd->od_svname, PFID(fid), attr->la_gid, rc);

out:
	if (unlikely(rc && db)) {
		dmu_object_free(osd->od_os, db->db_object, oh->ot_tx);
		sa_buf_rele(db, osd_obj_tag);
		obj->oo_db = NULL;
	}
	up_write(&obj->oo_guard);
	RETURN(rc);
}