.Op Fl l Ar cpulock
.Op Fl m Ar size
.Op Fl n Ar numcpus
-.Op Fl p Ar file
+.Op Fl p Ar pidfile
.Op Fl r Ar file
.Sh DESCRIPTION
The
.Ar interface
argument is the name of a
.Xr tap 4
-device node.
+device node or the path to a
+.Xr vknetd 8
+socket.
The
.Pa /dev/
-path prefix does not have to be specified and will be automatically prepended.
+path prefix does not have to be specified and will be automatically prepended
+for a device node.
Specifying
.Cm auto
will pick the first unused
The
.Ar netmask
argument applies to all interfaces for which an address is specified.
+.Pp
+When running multiple vkernels it is often more convenient to simply
+connect to a
+.Xr vknetd 8
+socket and let vknetd deal with the tap and/or bridge. An example of
+this would be '/var/run/vknet:0.0.0.0:10.2.0.2/16'.
.It Fl l Ar cpulock
Specify which, if any, real CPUs to lock virtual CPUs to.
.Ar cpulock
The virtual kernel must be built with
.Cd options SMP
to use this option and will default to 2 CPUs unless otherwise specified.
-.It Fl p Ar file
-Specify a file in which to store the process ID.
-A warning is issued if this file cannot be opened for writing.
+.It Fl p Ar pidfile
+Specify a pidfile in which to store the process ID.
+Scripts can use this file to locate the vkernel pid for the purpose of
+shutting down or killing it.
+.Pp
+The vkernel will hold a lock on the pidfile while running.
+Scripts may test for the lock to determine if the pidfile is valid or
+stale so as to avoid accidently killing a random process.
+Something like '/usr/bin/lockf -ks -t 0 pidfile echo -n' may be used
+to test the lock.
+A non-zero exit code indicates that the pidfile represents a running
+vkernel.
+.Pp
+An error is issued and the vkernel exits if this file cannot be opened for
+writing or if it is already locked by an active vkernel process.
.It Fl r Ar file
Specify a R/W disk image
.Ar file
* Figure out the system memory image size. If an image file was
* specified and -m was not specified, use the image file's size.
*/
-
if (imageFile && stat(imageFile, &st) == 0 && Maxmem_bytes == 0)
Maxmem_bytes = (vm_paddr_t)st.st_size;
if ((imageFile == NULL || stat(imageFile, &st) < 0) &&
* Generate an image file name if necessary, then open/create the
* file exclusively locked. Do not allow multiple virtual kernels
* to use the same image file.
+ *
+ * Don't iterate through a million files if we do not have write
+ * access to the directory, stop if our open() failed on a
+ * non-existant file. Otherwise opens can fail for any number
+ * of reasons (lock failed, file not owned or writable by us, etc).
*/
if (imageFile == NULL) {
for (i = 0; i < 1000000; ++i) {
asprintf(&imageFile, "/var/vkernel/memimg.%06d", i);
fd = open(imageFile,
O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
- if (fd < 0 && errno == EWOULDBLOCK) {
+ if (fd < 0 && stat(imageFile, &st) == 0) {
free(imageFile);
continue;
}
close(s);
}
+/*
+ * Create the pid file and leave it open and locked while the vkernel is
+ * running. This allows a script to use /usr/bin/lockf to probe whether
+ * a vkernel is still running (so as not to accidently kill an unrelated
+ * process from a stale pid file).
+ */
static
void
-writepid( void )
+writepid(void)
{
- pid_t self;
- FILE *fp;
+ char buf[32];
+ int fd;
if (pid_file != NULL) {
- self = getpid();
- fp = fopen(pid_file, "w");
-
- if (fp != NULL) {
- fprintf(fp, "%ld\n", (long)self);
- fclose(fp);
- }
- else {
- perror("Warning: couldn't open pidfile");
+ snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
+ fd = open(pid_file, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0666);
+ if (fd < 0) {
+ if (errno == EWOULDBLOCK) {
+ perror("Failed to lock pidfile, "
+ "vkernel already running");
+ } else {
+ perror("Failed to create pidfile");
+ }
+ exit(EX_SOFTWARE);
}
+ ftruncate(fd, 0);
+ write(fd, buf, strlen(buf));
+ /* leave the file open to maintain the lock */
}
}
cleanpid( void )
{
if (pid_file != NULL) {
- if ( unlink(pid_file) != 0 )
+ if (unlink(pid_file) < 0)
perror("Warning: couldn't remove pidfile");
}
}
* Figure out the system memory image size. If an image file was
* specified and -m was not specified, use the image file's size.
*/
-
if (imageFile && stat(imageFile, &st) == 0 && Maxmem_bytes == 0)
Maxmem_bytes = (vm_paddr_t)st.st_size;
if ((imageFile == NULL || stat(imageFile, &st) < 0) &&
* Generate an image file name if necessary, then open/create the
* file exclusively locked. Do not allow multiple virtual kernels
* to use the same image file.
+ *
+ * Don't iterate through a million files if we do not have write
+ * access to the directory, stop if our open() failed on a
+ * non-existant file. Otherwise opens can fail for any number
*/
if (imageFile == NULL) {
for (i = 0; i < 1000000; ++i) {
asprintf(&imageFile, "/var/vkernel/memimg.%06d", i);
fd = open(imageFile,
O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
- if (fd < 0 && errno == EWOULDBLOCK) {
+ if (fd < 0 && stat(imageFile, &st) == 0) {
free(imageFile);
continue;
}
close(s);
}
+/*
+ * Create the pid file and leave it open and locked while the vkernel is
+ * running. This allows a script to use /usr/bin/lockf to probe whether
+ * a vkernel is still running (so as not to accidently kill an unrelated
+ * process from a stale pid file).
+ */
static
void
-writepid( void )
+writepid(void)
{
- pid_t self;
- FILE *fp;
+ char buf[32];
+ int fd;
if (pid_file != NULL) {
- self = getpid();
- fp = fopen(pid_file, "w");
-
- if (fp != NULL) {
- fprintf(fp, "%ld\n", (long)self);
- fclose(fp);
- }
- else {
- perror("Warning: couldn't open pidfile");
+ snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
+ fd = open(pid_file, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0666);
+ if (fd < 0) {
+ if (errno == EWOULDBLOCK) {
+ perror("Failed to lock pidfile, "
+ "vkernel already running");
+ } else {
+ perror("Failed to create pidfile");
+ }
+ exit(EX_SOFTWARE);
}
+ ftruncate(fd, 0);
+ write(fd, buf, strlen(buf));
+ /* leave the file open to maintain the lock */
}
}
cleanpid( void )
{
if (pid_file != NULL) {
- if ( unlink(pid_file) != 0 )
+ if (unlink(pid_file) < 0)
perror("Warning: couldn't remove pidfile");
}
}