inst_sync.c revision 0a653502ce7060b491de569a1991825128724441
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER START
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The contents of this file are subject to the terms of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Common Development and Distribution License (the "License").
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You may not use this file except in compliance with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * or http://www.opensolaris.org/os/licensing.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing permissions
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * and limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If applicable, add the following below this CDDL HEADER, with the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * information: Portions Copyright [yyyy] [name of copyright owner]
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER END
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Use is subject to license terms.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#pragma ident "%Z%%M% %I% %E% SMI"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Syscall to write out the instance number data structures to
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * stable storage.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/types.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/errno.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/t_lock.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/modctl.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/systm.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/syscall.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/vfs.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/vnode.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/cred.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/file.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/cmn_err.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/kmem.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/cladm.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/sunddi.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/dditypes.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/instance.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/debug.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/policy.h>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Userland sees:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * int inst_sync(pathname, flags);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Returns zero if instance number information was successfully
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * written to 'pathname', -1 plus error code in errno otherwise.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * POC notes:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - This could be done as a case of the modctl(2) system call
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * though the ability to have it load and unload would disappear.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - 'flags' have either of two meanings:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * INST_SYNC_IF_REQUIRED 'pathname' will be written if there
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * has been a change in the kernel's
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * internal view of instance number
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * information
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * INST_SYNC_ALWAYS 'pathname' will be written even if
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * the kernel's view hasn't changed.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - Maybe we should pass through two filenames - one to create,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * and the other as the 'final' target i.e. do the rename of
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * /etc/instance.new -> /etc/instance in the kernel.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int in_sync_sys(char *pathname, uint_t flags);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic struct sysent in_sync_sysent = {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster 2, /* number of arguments */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster SE_ARGC | SE_32RVAL1, /* c-style calling, 32-bit return value */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster in_sync_sys, /* the handler */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (krwlock_t *)0 /* rw lock allocated/used by framework */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster};
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic struct modlsys modlsys = {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster &mod_syscallops, "instance binding syscall", &in_sync_sysent
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster};
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#ifdef _SYSCALL32_IMPL
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic struct modlsys modlsys32 = {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster &mod_syscallops32, "32-bit instance binding syscall", &in_sync_sysent
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster};
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic struct modlinkage modlinkage = {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster MODREV_1,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster &modlsys,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#ifdef _SYSCALL32_IMPL
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster &modlsys32,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster NULL
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster};
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterint
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster_init(void)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (mod_install(&modlinkage));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterint
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster_info(struct modinfo *modinfop)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (mod_info(&modlinkage, modinfop));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterint
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster_fini(void)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (mod_remove(&modlinkage));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int in_write_instance(struct vnode *vp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_sync_sys(char *pathname, uint_t flags)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster struct vnode *vp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * We must have sufficient privilege to do this, since we lock critical
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * data structures whilst we're doing it ..
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((error = secpolicy_sys_devices(CRED())) != 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (set_errno(error));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (flags != INST_SYNC_ALWAYS && flags != INST_SYNC_IF_REQUIRED)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (set_errno(EINVAL));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Only one process is allowed to get the state of the instance
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * number assignments on the system at any given time.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster e_ddi_enter_instance();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Recreate the instance file only if the device tree has changed
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * or if the caller explicitly requests so.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (e_ddi_instance_is_clean() && flags != INST_SYNC_ALWAYS) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = EALREADY;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster goto end;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Create an instance file for writing, giving it a mode that
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * will only permit reading. Note that we refuse to overwrite
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * an existing file.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((error = vn_open(pathname, UIO_USERSPACE,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FCREAT, 0444, &vp, CRCREAT, 0)) != 0) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error == EISDIR)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = EACCES; /* SVID compliance? */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster goto end;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * So far so good. We're singly threaded, the vnode is beckoning
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * so let's get on with it. Any error, and we just give up and
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * hand the first error we get back to userland.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = in_write_instance(vp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If there was any sort of error, we deliberately go and
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * remove the file we just created so that any attempts to
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * use it will quickly fail.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) vn_remove(pathname, UIO_USERSPACE, RMFILE);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster else
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster e_ddi_instance_set_clean();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterend:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster e_ddi_exit_instance();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error ? set_errno(error) : 0);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * At the risk of reinventing stdio ..
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define FBUFSIZE 512
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fostertypedef struct _File {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster char *ptr;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int count;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster char buf[FBUFSIZE];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster vnode_t *vp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster offset_t voffset;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster} File;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_write(struct vnode *vp, offset_t *vo, caddr_t buf, int count)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ssize_t resid;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster rlim64_t rlimit = *vo + count + 1;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = vn_rdwr(UIO_WRITE, vp, buf, count, *vo,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster UIO_SYSSPACE, 0, rlimit, CRED(), &resid);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *vo += (offset_t)(count - resid);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic File *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_fvpopen(struct vnode *vp)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster File *fp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fp = kmem_zalloc(sizeof (File), KM_SLEEP);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fp->vp = vp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fp->ptr = fp->buf;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (fp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_fclose(File *fp)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = VOP_CLOSE(fp->vp, FCREAT, 1, (offset_t)0, CRED(), NULL);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster VN_RELE(fp->vp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster kmem_free(fp, sizeof (File));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_fflush(File *fp)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (fp->count)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = in_write(fp->vp, &fp->voffset, fp->buf, fp->count);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error == 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = VOP_FSYNC(fp->vp, FSYNC, CRED(), NULL);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_fputs(File *fp, char *buf)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster while (*buf) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *fp->ptr++ = *buf++;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (++fp->count == FBUFSIZE) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = in_write(fp->vp, &fp->voffset, fp->buf,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fp->count);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster break;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fp->count = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fp->ptr = fp->buf;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * External linkage
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic File *in_fp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * XXX what is the maximum length of the name of a driver? Must be maximum
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * XXX file name length (find the correct constant and substitute for this one
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define DRVNAMELEN (1 + 256)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic char linebuffer[MAXPATHLEN + 1 + 1 + 1 + 1 + 10 + 1 + DRVNAMELEN];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * XXX Maybe we should just write 'in_fprintf' instead ..
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_walktree(in_node_t *np, char *this)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster char *next;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster in_drv_t *dp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (error = 0; np; np = np->in_sibling) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (np->in_unit_addr[0] == '\0')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) sprintf(this, "/%s", np->in_node_name);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster else
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) sprintf(this, "/%s@%s", np->in_node_name,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster np->in_unit_addr);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster next = this + strlen(this);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ASSERT(np->in_drivers);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (dp = np->in_drivers; dp; dp = dp->ind_next_drv) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster uint_t inst_val = dp->ind_instance;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Flushing IN_PROVISIONAL could result in duplicate
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * instances
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Flushing IN_UNKNOWN results in instance -1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (dp->ind_state != IN_PERMANENT)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster continue;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) sprintf(next, "\" %d \"%s\"\n", inst_val,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster dp->ind_driver_name);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error = in_fputs(in_fp, linebuffer))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (np->in_child)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error = in_walktree(np->in_child, next))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster break;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Walk the instance tree, writing out what we find.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * There's some fairly nasty sharing of buffers in this
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * bit of code, so be careful out there when you're
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * rewriting it ..
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterin_write_instance(struct vnode *vp)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int error;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster char *cp;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster in_fp = in_fvpopen(vp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Place a bossy comment at the beginning of the file.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = in_fputs(in_fp,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "#\n#\tCaution! This file contains critical kernel state\n#\n");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error == 0) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster in_node_t *root = e_ddi_instance_root();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster cp = linebuffer;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *cp++ = '\"';
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = in_walktree(root->in_child, cp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (error == 0) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((error = in_fflush(in_fp)) == 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster error = in_fclose(in_fp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster } else
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) in_fclose(in_fp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (error);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster