/* * 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); }
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); }
/* * 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; }
/* * 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); }
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); }
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; }
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)); }
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); }
/* * 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); }
/* * 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); }
/* * 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); }