summaryrefslogtreecommitdiffstats
path: root/sys/nfs4client/nfs4_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfs4client/nfs4_dev.c')
-rw-r--r--sys/nfs4client/nfs4_dev.c456
1 files changed, 0 insertions, 456 deletions
diff --git a/sys/nfs4client/nfs4_dev.c b/sys/nfs4client/nfs4_dev.c
deleted file mode 100644
index fc1e487..0000000
--- a/sys/nfs4client/nfs4_dev.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/* $FreeBSD$ */
-/* $Id: nfs4_dev.c,v 1.10 2003/11/05 14:58:59 rees Exp $ */
-
-/*-
- * copyright (c) 2003
- * the regents of the university of michigan
- * all rights reserved
- *
- * permission is granted to use, copy, create derivative works and redistribute
- * this software and such derivative works for any purpose, so long as the name
- * of the university of michigan is not used in any advertising or publicity
- * pertaining to the use or distribution of this software without specific,
- * written prior authorization. if the above copyright notice or any other
- * identification of the university of michigan is included in any copy of any
- * portion of this software, then the disclaimer below must also be included.
- *
- * this software is provided as is, without representation from the university
- * of michigan as to its fitness for any purpose, and without warranty by the
- * university of michigan of any kind, either express or implied, including
- * without limitation the implied warranties of merchantability and fitness for
- * a particular purpose. the regents of the university of michigan shall not be
- * liable for any damages, including special, indirect, incidental, or
- * consequential damages, with respect to any claim arising out of or in
- * connection with the use of the software, even if it has been or is hereafter
- * advised of the possibility of such damages.
- */
-
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/queue.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/poll.h>
-#include <sys/mutex.h>
-#include <sys/stat.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/wait.h>
-#include <sys/signalvar.h>
-
-#include <nfs4client/nfs4_dev.h>
-
-#ifdef NFS4DEVVERBOSE
-#define NFS4DEV_DEBUG(X...) printf(X)
-#else
-#define NFS4DEV_DEBUG(X...)
-#endif
-
-#define NFS4DEV_NAME "nfs4"
-#define CDEV_MINOR 1
-
-MALLOC_DEFINE(M_NFS4DEV, "nfs4_dev", "NFS4 device");
-
-struct nfs4dev_upcall {
- /* request msg */
- struct nfs4dev_msg up_reqmsg;
- size_t up_reqmsglen;
-
- /* reply (payload only) */
- caddr_t up_rep;
- size_t * up_replen;
-
- int up_copied; /* non-zero when reply has been copied to
- '*up_rep' */
-
- int up_error; /* non-zero if an error occured */
-
- TAILQ_ENTRY(nfs4dev_upcall) up_entry;
-};
-
-
-#define nfs4dev_upcall_get(MP) (MP) = malloc(sizeof(struct nfs4dev_upcall), M_NFS4DEV, M_WAITOK | M_ZERO)
-
-#define nfs4dev_upcall_put(MP) free((MP), M_NFS4DEV)
-
-static int nfs4dev_nopen = 0;
-static struct thread * nfs4dev_reader = NULL;
-static struct cdev *nfs4device = 0;
-static struct mtx nfs4dev_daemon_mtx;
-
-static int nfs4dev_xid = 0;
-/* queue of pending upcalls */
-TAILQ_HEAD(, nfs4dev_upcall) nfs4dev_newq;
-static struct mtx nfs4dev_newq_mtx;
-
-/* queue of upcalls waiting for replys */
-TAILQ_HEAD(, nfs4dev_upcall) nfs4dev_waitq;
-static struct mtx nfs4dev_waitq_mtx;
-
-/* dev hooks */
-static d_open_t nfs4dev_open;
-static d_close_t nfs4dev_close;
-static d_ioctl_t nfs4dev_ioctl;
-static d_poll_t nfs4dev_poll;
-
-static struct cdevsw nfs4dev_cdevsw = {
-#if (__FreeBSD_version > 502102)
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
-#endif
- .d_open = nfs4dev_open,
- .d_close = nfs4dev_close,
- .d_ioctl = nfs4dev_ioctl,
- .d_poll = nfs4dev_poll,
- .d_name = NFS4DEV_NAME,
-};
-
-static int nfs4dev_reply(caddr_t);
-static int nfs4dev_request(caddr_t);
-
-/* Userland requests a new operation to service */
-static int
-nfs4dev_request(caddr_t addr)
-{
- struct nfs4dev_upcall * u;
- struct nfs4dev_msg * m = (struct nfs4dev_msg *) addr;
-
- mtx_lock(&nfs4dev_newq_mtx);
-
- if (TAILQ_EMPTY(&nfs4dev_newq)) {
- mtx_unlock(&nfs4dev_newq_mtx);
- return EAGAIN;
- }
-
- u = TAILQ_FIRST(&nfs4dev_newq);
- TAILQ_REMOVE(&nfs4dev_newq, u, up_entry);
- mtx_unlock(&nfs4dev_newq_mtx);
-
- bcopy(&u->up_reqmsg, m, sizeof(struct nfs4dev_msg));
-
- mtx_lock(&nfs4dev_waitq_mtx);
- TAILQ_INSERT_TAIL(&nfs4dev_waitq, u, up_entry);
- mtx_unlock(&nfs4dev_waitq_mtx);
-
- return 0;
-}
-
-static int
-nfs4dev_reply(caddr_t addr)
-{
- struct nfs4dev_upcall * u;
- struct nfs4dev_msg * m = (struct nfs4dev_msg *) addr;
- int error;
-
- if (m->msg_vers != NFS4DEV_VERSION) {
- printf("nfs4dev version mismatch\n");
- return EINVAL;
- }
-
- if (m->msg_type > NFS4DEV_MAX_TYPE) {
- NFS4DEV_DEBUG("nfs4dev: unsupported message type\n");
- return EINVAL;
- }
-
- if (m->msg_len < sizeof(*m) - NFS4DEV_MSG_MAX_DATALEN ||
- m->msg_len > NFS4DEV_MSG_MAX_DATALEN) {
- NFS4DEV_DEBUG("bad message length\n");
- return EINVAL;
- }
-
- /* match the reply with a request */
- mtx_lock(&nfs4dev_waitq_mtx);
- TAILQ_FOREACH(u, &nfs4dev_waitq, up_entry) {
- if (m->msg_xid == u->up_reqmsg.msg_xid) {
- if (m->msg_type == u->up_reqmsg.msg_type)
- goto found;
- NFS4DEV_DEBUG("nfs4dev: op type mismatch!\n");
- break;
- }
- }
- mtx_unlock(&nfs4dev_waitq_mtx);
-
- NFS4DEV_DEBUG("nfs4dev msg op: %d xid: %x not found.\n",
- m->msg_type, m->msg_xid);
-
- error = EIO;
- goto bad;
-
-found:
- TAILQ_REMOVE(&nfs4dev_waitq, u, up_entry);
- mtx_unlock(&nfs4dev_waitq_mtx);
-
- if (m->msg_error) {
- error = m->msg_error;
- goto bad;
- }
-
- if (m->msg_len > *u->up_replen) {
- error = EFAULT;
- goto bad;
- }
-
- bcopy(m->msg_data, u->up_rep, m->msg_len);
- *u->up_replen = m->msg_len;
-
- u->up_copied = m->msg_len;
- wakeup(u);
-
- return 0;
-bad:
- if (u) {
- u->up_error = error;
- wakeup(u);
- }
- return error;
-}
-
-void
-nfs4dev_init(void)
-{
- nfs4dev_xid = arc4random();
- TAILQ_INIT(&nfs4dev_newq);
- TAILQ_INIT(&nfs4dev_waitq);
- mtx_init(&nfs4dev_newq_mtx, "nfs4dev newq", NULL, MTX_DEF);
- mtx_init(&nfs4dev_waitq_mtx, "nfs4dev waitq", NULL, MTX_DEF);
-
- mtx_init(&nfs4dev_daemon_mtx, "nfs4dev state", NULL, MTX_DEF);
-
- nfs4device = make_dev(&nfs4dev_cdevsw, CDEV_MINOR, (uid_t)0, (gid_t)0,
- S_IRUSR | S_IWUSR, "nfs4");
-}
-
-void
-nfs4dev_uninit(void)
-{
- struct proc * dead = NULL;
-
- mtx_lock(&nfs4dev_daemon_mtx);
- if (nfs4dev_nopen) {
- if (nfs4dev_reader == NULL) {
- NFS4DEV_DEBUG("nfs4dev uninit(): unregistered reader\n");
- } else {
- dead = nfs4dev_reader->td_proc;
- }
- }
- mtx_unlock(&nfs4dev_daemon_mtx);
-
- if (dead != NULL) {
- NFS4DEV_DEBUG("nfs4dev_uninit(): you forgot to kill attached daemon (pid: %u)\n",
- dead->p_pid);
- PROC_LOCK(dead);
- psignal(dead, SIGTERM);
- PROC_UNLOCK(dead);
- }
-
- /* XXX moot? */
- nfs4dev_purge();
-
- mtx_destroy(&nfs4dev_newq_mtx);
- mtx_destroy(&nfs4dev_waitq_mtx);
- mtx_destroy(&nfs4dev_daemon_mtx);
-
- destroy_dev(nfs4device);
-}
-
-/* device interface functions */
-static int
-nfs4dev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
- if (dev != nfs4device)
- return ENODEV;
-
- mtx_lock(&nfs4dev_daemon_mtx);
- if (nfs4dev_nopen) {
- mtx_unlock(&nfs4dev_daemon_mtx);
- return EBUSY;
- }
-
- nfs4dev_nopen++;
- nfs4dev_reader = curthread;
- mtx_unlock(&nfs4dev_daemon_mtx);
-
- return (0);
-}
-
-static int
-nfs4dev_close(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
- struct nfs4dev_upcall * u;
-
- if (dev != nfs4device)
- return ENODEV;
-
- mtx_lock(&nfs4dev_daemon_mtx);
- if (!nfs4dev_nopen) {
- mtx_unlock(&nfs4dev_daemon_mtx);
- return ENOENT;
- }
-
- nfs4dev_nopen--;
- nfs4dev_reader = NULL;
- mtx_unlock(&nfs4dev_daemon_mtx);
-
- mtx_lock(&nfs4dev_waitq_mtx);
-
- while (!TAILQ_EMPTY(&nfs4dev_waitq)) {
- u = TAILQ_FIRST(&nfs4dev_waitq);
- TAILQ_REMOVE(&nfs4dev_waitq, u, up_entry);
- u->up_error = EINTR;
- wakeup(u);
- }
-
- mtx_unlock(&nfs4dev_waitq_mtx);
-
- return 0;
-}
-
-static int
-nfs4dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
-{
- int error;
-
- if (dev != nfs4device)
- return ENODEV;
-
- if (data == NULL)
- return EFAULT;
-
- if (nfs4dev_reader != curthread)
- nfs4dev_reader = curthread;
-
- switch (cmd) {
- case NFS4DEVIOCGET:
- error = nfs4dev_request(data);
- break;
- case NFS4DEVIOCPUT:
- error = nfs4dev_reply(data);
- break;
- default:
- NFS4DEV_DEBUG("nfs4dev_ioctl: unkown ioctl cmd %d\n", (int)cmd);
- error = EOPNOTSUPP;
- break;
- }
-
- return error;
-}
-
-static int
-nfs4dev_poll(struct cdev *dev, int events, struct thread *td)
-{
- int revents;
-
- if (dev != nfs4device)
- return EINVAL;
-
- mtx_lock(&nfs4dev_daemon_mtx);
- if (nfs4dev_nopen == 0) {
- mtx_unlock(&nfs4dev_daemon_mtx);
- return 0;
- }
- mtx_unlock(&nfs4dev_daemon_mtx);
-
- revents = 0;
-
- /* check readable data */
- mtx_lock(&nfs4dev_newq_mtx);
- if (!TAILQ_EMPTY(&nfs4dev_newq))
- revents |= POLLIN;
- mtx_unlock(&nfs4dev_newq_mtx);
-
- mtx_lock(&nfs4dev_waitq_mtx);
- if (!TAILQ_EMPTY(&nfs4dev_waitq))
- revents |= POLLOUT;
- mtx_unlock(&nfs4dev_waitq_mtx);
-
- return revents;
-}
-
-int
-nfs4dev_call(uint32_t type, caddr_t req_data, size_t req_len, caddr_t rep_data, size_t * rep_lenp)
-{
- struct nfs4dev_upcall * u;
- int error = 0;
- unsigned int xtmp;
-
- mtx_lock(&nfs4dev_daemon_mtx);
- if (nfs4dev_nopen == 0) {
- mtx_unlock(&nfs4dev_daemon_mtx);
- return EINVAL;
- }
- mtx_unlock(&nfs4dev_daemon_mtx);
-
- if (type > NFS4DEV_MAX_TYPE)
- return EOPNOTSUPP;
-
- NFS4DEV_DEBUG("upcall %d/%d:%d\n", type, req_len, *rep_lenp);
-
- nfs4dev_upcall_get(u);
-
- u->up_error = 0;
- u->up_rep = rep_data;
- u->up_replen = rep_lenp;
- u->up_copied = 0;
-
- u->up_reqmsg.msg_vers = NFS4DEV_VERSION;
- /* XXX efficient copying */
- bcopy(req_data, u->up_reqmsg.msg_data, req_len);
- u->up_reqmsg.msg_len = req_len;
-
- mtx_lock(&nfs4dev_newq_mtx);
-
- /* get new XID */
- while ((xtmp = arc4random() % 256) == 0);
- nfs4dev_xid += xtmp;
- u->up_reqmsg.msg_xid = nfs4dev_xid;
-
- TAILQ_INSERT_TAIL(&nfs4dev_newq, u, up_entry);
- mtx_unlock(&nfs4dev_newq_mtx);
-
-
- NFS4DEV_DEBUG("nfs4dev op: %d xid: %x sleeping\n", u->up_reqmsg.msg_type, u->up_reqmsg.msg_xid);
-
- do {
- tsleep(u, PLOCK, "nfs4dev", 0);
- } while (u->up_copied == 0 && u->up_error == 0);
-
- /* upcall now removed from the queue */
-
- NFS4DEV_DEBUG("nfs4dev prog: %d xid: %x continues...\n",
- u->up_reqmsg.msg_type, u->up_reqmsg.msg_xid);
-
- if (u->up_error) {
- error = u->up_error;
- NFS4DEV_DEBUG("nfs4dev prog: %d xid: %x error: %d\n",
- u->up_reqmsg.msg_type, u->up_reqmsg.msg_xid, u->up_error);
- goto out;
- }
-
-out:
- nfs4dev_upcall_put(u);
- return error;
-}
-
-void
-nfs4dev_purge(void)
-{
- struct nfs4dev_upcall * u;
-
- mtx_lock(&nfs4dev_newq_mtx);
- while (!TAILQ_EMPTY(&nfs4dev_newq)) {
- u = TAILQ_FIRST(&nfs4dev_newq);
- TAILQ_REMOVE(&nfs4dev_newq, u, up_entry);
- u->up_error = EINTR;
- wakeup(u);
- }
- mtx_unlock(&nfs4dev_newq_mtx);
-
- mtx_lock(&nfs4dev_waitq_mtx);
- while (!TAILQ_EMPTY(&nfs4dev_waitq)) {
- u = TAILQ_FIRST(&nfs4dev_waitq);
- TAILQ_REMOVE(&nfs4dev_waitq, u, up_entry);
- u->up_error = EINTR;
- wakeup(u);
- }
- mtx_unlock(&nfs4dev_waitq_mtx);
-}
OpenPOWER on IntegriCloud