Home | History | Annotate | Line # | Download | only in librumpuser
rumpuser.c revision 1.15.4.5
      1  1.15.4.5   yamt /*	$NetBSD: rumpuser.c,v 1.15.4.5 2014/05/22 11:37:00 yamt Exp $	*/
      2       1.1  pooka 
      3       1.1  pooka /*
      4       1.1  pooka  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
      5       1.1  pooka  *
      6       1.1  pooka  * Redistribution and use in source and binary forms, with or without
      7       1.1  pooka  * modification, are permitted provided that the following conditions
      8       1.1  pooka  * are met:
      9       1.1  pooka  * 1. Redistributions of source code must retain the above copyright
     10       1.1  pooka  *    notice, this list of conditions and the following disclaimer.
     11       1.1  pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.1  pooka  *    notice, this list of conditions and the following disclaimer in the
     13       1.1  pooka  *    documentation and/or other materials provided with the distribution.
     14       1.1  pooka  *
     15       1.1  pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16       1.1  pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17       1.1  pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18       1.1  pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19       1.1  pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20       1.1  pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21       1.1  pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22       1.1  pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23       1.1  pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24       1.1  pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25       1.1  pooka  * SUCH DAMAGE.
     26       1.1  pooka  */
     27       1.1  pooka 
     28  1.15.4.2   yamt #include "rumpuser_port.h"
     29  1.15.4.2   yamt 
     30       1.1  pooka #if !defined(lint)
     31  1.15.4.5   yamt __RCSID("$NetBSD: rumpuser.c,v 1.15.4.5 2014/05/22 11:37:00 yamt Exp $");
     32       1.1  pooka #endif /* !lint */
     33       1.1  pooka 
     34       1.1  pooka #include <sys/ioctl.h>
     35       1.1  pooka #include <sys/mman.h>
     36       1.1  pooka #include <sys/uio.h>
     37  1.15.4.2   yamt #include <sys/stat.h>
     38  1.15.4.2   yamt #include <sys/time.h>
     39       1.1  pooka 
     40       1.1  pooka #ifdef __NetBSD__
     41      1.15  pooka #include <sys/disk.h>
     42       1.1  pooka #include <sys/disklabel.h>
     43      1.15  pooka #include <sys/dkio.h>
     44       1.1  pooka #endif
     45       1.1  pooka 
     46  1.15.4.5   yamt #if defined(__NetBSD__) || defined(__FreeBSD__) || \
     47  1.15.4.5   yamt     defined(__DragonFly__) || defined(__APPLE__)
     48  1.15.4.5   yamt #define	__BSD__
     49  1.15.4.5   yamt #endif
     50  1.15.4.5   yamt 
     51  1.15.4.5   yamt #if defined(__BSD__)
     52  1.15.4.4   yamt #include <sys/sysctl.h>
     53  1.15.4.4   yamt #endif
     54  1.15.4.4   yamt 
     55       1.1  pooka #include <assert.h>
     56       1.1  pooka #include <errno.h>
     57       1.1  pooka #include <fcntl.h>
     58  1.15.4.3   yamt #include <netdb.h>
     59       1.2  pooka #include <signal.h>
     60       1.1  pooka #include <stdarg.h>
     61       1.1  pooka #include <stdint.h>
     62       1.1  pooka #include <stdio.h>
     63       1.1  pooka #include <stdlib.h>
     64       1.1  pooka #include <string.h>
     65       1.1  pooka #include <time.h>
     66       1.1  pooka #include <unistd.h>
     67       1.1  pooka 
     68       1.1  pooka #include <rump/rumpuser.h>
     69       1.1  pooka 
     70       1.1  pooka #include "rumpuser_int.h"
     71       1.1  pooka 
     72  1.15.4.5   yamt struct rumpuser_hyperup rumpuser__hyp;
     73  1.15.4.5   yamt 
     74       1.1  pooka int
     75  1.15.4.5   yamt rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
     76       1.8  pooka {
     77       1.8  pooka 
     78  1.15.4.5   yamt 	if (version != RUMPUSER_VERSION) {
     79  1.15.4.5   yamt 		fprintf(stderr, "rumpuser mismatch, kern: %d, hypervisor %d\n",
     80  1.15.4.5   yamt 		    version, RUMPUSER_VERSION);
     81  1.15.4.5   yamt 		return 1;
     82  1.15.4.5   yamt 	}
     83  1.15.4.5   yamt 
     84  1.15.4.5   yamt #ifdef RUMPUSER_USE_DEVRANDOM
     85  1.15.4.5   yamt 	uint32_t rv;
     86  1.15.4.5   yamt 	int fd;
     87  1.15.4.5   yamt 
     88  1.15.4.5   yamt 	if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
     89  1.15.4.5   yamt 		srandom(time(NULL));
     90  1.15.4.5   yamt 	} else {
     91  1.15.4.5   yamt 		if (read(fd, &rv, sizeof(rv)) != sizeof(rv))
     92  1.15.4.5   yamt 			srandom(time(NULL));
     93  1.15.4.5   yamt 		else
     94  1.15.4.5   yamt 			srandom(rv);
     95  1.15.4.5   yamt 		close(fd);
     96  1.15.4.5   yamt 	}
     97  1.15.4.5   yamt #endif
     98  1.15.4.5   yamt 
     99  1.15.4.5   yamt 	rumpuser__thrinit();
    100  1.15.4.5   yamt 	rumpuser__hyp = *hyp;
    101  1.15.4.5   yamt 
    102  1.15.4.5   yamt 	return 0;
    103       1.8  pooka }
    104       1.8  pooka 
    105       1.8  pooka int
    106  1.15.4.5   yamt rumpuser_getfileinfo(const char *path, uint64_t *sizep, int *ftp)
    107       1.1  pooka {
    108       1.1  pooka 	struct stat sb;
    109  1.15.4.5   yamt 	uint64_t size = 0;
    110  1.15.4.5   yamt 	int needsdev = 0, rv = 0, ft = 0;
    111      1.12  pooka 	int fd = -1;
    112       1.1  pooka 
    113       1.1  pooka 	if (stat(path, &sb) == -1) {
    114  1.15.4.5   yamt 		rv = errno;
    115  1.15.4.5   yamt 		goto out;
    116       1.1  pooka 	}
    117       1.1  pooka 
    118       1.1  pooka 	switch (sb.st_mode & S_IFMT) {
    119       1.1  pooka 	case S_IFDIR:
    120       1.1  pooka 		ft = RUMPUSER_FT_DIR;
    121       1.1  pooka 		break;
    122       1.1  pooka 	case S_IFREG:
    123       1.1  pooka 		ft = RUMPUSER_FT_REG;
    124       1.1  pooka 		break;
    125       1.1  pooka 	case S_IFBLK:
    126       1.1  pooka 		ft = RUMPUSER_FT_BLK;
    127       1.1  pooka 		needsdev = 1;
    128       1.1  pooka 		break;
    129       1.1  pooka 	case S_IFCHR:
    130       1.1  pooka 		ft = RUMPUSER_FT_CHR;
    131       1.1  pooka 		needsdev = 1;
    132       1.1  pooka 		break;
    133       1.1  pooka 	default:
    134       1.1  pooka 		ft = RUMPUSER_FT_OTHER;
    135       1.1  pooka 		break;
    136       1.1  pooka 	}
    137       1.1  pooka 
    138       1.1  pooka 	if (!needsdev) {
    139       1.1  pooka 		size = sb.st_size;
    140       1.1  pooka 	} else if (sizep) {
    141       1.1  pooka 		/*
    142       1.1  pooka 		 * Welcome to the jungle.  Of course querying the kernel
    143       1.1  pooka 		 * for a device partition size is supposed to be far from
    144       1.1  pooka 		 * trivial.  On NetBSD we use ioctl.  On $other platform
    145       1.1  pooka 		 * we have a problem.  We try "the lseek trick" and just
    146       1.1  pooka 		 * fail if that fails.  Platform specific code can later
    147       1.1  pooka 		 * be written here if appropriate.
    148       1.1  pooka 		 *
    149       1.1  pooka 		 * On NetBSD we hope and pray that for block devices nobody
    150       1.1  pooka 		 * else is holding them open, because otherwise the kernel
    151       1.1  pooka 		 * will not permit us to open it.  Thankfully, this is
    152       1.1  pooka 		 * usually called only in bootstrap and then we can
    153       1.1  pooka 		 * forget about it.
    154       1.1  pooka 		 */
    155       1.1  pooka #ifndef __NetBSD__
    156       1.1  pooka 		off_t off;
    157       1.1  pooka 
    158       1.1  pooka 		fd = open(path, O_RDONLY);
    159       1.1  pooka 		if (fd == -1) {
    160  1.15.4.5   yamt 			rv = errno;
    161       1.1  pooka 			goto out;
    162       1.1  pooka 		}
    163       1.1  pooka 
    164       1.1  pooka 		off = lseek(fd, 0, SEEK_END);
    165       1.1  pooka 		if (off != 0) {
    166       1.1  pooka 			size = off;
    167       1.1  pooka 			goto out;
    168       1.1  pooka 		}
    169       1.1  pooka 		fprintf(stderr, "error: device size query not implemented on "
    170       1.1  pooka 		    "this platform\n");
    171  1.15.4.5   yamt 		rv = EOPNOTSUPP;
    172       1.1  pooka 		goto out;
    173       1.1  pooka #else
    174       1.1  pooka 		struct disklabel lab;
    175       1.1  pooka 		struct partition *parta;
    176      1.15  pooka 		struct dkwedge_info dkw;
    177       1.1  pooka 
    178       1.1  pooka 		fd = open(path, O_RDONLY);
    179       1.1  pooka 		if (fd == -1) {
    180  1.15.4.5   yamt 			rv = errno;
    181       1.1  pooka 			goto out;
    182       1.1  pooka 		}
    183       1.1  pooka 
    184      1.15  pooka 		if (ioctl(fd, DIOCGDINFO, &lab) == 0) {
    185      1.15  pooka 			parta = &lab.d_partitions[DISKPART(sb.st_rdev)];
    186      1.15  pooka 			size = (uint64_t)lab.d_secsize * parta->p_size;
    187      1.15  pooka 			goto out;
    188      1.15  pooka 		}
    189      1.15  pooka 
    190      1.15  pooka 		if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
    191      1.15  pooka 			/*
    192      1.15  pooka 			 * XXX: should use DIOCGDISKINFO to query
    193      1.15  pooka 			 * sector size, but that requires proplib,
    194      1.15  pooka 			 * so just don't bother for now.  it's nice
    195      1.15  pooka 			 * that something as difficult as figuring out
    196      1.15  pooka 			 * a partition's size has been made so easy.
    197      1.15  pooka 			 */
    198      1.15  pooka 			size = dkw.dkw_size << DEV_BSHIFT;
    199       1.1  pooka 			goto out;
    200       1.1  pooka 		}
    201       1.1  pooka 
    202  1.15.4.5   yamt 		rv = errno;
    203       1.1  pooka #endif /* __NetBSD__ */
    204       1.1  pooka 	}
    205       1.1  pooka 
    206       1.1  pooka  out:
    207       1.1  pooka 	if (rv == 0 && sizep)
    208       1.1  pooka 		*sizep = size;
    209       1.1  pooka 	if (rv == 0 && ftp)
    210       1.1  pooka 		*ftp = ft;
    211      1.12  pooka 	if (fd != -1)
    212      1.12  pooka 		close(fd);
    213       1.1  pooka 
    214  1.15.4.5   yamt 	ET(rv);
    215       1.1  pooka }
    216       1.1  pooka 
    217       1.1  pooka int
    218  1.15.4.5   yamt rumpuser_malloc(size_t howmuch, int alignment, void **memp)
    219       1.1  pooka {
    220  1.15.4.5   yamt 	void *mem = NULL;
    221       1.6  pooka 	int rv;
    222       1.5  pooka 
    223       1.5  pooka 	if (alignment == 0)
    224       1.5  pooka 		alignment = sizeof(void *);
    225       1.1  pooka 
    226      1.14  pooka 	rv = posix_memalign(&mem, (size_t)alignment, howmuch);
    227       1.6  pooka 	if (__predict_false(rv != 0)) {
    228       1.6  pooka 		if (rv == EINVAL) {
    229       1.6  pooka 			printf("rumpuser_malloc: invalid alignment %d\n",
    230       1.6  pooka 			    alignment);
    231       1.6  pooka 			abort();
    232       1.6  pooka 		}
    233       1.6  pooka 	}
    234       1.1  pooka 
    235  1.15.4.5   yamt 	*memp = mem;
    236  1.15.4.5   yamt 	ET(rv);
    237       1.1  pooka }
    238       1.1  pooka 
    239  1.15.4.5   yamt /*ARGSUSED1*/
    240       1.1  pooka void
    241  1.15.4.5   yamt rumpuser_free(void *ptr, size_t size)
    242       1.1  pooka {
    243       1.1  pooka 
    244       1.1  pooka 	free(ptr);
    245       1.1  pooka }
    246       1.1  pooka 
    247  1.15.4.5   yamt int
    248       1.7  pooka rumpuser_anonmmap(void *prefaddr, size_t size, int alignbit,
    249  1.15.4.5   yamt 	int exec, void **memp)
    250       1.1  pooka {
    251  1.15.4.5   yamt 	void *mem;
    252  1.15.4.5   yamt 	int prot, rv;
    253       1.1  pooka 
    254  1.15.4.2   yamt #ifndef MAP_ALIGNED
    255  1.15.4.2   yamt #define MAP_ALIGNED(a) 0
    256  1.15.4.2   yamt 	if (alignbit)
    257  1.15.4.2   yamt 		fprintf(stderr, "rumpuser_anonmmap: warning, requested "
    258  1.15.4.2   yamt 		    "alignment not supported by hypervisor\n");
    259  1.15.4.2   yamt #endif
    260  1.15.4.2   yamt 
    261       1.1  pooka 	prot = PROT_READ|PROT_WRITE;
    262       1.1  pooka 	if (exec)
    263       1.1  pooka 		prot |= PROT_EXEC;
    264  1.15.4.5   yamt 	mem = mmap(prefaddr, size, prot,
    265  1.15.4.3   yamt 	    MAP_PRIVATE | MAP_ANON | MAP_ALIGNED(alignbit), -1, 0);
    266  1.15.4.5   yamt 	if (mem == MAP_FAILED) {
    267  1.15.4.5   yamt 		rv = errno;
    268  1.15.4.5   yamt 	} else {
    269  1.15.4.5   yamt 		*memp = mem;
    270  1.15.4.5   yamt 		rv = 0;
    271       1.1  pooka 	}
    272  1.15.4.5   yamt 
    273  1.15.4.5   yamt 	ET(rv);
    274       1.1  pooka }
    275       1.1  pooka 
    276       1.1  pooka void
    277       1.1  pooka rumpuser_unmap(void *addr, size_t len)
    278       1.1  pooka {
    279       1.1  pooka 
    280  1.15.4.5   yamt 	munmap(addr, len);
    281       1.1  pooka }
    282       1.1  pooka 
    283       1.1  pooka int
    284  1.15.4.5   yamt rumpuser_open(const char *path, int ruflags, int *fdp)
    285       1.1  pooka {
    286  1.15.4.5   yamt 	int fd, flags, rv;
    287  1.15.4.2   yamt 
    288  1.15.4.2   yamt 	switch (ruflags & RUMPUSER_OPEN_ACCMODE) {
    289  1.15.4.2   yamt 	case RUMPUSER_OPEN_RDONLY:
    290  1.15.4.2   yamt 		flags = O_RDONLY;
    291  1.15.4.2   yamt 		break;
    292  1.15.4.2   yamt 	case RUMPUSER_OPEN_WRONLY:
    293  1.15.4.2   yamt 		flags = O_WRONLY;
    294  1.15.4.2   yamt 		break;
    295  1.15.4.2   yamt 	case RUMPUSER_OPEN_RDWR:
    296  1.15.4.2   yamt 		flags = O_RDWR;
    297  1.15.4.2   yamt 		break;
    298  1.15.4.2   yamt 	default:
    299  1.15.4.5   yamt 		rv = EINVAL;
    300  1.15.4.5   yamt 		goto out;
    301  1.15.4.2   yamt 	}
    302  1.15.4.2   yamt 
    303  1.15.4.2   yamt #define TESTSET(_ru_, _h_) if (ruflags & _ru_) flags |= _h_;
    304  1.15.4.2   yamt 	TESTSET(RUMPUSER_OPEN_CREATE, O_CREAT);
    305  1.15.4.2   yamt 	TESTSET(RUMPUSER_OPEN_EXCL, O_EXCL);
    306  1.15.4.2   yamt #undef TESTSET
    307       1.1  pooka 
    308  1.15.4.5   yamt 	KLOCK_WRAP(fd = open(path, flags, 0644));
    309  1.15.4.5   yamt 	if (fd == -1) {
    310  1.15.4.5   yamt 		rv = errno;
    311  1.15.4.5   yamt 	} else {
    312  1.15.4.5   yamt 		*fdp = fd;
    313  1.15.4.5   yamt 		rv = 0;
    314  1.15.4.5   yamt 	}
    315       1.1  pooka 
    316  1.15.4.5   yamt  out:
    317  1.15.4.5   yamt 	ET(rv);
    318       1.1  pooka }
    319       1.1  pooka 
    320       1.1  pooka int
    321  1.15.4.5   yamt rumpuser_close(int fd)
    322       1.1  pooka {
    323  1.15.4.5   yamt 	int nlocks;
    324       1.1  pooka 
    325  1.15.4.5   yamt 	rumpkern_unsched(&nlocks, NULL);
    326  1.15.4.5   yamt 	fsync(fd);
    327  1.15.4.5   yamt 	close(fd);
    328  1.15.4.5   yamt 	rumpkern_sched(nlocks, NULL);
    329       1.1  pooka 
    330  1.15.4.5   yamt 	ET(0);
    331       1.1  pooka }
    332       1.1  pooka 
    333  1.15.4.5   yamt /*
    334  1.15.4.5   yamt  * Assume "struct rumpuser_iovec" and "struct iovec" are the same.
    335  1.15.4.5   yamt  * If you encounter POSIX platforms where they aren't, add some
    336  1.15.4.5   yamt  * translation for iovlen > 1.
    337  1.15.4.5   yamt  */
    338  1.15.4.5   yamt int
    339  1.15.4.5   yamt rumpuser_iovread(int fd, struct rumpuser_iovec *ruiov, size_t iovlen,
    340  1.15.4.5   yamt 	int64_t roff, size_t *retp)
    341       1.1  pooka {
    342  1.15.4.5   yamt 	struct iovec *iov = (struct iovec *)ruiov;
    343  1.15.4.5   yamt 	off_t off = (off_t)roff;
    344  1.15.4.5   yamt 	ssize_t nn;
    345  1.15.4.5   yamt 	int rv;
    346       1.1  pooka 
    347  1.15.4.5   yamt 	if (off == RUMPUSER_IOV_NOSEEK) {
    348  1.15.4.5   yamt 		KLOCK_WRAP(nn = readv(fd, iov, iovlen));
    349  1.15.4.5   yamt 	} else {
    350  1.15.4.5   yamt 		int nlocks;
    351       1.1  pooka 
    352  1.15.4.5   yamt 		rumpkern_unsched(&nlocks, NULL);
    353  1.15.4.5   yamt 		if (lseek(fd, off, SEEK_SET) == off) {
    354  1.15.4.5   yamt 			nn = readv(fd, iov, iovlen);
    355  1.15.4.5   yamt 		} else {
    356  1.15.4.5   yamt 			nn = -1;
    357  1.15.4.5   yamt 		}
    358  1.15.4.5   yamt 		rumpkern_sched(nlocks, NULL);
    359  1.15.4.5   yamt 	}
    360       1.1  pooka 
    361  1.15.4.5   yamt 	if (nn == -1) {
    362  1.15.4.5   yamt 		rv = errno;
    363  1.15.4.5   yamt 	} else {
    364  1.15.4.5   yamt 		*retp = (size_t)nn;
    365       1.1  pooka 		rv = 0;
    366  1.15.4.5   yamt 	}
    367       1.1  pooka 
    368  1.15.4.5   yamt 	ET(rv);
    369       1.1  pooka }
    370       1.1  pooka 
    371  1.15.4.5   yamt int
    372  1.15.4.5   yamt rumpuser_iovwrite(int fd, const struct rumpuser_iovec *ruiov, size_t iovlen,
    373  1.15.4.5   yamt 	int64_t roff, size_t *retp)
    374       1.1  pooka {
    375  1.15.4.5   yamt 	const struct iovec *iov = (const struct iovec *)ruiov;
    376  1.15.4.5   yamt 	off_t off = (off_t)roff;
    377  1.15.4.5   yamt 	ssize_t nn;
    378  1.15.4.5   yamt 	int rv;
    379       1.1  pooka 
    380  1.15.4.5   yamt 	if (off == RUMPUSER_IOV_NOSEEK) {
    381  1.15.4.5   yamt 		KLOCK_WRAP(nn = writev(fd, iov, iovlen));
    382  1.15.4.5   yamt 	} else {
    383  1.15.4.5   yamt 		int nlocks;
    384       1.1  pooka 
    385  1.15.4.5   yamt 		rumpkern_unsched(&nlocks, NULL);
    386  1.15.4.5   yamt 		if (lseek(fd, off, SEEK_SET) == off) {
    387  1.15.4.5   yamt 			nn = writev(fd, iov, iovlen);
    388  1.15.4.5   yamt 		} else {
    389  1.15.4.5   yamt 			nn = -1;
    390  1.15.4.5   yamt 		}
    391  1.15.4.5   yamt 		rumpkern_sched(nlocks, NULL);
    392  1.15.4.5   yamt 	}
    393       1.1  pooka 
    394  1.15.4.5   yamt 	if (nn == -1) {
    395  1.15.4.5   yamt 		rv = errno;
    396  1.15.4.5   yamt 	} else {
    397  1.15.4.5   yamt 		*retp = (size_t)nn;
    398       1.1  pooka 		rv = 0;
    399  1.15.4.5   yamt 	}
    400       1.1  pooka 
    401  1.15.4.5   yamt 	ET(rv);
    402       1.1  pooka }
    403       1.1  pooka 
    404  1.15.4.5   yamt int
    405  1.15.4.5   yamt rumpuser_syncfd(int fd, int flags, uint64_t start, uint64_t len)
    406       1.1  pooka {
    407  1.15.4.5   yamt 	int rv = 0;
    408  1.15.4.5   yamt 
    409  1.15.4.5   yamt 	/*
    410  1.15.4.5   yamt 	 * For now, assume fd is regular file and does not care
    411  1.15.4.5   yamt 	 * about read syncing
    412  1.15.4.5   yamt 	 */
    413  1.15.4.5   yamt 	if ((flags & RUMPUSER_SYNCFD_BOTH) == 0) {
    414  1.15.4.5   yamt 		rv = EINVAL;
    415  1.15.4.5   yamt 		goto out;
    416       1.1  pooka 	}
    417  1.15.4.5   yamt 	if ((flags & RUMPUSER_SYNCFD_WRITE) == 0) {
    418  1.15.4.5   yamt 		rv = 0;
    419  1.15.4.5   yamt 		goto out;
    420       1.1  pooka 	}
    421       1.1  pooka 
    422  1.15.4.5   yamt #ifdef __NetBSD__
    423  1.15.4.5   yamt 	{
    424  1.15.4.5   yamt 	int fsflags = FDATASYNC;
    425       1.1  pooka 
    426  1.15.4.5   yamt 	if (fsflags & RUMPUSER_SYNCFD_SYNC)
    427  1.15.4.5   yamt 		fsflags |= FDISKSYNC;
    428  1.15.4.5   yamt 	if (fsync_range(fd, fsflags, start, len) == -1)
    429  1.15.4.5   yamt 		rv = errno;
    430       1.1  pooka 	}
    431  1.15.4.5   yamt #else
    432  1.15.4.5   yamt 	/* el-simplo */
    433  1.15.4.5   yamt 	if (fsync(fd) == -1)
    434  1.15.4.5   yamt 		rv = errno;
    435  1.15.4.5   yamt #endif
    436       1.1  pooka 
    437  1.15.4.5   yamt  out:
    438  1.15.4.5   yamt 	ET(rv);
    439       1.1  pooka }
    440       1.1  pooka 
    441       1.1  pooka int
    442  1.15.4.5   yamt rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
    443       1.1  pooka {
    444  1.15.4.5   yamt 	enum rumpclock rclk = enum_rumpclock;
    445  1.15.4.5   yamt 	struct timespec ts;
    446  1.15.4.5   yamt 	clockid_t clk;
    447       1.1  pooka 	int rv;
    448       1.1  pooka 
    449  1.15.4.5   yamt 	switch (rclk) {
    450  1.15.4.5   yamt 	case RUMPUSER_CLOCK_RELWALL:
    451  1.15.4.5   yamt 		clk = CLOCK_REALTIME;
    452  1.15.4.5   yamt 		break;
    453  1.15.4.5   yamt 	case RUMPUSER_CLOCK_ABSMONO:
    454  1.15.4.5   yamt #ifdef HAVE_CLOCK_NANOSLEEP
    455  1.15.4.5   yamt 		clk = CLOCK_MONOTONIC;
    456  1.15.4.5   yamt #else
    457  1.15.4.5   yamt 		clk = CLOCK_REALTIME;
    458  1.15.4.5   yamt #endif
    459  1.15.4.5   yamt 		break;
    460  1.15.4.5   yamt 	default:
    461  1.15.4.5   yamt 		abort();
    462       1.1  pooka 	}
    463       1.1  pooka 
    464  1.15.4.5   yamt 	if (clock_gettime(clk, &ts) == -1) {
    465  1.15.4.5   yamt 		rv = errno;
    466      1.13  pooka 	} else {
    467  1.15.4.5   yamt 		*sec = ts.tv_sec;
    468  1.15.4.5   yamt 		*nsec = ts.tv_nsec;
    469  1.15.4.5   yamt 		rv = 0;
    470      1.13  pooka 	}
    471      1.13  pooka 
    472  1.15.4.5   yamt 	ET(rv);
    473       1.1  pooka }
    474       1.1  pooka 
    475       1.1  pooka int
    476  1.15.4.5   yamt rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
    477       1.1  pooka {
    478  1.15.4.5   yamt 	enum rumpclock rclk = enum_rumpclock;
    479  1.15.4.5   yamt 	struct timespec rqt, rmt;
    480  1.15.4.5   yamt 	int nlocks;
    481  1.15.4.5   yamt 	int rv;
    482       1.1  pooka 
    483  1.15.4.5   yamt 	rumpkern_unsched(&nlocks, NULL);
    484       1.1  pooka 
    485  1.15.4.5   yamt 	/*LINTED*/
    486  1.15.4.5   yamt 	rqt.tv_sec = sec;
    487  1.15.4.5   yamt 	/*LINTED*/
    488  1.15.4.5   yamt 	rqt.tv_nsec = nsec;
    489       1.1  pooka 
    490  1.15.4.5   yamt 	switch (rclk) {
    491  1.15.4.5   yamt 	case RUMPUSER_CLOCK_RELWALL:
    492  1.15.4.5   yamt 		do {
    493  1.15.4.5   yamt 			rv = nanosleep(&rqt, &rmt);
    494  1.15.4.5   yamt 			rqt = rmt;
    495  1.15.4.5   yamt 		} while (rv == -1 && errno == EINTR);
    496  1.15.4.5   yamt 		if (rv == -1) {
    497  1.15.4.5   yamt 			rv = errno;
    498  1.15.4.5   yamt 		}
    499  1.15.4.5   yamt 		break;
    500  1.15.4.5   yamt 	case RUMPUSER_CLOCK_ABSMONO:
    501  1.15.4.5   yamt 		do {
    502  1.15.4.5   yamt #ifdef HAVE_CLOCK_NANOSLEEP
    503  1.15.4.5   yamt 			rv = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
    504  1.15.4.5   yamt 			    &rqt, NULL);
    505  1.15.4.5   yamt #else
    506  1.15.4.5   yamt 			/* le/la/der/die/das sigh. timevalspec tailspin */
    507  1.15.4.5   yamt 			struct timespec ts, tsr;
    508  1.15.4.5   yamt 			clock_gettime(CLOCK_REALTIME, &ts);
    509  1.15.4.5   yamt 			if (ts.tv_sec == rqt.tv_sec ?
    510  1.15.4.5   yamt 			    ts.tv_nsec > rqt.tv_nsec : ts.tv_sec > rqt.tv_sec) {
    511  1.15.4.5   yamt 				rv = 0;
    512  1.15.4.5   yamt 			} else {
    513  1.15.4.5   yamt 				tsr.tv_sec = rqt.tv_sec - ts.tv_sec;
    514  1.15.4.5   yamt 				tsr.tv_nsec = rqt.tv_nsec - ts.tv_nsec;
    515  1.15.4.5   yamt 				if (tsr.tv_nsec < 0) {
    516  1.15.4.5   yamt 					tsr.tv_sec--;
    517  1.15.4.5   yamt 					tsr.tv_nsec += 1000*1000*1000;
    518  1.15.4.5   yamt 				}
    519  1.15.4.5   yamt 				rv = nanosleep(&tsr, NULL);
    520  1.15.4.5   yamt 			}
    521  1.15.4.5   yamt #endif
    522  1.15.4.5   yamt 		} while (rv == -1 && errno == EINTR);
    523  1.15.4.5   yamt 		if (rv == -1) {
    524  1.15.4.5   yamt 			rv = errno;
    525  1.15.4.5   yamt 		}
    526  1.15.4.5   yamt 		break;
    527  1.15.4.5   yamt 	default:
    528       1.1  pooka 		abort();
    529  1.15.4.5   yamt 	}
    530       1.1  pooka 
    531  1.15.4.5   yamt 	rumpkern_sched(nlocks, NULL);
    532       1.1  pooka 
    533  1.15.4.5   yamt 	ET(rv);
    534       1.1  pooka }
    535       1.1  pooka 
    536  1.15.4.5   yamt static int
    537  1.15.4.5   yamt gethostncpu(void)
    538       1.1  pooka {
    539  1.15.4.5   yamt 	int ncpu = 1; /* unknown, really */
    540       1.1  pooka 
    541  1.15.4.5   yamt #ifdef _SC_NPROCESSORS_ONLN
    542  1.15.4.5   yamt 	ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    543  1.15.4.5   yamt #endif
    544  1.15.4.5   yamt 
    545  1.15.4.5   yamt 	return ncpu;
    546       1.1  pooka }
    547       1.1  pooka 
    548       1.1  pooka int
    549  1.15.4.5   yamt rumpuser_getparam(const char *name, void *buf, size_t blen)
    550       1.1  pooka {
    551       1.1  pooka 	int rv;
    552       1.1  pooka 
    553  1.15.4.5   yamt 	if (strcmp(name, RUMPUSER_PARAM_NCPU) == 0) {
    554  1.15.4.5   yamt 		int ncpu;
    555  1.15.4.2   yamt 
    556  1.15.4.5   yamt 		if (getenv_r("RUMP_NCPU", buf, blen) == -1) {
    557  1.15.4.5   yamt 			sprintf(buf, "2"); /* default */
    558  1.15.4.5   yamt 		} else if (strcmp(buf, "host") == 0) {
    559  1.15.4.5   yamt 			ncpu = gethostncpu();
    560  1.15.4.5   yamt 			snprintf(buf, blen, "%d", ncpu);
    561  1.15.4.2   yamt 		}
    562  1.15.4.5   yamt 		rv = 0;
    563  1.15.4.5   yamt 	} else if (strcmp(name, RUMPUSER_PARAM_HOSTNAME) == 0) {
    564  1.15.4.5   yamt 		char tmp[MAXHOSTNAMELEN];
    565  1.15.4.2   yamt 
    566  1.15.4.5   yamt 		if (gethostname(tmp, sizeof(tmp)) == -1) {
    567  1.15.4.5   yamt 			snprintf(buf, blen, "rump-%05d", (int)getpid());
    568  1.15.4.5   yamt 		} else {
    569  1.15.4.5   yamt 			snprintf(buf, blen, "rump-%05d.%s",
    570  1.15.4.5   yamt 			    (int)getpid(), tmp);
    571  1.15.4.5   yamt 		}
    572  1.15.4.5   yamt 		rv = 0;
    573  1.15.4.5   yamt 	} else if (*name == '_') {
    574  1.15.4.5   yamt 		rv = EINVAL;
    575  1.15.4.5   yamt 	} else {
    576  1.15.4.5   yamt 		if (getenv_r(name, buf, blen) == -1)
    577  1.15.4.5   yamt 			rv = errno;
    578  1.15.4.5   yamt 		else
    579  1.15.4.5   yamt 			rv = 0;
    580  1.15.4.2   yamt 	}
    581  1.15.4.2   yamt 
    582  1.15.4.5   yamt 	ET(rv);
    583  1.15.4.2   yamt }
    584  1.15.4.2   yamt 
    585  1.15.4.5   yamt void
    586  1.15.4.5   yamt rumpuser_putchar(int c)
    587  1.15.4.2   yamt {
    588  1.15.4.2   yamt 
    589  1.15.4.5   yamt 	putchar(c);
    590  1.15.4.2   yamt }
    591  1.15.4.4   yamt 
    592  1.15.4.5   yamt __dead void
    593  1.15.4.5   yamt rumpuser_exit(int rv)
    594  1.15.4.4   yamt {
    595  1.15.4.4   yamt 
    596  1.15.4.5   yamt 	if (rv == RUMPUSER_PANIC)
    597  1.15.4.5   yamt 		abort();
    598  1.15.4.5   yamt 	else
    599  1.15.4.5   yamt 		exit(rv);
    600  1.15.4.4   yamt }
    601  1.15.4.4   yamt 
    602  1.15.4.5   yamt void
    603  1.15.4.5   yamt rumpuser_seterrno(int error)
    604  1.15.4.4   yamt {
    605  1.15.4.4   yamt 
    606  1.15.4.5   yamt 	errno = error;
    607  1.15.4.4   yamt }
    608  1.15.4.2   yamt 
    609       1.1  pooka /*
    610       1.1  pooka  * This is meant for safe debugging prints from the kernel.
    611       1.1  pooka  */
    612  1.15.4.5   yamt void
    613       1.1  pooka rumpuser_dprintf(const char *format, ...)
    614       1.1  pooka {
    615       1.1  pooka 	va_list ap;
    616       1.1  pooka 
    617       1.1  pooka 	va_start(ap, format);
    618  1.15.4.5   yamt 	vfprintf(stderr, format, ap);
    619       1.1  pooka 	va_end(ap);
    620       1.1  pooka }
    621       1.2  pooka 
    622       1.2  pooka int
    623  1.15.4.5   yamt rumpuser_kill(int64_t pid, int rumpsig)
    624       1.2  pooka {
    625  1.15.4.5   yamt 	int sig;
    626       1.2  pooka 
    627  1.15.4.5   yamt 	sig = rumpuser__sig_rump2host(rumpsig);
    628  1.15.4.5   yamt 	if (sig > 0)
    629  1.15.4.5   yamt 		raise(sig);
    630  1.15.4.5   yamt 	return 0;
    631       1.2  pooka }
    632       1.4  pooka 
    633       1.4  pooka int
    634  1.15.4.5   yamt rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
    635       1.4  pooka {
    636  1.15.4.5   yamt 	size_t origlen = buflen;
    637  1.15.4.5   yamt 	uint32_t *p = buf;
    638  1.15.4.5   yamt 	uint32_t tmp;
    639  1.15.4.5   yamt 	int chunk;
    640  1.15.4.2   yamt 
    641  1.15.4.5   yamt 	do {
    642  1.15.4.5   yamt 		chunk = buflen < 4 ? buflen : 4; /* portable MIN ... */
    643  1.15.4.5   yamt 		tmp = RUMPUSER_RANDOM();
    644  1.15.4.5   yamt 		memcpy(p, &tmp, chunk);
    645  1.15.4.5   yamt 		p++;
    646  1.15.4.5   yamt 		buflen -= chunk;
    647  1.15.4.5   yamt 	} while (chunk);
    648  1.15.4.2   yamt 
    649  1.15.4.5   yamt 	*retp = origlen;
    650  1.15.4.5   yamt 	ET(0);
    651  1.15.4.1   yamt }
    652