/* * Wakeup all sleepers and cleanup. */ int xfs_devclose_common(dev_t dev, struct proc *proc) { struct xfs_channel *chan = &xfs_channel[minor(dev)]; struct xfs_link *first; /* Sanity check, paranoia? */ if (!(chan->status & CHANNEL_OPENED)) panic("xfs_devclose never opened?"); chan->status &= ~CHANNEL_OPENED; /* No one is going to read those messages so empty queue! */ while (!xfs_emptyq(&chan->messageq)) { XFSDEB(XDEBDEV, ("before outq(messageq)\n")); first = chan->messageq.next; xfs_outq(first); if (first->error_or_size != 0) xfs_free(first, first->error_or_size); XFSDEB(XDEBDEV, ("after outq(messageq)\n")); } /* Wakeup those waiting for replies that will never arrive. */ while (!xfs_emptyq(&chan->sleepq)) { XFSDEB(XDEBDEV, ("before outq(sleepq)\n")); first = chan->sleepq.next; xfs_outq(first); first->error_or_size = ENODEV; wakeup((caddr_t) first); XFSDEB(XDEBDEV, ("after outq(sleepq)\n")); } if (chan->status & CHANNEL_WAITING) wakeup((caddr_t) chan); if (chan->message_buffer) { xfs_free(chan->message_buffer, MAX_XMSG_SIZE); chan->message_buffer = NULL; } /* * Free all xfs nodes. */ if (xfs[minor(dev)].mp != NULL) { if (xfs_vfs_busy(xfs[minor(dev)].mp, 0, NULL, proc)) { XFSDEB(XDEBNODE, ("xfs_dev_close: vfs_busy() --> BUSY\n")); return EBUSY; } free_all_xfs_nodes(&xfs[minor(dev)], FORCECLOSE, 0); xfs_vfs_unbusy(xfs[minor(dev)].mp, proc); } return 0; }
/* * Move messages from kernel to user space. */ int xfs_devread(dev_t dev, struct uio * uiop, int ioflag) { struct xfs_channel *chan = &xfs_channel[minor(dev)]; struct xfs_link *first; int error = 0; XFSDEB(XDEBDEV, ("xfs_devread dev = %d\n", dev)); XFSDEB(XDEBDEV, ("xfs_devread: m = %p, m->prev = %p, m->next = %p\n", &chan->messageq, chan->messageq.prev, chan->messageq.next)); again: if (!xfs_emptyq (&chan->messageq)) { while (!xfs_emptyq (&chan->messageq)) { /* Remove message */ first = chan->messageq.next; XFSDEB(XDEBDEV, ("xfs_devread: first = %p, " "first->prev = %p, first->next = %p\n", first, first->prev, first->next)); XFSDEB(XDEBDEV, ("xfs_devread: message->size = %u\n", first->message->size)); error = uiomove((caddr_t) first->message, first->message->size, uiop); if (error) break; xfs_outq(first); if (first->error_or_size != 0) xfs_free(first, first->error_or_size); } } else { chan->status |= CHANNEL_WAITING; if (tsleep((caddr_t) chan, (PZERO + 1) | PCATCH, "xfsr", 0)) { XFSDEB(XDEBMSG, ("caught signal xfs_devread\n")); error = EINTR; } else if ((chan->status & CHANNEL_WAITING) == 0) { goto again; } else error = EIO; } XFSDEB(XDEBDEV, ("xfs_devread done error = %d\n", error)); return error; }
static int xfs_realselect(dev_t dev, struct proc *p) { struct xfs_channel *chan = &xfs_channel[minor(dev)]; if (!xfs_emptyq(&chan->messageq)) return 1; /* Something to read */ selrecord (p, &chan->selinfo); return 0; }
int xfs_devpoll(dev_t dev, int events, d_thread_t * p) { struct xfs_channel *chan = &xfs_channel[minor(dev)]; NNPFSDEB(XDEBDEV, ("xfs_devpoll dev = %d(%d), events = 0x%x\n", major(dev), minor(dev), events)); if ((events & (POLLIN | POLLRDNORM)) == 0) return 0; /* only supports read */ if (!xfs_emptyq(&chan->messageq)) return (events & (POLLIN | POLLRDNORM)); selrecord (p, &chan->selinfo); return 0; }