static int setdumpdev(cdev_t dev) { int error; int doopen; if (dev == NULL) { disk_dumpconf(NULL, 0/*off*/); return (0); } /* * We have to open the device before we can perform ioctls on it, * or the slice/label data may not be present. Device opens are * usually tracked by specfs, but the dump device can be set in * early boot and may not be open so this is somewhat of a hack. */ doopen = (dev->si_sysref.refcnt == 1); if (doopen) { error = dev_dopen(dev, FREAD, S_IFCHR, proc0.p_ucred); if (error) return (error); } error = disk_dumpconf(dev, 1/*on*/); return error; }
static int devfs_spec_open(struct vop_open_args *ap) { struct vnode *vp = ap->a_vp; struct vnode *orig_vp = NULL; struct devfs_node *node = DEVFS_NODE(vp); struct devfs_node *newnode; cdev_t dev, ndev = NULL; int error = 0; if (node) { if (node->d_dev == NULL) return ENXIO; if (!devfs_node_is_accessible(node)) return ENOENT; } if ((dev = vp->v_rdev) == NULL) return ENXIO; vn_lock(vp, LK_UPGRADE | LK_RETRY); if (node && ap->a_fp) { devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_open: -1.1-\n"); lockmgr(&devfs_lock, LK_EXCLUSIVE); ndev = devfs_clone(dev, node->d_dir.d_name, node->d_dir.d_namlen, ap->a_mode, ap->a_cred); if (ndev != NULL) { newnode = devfs_create_device_node( DEVFS_MNTDATA(vp->v_mount)->root_node, ndev, NULL, NULL); /* XXX: possibly destroy device if this happens */ if (newnode != NULL) { dev = ndev; devfs_link_dev(dev); devfs_debug(DEVFS_DEBUG_DEBUG, "parent here is: %s, node is: |%s|\n", ((node->parent->node_type == Nroot) ? "ROOT!" : node->parent->d_dir.d_name), newnode->d_dir.d_name); devfs_debug(DEVFS_DEBUG_DEBUG, "test: %s\n", ((struct devfs_node *)(TAILQ_LAST(DEVFS_DENODE_HEAD(node->parent), devfs_node_head)))->d_dir.d_name); /* * orig_vp is set to the original vp if we cloned. */ /* node->flags |= DEVFS_CLONED; */ devfs_allocv(&vp, newnode); orig_vp = ap->a_vp; ap->a_vp = vp; } } lockmgr(&devfs_lock, LK_RELEASE); } devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_open() called on %s! \n", dev->si_name); /* * Make this field valid before any I/O in ->d_open */ if (!dev->si_iosize_max) /* XXX: old DFLTPHYS == 64KB dependency */ dev->si_iosize_max = min(MAXPHYS,64*1024); if (dev_dflags(dev) & D_TTY) vsetflags(vp, VISTTY); /* * Open underlying device */ vn_unlock(vp); error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_cred, ap->a_fp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* * Clean up any cloned vp if we error out. */ if (error) { if (orig_vp) { vput(vp); ap->a_vp = orig_vp; /* orig_vp = NULL; */ } return error; } /* * This checks if the disk device is going to be opened for writing. * It will be only allowed in the cases where securelevel permits it * and it's not mounted R/W. */ if ((dev_dflags(dev) & D_DISK) && (ap->a_mode & FWRITE) && (ap->a_cred != FSCRED)) { /* Very secure mode. No open for writing allowed */ if (securelevel >= 2) return EPERM; /* * If it is mounted R/W, do not allow to open for writing. * In the case it's mounted read-only but securelevel * is >= 1, then do not allow opening for writing either. */ if (vfs_mountedon(vp)) { if (!(dev->si_mountpoint->mnt_flag & MNT_RDONLY)) return EBUSY; else if (securelevel >= 1) return EPERM; } } if (dev_dflags(dev) & D_TTY) { if (dev->si_tty) { struct tty *tp; tp = dev->si_tty; if (!tp->t_stop) { devfs_debug(DEVFS_DEBUG_DEBUG, "devfs: no t_stop\n"); tp->t_stop = nottystop; } } } if (vn_isdisk(vp, NULL)) { if (!dev->si_bsize_phys) dev->si_bsize_phys = DEV_BSIZE; vinitvmio(vp, IDX_TO_OFF(INT_MAX), PAGE_SIZE, -1); } vop_stdopen(ap); #if 0 if (node) nanotime(&node->atime); #endif /* * If we replaced the vp the vop_stdopen() call will have loaded * it into fp->f_data and vref()d the vp, giving us two refs. So * instead of just unlocking it here we have to vput() it. */ if (orig_vp) vput(vp); /* Ugly pty magic, to make pty devices appear once they are opened */ if (node && (node->flags & DEVFS_PTY) == DEVFS_PTY) node->flags &= ~DEVFS_INVISIBLE; if (ap->a_fp) { KKASSERT(ap->a_fp->f_type == DTYPE_VNODE); KKASSERT((ap->a_fp->f_flag & FMASK) == (ap->a_mode & FMASK)); ap->a_fp->f_ops = &devfs_dev_fileops; KKASSERT(ap->a_fp->f_data == (void *)vp); } return 0; }