version 1.104, 2007/08/03 08:45:36 |
version 1.104.2.5, 2007/12/03 16:15:05 |
Line 52 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 52 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/lockf.h> |
#include <sys/lockf.h> |
#include <sys/tty.h> |
#include <sys/tty.h> |
#include <sys/kauth.h> |
#include <sys/kauth.h> |
|
#include <sys/fstrans.h> |
|
|
#include <miscfs/genfs/genfs.h> |
#include <miscfs/genfs/genfs.h> |
#include <miscfs/specfs/specdev.h> |
#include <miscfs/specfs/specdev.h> |
Line 166 spec_open(void *v) |
|
Line 167 spec_open(void *v) |
|
struct vnode *a_vp; |
struct vnode *a_vp; |
int a_mode; |
int a_mode; |
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct lwp *a_l; |
|
} */ *ap = v; |
} */ *ap = v; |
struct lwp *l = ap->a_l; |
struct lwp *l = curlwp; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
dev_t dev = (dev_t)vp->v_rdev; |
dev_t dev = (dev_t)vp->v_rdev; |
int error; |
int error; |
Line 195 spec_open(void *v) |
|
Line 195 spec_open(void *v) |
|
return (error); |
return (error); |
|
|
if (cdev_type(dev) == D_TTY) |
if (cdev_type(dev) == D_TTY) |
vp->v_flag |= VISTTY; |
vp->v_vflag |= VV_ISTTY; |
VOP_UNLOCK(vp, 0); |
VOP_UNLOCK(vp, 0); |
error = cdev_open(dev, ap->a_mode, S_IFCHR, l); |
error = cdev_open(dev, ap->a_mode, S_IFCHR, l); |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
Line 295 spec_read(void *v) |
|
Line 295 spec_read(void *v) |
|
error = bread(vp, bn, bsize, NOCRED, &bp); |
error = bread(vp, bn, bsize, NOCRED, &bp); |
n = min(n, bsize - bp->b_resid); |
n = min(n, bsize - bp->b_resid); |
if (error) { |
if (error) { |
brelse(bp); |
brelse(bp, 0); |
return (error); |
return (error); |
} |
} |
error = uiomove((char *)bp->b_data + on, n, uio); |
error = uiomove((char *)bp->b_data + on, n, uio); |
brelse(bp); |
brelse(bp, 0); |
} while (error == 0 && uio->uio_resid > 0 && n != 0); |
} while (error == 0 && uio->uio_resid > 0 && n != 0); |
return (error); |
return (error); |
|
|
Line 370 spec_write(void *v) |
|
Line 370 spec_write(void *v) |
|
else |
else |
error = bread(vp, bn, bsize, NOCRED, &bp); |
error = bread(vp, bn, bsize, NOCRED, &bp); |
if (error) { |
if (error) { |
brelse(bp); |
brelse(bp, 0); |
return (error); |
return (error); |
} |
} |
n = min(n, bsize - bp->b_resid); |
n = min(n, bsize - bp->b_resid); |
error = uiomove((char *)bp->b_data + on, n, uio); |
error = uiomove((char *)bp->b_data + on, n, uio); |
if (error) |
if (error) |
brelse(bp); |
brelse(bp, 0); |
else { |
else { |
if (n + on == bsize) |
if (n + on == bsize) |
bawrite(bp); |
bawrite(bp); |
else |
else |
bdwrite(bp); |
bdwrite(bp); |
if (bp->b_error != 0) |
error = bp->b_error; |
error = bp->b_error; |
|
} |
} |
} while (error == 0 && uio->uio_resid > 0 && n != 0); |
} while (error == 0 && uio->uio_resid > 0 && n != 0); |
return (error); |
return (error); |
Line 407 spec_ioctl(void *v) |
|
Line 406 spec_ioctl(void *v) |
|
void *a_data; |
void *a_data; |
int a_fflag; |
int a_fflag; |
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct lwp *a_l; |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp; |
struct vnode *vp; |
dev_t dev; |
dev_t dev; |
Line 420 spec_ioctl(void *v) |
|
Line 418 spec_ioctl(void *v) |
|
vp = ap->a_vp; |
vp = ap->a_vp; |
dev = NODEV; |
dev = NODEV; |
simple_lock(&vp->v_interlock); |
simple_lock(&vp->v_interlock); |
if ((vp->v_flag & VXLOCK) == 0 && vp->v_specinfo) { |
if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specinfo) { |
dev = vp->v_rdev; |
dev = vp->v_rdev; |
} |
} |
simple_unlock(&vp->v_interlock); |
simple_unlock(&vp->v_interlock); |
Line 432 spec_ioctl(void *v) |
|
Line 430 spec_ioctl(void *v) |
|
|
|
case VCHR: |
case VCHR: |
return cdev_ioctl(dev, ap->a_command, ap->a_data, |
return cdev_ioctl(dev, ap->a_command, ap->a_data, |
ap->a_fflag, ap->a_l); |
ap->a_fflag, curlwp); |
|
|
case VBLK: |
case VBLK: |
if (ap->a_command == 0 && (long)ap->a_data == B_TAPE) { |
|
if (bdev_type(dev) == D_TAPE) |
|
return (0); |
|
else |
|
return (1); |
|
} |
|
return bdev_ioctl(dev, ap->a_command, ap->a_data, |
return bdev_ioctl(dev, ap->a_command, ap->a_data, |
ap->a_fflag, ap->a_l); |
ap->a_fflag, curlwp); |
|
|
default: |
default: |
panic("spec_ioctl"); |
panic("spec_ioctl"); |
Line 457 spec_poll(void *v) |
|
Line 449 spec_poll(void *v) |
|
struct vop_poll_args /* { |
struct vop_poll_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
int a_events; |
int a_events; |
struct lwp *a_l; |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp; |
struct vnode *vp; |
dev_t dev; |
dev_t dev; |
Line 470 spec_poll(void *v) |
|
Line 461 spec_poll(void *v) |
|
vp = ap->a_vp; |
vp = ap->a_vp; |
dev = NODEV; |
dev = NODEV; |
simple_lock(&vp->v_interlock); |
simple_lock(&vp->v_interlock); |
if ((vp->v_flag & VXLOCK) == 0 && vp->v_specinfo) { |
if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specinfo) { |
dev = vp->v_rdev; |
dev = vp->v_rdev; |
} |
} |
simple_unlock(&vp->v_interlock); |
simple_unlock(&vp->v_interlock); |
Line 481 spec_poll(void *v) |
|
Line 472 spec_poll(void *v) |
|
switch (vp->v_type) { |
switch (vp->v_type) { |
|
|
case VCHR: |
case VCHR: |
return cdev_poll(dev, ap->a_events, ap->a_l); |
return cdev_poll(dev, ap->a_events, curlwp); |
|
|
default: |
default: |
return (genfs_poll(v)); |
return (genfs_poll(v)); |
Line 522 spec_mmap(void *v) |
|
Line 513 spec_mmap(void *v) |
|
struct vnode *a_vp; |
struct vnode *a_vp; |
vm_prot_t a_prot; |
vm_prot_t a_prot; |
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct lwp *a_l; |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
|
|
Line 546 spec_fsync(void *v) |
|
Line 536 spec_fsync(void *v) |
|
int a_flags; |
int a_flags; |
off_t offlo; |
off_t offlo; |
off_t offhi; |
off_t offhi; |
struct lwp *a_l; |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
|
|
Line 567 spec_strategy(void *v) |
|
Line 556 spec_strategy(void *v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct buf *bp = ap->a_bp; |
struct buf *bp = ap->a_bp; |
int error, s; |
int error; |
struct spec_cow_entry *e; |
|
|
|
error = 0; |
error = 0; |
bp->b_dev = vp->v_rdev; |
bp->b_dev = vp->v_rdev; |
if (!(bp->b_flags & B_READ) && |
if (!(bp->b_flags & B_READ) && |
(LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start) |
(LIST_FIRST(&bp->b_dep)) != NULL && bioopsp) |
(*bioops.io_start)(bp); |
bioopsp->io_start(bp); |
|
|
if (!(bp->b_flags & B_READ) && !SLIST_EMPTY(&vp->v_spec_cow_head)) { |
if (!(bp->b_flags & B_READ)) |
SPEC_COW_LOCK(vp->v_specinfo, s); |
error = fscow_run(bp, false); |
while (vp->v_spec_cow_req > 0) |
|
ltsleep(&vp->v_spec_cow_req, PRIBIO, "cowlist", 0, |
|
&vp->v_spec_cow_slock); |
|
vp->v_spec_cow_count++; |
|
SPEC_COW_UNLOCK(vp->v_specinfo, s); |
|
|
|
SLIST_FOREACH(e, &vp->v_spec_cow_head, ce_list) { |
|
if ((error = (*e->ce_func)(e->ce_cookie, bp)) != 0) |
|
break; |
|
} |
|
|
|
SPEC_COW_LOCK(vp->v_specinfo, s); |
|
vp->v_spec_cow_count--; |
|
if (vp->v_spec_cow_req && vp->v_spec_cow_count == 0) |
|
wakeup(&vp->v_spec_cow_req); |
|
SPEC_COW_UNLOCK(vp->v_specinfo, s); |
|
} |
|
|
|
if (error) { |
if (error) { |
bp->b_error = error; |
bp->b_error = error; |
Line 653 spec_close(void *v) |
|
Line 624 spec_close(void *v) |
|
struct vnode *a_vp; |
struct vnode *a_vp; |
int a_fflag; |
int a_fflag; |
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct lwp *a_l; |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct session *sess; |
struct session *sess; |
Line 661 spec_close(void *v) |
|
Line 631 spec_close(void *v) |
|
int mode, error, count, flags, flags1; |
int mode, error, count, flags, flags1; |
|
|
count = vcount(vp); |
count = vcount(vp); |
flags = vp->v_flag; |
flags = vp->v_iflag; |
|
|
switch (vp->v_type) { |
switch (vp->v_type) { |
|
|
Line 680 spec_close(void *v) |
|
Line 650 spec_close(void *v) |
|
* actual tty device. |
* actual tty device. |
*/ |
*/ |
mutex_enter(&proclist_lock); |
mutex_enter(&proclist_lock); |
if (count == 2 && ap->a_l && |
if (count == 2 && |
vp == (sess = ap->a_l->l_proc->p_session)->s_ttyvp) { |
vp == (sess = curlwp->l_proc->p_session)->s_ttyvp) { |
sess->s_ttyvp = NULL; |
sess->s_ttyvp = NULL; |
if (sess->s_ttyp->t_session != NULL) { |
if (sess->s_ttyp->t_session != NULL) { |
sess->s_ttyp->t_pgrp = NULL; |
sess->s_ttyp->t_pgrp = NULL; |
Line 703 spec_close(void *v) |
|
Line 673 spec_close(void *v) |
|
* of forcably closing the device, otherwise we only |
* of forcably closing the device, otherwise we only |
* close on last reference. |
* close on last reference. |
*/ |
*/ |
if (count > 1 && (flags & VXLOCK) == 0) |
if (count > 1 && (flags & VI_XLOCK) == 0) |
return (0); |
return (0); |
mode = S_IFCHR; |
mode = S_IFCHR; |
break; |
break; |
Line 714 spec_close(void *v) |
|
Line 684 spec_close(void *v) |
|
* we must invalidate any in core blocks, so that |
* we must invalidate any in core blocks, so that |
* we can, for instance, change floppy disks. |
* we can, for instance, change floppy disks. |
*/ |
*/ |
error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_l, 0, 0); |
error = vinvalbuf(vp, V_SAVE, ap->a_cred, curlwp, 0, 0); |
if (error) |
if (error) |
return (error); |
return (error); |
/* |
/* |
Line 726 spec_close(void *v) |
|
Line 696 spec_close(void *v) |
|
* sum of the reference counts on all the aliased |
* sum of the reference counts on all the aliased |
* vnodes descends to one, we are on last close. |
* vnodes descends to one, we are on last close. |
*/ |
*/ |
if (count > 1 && (flags & VXLOCK) == 0) |
if (count > 1 && (flags & VI_XLOCK) == 0) |
return (0); |
return (0); |
mode = S_IFBLK; |
mode = S_IFBLK; |
break; |
break; |
Line 738 spec_close(void *v) |
|
Line 708 spec_close(void *v) |
|
flags1 = ap->a_fflag; |
flags1 = ap->a_fflag; |
|
|
/* |
/* |
* if VXLOCK is set, then we're going away soon, so make this |
* if VI_XLOCK is set, then we're going away soon, so make this |
* non-blocking. Also ensures that we won't wedge in vn_lock below. |
* non-blocking. Also ensures that we won't wedge in vn_lock below. |
*/ |
*/ |
if (flags & VXLOCK) |
if (flags & VI_XLOCK) |
flags1 |= FNONBLOCK; |
flags1 |= FNONBLOCK; |
|
|
/* |
/* |
* If we're able to block, release the vnode lock & reacquire. We |
* If we're able to block, release the vnode lock & reacquire. We |
* might end up sleeping for someone else who wants our queues. They |
* might end up sleeping for someone else who wants our queues. They |
* won't get them if we hold the vnode locked. Also, if VXLOCK is |
* won't get them if we hold the vnode locked. Also, if VI_XLOCK is |
* set, don't release the lock as we won't be able to regain it. |
* set, don't release the lock as we won't be able to regain it. |
*/ |
*/ |
if (!(flags1 & FNONBLOCK)) |
if (!(flags1 & FNONBLOCK)) |
VOP_UNLOCK(vp, 0); |
VOP_UNLOCK(vp, 0); |
|
|
if (vp->v_type == VBLK) |
if (vp->v_type == VBLK) |
error = bdev_close(dev, flags1, mode, ap->a_l); |
error = bdev_close(dev, flags1, mode, curlwp); |
else |
else |
error = cdev_close(dev, flags1, mode, ap->a_l); |
error = cdev_close(dev, flags1, mode, curlwp); |
|
|
if (!(flags1 & FNONBLOCK)) |
if (!(flags1 & FNONBLOCK)) |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |