/* * 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; }
void free_xfs_node(struct xfs_node *node) { struct xfs *xfsp = NNPFS_FROM_XNODE(node); NNPFSDEB(XDEBNODE, ("free_xfs_node(%lx) (%d,%d,%d,%d)\n", (unsigned long)node, node->handle.a, node->handle.b, node->handle.c, node->handle.d)); /* XXX Really need to put back dirty data first. */ if (DATA_FROM_XNODE(node)) { vrele(DATA_FROM_XNODE(node)); DATA_FROM_XNODE(node) = NULL; } xfsp->nnodes--; XNODE_TO_VNODE(node)->v_data = NULL; if (node->rd_cred) { crfree (node->rd_cred); node->rd_cred = NULL; } if (node->wr_cred) { crfree (node->wr_cred); node->wr_cred = NULL; } xfs_free(node, sizeof(*node), M_NNPFS_NODE); NNPFSDEB(XDEBNODE, ("free_xfs_node done\n")); }
/* * 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; }
/* * Send a message to user space and wait for reply. */ int xfs_message_rpc(int fd, struct xfs_message_header * message, u_int size) { int ret; struct xfs_channel *chan = &xfs_channel[fd]; struct xfs_link *this_message; struct xfs_link *this_process; struct xfs_message_header *msg; #if defined(HAVE_STRUCT_PROC_P_SIGMASK) sigset_t oldsigmask; #endif /* HAVE_STRUCT_PROC_P_SIGMASK */ XFSDEB(XDEBMSG, ("xfs_message_rpc opcode = %d\n", message->opcode)); if (!(chan->status & CHANNEL_OPENED)) /* No receiver? */ return ENODEV; if (size < sizeof(struct xfs_message_wakeup)) { printf("XFS PANIC Error: Message to small to receive wakeup, opcode = %d\n", message->opcode); return ENOMEM; } this_message = xfs_alloc(sizeof(struct xfs_link)); this_process = xfs_alloc(sizeof(struct xfs_link)); msg = xfs_alloc(size); bcopy(message, msg, size); msg->size = size; msg->sequence_num = chan->nsequence++; this_message->error_or_size = 0; this_message->message = msg; this_process->message = msg; xfs_appendq(&chan->messageq, this_message); xfs_appendq(&chan->sleepq, this_process); xfs_select_wakeup(chan); this_process->error_or_size = 0; if (chan->status & CHANNEL_WAITING) { chan->status &= ~CHANNEL_WAITING; wakeup((caddr_t) chan); } /* * Remove SIGIO from the sigmask so no IO will * wake us up from tsleep() */ #ifdef HAVE_STRUCT_PROC_P_SIGMASK oldsigmask = xfs_curproc()->p_sigmask; #ifdef __sigaddset __sigaddset(&xfs_curproc()->p_sigmask, SIGIO); #else xfs_curproc()->p_sigmask |= sigmask(SIGIO); #endif /* __sigaddset */ #elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) oldsigmask = xfs_curproc()->p_sigwaitmask; sigaddset(&xfs_curproc()->p_sigwaitmask, SIGIO); #endif /* * We have to check if we have a receiver here too because the * daemon could have terminated before we sleep. This seems to * happen sometimes when rebooting. */ if (!(chan->status & CHANNEL_OPENED) || tsleep((caddr_t) this_process, (PZERO + 1) | PCATCH, "xfs", 0)) { XFSDEB(XDEBMSG, ("caught signal\n")); this_process->error_or_size = EINTR; } #ifdef HAVE_STRUCT_PROC_P_SIGMASK xfs_curproc()->p_sigmask = oldsigmask; #elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) xfs_curproc()->p_sigwaitmask = oldsigmask; #endif /* * Caught signal, got reply message or device was closed. * Need to clean up both messageq and sleepq. */ if (xfs_onq(this_message)) { xfs_outq(this_message); } if (xfs_onq(this_process)) { xfs_outq(this_process); } ret = this_process->error_or_size; XFSDEB(XDEBMSG, ("xfs_message_rpc this_process->error_or_size = %d\n", this_process->error_or_size)); XFSDEB(XDEBMSG, ("xfs_message_rpc opcode ((xfs_message_wakeup*)(this_process->message))->error = %d\n", ((struct xfs_message_wakeup *) (this_process->message))->error)); bcopy(msg, message, size); xfs_free(this_message, sizeof(*this_message)); xfs_free(this_process, sizeof(*this_process)); xfs_free(msg, size); return ret; }