version 1.30, 2001/02/27 19:52:21 |
version 1.30.4.4, 2002/09/06 08:48:34 |
|
|
* @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 |
* @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 |
*/ |
*/ |
|
|
|
#include <sys/cdefs.h> |
|
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
|
|
#include <sys/malloc.h> |
#include <sys/malloc.h> |
#include <sys/un.h> |
#include <sys/un.h> |
#include <sys/poll.h> |
#include <sys/poll.h> |
|
#include <sys/event.h> |
|
|
#include <miscfs/fifofs/fifo.h> |
#include <miscfs/fifofs/fifo.h> |
#include <miscfs/genfs/genfs.h> |
#include <miscfs/genfs/genfs.h> |
|
|
struct fifoinfo { |
struct fifoinfo { |
struct socket *fi_readsock; |
struct socket *fi_readsock; |
struct socket *fi_writesock; |
struct socket *fi_writesock; |
|
long fi_opencount; |
long fi_readers; |
long fi_readers; |
long fi_writers; |
long fi_writers; |
}; |
}; |
|
|
|
static void filt_fifordetach(struct knote *kn); |
|
static int filt_fiforead(struct knote *kn, long hint); |
|
static void filt_fifowdetach(struct knote *kn); |
|
static int filt_fifowrite(struct knote *kn, long hint); |
|
|
|
const struct filterops fiforead_filtops = |
|
{ 1, NULL, filt_fifordetach, filt_fiforead }; |
|
const struct filterops fifowrite_filtops = |
|
{ 1, NULL, filt_fifowdetach, filt_fifowrite }; |
|
|
int (**fifo_vnodeop_p) __P((void *)); |
int (**fifo_vnodeop_p) __P((void *)); |
const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { |
const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { |
{ &vop_default_desc, vn_default_error }, |
{ &vop_default_desc, vn_default_error }, |
Line 81 const struct vnodeopv_entry_desc fifo_vn |
|
Line 96 const struct vnodeopv_entry_desc fifo_vn |
|
{ &vop_lease_desc, fifo_lease_check }, /* lease */ |
{ &vop_lease_desc, fifo_lease_check }, /* lease */ |
{ &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ |
{ &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ |
{ &vop_poll_desc, fifo_poll }, /* poll */ |
{ &vop_poll_desc, fifo_poll }, /* poll */ |
|
{ &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */ |
{ &vop_revoke_desc, fifo_revoke }, /* revoke */ |
{ &vop_revoke_desc, fifo_revoke }, /* revoke */ |
{ &vop_mmap_desc, fifo_mmap }, /* mmap */ |
{ &vop_mmap_desc, fifo_mmap }, /* mmap */ |
{ &vop_fsync_desc, fifo_fsync }, /* fsync */ |
{ &vop_fsync_desc, fifo_fsync }, /* fsync */ |
Line 110 const struct vnodeopv_entry_desc fifo_vn |
|
Line 126 const struct vnodeopv_entry_desc fifo_vn |
|
{ &vop_truncate_desc, fifo_truncate }, /* truncate */ |
{ &vop_truncate_desc, fifo_truncate }, /* truncate */ |
{ &vop_update_desc, fifo_update }, /* update */ |
{ &vop_update_desc, fifo_update }, /* update */ |
{ &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ |
|
{ &vop_putpages_desc, fifo_putpages }, /* putpages */ |
{ (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } |
{ (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } |
}; |
}; |
const struct vnodeopv_desc fifo_vnodeop_opv_desc = |
const struct vnodeopv_desc fifo_vnodeop_opv_desc = |
Line 180 fifo_open(void *v) |
|
Line 197 fifo_open(void *v) |
|
return (error); |
return (error); |
} |
} |
fip->fi_readers = fip->fi_writers = 0; |
fip->fi_readers = fip->fi_writers = 0; |
|
fip->fi_opencount = 0; |
wso->so_state |= SS_CANTRCVMORE; |
wso->so_state |= SS_CANTRCVMORE; |
rso->so_state |= SS_CANTSENDMORE; |
rso->so_state |= SS_CANTSENDMORE; |
} |
} |
|
fip->fi_opencount++; |
if (ap->a_mode & FREAD) { |
if (ap->a_mode & FREAD) { |
if (fip->fi_readers++ == 0) { |
if (fip->fi_readers++ == 0) { |
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; |
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; |
Line 248 fifo_read(void *v) |
|
Line 267 fifo_read(void *v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct uio *uio; |
struct uio *uio; |
struct socket *rso; |
struct socket *rso; |
int error, startresid; |
int error; |
|
size_t startresid; |
|
|
uio = ap->a_uio; |
uio = ap->a_uio; |
rso = ap->a_vp->v_fifoinfo->fi_readsock; |
rso = ap->a_vp->v_fifoinfo->fi_readsock; |
Line 423 fifo_close(void *v) |
|
Line 443 fifo_close(void *v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp; |
struct vnode *vp; |
struct fifoinfo *fip; |
struct fifoinfo *fip; |
int error1, error2; |
|
|
|
vp = ap->a_vp; |
vp = ap->a_vp; |
fip = vp->v_fifoinfo; |
fip = vp->v_fifoinfo; |
Line 435 fifo_close(void *v) |
|
Line 454 fifo_close(void *v) |
|
if (--fip->fi_writers == 0) |
if (--fip->fi_writers == 0) |
socantrcvmore(fip->fi_readsock); |
socantrcvmore(fip->fi_readsock); |
} |
} |
if (vp->v_usecount > 1) |
if (--fip->fi_opencount == 0) { |
return (0); |
(void) soclose(fip->fi_readsock); |
error1 = soclose(fip->fi_readsock); |
(void) soclose(fip->fi_writesock); |
error2 = soclose(fip->fi_writesock); |
FREE(fip, M_VNODE); |
FREE(fip, M_VNODE); |
vp->v_fifoinfo = NULL; |
vp->v_fifoinfo = NULL; |
} |
if (error1) |
return (0); |
return (error1); |
|
return (error2); |
|
} |
} |
|
|
/* |
/* |
Line 505 fifo_pathconf(void *v) |
|
Line 522 fifo_pathconf(void *v) |
|
} |
} |
/* NOTREACHED */ |
/* NOTREACHED */ |
} |
} |
|
|
|
/* ARGSUSED */ |
|
int |
|
fifo_kqfilter(void *v) |
|
{ |
|
struct vop_kqfilter_args /* { |
|
struct vnode *a_vp; |
|
struct knote *a_kn; |
|
} */ *ap = v; |
|
struct socket *so; |
|
struct sockbuf *sb; |
|
|
|
so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock; |
|
switch (ap->a_kn->kn_filter) { |
|
case EVFILT_READ: |
|
ap->a_kn->kn_fop = &fiforead_filtops; |
|
sb = &so->so_rcv; |
|
break; |
|
case EVFILT_WRITE: |
|
ap->a_kn->kn_fop = &fifowrite_filtops; |
|
sb = &so->so_snd; |
|
break; |
|
default: |
|
return (1); |
|
} |
|
|
|
SLIST_INSERT_HEAD(&sb->sb_sel.si_klist, ap->a_kn, kn_selnext); |
|
sb->sb_flags |= SB_KNOTE; |
|
return (0); |
|
} |
|
|
|
static void |
|
filt_fifordetach(struct knote *kn) |
|
{ |
|
struct socket *so; |
|
|
|
so = (struct socket *)kn->kn_hook; |
|
SLIST_REMOVE(&so->so_rcv.sb_sel.si_klist, kn, knote, kn_selnext); |
|
if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_klist)) |
|
so->so_rcv.sb_flags &= ~SB_KNOTE; |
|
} |
|
|
|
static int |
|
filt_fiforead(struct knote *kn, long hint) |
|
{ |
|
struct socket *so; |
|
|
|
so = (struct socket *)kn->kn_hook; |
|
kn->kn_data = so->so_rcv.sb_cc; |
|
if (so->so_state & SS_CANTRCVMORE) { |
|
kn->kn_flags |= EV_EOF; |
|
return (1); |
|
} |
|
kn->kn_flags &= ~EV_EOF; |
|
return (kn->kn_data > 0); |
|
} |
|
|
|
static void |
|
filt_fifowdetach(struct knote *kn) |
|
{ |
|
struct socket *so; |
|
|
|
so = (struct socket *)kn->kn_hook; |
|
SLIST_REMOVE(&so->so_snd.sb_sel.si_klist, kn, knote, kn_selnext); |
|
if (SLIST_EMPTY(&so->so_snd.sb_sel.si_klist)) |
|
so->so_snd.sb_flags &= ~SB_KNOTE; |
|
} |
|
|
|
static int |
|
filt_fifowrite(struct knote *kn, long hint) |
|
{ |
|
struct socket *so; |
|
|
|
so = (struct socket *)kn->kn_hook; |
|
kn->kn_data = sbspace(&so->so_snd); |
|
if (so->so_state & SS_CANTSENDMORE) { |
|
kn->kn_flags |= EV_EOF; |
|
return (1); |
|
} |
|
kn->kn_flags &= ~EV_EOF; |
|
return (kn->kn_data >= so->so_snd.sb_lowat); |
|
} |