-/* $OpenBSD: vioscsi.c,v 1.7 2018/07/10 20:43:15 reyk Exp $ */
+/* $OpenBSD: vioscsi.c,v 1.8 2018/07/15 14:36:54 reyk Exp $ */
/*
* Copyright (c) 2017 Carlos Cardenas <ccardenas@openbsd.org>
inq = (struct scsi_inquiry *)(req->cdb);
inq_len = (uint16_t)_2btol(inq->length);
- log_debug("%s: INQ - EVPD %d PAGE_CODE 0x%08x LEN %d", __func__,
+ DPRINTF("%s: INQ - EVPD %d PAGE_CODE 0x%08x LEN %d", __func__,
inq->flags & SI_EVPD, inq->pagecode, inq_len);
vioscsi_prepare_resp(&resp,
mode_page_ctl = mode_sense->page & SMS_PAGE_CTRL;
mode_page_code = mode_sense->page & SMS_PAGE_CODE;
- log_debug("%s: M_SENSE - DBD %d Page Ctrl 0x%x Code 0x%x Len %u",
+ DPRINTF("%s: M_SENSE - DBD %d Page Ctrl 0x%x Code 0x%x Len %u",
__func__, mode_sense->byte2 & SMS_DBD, mode_page_ctl,
mode_page_code, mode_sense->length);
mode_page_code = mode_sense_10->page & SMS_PAGE_CODE;
mode_sense_len = (uint16_t)_2btol(mode_sense_10->length);
- log_debug("%s: M_SENSE_10 - DBD %d Page Ctrl 0x%x Code 0x%x Len %u",
+ DPRINTF("%s: M_SENSE_10 - DBD %d Page Ctrl 0x%x Code 0x%x Len %u",
__func__, mode_sense_10->byte2 & SMS_DBD, mode_page_ctl,
mode_page_code, mode_sense_len);
memset(&resp, 0, sizeof(resp));
r_cap = (struct scsi_read_capacity *)(req->cdb);
r_cap_addr = _4btol(r_cap->addr);
- log_debug("%s: %s - Addr 0x%08x", __func__,
+ DPRINTF("%s: %s - Addr 0x%08x", __func__,
vioscsi_op_names(r_cap->opcode), r_cap_addr);
vioscsi_prepare_resp(&resp,
goto read_capacity_out;
}
- log_debug("%s: ISO has %lld bytes and %lld blocks",
+ DPRINTF("%s: ISO has %lld bytes and %lld blocks",
__func__, dev->sz, dev->n_blocks);
/*
memset(&resp, 0, sizeof(resp));
r_cap_16 = (struct scsi_read_capacity_16 *)(req->cdb);
r_cap_addr_16 = _8btol(r_cap_16->addr);
- log_debug("%s: %s - Addr 0x%016llx", __func__,
+ DPRINTF("%s: %s - Addr 0x%016llx", __func__,
vioscsi_op_names(r_cap_16->opcode), r_cap_addr_16);
vioscsi_prepare_resp(&resp, VIRTIO_SCSI_S_OK, SCSI_OK, 0, 0, 0);
goto read_capacity_16_out;
}
- log_debug("%s: ISO has %lld bytes and %lld blocks", __func__,
+ DPRINTF("%s: ISO has %lld bytes and %lld blocks", __func__,
dev->sz, dev->n_blocks);
_lto8b(dev->n_blocks - 1, r_cap_data_16->addr);
rpl = (struct scsi_report_luns *)(req->cdb);
rpl_length = _4btol(rpl->length);
- log_debug("%s: REPORT_LUNS Report 0x%x Length %d", __func__,
+ DPRINTF("%s: REPORT_LUNS Report 0x%x Length %d", __func__,
rpl->selectreport, rpl_length);
if (rpl_length < RPL_MIN_SIZE) {
- log_debug("%s: RPL_Length %d < %d (RPL_MIN_SIZE)", __func__,
+ DPRINTF("%s: RPL_Length %d < %d (RPL_MIN_SIZE)", __func__,
rpl_length, RPL_MIN_SIZE);
vioscsi_prepare_resp(&resp,
read_lba = ((read_6->addr[0] & SRW_TOPADDR) << 16 ) |
(read_6->addr[1] << 8) | read_6->addr[2];
- log_debug("%s: READ Addr 0x%08x Len %d (%d)",
+ DPRINTF("%s: READ Addr 0x%08x Len %d (%d)",
__func__, read_lba, read_6->length, read_6->length * dev->max_xfer);
/* check if lba is in range */
if (read_lba > dev->n_blocks - 1) {
- log_debug("%s: requested block out of range req: %ud max: %lld",
+ DPRINTF("%s: requested block out of range req: %ud max: %lld",
__func__, read_lba, dev->n_blocks);
vioscsi_prepare_resp(&resp,
read_10_len = _2btol(read_10->length);
chunk_offset = 0;
- log_debug("%s: READ_10 Addr 0x%08x Len %d (%d)",
+ DPRINTF("%s: READ_10 Addr 0x%08x Len %d (%d)",
__func__, read_lba, read_10_len, read_10_len * dev->max_xfer);
/* check if lba is in range */
if (read_lba > dev->n_blocks - 1) {
- log_debug("%s: requested block out of range req: %ud max: %lld",
+ DPRINTF("%s: requested block out of range req: %ud max: %lld",
__func__, read_lba, dev->n_blocks);
vioscsi_prepare_resp(&resp,
vioscsi_prepare_resp(&resp, VIRTIO_SCSI_S_OK, SCSI_OK, 0, 0, 0);
if (dev->locked) {
- log_debug("%s: unlocking medium", __func__);
+ DPRINTF("%s: unlocking medium", __func__);
} else {
- log_debug("%s: locking medium", __func__);
+ DPRINTF("%s: locking medium", __func__);
}
dev->locked = dev->locked ? 0 : 1;
memset(&resp, 0, sizeof(resp));
mech_status = (struct scsi_mechanism_status *)(req->cdb);
mech_status_len = (uint16_t)_2btol(mech_status->length);
- log_debug("%s: MECH_STATUS Len %u", __func__, mech_status_len);
+ DPRINTF("%s: MECH_STATUS Len %u", __func__, mech_status_len);
mech_status_header = calloc(1, sizeof(*mech_status_header));
memset(&resp, 0, sizeof(resp));
toc = (struct scsi_read_toc *)(req->cdb);
toc_len = (uint16_t)_2btol(toc->data_len);
- log_debug("%s: %s - MSF %d Track 0x%02x Addr 0x%04x",
+ DPRINTF("%s: %s - MSF %d Track 0x%02x Addr 0x%04x",
__func__, vioscsi_op_names(toc->opcode),
((toc->byte2 >> 1) & 1), toc->from_track, toc_len);
if (toc->from_track > 1 &&
toc->from_track != READ_TOC_LEAD_OUT_TRACK) {
/* illegal request */
- log_debug("%s: illegal request Track 0x%02x",
+ DPRINTF("%s: illegal request Track 0x%02x",
__func__, toc->from_track);
vioscsi_prepare_resp(&resp,
memset(&resp, 0, sizeof(resp));
read_disc =
(struct scsi_read_disc_information *)(req->cdb);
- log_debug("%s: Disc Info %x", __func__, read_disc->byte2);
+ DPRINTF("%s: Disc Info %x", __func__, read_disc->byte2);
/* send back unsupported */
vioscsi_prepare_resp(&resp,
memset(&resp, 0, sizeof(resp));
gesn = (struct scsi_gesn *)(req->cdb);
- log_debug("%s: GESN Method %s", __func__,
+ DPRINTF("%s: GESN Method %s", __func__,
gesn->byte2 ? "Polling" : "Asynchronous");
if (gesn->byte2 == 0) {
get_configuration = (struct scsi_get_configuration *)(req->cdb);
get_conf_feature = (uint16_t)_2btol(get_configuration->feature);
get_conf_len = (uint16_t)_2btol(get_configuration->length);
- log_debug("%s: Conf RT %x Feature %d Len %d", __func__,
+ DPRINTF("%s: Conf RT %x Feature %d Len %d", __func__,
get_configuration->byte2, get_conf_feature, get_conf_len);
get_conf_reply = (uint8_t*)calloc(G_CONFIG_REPLY_SIZE, sizeof(uint8_t));
*intr = 0xFF;
- log_debug("%s: request %s reg %u,%s sz %u", __func__,
+ DPRINTF("%s: request %s reg %u,%s sz %u", __func__,
dir ? "READ" : "WRITE", reg, vioscsi_reg_name(reg), sz);
if (dir == 0) {
break;
case VIRTIO_CONFIG_GUEST_FEATURES:
dev->cfg.guest_feature = *data;
- log_debug("%s: guest feature set to %u",
+ DPRINTF("%s: guest feature set to %u",
__func__, dev->cfg.guest_feature);
break;
case VIRTIO_CONFIG_QUEUE_ADDRESS:
break;
case VIRTIO_CONFIG_DEVICE_STATUS:
dev->cfg.device_status = *data;
- log_debug("%s: device status set to %u",
+ DPRINTF("%s: device status set to %u",
__func__, dev->cfg.device_status);
if (dev->cfg.device_status == 0) {
- log_debug("%s: device reset", __func__);
+ DPRINTF("%s: device reset", __func__);
dev->cfg.guest_feature = 0;
dev->cfg.queue_address = 0;
vioscsi_update_qa(dev);
* respond with a BAD_TARGET response.
*/
if (req.lun[1] >= VIOSCSI_MAX_TARGET || req.lun[3] > 0) {
- log_debug("%s: Ignore CMD 0x%02x,%s on lun %u:%u:%u:%u",
+ DPRINTF("%s: Ignore CMD 0x%02x,%s on lun %u:%u:%u:%u",
__func__, req.cdb[0], vioscsi_op_names(req.cdb[0]),
req.lun[0], req.lun[1], req.lun[2], req.lun[3]);
/* Move index for response */
goto next_msg;
}
- log_debug("%s: Queue %d id 0x%llx lun %u:%u:%u:%u"
+ DPRINTF("%s: Queue %d id 0x%llx lun %u:%u:%u:%u"
" cdb OP 0x%02x,%s",
__func__, dev->cfg.queue_notify, req.id,
req.lun[0], req.lun[1], req.lun[2], req.lun[3],
-/* $OpenBSD: vmd.c,v 1.97 2018/07/13 10:26:57 reyk Exp $ */
+/* $OpenBSD: vmd.c,v 1.98 2018/07/15 14:36:54 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
#include <signal.h>
#include <syslog.h>
#include <unistd.h>
+#include <util.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
vm->vm_running = 0;
vm->vm_shutdown = 0;
+ user_inc(&vm->vm_params.vmc_params, vm->vm_user, 0);
+ user_put(vm->vm_user);
+
if (vm->vm_iev.ibuf.fd != -1) {
event_del(&vm->vm_iev.ev);
close(vm->vm_iev.ibuf.fd);
TAILQ_REMOVE(env->vmd_vms, vm, vm_entry);
+ user_put(vm->vm_user);
vm_stop(vm, 0, caller);
free(vm);
}
struct vmd_vm *vm = NULL, *vm_parent = NULL;
struct vm_create_params *vcp = &vmc->vmc_params;
struct vmop_owner *vmo = NULL;
+ struct vmd_user *usr = NULL;
uint32_t rng;
unsigned int i;
struct vmd_switch *sw;
}
}
+ /* track active users */
+ if (uid != 0 && env->vmd_users != NULL &&
+ (usr = user_get(uid)) == NULL) {
+ log_warnx("could not add user");
+ goto fail;
+ }
+
if ((vm = calloc(1, sizeof(*vm))) == NULL)
goto fail;
vm->vm_tty = -1;
vm->vm_receive_fd = -1;
vm->vm_paused = 0;
+ vm->vm_user = usr;
for (i = 0; i < vcp->vcp_ndisks; i++)
vm->vm_disks[i] = -1;
return (NULL);
}
+struct vmd_user *
+user_get(uid_t uid)
+{
+ struct vmd_user *usr;
+
+ if (uid == 0)
+ return (NULL);
+
+ /* first try to find an existing user */
+ TAILQ_FOREACH(usr, env->vmd_users, usr_entry) {
+ if (usr->usr_id.uid == uid)
+ goto done;
+ }
+
+ if ((usr = calloc(1, sizeof(*usr))) == NULL) {
+ log_warn("could not allocate user");
+ return (NULL);
+ }
+
+ usr->usr_id.uid = uid;
+ usr->usr_id.gid = -1;
+ TAILQ_INSERT_TAIL(env->vmd_users, usr, usr_entry);
+
+ done:
+ DPRINTF("%s: uid %d #%d +",
+ __func__, usr->usr_id.uid, usr->usr_refcnt + 1);
+ usr->usr_refcnt++;
+
+ return (usr);
+}
+
+void
+user_put(struct vmd_user *usr)
+{
+ if (usr == NULL)
+ return;
+
+ DPRINTF("%s: uid %d #%d -",
+ __func__, usr->usr_id.uid, usr->usr_refcnt - 1);
+
+ if (--usr->usr_refcnt > 0)
+ return;
+
+ TAILQ_REMOVE(env->vmd_users, usr, usr_entry);
+ free(usr);
+}
+
+void
+user_inc(struct vm_create_params *vcp, struct vmd_user *usr, int inc)
+{
+ char mem[FMT_SCALED_STRSIZE];
+
+ if (usr == NULL)
+ return;
+
+ /* increment or decrement counters */
+ inc = inc ? 1 : -1;
+
+ usr->usr_maxcpu += vcp->vcp_ncpus * inc;
+ usr->usr_maxmem += vcp->vcp_memranges[0].vmr_size * inc;
+ usr->usr_maxifs += vcp->vcp_nnics * inc;
+
+ if (log_getverbose() > 1) {
+ (void)fmt_scaled(usr->usr_maxmem * 1024 * 1024, mem);
+ log_debug("%s: %c uid %d ref %d cpu %llu mem %s ifs %llu",
+ __func__, inc == 1 ? '+' : '-',
+ usr->usr_id.uid, usr->usr_refcnt,
+ usr->usr_maxcpu, mem, usr->usr_maxifs);
+ }
+}
+
+int
+user_checklimit(struct vmd_user *usr, struct vm_create_params *vcp)
+{
+ const char *limit = "";
+
+ /* XXX make the limits configurable */
+ if (usr->usr_maxcpu > VM_DEFAULT_USER_MAXCPU) {
+ limit = "cpu ";
+ goto fail;
+ }
+ if (usr->usr_maxcpu > VM_DEFAULT_USER_MAXMEM) {
+ limit = "memory ";
+ goto fail;
+ }
+ if (usr->usr_maxifs > VM_DEFAULT_USER_MAXIFS) {
+ limit = "interface ";
+ goto fail;
+ }
+
+ return (0);
+
+ fail:
+ log_warnx("%s: user %d %slimit reached", vcp->vcp_name,
+ usr->usr_id.uid, limit);
+ return (-1);
+}
+
char *
get_string(uint8_t *ptr, size_t len)
{