* Copyright (c) 1990 The Regents of the University of California.
* %sccs.include.redist.c%
* @(#)fifo_vnops.c 7.13 (Berkeley) %G%
* This structure is associated with the FIFO vnode and stores
* the state associated with the FIFO.
struct socket
*fi_readsock
;
struct socket
*fi_writesock
;
int (**fifo_vnodeop_p
)();
struct vnodeopv_entry_desc fifo_vnodeop_entries
[] = {
{ &vop_default_desc
, vn_default_error
},
{ &vop_lookup_desc
, fifo_lookup
}, /* lookup */
{ &vop_create_desc
, fifo_create
}, /* create */
{ &vop_mknod_desc
, fifo_mknod
}, /* mknod */
{ &vop_open_desc
, fifo_open
}, /* open */
{ &vop_close_desc
, fifo_close
}, /* close */
{ &vop_access_desc
, fifo_access
}, /* access */
{ &vop_getattr_desc
, fifo_getattr
}, /* getattr */
{ &vop_setattr_desc
, fifo_setattr
}, /* setattr */
{ &vop_read_desc
, fifo_read
}, /* read */
{ &vop_write_desc
, fifo_write
}, /* write */
{ &vop_ioctl_desc
, fifo_ioctl
}, /* ioctl */
{ &vop_select_desc
, fifo_select
}, /* select */
{ &vop_mmap_desc
, fifo_mmap
}, /* mmap */
{ &vop_fsync_desc
, fifo_fsync
}, /* fsync */
{ &vop_seek_desc
, fifo_seek
}, /* seek */
{ &vop_remove_desc
, fifo_remove
}, /* remove */
{ &vop_link_desc
, fifo_link
}, /* link */
{ &vop_rename_desc
, fifo_rename
}, /* rename */
{ &vop_mkdir_desc
, fifo_mkdir
}, /* mkdir */
{ &vop_rmdir_desc
, fifo_rmdir
}, /* rmdir */
{ &vop_symlink_desc
, fifo_symlink
}, /* symlink */
{ &vop_readdir_desc
, fifo_readdir
}, /* readdir */
{ &vop_readlink_desc
, fifo_readlink
}, /* readlink */
{ &vop_abortop_desc
, fifo_abortop
}, /* abortop */
{ &vop_inactive_desc
, fifo_inactive
}, /* inactive */
{ &vop_reclaim_desc
, fifo_reclaim
}, /* reclaim */
{ &vop_lock_desc
, fifo_lock
}, /* lock */
{ &vop_unlock_desc
, fifo_unlock
}, /* unlock */
{ &vop_bmap_desc
, fifo_bmap
}, /* bmap */
{ &vop_strategy_desc
, fifo_strategy
}, /* strategy */
{ &vop_print_desc
, fifo_print
}, /* print */
{ &vop_islocked_desc
, fifo_islocked
}, /* islocked */
{ &vop_advlock_desc
, fifo_advlock
}, /* advlock */
{ &vop_blkatoff_desc
, fifo_blkatoff
}, /* blkatoff */
{ &vop_vget_desc
, fifo_vget
}, /* vget */
{ &vop_valloc_desc
, fifo_valloc
}, /* valloc */
{ &vop_vfree_desc
, fifo_vfree
}, /* vfree */
{ &vop_truncate_desc
, fifo_truncate
}, /* truncate */
{ &vop_update_desc
, fifo_update
}, /* update */
{ &vop_bwrite_desc
, fifo_bwrite
}, /* bwrite */
{ (struct vnodeop_desc
*)NULL
, (int(*)())NULL
}
struct vnodeopv_desc fifo_vnodeop_opv_desc
=
{ &fifo_vnodeop_p
, fifo_vnodeop_entries
};
* Trivial lookup routine that always fails.
struct vop_lookup_args
*ap
;
* Open called to set up a new instance of a fifo or
* to find an active instance of a fifo.
struct vop_open_args
*ap
;
#define mode (ap->a_mode)
#define cred (ap->a_cred)
register struct fifoinfo
*fip
;
struct socket
*rso
, *wso
;
static char openstr
[] = "fifo";
if ((mode
& (FREAD
|FWRITE
)) == (FREAD
|FWRITE
))
if ((fip
= vp
->v_fifoinfo
) == NULL
) {
MALLOC(fip
, struct fifoinfo
*, sizeof(*fip
), M_VNODE
, M_WAITOK
);
if (error
= socreate(AF_UNIX
, &rso
, SOCK_STREAM
, 0)) {
if (error
= socreate(AF_UNIX
, &wso
, SOCK_STREAM
, 0)) {
if (error
= unp_connect2(wso
, rso
)) {
fip
->fi_readers
= fip
->fi_writers
= 0;
wso
->so_state
|= SS_CANTRCVMORE
;
rso
->so_state
|= SS_CANTSENDMORE
;
if (fip
->fi_readers
== 1) {
fip
->fi_writesock
->so_state
&= ~SS_CANTSENDMORE
;
wakeup((caddr_t
)&fip
->fi_writers
);
while (fip
->fi_writers
== 0) {
error
= tsleep((caddr_t
)&fip
->fi_readers
, PSOCK
,
if (fip
->fi_readers
== 0 && (mode
& O_NONBLOCK
)) {
if (fip
->fi_writers
== 1) {
fip
->fi_readsock
->so_state
&= ~SS_CANTRCVMORE
;
wakeup((caddr_t
)&fip
->fi_readers
);
while (fip
->fi_readers
== 0) {
error
= tsleep((caddr_t
)&fip
->fi_writers
,
VOP_CLOSE(vp
, mode
, cred
, p
);
struct vop_read_args
*ap
;
#define ioflag (ap->a_ioflag)
#define cred (ap->a_cred)
register struct socket
*rso
= vp
->v_fifoinfo
->fi_readsock
;
if (uio
->uio_rw
!= UIO_READ
)
rso
->so_state
|= SS_NBIO
;
startresid
= uio
->uio_resid
;
error
= soreceive(rso
, (struct mbuf
**)0, uio
, (int *)0,
(struct mbuf
**)0, (struct mbuf
**)0);
* Clear EOF indication after first such return.
if (uio
->uio_resid
== startresid
)
rso
->so_state
&= ~SS_CANTRCVMORE
;
rso
->so_state
&= ~SS_NBIO
;
struct vop_write_args
*ap
;
#define ioflag (ap->a_ioflag)
#define cred (ap->a_cred)
struct socket
*wso
= vp
->v_fifoinfo
->fi_writesock
;
if (uio
->uio_rw
!= UIO_WRITE
)
panic("fifo_write mode");
wso
->so_state
|= SS_NBIO
;
error
= sosend(wso
, (struct mbuf
*)0, uio
, 0, (struct mbuf
*)0, 0);
wso
->so_state
&= ~SS_NBIO
;
* Device ioctl operation.
struct vop_ioctl_args
*ap
;
#define com (ap->a_command)
#define data (ap->a_data)
#define fflag (ap->a_fflag)
#define cred (ap->a_cred)
filetmp
.f_data
= (caddr_t
)vp
->v_fifoinfo
->fi_readsock
;
filetmp
.f_data
= (caddr_t
)vp
->v_fifoinfo
->fi_writesock
;
return (soo_ioctl(&filetmp
, com
, data
, p
));
struct vop_select_args
*ap
;
#define which (ap->a_which)
#define fflag (ap->a_fflags)
#define cred (ap->a_cred)
filetmp
.f_data
= (caddr_t
)vp
->v_fifoinfo
->fi_readsock
;
filetmp
.f_data
= (caddr_t
)vp
->v_fifoinfo
->fi_writesock
;
return (soo_select(&filetmp
, which
, p
));
* This is a noop, simply returning what one has been given.
struct vop_bmap_args
*ap
;
* At the moment we do not do any locking.
struct vop_lock_args
*ap
;
struct vop_unlock_args
*ap
;
struct vop_close_args
*ap
;
#define fflag (ap->a_fflag)
#define cred (ap->a_cred)
register struct fifoinfo
*fip
= vp
->v_fifoinfo
;
if (fip
->fi_writers
== 0)
socantrcvmore(fip
->fi_readsock
);
if (fip
->fi_readers
== 0)
socantsendmore(fip
->fi_writesock
);
error1
= soclose(fip
->fi_readsock
);
error2
= soclose(fip
->fi_writesock
);
* Print out the contents of a fifo vnode.
struct vop_print_args
*ap
;
* Print out internal contents of a fifo vnode.
register struct fifoinfo
*fip
= vp
->v_fifoinfo
;
printf(", fifo with %d readers and %d writers",
fip
->fi_readers
, fip
->fi_writers
);
* Fifo advisory byte-level locks.
struct vop_advlock_args
*ap
;
#define flags (ap->a_flags)
panic("fifo_badop called");