diff options
48 files changed, 19 insertions, 11185 deletions
diff --git a/etc/rc.d/idmapd b/etc/rc.d/idmapd deleted file mode 100755 index 4c90fd4..0000000 --- a/etc/rc.d/idmapd +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# PROVIDE: idmapd -# REQUIRE: rpcbind -# KEYWORD: nojail shutdown - -. /etc/rc.subr - -name="idmapd" - -load_rc_config $name -rcvar="idmapd_enable" -command="${idmapd:-/sbin/${name}}" -eval ${name}_flags=\"${idmapd_flags}\" -run_rc_command "$1" diff --git a/sbin/Makefile b/sbin/Makefile index 649f4a2..8ece390 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -36,7 +36,6 @@ SUBDIR= adjkerntz \ ggate \ growfs \ gvinum \ - idmapd \ ifconfig \ init \ ${_ipf} \ diff --git a/sbin/idmapd/Makefile b/sbin/idmapd/Makefile deleted file mode 100644 index 8206e0d..0000000 --- a/sbin/idmapd/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# @(#)Makefile 8.2 (Berkeley) 3/27/94 -# -# $FreeBSD$ - -PROG= idmapd -MAN= idmapd.8 - -CFLAGS+= -DNFS -I${.CURDIR}/../../sys -WARNS?= 2 - -.include <bsd.prog.mk> diff --git a/sbin/idmapd/idmapd.8 b/sbin/idmapd/idmapd.8 deleted file mode 100644 index 1fb6216..0000000 --- a/sbin/idmapd/idmapd.8 +++ /dev/null @@ -1,63 +0,0 @@ -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd October 15, 2006 -.Dt IDMAPD 8 -.Os -.Sh NAME -.Nm idmapd -.Nd name/UID mapper for NFSv4 -.Sh SYNOPSIS -.Nm -.Op Fl v -.Op Fl d Ar domainname -.Sh DESCRIPTION -The -.Nm -daemon normally runs in the background and services UID/GID-to-name and -name-to-UID/GID mapping -requests from the NFSv4 client kernel threads. -.Pp -The options are: -.Bl -tag -width indent -.It Fl d -Set the domain part of the name string to the specified string. -.It Fl v -Be verbose, and do not run in the background. -.El -.Sh FILES -.Bl -tag -width ".Pa /etc/master.passwd" -compact -.It Pa /etc/pwd.db -The insecure password database file. -.It Pa /etc/spwd.db -The secure password database file. -.It Pa /etc/master.passwd -The current password file. -.It Pa /etc/passwd -A Version 7 format password file. -.El -.Sh SEE ALSO -.Xr getpwnam 3 , -.Xr getpwuid 3 , -.Xr mount_nfs4 8 diff --git a/sbin/idmapd/idmapd.c b/sbin/idmapd/idmapd.c deleted file mode 100644 index fa3a082..0000000 --- a/sbin/idmapd/idmapd.c +++ /dev/null @@ -1,418 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: idmapd.c,v 1.5 2003/11/05 14:58:58 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. - */ - -/* XXX ignores the domain of received names. */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/syscall.h> -#include <sys/errno.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/queue.h> - -#include <nfs4client/nfs4_dev.h> -#include <nfs4client/nfs4_idmap.h> - -#include <stdio.h> -#include <fcntl.h> -#include <assert.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <pwd.h> -#include <grp.h> - -#define DEV_PATH "/dev/nfs4" - -#define DOMAIN "@FreeBSD.org" -#define BADUSER "nobody" -#define BADGROUP "nogroup" -#define BADUID 65534 -#define BADGID 65533 - -struct idmap_e { - struct nfs4dev_msg msg; - TAILQ_ENTRY(idmap_e) next; -}; - -int fd, verbose; -char *domain = DOMAIN; - -TAILQ_HEAD(, idmap_e) upcall_q; - -#define add_idmap_e(E) do { \ - assert(E != NULL); \ - TAILQ_INSERT_TAIL(&upcall_q, E, next); \ -} while(0) - -#define remove_idmap_e(E) do { \ - assert(E != NULL && !TAILQ_EMPTY(&upcall_q)); \ - E = TAILQ_FIRST(&upcall_q); \ - TAILQ_REMOVE(&upcall_q, E, next); \ -} while(0) - -#define get_idmap_e(E) do { \ - if ((E = (struct idmap_e *) malloc(sizeof(struct idmap_e))) == NULL) {\ - fprintf(stderr, "get_idmap_e(): error in malloc\n");\ - } } while(0) - -#define put_idmap_e(E) free(E) - -/* from marius */ -int -validateascii(char *string, u_int32_t len) -{ - int i; - - for (i = 0; i < len; i++) { - if (string[i] == '\0') - break; - if (string[i] & 0x80) - return (-1); - } - - if (string[i] != '\0') - return (-1); - return (i + 1); -} - -char * -idmap_prune_domain(struct idmap_msg * m) -{ - size_t i; - size_t len; - char * ret = NULL; - - if (m == NULL) - return NULL; - - len = m->id_namelen; - - if (validateascii(m->id_name, len) < 0) { - fprintf(stderr, "msg has invalid ascii\n"); - return NULL; - } - - for (i=0; i < len && m->id_name[i] != '@' ; i++); - - ret = (char *)malloc(i+1); - if (ret == NULL) - return NULL; - - bcopy(m->id_name, ret, i); - ret[i] = '\0'; - - return ret; -} - -int -idmap_add_domain(struct idmap_msg * m, char * name) -{ - size_t len, nlen; - - if (m == NULL || name == NULL) - return -1; - - len = strlen(name); - - nlen = len + strlen(domain); - - if (nlen > IDMAP_MAXNAMELEN) - return -1; - - bcopy(name, &m->id_name[0], len); - bcopy(domain, &m->id_name[len], strlen(domain)); - - m->id_name[nlen] = '\0'; - m->id_namelen = nlen; - - return 0; -} - -int -idmap_name(struct idmap_msg * m, char *name) -{ - if (m == NULL || name == NULL || m->id_namelen != 0) - return -1; - - if (idmap_add_domain(m, name)) - return -1; - - return 0; -} - -int -idmap_id(struct idmap_msg * m, ident_t id) -{ - if (m == NULL || m->id_namelen == 0) { - fprintf(stderr, "idmap_id: bad msg\n"); - return -1; - } - - switch(m->id_type) { - case IDMAP_TYPE_UID: - m->id_id.uid = id.uid; - break; - case IDMAP_TYPE_GID: - m->id_id.gid = id.gid; - break; - default: - return -1; - break; - }; - - return 0; -} - -int -idmap_service(struct idmap_e * e) -{ - struct idmap_msg * m; - struct passwd * pwd; - struct group * grp; - ident_t id; - char * name; - - if (e == NULL) { - fprintf(stderr, "bad entry\n"); - return -1; - } - - if (e->msg.msg_vers != NFS4DEV_VERSION) { - fprintf(stderr, "kernel/userland version mismatch! %d/%d\n", - e->msg.msg_vers, NFS4DEV_VERSION); - return -1; - } - - if (e->msg.msg_type != NFS4DEV_TYPE_IDMAP) { - fprintf(stderr, "bad type!\n"); - return -1; - } - - if (e->msg.msg_len != sizeof(struct idmap_msg)) { - fprintf(stderr, "bad message length: %zu/%zu\n", e->msg.msg_len, - sizeof(struct idmap_msg)); - return -1; - } - - if (verbose) - printf("servicing msg xid: %x\n", e->msg.msg_xid); - - - m = (struct idmap_msg *)e->msg.msg_data; - - if (m->id_namelen != 0 && m->id_namelen != strlen(m->id_name)) { - fprintf(stderr, "bad name length in idmap_msg\n"); - return -1; - } - - switch (m->id_type) { - case IDMAP_TYPE_UID: - if (m->id_namelen == 0) { - /* id to name */ - pwd = getpwuid(m->id_id.uid); - - if (pwd == NULL) { - fprintf(stderr, "unknown uid %d!\n", - (uint32_t)m->id_id.uid); - name = BADUSER; - } else - name = pwd->pw_name; - - if (idmap_name(m, name)) - return -1; - - } else { - /* name to id */ - name = idmap_prune_domain(m); - if (name == NULL) - return -1; - - pwd = getpwnam(name); - - if (pwd == NULL) { - fprintf(stderr, "unknown username %s!\n", name); - - id.uid = (uid_t)BADUID; - } else - id.uid = pwd->pw_uid; - - free(name); - - if (idmap_id(m, id)) - return -1; - } - break; - case IDMAP_TYPE_GID: - if (m->id_namelen == 0) { - /* id to name */ - grp = getgrgid(m->id_id.gid); - - if (grp == NULL) { - fprintf(stderr, "unknown gid %d!\n", - (uint32_t)m->id_id.gid); - name = BADGROUP; - } else - name = grp->gr_name; - - if (idmap_name(m, name)) - return -1; - } else { - /* name to id */ - name = idmap_prune_domain(m); - if (name == NULL) - return -1; - - grp = getgrnam(name); - - if (grp == NULL) { - fprintf(stderr, "unknown groupname %s!\n", name); - - id.gid = (gid_t)BADGID; - } else - id.gid = grp->gr_gid; - - free(name); - - if (idmap_id(m, id)) - return -1; - } - break; - default: - fprintf(stderr, "bad idmap type: %d\n", m->id_type); - return -1; - break; - } - - return 0; -} - -int -main(int argc, char ** argv) -{ - int error = 0; - struct idmap_e * entry; - fd_set read_fds, write_fds; - int maxfd; - int ret, ch; - - while ((ch = getopt(argc, argv, "d:v")) != -1) { - switch (ch) { - case 'd': - domain = optarg; - break; - case 'v': - verbose = 1; - break; - default: - fprintf(stderr, "usage: %s [-v] [-d domain]\n", argv[0]); - exit(1); - break; - } - } - - - TAILQ_INIT(&upcall_q); - - fd = open(DEV_PATH, O_RDWR, S_IRUSR | S_IWUSR); - - if (fd < 0) { - perror(DEV_PATH); - exit(1); - } - - if (!verbose) - daemon(0,0); - - maxfd = fd; - for (;;) { - struct timeval timo = {1, 0}; - do { - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - - FD_SET(fd, &read_fds); - FD_SET(fd, &write_fds); - - ret = select(maxfd+1, &read_fds, &write_fds, NULL, &timo); - } while (ret < 0 && errno == EINTR); - - if (ret <= 0) { - if (ret != 0) - perror("select"); - continue; - } - - - if (FD_ISSET(fd, &read_fds)) { - for (;;) { - get_idmap_e(entry); - - error = ioctl(fd, NFS4DEVIOCGET, &entry->msg); - - if (error == -1) { - if (errno != EAGAIN) - perror("get ioctl:"); - put_idmap_e(entry); - break; - } - - switch (entry->msg.msg_type ) { - case NFS4DEV_TYPE_IDMAP: - if (idmap_service(entry)) - entry->msg.msg_error = EIO; - break; - default: - fprintf(stderr, "unknown nfs4dev_msg type\n"); - entry->msg.msg_error = EIO; - break; - } - - add_idmap_e(entry); - } - } - - if (FD_ISSET(fd, &write_fds)) { - while (!TAILQ_EMPTY(&upcall_q)) { - remove_idmap_e(entry); - - error = ioctl(fd, NFS4DEVIOCPUT, &entry->msg); - - if (error == -1) { - if (errno != EAGAIN) - perror("put ioctl"); - break; - } - put_idmap_e(entry); - } - } - } - - /* never reached */ - exit(1); -} diff --git a/sbin/mount_nfs/Makefile b/sbin/mount_nfs/Makefile index 4f7efea..960f97c 100644 --- a/sbin/mount_nfs/Makefile +++ b/sbin/mount_nfs/Makefile @@ -5,15 +5,13 @@ PROG= mount_nfs SRCS= mount_nfs.c getmntopts.c mounttab.c MAN= mount_nfs.8 -MLINKS= mount_nfs.8 mount_nfs4.8 +MLINKS= mount_nfs.8 MOUNT= ${.CURDIR}/../mount UMNTALL= ${.CURDIR}/../../usr.sbin/rpc.umntall CFLAGS+= -DNFS -I${MOUNT} -I${UMNTALL} WARNS?= 3 -LINKS= ${BINDIR}/mount_nfs ${BINDIR}/mount_nfs4 - .PATH: ${MOUNT} ${UMNTALL} .include <bsd.prog.mk> diff --git a/sbin/mount_nfs/mount_nfs.8 b/sbin/mount_nfs/mount_nfs.8 index c75a30d..78a3b19 100644 --- a/sbin/mount_nfs/mount_nfs.8 +++ b/sbin/mount_nfs/mount_nfs.8 @@ -36,7 +36,7 @@ .Nd mount NFS file systems .Sh SYNOPSIS .Nm -.Op Fl 234bcdiLlNPsTU +.Op Fl 23bcdiLlNPsTU .Op Fl a Ar maxreadahead .Op Fl D Ar deadthresh .Op Fl g Ar maxgroups @@ -157,8 +157,6 @@ then version 2). Note that NFS version 2 has a file size limit of 2 gigabytes. .It Cm nfsv3 Use the NFS Version 3 protocol. -.It Cm nfsv4 -Use the NFS Version 4 protocol. .It Cm noconn For UDP mount points, do not do a .Xr connect 2 . @@ -303,9 +301,6 @@ Same as .It Fl 3 Same as .Fl o Cm nfsv3 -.It Fl 4 -Same as -.Fl o Cm nfsv4 .It Fl D Same as .Fl o Cm deadthresh diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c index a2f5e89..102c51d 100644 --- a/sbin/mount_nfs/mount_nfs.c +++ b/sbin/mount_nfs/mount_nfs.c @@ -1,28 +1,4 @@ /* - * 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. - */ - -/* * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -140,7 +116,6 @@ enum mountmode { ANY, V2, V3, - V4 } mountmode = ANY; /* Return codes for nfs_tryproto. */ @@ -155,7 +130,6 @@ int fallback_mount(struct iovec *iov, int iovlen, int mntflags); int sec_name_to_num(char *sec); char *sec_num_to_name(int num); int getnfsargs(char *, struct iovec **iov, int *iovlen); -int getnfs4args(char *, struct iovec **iov, int *iovlen); /* void set_rpc_maxgrouplist(int); */ struct netconfig *getnetconf_cached(const char *netid); const char *netidbytype(int af, int sotype); @@ -164,8 +138,6 @@ int xdr_dir(XDR *, char *); int xdr_fh(XDR *, struct nfhret *); enum tryret nfs_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr, struct iovec **iov, int *iovlen); -enum tryret nfs4_tryproto(struct addrinfo *ai, char *hostp, char *spec, - char **errstr); enum tryret returncode(enum clnt_stat stat, struct rpc_err *rpcerr); extern int getosreldate(void); @@ -190,15 +162,8 @@ main(int argc, char *argv[]) ++fstype; - if (strcmp(fstype, "nfs4") == 0) { - nfsproto = IPPROTO_TCP; - portspec = "2049"; - build_iovec(&iov, &iovlen, "tcp", NULL, 0); - mountmode = V4; - } - while ((c = getopt(argc, argv, - "234a:bcdD:g:I:iLlNo:PR:r:sTt:w:x:U")) != -1) + "23a:bcdD:g:I:iLlNo:PR:r:sTt:w:x:U")) != -1) switch (c) { case '2': mountmode = V2; @@ -206,10 +171,6 @@ main(int argc, char *argv[]) case '3': mountmode = V3; break; - case '4': - mountmode = V4; - fstype = "nfs4"; - break; case 'a': printf("-a deprecated, use -o readhead=<value>\n"); build_iovec(&iov, &iovlen, "readahead", optarg, (size_t)-1); @@ -301,10 +262,6 @@ main(int argc, char *argv[]) mountmode = V2; } else if (strcmp(opt, "nfsv3") == 0) { mountmode = V3; - } else if (strcmp(opt, "nfsv4") == 0) { - pass_flag_to_nmount=0; - mountmode = V4; - fstype = "nfs4"; } else if (strcmp(opt, "port") == 0) { pass_flag_to_nmount=0; asprintf(&portspec, "%d", @@ -406,13 +363,8 @@ main(int argc, char *argv[]) /* The default is to keep retrying forever. */ retrycnt = 0; - if (mountmode == V4) { - if (!getnfs4args(spec, &iov, &iovlen)) - exit(1); - } else { - if (!getnfsargs(spec, &iov, &iovlen)) - exit(1); - } + if (!getnfsargs(spec, &iov, &iovlen)) + exit(1); /* resolve the mountpoint with realpath(3) */ (void)checkpath(name, mntpath); @@ -814,129 +766,6 @@ getnfsargs(char *spec, struct iovec **iov, int *iovlen) return (1); } - -int -getnfs4args(char *spec, struct iovec **iov, int *iovlen) -{ - struct addrinfo hints, *ai_nfs, *ai; - enum tryret ret; - int ecode, speclen, remoteerr, sotype; - char *hostp, *delimp, *errstr; - size_t len; - static char nam[MNAMELEN + 1]; - - if (nfsproto == IPPROTO_TCP) - sotype = SOCK_STREAM; - else if (nfsproto == IPPROTO_UDP) - sotype = SOCK_DGRAM; - - - if ((delimp = strrchr(spec, ':')) != NULL) { - hostp = spec; - spec = delimp + 1; - } else if ((delimp = strrchr(spec, '@')) != NULL) { - warnx("path@server syntax is deprecated, use server:path"); - hostp = delimp + 1; - } else { - warnx("no <host>:<dirpath> nfs-name"); - return (0); - } - *delimp = '\0'; - - /* - * If there has been a trailing slash at mounttime it seems - * that some mountd implementations fail to remove the mount - * entries from their mountlist while unmounting. - */ - for (speclen = strlen(spec); - speclen > 1 && spec[speclen - 1] == '/'; - speclen--) - spec[speclen - 1] = '\0'; - if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) { - warnx("%s:%s: %s", hostp, spec, strerror(ENAMETOOLONG)); - return (0); - } - /* Make both '@' and ':' notations equal */ - if (*hostp != '\0') { - len = strlen(hostp); - memmove(nam, hostp, len); - nam[len] = ':'; - memmove(nam + len + 1, spec, speclen); - nam[len + speclen + 1] = '\0'; - } - - /* - * Handle an internet host address. - */ - memset(&hints, 0, sizeof hints); - hints.ai_flags = AI_NUMERICHOST; - hints.ai_socktype = sotype; - if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) { - hints.ai_flags = 0; - if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs)) - != 0) { - if (portspec == NULL) - errx(1, "%s: %s", hostp, gai_strerror(ecode)); - else - errx(1, "%s:%s: %s", hostp, portspec, - gai_strerror(ecode)); - return (0); - } - } - - ret = TRYRET_LOCALERR; - for (;;) { - /* - * Try each entry returned by getaddrinfo(). Note the - * occurence of remote errors by setting `remoteerr'. - */ - remoteerr = 0; - for (ai = ai_nfs; ai != NULL; ai = ai->ai_next) { - if ((ai->ai_family == AF_INET6) && - (opflags & OF_NOINET6)) - continue; - if ((ai->ai_family == AF_INET) && - (opflags & OF_NOINET4)) - continue; - ret = nfs4_tryproto(ai, hostp, spec, &errstr); - if (ret == TRYRET_SUCCESS) - break; - if (ret != TRYRET_LOCALERR) - remoteerr = 1; - if ((opflags & ISBGRND) == 0) - fprintf(stderr, "%s\n", errstr); - } - if (ret == TRYRET_SUCCESS) - break; - - /* Exit if all errors were local. */ - if (!remoteerr) - exit(1); - - /* - * If retrycnt == 0, we are to keep retrying forever. - * Otherwise decrement it, and exit if it hits zero. - */ - if (retrycnt != 0 && --retrycnt == 0) - exit(1); - - if ((opflags & (BGRND | ISBGRND)) == BGRND) { - warnx("Cannot immediately mount %s:%s, backgrounding", - hostp, spec); - opflags |= ISBGRND; - if (daemon(0, 0) != 0) - err(1, "daemon"); - } - sleep(60); - } - freeaddrinfo(ai_nfs); - build_iovec(iov, iovlen, "hostname", nam, (size_t)-1); - /* Add mounted file system to PATH_MOUNTTAB */ - if (!add_mtab(hostp, spec)) - warnx("can't update %s for %s:%s", PATH_MOUNTTAB, hostp, spec); - return (1); -} - /* * Try to set up the NFS arguments according to the address * family, protocol (and possibly port) specified in `ai'. @@ -1142,82 +971,6 @@ tryagain: return (TRYRET_SUCCESS); } - -/* - * Try to set up the NFS arguments according to the address - * family, protocol (and possibly port) specified in `ai'. - * - * Returns TRYRET_SUCCESS if successful, or: - * TRYRET_TIMEOUT The server did not respond. - * TRYRET_REMOTEERR The server reported an error. - * TRYRET_LOCALERR Local failure. - * - * In all error cases, *errstr will be set to a statically-allocated string - * describing the error. - */ -enum tryret -nfs4_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr) -{ - static char errbuf[256]; - struct sockaddr_storage nfs_ss; - struct netbuf nfs_nb; - struct netconfig *nconf; - const char *netid; - int nfsvers, sotype; - - errbuf[0] = '\0'; - *errstr = errbuf; - - if (nfsproto == IPPROTO_TCP) - sotype = SOCK_STREAM; - else if (nfsproto == IPPROTO_UDP) - sotype = SOCK_DGRAM; - - if ((netid = netidbytype(ai->ai_family, sotype)) == NULL) { - snprintf(errbuf, sizeof errbuf, - "af %d sotype %d not supported", ai->ai_family, sotype); - return (TRYRET_LOCALERR); - } - if ((nconf = getnetconf_cached(netid)) == NULL) { - snprintf(errbuf, sizeof errbuf, "%s: %s", netid, nc_sperror()); - return (TRYRET_LOCALERR); - } - - nfsvers = 4; - - if (portspec != NULL && atoi(portspec) != 0) { - /* `ai' contains the complete nfsd sockaddr. */ - nfs_nb.buf = ai->ai_addr; - nfs_nb.len = nfs_nb.maxlen = ai->ai_addrlen; - } else { - /* Ask the remote rpcbind. */ - nfs_nb.buf = &nfs_ss; - nfs_nb.len = nfs_nb.maxlen = sizeof nfs_ss; - - if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, &nfs_nb, - hostp)) { - snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", - netid, hostp, spec, - clnt_spcreateerror("RPCPROG_NFS")); - return (returncode(rpc_createerr.cf_stat, - &rpc_createerr.cf_error)); - } - } - - /* - * Store the filehandle and server address in nfsargsp, making - * sure to copy any locally allocated structures. - */ - addrlen = nfs_nb.len; - addr = malloc(addrlen); - - if (addr == NULL) - err(1, "malloc"); - bcopy(nfs_nb.buf, addr, addrlen); - - return (TRYRET_SUCCESS); -} - /* * Catagorise a RPC return status and error into an `enum tryret' * return code. @@ -1361,7 +1114,7 @@ void usage() { (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", -"usage: mount_nfs [-234bcdiLlNPsTU] [-a maxreadahead] [-D deadthresh]", +"usage: mount_nfs [-23bcdiLlNPsTU] [-a maxreadahead] [-D deadthresh]", " [-g maxgroups] [-I readdirsize] [-o options] [-R retrycnt]", " [-r readsize] [-t timeout] [-w writesize] [-x retrans]", " rhost:path node"); diff --git a/sys/Makefile b/sys/Makefile index f41da81..cb5fd13 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -11,7 +11,7 @@ SUBDIR= boot CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \ geom gnu isa kern libkern modules net net80211 netatalk \ netgraph netinet netinet6 netipsec netipx netnatm netncp \ - netsmb nfs nfs4client nfsclient nfsserver nlm opencrypto \ + netsmb nfs nfsclient nfsserver nlm opencrypto \ pci rpc security sys ufs vm xdr ${CSCOPE_ARCHDIR} .if defined(ALL_ARCH) CSCOPE_ARCHDIR ?= amd64 arm i386 ia64 mips pc98 powerpc sparc64 sun4v diff --git a/sys/conf/files b/sys/conf/files index 33b4c6f..a3bd42f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2450,14 +2450,6 @@ netsmb/smb_subr.c optional netsmb netsmb/smb_trantcp.c optional netsmb netsmb/smb_usr.c optional netsmb nfs/nfs_common.c optional nfsclient | nfsserver -nfs4client/nfs4_dev.c optional nfsclient -nfs4client/nfs4_idmap.c optional nfsclient -nfs4client/nfs4_socket.c optional nfsclient -nfs4client/nfs4_subs.c optional nfsclient -nfs4client/nfs4_vfs_subs.c optional nfsclient -nfs4client/nfs4_vfsops.c optional nfsclient -nfs4client/nfs4_vn_subs.c optional nfsclient -nfs4client/nfs4_vnops.c optional nfsclient nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient @@ -2519,7 +2511,6 @@ rpc/rpc_generic.c optional krpc | nfslockd | nfsclient | nfsserver rpc/rpc_prot.c optional krpc | nfslockd | nfsclient | nfsserver rpc/rpcb_clnt.c optional krpc | nfslockd | nfsclient | nfsserver rpc/rpcb_prot.c optional krpc | nfslockd | nfsclient | nfsserver -rpc/rpcclnt.c optional nfsclient rpc/svc.c optional krpc | nfslockd | nfsserver rpc/svc_auth.c optional krpc | nfslockd | nfsserver rpc/svc_auth_unix.c optional krpc | nfslockd | nfsserver diff --git a/sys/conf/options b/sys/conf/options index 758190f..cc06bd7 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -226,7 +226,6 @@ KGSSAPI_DEBUG opt_kgssapi.h # filesystems will be enabled - but look below. NFSCLIENT opt_nfs.h NFSSERVER opt_nfs.h -NFS4CLIENT opt_nfs.h # Use this option to compile both NFS client and server using the # legacy RPC implementation instead of the newer KRPC system (which diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index 6e27e4d..4b37802 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <sys/vnode.h> #include <rpc/rpc.h> -#include <rpc/rpcclnt.h> #include <kgssapi/krb5/kcrypto.h> diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h index 5be6587..d452927 100644 --- a/sys/fs/nfs/nfsport.h +++ b/sys/fs/nfs/nfsport.h @@ -98,7 +98,6 @@ #include <crypto/des/des.h> #include <sys/md5.h> #include <rpc/rpc.h> -#include <rpc/rpcclnt.h> #include <rpc/rpcsec_gss.h> /* diff --git a/sys/modules/nfs4client/Makefile b/sys/modules/nfs4client/Makefile deleted file mode 100644 index bdc272f..0000000 --- a/sys/modules/nfs4client/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../nfsclient ${.CURDIR}/../../nfs4client \ - ${.CURDIR}/../../nfs ${.CURDIR}/../../rpc -KMOD= nfs4client -SRCS= vnode_if.h \ - nfs_bio.c nfs_lock.c nfs_node.c nfs_nfsiod.c \ - nfs_common.c \ - opt_inet.h opt_nfs.h opt_bootp.h opt_nfsroot.h \ - nfs4_dev.c nfs4_idmap.c nfs4_socket.c nfs4_subs.c \ - nfs4_vfs_subs.c nfs4_vfsops.c nfs4_vn_subs.c nfs4_vnops.c -SRCS+= opt_inet6.h - -# USE THE RPCCLNT: -CFLAGS+= -DRPCCLNT_DEBUG -SRCS+= rpcclnt.c - -# USE THE NEW IDMAPPER -CFLAGS+= -DUSE_NEW_IDMAPPER - -.if !defined(KERNBUILDDIR) -NFS_INET?= 1 # 0/1 - requires INET to be configured in kernel -NFS_INET6?= 1 # 0/1 - requires INET6 to be configured in kernel - -.if ${NFS_INET} > 0 -opt_inet.h: - echo "#define INET 1" > ${.TARGET} -.endif - -.if ${NFS_INET6} > 0 -opt_inet6.h: - echo "#define INET6 1" > ${.TARGET} -.endif -.endif - -.include <bsd.kmod.mk> diff --git a/sys/modules/nfsclient/Makefile b/sys/modules/nfsclient/Makefile index a420502..af02f6a 100644 --- a/sys/modules/nfsclient/Makefile +++ b/sys/modules/nfsclient/Makefile @@ -1,24 +1,14 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../nfsclient ${.CURDIR}/../../nfs4client \ - ${.CURDIR}/../../nfs ${.CURDIR}/../../rpc +.PATH: ${.CURDIR}/../../nfsclient ${.CURDIR}/../../nfs ${.CURDIR}/../../rpc KMOD= nfsclient SRCS= vnode_if.h \ nfs_bio.c nfs_lock.c nfs_node.c nfs_socket.c nfs_subs.c nfs_nfsiod.c \ nfs_vfsops.c nfs_vnops.c nfs_common.c nfs_krpc.c \ opt_inet.h opt_nfs.h opt_bootp.h opt_nfsroot.h -SRCS+= nfs4_dev.c nfs4_idmap.c nfs4_socket.c nfs4_subs.c \ - nfs4_vfs_subs.c nfs4_vfsops.c nfs4_vn_subs.c nfs4_vnops.c SRCS+= opt_inet6.h opt_kdtrace.h opt_kgssapi.h opt_route.h -# USE THE RPCCLNT: -CFLAGS+= -DRPCCLNT_DEBUG -SRCS+= rpcclnt.c - -# USE THE NEW IDMAPPER -CFLAGS+= -DUSE_NEW_IDMAPPER - .if !defined(KERNBUILDDIR) NFS_INET?= 1 # 0/1 - requires INET to be configured in kernel NFS_INET6?= 1 # 0/1 - requires INET6 to be configured in kernel diff --git a/sys/nfs4client/nfs4.h b/sys/nfs4client/nfs4.h deleted file mode 100644 index 4bcc6a7..0000000 --- a/sys/nfs4client/nfs4.h +++ /dev/null @@ -1,260 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4.h,v 1.25 2003/11/05 14:58:58 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. - */ - -#ifndef _NFS4CLIENT_NFS4_H -#define _NFS4CLIENT_NFS4_H - -#define NFS4_USE_RPCCLNT - -#define NFS4_MINOR_VERSION 0 -#define NFS_PORT 2049 -#define NFS4_DEF_FILE_IO_BUFFER_SIZE 4096 -#define NFS4_MAX_FILE_IO_BUFFER_SIZE 32768 -#define NFS4_DEF_MAXFILESIZE 0xffffffff -#define NFS4_SUPER_MAGIC 0xF00BA4 - -#define NFS4FS_SILLY_RENAME 1 -#define NFS4FS_STRICT_LOCKING 1 -#define NFS4FS_RETRY_OLD_STATEID 1 -#define NFS4FS_MIN_LEASE (1 * hz) -#define NFS4FS_DEFAULT_LEASE (30 * hz) -#define NFS4FS_MAX_LEASE (120 * hz) -#define NFS4FS_RETRY_MIN_DELAY (hz >> 4) -#define NFS4FS_RETRY_MAX_DELAY (hz << 3) -#define NFS4FS_SEMAPHORE_DELAY (hz >> 4) -#define NFS4FS_GRACE_DELAY (hz * 5) -#define NFS4FS_OLD_STATEID_DELAY (hz >> 3) -#define NFS4FS_OP_MAX 10 - - -#define NFS4_BUFSIZE 8192 -#define NFS4FS_MAX_IOV 10 -#define NFS4_SETCLIENTID_MAXTRIES 5 -#define NFS4_READDIR_MAXTRIES 5 -#define NFS4_MAXIO 4 -#define NFS4_MAX_REQUEST_SOFT 192 -#define NFS4_MAX_REQUEST_HARD 256 -#define NFS4_MAXCOMMIT 64 -#define NFS4_READ_DELAY (2 * HZ) -#define NFS4_WRITEBACK_DELAY (5 * HZ) -#define NFS4_WRITEBACK_LOCKDELAY (60 * HZ) -#define NFS4_COMMIT_DELAY (5 * HZ) -#define RPC_SLACK_SPACE 512 - - -struct nfs4_compound { - char *tag; - - int req_nops; - uint32_t *req_nopsp; - uint32_t *req_seqidp; - uint32_t *req_stateidp[NFS4_MAXIO]; - uint32_t req_nstateid; - - u_int seqidused; - - int rep_status; - int rep_nops; - - struct nfs4_fctx *fcp; - - struct vnode *curvp; - struct vnode *savevp; - - struct nfsmount *nmp; -}; - -struct nfs4_fdata { - struct nfsnode *fd_n; - pid_t fd_pid; -}; - -struct nfs4_oparg_putfh { - /* filled in by caller */ -/* struct dentry *dentry;*/ - - /* filled in by setup routine */ -/* nfs_opnum4 op;*/ - uint32_t fh_len; - nfsfh_t fh_val; - int nlookups; -}; - -struct nfs4_oparg_getattr { - struct vnode *vp; - nfsv4bitmap *bm; - struct nfsv4_fattr fa; -}; - -struct nfs4_oparg_getfh { - uint32_t fh_len; - nfsfh_t fh_val; - struct vnode *vp; -}; - -struct nfs4_oparg_lookup { - const char *name; - uint32_t namelen; - struct vnode *vp; -}; - -struct nfs4_oparg_setclientid { - struct nfsmount *np; - uint32_t namelen; - char *name; - char *cb_netid; - uint32_t cb_netidlen; - char *cb_univaddr; - uint32_t cb_univaddrlen; - uint32_t cb_prog; - - uint64_t clientid; - u_char verf[NFSX_V4VERF]; -}; - -struct nfs4_oparg_access { - uint32_t mode; - uint32_t rmode; - uint32_t supported; -}; - -struct nfs4_oparg_open { - uint32_t flags; - uint32_t rflags; - - nfsv4cltype ctype; - struct vattr *vap; - struct componentname *cnp; - - struct nfs4_fctx *fcp; - - char stateid[NFSX_V4STATEID]; -}; - -struct nfs4_oparg_read { - uint64_t off; - uint32_t maxcnt; - uint32_t eof; - uint32_t retlen; - struct uio *uiop; - struct nfs4_fctx *fcp; -}; - -struct nfs4_oparg_write { - uint64_t off; - uint32_t stable; - uint32_t cnt; - uint32_t retlen; - uint32_t committed; - struct uio *uiop; - u_char wverf[NFSX_V4VERF]; - struct nfs4_fctx *fcp; -}; - -struct nfs4_oparg_commit { - uint32_t len; - off_t start; - - u_char verf[NFSX_V4VERF]; -}; - -struct nfs4_oparg_readdir { - uint32_t cnt; - nfsv4bitmap *bm; - uint64_t cookie; - u_char verf[NFSX_V4VERF]; -}; - -struct nfs4_oparg_create { - nfstype type; - char *linktext; - char *name; - uint32_t namelen; - struct vattr *vap; -}; - -struct nfs4_oparg_rename { - const char *fname; - uint32_t fnamelen; - const char *tname; - uint32_t tnamelen; -}; - -struct nfs4_oparg_link { - const char *name; - uint32_t namelen; -}; - -/* - * Lockowner - */ -struct nfs4_lowner { - uint32_t lo_cnt; - uint32_t lo_seqid; - uint32_t lo_id; -}; - -#define NFS4_SEQIDMUTATINGERROR(err) \ -(((err) != NFSERR_STALE_CLIENTID) && \ - ((err) != NFSERR_BAD_SEQID) && \ - ((err) != NFSERR_STALE_STATEID) && \ - ((err) != NFSERR_BAD_STATEID)) - -/* Standard bitmasks */ -extern nfsv4bitmap nfsv4_fsinfobm; -extern nfsv4bitmap nfsv4_fsattrbm; -extern nfsv4bitmap nfsv4_getattrbm; -extern nfsv4bitmap nfsv4_readdirbm; - -vfs_init_t nfs4_init; -vfs_uninit_t nfs4_uninit; - -uint32_t nfs_v4fileid4_to_fileid(uint64_t); - -int nfs4_readrpc(struct vnode *, struct uio *, struct ucred *); -int nfs4_writerpc(struct vnode *, struct uio *, struct ucred *, int *, - int *); -int nfs4_commit(struct vnode *vp, u_quad_t offset, int cnt, - struct ucred *cred, struct thread *td); -int nfs4_readdirrpc(struct vnode *, struct uio *, struct ucred *); -int nfs4_readlinkrpc(struct vnode *, struct uio *, struct ucred *); -int nfs4_sigintr(struct nfsmount *, struct nfsreq *, struct thread *); -int nfs4_writebp(struct buf *, int, struct thread *); -int nfs4_request(struct vnode *, struct mbuf *, int, struct thread *, - struct ucred *, struct mbuf **, struct mbuf **, caddr_t *); -int nfs4_request_mnt(struct nfsmount *, struct mbuf *, int, struct thread *, - struct ucred *, struct mbuf **, struct mbuf **, caddr_t *); -int nfs4_connect(struct nfsmount *); -void nfs4_disconnect(struct nfsmount *); -void nfs4_safedisconnect(struct nfsmount *); -int nfs4_nmcancelreqs(struct nfsmount *); - -void nfs_v4initcompound(struct nfs4_compound *); -int nfs_v4postop(struct nfs4_compound *, int); -int nfs_v4handlestatus(int, struct nfs4_compound *); - -#endif /* _NFS4CLIENT_NFS4_H */ 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); -} diff --git a/sys/nfs4client/nfs4_dev.h b/sys/nfs4client/nfs4_dev.h deleted file mode 100644 index be14ce2..0000000 --- a/sys/nfs4client/nfs4_dev.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_dev.h,v 1.3 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. - */ - -#ifndef _NFS3_DEV_H_ -#define _NFS4_DEV_H_ - -#include <sys/ioccom.h> - - -/* type of upcall */ -#define NFS4DEV_TYPE_IDMAP 0 -#define NFS4DEV_TYPE_GSS 1 -#define NFS4DEV_MAX_TYPE 1 - -struct nfs4dev_msg { - unsigned int msg_vers; - unsigned int msg_type; - unsigned int msg_xid; - unsigned int msg_error; - - #define NFS4DEV_MSG_MAX_DATALEN 350 - size_t msg_len; - uint8_t msg_data[NFS4DEV_MSG_MAX_DATALEN]; -}; - -#define NFS4DEV_VERSION (0x3 << 16 | (int) sizeof(struct nfs4dev_msg)) - -/* ioctl commands */ -#define NFS4DEVIOCGET _IOR('A', 0x200, struct nfs4dev_msg) -#define NFS4DEVIOCPUT _IOW('A', 0x201, struct nfs4dev_msg) - -#ifdef _KERNEL -int nfs4dev_call(uint32_t type, caddr_t req_data, size_t req_len, caddr_t rep_datap, size_t * rep_lenp); - -void nfs4dev_purge(void); - -void nfs4dev_init(void); -void nfs4dev_uninit(void); -#endif - -#endif /* _NFS4_DEV_H_ */ diff --git a/sys/nfs4client/nfs4_idmap.c b/sys/nfs4client/nfs4_idmap.c deleted file mode 100644 index 5a02b47..0000000 --- a/sys/nfs4client/nfs4_idmap.c +++ /dev/null @@ -1,509 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_idmap.c,v 1.4 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. - */ - -/* TODO: - * o validate ascii - * */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/lock.h> -#include <sys/lockmgr.h> -#include <sys/fnv_hash.h> -#include <sys/proc.h> -#include <sys/syscall.h> -#include <sys/sysent.h> -#include <sys/libkern.h> - -#include <rpc/rpcclnt.h> - -#include <nfs4client/nfs4_dev.h> -#include <nfs4client/nfs4_idmap.h> - - -#ifdef IDMAPVERBOSE -#define IDMAP_DEBUG(...) printf(__VA_ARGS__); -#else -#define IDMAP_DEBUG(...) -#endif - -#define IDMAP_HASH_SIZE 37 - -MALLOC_DEFINE(M_IDMAP, "idmap", "idmap"); - -#define idmap_entry_get(ID) (ID) = malloc(sizeof(struct idmap_entry), M_IDMAP, M_WAITOK | M_ZERO) -#define idmap_entry_put(ID) free((ID), M_IDMAP) - - - -struct idmap_entry { - struct idmap_msg id_info; - - TAILQ_ENTRY(idmap_entry) id_entry_id; - TAILQ_ENTRY(idmap_entry) id_entry_name; -}; - -struct idmap_hash { - TAILQ_HEAD(, idmap_entry) hash_name[IDMAP_HASH_SIZE]; - TAILQ_HEAD(, idmap_entry) hash_id[IDMAP_HASH_SIZE]; - - struct lock hash_lock; -}; - -#define IDMAP_RLOCK(lock) lockmgr(lock, LK_SHARED, NULL) -#define IDMAP_WLOCK(lock) lockmgr(lock, LK_EXCLUSIVE, NULL) -#define IDMAP_UNLOCK(lock) lockmgr(lock, LK_RELEASE, NULL) - - -static struct idmap_hash idmap_uid_hash; -static struct idmap_hash idmap_gid_hash; - -static struct idmap_entry * idmap_name_lookup(uint32_t, char *); -static struct idmap_entry * idmap_id_lookup(uint32_t, ident_t); -static int idmap_upcall_name(uint32_t, char *, struct idmap_entry **); -static int idmap_upcall_id(uint32_t , ident_t, struct idmap_entry ** ); -static int idmap_add(struct idmap_entry *); - -static int -idmap_upcall_name(uint32_t type, char * name, struct idmap_entry ** found) -{ - int error; - struct idmap_entry * e; - size_t len, siz; - - if (type > IDMAP_MAX_TYPE || type == 0) { - IDMAP_DEBUG("bad type %d\n", type); - return EINVAL; /* XXX */ - } - - if (name == NULL || (len = strlen(name)) == 0 || len > IDMAP_MAXNAMELEN) { - IDMAP_DEBUG("idmap_upcall_name: bad name\n"); - return EFAULT; /* XXX */ - } - - e = malloc(sizeof(struct idmap_entry), M_IDMAP, - M_WAITOK | M_ZERO); - - e->id_info.id_type = type; - bcopy(name, e->id_info.id_name, len); - e->id_info.id_namelen = len; - - - siz = sizeof(struct idmap_msg); - error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz, - (caddr_t)&e->id_info, &siz); - - if (error) { - IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error); - *found = NULL; - return error; - } - - if (siz != sizeof(struct idmap_msg)) { - IDMAP_DEBUG("bad size of returned message\n"); - *found = NULL; - return EFAULT; - } - - *found = e; - return 0; -} - -static int -idmap_upcall_id(uint32_t type, ident_t id, struct idmap_entry ** found) -{ - int error; - struct idmap_entry * e; - size_t siz; - - if (type > IDMAP_MAX_TYPE) - panic("bad type"); /* XXX */ - - e = malloc(sizeof(struct idmap_entry), M_IDMAP, - M_WAITOK | M_ZERO); - - e->id_info.id_type = type; - e->id_info.id_namelen = 0; /* should already */ - e->id_info.id_id = id; - - siz = sizeof(struct idmap_msg); - error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz, - (caddr_t)&e->id_info, &siz); - - if (error) { - IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error); - *found = NULL; - return error; - } - - if (siz != sizeof(struct idmap_msg)) { - IDMAP_DEBUG("bad size of returned message\n"); - *found = NULL; - return EFAULT; - } - - *found = e; - return 0; -} - -static void -idmap_hashf(struct idmap_entry *e, uint32_t * hval_id, uint32_t * hval_name) -{ - switch (e->id_info.id_type) { - case IDMAP_TYPE_UID: - *hval_id = e->id_info.id_id.uid % IDMAP_HASH_SIZE; - break; - case IDMAP_TYPE_GID: - *hval_id = e->id_info.id_id.gid % IDMAP_HASH_SIZE; - break; - default: - /* XXX yikes! */ - panic("hashf: bad type!"); - break; - } - - if (e->id_info.id_namelen == 0) - /* XXX */ panic("hashf: bad name"); - - *hval_name = fnv_32_str(e->id_info.id_name, FNV1_32_INIT) % IDMAP_HASH_SIZE; -} - -static int -idmap_add(struct idmap_entry * e) -{ - struct idmap_hash * hash; - uint32_t hval_id, hval_name; - - if (e->id_info.id_namelen == 0) { - printf("idmap_add: name of len 0\n"); - return EINVAL; - } - - switch (e->id_info.id_type) { - case IDMAP_TYPE_UID: - hash = &idmap_uid_hash; - break; - case IDMAP_TYPE_GID: - hash = &idmap_gid_hash; - break; - default: - /* XXX yikes */ - panic("idmap add: bad type!"); - break; - } - - idmap_hashf(e, &hval_id, &hval_name); - - IDMAP_WLOCK(&hash->hash_lock); - - TAILQ_INSERT_TAIL(&hash->hash_id[hval_id], e, id_entry_id); - TAILQ_INSERT_TAIL(&hash->hash_name[hval_name], e, id_entry_name); - - IDMAP_UNLOCK(&hash->hash_lock); - - return 0; -} - -static struct idmap_entry * -idmap_id_lookup(uint32_t type, ident_t id) -{ - struct idmap_hash * hash; - uint32_t hval; - struct idmap_entry * e; - - switch (type) { - case IDMAP_TYPE_UID: - hash = &idmap_uid_hash; - hval = id.uid % IDMAP_HASH_SIZE; - break; - case IDMAP_TYPE_GID: - hash = &idmap_gid_hash; - hval = id.gid % IDMAP_HASH_SIZE; - break; - default: - /* XXX yikes */ - panic("lookup: bad type!"); - break; - } - - - IDMAP_RLOCK(&hash->hash_lock); - - TAILQ_FOREACH(e, &hash->hash_id[hval], id_entry_name) { - if ((type == IDMAP_TYPE_UID && e->id_info.id_id.uid == id.uid)|| - (type == IDMAP_TYPE_GID && e->id_info.id_id.gid == id.gid)) { - IDMAP_UNLOCK(&hash->hash_lock); - return e; - } - } - - IDMAP_UNLOCK(&hash->hash_lock); - return NULL; -} - -static struct idmap_entry * -idmap_name_lookup(uint32_t type, char * name) -{ - struct idmap_hash * hash; - uint32_t hval; - struct idmap_entry * e; - size_t len; - - switch (type) { - case IDMAP_TYPE_UID: - hash = &idmap_uid_hash; - break; - case IDMAP_TYPE_GID: - hash = &idmap_gid_hash; - break; - default: - /* XXX yikes */ - panic("lookup: bad type!"); - break; - } - - len = strlen(name); - - if (len == 0 || len > IDMAP_MAXNAMELEN) { - IDMAP_DEBUG("bad name length %d\n", len); - return NULL; - } - - hval = fnv_32_str(name, FNV1_32_INIT) % IDMAP_HASH_SIZE; - - IDMAP_RLOCK(&hash->hash_lock); - - TAILQ_FOREACH(e, &hash->hash_name[hval], id_entry_name) { - if ((strlen(e->id_info.id_name) == strlen(name)) && strncmp(e->id_info.id_name, name, strlen(name)) == 0) { - IDMAP_UNLOCK(&hash->hash_lock); - return e; - } - } - - IDMAP_UNLOCK(&hash->hash_lock); - return NULL; -} - -void -idmap_init(void) -{ - unsigned int i; - - for (i=0; i<IDMAP_HASH_SIZE; i++) { - TAILQ_INIT(&idmap_uid_hash.hash_name[i]); - TAILQ_INIT(&idmap_uid_hash.hash_id[i]); - - TAILQ_INIT(&idmap_gid_hash.hash_name[i]); - TAILQ_INIT(&idmap_gid_hash.hash_id[i]); - } - - lockinit(&idmap_uid_hash.hash_lock, PLOCK, "idmap uid hash table", 0,0); - lockinit(&idmap_gid_hash.hash_lock, PLOCK, "idmap gid hash table", 0,0); - -} - -void idmap_uninit(void) -{ - struct idmap_entry * e; - int i; - - lockdestroy(&idmap_uid_hash.hash_lock); - lockdestroy(&idmap_gid_hash.hash_lock); - - for (i=0; i<IDMAP_HASH_SIZE; i++) { - while(!TAILQ_EMPTY(&idmap_uid_hash.hash_name[i])) { - e = TAILQ_FIRST(&idmap_uid_hash.hash_name[i]); - TAILQ_REMOVE(&idmap_uid_hash.hash_name[i], e, id_entry_name); - TAILQ_REMOVE(&idmap_uid_hash.hash_id[i], e, id_entry_id); - free(e, M_IDMAP); - } - - while(!TAILQ_EMPTY(&idmap_gid_hash.hash_name[i])) { - e = TAILQ_FIRST(&idmap_gid_hash.hash_name[i]); - TAILQ_REMOVE(&idmap_gid_hash.hash_name[i], e, id_entry_name); - TAILQ_REMOVE(&idmap_gid_hash.hash_id[i], e, id_entry_id); - free(e, M_IDMAP); - } - - } -} - -int -idmap_uid_to_name(uid_t uid, char ** name, size_t * len) -{ - struct idmap_entry * e; - int error = 0; - ident_t id; - - id.uid = uid; - - - if ((e = idmap_id_lookup(IDMAP_TYPE_UID, id)) == NULL) { - if ((error = idmap_upcall_id(IDMAP_TYPE_UID, id, &e)) != 0) { - IDMAP_DEBUG("error in upcall\n"); - return error; - } - - if (e == NULL) { - IDMAP_DEBUG("no error from upcall, but no data returned\n"); - return EFAULT; - } - - if (idmap_add(e) != 0) { - IDMAP_DEBUG("idmap_add failed\n"); - free(e, M_IDMAP); - return EFAULT; - } - } - - *name = e->id_info.id_name; - *len = e->id_info.id_namelen; - return 0; -} - -int -idmap_gid_to_name(gid_t gid, char ** name, size_t * len) -{ - struct idmap_entry * e; - int error = 0; - ident_t id; - - id.gid = gid; - - - if ((e = idmap_id_lookup(IDMAP_TYPE_GID, id)) == NULL) { - if ((error = idmap_upcall_id(IDMAP_TYPE_GID, id, &e))) { - IDMAP_DEBUG("error in upcall\n"); - return error; - } - - if (e == NULL) { - IDMAP_DEBUG("no error from upcall, but no data returned\n"); - return EFAULT; - } - - if (idmap_add(e) != 0) { - IDMAP_DEBUG("idmap_add failed\n"); - free(e, M_IDMAP); - } - } - - *name = e->id_info.id_name; - *len = e->id_info.id_namelen; - return 0; -} - -int -idmap_name_to_uid(char * name, size_t len, uid_t * id) -{ - struct idmap_entry * e; - int error = 0; - char * namestr; - - if (name == NULL ) - return EFAULT; - - if (len == 0 || len > IDMAP_MAXNAMELEN) { - IDMAP_DEBUG("idmap_name_to_uid: bad len\n"); - return EINVAL; - } - - /* XXX hack */ - namestr = malloc(len + 1, M_TEMP, M_WAITOK); - bcopy(name, namestr, len); - namestr[len] = '\0'; - - - if ((e = idmap_name_lookup(IDMAP_TYPE_UID, namestr)) == NULL) { - if ((error = idmap_upcall_name(IDMAP_TYPE_UID, namestr, &e))) { - free(namestr, M_TEMP); - return error; - } - - if (e == NULL) { - IDMAP_DEBUG("no error from upcall, but no data returned\n"); - free(namestr, M_TEMP); - return EFAULT; - } - - if (idmap_add(e) != 0) { - IDMAP_DEBUG("idmap_add failed\n"); - free(e, M_IDMAP); - } - } - - *id = e->id_info.id_id.uid; - free(namestr, M_TEMP); - return 0; -} - -int -idmap_name_to_gid(char * name, size_t len, gid_t * id) -{ - struct idmap_entry * e; - int error = 0; - - char * namestr; - - if (name == NULL ) - return EFAULT; - - if (len == 0 || len > IDMAP_MAXNAMELEN) { - IDMAP_DEBUG("idmap_name_to_uid: bad len\n"); - return EINVAL; - } - - /* XXX hack */ - namestr = malloc(len + 1, M_TEMP, M_WAITOK); - bcopy(name, namestr, len); - namestr[len] = '\0'; - - - if ((e = idmap_name_lookup(IDMAP_TYPE_GID, namestr)) == NULL) { - if ((error = idmap_upcall_name(IDMAP_TYPE_GID, namestr, &e)) != 0) { - IDMAP_DEBUG("error in upcall\n"); - free(namestr, M_TEMP); - return error; - } - - if (e == NULL) { - IDMAP_DEBUG("no error from upcall, but no data returned\n"); - free(namestr, M_TEMP); - return EFAULT; - } - - if (idmap_add(e) != 0) { - IDMAP_DEBUG("idmap_add failed\n"); - free(e, M_IDMAP); - } - } - - *id = e->id_info.id_id.gid; - free(namestr, M_TEMP); - return 0; -} diff --git a/sys/nfs4client/nfs4_idmap.h b/sys/nfs4client/nfs4_idmap.h deleted file mode 100644 index 0b09cf4..0000000 --- a/sys/nfs4client/nfs4_idmap.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_idmap.h,v 1.2 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. - */ - -#ifndef __NFS4_IDMAP_H__ -#define __NFS4_IDMAP_H__ - -#define IDMAP_TYPE_GID 1 -#define IDMAP_TYPE_UID 2 -#define IDMAP_MAX_TYPE 2 - -typedef union { - uid_t uid; - gid_t gid; -} ident_t; - -#define IDMAP_MAXNAMELEN 249 -struct idmap_msg { - uint32_t id_type; - ident_t id_id; - size_t id_namelen; - char id_name[IDMAP_MAXNAMELEN + 1]; -}; - - -#ifdef _KERNEL -MALLOC_DECLARE(M_IDMAP); - -void idmap_init(void); -void idmap_uninit(void); - -int idmap_gid_to_name(gid_t id, char ** name, size_t * len); -int idmap_uid_to_name(uid_t id, char ** name, size_t * len); - -int idmap_name_to_gid(char *, size_t len, gid_t *); -int idmap_name_to_uid(char *, size_t len, uid_t *); - -#endif /* _KERNEL */ - - -#endif /* __NFS4_GSS_H__ */ diff --git a/sys/nfs4client/nfs4_socket.c b/sys/nfs4client/nfs4_socket.c deleted file mode 100644 index c1fe154..0000000 --- a/sys/nfs4client/nfs4_socket.c +++ /dev/null @@ -1,348 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs_socket.c,v 1.12 2003/11/05 14:59:01 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. - */ - -/*- - * Copyright (c) 1989, 1991, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Socket operations for use by nfs - */ - -#include "opt_inet6.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/mount.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/protosw.h> -#include <sys/signalvar.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/syslog.h> -#include <sys/vnode.h> - -#include <netinet/in.h> -#include <netinet/tcp.h> - -#include <rpc/rpcclnt.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfs4client/nfs4.h> -#include <nfs/xdr_subs.h> -#include <nfsclient/nfsm_subs.h> -#include <nfsclient/nfsmount.h> - -#ifdef NFS4_USE_RPCCLNT -#include <rpc/rpcclnt.h> -#include <rpc/rpcm_subs.h> -#endif - -#ifdef NFS4_USE_RPCCLNT -static struct rpc_program nfs_program = { - NFS_PROG, NFS_VER4, "NFSv4" -}; -#endif - - -static struct { - short nfserr; - short syserr; -} nfs_errtbl[] = { - { NFS_OK, 0 }, - { NFSERR_PERM, EPERM }, - { NFSERR_NOENT, ENOENT }, - { NFSERR_IO, EIO }, - { NFSERR_NXIO, ENXIO }, - { NFSERR_ACCES, EACCES }, - { NFSERR_EXIST, EEXIST }, - { NFSERR_XDEV, EXDEV }, - { NFSERR_MLINK, EMLINK }, - { NFSERR_NODEV, ENODEV }, - { NFSERR_NOTDIR, ENOTDIR }, - { NFSERR_ISDIR, EISDIR }, - { NFSERR_INVAL, EINVAL }, - { NFSERR_FBIG, EFBIG }, - { NFSERR_NOSPC, ENOSPC }, - { NFSERR_ROFS, EROFS }, - { NFSERR_MLINK, EMLINK }, - { NFSERR_NAMETOL, ENAMETOOLONG }, - { NFSERR_NOTEMPTY, ENOTEMPTY }, - { NFSERR_NOTSUPP, EOPNOTSUPP }, -#ifdef EDQUOT - { NFSERR_DQUOT, EDQUOT }, -#endif - { NFSERR_STALE, ESTALE }, - { NFSERR_DENIED, EAGAIN }, - { NFSERR_SYMLINK, ELOOP }, - { NFSERR_BADXDR, EBADRPC }, - { NFSERR_WRONGSEC, EPERM }, - { -1, EIO } -}; - -static int -nfs4_nfserr_to_syserr(int nfserr) -{ - int i, syserr; - - /* XXX : not the optimal algorithm, but will do for now! */ - for (i = 0; nfs_errtbl[i].nfserr != -1; i++) { - if (nfs_errtbl[i].nfserr == nfserr) - break; - } -#ifdef NFS4_MAP_UNKNOWN_ERR - syserr = nfs_errtbl[i].syserr; -#else - if (nfs_errtbl[i].nfserr != -1) - syserr = nfs_errtbl[i].syserr; - else - syserr = nfserr; -#endif - return syserr; -} - -int -nfs4_connect(struct nfsmount *nmp) -{ - struct rpcclnt * rpc = &nmp->nm_rpcclnt; - struct rpc_auth * auth; - int flag = 0; - int error; - - /* XXX hack! */ -#ifdef __OpenBSD__ - struct proc * td = curproc; -#else - struct thread * td = curthread; -#endif - - auth = malloc(sizeof(struct rpc_auth), M_TEMP, M_WAITOK); - auth->auth_type = RPCAUTH_UNIX; - - /* translate nfs flags -> rpcclnt flags */ - if (nmp->nm_flag & NFSMNT_SOFT) - flag |= RPCCLNT_SOFT; - - if (nmp->nm_flag & NFSMNT_INT) - flag |= RPCCLNT_INT; - - if (nmp->nm_flag & NFSMNT_NOCONN) - flag |= RPCCLNT_NOCONN; - - if (nmp->nm_flag & NFSMNT_DUMBTIMR) - flag |= RPCCLNT_DUMBTIMR; - - /* rpc->rc_servername = nmp->nm_mountp->mnt_stat.f_mntfromname; */ - - error = rpcclnt_setup(rpc, &nfs_program, nmp->nm_nam, nmp->nm_sotype, - nmp->nm_soproto, auth, - /* XXX: check nmp->nm_flag to make sure these are set */ - (nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize, - nmp->nm_wsize, flag); - - /* set deadthresh, timeo, retry */ - rpc->rc_deadthresh = nmp->nm_deadthresh; - rpc->rc_timeo = nmp->nm_timeo; - rpc->rc_retry = nmp->nm_retry; - - - if (error) - return error; - - return rpcclnt_connect(rpc, td); -} - -/* - * NFS disconnect. Clean up and unlink. - */ -void -nfs4_disconnect(struct nfsmount *nmp) -{ - rpcclnt_disconnect(&nmp->nm_rpcclnt); -} - -void -nfs4_safedisconnect(struct nfsmount *nmp) -{ - rpcclnt_safedisconnect(&nmp->nm_rpcclnt); -} - -/* - * nfs_request - goes something like this - * - fill in request struct - * - links it into list - * - calls nfs_send() for first transmit - * - calls nfs_receive() to get reply - * - break down rpc header and return with nfs reply pointed to - * by mrep or error - * nb: always frees up mreq mbuf list - */ -/* XXX overloaded before */ -#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */ - -int -nfs4_request(struct vnode *vp, struct mbuf *mrest, int procnum, - struct thread *td, struct ucred *cred, struct mbuf **mrp, - struct mbuf **mdp, caddr_t *dposp) -{ - int error; - - error = nfs4_request_mnt(VFSTONFS(vp->v_mount), mrest, procnum, - td, cred, mrp, mdp, dposp); - - /* - ** If the File Handle was stale, invalidate the - ** lookup cache, just in case. - **/ - if (error == ESTALE) - nfs_purgecache(vp); - - return (error); -} - - -int -nfs4_request_mnt(struct nfsmount *nmp, struct mbuf *mrest, int procnum, - struct thread *td, struct ucred *cred, struct mbuf **mrp, - struct mbuf **mdp, caddr_t *dposp) -{ - int error; - u_int32_t *tl; - struct rpcclnt * clnt = &nmp->nm_rpcclnt; - struct mbuf *md, *mrep; - caddr_t dpos; - struct rpc_reply reply; - - if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred, - &reply)) != 0) { - goto out; - } - - /* XXX: don't free mrest if an error occured, to allow caller to retry*/ - m_freem(mrest); - mrep = reply.mrep; - md = reply.result_md; - dpos = reply.result_dpos; - - tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); - if (*tl != 0) { - error = fxdr_unsigned(int, *tl); -#if 0 - if ((nmp->nm_flag & NFSMNT_NFSV3) && - error == NFSERR_TRYLATER) { - m_freem(mrep); - error = 0; - waituntil = time_second + trylater_delay; - while (time_second < waituntil) - (void) tsleep(&fake_wchan, PSOCK, "nqnfstry", hz); - trylater_delay *= nfs_backoff[trylater_cnt]; - if (trylater_cnt < NFS_NBACKOFF - 1) - trylater_cnt++; - goto tryagain; - } -#endif - goto out; - } - - *mrp = mrep; - *mdp = md; - *dposp = dpos; - return (0); -nfsmout: -out: - m_freem(reply.mrep); - *mrp = NULL; - *mdp = NULL; - return (nfs4_nfserr_to_syserr(error)); -} - - -/* - * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and - * wait for all requests to complete. This is used by forced unmounts - * to terminate any outstanding RPCs. - */ -int -nfs4_nmcancelreqs(nmp) - struct nfsmount *nmp; -{ - return rpcclnt_cancelreqs(&nmp->nm_rpcclnt); -} - -/* - * Test for a termination condition pending on the process. - * This is used for NFSMNT_INT mounts. - */ -int -nfs4_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td) -{ - if (rep != NULL) { - printf("nfs_sigintr: attempting to use nfsreq != NULL\n"); - return EINTR; - } - return rpcclnt_sigintr(&nmp->nm_rpcclnt, NULL, td); -} diff --git a/sys/nfs4client/nfs4_subs.c b/sys/nfs4client/nfs4_subs.c deleted file mode 100644 index 21c89c9..0000000 --- a/sys/nfs4client/nfs4_subs.c +++ /dev/null @@ -1,1367 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_subs.c,v 1.52 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/cdefs.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/proc.h> -#include <sys/mount.h> -#include <sys/vnode.h> -#include <sys/namei.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/malloc.h> -#include <sys/sysent.h> -#include <sys/syscall.h> -#include <sys/sysproto.h> -#include <sys/fcntl.h> - -#include <machine/stdarg.h> - -#include <vm/vm.h> -#include <vm/vm_object.h> -#include <vm/vm_extern.h> -#include <vm/uma.h> - -#include <rpc/rpcclnt.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfs4client/nfs4.h> -#include <nfsclient/nfsnode.h> -#include <nfsclient/nfsmount.h> -#include <nfs/xdr_subs.h> -#include <nfsclient/nfsm_subs.h> - -#include <nfs4client/nfs4_dev.h> -#include <nfs4client/nfs4_idmap.h> -#include <nfs4client/nfs4m_subs.h> - -#include <netinet/in.h> - -#define NFSM_DISSECT(s) do { \ - tl = nfsm_dissect_xx((s), md, dpos); \ - if (tl == NULL) { \ - printf("NFSM_DISSECT error; allocation (%s/%d) (%s:%d)\n", #s, s, __FILE__, __LINE__); \ - return (EBADRPC); \ - } \ -} while (0) - -#define NFSM_ADV(s) do { \ - t1 = nfsm_adv_xx((s), md, dpos); \ - if (t1 != 0) { \ - printf("NFSM_ADV error; allocation (%s/%d) (%s:%d)\n", #s, s, __FILE__, __LINE__); \ - return (EBADRPC); \ - } \ -} while (0) - -#define NFSM_MTOTIME(t) do { \ - NFSM_DISSECT(3 * NFSX_UNSIGNED); \ - (t).tv_sec = fxdr_hyper(tl); \ - tl += 2; \ - (t).tv_nsec = fxdr_unsigned(long, *tl++); \ -} while (0) - -static uint32_t __fsinfo_bm[2], __fsattr_bm[2], __getattr_bm[2], __readdir_bm[2]; - -nfsv4bitmap nfsv4_fsinfobm = { 2, __fsinfo_bm }; -nfsv4bitmap nfsv4_fsattrbm = { 2, __fsattr_bm }; -nfsv4bitmap nfsv4_getattrbm = { 2, __getattr_bm }; -nfsv4bitmap nfsv4_readdirbm = { 2, __readdir_bm }; - -/* Helper routines */ -int nfsm_v4build_attrs_xx(struct vattr *, struct mbuf **, caddr_t *); -int nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *, struct mbuf **, caddr_t *); - -void -nfsm_v4init(void) -{ - - /* Set up bitmasks */ - FA4_SET(FA4_FSID, __fsinfo_bm); - FA4_SET(FA4_MAXREAD, __fsinfo_bm); - FA4_SET(FA4_MAXWRITE, __fsinfo_bm); - FA4_SET(FA4_LEASE_TIME, __fsinfo_bm); - - FA4_SET(FA4_FSID, __fsattr_bm); - FA4_SET(FA4_FILES_FREE, __fsattr_bm); - FA4_SET(FA4_FILES_TOTAL, __fsattr_bm); - FA4_SET(FA4_SPACE_AVAIL, __fsattr_bm); - FA4_SET(FA4_SPACE_FREE, __fsattr_bm); - FA4_SET(FA4_SPACE_TOTAL, __fsattr_bm); - - FA4_SET(FA4_TYPE, __getattr_bm); - FA4_SET(FA4_FSID, __getattr_bm); - FA4_SET(FA4_SIZE, __getattr_bm); - FA4_SET(FA4_MODE, __getattr_bm); - FA4_SET(FA4_RAWDEV, __getattr_bm); - FA4_SET(FA4_NUMLINKS, __getattr_bm); - FA4_SET(FA4_OWNER, __getattr_bm); - FA4_SET(FA4_OWNER_GROUP, __getattr_bm); - FA4_SET(FA4_FILEID, __getattr_bm); - FA4_SET(FA4_TIME_ACCESS, __getattr_bm); - FA4_SET(FA4_TIME_CREATE, __getattr_bm); - FA4_SET(FA4_TIME_METADATA, __getattr_bm); - FA4_SET(FA4_TIME_MODIFY, __getattr_bm); - - FA4_SET(FA4_TYPE, __readdir_bm); - FA4_SET(FA4_FSID, __readdir_bm); - FA4_SET(FA4_FILEID, __readdir_bm); - FA4_SET(FA4_RDATTR_ERROR, __readdir_bm); -} - -/* - * Util - */ - -uint32_t -nfs_v4fileid4_to_fileid(uint64_t fid) -{ - return ((uint32_t)((fid >> 32) | fid)); -} - -void -nfs_v4initcompound(struct nfs4_compound *cp) -{ - bzero(cp, sizeof(*cp)); -} - -/* - * Build/dissect XDR buffer with a format string. - * - * u - unsigned - * h - hyper - * s - stringlength, string - * k - skip length (bytes) - * a - arraylength, componentlenght, array - * o - opaque fix length - * O - opaque var length in bytes - */ - -void -nfsm_buildf_xx(struct mbuf **mb, caddr_t *bpos, char *fmt, ...) -{ - uint32_t *tl, t1, len, uval; - uint64_t hval; - va_list args; - char *p, *which; - - va_start(args, fmt); - for (which = fmt; *which != '\0'; which++) - switch (*which) { - case 'u': /* Unsigned */ - tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos); - uval = va_arg(args, uint32_t); - *tl++ = txdr_unsigned(uval); - break; - case 'h': /* Hyper */ - tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos); - hval = va_arg(args, uint64_t); - txdr_hyper(hval, tl); - break; - case 'o': /* Fixed-length opaque */ - len = va_arg(args, uint32_t); - p = va_arg(args, char *); - tl = nfsm_build_xx(nfsm_rndup(len), mb, bpos); - bcopy(p, tl, len); - break; - case 'O': /* Variable-length opaque */ - case 's': /* String */ - len = va_arg(args, uint32_t); - p = va_arg(args, char *); - t1 = nfsm_strtom_xx(p, len, len, mb, bpos); - break; - case 'k': /* Skip */ - len = va_arg(args, uint32_t); - nfsm_build_xx(nfsm_rndup(len), mb, bpos); - break; - default: - panic("Invalid buildf string %s[%c]", fmt, *which); - break; - } - va_end(args); -} - -int -nfsm_dissectf_xx(struct mbuf **md, caddr_t *dpos, char *fmt, ...) -{ - uint32_t *tl, t1, len, *uval; - uint64_t *hval; - va_list args; - char *p, *which; - - va_start(args, fmt); - for (which = fmt; *which != '\0'; which++) - switch (*which) { - case 'u': /* Unsigned */ - tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); - if (tl == NULL) - return (EBADRPC); - uval = va_arg(args, uint32_t *); - *uval = fxdr_unsigned(uint32_t, *tl++); - break; - case 'h': /* Hyper */ - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL) - return (EBADRPC); - hval = va_arg(args, uint64_t *); - *hval = fxdr_hyper(tl); - break; - case 'o': /* Fixed-length opaque */ - len = va_arg(args, uint32_t); - p = va_arg(args, void *); - tl = nfsm_dissect_xx(nfsm_rndup(len), md, dpos); - if (tl == NULL) - return (EBADRPC); - bcopy(tl, p, len); - break; - case 'O': /* Variable-length opaque */ - case 's': /* String */ - len = va_arg(args, uint32_t); - p = va_arg(args, char *); - tl = nfsm_dissect_xx(nfsm_rndup(len), md, dpos); - if (tl == NULL) - return (EBADRPC); - bcopy(tl, p, len); - break; - case 'k': /* Skip bytes */ - len = va_arg(args, uint32_t); - t1 = nfsm_adv_xx(nfsm_rndup(len), md, dpos); - break; - default: - panic("Invalid dissectf string %s[%c]", fmt, *which); - break; - } - va_end(args); - - return (0); -} - -/* - * XXX - There are a few problems with the way the postops are places - * in the code. Ideally, they should be taken care of immediately, as - * to avoid uneceesary waits for mutexes, but then we would be - * introducing even more complexity by having to handle two separate - * cases. Also, since they are placed at the end of the vnops', there - * may be operations which sleep in between, further extending this - * wait. It is conceivable that there is a deadlock condition there, - * too. - * - * Also, for vnops that do multiple operations, it's inconvenient - * since on error, individual decoding will got nfsmout. - */ - -int -nfs_v4postop(struct nfs4_compound *cp, int status) -{ - struct nfs4_fctx *fcp = cp->fcp; - - /* - * XXX does the previous result need to be stores with the - * lockowner? ack, spec is unclear .. - */ - - if (fcp != NULL) - if (cp->seqidused < cp->rep_nops || - (cp->seqidused + 1 == cp->rep_nops && - NFS4_SEQIDMUTATINGERROR(status))) - fcp->lop->lo_seqid++; - - return (status); -} - -int -nfs_v4handlestatus(int status, struct nfs4_compound *cp) -{ - return (status); -} - -/* - * Initial setup of compound. - */ - -int -nfsm_v4build_compound_xx(struct nfs4_compound *cp, char *tag, - struct mbuf **mb, caddr_t *bpos) -{ - uint32_t t1, *tl, siz; - - /* Tag */ - siz = strlen(tag); - t1 = nfsm_rndup(siz) + NFSX_UNSIGNED; - if (t1 <= M_TRAILINGSPACE(*mb)) { - tl = nfsm_build_xx(t1, mb, bpos); - *tl++ = txdr_unsigned(siz); - *(tl + ((t1 >> 2) - 2)) = 0; - bcopy(tag, tl, siz); - } else { - t1 = nfsm_strtmbuf(mb, bpos, (const char *)tag, siz); - if (t1 != 0) - return (t1); - } - - /* Minor version and argarray*/ - tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos); - *tl++ = txdr_unsigned(NFS4_MINOR_VERSION); - /* Save for backfill */ - cp->req_nopsp = tl; - *tl = txdr_unsigned(0); - - cp->curvp = NULL; - cp->savevp = NULL; - - return (0); -} - -/* - * XXX - * - backfill for stateid, and such - */ -int -nfsm_v4build_finalize_xx(struct nfs4_compound *cp, struct mbuf **mb, caddr_t *bpos) -{ - *cp->req_nopsp = txdr_unsigned(cp->req_nops); - - return (0); -} - -int -nfsm_v4build_putfh_xx(struct nfs4_compound *cp, struct vnode *vp, - struct mbuf **mb, caddr_t *bpos) -{ - uint32_t t1; - - /* Op */ - nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_PUTFH); - - /* FH */ - t1 = nfsm_fhtom_xx(vp, 1, mb, bpos); - if (t1 != 0) - return (t1); - - cp->req_nops++; - cp->curvp = vp; - - return (0); -} - -int -nfsm_v4build_putfh_nv_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uuo", - NFSV4OP_PUTFH, - gfh->fh_len, - gfh->fh_len, - &gfh->fh_val); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_simple_xx(struct nfs4_compound *cp, uint32_t op, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "u", op); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga, - struct mbuf **mb, caddr_t *bpos) -{ - int i; - - /* Op + bitmap length + bitmap */ - nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_GETATTR, ga->bm->bmlen); - for (i = 0; i < ga->bm->bmlen; i++) - nfsm_buildf_xx(mb, bpos, "u", ga->bm->bmval[i]); - - ga->vp = cp->curvp; - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_setattr_xx(struct nfs4_compound *cp, struct vattr *vap, - struct nfs4_fctx *fcp, struct mbuf **mb, caddr_t *bpos) -{ - int error; - static char zero_stateid[NFSX_V4STATEID]; - - nfsm_buildf_xx(mb, bpos, "uo", - NFSV4OP_SETATTR, - NFSX_V4STATEID, fcp ? fcp->stateid : zero_stateid); - error = nfsm_v4build_attrs_xx(vap, mb, bpos); - if (error == 0) - cp->req_nops++; - - return (error); -} - -int -nfsm_v4build_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_GETFH); - - gfh->vp = cp->curvp; - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_lookup_xx(struct nfs4_compound *cp, struct nfs4_oparg_lookup *l, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LOOKUP, l->namelen, l->name); - - cp->curvp = l->vp; - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_setclientid_xx(struct nfs4_compound *cp, - struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos) -{ - struct timeval tv; - - microtime(&tv); - - nfsm_buildf_xx(mb, bpos, "uuusussu", - NFSV4OP_SETCLIENTID, - tv.tv_sec, tv.tv_usec, - sci->namelen, sci->name, - sci->cb_prog, - sci->cb_netidlen, sci->cb_netid, - sci->cb_univaddrlen, sci->cb_univaddr, - 0xCA11BACC); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_setclientid_confirm_xx(struct nfs4_compound *cp, - struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uho", - NFSV4OP_SETCLIENTID_CONFIRM, - sci->clientid, - sizeof(sci->verf), sci->verf); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op, - struct mbuf **mb, caddr_t *bpos) -{ - int error = 0; - struct nfs4_lowner *lop = op->fcp->lop; - - nfsm_buildf_xx(mb, bpos, "uuuuhuu", - NFSV4OP_OPEN, - lop->lo_seqid, - op->flags & O_ACCMODE, - NFSV4OPENSHARE_DENY_NONE, - cp->nmp->nm_clientid, - 4, lop->lo_id); - - if (op->flags & O_CREAT) { - nfsm_buildf_xx(mb, bpos, "u", OTCREATE); - /* openflag4: mode */ - nfsm_buildf_xx(mb, bpos, "u", CMUNCHECKED); - /* openflag4: createattrs... */ - if (op->vap != NULL) { - if (op->flags & O_TRUNC) - op->vap->va_size = 0; - error = nfsm_v4build_attrs_xx(op->vap, mb, bpos); - if (error != 0) - return (error); - } else - nfsm_buildf_xx(mb, bpos, "uu", 0, 0); - } else - nfsm_buildf_xx(mb, bpos, "u", OTNOCREATE); - - nfsm_buildf_xx(mb, bpos, "us", op->ctype, - op->cnp->cn_namelen, op->cnp->cn_nameptr); - - cp->seqidused = cp->req_nops++; - cp->fcp = op->fcp; - - return (error); -} - -/* - * XXX - * - Wait on recovery - */ -int -nfsm_v4build_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uou", - NFSV4OP_OPEN_CONFIRM, - NFSX_V4STATEID, op->fcp->stateid, - op->fcp->lop->lo_seqid); - - cp->seqidused = cp->req_nops++; - cp->fcp = op->fcp; - - return (0); -} - -/* - * XXX - * - Wait on recovery - */ -int -nfsm_v4build_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp, - struct mbuf **mb, caddr_t *bpos) -{ - struct nfs4_lowner *lop = fcp->lop; - - nfsm_buildf_xx(mb, bpos, "uuo", - NFSV4OP_CLOSE, - lop->lo_seqid, - NFSX_V4STATEID, fcp->stateid); - - cp->seqidused = cp->req_nops++; - cp->fcp = fcp; - - return (0); -} - -int -nfsm_v4build_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_ACCESS, acc->mode); - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uohu", - NFSV4OP_READ, - NFSX_V4STATEID, r->fcp->stateid, - r->off, - r->maxcnt); - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uohuu", - NFSV4OP_WRITE, - NFSX_V4STATEID, w->fcp->stateid, - w->off, - w->stable, - w->cnt); - cp->req_nops++; - return (nfsm_uiotombuf(w->uiop, mb, w->cnt, bpos)); -} - -int -nfsm_v4build_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uhu", NFSV4OP_COMMIT, c->start, c->len); - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_readdir_xx(struct nfs4_compound *cp, struct nfs4_oparg_readdir *r, - struct mbuf **mb, caddr_t *bpos) -{ - int i; - - nfsm_buildf_xx(mb, bpos, "uhouuu", - NFSV4OP_READDIR, - r->cookie, - sizeof(r->verf), r->verf, - r->cnt >> 4, /* meaningless "dircount" field */ - r->cnt, - r->bm->bmlen); - - for (i = 0; i < r->bm->bmlen; i++) - nfsm_buildf_xx(mb, bpos, "u", r->bm->bmval[i]); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_renew_xx(struct nfs4_compound *cp, uint64_t cid, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uh", NFSV4OP_RENEW, cid); - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c, - struct mbuf **mb, caddr_t *bpos) -{ - uint32_t t1; - - nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_CREATE, c->type); - - if (c->type == NFLNK) - /* XXX strlen */ - nfsm_buildf_xx(mb, bpos, "s", strlen(c->linktext), c->linktext); - else if (c->type == NFCHR || c->type == NFBLK) - nfsm_buildf_xx(mb, bpos, "uu", - major(c->vap->va_rdev), minor(c->vap->va_rdev)); - - /* Name */ - nfsm_buildf_xx(mb, bpos, "s", c->namelen, c->name); - - /* Attributes */ - t1 = nfsm_v4build_attrs_xx(c->vap, mb, bpos); - if (t1 != 0) - return (t1); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_rename_xx(struct nfs4_compound *cp, struct nfs4_oparg_rename *r, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "uss", NFSV4OP_RENAME, r->fnamelen, r->fname, - r->tnamelen, r->tname); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_link_xx(struct nfs4_compound *cp, struct nfs4_oparg_link *l, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LINK, l->namelen, l->name); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_remove_xx(struct nfs4_compound *cp, const char *name, u_int namelen, - struct mbuf **mb, caddr_t *bpos) -{ - nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_REMOVE, namelen, name); - - cp->req_nops++; - - return (0); -} - -int -nfsm_v4build_attrs_xx(struct vattr *vap, struct mbuf **mb, caddr_t *bpos) -{ - uint32_t *tl, *attrlenp, *bmvalp, len; - size_t siz; - - tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos); - - *tl++ = txdr_unsigned(2); /* bitmap length */ - bmvalp = tl; - bzero(bmvalp, 8); - tl += 2; - attrlenp = tl; - - len = 0; - if (vap->va_size != VNOVAL) { - tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos); - FA4_SET(FA4_SIZE, bmvalp); - txdr_hyper(vap->va_size, tl); tl += 2; - len += 2 * NFSX_UNSIGNED; - } - if (vap->va_mode != (u_short)VNOVAL) { - tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos); - FA4_SET(FA4_MODE, bmvalp); - *tl++ = txdr_unsigned(vap->va_mode); - len += NFSX_UNSIGNED; - } - if (vap->va_uid != VNOVAL) { - int error; - char *name; - error = idmap_uid_to_name(vap->va_uid, &name, &siz); - if (error || name == NULL || siz == 0) { - /* XXX */ - siz = sizeof("nobody") - 1; - tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, - bpos); - *tl++ = txdr_unsigned(siz); - bcopy("nobody", tl, siz); - len += NFSX_UNSIGNED + nfsm_rndup(siz); - } else { - tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, - bpos); - *tl++ = txdr_unsigned(siz); - bcopy(name, tl, siz); - len += NFSX_UNSIGNED + nfsm_rndup(siz); - } - FA4_SET(FA4_OWNER, bmvalp); - } - if (vap->va_gid != VNOVAL) { - int error; - char *name; - error = idmap_gid_to_name(vap->va_gid, &name, &siz); - if (error || name == NULL || siz == 0) { - /* XXX */ - siz = sizeof("nogroup") - 1; - tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, - bpos); - *tl++ = txdr_unsigned(siz); - bcopy("nogroup", tl, siz); - len += NFSX_UNSIGNED + nfsm_rndup(siz); - } else { - tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, - bpos); - *tl++ = txdr_unsigned(siz); - bcopy(name, tl, siz); - len += NFSX_UNSIGNED + nfsm_rndup(siz); - } - FA4_SET(FA4_OWNER_GROUP, bmvalp); - } - if (vap->va_atime.tv_sec != VNOVAL) { - uint64_t val = vap->va_atime.tv_sec; - tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos); - FA4_SET(FA4_TIME_ACCESS_SET, bmvalp); - *tl++ = txdr_unsigned(THCLIENTTIME); - txdr_hyper(val, tl); tl += 2; - *tl++ = txdr_unsigned(vap->va_atime.tv_nsec); - len += 4 * NFSX_UNSIGNED; - } - if (vap->va_mtime.tv_sec != VNOVAL) { - uint64_t val = vap->va_mtime.tv_sec; - tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos); - FA4_SET(FA4_TIME_MODIFY_SET, bmvalp); - *tl++ = txdr_unsigned(THCLIENTTIME); - txdr_hyper(val, tl); tl += 2; - *tl++ = txdr_unsigned(vap->va_mtime.tv_nsec); - len += 4 * NFSX_UNSIGNED; - } - - bmvalp[0] = txdr_unsigned(bmvalp[0]); - bmvalp[1] = txdr_unsigned(bmvalp[1]); - - *attrlenp = txdr_unsigned(len); - - return (0); -} - -int -nfsm_v4dissect_compound_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos) -{ - uint32_t taglen, t1, *tl; - - tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); - if (tl == NULL) - return (EBADRPC); - - /* Reply status is handled by the RPC code */ - - taglen = fxdr_unsigned(uint32_t, *tl++); - t1 = nfsm_adv_xx(nfsm_rndup(taglen), md, dpos); - if (t1 != 0) - return (EBADRPC); - - tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); - if (tl == NULL) - return (EBADRPC); - - cp->rep_nops = fxdr_unsigned(uint32_t, *tl++); - - return (0); -} - -int -nfsm_v4dissect_simple_xx(struct nfs4_compound *cp, uint32_t op, - uint32_t skipbytes, struct mbuf **md, caddr_t *dpos) -{ - uint32_t t1, dop, status; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &dop, &status); - if (t1 != 0) - return (t1); - - if (dop != op || status != 0) - return (EBADRPC); - - if (skipbytes > 0) - NFSM_ADV(nfsm_rndup(skipbytes)); - - return (0); -} - -int -nfsm_v4dissect_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl; - - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETATTR || - *tl++ != 0) - return (EBADRPC); - - return (nfsm_v4dissect_attrs_xx(&ga->fa, md, dpos)); -} - -int -nfsm_v4dissect_setattr_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos) -{ - uint32_t t1, op, bmlen, status; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status); - if (t1 != 0) - return (t1); - - if (op != NFSV4OP_SETATTR || status != 0) - return (EBADRPC); - - t1 = nfsm_dissectf_xx(md, dpos, "u", &bmlen); - if (t1 != 0) - return (t1); - - return (nfsm_dissectf_xx(md, dpos, "k", bmlen << 2)); -} - -int -nfsm_v4dissect_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl, len, xdrlen; - - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETFH) - return (EBADRPC); - - if (*tl++ != 0) - return (EBADRPC); - - NFSM_DISSECT(NFSX_UNSIGNED); - len = fxdr_unsigned(uint32_t, *tl++); - if (len > NFSX_V4FH) - return (EBADRPC); - - /* XXX integrate this into nfs_mtofh()? */ - - gfh->fh_len = len; - xdrlen = nfsm_rndup(len); - - NFSM_DISSECT(xdrlen); - bcopy(tl, &gfh->fh_val, xdrlen); - - return (0); -} - -int -nfsm_v4dissect_setclientid_xx(struct nfs4_compound *cp, - struct nfs4_oparg_setclientid *sci, struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl; - - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_SETCLIENTID) - return (EBADRPC); - - /* Handle NFS4ERR_CLID_INUSE specially */ - if (*tl++ != 0) - return (EBADRPC); - - NFSM_DISSECT(2 * NFSX_UNSIGNED); - sci->clientid = fxdr_hyper(tl); - - NFSM_DISSECT(nfsm_rndup(NFSX_V4VERF)); - bcopy(tl, sci->verf, NFSX_V4VERF); - - return (0); -} - -int -nfsm_v4dissect_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl, t1; - - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_CLOSE || - *tl++ != 0) - return (EBADRPC); - - /* Copy stateid */ - t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid); - if (t1 != 0) - return (t1); - - return (0); -} - -int -nfsm_v4dissect_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl; - - tl = nfsm_dissect_xx(4 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_ACCESS || - *tl++ != 0) - return (EBADRPC); - - acc->supported = fxdr_unsigned(uint32_t, *tl++); - acc->rmode = fxdr_unsigned(uint32_t, *tl++); - - return (0); -} - -int -nfsm_v4dissect_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl, t1, bmlen, delegtype = ODNONE; - int error = 0; - nfsv4changeinfo cinfo; - struct nfs4_fctx *fcp = op->fcp; - - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN || - *tl++ != 0) - return (EBADRPC); - - t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid); - if (t1 != 0) - return (t1); - - error = nfsm_v4dissect_changeinfo_xx(&cinfo, md, dpos); - if (error != 0) - goto nfsmout; - - NFSM_DISSECT(2 * NFSX_UNSIGNED); - - op->rflags = fxdr_unsigned(uint32_t, *tl++); - bmlen = fxdr_unsigned(uint32_t, *tl++); - if (bmlen > 2) { - error = EBADRPC; - goto nfsmout; - } - - /* Skip */ - NFSM_ADV(nfsm_rndup(bmlen << 2)); - - NFSM_DISSECT(NFSX_UNSIGNED); - delegtype = fxdr_unsigned(uint32_t, *tl++); - switch (delegtype) { - case ODREAD: - case ODWRITE: - printf("nfs4: client delegation not yet supported\n"); - error = EOPNOTSUPP; - goto nfsmout; - break; - case ODNONE: - default: - break; - } - - nfsmout: - return (error); -} - -int -nfsm_v4dissect_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl; - - tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); - if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN_CONFIRM || - *tl++ != 0) - return (EBADRPC); - - return nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, op->fcp->stateid); -} - -int -nfsm_v4dissect_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t op, status, t1; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status); - if (t1 != 0) - return (t1); - - if (op != NFSV4OP_READ || status != 0) - return (EBADRPC); - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &r->eof, &r->retlen); - if (t1 != 0) - return (t1); - - return (nfsm_mbuftouio(md, r->uiop, r->retlen, dpos)); -} - -int -nfsm_v4dissect_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t op, status, t1; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status); - if (t1 != 0) - return (t1); - - if (op != NFSV4OP_WRITE || status != 0) - return (EBADRPC); - - return (nfsm_dissectf_xx(md, dpos, "uuo", &w->retlen, &w->committed, - NFSX_V4VERF, w->wverf)); -} - -int -nfsm_v4dissect_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t t1, op, status; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status); - if (t1 != 0) - return (t1); - - if (op != NFSV4OP_COMMIT || status != 0) - return (EBADRPC); - - return (nfsm_dissectf_xx(md, dpos, "o", NFSX_V4VERF, c->verf)); -} - -int -nfsm_v4dissect_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t t1, *tl, op, status, bmlen; - nfsv4changeinfo ci; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status); - if (t1 != 0) - return (t1); - - if (op != NFSV4OP_CREATE || status != 0) - return (EBADRPC); - - /* Just throw this away for now */ - t1 = nfsm_v4dissect_changeinfo_xx(&ci, md, dpos); - if (t1 != 0) - return (t1); - - /* Throw this away too */ - NFSM_DISSECT(NFSX_UNSIGNED); - bmlen = fxdr_unsigned(uint32_t, *tl++); - NFSM_DISSECT(bmlen * NFSX_UNSIGNED); - tl += bmlen; - - return 0; -} - -int -nfsm_v4dissect_readlink_xx(struct nfs4_compound *cp, struct uio *uiop, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t t1, *tl, op, status, linklen; - - t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status); - if (t1 != 0) - return (t1); - - if (op != NFSV4OP_READLINK || status != 0) - return (EBADRPC); - - /* Do this one manually for careful checking of sizes. */ - NFSM_DISSECT(NFSX_UNSIGNED); - linklen = fxdr_unsigned(uint32_t, *tl++); - if (linklen <= 0) - return (EBADRPC); - - return (nfsm_mbuftouio(md, uiop, MIN(linklen, uiop->uio_resid), dpos)); -} - -int -nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *ci, - struct mbuf **md, caddr_t *dpos) -{ - uint32_t *tl; - - NFSM_DISSECT(5 * NFSX_UNSIGNED); - - ci->ciatomic = fxdr_unsigned(uint32_t, *tl++); - ci->cibefore = fxdr_hyper(tl); tl += 2; - ci->ciafter = fxdr_hyper(tl); tl += 2; - - return (0); -} - -int -nfsm_v4dissect_attrs_xx(struct nfsv4_fattr *fa, struct mbuf **md, caddr_t *dpos) -{ - uint32_t t1, *tl, bmlen, bmval[2], attrlen, len = 0; - - /* Bitmap length + value */ - NFSM_DISSECT(NFSX_UNSIGNED); - - bmlen = fxdr_unsigned(uint32_t, *tl++); - if (bmlen > 2) - return (EBADRPC); - - if (bmlen == 0) - return (0); - - NFSM_DISSECT(nfsm_rndup(bmlen << 2) + NFSX_UNSIGNED); - - bmval[0] = bmlen > 0 ? fxdr_unsigned(uint32_t, *tl++) : 0; - bmval[1] = bmlen > 1 ? fxdr_unsigned(uint32_t, *tl++) : 0; - - /* Attribute length */ - attrlen = fxdr_unsigned(uint32_t, *tl++); - - /* - * XXX check for correct (<=) attributes mask return from - * server. need to pass this in. - */ - - if (FA4_ISSET(FA4_TYPE, bmval)) { - /* overflow check */ - NFSM_DISSECT(NFSX_UNSIGNED); - fa->fa4_type = fxdr_unsigned(uint32_t, *tl++); - fa->fa4_valid |= FA4V_TYPE; - len += NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_CHANGE, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_changeid = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_CHANGEID; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_SIZE, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_size = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_SIZE; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_FSID, bmval)) { - NFSM_DISSECT(4 * NFSX_UNSIGNED); - fa->fa4_fsid_major = fxdr_hyper(tl); tl += 2; - fa->fa4_fsid_minor = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_SIZE; - len += 4 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_LEASE_TIME, bmval)) { - NFSM_DISSECT(NFSX_UNSIGNED); - fa->fa4_lease_time = fxdr_unsigned(uint32_t, *tl++); - fa->fa4_valid |= FA4V_LEASE_TIME; - len += NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_RDATTR_ERROR, bmval)) { - /* ignore for now; we only ask for it so the compound won't fail */ - NFSM_DISSECT(NFSX_UNSIGNED); - tl++; - len += NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_FILEID, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_fileid = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_FILEID; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_FILES_FREE, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_ffree = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_FFREE; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_FILES_TOTAL, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_ftotal = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_FTOTAL; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_MAXFILESIZE, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_maxfilesize = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_MAXFILESIZE; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_MAXNAME, bmval)) { - NFSM_DISSECT(NFSX_UNSIGNED); - fa->fa4_maxname = fxdr_unsigned(uint32_t, *tl++); - fa->fa4_valid |= FA4V_MAXNAME; - len += NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_MAXREAD, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_maxread = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_MAXREAD; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_MAXWRITE, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_maxwrite = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_MAXWRITE; - len += 2 * NFSX_UNSIGNED; - } - - if (FA4_ISSET(FA4_MODE, bmval)) { - NFSM_DISSECT(NFSX_UNSIGNED); - fa->fa4_mode = fxdr_unsigned(mode_t, *tl++); - fa->fa4_valid |= FA4V_MODE; - len += NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_NUMLINKS, bmval)) { - NFSM_DISSECT(NFSX_UNSIGNED); - fa->fa4_nlink = fxdr_unsigned(nlink_t, *tl++); - fa->fa4_valid |= FA4V_NLINK; - len += NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_OWNER, bmval)) { - uint32_t ownerlen; - int error; - - NFSM_DISSECT(NFSX_UNSIGNED); - - ownerlen = fxdr_unsigned(uint32_t, *tl++); - NFSM_DISSECT(nfsm_rndup(ownerlen)); - error = idmap_name_to_uid((char *)tl, ownerlen, &fa->fa4_uid); - if (error) - fa->fa4_uid = -2; - fa->fa4_valid |= FA4V_UID; - len += NFSX_UNSIGNED + nfsm_rndup(ownerlen); - } - if (FA4_ISSET(FA4_OWNER_GROUP, bmval)) { - uint32_t ownergrouplen; - int error; - - NFSM_DISSECT(NFSX_UNSIGNED); - ownergrouplen = fxdr_unsigned(uint32_t, *tl++); - NFSM_DISSECT(nfsm_rndup(ownergrouplen)); - error = idmap_name_to_gid((char *)tl, ownergrouplen, &fa->fa4_gid); - if (error) - fa->fa4_gid = -2; - fa->fa4_valid |= FA4V_GID; - len += NFSX_UNSIGNED + nfsm_rndup(ownergrouplen); - } - if (FA4_ISSET(FA4_RAWDEV, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_rdev_major = fxdr_unsigned(uint32_t, *tl++); - fa->fa4_rdev_minor = fxdr_unsigned(uint32_t, *tl++); - fa->fa4_valid |= FA4V_RDEV; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_SPACE_AVAIL, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_savail = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_SAVAIL; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_SPACE_FREE, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_sfree = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_SFREE; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_SPACE_TOTAL, bmval)) { - NFSM_DISSECT(2 * NFSX_UNSIGNED); - fa->fa4_stotal = fxdr_hyper(tl); - fa->fa4_valid |= FA4V_STOTAL; - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_SPACE_USED, bmval)) { - NFSM_ADV(2 * NFSX_UNSIGNED); - len += 2 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_TIME_ACCESS, bmval)) { - NFSM_MTOTIME(fa->fa4_atime); - fa->fa4_valid |= FA4V_ATIME; - len += 3 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_TIME_CREATE, bmval)) { - NFSM_MTOTIME(fa->fa4_btime); - fa->fa4_valid |= FA4V_BTIME; - len += 3 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_TIME_METADATA, bmval)) { - NFSM_MTOTIME(fa->fa4_ctime); - fa->fa4_valid |= FA4V_CTIME; - len += 3 * NFSX_UNSIGNED; - } - if (FA4_ISSET(FA4_TIME_MODIFY, bmval)) { - NFSM_MTOTIME(fa->fa4_mtime); - fa->fa4_valid |= FA4V_MTIME; - len += 3 * NFSX_UNSIGNED; - } - - if (len != attrlen) - return (EBADRPC); - - return (0); -} diff --git a/sys/nfs4client/nfs4_vfs.h b/sys/nfs4client/nfs4_vfs.h deleted file mode 100644 index 61999ac..0000000 --- a/sys/nfs4client/nfs4_vfs.h +++ /dev/null @@ -1,34 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_vfs.h,v 1.4 2003/11/05 14:59:00 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. - */ - -#ifndef _NFS4CLIENT_NFS4_VFS_H -#define _NFS4CLIENT_NFS4_VFS_H - -void nfs4_vfsop_fsinfo(struct nfsv4_fattr *, struct nfsmount *); -void nfs4_vfsop_statfs(struct nfsv4_fattr *, struct statfs *, struct mount *); - -#endif /* _NFS4CLIENT_NFS4_VFS_H */ diff --git a/sys/nfs4client/nfs4_vfs_subs.c b/sys/nfs4client/nfs4_vfs_subs.c deleted file mode 100644 index 6d667af..0000000 --- a/sys/nfs4client/nfs4_vfs_subs.c +++ /dev/null @@ -1,125 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_vfs_subs.c,v 1.5 2003/11/05 14:59:00 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/systm.h> -#include <sys/kernel.h> -#include <sys/limits.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/module.h> -#include <sys/mount.h> -#include <sys/proc.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/sockio.h> -#include <sys/vnode.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/uma.h> - -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> - -#include <rpc/rpcclnt.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfsclient/nfsmount.h> -#include <nfs/xdr_subs.h> -#include <nfsclient/nfsm_subs.h> -#include <nfsclient/nfsdiskless.h> - -/* NFSv4 */ -#include <nfs4client/nfs4.h> -#include <nfs4client/nfs4m_subs.h> -#include <nfs4client/nfs4_vfs.h> - -#include <nfsclient/nfsnode.h> - -void -nfs4_vfsop_fsinfo(struct nfsv4_fattr *fap, struct nfsmount *nmp) -{ - uint32_t max; - - if (fap->fa4_valid & FA4V_FSID) { - nmp->nm_fsid.val[0] = fap->fa4_fsid_major; - nmp->nm_fsid.val[1] = fap->fa4_fsid_minor; - } - if (fap->fa4_valid & FA4V_MAXREAD) { - max = fap->fa4_maxread; - if (max < nmp->nm_rsize) { - nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); - if (nmp->nm_rsize == 0) - nmp->nm_rsize = max; - } - if (max < nmp->nm_readdirsize) { - nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); - if (nmp->nm_readdirsize == 0) - nmp->nm_readdirsize = max; - } - } - if (fap->fa4_valid & FA4V_MAXWRITE) { - max = fap->fa4_maxwrite; - if (max < nmp->nm_wsize) { - nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); - if (nmp->nm_wsize == 0) - nmp->nm_wsize = max; - } - } - if (fap->fa4_valid & FA4V_LEASE_TIME) - nmp->nm_lease_time = fap->fa4_lease_time; - - /* nmp->nm_flag |= NFSMNT_GOTFSINFO; */ -} - -void -nfs4_vfsop_statfs(struct nfsv4_fattr *fap, struct statfs *sbp, struct mount *mp) -{ - struct nfsmount *nmp = VFSTONFS(mp); - - sbp->f_iosize = nfs_iosize(nmp); - sbp->f_bsize = NFS_FABLKSIZE; - - if (fap->fa4_valid & FA4V_FSID) { - sbp->f_fsid.val[0] = fap->fa4_fsid_major; - sbp->f_fsid.val[1] = fap->fa4_fsid_minor; - } - - sbp->f_ffree = fap->fa4_valid & FA4V_FFREE ? fap->fa4_ffree : 0; - /* sbp->f_ftotal = fa->fa4_valid & FA4_FTOTAL ? fa->fa4_ftotal : 0; */ - sbp->f_bavail = fap->fa4_valid & FA4V_SAVAIL ? - fap->fa4_savail / NFS_FABLKSIZE : 500000; - sbp->f_bfree = fap->fa4_valid & FA4V_SFREE ? - fap->fa4_sfree / NFS_FABLKSIZE : 500000; - sbp->f_blocks = fap->fa4_valid & FA4V_STOTAL ? - fap->fa4_stotal / NFS_FABLKSIZE : 1000000; -} diff --git a/sys/nfs4client/nfs4_vfsops.c b/sys/nfs4client/nfs4_vfsops.c deleted file mode 100644 index 808b63d..0000000 --- a/sys/nfs4client/nfs4_vfsops.c +++ /dev/null @@ -1,886 +0,0 @@ -/* $Id: nfs_vfsops.c,v 1.38 2003/11/05 14:59:01 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. - */ - -/*- - * Copyright (c) 1989, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_bootp.h" -#include "opt_nfsroot.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/limits.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/module.h> -#include <sys/mount.h> -#include <sys/proc.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/sockio.h> -#include <sys/sysctl.h> -#include <sys/unistd.h> -#include <sys/vnode.h> -#include <sys/signalvar.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/uma.h> - -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_var.h> - -#include <rpc/rpcclnt.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfs4client/nfs4.h> -#include <nfsclient/nfsnode.h> -#include <nfsclient/nfsmount.h> -#include <nfs/xdr_subs.h> -#include <nfsclient/nfsm_subs.h> -#include <nfsclient/nfsdiskless.h> - -#include <nfs4client/nfs4m_subs.h> -#include <nfs4client/nfs4_vfs.h> - -#include <nfs4client/nfs4_dev.h> -#include <nfs4client/nfs4_idmap.h> - -SYSCTL_NODE(_vfs, OID_AUTO, nfs4, CTLFLAG_RW, 0, "NFS4 filesystem"); -SYSCTL_STRUCT(_vfs_nfs4, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, - &nfsstats, nfsstats, "S,nfsstats"); - -static void nfs4_decode_args(struct nfsmount *nmp, struct nfs_args *argp); -static void nfs4_daemon(void *arg); -static int mountnfs(struct nfs_args *, struct mount *, - struct sockaddr *, char *, struct vnode **, - struct ucred *cred); -static int nfs4_do_setclientid(struct nfsmount *nmp, struct ucred *cred); -static vfs_mount_t nfs4_mount; -static vfs_cmount_t nfs4_cmount; -static vfs_unmount_t nfs4_unmount; -static vfs_root_t nfs4_root; -static vfs_statfs_t nfs4_statfs; -static vfs_sync_t nfs4_sync; - -static int fake_wchan; - -/* - * nfs vfs operations. - */ -static struct vfsops nfs4_vfsops = { - .vfs_init = nfs4_init, - .vfs_mount = nfs4_mount, - .vfs_cmount = nfs4_cmount, - .vfs_root = nfs4_root, - .vfs_statfs = nfs4_statfs, - .vfs_sync = nfs4_sync, - .vfs_uninit = nfs4_uninit, - .vfs_unmount = nfs4_unmount, -}; -VFS_SET(nfs4_vfsops, nfs4, VFCF_NETWORK); - -static struct nfs_rpcops nfs4_rpcops = { - nfs4_readrpc, - nfs4_writerpc, - nfs4_writebp, - nfs4_readlinkrpc, - nfs4_invaldir, - nfs4_commit, -}; - -/* So that loader and kldload(2) can find us, wherever we are.. */ -MODULE_VERSION(nfs4, 1); - -void nfsargs_ntoh(struct nfs_args *); - -int -nfs4_init(struct vfsconf *vfsp) -{ - - rpcclnt_init(); - nfs4dev_init(); - idmap_init(); - nfsm_v4init(); - - return (0); -} - -int -nfs4_uninit(struct vfsconf *vfsp) -{ - - rpcclnt_uninit(); - nfs4dev_uninit(); - idmap_uninit(); - - return (0); -} - -/* - * nfs statfs call - */ -static int -nfs4_statfs(struct mount *mp, struct statfs *sbp) -{ - struct vnode *vp; - struct thread *td; - struct nfs_statfs *sfp; - caddr_t bpos, dpos; - struct nfsmount *nmp = VFSTONFS(mp); - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfsnode *np; - struct nfs4_compound cp; - struct nfs4_oparg_getattr ga; - struct nfsv4_fattr *fap = &ga.fa; - - td = curthread; -#ifndef nolint - sfp = NULL; -#endif - error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE); - if (error) - return (error); - vp = NFSTOV(np); - nfsstats.rpccnt[NFSPROC_FSSTAT]++; - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, NFSX_FH(1)); - mb = mreq; - bpos = mtod(mb, caddr_t); - - ga.bm = &nfsv4_fsattrbm; - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "statfs()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_getattr(&cp, &ga); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, td, td->td_ucred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_getattr(&cp, &ga); - - nfs4_vfsop_statfs(fap, sbp, mp); - -nfsmout: - error = nfs_v4postop(&cp, error); - - vput(vp); - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -static void -nfs4_decode_args(struct nfsmount *nmp, struct nfs_args *argp) -{ - int s; - int adjsock; - int maxio; - - s = splnet(); - - /* - * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes - * no sense in that context. Also, set appropriate retransmit - * and soft timeout behavior. - */ - if (argp->sotype == SOCK_STREAM) { - nmp->nm_flag &= ~NFSMNT_NOCONN; - nmp->nm_flag |= NFSMNT_DUMBTIMR; - nmp->nm_timeo = NFS_MAXTIMEO; - nmp->nm_retry = NFS_RETRANS_TCP; - } - - nmp->nm_flag &= ~NFSMNT_RDIRPLUS; - - /* Re-bind if rsrvd port requested and wasn't on one */ - adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT) - && (argp->flags & NFSMNT_RESVPORT); - /* Also re-bind if we're switching to/from a connected UDP socket */ - adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) != - (argp->flags & NFSMNT_NOCONN)); - - /* Update flags atomically. Don't change the lock bits. */ - nmp->nm_flag = argp->flags | nmp->nm_flag; - splx(s); - - if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { - nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; - if (nmp->nm_timeo < NFS_MINTIMEO) - nmp->nm_timeo = NFS_MINTIMEO; - else if (nmp->nm_timeo > NFS_MAXTIMEO) - nmp->nm_timeo = NFS_MAXTIMEO; - } - - if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { - nmp->nm_retry = argp->retrans; - if (nmp->nm_retry > NFS_MAXREXMIT) - nmp->nm_retry = NFS_MAXREXMIT; - } - - if (argp->flags & NFSMNT_NFSV3) { - if (argp->sotype == SOCK_DGRAM) - maxio = NFS_MAXDGRAMDATA; - else - maxio = NFS_MAXDATA; - } else - maxio = NFS_V2MAXDATA; - - if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { - nmp->nm_wsize = argp->wsize; - /* Round down to multiple of blocksize */ - nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); - if (nmp->nm_wsize <= 0) - nmp->nm_wsize = NFS_FABLKSIZE; - } - if (nmp->nm_wsize > maxio) - nmp->nm_wsize = maxio; - if (nmp->nm_wsize > MAXBSIZE) - nmp->nm_wsize = MAXBSIZE; - - if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { - nmp->nm_rsize = argp->rsize; - /* Round down to multiple of blocksize */ - nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); - if (nmp->nm_rsize <= 0) - nmp->nm_rsize = NFS_FABLKSIZE; - } - if (nmp->nm_rsize > maxio) - nmp->nm_rsize = maxio; - if (nmp->nm_rsize > MAXBSIZE) - nmp->nm_rsize = MAXBSIZE; - - if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { - nmp->nm_readdirsize = argp->readdirsize; - } - if (nmp->nm_readdirsize > maxio) - nmp->nm_readdirsize = maxio; - if (nmp->nm_readdirsize > nmp->nm_rsize) - nmp->nm_readdirsize = nmp->nm_rsize; - - if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0) - nmp->nm_acregmin = argp->acregmin; - else - nmp->nm_acregmin = NFS_MINATTRTIMO; - if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0) - nmp->nm_acregmax = argp->acregmax; - else - nmp->nm_acregmax = NFS_MAXATTRTIMO; - if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0) - nmp->nm_acdirmin = argp->acdirmin; - else - nmp->nm_acdirmin = NFS_MINDIRATTRTIMO; - if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0) - nmp->nm_acdirmax = argp->acdirmax; - else - nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO; - if (nmp->nm_acdirmin > nmp->nm_acdirmax) - nmp->nm_acdirmin = nmp->nm_acdirmax; - if (nmp->nm_acregmin > nmp->nm_acregmax) - nmp->nm_acregmin = nmp->nm_acregmax; - - if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) { - if (argp->maxgrouplist <= NFS_MAXGRPS) - nmp->nm_numgrps = argp->maxgrouplist; - else - nmp->nm_numgrps = NFS_MAXGRPS; - } - if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) { - if (argp->readahead <= NFS_MAXRAHEAD) - nmp->nm_readahead = argp->readahead; - else - nmp->nm_readahead = NFS_MAXRAHEAD; - } - if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) { - if (argp->deadthresh <= NFS_MAXDEADTHRESH) - nmp->nm_deadthresh = argp->deadthresh; - else - nmp->nm_deadthresh = NFS_MAXDEADTHRESH; - } - - adjsock |= ((nmp->nm_sotype != argp->sotype) || - (nmp->nm_soproto != argp->proto)); - nmp->nm_sotype = argp->sotype; - nmp->nm_soproto = argp->proto; - - if (nmp->nm_rpcclnt.rc_so && adjsock) { - nfs_safedisconnect(nmp); - if (nmp->nm_sotype == SOCK_DGRAM) { - while (nfs4_connect(nmp)) { - printf("nfs4_decode_args: retrying connect\n"); - (void)tsleep(&fake_wchan, PSOCK, "nfscon", hz); - } - } - } -} - -/* - * VFS Operations. - * - * mount system call - * It seems a bit dumb to copyinstr() the host and path here and then - * bcopy() them in mountnfs(), but I wanted to detect errors before - * doing the sockargs() call because sockargs() allocates an mbuf and - * an error after that means that I have to release the mbuf. - */ -/* ARGSUSED */ -static int -nfs4_cmount(struct mntarg *ma, void *data, int flags) -{ - struct nfs_args args; - int error; - - error = copyin(data, &args, sizeof(struct nfs_args)); - if (error) - return (error); - ma = mount_arg(ma, "nfs_args", &args, sizeof args); - error = kernel_mount(ma, flags); - return (error); -} - -static int -nfs4_mount(struct mount *mp) -{ - int error; - struct nfs_args args; - struct sockaddr *nam; - struct vnode *vp; - char hst[MNAMELEN]; - size_t len; - - if (mp->mnt_flag & MNT_ROOTFS) { - printf("nfs4_mountroot not supported\n"); - return (EINVAL); - } - error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, sizeof args); - if (error) - return (error); - - if (args.version != NFS_ARGSVERSION) - return (EPROGMISMATCH); - if (mp->mnt_flag & MNT_UPDATE) { - struct nfsmount *nmp = VFSTONFS(mp); - - if (nmp == NULL) - return (EIO); - /* - * When doing an update, we can't change from or to - * v3, switch lockd strategies or change cookie translation - */ - args.flags = (args.flags & - ~(NFSMNT_NFSV3 | NFSMNT_NFSV4 | NFSMNT_NOLOCKD)) | - (nmp->nm_flag & - (NFSMNT_NFSV3 | NFSMNT_NFSV4 | NFSMNT_NOLOCKD)); - nfs4_decode_args(nmp, &args); - return (0); - } - - error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); - if (error) - return (error); - bzero(&hst[len], MNAMELEN - len); - /* sockargs() call must be after above copyin() calls */ - error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen); - if (error) - return (error); - error = mountnfs(&args, mp, nam, hst, &vp, curthread->td_ucred); - return (error); -} - -/* - * renew should be done async - * should re-scan mount queue each time - */ -struct proc *nfs4_daemonproc; - -static int -nfs4_do_renew(struct nfsmount *nmp, struct ucred *cred) -{ - struct nfs4_compound cp; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - caddr_t bpos, dpos; - int error; - - mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, sizeof(uint64_t)); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_do_renew()"); - nfsm_v4build_renew(&cp, nmp->nm_clientid); - nfsm_v4build_finalize(&cp); - - nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_renew(&cp); - nmp->nm_last_renewal = time_second; - return (0); - - nfsmout: - error = nfs_v4postop(&cp, error); - - /* XXX */ - if (mrep != NULL) - m_freem(mrep); - return (error); -} - -static void -nfs4_daemon(void *arg) -{ - struct mount *mp; - struct nfsmount *nmp; - int nmounts; - - while (1) { - nmounts = 0; - mtx_lock(&mountlist_mtx); - TAILQ_FOREACH(mp, &mountlist, mnt_list) { - if (strcmp(mp->mnt_vfc->vfc_name, "nfs4") != 0) - continue; - nmounts++; - nmp = VFSTONFS(mp); - if (time_second < nmp->nm_last_renewal + nmp->nm_lease_time - 4) - continue; - mtx_unlock(&mountlist_mtx); - mtx_lock(&Giant); - nfs4_do_renew(nmp, (struct ucred *) arg); - mtx_unlock(&Giant); - mtx_lock(&mountlist_mtx); - } - mtx_unlock(&mountlist_mtx); - - /* Must kill the daemon here, or module unload will cause a panic */ - if (nmounts == 0) { - mtx_lock(&Giant); - nfs4_daemonproc = NULL; - mtx_unlock(&Giant); - /*printf("nfsv4 renewd exiting\n");*/ - kproc_exit(0); - } - tsleep(&nfs4_daemonproc, PVFS, "nfs4", 2 * hz); - } -} - -/* - * Common code for mount and mountroot - */ -static int -mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, - char *hst, struct vnode **vpp, struct ucred *cred) -{ - struct nfsmount *nmp; - char *rpth, *cp1, *cp2; - int nlkup = 0, error; - struct nfs4_compound cp; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - caddr_t bpos, dpos; - struct nfs4_oparg_lookup lkup; - struct nfs4_oparg_getfh gfh; - struct nfs4_oparg_getattr ga; - struct thread *td = curthread; /* XXX */ - - if (mp->mnt_flag & MNT_UPDATE) { - nmp = VFSTONFS(mp); - /* update paths, file handles, etc, here XXX */ - free(nam, M_SONAME); - return (0); - } else { - nmp = uma_zalloc(nfsmount_zone, M_WAITOK); - bzero((caddr_t)nmp, sizeof (struct nfsmount)); - TAILQ_INIT(&nmp->nm_bufq); - mp->mnt_data = nmp; - } - - vfs_getnewfsid(mp); - nmp->nm_mountp = mp; - mtx_init(&nmp->nm_mtx, "NFS4mount lock", NULL, MTX_DEF); - - nmp->nm_maxfilesize = 0xffffffffLL; - nmp->nm_timeo = NFS_TIMEO; - nmp->nm_retry = NFS_RETRANS; - nmp->nm_wsize = NFS_WSIZE; - nmp->nm_rsize = NFS_RSIZE; - nmp->nm_readdirsize = NFS_READDIRSIZE; - nmp->nm_numgrps = NFS_MAXGRPS; - nmp->nm_readahead = NFS_DEFRAHEAD; - nmp->nm_deadthresh = NFS_MAXDEADTHRESH; - vfs_mountedfrom(mp, hst); - nmp->nm_nam = nam; - /* Set up the sockets and per-host congestion */ - nmp->nm_sotype = argp->sotype; - nmp->nm_soproto = argp->proto; - nmp->nm_rpcops = &nfs4_rpcops; - /* XXX */ - mp->mnt_stat.f_iosize = PAGE_SIZE; - - argp->flags |= (NFSMNT_NFSV3 | NFSMNT_NFSV4); - - nfs4_decode_args(nmp, argp); - - if ((error = nfs4_connect(nmp))) - goto bad; - - mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1)); - mb = mreq; - bpos = mtod(mb, caddr_t); - - ga.bm = &nfsv4_fsinfobm; - nfs_v4initcompound(&cp); - - /* Get remote path */ - rpth = hst; - strsep(&rpth, ":"); - - nfsm_v4build_compound(&cp, "mountnfs()"); - nfsm_v4build_putrootfh(&cp); - for (cp1 = rpth; cp1 && *cp1; cp1 = cp2) { - while (*cp1 == '/') - cp1++; - if (!*cp1) - break; - for (cp2 = cp1; *cp2 && *cp2 != '/'; cp2++) - ; - lkup.name = cp1; - lkup.namelen = cp2 - cp1; - nfsm_v4build_lookup(&cp, &lkup); - nlkup++; - } - nfsm_v4build_getfh(&cp, &gfh); - nfsm_v4build_getattr(&cp, &ga); - nfsm_v4build_finalize(&cp); - - nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putrootfh(&cp); - while (nlkup--) - nfsm_v4dissect_lookup(&cp); - nfsm_v4dissect_getfh(&cp, &gfh); - nfsm_v4dissect_getattr(&cp, &ga); - - nfs4_vfsop_fsinfo(&ga.fa, nmp); - nmp->nm_state |= NFSSTA_GOTFSINFO; - - /* Copy root fh into nfsmount. */ - nmp->nm_fhsize = gfh.fh_len; - bcopy(&gfh.fh_val, nmp->nm_fh, nmp->nm_fhsize); - nmp->nm_last_renewal = time_second; - - if ((error = nfs4_do_setclientid(nmp, cred)) != 0) - goto nfsmout; - - /* Start renewd if it isn't already running */ - if (nfs4_daemonproc == NULL) - kproc_create(nfs4_daemon, crdup(cred), &nfs4_daemonproc, - (RFPROC|RFMEM), 0, "nfs4rd"); - - return (0); - nfsmout: - error = nfs_v4postop(&cp, error); - - /* XXX */ - if (mrep != NULL) - m_freem(mrep); -bad: - mtx_destroy(&nmp->nm_mtx); - nfs4_disconnect(nmp); - uma_zfree(nfsmount_zone, nmp); - free(nam, M_SONAME); - - return (error); -} - -/* - * unmount system call - */ -static int -nfs4_unmount(struct mount *mp, int mntflags) -{ - struct nfsmount *nmp; - int error, flags = 0; - - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - nmp = VFSTONFS(mp); - /* - * Goes something like this.. - * - Call vflush to clear out vnodes for this filesystem - * - Close the socket - * - Free up the data structures - */ - /* In the forced case, cancel any outstanding requests. */ - if (flags & FORCECLOSE) { - error = nfs_nmcancelreqs(nmp); - if (error) - return (error); - nfs4dev_purge(); - } - - error = vflush(mp, 0, flags, curthread); - if (error) - return (error); - - /* - * We are now committed to the unmount. - */ - nfs4_disconnect(nmp); - free(nmp->nm_nam, M_SONAME); - - /* XXX there's a race condition here for SMP */ - wakeup(&nfs4_daemonproc); - - mtx_destroy(&nmp->nm_mtx); - uma_zfree(nfsmount_zone, nmp); - return (0); -} - -/* - * Return root of a filesystem - */ -static int -nfs4_root(struct mount *mp, int flags, struct vnode **vpp) -{ - struct vnode *vp; - struct nfsmount *nmp; - struct nfsnode *np; - int error; - - nmp = VFSTONFS(mp); - error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, - LK_EXCLUSIVE); - if (error) - return (error); - vp = NFSTOV(np); - if (vp->v_type == VNON) - vp->v_type = VDIR; - vp->v_vflag |= VV_ROOT; - *vpp = vp; - - return (0); -} - -/* - * Flush out the buffer cache - */ -static int -nfs4_sync(struct mount *mp, int waitfor) -{ - struct vnode *vp, *mvp; - struct thread *td; - int error, allerror = 0; - - td = curthread; - - /* - * Force stale buffer cache information to be flushed. - */ - MNT_ILOCK(mp); -loop: - MNT_VNODE_FOREACH(vp, mp, mvp) { - VI_LOCK(vp); - MNT_IUNLOCK(mp); - /* XXX racy bv_cnt check. */ - if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 || - waitfor == MNT_LAZY) { - VI_UNLOCK(vp); - MNT_ILOCK(mp); - continue; - } - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { - MNT_ILOCK(mp); - MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); - goto loop; - } - error = VOP_FSYNC(vp, waitfor, td); - if (error) - allerror = error; - VOP_UNLOCK(vp, 0); - vrele(vp); - - MNT_ILOCK(mp); - } - MNT_IUNLOCK(mp); - return (allerror); -} - -static int -nfs4_do_setclientid(struct nfsmount *nmp, struct ucred *cred) -{ - struct nfs4_oparg_setclientid scid; - struct nfs4_compound cp; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - caddr_t bpos, dpos; - struct route ro; - char *ipsrc = NULL, uaddr[24], name[24]; - int try = 0; - static unsigned long seq; - int error; - -#ifndef NFS4_USE_RPCCLNT - return (0); -#endif - if (nmp->nm_clientid) { - printf("nfs4_do_setclientid: already have clientid!\n"); - error = 0; - goto nfsmout; - } - - /* Try not to re-use clientids */ - if (seq == 0) - seq = time_second; - -#ifdef NFS4_USE_RPCCLNT - scid.cb_netid = (nmp->nm_rpcclnt.rc_sotype == SOCK_STREAM) ? "tcp" : "udp"; -#endif - scid.cb_netid = "tcp"; - scid.cb_netidlen = 3; - scid.cb_prog = 0x1234; /* XXX */ - - /* Do a route lookup to find our source address for talking to this server */ - bzero(&ro, sizeof ro); - -#ifdef NFS4_USE_RPCCLNT - ro.ro_dst = *nmp->nm_rpcclnt.rc_name; -#endif -/* XXX MRT NFS uses table 0 */ - in_rtalloc(&ro, 0); - if (ro.ro_rt == NULL) { - error = EHOSTUNREACH; - goto nfsmout; - } - ipsrc = inet_ntoa(IA_SIN(ifatoia(ro.ro_rt->rt_ifa))->sin_addr); - sprintf(uaddr, "%s.12.48", ipsrc); - scid.cb_univaddr = uaddr; - scid.cb_univaddrlen = strlen(uaddr); - RTFREE(ro.ro_rt); - - try_again: - sprintf(name, "%s-%d", ipsrc, (int) ((seq + try) % 1000000L)); - scid.namelen = strlen(name); - scid.name = name; - nfs_v4initcompound(&cp); - - mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1)); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_do_setclientid()"); - nfsm_v4build_setclientid(&cp, &scid); - nfsm_v4build_finalize(&cp); - - nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_setclientid(&cp, &scid); - nmp->nm_clientid = scid.clientid; - - error = nfs_v4postop(&cp, error); - - /* Confirm */ - m_freem(mrep); - mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1)); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_do_setclientid() (confirm)"); - nfsm_v4build_setclientid_confirm(&cp, &scid); - nfsm_v4build_finalize(&cp); - - nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_setclientid_confirm(&cp); - - nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep) - m_freem(mrep); - if (error == NFSERR_CLID_INUSE && (++try < NFS4_SETCLIENTID_MAXTRIES)) - goto try_again; - - return (error); -} diff --git a/sys/nfs4client/nfs4_vn.h b/sys/nfs4client/nfs4_vn.h deleted file mode 100644 index 2f5f730..0000000 --- a/sys/nfs4client/nfs4_vn.h +++ /dev/null @@ -1,33 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_vn.h,v 1.5 2003/11/05 14:59:00 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. - */ - -#ifndef _NFS4CLIENT_NFS4_VFS_H -#define _NFS4CLIENT_NFS4_VFS_H - -void nfs4_vnop_loadattrcache(struct vnode *, struct nfsv4_fattr *, struct vattr *); - -#endif /* _NFS4CLIENT_NFS4_VFS_H */ diff --git a/sys/nfs4client/nfs4_vn_subs.c b/sys/nfs4client/nfs4_vn_subs.c deleted file mode 100644 index 12095d0..0000000 --- a/sys/nfs4client/nfs4_vn_subs.c +++ /dev/null @@ -1,225 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4_vn_subs.c,v 1.9 2003/11/05 14:59:00 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/systm.h> -#include <sys/kernel.h> -#include <sys/limits.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/module.h> -#include <sys/mount.h> -#include <sys/proc.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/sockio.h> -#include <sys/vnode.h> -#include <sys/types.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/uma.h> - -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> - -#include <rpc/rpcclnt.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfsclient/nfsmount.h> -#include <nfs/xdr_subs.h> -#include <nfsclient/nfsm_subs.h> -#include <nfsclient/nfsdiskless.h> - -/* NFSv4 */ -#include <nfs4client/nfs4.h> -#include <nfs4client/nfs4m_subs.h> -#include <nfs4client/nfs4_vn.h> - -#include <nfsclient/nfsnode.h> - -void -nfs4_vnop_loadattrcache(struct vnode *vp, struct nfsv4_fattr *fap, - struct vattr *vaper) -{ - struct vattr *vap; - struct nfsnode *np; - int32_t rdev; - enum vtype vtyp; - u_short vmode; - struct timespec mtime; - struct timeval tv; - - microtime(&tv); - - vtyp = nv3tov_type[fap->fa4_type & 0x7]; - vmode = (fap->fa4_valid & FA4V_MODE) ? fap->fa4_mode : 0777; - rdev = (fap->fa4_valid & FA4V_RDEV) ? - makedev(fap->fa4_rdev_major, fap->fa4_rdev_minor) : 0; - if (fap->fa4_valid & FA4V_MTIME) - mtime = fap->fa4_mtime; - else - bzero(&mtime, sizeof mtime); - - /* - * If v_type == VNON it is a new node, so fill in the v_type, - * n_mtime fields. Check to see if it represents a special - * device, and if so, check for a possible alias. Once the - * correct vnode has been obtained, fill in the rest of the - * information. - */ - np = VTONFS(vp); - vap = &np->n_vattr; - if (vp->v_type != vtyp || np->n_mtime.tv_sec == 0) { - bzero(vap, sizeof *vap); - vp->v_type = vtyp; - np->n_mtime.tv_sec = mtime.tv_sec; - } - vap->va_type = vtyp; - vap->va_mode = (vmode & 07777); - vap->va_rdev = rdev; - vap->va_mtime = mtime; - vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; - if (fap->fa4_valid & FA4V_NLINK) - vap->va_nlink = fap->fa4_nlink; - if (fap->fa4_valid & FA4V_UID) - vap->va_uid = fap->fa4_uid; - if (fap->fa4_valid & FA4V_GID) - vap->va_gid = fap->fa4_gid; - vap->va_size = fap->fa4_size; - vap->va_blocksize = NFS_FABLKSIZE; - vap->va_bytes = fap->fa4_size; - if (fap->fa4_valid & FA4V_FILEID) - vap->va_fileid = nfs_v4fileid4_to_fileid(fap->fa4_fileid); - if (fap->fa4_valid & FA4V_ATIME) - vap->va_atime = fap->fa4_atime; - if (fap->fa4_valid & FA4V_BTIME) - vap->va_birthtime = fap->fa4_btime; - if (fap->fa4_valid & FA4V_CTIME) - vap->va_ctime = fap->fa4_ctime; - vap->va_flags = 0; - vap->va_filerev = 0; - /* XXX dontshrink flag? */ - if (vap->va_size != np->n_size) { - if (vap->va_type == VREG) { - if (np->n_flag & NMODIFIED) { - if (vap->va_size < np->n_size) - vap->va_size = np->n_size; - else - np->n_size = vap->va_size; - } else - np->n_size = vap->va_size; - vnode_pager_setsize(vp, np->n_size); - } else - np->n_size = vap->va_size; - } - np->n_attrstamp = tv.tv_sec; - if (vaper != NULL) { - bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap)); - if (np->n_flag & NCHG) { - if (np->n_flag & NACC) - vaper->va_atime = np->n_atim; - if (np->n_flag & NUPD) - vaper->va_mtime = np->n_mtim; - } - } -} - -static uint64_t nfs_nullcookie = 0; -/* - * This function finds the directory cookie that corresponds to the - * logical byte offset given. - */ -uint64_t * -nfs4_getcookie(struct nfsnode *np, off_t off, int add) -{ - struct nfsdmap *dp, *dp2; - int pos; - - pos = (uoff_t)off / NFS_DIRBLKSIZ; - if (pos == 0 || off < 0) { -#ifdef DIAGNOSTIC - if (add) - panic("nfs getcookie add at <= 0"); -#endif - return (&nfs_nullcookie); - } - pos--; - dp = LIST_FIRST(&np->n_cookies); - if (!dp) { - if (add) { - dp = malloc(sizeof (struct nfsdmap), - M_NFSDIROFF, M_WAITOK); - dp->ndm_eocookie = 0; - LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); - } else - return (NULL); - } - while (pos >= NFSNUMCOOKIES) { - pos -= NFSNUMCOOKIES; - if (LIST_NEXT(dp, ndm_list)) { - if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && - pos >= dp->ndm_eocookie) - return (NULL); - dp = LIST_NEXT(dp, ndm_list); - } else if (add) { - dp2 = malloc(sizeof (struct nfsdmap), - M_NFSDIROFF, M_WAITOK); - dp2->ndm_eocookie = 0; - LIST_INSERT_AFTER(dp, dp2, ndm_list); - dp = dp2; - } else - return (NULL); - } - if (pos >= dp->ndm_eocookie) { - if (add) - dp->ndm_eocookie = pos + 1; - else - return (NULL); - } - return (&dp->ndm4_cookies[pos]); -} - -/* - * Invalidate cached directory information, except for the actual directory - * blocks (which are invalidated separately). - * Done mainly to avoid the use of stale offset cookies. - */ -void -nfs4_invaldir(struct vnode *vp) -{ - struct nfsnode *np = VTONFS(vp); - - np->n_direofoffset = 0; - bzero(np->n4_cookieverf, NFSX_V4VERF); - if (LIST_FIRST(&np->n_cookies)) - LIST_FIRST(&np->n_cookies)->ndm_eocookie = 0; -} diff --git a/sys/nfs4client/nfs4_vnops.c b/sys/nfs4client/nfs4_vnops.c deleted file mode 100644 index af85494..0000000 --- a/sys/nfs4client/nfs4_vnops.c +++ /dev/null @@ -1,2931 +0,0 @@ -/* $Id: nfs_vnops.c,v 1.45 2003/11/05 14:59:02 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. - */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * vnode op calls for Sun NFS version 2 and 3 - */ - -#include "opt_inet.h" - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#include <sys/resourcevar.h> -#include <sys/proc.h> -#include <sys/mount.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/namei.h> -#include <sys/socket.h> -#include <sys/vnode.h> -#include <sys/dirent.h> -#include <sys/fcntl.h> -#include <sys/lockf.h> -#include <sys/stat.h> -#include <sys/sysctl.h> -#include <sys/lockmgr.h> -#include <sys/signalvar.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> - -#include <fs/fifofs/fifo.h> - -#include <rpc/rpcclnt.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfs4client/nfs4.h> -#include <nfsclient/nfsnode.h> -#include <nfsclient/nfsmount.h> -#include <nfsclient/nfs_lock.h> -#include <nfs/xdr_subs.h> -#include <nfsclient/nfsm_subs.h> - -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_var.h> - -/* NFSv4 */ -#include <nfs4client/nfs4m_subs.h> -#include <nfs4client/nfs4_vn.h> - -/* Defs */ -#define TRUE 1 -#define FALSE 0 - -/* - * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these - * calls are not in getblk() and brelse() so that they would not be necessary - * here. - */ -#ifndef B_VMIO -#define vfs_busy_pages(bp, f) -#endif - -static int nfs4_flush(struct vnode *, int, struct thread *, - int); -static int nfs4_setattrrpc(struct vnode *, struct vattr *, struct ucred *); -static int nfs4_closerpc(struct vnode *, struct ucred *, int); - -static vop_lookup_t nfs4_lookup; -static vop_create_t nfs4_create; -static vop_mknod_t nfs4_mknod; -static vop_open_t nfs4_open; -static vop_close_t nfs4_close; -static vop_access_t nfs4_access; -static vop_getattr_t nfs4_getattr; -static vop_setattr_t nfs4_setattr; -static vop_read_t nfs4_read; -static vop_fsync_t nfs4_fsync; -static vop_remove_t nfs4_remove; -static vop_link_t nfs4_link; -static vop_rename_t nfs4_rename; -static vop_mkdir_t nfs4_mkdir; -static vop_rmdir_t nfs4_rmdir; -static vop_symlink_t nfs4_symlink; -static vop_readdir_t nfs4_readdir; -static vop_strategy_t nfs4_strategy; -static int nfs4_lookitup(struct vnode *, const char *, int, - struct ucred *, struct thread *, struct nfsnode **); -static int nfs4_sillyrename(struct vnode *, struct vnode *, - struct componentname *); -static vop_readlink_t nfs4_readlink; -static vop_print_t nfs4_print; -static vop_advlock_t nfs4_advlock; -static vop_advlockasync_t nfs4_advlockasync; - -/* - * Global vfs data structures for nfs - */ -struct vop_vector nfs4_vnodeops = { - .vop_default = &default_vnodeops, - .vop_access = nfs4_access, - .vop_advlock = nfs4_advlock, - .vop_advlockasync = nfs4_advlockasync, - .vop_close = nfs4_close, - .vop_create = nfs4_create, - .vop_fsync = nfs4_fsync, - .vop_getattr = nfs4_getattr, - .vop_getpages = nfs_getpages, - .vop_putpages = nfs_putpages, - .vop_inactive = nfs_inactive, - .vop_link = nfs4_link, - .vop_lookup = nfs4_lookup, - .vop_mkdir = nfs4_mkdir, - .vop_mknod = nfs4_mknod, - .vop_open = nfs4_open, - .vop_print = nfs4_print, - .vop_read = nfs4_read, - .vop_readdir = nfs4_readdir, - .vop_readlink = nfs4_readlink, - .vop_reclaim = nfs_reclaim, - .vop_remove = nfs4_remove, - .vop_rename = nfs4_rename, - .vop_rmdir = nfs4_rmdir, - .vop_setattr = nfs4_setattr, - .vop_strategy = nfs4_strategy, - .vop_symlink = nfs4_symlink, - .vop_write = nfs_write, -}; - -static int nfs4_removerpc(struct vnode *dvp, const char *name, int namelen, - struct ucred *cred, struct thread *td); -static int nfs4_renamerpc(struct vnode *fdvp, const char *fnameptr, - int fnamelen, struct vnode *tdvp, - const char *tnameptr, int tnamelen, - struct ucred *cred, struct thread *td); -static int nfs4_renameit(struct vnode *sdvp, struct componentname *scnp, - struct sillyrename *sp); -static int nfs4_openrpc(struct vnode *, struct vnode **, - struct componentname *, int, struct vattr *); -static int nfs4_open_confirm(struct vnode *vp, struct nfs4_compound *cpp, - struct nfs4_oparg_open *openap, - struct nfs4_oparg_getfh *gfh, - struct ucred *cred, struct thread *td); -static int nfs4_createrpc(struct vnode *, struct vnode **, - struct componentname *, nfstype, - struct vattr *, char *); - -/* - * Global variables - */ -struct nfs4_lowner nfs4_masterlowner; - -#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) - -SYSCTL_DECL(_vfs_nfs4); - -static int nfs4_access_cache_timeout = NFS_MAXATTRTIMO; -SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_timeout, CTLFLAG_RW, - &nfs4_access_cache_timeout, 0, "NFS ACCESS cache timeout"); - -#if 0 -static int nfsv3_commit_on_close = 0; -SYSCTL_INT(_vfs_nfs4, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW, - &nfsv3_commit_on_close, 0, "write+commit on close, else only write"); - -SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_hits, CTLFLAG_RD, - &nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count"); - -SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_misses, CTLFLAG_RD, - &nfsstats.accesscache_misses, 0, "NFS ACCESS cache miss count"); -#endif - -#define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \ - | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \ - | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP) -static int -nfs4_v3_access_otw(struct vnode *vp, int wmode, struct thread *td, - struct ucred *cred, uint32_t *retmode) -{ - const int v3 = 1; - u_int32_t *tl; - int error = 0, attrflag, i, lrupos; - - return (0); - - struct mbuf *mreq, *mrep = NULL, *md, *mb; - caddr_t bpos, dpos; - u_int32_t rmode; - struct nfsnode *np = VTONFS(vp); - - nfsstats.rpccnt[NFSPROC_ACCESS]++; - mreq = nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); - mb = mreq; - bpos = mtod(mb, caddr_t); - nfsm_fhtom(vp, v3); - tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED); - *tl = txdr_unsigned(wmode); - nfsm_request(vp, NFSPROC_ACCESS, td, cred); - nfsm_postop_attr(vp, attrflag); - if (!error) { - lrupos = 0; - tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); - rmode = fxdr_unsigned(u_int32_t, *tl); - for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { - if (np->n_accesscache[i].uid == cred->cr_uid) { - np->n_accesscache[i].mode = rmode; - np->n_accesscache[i].stamp = time_second; - break; - } - if (i > 0 && np->n_accesscache[i].stamp < - np->n_accesscache[lrupos].stamp) - lrupos = i; - } - if (i == NFS_ACCESSCACHESIZE) { - np->n_accesscache[lrupos].uid = cred->cr_uid; - np->n_accesscache[lrupos].mode = rmode; - np->n_accesscache[lrupos].stamp = time_second; - } - if (retmode != NULL) - *retmode = rmode; - } - m_freem(mrep); -nfsmout: - return error; -} - -/* - * nfs access vnode op. - * For nfs version 2, just return ok. File accesses may fail later. - * For nfs version 3, use the access rpc to check accessibility. If file modes - * are changed on the server, accesses might still fail later. - */ -static int -nfs4_access(struct vop_access_args *ap) -{ - struct vnode *vp = ap->a_vp; - int error = 0, i, gotahit; - u_int32_t mode, rmode, wmode; - int v3 = NFS_ISV3(vp); /* v3 \in v4 */ - struct nfsnode *np = VTONFS(vp); - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_compound cp; - struct nfs4_oparg_access acc; - struct thread *td = ap->a_td; - struct ucred *cred = ap->a_cred; - - /* - * Disallow write attempts on filesystems mounted read-only; - * unless the file is a socket, fifo, or a block or character - * device resident on the filesystem. - */ - if ((ap->a_accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { - switch (vp->v_type) { - case VREG: - case VDIR: - case VLNK: - return (EROFS); - default: - break; - } - } - /* - * For nfs v3, check to see if we have done this recently, and if - * so return our cached result instead of making an ACCESS call. - * If not, do an access rpc, otherwise you are stuck emulating - * ufs_access() locally using the vattr. This may not be correct, - * since the server may apply other access criteria such as - * client uid-->server uid mapping that we do not know about. - */ - /* XXX Disable this for now; needs fixing of _access_otw() */ - if (0 && v3) { - if (ap->a_accmode & VREAD) - mode = NFSV3ACCESS_READ; - else - mode = 0; - if (vp->v_type != VDIR) { - if (ap->a_accmode & VWRITE) - mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); - if (ap->a_accmode & VEXEC) - mode |= NFSV3ACCESS_EXECUTE; - } else { - if (ap->a_accmode & VWRITE) - mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | - NFSV3ACCESS_DELETE); - if (ap->a_accmode & VEXEC) - mode |= NFSV3ACCESS_LOOKUP; - } - /* XXX safety belt, only make blanket request if caching */ - if (nfs4_access_cache_timeout > 0) { - wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY | - NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE | - NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP; - } else { - wmode = mode; - } - - /* - * Does our cached result allow us to give a definite yes to - * this request? - */ - gotahit = 0; - for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { - if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) { - if (time_second < (np->n_accesscache[i].stamp + - nfs4_access_cache_timeout) && - (np->n_accesscache[i].mode & mode) == mode) { - nfsstats.accesscache_hits++; - gotahit = 1; - } - break; - } - } - if (gotahit == 0) { - /* - * Either a no, or a don't know. Go to the wire. - */ - nfsstats.accesscache_misses++; - error = nfs4_v3_access_otw(vp, wmode, ap->a_td, - ap->a_cred, &rmode); - if (error == 0) { - if ((rmode & mode) != mode) - error = EACCES; - } - } - return (error); - } - - /* XXX use generic access code here? */ - mode = ap->a_accmode & VREAD ? NFSV4ACCESS_READ : 0; - if (vp->v_type == VDIR) { - if (ap->a_accmode & VWRITE) - mode |= NFSV4ACCESS_MODIFY | NFSV4ACCESS_EXTEND | NFSV4ACCESS_DELETE; - if (ap->a_accmode & VEXEC) - mode |= NFSV4ACCESS_LOOKUP; - } else { - if (ap->a_accmode & VWRITE) - mode |= NFSV4ACCESS_MODIFY | NFSV4ACCESS_EXTEND; - if (ap->a_accmode & VEXEC) - mode |= NFSV4ACCESS_EXECUTE; - } - - nfs_v4initcompound(&cp); - acc.mode = mode; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_access()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_access(&cp, &acc); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_access(&cp, &acc); - - if ((acc.rmode & mode) != mode) - error = EACCES; - - nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -static int -nfs4_openrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, - int flags, struct vattr *vap) -{ - struct vnode *vp = *vpp; - struct nfs4_oparg_getattr getattr; - struct nfs4_oparg_getfh getfh; - struct nfs4_oparg_open opena; - struct nfs4_compound cp; - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - struct nfs4_fctx xfc, *fcp; - struct nfsnode *np; - - if (vp == NULL) { - /* Create a new file */ - np = NULL; - fcp = &xfc; - bzero(fcp, sizeof(*fcp)); - } else { - np = VTONFS(vp); - fcp = flags & FWRITE ? &np->n_wfc : &np->n_rfc; - } - - /* - * Since we are currently only one lockowner; we only open the - * file once each for reading and writing. - */ - if (fcp->refcnt++ != 0) { - *vpp = vp; - /*printf("not opening %s\n", np->n_name != NULL ? np->n_name : "");*/ - return (0); - } - - fcp->lop = &nfs4_masterlowner; - fcp->np = np; - - nfs_v4initcompound(&cp); - cp.nmp = VFSTONFS(dvp->v_mount); - - opena.ctype = NCLNULL; - opena.flags = flags; - opena.vap = vap; - opena.fcp = fcp; /* For lockowner */ - opena.cnp = cnp; - - getattr.bm = &nfsv4_getattrbm; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_openrpc()"); - nfsm_v4build_putfh(&cp, dvp); - nfsm_v4build_open(&cp, &opena); - nfsm_v4build_getattr(&cp, &getattr); - nfsm_v4build_getfh(&cp, &getfh); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp != NULL ? vp : dvp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_open(&cp, &opena); - nfsm_v4dissect_getattr(&cp, &getattr); - nfsm_v4dissect_getfh(&cp, &getfh); - - error = nfs_v4postop(&cp, error); - - if (opena.rflags & NFSV4OPENRES_CONFIRM) { - error = nfs4_open_confirm(vp ? vp : dvp, &cp, &opena, &getfh, cred, td); - if (error != 0) - goto nfsmout; - } - - if (vp == NULL) { - /* New file */ - error = nfs_nget(dvp->v_mount, &getfh.fh_val, - getfh.fh_len, &np, LK_EXCLUSIVE); - if (error != 0) - goto nfsmout; - - vp = NFSTOV(np); - np->n_dvp = dvp; - np->n_namelen = cnp->cn_namelen; /* XXX memory leaks on these; track! */ - if (np->n_name != NULL) - free(np->n_name, M_NFSREQ); - np->n_name = malloc(np->n_namelen + 1, M_NFSREQ, M_WAITOK); - bcopy(cnp->cn_nameptr, np->n_name, np->n_namelen); - np->n_name[np->n_namelen] = '\0'; - if (flags & FWRITE) - np->n_wfc = *fcp; - else - np->n_rfc = *fcp; - - /*printf("opened new file %s\n", np->n_name);*/ - - nfs4_vnop_loadattrcache(vp, &getattr.fa, NULL); - *vpp = vp; - } else { - /*printf("openend \"old\" %s\n", np->n_name != NULL ? np->n_name : "");*/ - - if (flags & O_TRUNC && np->n_size != 0) { - struct vattr va; - - VATTR_NULL(&va); - va.va_size = 0; - error = nfs4_setattrrpc(vp, &va, cnp->cn_cred); - } - np->n_attrstamp = 0; - } - - nfsmout: - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -static int -nfs4_open_confirm(struct vnode *vp, struct nfs4_compound *cpp, - struct nfs4_oparg_open *openap, struct nfs4_oparg_getfh *gfh, - struct ucred *cred, struct thread *td) -{ - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - - nfs_v4initcompound(cpp); - cpp->nmp = VFSTONFS(vp->v_mount); - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(cpp, "nfs4_open_confirm()"); - nfsm_v4build_putfh_nv(cpp, gfh); - nfsm_v4build_open_confirm(cpp, openap); - nfsm_v4build_finalize(cpp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(cpp); - nfsm_v4dissect_putfh(cpp); - nfsm_v4dissect_open_confirm(cpp, openap); - - nfsmout: - error = nfs_v4postop(cpp, error); - - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - - -/* - * nfs open vnode op - * Check to see if the type is ok - * and that deletion is not in progress. - * For paged in text files, you will need to flush the page cache - * if consistency is lost. - */ -/* ARGSUSED */ -static int -nfs4_open(struct vop_open_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - enum vtype vtype = vp->v_type; - int mode = ap->a_mode; - struct componentname cn; - - if (vtype != VREG) { - if (vtype != VDIR && vtype != VLNK) { -#ifdef DIAGNOSTIC - printf("open eacces vtyp=%d\n", vp->v_type); -#endif - return (EACCES); - } else - return (0); - } - - if (np->n_flag & NCREATED) { - np->n_flag &= ~NCREATED; - return (0); - } - - cn.cn_nameptr = np->n_name; - cn.cn_namelen = np->n_namelen; - cn.cn_cred = ap->a_cred; - cn.cn_thread = ap->a_td; - - return (nfs4_openrpc(np->n_dvp, &vp, &cn, mode, NULL)); -} - -static int -nfs4_closerpc(struct vnode *vp, struct ucred *cred, int flags) -{ - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct thread *td; - struct nfs4_fctx *fcp; - struct nfs4_compound cp; - struct nfsnode *np = VTONFS(vp); - - td = curthread; - fcp = flags & FWRITE ? &np->n_wfc : &np->n_rfc; - - nfs_v4initcompound(&cp); - - if (--fcp->refcnt != 0) - return (0); - - /*printf("closing %s\n", np->n_name != NULL ? np->n_name : "");*/ - - cp.fcp = fcp; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_closerpc()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_close(&cp, fcp); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_close(&cp, fcp); - - nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -/* - * nfs close vnode op - * play it safe for now (see comments in v2/v3 nfs_close regarding dirty buffers) - */ -/* ARGSUSED */ -static int -nfs4_close(struct vop_close_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - int error = 0; - - if (vp->v_type != VREG) - return (0); - - if (np->n_flag & NMODIFIED) { - error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1); - np->n_attrstamp = 0; - } - - error = nfs4_closerpc(vp, ap->a_cred, ap->a_fflag); - - if (!error && np->n_flag & NWRITEERR) { - np->n_flag &= ~NWRITEERR; - error = np->n_error; - } - return (error); -} - -/* - * nfs getattr call from vfs. - */ -static int -nfs4_getattr(struct vop_getattr_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_oparg_getattr ga; - struct nfs4_compound cp; - - /* - * Update local times for special files. - */ - if (np->n_flag & (NACC | NUPD)) - np->n_flag |= NCHG; - /* - * First look in the cache. - */ - if (nfs_getattrcache(vp, ap->a_vap) == 0) - return (0); - - nfsstats.rpccnt[NFSPROC_GETATTR]++; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, NFSX_FH(1)); - mb = mreq; - bpos = mtod(mb, caddr_t); - - ga.bm = &nfsv4_getattrbm; - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_getattr()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_getattr(&cp, &ga); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, curthread, ap->a_cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_getattr(&cp, &ga); - - nfs4_vnop_loadattrcache(vp, &ga.fa, ap->a_vap); - -nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - return (error); -} - -/* - * nfs setattr call. - */ -static int -nfs4_setattr(struct vop_setattr_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - struct vattr *vap = ap->a_vap; - struct thread *td = curthread; - int error = 0; - u_quad_t tsize; - -#ifndef nolint - tsize = (u_quad_t)0; -#endif - - /* - * Setting of flags is not supported. - */ - if (vap->va_flags != VNOVAL) - return (EOPNOTSUPP); - - /* - * Disallow write attempts if the filesystem is mounted read-only. - */ - if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || - vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || - vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && - (vp->v_mount->mnt_flag & MNT_RDONLY)) - return (EROFS); - if (vap->va_size != VNOVAL) { - switch (vp->v_type) { - case VDIR: - return (EISDIR); - case VCHR: - case VBLK: - case VSOCK: - case VFIFO: - if (vap->va_mtime.tv_sec == VNOVAL && - vap->va_atime.tv_sec == VNOVAL && - vap->va_mode == (mode_t)VNOVAL && - vap->va_uid == (uid_t)VNOVAL && - vap->va_gid == (gid_t)VNOVAL) - return (0); - vap->va_size = VNOVAL; - break; - default: - /* - * Disallow write attempts if the filesystem is - * mounted read-only. - */ - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - - /* - * We run vnode_pager_setsize() early (why?), - * we must set np->n_size now to avoid vinvalbuf - * V_SAVE races that might setsize a lower - * value. - */ - - tsize = np->n_size; - error = nfs_meta_setsize(vp, ap->a_cred, td, - vap->va_size); - - if (np->n_flag & NMODIFIED) { - if (vap->va_size == 0) - error = nfs_vinvalbuf(vp, 0, td, 1); - else - error = nfs_vinvalbuf(vp, V_SAVE, td, 1); - if (error) { - vnode_pager_setsize(vp, np->n_size); - return (error); - } - } - /* - * np->n_size has already been set to vap->va_size - * in nfs_meta_setsize(). We must set it again since - * nfs_loadattrcache() could be called through - * nfs_meta_setsize() and could modify np->n_size. - */ - np->n_vattr.va_size = np->n_size = vap->va_size; - }; - } else if ((vap->va_mtime.tv_sec != VNOVAL || - vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) && - vp->v_type == VREG && - (error = nfs_vinvalbuf(vp, V_SAVE, td, 1)) == EINTR) - return (error); - - if (vap->va_size != VNOVAL && np->n_wfc.refcnt == 0) { - /* Have to open the file before we can truncate it */ - struct componentname cn; - - cn.cn_nameptr = np->n_name; - cn.cn_namelen = np->n_namelen; - cn.cn_cred = ap->a_cred; - cn.cn_thread = td; - error = nfs4_openrpc(np->n_dvp, &vp, &cn, FWRITE, NULL); - if (error) - return error; - np->n_flag |= NTRUNCATE; - } - - error = nfs4_setattrrpc(vp, vap, ap->a_cred); - if (error && vap->va_size != VNOVAL) { - np->n_size = np->n_vattr.va_size = tsize; - vnode_pager_setsize(vp, np->n_size); - } - return (error); -} - -/* - * Do an nfs setattr rpc. - */ -static int -nfs4_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred) -{ - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct thread *td; - struct nfs4_compound cp; - struct nfs4_oparg_getattr ga; - struct nfsnode *np = VTONFS(vp); - struct nfs4_fctx *fcp; - - td = curthread; - nfsstats.rpccnt[NFSPROC_SETATTR]++; - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - ga.bm = &nfsv4_getattrbm; - fcp = (vap->va_size != VNOVAL) ? &np->n_wfc : NULL; - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_setattrrpc"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_setattr(&cp, vap, fcp); - nfsm_v4build_getattr(&cp, &ga); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_setattr(&cp); - nfsm_v4dissect_getattr(&cp, &ga); - - nfs4_vnop_loadattrcache(vp, &ga.fa, NULL); - - /* TODO: do the settatr and close in a single compound rpc */ - if (np->n_flag & NTRUNCATE) { - error = nfs4_closerpc(vp, cred, FWRITE); - np->n_flag &= ~NTRUNCATE; - } - -nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -/* - * nfs lookup call, one step at a time... - * First look in cache - * If not found, unlock the directory nfsnode and do the rpc - */ -static int -nfs4_lookup(struct vop_lookup_args *ap) -{ - struct componentname *cnp = ap->a_cnp; - struct vnode *dvp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - int isdot, flags = cnp->cn_flags; - struct vnode *newvp; - struct nfsmount *nmp; - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - long len; - nfsfh_t *fhp; - struct nfsnode *np; - int error = 0, fhsize; - struct thread *td = cnp->cn_thread; - struct nfs4_compound cp; - struct nfs4_oparg_getattr ga, dga; - struct nfs4_oparg_lookup l; - struct nfs4_oparg_getfh gfh; - - *vpp = NULLVP; - if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && - (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) - return (EROFS); - if (dvp->v_type != VDIR) - return (ENOTDIR); - nmp = VFSTONFS(dvp->v_mount); - np = VTONFS(dvp); - - isdot = cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.'; - - if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) { - *vpp = NULLVP; - return (error); - } - if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { - struct vattr vattr; - - newvp = *vpp; - if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred) - && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { - nfsstats.lookupcache_hits++; - if (cnp->cn_nameiop != LOOKUP && - (flags & ISLASTCN)) - cnp->cn_flags |= SAVENAME; - return (0); - } - cache_purge(newvp); - if (newvp != dvp) - vput(newvp); - else - vrele(newvp); - } - - error = 0; - newvp = NULLVP; - nfsstats.lookupcache_misses++; - nfsstats.rpccnt[NFSPROC_LOOKUP]++; - - len = cnp->cn_namelen; - mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - ga.bm = &nfsv4_getattrbm; - dga.bm = &nfsv4_getattrbm; - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_lookup()"); - nfsm_v4build_putfh(&cp, dvp); - nfsm_v4build_getattr(&cp, &dga); - if (flags & ISDOTDOT) - nfsm_v4build_lookupp(&cp); - else if (!isdot) { - l.name = cnp->cn_nameptr; - l.namelen = len; - nfsm_v4build_lookup(&cp, &l); - } - nfsm_v4build_getattr(&cp, &ga); - nfsm_v4build_getfh(&cp, &gfh); - nfsm_v4build_finalize(&cp); - - nfsm_request(dvp, NFSV4PROC_COMPOUND, cnp->cn_thread, cnp->cn_cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_getattr(&cp, &dga); - if (flags & ISDOTDOT) - nfsm_v4dissect_lookupp(&cp); - else if (!isdot) - nfsm_v4dissect_lookup(&cp); - nfsm_v4dissect_getattr(&cp, &ga); - nfsm_v4dissect_getfh(&cp, &gfh); - - nfs4_vnop_loadattrcache(dvp, &dga.fa, NULL); - fhp = &gfh.fh_val; - fhsize = gfh.fh_len; - - /* - * Handle RENAME case... - */ - if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN)) { - if (NFS_CMPFH(np, fhp, fhsize)) - return (EISDIR); - - error = nfs_nget(dvp->v_mount, fhp, fhsize, &np, LK_EXCLUSIVE); - if (error) - return (error); - - newvp = NFSTOV(np); - - nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL); - - *vpp = newvp; - cnp->cn_flags |= SAVENAME; - return (0); - } - - if (flags & ISDOTDOT) { - VOP_UNLOCK(dvp, 0); - - error = nfs_nget(dvp->v_mount, fhp, fhsize, &np, LK_EXCLUSIVE); - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - if (error) - return (error); - newvp = NFSTOV(np); - - nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL); - } else if (NFS_CMPFH(np, fhp, fhsize)) { - VREF(dvp); - newvp = dvp; - } else { - error = nfs_nget(dvp->v_mount, fhp, fhsize, &np, LK_EXCLUSIVE); - if (error) - return (error); - newvp = NFSTOV(np); - - /* Fill in np used by open. */ - np->n_dvp = dvp; - np->n_namelen = cnp->cn_namelen; - if (np->n_name != NULL) - free(np->n_name, M_NFSREQ); - np->n_name = malloc(np->n_namelen + 1, M_NFSREQ, M_WAITOK); - bcopy(cnp->cn_nameptr, np->n_name, np->n_namelen); - np->n_name[np->n_namelen] = '\0'; - - nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL); - } - - if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) - cnp->cn_flags |= SAVENAME; - if ((cnp->cn_flags & MAKEENTRY) && - (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { - np->n_ctime = np->n_vattr.va_ctime.tv_sec; - cache_enter(dvp, newvp, cnp); - } - *vpp = newvp; - m_freem(mrep); -nfsmout: - error = nfs_v4postop(&cp, error); - - if (error) { - if (newvp != NULLVP) { - vrele(newvp); - *vpp = NULLVP; - } - if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && - (flags & ISLASTCN) && error == ENOENT) { - if (dvp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else - error = EJUSTRETURN; - } - if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) - cnp->cn_flags |= SAVENAME; - } - - return (error); -} - -/* - * nfs read call. - * Just call nfs_bioread() to do the work. - */ -static int -nfs4_read(struct vop_read_args *ap) -{ - struct vnode *vp = ap->a_vp; - - switch (vp->v_type) { - case VREG: - return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); - case VDIR: - return (EISDIR); - default: - return (EOPNOTSUPP); - } -} - -/* - * nfs readlink call - */ -static int -nfs4_readlink(struct vop_readlink_args *ap) -{ - struct vnode *vp = ap->a_vp; - - if (vp->v_type != VLNK) - return (EINVAL); - return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); -} - -/* - * Do a readlink rpc. - * Called by nfs_doio() from below the buffer cache. - */ -int -nfs4_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) -{ - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_compound cp; - - nfsstats.rpccnt[NFSPROC_READLINK]++; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_readlinkrpc()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_readlink(&cp); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_readlink(&cp, uiop); - -nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - return (error); -} - -/* - * nfs read rpc call - * Ditto above - */ -int -nfs4_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) -{ - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfsmount *nmp; - int error = 0, len, tsiz; - struct nfs4_compound cp; - struct nfs4_oparg_read read; - struct nfsnode *np = VTONFS(vp); - - nmp = VFSTONFS(vp->v_mount); - tsiz = uiop->uio_resid; - if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) - return (EFBIG); - - if (tsiz == 0) - return (0); - - read.uiop = uiop; - read.fcp = np->n_rfc.refcnt > 0 ? &np->n_rfc : &np->n_wfc; - - while (tsiz > 0) { - nfsstats.rpccnt[NFSPROC_READ]++; - len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; - - read.off = uiop->uio_offset; - read.maxcnt = len; - nfs_v4initcompound(&cp); - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_readrpc()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_read(&cp, &read); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred); - if (error != 0) { - error = nfs_v4postop(&cp, error); - goto nfsmout; - } - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_read(&cp, &read); - - if (read.eof || read.retlen == 0) - tsiz = 0; - else - tsiz -= read.retlen; - - error = nfs_v4postop(&cp, error); - - m_freem(mrep); - mrep = NULL; - } -nfsmout: - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -/* - * nfs write call - */ -int -nfs4_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, - int *iomode, int *must_commit) -{ - int32_t backup; - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfsmount *nmp = VFSTONFS(vp->v_mount); - int error = 0, len, tsiz, wccflag = 1, rlen; - struct nfs4_compound cp; - struct nfs4_oparg_write write; - nfsv4stablehow commit, committed = NSHFILESYNC; - caddr_t verf; - struct nfsnode *np = VTONFS(vp); - -#ifndef DIAGNOSTIC - if (uiop->uio_iovcnt != 1) - panic("nfs: writerpc iovcnt > 1"); -#endif - *must_commit = 0; - tsiz = uiop->uio_resid; - if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) - return (EFBIG); - - if (tsiz == 0) - return (0); - - write.stable = (nfsv4stablehow)*iomode; - write.uiop = uiop; - write.fcp = &np->n_wfc; - - while (tsiz > 0) { - nfsstats.rpccnt[NFSPROC_WRITE]++; - len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; - - write.off = uiop->uio_offset; - write.cnt = len; - nfs_v4initcompound(&cp); - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_writerpc()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_write(&cp, &write); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred); - if (error != 0) { - error = nfs_v4postop(&cp, error); - goto nfsmout; - } - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_write(&cp, &write); - - rlen = write.retlen; - if (rlen == 0) { - error = NFSERR_IO; - break; - } else if (rlen < len) { - backup = len - rlen; - uiop->uio_iov->iov_base = - (char *)uiop->uio_iov->iov_base - backup; - uiop->uio_iov->iov_len += backup; - uiop->uio_offset -= backup; - uiop->uio_resid += backup; - len = rlen; - } - - commit = write.committed; - - if (committed == NSHFILESYNC || - (committed = NSHDATASYNC && commit == NSHUNSTABLE)) - committed = commit; - - verf = (caddr_t)write.wverf; - - if ((nmp->nm_flag & NFSSTA_HASWRITEVERF) == 0) { - bcopy(verf, nmp->nm_verf, NFSX_V4VERF); - nmp->nm_flag |= NFSMNT_HASWRITEVERF; - } else if (bcmp(verf, nmp->nm_verf, NFSX_V4VERF)) { - *must_commit = 1; - bcopy(verf, nmp->nm_verf, NFSX_V4VERF); - } - - /* XXX wccflag */ - if (wccflag) - VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime; - - error = nfs_v4postop(&cp, error); - - m_freem(mrep); - mrep = NULL; - if (error) - break; - tsiz -= len; - } -nfsmout: - if (mrep != NULL) - m_freem(mrep); - *iomode = committed; - if (error) - uiop->uio_resid = tsiz; - return (error); -} - -/* ARGSUSED */ -static int -nfs4_mknod(struct vop_mknod_args *ap) -{ - struct vattr *vap = ap->a_vap; - struct vnode *newvp = NULL; - int error; - - error = nfs4_createrpc(ap->a_dvp, &newvp, - ap->a_cnp, (nfstype)vap->va_type, vap, NULL); - - /* XXX - is this actually referenced here? */ - if (error == 0) { - *ap->a_vpp = newvp; - vrele(newvp); - } - - return (error); -} - -static int -nfs4_createrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, - nfstype ftype, struct vattr *vap, char *linktarget) -{ - struct nfsnode *dnp = VTONFS(dvp); - struct nfsnode *np = NULL; - struct vnode *newvp = NULL; - struct nfs4_compound cp; - struct nfs4_oparg_create c; - struct nfs4_oparg_getattr ga; - struct nfs4_oparg_getfh gfh; - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - int error = 0; - - nfsstats.rpccnt[NFSPROC_CREATE]++; - - mreq = nfsm_reqhead(dvp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - bzero(&c, sizeof(c)); - bzero(&ga, sizeof(ga)); - - c.type = ftype; - c.vap = vap; - c.linktext = linktarget; - c.name = cnp->cn_nameptr; - c.namelen = cnp->cn_namelen; - - ga.bm = &nfsv4_getattrbm; - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_createrpc()"); - nfsm_v4build_putfh(&cp, dvp); - nfsm_v4build_create(&cp, &c); - nfsm_v4build_getattr(&cp, &ga); - nfsm_v4build_getfh(&cp, &gfh); - nfsm_v4build_finalize(&cp); - - nfsm_request(dvp, NFSV4PROC_COMPOUND, cnp->cn_thread, cnp->cn_cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_create(&cp, &c); - nfsm_v4dissect_getattr(&cp, &ga); - nfsm_v4dissect_getfh(&cp, &gfh); - - error = nfs_nget(dvp->v_mount, &gfh.fh_val, gfh.fh_len, &np, LK_EXCLUSIVE); - if (error != 0) - goto nfsmout; - - newvp = NFSTOV(np); - nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL); - - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, newvp, cnp); - - dnp->n_flag |= NMODIFIED; - dnp->n_attrstamp = 0; - - nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - /* XXX */ - /*free(cnp->cn_pnbuf, M_NAMEI);*/ - if (error != 0 && newvp != NULL) - vput(newvp); - else if (error == 0) - *vpp = newvp; - - return (error); -} - -static int -nfs4_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen, - struct vnode *tdvp, const char *tnameptr, int tnamelen, - struct ucred *cred, struct thread *td) -{ - - struct nfsnode *fnp = VTONFS(fdvp), *tnp = VTONFS(tdvp); - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_compound cp; - struct nfs4_oparg_rename r; - int error = 0; - - nfsstats.rpccnt[NFSPROC_RENAME]++; - - r.fname = fnameptr; - r.fnamelen = fnamelen; - r.tname = tnameptr; - r.tnamelen = tnamelen; - nfs_v4initcompound(&cp); - - mreq = nfsm_reqhead(fdvp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_renamerpc()"); - nfsm_v4build_putfh(&cp, fdvp); - nfsm_v4build_savefh(&cp); - nfsm_v4build_putfh(&cp, tdvp); - nfsm_v4build_rename(&cp, &r); - nfsm_v4build_finalize(&cp); - - nfsm_request(fdvp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_savefh(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_rename(&cp); - - /* XXX should this always be performed? */ - fnp->n_flag |= NMODIFIED; - tnp->n_flag |= NMODIFIED; - fnp->n_attrstamp = tnp->n_attrstamp = 0; - - nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -/* - * nfs file create call - */ -static int -nfs4_create(struct vop_create_args *ap) -{ - struct vnode *dvp = ap->a_dvp; - struct vattr *vap = ap->a_vap; - struct nfsnode *dnp = VTONFS(dvp); - struct componentname *cnp = ap->a_cnp; - struct vnode *newvp = NULL; - int error = 0, fmode = (O_CREAT | FREAD | FWRITE); - struct vattr vattr; - - if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0) - return (error); - - if (vap->va_vaflags & VA_EXCLUSIVE) - fmode |= O_EXCL; - - error = nfs4_openrpc(dvp, &newvp, cnp, fmode, vap); - if (error != 0) - goto out; - - VTONFS(newvp)->n_flag |= NCREATED; - - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, newvp, cnp); - - *ap->a_vpp = newvp; - - dnp->n_flag |= NMODIFIED; - dnp->n_attrstamp = 0; /* XXX; wccflag */ - - out: - return (error); -} - -/* - * nfs file remove call - * To try and make nfs semantics closer to ufs semantics, a file that has - * other processes using the vnode is renamed instead of removed and then - * removed later on the last close. - * - If v_usecount > 1 - * If a rename is not already in the works - * call nfs4_sillyrename() to set it up - * else - * do the remove rpc - */ -static int -nfs4_remove(struct vop_remove_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct componentname *cnp = ap->a_cnp; - struct nfsnode *np = VTONFS(vp); - int error = 0; - struct vattr vattr; - -#ifndef DIAGNOSTIC - if ((cnp->cn_flags & HASBUF) == 0) - panic("nfs4_remove: no name"); - if (vrefcnt(vp) < 1) - panic("nfs4_remove: bad v_usecount"); -#endif - if (vp->v_type == VDIR) - error = EPERM; - else if (vrefcnt(vp) == 1 || (np->n_sillyrename && - !VOP_GETATTR(vp, &vattr, cnp->cn_cred) && vattr.va_nlink > 1)) { - /* - * Purge the name cache so that the chance of a lookup for - * the name succeeding while the remove is in progress is - * minimized. Without node locking it can still happen, such - * that an I/O op returns ESTALE, but since you get this if - * another host removes the file.. - */ - cache_purge(vp); - /* - * throw away biocache buffers, mainly to avoid - * unnecessary delayed writes later. - */ - error = nfs_vinvalbuf(vp, 0, cnp->cn_thread, 1); - /* Do the rpc */ - if (error != EINTR) - error = nfs4_removerpc(dvp, cnp->cn_nameptr, - cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread); - /* - * Kludge City: If the first reply to the remove rpc is lost.. - * the reply to the retransmitted request will be ENOENT - * since the file was in fact removed - * Therefore, we cheat and return success. - */ - if (error == ENOENT) - error = 0; - } else if (!np->n_sillyrename) - error = nfs4_sillyrename(dvp, vp, cnp); - np->n_attrstamp = 0; - return (error); -} - -/* - * nfs file remove rpc called from nfs_inactive - */ -int -nfs4_removeit(struct sillyrename *sp) -{ - /* - * Make sure that the directory vnode is still valid. - * XXX we should lock sp->s_dvp here. - */ - if (sp->s_dvp->v_type == VBAD) - return (0); - return (nfs4_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, - NULL)); -} - -/* - * Nfs remove rpc, called from nfs4_remove() and nfs4_removeit(). - */ -static int -nfs4_removerpc(struct vnode *dvp, const char *name, int namelen, - struct ucred *cred, struct thread *td) -{ - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_compound cp; - - nfsstats.rpccnt[NFSPROC_REMOVE]++; - - mreq = nfsm_reqhead(dvp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_removerpc()"); - nfsm_v4build_putfh(&cp, dvp); - nfsm_v4build_remove(&cp, name, namelen); - nfsm_v4build_finalize(&cp); - - nfsm_request(dvp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_remove(&cp); - - nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - VTONFS(dvp)->n_flag |= NMODIFIED; - VTONFS(dvp)->n_attrstamp = 0; /* XXX wccflag */ - - return (error); -} - -/* - * nfs file rename call - */ -static int -nfs4_rename(struct vop_rename_args *ap) -{ - struct vnode *fvp = ap->a_fvp; - struct vnode *tvp = ap->a_tvp; - struct vnode *fdvp = ap->a_fdvp; - struct vnode *tdvp = ap->a_tdvp; - struct componentname *tcnp = ap->a_tcnp; - struct componentname *fcnp = ap->a_fcnp; - int error; - - #ifndef DIAGNOSTIC - if ((tcnp->cn_flags & HASBUF) == 0 || - (fcnp->cn_flags & HASBUF) == 0) - panic("nfs4_rename: no name"); -#endif - /* Check for cross-device rename */ - if ((fvp->v_mount != tdvp->v_mount) || - (tvp && (fvp->v_mount != tvp->v_mount))) { - error = EXDEV; - goto out; - } - - if (fvp == tvp) { - printf("nfs4_rename: fvp == tvp (can't happen)\n"); - error = 0; - goto out; - } - if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) - goto out; - - /* - * We have to flush B_DELWRI data prior to renaming - * the file. If we don't, the delayed-write buffers - * can be flushed out later after the file has gone stale - * under NFSV3. NFSV2 does not have this problem because - * ( as far as I can tell ) it flushes dirty buffers more - * often. - */ - VOP_FSYNC(fvp, MNT_WAIT, fcnp->cn_thread); - VOP_UNLOCK(fvp, 0); - if (tvp) - VOP_FSYNC(tvp, MNT_WAIT, tcnp->cn_thread); - - /* - * If the tvp exists and is in use, sillyrename it before doing the - * rename of the new file over it. - * XXX Can't sillyrename a directory. - */ - if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename && - tvp->v_type != VDIR && !nfs4_sillyrename(tdvp, tvp, tcnp)) { - vput(tvp); - tvp = NULL; - } - - error = nfs4_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, - tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, - tcnp->cn_thread); - - if (fvp->v_type == VDIR) { - if (tvp != NULL && tvp->v_type == VDIR) - cache_purge(tdvp); - cache_purge(fdvp); - } - -out: - if (tdvp == tvp) - vrele(tdvp); - else - vput(tdvp); - if (tvp) - vput(tvp); - vrele(fdvp); - vrele(fvp); - /* - * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. - */ - if (error == ENOENT) - error = 0; - return (error); -} - -/* - * nfs file rename rpc called from nfs4_remove() above - */ -static int -nfs4_renameit(struct vnode *sdvp, struct componentname *scnp, - struct sillyrename *sp) -{ - return (nfs4_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, sdvp, - sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread)); -} - -/* - * nfs hard link create call - */ -static int -nfs4_link(struct vop_link_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct vnode *tdvp = ap->a_tdvp; - struct componentname *cnp = ap->a_cnp; - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_compound cp; - struct nfs4_oparg_link l; - - if (vp->v_mount != tdvp->v_mount) { - return (EXDEV); - } - - /* - * Push all writes to the server, so that the attribute cache - * doesn't get "out of sync" with the server. - * XXX There should be a better way! - */ - VOP_FSYNC(vp, MNT_WAIT, cnp->cn_thread); - - nfsstats.rpccnt[NFSPROC_LINK]++; - - l.name = cnp->cn_nameptr; - l.namelen = cnp->cn_namelen; - nfs_v4initcompound(&cp); - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - nfsm_v4build_compound(&cp, "nfs4_link()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_savefh(&cp); - nfsm_v4build_putfh(&cp, tdvp); - nfsm_v4build_link(&cp, &l); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, cnp->cn_thread, cnp->cn_cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_savefh(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_link(&cp); - - VTONFS(tdvp)->n_flag |= NMODIFIED; - VTONFS(vp)->n_attrstamp = 0; - VTONFS(tdvp)->n_attrstamp = 0; - -nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - - return (error); -} - -/* - * nfs symbolic link create call - */ -static int -nfs4_symlink(struct vop_symlink_args *ap) -{ - struct vnode *dvp = ap->a_dvp; - int error = 0; - struct vnode *newvp = NULL; - - nfsstats.rpccnt[NFSPROC_SYMLINK]++; - - error = nfs4_createrpc(ap->a_dvp, &newvp, ap->a_cnp, NFLNK, - ap->a_vap, ap->a_target); - - if (error != 0 && newvp != NULL) - vput(newvp); - else if (error == 0) - *ap->a_vpp = newvp; - - VTONFS(dvp)->n_flag |= NMODIFIED; - VTONFS(dvp)->n_attrstamp = 0; /* XXX wccflags */ - - return (error); -} - -/* - * nfs make dir call - */ -static int -nfs4_mkdir(struct vop_mkdir_args *ap) -{ - return (nfs4_createrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, NFDIR, - ap->a_vap, NULL)); -} - -/* - * nfs remove directory call - */ -static int -nfs4_rmdir(struct vop_rmdir_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct nfsnode *dnp = VTONFS(dvp); - struct componentname *cnp = ap->a_cnp; - int error = 0; - - if (dvp == vp) - return (EINVAL); - - error = (nfs4_removerpc(dvp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_cred, - NULL)); - if (error) - return (error); - - dnp->n_flag |= NMODIFIED; - dnp->n_attrstamp = 0; - cache_purge(dvp); - cache_purge(vp); - - return (error); -} - -/* - * nfs readdir call - */ -static int -nfs4_readdir(struct vop_readdir_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - struct uio *uio = ap->a_uio; - int tresid, error; - struct vattr vattr; - - if (vp->v_type != VDIR) - return (EPERM); - /* - * First, check for hit on the EOF offset cache - */ - if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && - (np->n_flag & NMODIFIED) == 0) { - if (!VOP_GETATTR(vp, &vattr, ap->a_cred) && - !NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { - nfsstats.direofcache_hits++; - return (0); - } - } - - /* - * Call nfs_bioread() to do the real work. - */ - tresid = uio->uio_resid; - error = nfs_bioread(vp, uio, 0, ap->a_cred); - - if (!error && uio->uio_resid == tresid) - nfsstats.direofcache_misses++; - return (error); -} - -static u_char fty_to_dty[] = { - DT_UNKNOWN, /* NFNON */ - DT_REG, /* NFREG */ - DT_DIR, /* NFDIR */ - DT_BLK, /* NFBLK */ - DT_CHR, /* NFCHR */ - DT_LNK, /* NFLNK */ - DT_SOCK, /* NFSOCK */ - DT_FIFO, /* NFFIFO */ - DT_UNKNOWN, /* NFATTRDIT */ - DT_UNKNOWN, /* NFNAMEDATTR */ - DT_UNKNOWN, /* NFBAD */ -}; - -/* - * Readdir rpc call. - * Called from below the buffer cache by nfs_doio(). - */ -int -nfs4_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) -{ - int len, left; - struct dirent *dp = NULL; - u_int32_t *tl; - caddr_t p; - uint64_t *cookiep; - caddr_t bpos, dpos; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - uint64_t cookie; - struct nfsmount *nmp = VFSTONFS(vp->v_mount); - struct nfsnode *dnp = VTONFS(vp); - int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; - struct nfs4_compound cp; - struct nfs4_oparg_readdir readdir; - struct nfsv4_fattr fattr; - u_int fty; - -#ifndef DIAGNOSTIC - if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || - (uiop->uio_resid & (DIRBLKSIZ - 1))) - panic("nfs readdirrpc bad uio"); -#endif - - /* - * If there is no cookie, assume directory was stale. - */ - cookiep = nfs4_getcookie(dnp, uiop->uio_offset, 0); - if (cookiep) - cookie = *cookiep; - else - return (NFSERR_BAD_COOKIE); - - /* Generate fake entries for "." and ".." */ - while (cookie < 2 && bigenough) { - cookie++; - len = 4 + DIRHDSIZ; - - if (len > uiop->uio_resid) { - bigenough = 0; - break; - } - dp = (struct dirent *)uiop->uio_iov->iov_base; - - dp->d_namlen = cookie; - dp->d_reclen = len; - dp->d_type = DT_DIR; - if (cookie == 1) - dp->d_fileno = dnp->n_vattr.va_fileid; /* XXX has problems with pynfs virtualhandles */ - else - dp->d_fileno = dnp->n_dvp != NULL ? - VTONFS(dnp->n_dvp)->n_vattr.va_fileid : cookie; - - p = dp->d_name; - *p++ = '.'; - if (cookie == 2) - *p++ = '.'; - *p = '\0'; - - blksiz += len; - if (blksiz == DIRBLKSIZ) - blksiz = 0; - uiop->uio_offset += len; - uiop->uio_resid -= len; - uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + len; - uiop->uio_iov->iov_len -= len; - } - - if (cookie == 2) - cookie = 0; - - /* This is sort of ugly, to prevent v4postop() from acting weird */ - bzero(&cp, sizeof(cp)); - - /* - * Loop around doing readdir rpc's of size nm_readdirsize - * truncated to a multiple of DIRBLKSIZ. - * The stopping criteria is EOF or buffer full. - */ - /* - * XXX this is sort of ugly for nfsv4; we don't maintain the - * strict abstraction, but do the decoding inline. that's ok. - */ - while (more_dirs && bigenough) { - nfsstats.rpccnt[NFSPROC_READDIR]++; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - readdir.cnt = nmp->nm_readdirsize; - readdir.cookie = cookie; - readdir.bm = &nfsv4_readdirbm; - if (cookie == 0) - bzero(&readdir.verf, sizeof(readdir.verf)); - else - bcopy(&dnp->n_cookieverf, &readdir.verf, - sizeof(readdir.verf)); - - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_readdirrpc()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_readdir(&cp, &readdir); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - - /* - * XXX - Readdir gets handled inline like in - * NFSv{2,3}. This is a nasty inconsistency and - * should be fixed. - */ - - tl = nfsm_dissect(uint32_t *, 5 * NFSX_UNSIGNED); - if (fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_READDIR) { - error = EBADRPC; - goto nfsmout; - } - if (fxdr_unsigned(uint32_t, *tl++) != 0) { - error = EBADRPC; - goto nfsmout; - } - - bcopy(tl, &dnp->n_cookieverf, NFSX_V4VERF); - tl += 2; - more_dirs = fxdr_unsigned(int, *tl++); - - /* loop thru the dir entries, doctoring them to 4bsd form */ - while (more_dirs && bigenough) { - tl = nfsm_dissect(uint32_t *, 3 * NFSX_UNSIGNED); - cookie = fxdr_hyper(tl); - tl += 2; - /* XXX cookie sanity check */ - len = fxdr_unsigned(int, *tl++); - if (len <= 0 || len > NFS_MAXNAMLEN) { - error = EBADRPC; - goto nfsmout; - } - tlen = nfsm_rndup(len); - if (tlen == len) - tlen += 4; /* To ensure null termination */ - left = DIRBLKSIZ - blksiz; - if ((tlen + DIRHDSIZ) > left) { - dp->d_reclen += left; - uiop->uio_iov->iov_base = - (char *)uiop->uio_iov->iov_base + left; - uiop->uio_iov->iov_len -= left; - uiop->uio_offset += left; - uiop->uio_resid -= left; - blksiz = 0; - } - if ((tlen + DIRHDSIZ) > uiop->uio_resid) - bigenough = 0; - if (bigenough) { - dp = (struct dirent *)uiop->uio_iov->iov_base; - - dp->d_namlen = len; - dp->d_reclen = tlen + DIRHDSIZ; - - blksiz += dp->d_reclen; - if (blksiz == DIRBLKSIZ) - blksiz = 0; - uiop->uio_offset += DIRHDSIZ; - uiop->uio_resid -= DIRHDSIZ; - uiop->uio_iov->iov_base = - (char *)uiop->uio_iov->iov_base + DIRHDSIZ; - uiop->uio_iov->iov_len -= DIRHDSIZ; - - /* Copy name */ - nfsm_mtouio(uiop, len); - p = uiop->uio_iov->iov_base; - tlen -= len; - *p = '\0'; /* null terminate */ - /* printf("nfs4_readdirrpc: name: \"%s\" cookie %d\n", - p - len, (int) cookie);*/ - uiop->uio_iov->iov_base = - (char *)uiop->uio_iov->iov_base + tlen; - uiop->uio_iov->iov_len -= tlen; - uiop->uio_offset += tlen; - uiop->uio_resid -= tlen; - - /* Copy attributes */ - nfsm_v4dissect_attrs(&fattr); - - dp->d_fileno = nfs_v4fileid4_to_fileid( - fattr.fa4_valid & FA4V_FILEID && - fattr.fa4_fileid ? - fattr.fa4_fileid : cookie); - - fty = (u_int)fattr.fa4_type; - dp->d_type = fattr.fa4_valid & FA4V_TYPE && - (fty < sizeof(fty_to_dty)) ? - fty_to_dty[fty] : DT_UNKNOWN; - } else - nfsm_adv(nfsm_rndup(len)); - - tl = nfsm_dissect(uint32_t *, NFSX_UNSIGNED); - more_dirs = fxdr_unsigned(int, *tl++); - } - /* - * If at end of rpc data, get the eof boolean - */ - if (!more_dirs) { - tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); - more_dirs = (fxdr_unsigned(int, *tl) == 0); - } - - error = nfs_v4postop(&cp, error); - - m_freem(mrep); - mrep = NULL; - } - /* - * Fill last record, iff any, out to a multiple of DIRBLKSIZ - * by increasing d_reclen for the last record. - */ - if (blksiz > 0) { - left = DIRBLKSIZ - blksiz; - dp->d_reclen += left; - uiop->uio_iov->iov_base = - (char *)uiop->uio_iov->iov_base + left; - uiop->uio_iov->iov_len -= left; - uiop->uio_offset += left; - uiop->uio_resid -= left; - } - - /* - * We are now either at the end of the directory or have filled the - * block. - */ - if (bigenough) - dnp->n_direofoffset = uiop->uio_offset; - else { - if (uiop->uio_resid > 0) - printf("EEK! readdirrpc resid > 0\n"); - cookiep = nfs4_getcookie(dnp, uiop->uio_offset, 1); - *cookiep = cookie; - } -nfsmout: - if (mrep != NULL) - m_freem(mrep); - return (error); -} - -/* - * Silly rename. To make the NFS filesystem that is stateless look a little - * more like the "ufs" a remove of an active vnode is translated to a rename - * to a funny looking filename that is removed by nfs_inactive on the - * nfsnode. There is the potential for another process on a different client - * to create the same funny name between the nfs_lookitup() fails and the - * nfs_rename() completes, but... - */ -static int -nfs4_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) -{ - struct sillyrename *sp; - struct nfsnode *np; - int error; - short pid; - - cache_purge(dvp); - np = VTONFS(vp); -#ifndef DIAGNOSTIC - if (vp->v_type == VDIR) - panic("nfs: sillyrename dir"); -#endif - sp = malloc(sizeof (struct sillyrename), M_NFSREQ, M_WAITOK); - sp->s_cred = crhold(cnp->cn_cred); - sp->s_dvp = dvp; - sp->s_removeit = nfs4_removeit; - VREF(dvp); - - /* Fudge together a funny name */ - pid = cnp->cn_thread->td_proc->p_pid; - sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid); - - /* Try lookitups until we get one that isn't there */ - while (nfs4_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, - cnp->cn_thread, NULL) == 0) { - sp->s_name[4]++; - if (sp->s_name[4] > 'z') { - error = EINVAL; - goto bad; - } - } - error = nfs4_renameit(dvp, cnp, sp); - if (error) - goto bad; - error = nfs4_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, - cnp->cn_thread, &np); - np->n_sillyrename = sp; - return (0); -bad: - vrele(sp->s_dvp); - crfree(sp->s_cred); - free((caddr_t)sp, M_NFSREQ); - return (error); -} - -/* - * Look up a file name and optionally either update the file handle or - * allocate an nfsnode, depending on the value of npp. - * npp == NULL --> just do the lookup - * *npp == NULL --> allocate a new nfsnode and make sure attributes are - * handled too - * *npp != NULL --> update the file handle in the vnode - */ -static int -nfs4_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred, - struct thread *td, struct nfsnode **npp) -{ - struct vnode *newvp = NULL; - struct nfsnode *np, *dnp = VTONFS(dvp); - caddr_t bpos, dpos; - int error = 0, fhlen; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - nfsfh_t *nfhp; - struct nfs4_compound cp; - struct nfs4_oparg_lookup l; - struct nfs4_oparg_getfh gfh; - struct nfs4_oparg_getattr ga; - - nfsstats.rpccnt[NFSPROC_RENAME]++; - - mreq = nfsm_reqhead(dvp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - l.name = name; - l.namelen = len; - - nfs_v4initcompound(&cp); - - ga.bm = &nfsv4_getattrbm; - - nfsm_v4build_compound(&cp, "nfs4_renamerpc()"); - nfsm_v4build_putfh(&cp, dvp); - nfsm_v4build_lookup(&cp, &l); - nfsm_v4build_getfh(&cp, &gfh); - nfsm_v4build_getattr(&cp, &ga); - - nfsm_request(dvp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_lookup(&cp); - nfsm_v4dissect_getfh(&cp, &gfh); - nfsm_v4dissect_getattr(&cp, &ga); - - if (npp != NULL && error == 0) { - nfhp = &gfh.fh_val; - fhlen = gfh.fh_len; - - if (*npp != NULL) { - np = *npp; - if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { - free((caddr_t)np->n_fhp, M_NFSBIGFH); - np->n_fhp = &np->n_fh; - } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) - np->n_fhp =(nfsfh_t *)malloc(fhlen, M_NFSBIGFH, M_WAITOK); - bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); - np->n_fhsize = fhlen; - newvp = NFSTOV(np); - } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { - VREF(dvp); - newvp = dvp; - } else { - error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np, LK_EXCLUSIVE); - if (error) { - m_freem(mrep); - return (error); - } - newvp = NFSTOV(np); - } - - if (newvp != dvp) { - np->n_dvp = dvp; - np->n_namelen = len; - if (np->n_name != NULL) - free(np->n_name, M_NFSREQ); - np->n_name = malloc(np->n_namelen + 1, M_NFSREQ, M_WAITOK); - memcpy(np->n_name, name, len); - np->n_name[len] = '\0'; - } - nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL); - } - -nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep != NULL) - m_freem(mrep); - if (npp && *npp == NULL) { - if (error) { - if (newvp) { - if (newvp == dvp) - vrele(newvp); - else - vput(newvp); - } - } else - *npp = np; - } - - - return (error); -} - -/* - * Nfs Version 3 commit rpc - */ -int -nfs4_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred, - struct thread *td) -{ - struct nfsmount *nmp = VFSTONFS(vp->v_mount); - caddr_t bpos, dpos; - int error = 0; - struct mbuf *mreq, *mrep = NULL, *md, *mb; - struct nfs4_compound cp; - struct nfs4_oparg_commit commit; - - if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) - return (0); - nfsstats.rpccnt[NFSPROC_COMMIT]++; - - mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0); - mb = mreq; - bpos = mtod(mb, caddr_t); - - commit.start = offset; - commit.len = cnt; - - nfs_v4initcompound(&cp); - - nfsm_v4build_compound(&cp, "nfs4_commit()"); - nfsm_v4build_putfh(&cp, vp); - nfsm_v4build_commit(&cp, &commit); - nfsm_v4build_finalize(&cp); - - nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred); - if (error != 0) - goto nfsmout; - - nfsm_v4dissect_compound(&cp); - nfsm_v4dissect_putfh(&cp); - nfsm_v4dissect_commit(&cp, &commit); - - /* XXX */ - /* nfsm_wcc_data(vp, wccflag);*/ - if (bcmp(nmp->nm_verf, commit.verf, NFSX_V4VERF)) { - bcopy(commit.verf, nmp->nm_verf, NFSX_V4VERF); - error = NFSERR_STALEWRITEVERF; - } - -nfsmout: - error = nfs_v4postop(&cp, error); - - if (mrep == NULL) - m_freem(mrep); - return (error); -} - -/* - * Strategy routine. - * For async requests when nfsiod(s) are running, queue the request by - * calling nfs_asyncio(), otherwise just all nfs_doio() to do the - * request. - */ -static int -nfs4_strategy(struct vop_strategy_args *ap) -{ - struct buf *bp = ap->a_bp; - struct ucred *cr; - int error = 0; - - KASSERT(!(bp->b_flags & B_DONE), - ("nfs4_strategy: buffer %p unexpectedly marked B_DONE", bp)); - BUF_ASSERT_HELD(bp); - - if (bp->b_iocmd == BIO_READ) - cr = bp->b_rcred; - else - cr = bp->b_wcred; - - /* - * If the op is asynchronous and an i/o daemon is waiting - * queue the request, wake it up and wait for completion - * otherwise just do it ourselves. - */ - if ((bp->b_flags & B_ASYNC) == 0 || - nfs_asyncio(VFSTONFS(ap->a_vp->v_mount), bp, NOCRED, curthread)) - error = nfs_doio(ap->a_vp, bp, cr, curthread); - return (error); -} - -/* - * fsync vnode op. Just call nfs4_flush() with commit == 1. - */ -/* ARGSUSED */ -static int -nfs4_fsync(struct vop_fsync_args *ap) -{ - return (nfs4_flush(ap->a_vp, ap->a_waitfor, ap->a_td, 1)); -} - -/* - * Flush all the blocks associated with a vnode. - * Walk through the buffer pool and push any dirty pages - * associated with the vnode. - */ -static int -nfs4_flush(struct vnode *vp, int waitfor, struct thread *td, - int commit) -{ - struct nfsnode *np = VTONFS(vp); - struct bufobj *bo; - struct buf *bp; - int i; - struct buf *nbp; - struct nfsmount *nmp = VFSTONFS(vp->v_mount); - int error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; - int passone = 1; - u_quad_t off, endoff, toff; - struct ucred* wcred = NULL; - struct buf **bvec = NULL; -#ifndef NFS_COMMITBVECSIZ -#define NFS_COMMITBVECSIZ 20 -#endif - struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; - int bvecsize = 0, bveccount; - bo = &vp->v_bufobj; - - if (nmp->nm_flag & NFSMNT_INT) - slpflag = PCATCH; - if (!commit) - passone = 0; - /* - * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the - * server, but nas not been committed to stable storage on the server - * yet. On the first pass, the byte range is worked out and the commit - * rpc is done. On the second pass, nfs_writebp() is called to do the - * job. - */ -again: - off = (u_quad_t)-1; - endoff = 0; - bvecpos = 0; - if (NFS_ISV3(vp) && commit) { - if (bvec != NULL && bvec != bvec_on_stack) - free(bvec, M_TEMP); - /* - * Count up how many buffers waiting for a commit. - */ - bveccount = 0; - BO_LOCK(bo); - TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { - if (!BUF_ISLOCKED(bp) && - (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) - == (B_DELWRI | B_NEEDCOMMIT)) - bveccount++; - } - /* - * Allocate space to remember the list of bufs to commit. It is - * important to use M_NOWAIT here to avoid a race with nfs4_write. - * If we can't get memory (for whatever reason), we will end up - * committing the buffers one-by-one in the loop below. - */ - if (bveccount > NFS_COMMITBVECSIZ) { - /* - * Release the vnode interlock to avoid a lock - * order reversal. - */ - BO_UNLOCK(bo); - bvec = (struct buf **) - malloc(bveccount * sizeof(struct buf *), - M_TEMP, M_NOWAIT); - BO_LOCK(bo); - if (bvec == NULL) { - bvec = bvec_on_stack; - bvecsize = NFS_COMMITBVECSIZ; - } else - bvecsize = bveccount; - } else { - bvec = bvec_on_stack; - bvecsize = NFS_COMMITBVECSIZ; - } - TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { - if (bvecpos >= bvecsize) - break; - if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { - nbp = TAILQ_NEXT(bp, b_bobufs); - continue; - } - if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) != - (B_DELWRI | B_NEEDCOMMIT)) { - BUF_UNLOCK(bp); - nbp = TAILQ_NEXT(bp, b_bobufs); - continue; - } - BO_UNLOCK(bo); - bremfree(bp); - /* - * Work out if all buffers are using the same cred - * so we can deal with them all with one commit. - * - * NOTE: we are not clearing B_DONE here, so we have - * to do it later on in this routine if we intend to - * initiate I/O on the bp. - * - * Note: to avoid loopback deadlocks, we do not - * assign b_runningbufspace. - */ - if (wcred == NULL) - wcred = bp->b_wcred; - else if (wcred != bp->b_wcred) - wcred = NOCRED; - vfs_busy_pages(bp, 1); - - BO_LOCK(bo); - /* - * bp is protected by being locked, but nbp is not - * and vfs_busy_pages() may sleep. We have to - * recalculate nbp. - */ - nbp = TAILQ_NEXT(bp, b_bobufs); - - /* - * A list of these buffers is kept so that the - * second loop knows which buffers have actually - * been committed. This is necessary, since there - * may be a race between the commit rpc and new - * uncommitted writes on the file. - */ - bvec[bvecpos++] = bp; - toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + - bp->b_dirtyoff; - if (toff < off) - off = toff; - toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); - if (toff > endoff) - endoff = toff; - } - BO_UNLOCK(bo); - } - if (bvecpos > 0) { - /* - * Commit data on the server, as required. - * If all bufs are using the same wcred, then use that with - * one call for all of them, otherwise commit each one - * separately. - */ - if (wcred != NOCRED) - retv = nfs4_commit(vp, off, (int)(endoff - off), - wcred, td); - else { - retv = 0; - for (i = 0; i < bvecpos; i++) { - off_t off, size; - bp = bvec[i]; - off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + - bp->b_dirtyoff; - size = (u_quad_t)(bp->b_dirtyend - - bp->b_dirtyoff); - retv = nfs4_commit(vp, off, (int)size, - bp->b_wcred, td); - if (retv) break; - } - } - - if (retv == NFSERR_STALEWRITEVERF) - nfs_clearcommit(vp->v_mount); - - /* - * Now, either mark the blocks I/O done or mark the - * blocks dirty, depending on whether the commit - * succeeded. - */ - for (i = 0; i < bvecpos; i++) { - bp = bvec[i]; - bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK); - if (retv) { - /* - * Error, leave B_DELWRI intact - */ - vfs_unbusy_pages(bp); - brelse(bp); - } else { - /* - * Success, remove B_DELWRI ( bundirty() ). - * - * b_dirtyoff/b_dirtyend seem to be NFS - * specific. We should probably move that - * into bundirty(). XXX - */ - bufobj_wref(bo); - bp->b_flags |= B_ASYNC; - bundirty(bp); - bp->b_flags &= ~B_DONE; - bp->b_ioflags &= ~BIO_ERROR; - bp->b_dirtyoff = bp->b_dirtyend = 0; - bufdone(bp); - } - } - } - - /* - * Start/do any write(s) that are required. - */ -loop: - BO_LOCK(bo); - TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { - if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { - if (waitfor != MNT_WAIT || passone) - continue; - - error = BUF_TIMELOCK(bp, - LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, - BO_MTX(bo), "nfsfsync", slpflag, slptimeo); - if (error == 0) - panic("nfs4_fsync: inconsistent lock"); - if (error == ENOLCK) { - error = 0; - goto loop; - } - if (nfs4_sigintr(nmp, NULL, td)) { - error = EINTR; - goto done; - } - if (slpflag == PCATCH) { - slpflag = 0; - slptimeo = 2 * hz; - } - goto loop; - } - if ((bp->b_flags & B_DELWRI) == 0) - panic("nfs4_fsync: not dirty"); - if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) { - BUF_UNLOCK(bp); - continue; - } - BO_LOCK(bo); - bremfree(bp); - if (passone || !commit) - bp->b_flags |= B_ASYNC; - else - bp->b_flags |= B_ASYNC; - bwrite(bp); - goto loop; - } - if (passone) { - passone = 0; - BO_UNLOCK(bo); - goto again; - } - if (waitfor == MNT_WAIT) { - while (bo->bo_numoutput) { - error = bufobj_wwait(bo, slpflag, slptimeo); - if (error) { - BO_UNLOCK(bo); - if (nfs4_sigintr(nmp, NULL, td)) { - error = EINTR; - goto done; - } - if (slpflag == PCATCH) { - slpflag = 0; - slptimeo = 2 * hz; - } - BO_LOCK(bo); - } - } - if (vp->v_bufobj.bo_dirty.bv_cnt > 0 && commit) { - BO_UNLOCK(bo); - goto loop; - } - } - BO_UNLOCK(bo); - if (np->n_flag & NWRITEERR) { - error = np->n_error; - np->n_flag &= ~NWRITEERR; - } -done: - if (bvec != NULL && bvec != bvec_on_stack) - free(bvec, M_TEMP); - return (error); -} - -/* - * NFS advisory byte-level locks. - */ -static int -nfs4_advlock(struct vop_advlock_args *ap) -{ - struct vnode *vp = ap->a_vp; - u_quad_t size; - int error; - - return (EPERM); - - error = vn_lock(vp, LK_SHARED); - if (error) - return (error); - if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) { - size = VTONFS(vp)->n_size; - VOP_UNLOCK(vp, 0); - error = lf_advlock(ap, &(vp->v_lockf), size); - } else - error = nfs_dolock(ap); - return (error); -} - -/* - * NFS advisory byte-level locks. - */ -static int -nfs4_advlockasync(struct vop_advlockasync_args *ap) -{ - struct vnode *vp = ap->a_vp; - u_quad_t size; - int error; - - return (EPERM); - - error = vn_lock(vp, LK_SHARED); - if (error) - return (error); - if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) { - size = VTONFS(vp)->n_size; - VOP_UNLOCK(vp, 0); - error = lf_advlockasync(ap, &(vp->v_lockf), size); - } else { - VOP_UNLOCK(vp, 0); - error = EOPNOTSUPP; - } - return (error); -} - -/* - * Print out the contents of an nfsnode. - */ -static int -nfs4_print(struct vop_print_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct nfsnode *np = VTONFS(vp); - - printf("\tfileid %ld fsid 0x%x", - np->n_vattr.va_fileid, np->n_vattr.va_fsid); - if (vp->v_type == VFIFO) - fifo_printinfo(vp); - printf("\n"); - return (0); -} - -/* - * This is the "real" nfs::bwrite(struct buf*). - * We set B_CACHE if this is a VMIO buffer. - */ -int -nfs4_writebp(struct buf *bp, int force __unused, struct thread *td) -{ - int s; - int oldflags = bp->b_flags; -#if 0 - int retv = 1; - off_t off; -#endif - - BUF_ASSERT_HELD(bp); - - if (bp->b_flags & B_INVAL) { - brelse(bp); - return(0); - } - - bp->b_flags |= B_CACHE; - - /* - * Undirty the bp. We will redirty it later if the I/O fails. - */ - - s = splbio(); - bundirty(bp); - bp->b_flags &= ~B_DONE; - bp->b_ioflags &= ~BIO_ERROR; - bp->b_iocmd = BIO_WRITE; - - bufobj_wref(bp->b_bufobj); - curthread->td_ru.ru_oublock++; - splx(s); - - /* - * Note: to avoid loopback deadlocks, we do not - * assign b_runningbufspace. - */ - vfs_busy_pages(bp, 1); - - BUF_KERNPROC(bp); - bp->b_iooffset = dbtob(bp->b_blkno); - bstrategy(bp); - - if( (oldflags & B_ASYNC) == 0) { - int rtval = bufwait(bp); - - if (oldflags & B_DELWRI) { - s = splbio(); - reassignbuf(bp); - splx(s); - } - - brelse(bp); - return (rtval); - } - - return (0); -} - -/* - * Just call nfs_writebp() with the force argument set to 1. - * - * NOTE: B_DONE may or may not be set in a_bp on call. - */ -static int -nfs4_bwrite(struct buf *bp) -{ - - return (nfs4_writebp(bp, 1, curthread)); -} - -struct buf_ops buf_ops_nfs4 = { - .bop_name = "buf_ops_nfs4", - .bop_write = nfs4_bwrite, - .bop_strategy = bufstrategy, - .bop_sync = bufsync, - .bop_bdflush = bufbdflush, -}; diff --git a/sys/nfs4client/nfs4m_subs.h b/sys/nfs4client/nfs4m_subs.h deleted file mode 100644 index 60d0758..0000000 --- a/sys/nfs4client/nfs4m_subs.h +++ /dev/null @@ -1,498 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: nfs4m_subs.h,v 1.36 2003/11/05 14:59:01 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. - */ - -#ifndef _NFS4CLIENT_NFSM4_SUBS_H -#define _NFS4CLIENT_NFSM4_SUBS_H - -void nfsm_v4init(void); - -void nfsm_buildf_xx(struct mbuf **mb, caddr_t *bpos, char *fmt, ...); -int nfsm_dissectf_xx(struct mbuf **md, caddr_t *dpos, char *fmt, ...); - -int nfsm_v4build_compound_xx(struct nfs4_compound *, char *, - struct mbuf **, caddr_t *); -int nfsm_v4build_putfh_xx(struct nfs4_compound *, struct vnode *, - struct mbuf **, caddr_t *); -int nfsm_v4build_putfh_nv_xx(struct nfs4_compound *, struct nfs4_oparg_getfh *, - struct mbuf **, caddr_t *); -int nfsm_v4build_getattr_xx(struct nfs4_compound *, struct nfs4_oparg_getattr *, - struct mbuf **, caddr_t *); -int nfsm_v4build_finalize_xx(struct nfs4_compound *, struct mbuf **, caddr_t *); -int nfsm_v4build_getfh_xx(struct nfs4_compound *, struct nfs4_oparg_getfh *, - struct mbuf **, caddr_t *); -int nfsm_v4build_lookup_xx(struct nfs4_compound *, struct nfs4_oparg_lookup *, - struct mbuf **, caddr_t *); -int nfsm_v4build_setclientid_xx(struct nfs4_compound *, - struct nfs4_oparg_setclientid *, struct mbuf **, caddr_t *); -int nfsm_v4build_setclientid_confirm_xx(struct nfs4_compound *, - struct nfs4_oparg_setclientid *, struct mbuf **, caddr_t *); -int nfsm_v4build_close_xx(struct nfs4_compound *, struct nfs4_fctx *, - struct mbuf **, caddr_t *); -int nfsm_v4build_access_xx(struct nfs4_compound *, struct nfs4_oparg_access *, - struct mbuf **, caddr_t *); -int nfsm_v4build_open_xx(struct nfs4_compound *, struct nfs4_oparg_open *, - struct mbuf **, caddr_t *); -int nfsm_v4build_open_confirm_xx(struct nfs4_compound *, struct nfs4_oparg_open *, - struct mbuf **, caddr_t *); -int nfsm_v4build_read_xx(struct nfs4_compound *, struct nfs4_oparg_read *, - struct mbuf **, caddr_t *); -int nfsm_v4build_write_xx(struct nfs4_compound *, struct nfs4_oparg_write *, - struct mbuf **, caddr_t *); -int nfsm_v4build_commit_xx(struct nfs4_compound *, struct nfs4_oparg_commit *, - struct mbuf **, caddr_t *); -int nfsm_v4build_readdir_xx(struct nfs4_compound *, struct nfs4_oparg_readdir *, - struct mbuf **, caddr_t *); -int nfsm_v4build_renew_xx(struct nfs4_compound *, uint64_t, - struct mbuf **, caddr_t *); -int nfsm_v4build_setattr_xx(struct nfs4_compound *, struct vattr *, - struct nfs4_fctx *, struct mbuf **, caddr_t *); -int nfsm_v4build_create_xx(struct nfs4_compound *, struct nfs4_oparg_create *, - struct mbuf **, caddr_t *); -int nfsm_v4build_rename_xx(struct nfs4_compound *, struct nfs4_oparg_rename *, - struct mbuf **, caddr_t *); -int nfsm_v4build_link_xx(struct nfs4_compound *, struct nfs4_oparg_link *, - struct mbuf **, caddr_t *); -int nfsm_v4build_remove_xx(struct nfs4_compound *, const char *, u_int, - struct mbuf **, caddr_t *); - -int nfsm_v4dissect_compound_xx(struct nfs4_compound *, struct mbuf **, caddr_t *); -int nfsm_v4dissect_getattr_xx(struct nfs4_compound *, struct nfs4_oparg_getattr *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_getfh_xx(struct nfs4_compound *, struct nfs4_oparg_getfh *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_setclientid_xx(struct nfs4_compound *, - struct nfs4_oparg_setclientid *, struct mbuf **, caddr_t *); -int nfsm_v4dissect_close_xx(struct nfs4_compound *, struct nfs4_fctx *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_access_xx(struct nfs4_compound *, struct nfs4_oparg_access *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_open_xx(struct nfs4_compound *, struct nfs4_oparg_open *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_open_confirm_xx(struct nfs4_compound *, struct nfs4_oparg_open *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_read_xx(struct nfs4_compound *, struct nfs4_oparg_read *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_write_xx(struct nfs4_compound *, struct nfs4_oparg_write *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_commit_xx(struct nfs4_compound *, struct nfs4_oparg_commit *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_setattr_xx(struct nfs4_compound *, struct mbuf **, caddr_t *); -int nfsm_v4dissect_create_xx(struct nfs4_compound *, struct nfs4_oparg_create *, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_readlink_xx(struct nfs4_compound *, struct uio *, - struct mbuf **, caddr_t *); - -int nfsm_v4dissect_attrs_xx(struct nfsv4_fattr *, struct mbuf **, caddr_t *); - -int nfsm_v4build_simple_xx(struct nfs4_compound *, uint32_t, - struct mbuf **, caddr_t *); -int nfsm_v4dissect_simple_xx(struct nfs4_compound *, uint32_t, - uint32_t, struct mbuf **, caddr_t *); - -#define nfsm_v4build_putrootfh_xx(cp, mb, bpos) \ - nfsm_v4build_simple_xx((cp), NFSV4OP_PUTROOTFH, (mb), (bpos)) - -#define nfsm_v4build_lookupp_xx(cp, mb, bpos) \ - nfsm_v4build_simple_xx((cp), NFSV4OP_LOOKUPP, (mb), (bpos)) - -#define nfsm_v4build_savefh_xx(cp, mb, bpos) \ - nfsm_v4build_simple_xx((cp), NFSV4OP_SAVEFH, (mb), (bpos)) - -#define nfsm_v4build_readlink_xx(cp, mb, bpos) \ - nfsm_v4build_simple_xx((cp), NFSV4OP_READLINK, (mb), (bpos)) - - -#define nfsm_v4dissect_putrootfh_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_PUTROOTFH, 0, (mb), (bpos)) - -#define nfsm_v4dissect_lookup_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_LOOKUP, 0, (mb), (bpos)) - -#define nfsm_v4dissect_lookupp_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_LOOKUPP, 0, (mb), (bpos)) - -#define nfsm_v4dissect_putfh_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_PUTFH, 0, (mb), (bpos)) - -#define nfsm_v4dissect_renew_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_RENEW, 0, (mb), (bpos)) - -#define nfsm_v4dissect_setclientid_confirm_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_SETCLIENTID_CONFIRM, 0, (mb), (bpos)) - -#define nfsm_v4dissect_rename_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_RENAME, 0, (mb), (bpos)) - -#define nfsm_v4dissect_link_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_LINK, 0, (mb), (bpos)) - -#define nfsm_v4dissect_savefh_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_SAVEFH, 0, (mb), (bpos)) - -#define nfsm_v4dissect_remove_xx(cp, mb, bpos) \ - nfsm_v4dissect_simple_xx((cp), NFSV4OP_REMOVE, 0, (mb), (bpos)) - -#define nfsm_v4build_compound(cp, tag) do { \ - int32_t t1; \ - t1 = nfsm_v4build_compound_xx((cp), (tag), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_finalize(cp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_finalize_xx((cp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_putfh(cp, vp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_putfh_xx((cp), (vp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_putfh_nv(cp, gfh) do { \ - int32_t t1; \ - t1 = nfsm_v4build_putfh_nv_xx((cp), (gfh), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_putrootfh(cp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_putrootfh_xx((cp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_getattr(cp, ga) do { \ - int32_t t1; \ - t1 = nfsm_v4build_getattr_xx((cp), (ga), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_setattr(cp, vap, fcp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_setattr_xx((cp), (vap), (fcp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_lookup(cp, l) do { \ - int32_t t1; \ - t1 = nfsm_v4build_lookup_xx((cp), (l), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_lookupp(cp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_lookupp_xx((cp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_getfh(cp, gfh) do { \ - int32_t t1; \ - t1 = nfsm_v4build_getfh_xx((cp), (gfh), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_close(cp, fcp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_close_xx((cp), (fcp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_access(cp, acc) do { \ - int32_t t1; \ - t1 = nfsm_v4build_access_xx((cp), (acc), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_open(cp, o) do { \ - int32_t t1; \ - t1 = nfsm_v4build_open_xx((cp), (o), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_open_confirm(cp, o) do { \ - int32_t t1; \ - t1 = nfsm_v4build_open_confirm_xx((cp), (o), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_read(cp, r) do { \ - int32_t t1; \ - t1 = nfsm_v4build_read_xx((cp), (r), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_write(cp, w) do { \ - int32_t t1; \ - t1 = nfsm_v4build_write_xx((cp), (w), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_commit(cp, c) do { \ - int32_t t1; \ - t1 = nfsm_v4build_commit_xx((cp), (c), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_readdir(cp, r) do { \ - int32_t t1; \ - t1 = nfsm_v4build_readdir_xx((cp), (r), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_renew(cp, cid) do { \ - int32_t t1; \ - t1 = nfsm_v4build_renew_xx((cp), (cid), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_setclientid(cp, cid) do { \ - int32_t t1; \ - t1 = nfsm_v4build_setclientid_xx((cp), (cid), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_setclientid_confirm(cp, cid) do { \ - int32_t t1; \ - t1 = nfsm_v4build_setclientid_confirm_xx((cp), (cid), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_create(cp, c) do { \ - int32_t t1; \ - t1 = nfsm_v4build_create_xx((cp), (c), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_rename(cp, r) do { \ - int32_t t1; \ - t1 = nfsm_v4build_rename_xx((cp), (r), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_link(cp, r) do { \ - int32_t t1; \ - t1 = nfsm_v4build_link_xx((cp), (r), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_savefh(cp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_savefh_xx((cp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_readlink(cp) do { \ - int32_t t1; \ - t1 = nfsm_v4build_readlink_xx((cp), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -#define nfsm_v4build_remove(cp, name, namelen) do { \ - int32_t t1; \ - t1 = nfsm_v4build_remove_xx((cp), (name), (namelen), &mb, &bpos); \ - nfsm_bcheck(t1, mreq); \ -} while (0) - -/* --- */ - -#define nfsm_v4dissect_compound(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_compound_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_putfh(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_putfh_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_putrootfh(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_putrootfh_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_getattr(cp, ga) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_getattr_xx((cp), (ga), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_setattr(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_setattr_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_lookup(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_lookup_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_lookupp(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_lookupp_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_getfh(cp, gfh) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_getfh_xx((cp), (gfh), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_setclientid(cp, sci) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_setclientid_xx((cp), (sci), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_setclientid_confirm(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_setclientid_confirm_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_close(cp, fcp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_close_xx((cp), (fcp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_access(cp, acc) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_access_xx((cp), (acc), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_open(cp, openp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_open_xx((cp), (openp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_open_confirm(cp, openp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_open_confirm_xx((cp), (openp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_read(cp, r) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_read_xx((cp), (r), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_write(cp, w) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_write_xx((cp), (w), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_commit(cp, c) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_commit_xx((cp), (c), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_attrs(fattr) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_attrs_xx((fattr), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_renew(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_renew_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_create(cp, c) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_create_xx((cp), (c), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_rename(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_rename_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_link(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_link_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_savefh(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_savefh_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_readlink(cp, uiop) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_readlink_xx((cp), (uiop), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#define nfsm_v4dissect_remove(cp) \ -do { \ - int32_t t1; \ - t1 = nfsm_v4dissect_remove_xx((cp), &md, &dpos); \ - nfsm_dcheck(t1, mrep); \ -} while (0) - -#endif /* _NFS4CLIENT_NFSM4_SUBS_H */ diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c index f9bc5bf..05702f6 100644 --- a/sys/nfsclient/bootp_subr.c +++ b/sys/nfsclient/bootp_subr.c @@ -68,8 +68,6 @@ __FBSDID("$FreeBSD$"); #include <net/if_dl.h> #include <net/vnet.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> diff --git a/sys/nfsclient/krpc_subr.c b/sys/nfsclient/krpc_subr.c index 5682083..2023904 100644 --- a/sys/nfsclient/krpc_subr.c +++ b/sys/nfsclient/krpc_subr.c @@ -57,8 +57,6 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <netinet/in.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfsclient/krpc.h> #include <nfs/xdr_subs.h> diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h index 7f3a0f3..845f826 100644 --- a/sys/nfsclient/nfs.h +++ b/sys/nfsclient/nfs.h @@ -111,18 +111,6 @@ */ #define NFS_NFSSTATS 1 /* struct: struct nfsstats */ -/* - * File context information for nfsv4. Currently, there is only one - * lockowner for the whole machine "0." - */ -struct nfs4_fctx { - TAILQ_ENTRY(nfs4_fstate) next; - uint32_t refcnt; - struct nfs4_lowner *lop; - struct nfsnode *np; - char stateid[NFSX_V4STATEID]; -}; - #ifdef _KERNEL #ifdef MALLOC_DECLARE diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index 6c468fb..92be17c 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bio.h> #include <sys/buf.h> #include <sys/kernel.h> +#include <sys/mbuf.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/resourcevar.h> @@ -56,8 +57,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_pager.h> #include <vm/vnode_pager.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> @@ -65,8 +64,6 @@ __FBSDID("$FreeBSD$"); #include <nfsclient/nfsnode.h> #include <nfsclient/nfs_kdtrace.h> -#include <nfs4client/nfs4.h> - static struct buf *nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, struct thread *td); static int nfs_directio_write(struct vnode *vp, struct uio *uiop, @@ -1612,17 +1609,13 @@ nfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td) case VDIR: nfsstats.readdir_bios++; uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ; - if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) - error = nfs4_readdirrpc(vp, uiop, cr); - else { - if ((nmp->nm_flag & NFSMNT_RDIRPLUS) != 0) { - error = nfs_readdirplusrpc(vp, uiop, cr); - if (error == NFSERR_NOTSUPP) - nmp->nm_flag &= ~NFSMNT_RDIRPLUS; - } - if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) - error = nfs_readdirrpc(vp, uiop, cr); + if ((nmp->nm_flag & NFSMNT_RDIRPLUS) != 0) { + error = nfs_readdirplusrpc(vp, uiop, cr); + if (error == NFSERR_NOTSUPP) + nmp->nm_flag &= ~NFSMNT_RDIRPLUS; } + if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) + error = nfs_readdirrpc(vp, uiop, cr); /* * end-of-directory sets B_INVAL but does not generate an * error. diff --git a/sys/nfsclient/nfs_diskless.c b/sys/nfsclient/nfs_diskless.c index d6d6b21..26a27b9 100644 --- a/sys/nfsclient/nfs_diskless.c +++ b/sys/nfsclient/nfs_diskless.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <net/vnet.h> #include <netinet/in.h> -#include <rpc/rpcclnt.h> #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c index 7f5c624..1aa398e 100644 --- a/sys/nfsclient/nfs_krpc.c +++ b/sys/nfsclient/nfs_krpc.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include <sys/vnode.h> #include <rpc/rpc.h> -#include <rpc/rpcclnt.h> #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> @@ -70,8 +69,6 @@ __FBSDID("$FreeBSD$"); #include <nfsclient/nfsmount.h> #include <nfsclient/nfsnode.h> -#include <nfs4client/nfs4.h> - #ifndef NFS_LEGACYRPC #ifdef KDTRACE_HOOKS @@ -445,8 +442,6 @@ nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum, return (ESTALE); } nmp = VFSTONFS(vp->v_mount); - if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) - return nfs4_request(vp, mreq, procnum, td, cred, mrp, mdp, dposp); bzero(&nf, sizeof(struct nfs_feedback_arg)); nf.nf_mount = nmp; nf.nf_td = td; @@ -740,8 +735,6 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td) struct proc *p; sigset_t tmpset; - if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) - return nfs4_sigintr(nmp, rep, td); /* Terminate all requests while attempting a forced unmount. */ if (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF) return (EIO); diff --git a/sys/nfsclient/nfs_lock.c b/sys/nfsclient/nfs_lock.c index 19ad066..ea6649e 100644 --- a/sys/nfsclient/nfs_lock.c +++ b/sys/nfsclient/nfs_lock.c @@ -53,8 +53,6 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c index 9e0e272..7dc3f19 100644 --- a/sys/nfsclient/nfs_nfsiod.c +++ b/sys/nfsclient/nfs_nfsiod.c @@ -63,8 +63,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include <netinet/tcp.h> -#include <rpc/rpcclnt.h> - #include <nfs/xdr_subs.h> #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c index 517c3a9..a7f00ca 100644 --- a/sys/nfsclient/nfs_node.c +++ b/sys/nfsclient/nfs_node.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/fnv_hash.h> #include <sys/lock.h> #include <sys/malloc.h> +#include <sys/mbuf.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/proc.h> @@ -49,8 +50,6 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> @@ -133,19 +132,13 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp, int */ np = uma_zalloc(nfsnode_zone, M_WAITOK | M_ZERO); - if (nmp->nm_flag & NFSMNT_NFSV4) - error = getnewvnode("nfs4", mntp, &nfs4_vnodeops, &nvp); - else - error = getnewvnode("nfs", mntp, &nfs_vnodeops, &nvp); + error = getnewvnode("nfs", mntp, &nfs_vnodeops, &nvp); if (error) { uma_zfree(nfsnode_zone, np); return (error); } vp = nvp; - if (nmp->nm_flag & NFSMNT_NFSV4) - vp->v_bufobj.bo_ops = &buf_ops_nfs4; - else - vp->v_bufobj.bo_ops = &buf_ops_nfs; + vp->v_bufobj.bo_ops = &buf_ops_nfs; vp->v_data = np; np->n_vnode = vp; /* diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c index 42ef655..64951fa 100644 --- a/sys/nfsclient/nfs_socket.c +++ b/sys/nfsclient/nfs_socket.c @@ -62,8 +62,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include <netinet/tcp.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> @@ -72,8 +70,6 @@ __FBSDID("$FreeBSD$"); #include <nfsclient/nfsmount.h> #include <nfsclient/nfsnode.h> -#include <nfs4client/nfs4.h> - #ifdef NFS_LEGACYRPC #define TRUE 1 @@ -1145,8 +1141,6 @@ nfs_request(struct vnode *vp, struct mbuf *mrest, int procnum, return (ESTALE); } nmp = VFSTONFS(vp->v_mount); - if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) - return nfs4_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp); rep = malloc(sizeof(struct nfsreq), M_NFSREQ, M_WAITOK); bzero(rep, sizeof(struct nfsreq)); rep->r_nmp = nmp; @@ -1747,8 +1741,6 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td) struct proc *p; sigset_t tmpset; - if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) - return nfs4_sigintr(nmp, rep, td); if (rep) { mtx_lock(&rep->r_mtx); if (rep->r_flags & R_SOFTTERM) { diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index 1453dbf..71d4fb1 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -65,8 +65,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_extern.h> #include <vm/uma.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index d8ce36c..7d48023 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -66,7 +66,6 @@ __FBSDID("$FreeBSD$"); #include <net/route.h> #include <netinet/in.h> -#include <rpc/rpcclnt.h> #include <rpc/rpc.h> #include <nfs/rpcv2.h> diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 27d2c59..9f0d67a 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -70,8 +70,6 @@ __FBSDID("$FreeBSD$"); #include <fs/fifofs/fifo.h> -#include <rpc/rpcclnt.h> - #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> diff --git a/sys/nfsclient/nfsm_subs.h b/sys/nfsclient/nfsm_subs.h index 3dd817f..51d2611 100644 --- a/sys/nfsclient/nfsm_subs.h +++ b/sys/nfsclient/nfsm_subs.h @@ -147,17 +147,6 @@ do { \ } \ } while (0) -#define nfsm_request_mnt(n, t, p, c) \ -do { \ - error = nfs4_request_mnt((n), mreq, (t), (p), (c), &mrep, &md, &dpos); \ - if (error != 0) { \ - if (error & NFSERR_RETERR) \ - error &= ~NFSERR_RETERR; \ - else \ - goto nfsmout; \ - } \ -} while (0) - /* *********************************** */ /* Reply interpretation phase macros */ diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h index 75360fe..85f8501 100644 --- a/sys/nfsclient/nfsmount.h +++ b/sys/nfsclient/nfsmount.h @@ -79,7 +79,6 @@ struct nfsmount { int nm_numgrps; /* Max. size of groupslist */ u_char nm_fh[NFSX_V4FH]; /* File handle of root dir */ int nm_fhsize; /* Size of root file handle */ - struct rpcclnt nm_rpcclnt; /* rpc state */ #ifdef NFS_LEGACYRPC struct socket *nm_so; /* Rpc socket */ #endif diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h index 6f10d79..29198d8 100644 --- a/sys/nfsclient/nfsnode.h +++ b/sys/nfsclient/nfsnode.h @@ -135,8 +135,6 @@ struct nfsnode { short n_fhsize; /* size in bytes, of fh */ short n_flag; /* Flag for locking.. */ nfsfh_t n_fh; /* Small File Handle */ - struct nfs4_fctx n_rfc; - struct nfs4_fctx n_wfc; u_char *n_name; /* leaf name, for v4 OPEN op */ uint32_t n_namelen; int n_directio_opens; @@ -188,9 +186,7 @@ extern struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; extern struct vop_vector nfs_fifoops; extern struct vop_vector nfs_vnodeops; -extern struct vop_vector nfs4_vnodeops; extern struct buf_ops buf_ops_nfs; -extern struct buf_ops buf_ops_nfs4; extern vop_advlock_t *nfs_advlock_p; extern vop_reclaim_t *nfs_reclaim_p; @@ -206,12 +202,9 @@ int nfs_reclaim(struct vop_reclaim_args *); /* other stuff */ int nfs_removeit(struct sillyrename *); -int nfs4_removeit(struct sillyrename *); int nfs_nget(struct mount *, nfsfh_t *, int, struct nfsnode **, int flags); nfsuint64 *nfs_getcookie(struct nfsnode *, off_t, int); -uint64_t *nfs4_getcookie(struct nfsnode *, off_t, int); void nfs_invaldir(struct vnode *); -void nfs4_invaldir(struct vnode *); int nfs_upgrade_vnlock(struct vnode *vp); void nfs_downgrade_vnlock(struct vnode *vp, int old_lock); void nfs_printf(const char *fmt, ...); diff --git a/sys/nlm/nlm_advlock.c b/sys/nlm/nlm_advlock.c index a2c62f0..761ed73 100644 --- a/sys/nlm/nlm_advlock.c +++ b/sys/nlm/nlm_advlock.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/lockf.h> #include <sys/malloc.h> +#include <sys/mbuf.h> #include <sys/mount.h> #include <sys/mutex.h> #include <sys/proc.h> @@ -44,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include <sys/vimage.h> #include <sys/vnode.h> -#include <rpc/rpcclnt.h> #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> #include <nfsclient/nfsnode.h> diff --git a/sys/rpc/rpcclnt.c b/sys/rpc/rpcclnt.c deleted file mode 100644 index 1c90ff6..0000000 --- a/sys/rpc/rpcclnt.c +++ /dev/null @@ -1,2114 +0,0 @@ -/* $FreeBSD$ */ -/* $Id: rpcclnt.c,v 1.9 2003/11/05 14:59:03 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. - */ - -/*- - * Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of - * California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by Rick Macklem at - * The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. 3. All advertising - * materials mentioning features or use of this software must display the - * following acknowledgement: This product includes software developed by the - * University of California, Berkeley and its contributors. 4. Neither the - * name of the University nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95 - */ - -/* XXX: kill ugly debug strings */ -/* XXX: get rid of proct, as it is not even being used... (or keep it so v{2,3} - * can run, but clean it up! */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/mount.h> -#include <sys/kernel.h> -#include <sys/mbuf.h> -#include <sys/syslog.h> -#include <sys/malloc.h> -#include <sys/uio.h> -#include <sys/lock.h> -#include <sys/signalvar.h> -#include <sys/sysent.h> -#include <sys/syscall.h> -#include <sys/sysctl.h> - -#include <sys/domain.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/mutex.h> - -#include <netinet/in.h> -#include <netinet/tcp.h> - -#include <nfs/rpcv2.h> - -#include <rpc/rpcm_subs.h> -#include <rpc/rpcclnt.h> - -/* memory management */ -#ifdef __OpenBSD__ -struct pool rpctask_pool; -struct pool rpcclnt_pool; -#define RPCTASKPOOL_LWM 10 -#define RPCTASKPOOL_HWM 40 -#else -static MALLOC_DEFINE(M_RPCCLNT, "rpcclnt", "rpc state"); -#endif - -#define RPC_RETURN(X) do { RPCDEBUG("returning %d", X); return X; }while(0) - -/* - * Estimate rto for an nfs rpc sent via. an unreliable datagram. Use the mean - * and mean deviation of rtt for the appropriate type of rpc for the frequent - * rpcs and a default for the others. The justification for doing "other" - * this way is that these rpcs happen so infrequently that timer est. would - * probably be stale. Also, since many of these rpcs are non-idempotent, a - * conservative timeout is desired. getattr, lookup - A+2D read, write - - * A+4D other - nm_timeo - */ -#define RPC_RTO(n, t) \ - ((t) == 0 ? (n)->rc_timeo : \ - ((t) < 3 ? \ - (((((n)->rc_srtt[t-1] + 3) >> 2) + (n)->rc_sdrtt[t-1] + 1) >> 1) : \ - ((((n)->rc_srtt[t-1] + 7) >> 3) + (n)->rc_sdrtt[t-1] + 1))) - -#define RPC_SRTT(s,r) (r)->r_rpcclnt->rc_srtt[rpcclnt_proct((s),\ - (r)->r_procnum) - 1] - -#define RPC_SDRTT(s,r) (r)->r_rpcclnt->rc_sdrtt[rpcclnt_proct((s),\ - (r)->r_procnum) - 1] - - -/* - * There is a congestion window for outstanding rpcs maintained per mount - * point. The cwnd size is adjusted in roughly the way that: Van Jacobson, - * Congestion avoidance and Control, In "Proceedings of SIGCOMM '88". ACM, - * August 1988. describes for TCP. The cwnd size is chopped in half on a - * retransmit timeout and incremented by 1/cwnd when each rpc reply is - * received and a full cwnd of rpcs is in progress. (The sent count and cwnd - * are scaled for integer arith.) Variants of "slow start" were tried and - * were found to be too much of a performance hit (ave. rtt 3 times larger), - * I suspect due to the large rtt that nfs rpcs have. - */ -#define RPC_CWNDSCALE 256 -#define RPC_MAXCWND (RPC_CWNDSCALE * 32) -static const int rpcclnt_backoff[8] = {2, 4, 8, 16, 32, 64, 128, 256,}; - -/* XXX ugly debug strings */ -#define RPC_ERRSTR_ACCEPTED_SIZE 6 -char *rpc_errstr_accepted[RPC_ERRSTR_ACCEPTED_SIZE] = { - "", /* no good message... */ - "remote server hasn't exported program.", - "remote server can't support version number.", - "program can't support procedure.", - "procedure can't decode params.", - "remote error. remote side memory allocation failure?" -}; - -char *rpc_errstr_denied[2] = { - "remote server doesnt support rpc version 2!", - "remote server authentication error." -}; - -#define RPC_ERRSTR_AUTH_SIZE 6 -char *rpc_errstr_auth[RPC_ERRSTR_AUTH_SIZE] = { - "", - "auth error: bad credential (seal broken).", - "auth error: client must begin new session.", - "auth error: bad verifier (seal broken).", - "auth error: verifier expired or replayed.", - "auth error: rejected for security reasons.", -}; - -/* - * Static data, mostly RPC constants in XDR form - */ -static u_int32_t rpc_reply, rpc_call, rpc_vers; - -/* - * rpc_msgdenied, rpc_mismatch, rpc_auth_unix, rpc_msgaccepted, - * rpc_autherr, rpc_auth_kerb; - */ - -static u_int32_t rpcclnt_xid = 0; -static u_int32_t rpcclnt_xid_touched = 0; -struct rpcstats rpcstats; -int rpcclnt_ticks; -static int fake_wchan; - -SYSCTL_NODE(_kern, OID_AUTO, rpc, CTLFLAG_RD, 0, "RPC Subsystem"); - -SYSCTL_UINT(_kern_rpc, OID_AUTO, retries, CTLFLAG_RD, &rpcstats.rpcretries, 0, "retries"); -SYSCTL_UINT(_kern_rpc, OID_AUTO, request, CTLFLAG_RD, &rpcstats.rpcrequests, 0, "request"); -SYSCTL_UINT(_kern_rpc, OID_AUTO, timeouts, CTLFLAG_RD, &rpcstats.rpctimeouts, 0, "timeouts"); -SYSCTL_UINT(_kern_rpc, OID_AUTO, unexpected, CTLFLAG_RD, &rpcstats.rpcunexpected, 0, "unexpected"); -SYSCTL_UINT(_kern_rpc, OID_AUTO, invalid, CTLFLAG_RD, &rpcstats.rpcinvalid, 0, "invalid"); - - -#ifdef RPCCLNT_DEBUG -int rpcdebugon = 0; -SYSCTL_UINT(_kern_rpc, OID_AUTO, debug_on, CTLFLAG_RW, &rpcdebugon, 0, "RPC Debug messages"); -#endif - -/* - * Queue head for rpctask's - */ -static -TAILQ_HEAD(, rpctask) rpctask_q; -struct callout rpcclnt_callout; - -#ifdef __OpenBSD__ -static int rpcclnt_send(struct socket *, struct mbuf *, struct mbuf *, struct rpctask *); -static int rpcclnt_receive(struct rpctask *, struct mbuf **, struct mbuf **, RPC_EXEC_CTX); -#else -static int rpcclnt_send(struct socket *, struct sockaddr *, struct mbuf *, struct rpctask *); -static int rpcclnt_receive(struct rpctask *, struct sockaddr **, struct mbuf **, RPC_EXEC_CTX); -#endif - -static int rpcclnt_msg(RPC_EXEC_CTX, const char *, char *); - -static int rpcclnt_reply(struct rpctask *, RPC_EXEC_CTX); -static void rpcclnt_timer(void *); -static int rpcclnt_sndlock(int *, struct rpctask *); -static void rpcclnt_sndunlock(int *); -static int rpcclnt_rcvlock(struct rpctask *); -static void rpcclnt_rcvunlock(int *); -#if 0 -void rpcclnt_realign(struct mbuf *, int); -#else -static void rpcclnt_realign(struct mbuf **, int); -#endif - -static struct mbuf *rpcclnt_buildheader(struct rpcclnt *, int, struct mbuf *, u_int32_t, int *, struct mbuf **, struct ucred *); -static int rpcm_disct(struct mbuf **, caddr_t *, int, int, caddr_t *); -static u_int32_t rpcclnt_proct(struct rpcclnt *, u_int32_t); -static int rpc_adv(struct mbuf **, caddr_t *, int, int); -static void rpcclnt_softterm(struct rpctask * task); - -static int rpcauth_buildheader(struct rpc_auth * auth, struct ucred *, struct mbuf **, caddr_t *); - -void -rpcclnt_init(void) -{ -#ifdef __OpenBSD__ - static struct timeout rpcclnt_timer_to; -#endif - - rpcclnt_ticks = (hz * RPC_TICKINTVL + 500) / 1000; - if (rpcclnt_ticks < 1) - rpcclnt_ticks = 1; - rpcstats.rpcretries = 0; - rpcstats.rpcrequests = 0; - rpcstats.rpctimeouts = 0; - rpcstats.rpcunexpected = 0; - rpcstats.rpcinvalid = 0; - - /* - * rpc constants how about actually using more than one of these! - */ - - rpc_reply = txdr_unsigned(RPC_REPLY); - rpc_vers = txdr_unsigned(RPC_VER2); - rpc_call = txdr_unsigned(RPC_CALL); -#if 0 - rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); - rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); - rpc_mismatch = txdr_unsigned(RPC_MISMATCH); - rpc_autherr = txdr_unsigned(RPC_AUTHERR); - rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); - rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4); -#endif - - /* initialize rpctask queue */ - TAILQ_INIT(&rpctask_q); - -#ifdef __OpenBSD__ - /* initialize pools */ - pool_init(&rpctask_pool, sizeof(struct rpctask), 0, 0, RPCTASKPOOL_LWM, - "rpctask_p", NULL); - pool_setlowat(&rpctask_pool, RPCTASKPOOL_LWM); - pool_sethiwat(&rpctask_pool, RPCTASKPOOL_HWM); - - pool_init(&rpcclnt_pool, sizeof(struct rpcclnt), 0, 0, 1, "rpcclnt_p", NULL); - - /* initialize timers */ - timeout_set(&rpcclnt_timer_to, rpcclnt_timer, &rpcclnt_timer_to); - rpcclnt_timer(&rpcclnt_timer_to); -#else /* !__OpenBSD__ */ - callout_init(&rpcclnt_callout, 0); -#endif /* !__OpenBSD__ */ - - RPCDEBUG("rpc initialed"); - - return; -} - -void -rpcclnt_uninit(void) -{ - RPCDEBUG("uninit"); - /* XXX delete sysctl variables? */ - callout_stop(&rpcclnt_callout); -} - -int -rpcclnt_setup(clnt, program, addr, sotype, soproto, auth, max_read_size, max_write_size, flags) - struct rpcclnt * clnt; - struct rpc_program * program; - struct sockaddr * addr; - int sotype; - int soproto; - struct rpc_auth * auth; - int max_read_size; - int max_write_size; - int flags; -{ - if (clnt == NULL || program == NULL || addr == NULL || auth == NULL) - RPC_RETURN (EFAULT); - - if (program->prog_name == NULL) - RPC_RETURN (EFAULT); - clnt->rc_prog = program; - - clnt->rc_name = addr; - clnt->rc_sotype = sotype; - clnt->rc_soproto = soproto; - clnt->rc_auth = auth; - clnt->rc_rsize = max_read_size; - clnt->rc_wsize = max_write_size; - clnt->rc_flag = flags; - - clnt->rc_proctlen = 0; - clnt->rc_proct = NULL; - - RPC_RETURN (0); -} - -/* - * Initialize sockets and congestion for a new RPC connection. We do not free - * the sockaddr if error. - */ -int -rpcclnt_connect(rpc, td) - struct rpcclnt *rpc; - RPC_EXEC_CTX td; -{ - struct socket *so; - int s, error, rcvreserve, sndreserve; - struct sockaddr *saddr; - -#ifdef __OpenBSD__ - struct sockaddr_in *sin; - struct mbuf *m; -#else - struct sockaddr_in sin; - - int soarg; - struct sockopt opt; -#endif - - if (rpc == NULL) { - RPCDEBUG("no rpcclnt struct!\n"); - RPC_RETURN(EFAULT); - } - - /* create the socket */ - rpc->rc_so = NULL; - - saddr = rpc->rc_name; - - error = socreate(saddr->sa_family, &rpc->rc_so, rpc->rc_sotype, - rpc->rc_soproto, td->td_ucred, td); - if (error) { - RPCDEBUG("error %d in socreate()", error); - RPC_RETURN(error); - } - so = rpc->rc_so; - rpc->rc_soflags = so->so_proto->pr_flags; - - /* - * Some servers require that the client port be a reserved port - * number. We always allocate a reserved port, as this prevents - * filehandle disclosure through UDP port capture. - */ - if (saddr->sa_family == AF_INET) { -#ifdef __OpenBSD__ - struct mbuf *mopt; - int *ip; -#endif - -#ifdef __OpenBSD__ - MGET(mopt, M_TRYWAIT, MT_SOOPTS); - mopt->m_len = sizeof(int); - ip = mtod(mopt, int *); - *ip = IP_PORTRANGE_LOW; - - error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); -#else - soarg = IP_PORTRANGE_LOW; - bzero(&opt, sizeof(struct sockopt)); - opt.sopt_dir = SOPT_SET; - opt.sopt_level = IPPROTO_IP; - opt.sopt_name = IP_PORTRANGE; - opt.sopt_val = &soarg; - opt.sopt_valsize = sizeof(soarg); - - error = sosetopt(so, &opt); -#endif - if (error) - goto bad; - -#ifdef __OpenBSD__ - MGET(m, M_TRYWAIT, MT_SONAME); - sin = mtod(m, struct sockaddr_in *); - sin->sin_len = m->m_len = sizeof(struct sockaddr_in); - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = INADDR_ANY; - sin->sin_port = htons(0); - error = sobind(so, m); - m_freem(m); -#else - sin.sin_len = sizeof(struct sockaddr_in); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(0); - /* - * &thread0 gives us root credentials to ensure sobind - * will give us a reserved ephemeral port. - */ - error = sobind(so, (struct sockaddr *) & sin, &thread0); -#endif - if (error) - goto bad; - -#ifdef __OpenBSD__ - MGET(mopt, M_TRYWAIT, MT_SOOPTS); - mopt->m_len = sizeof(int); - ip = mtod(mopt, int *); - *ip = IP_PORTRANGE_DEFAULT; - error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); -#else - soarg = IP_PORTRANGE_DEFAULT; - bzero(&opt, sizeof(struct sockopt)); - opt.sopt_dir = SOPT_SET; - opt.sopt_level = IPPROTO_IP; - opt.sopt_name = IP_PORTRANGE; - opt.sopt_val = &soarg; - opt.sopt_valsize = sizeof(soarg); - error = sosetopt(so, &opt); -#endif - if (error) - goto bad; - } - /* - * Protocols that do not require connections may be optionally left - * unconnected for servers that reply from a port other than - * NFS_PORT. - */ - if (rpc->rc_flag & RPCCLNT_NOCONN) { - if (rpc->rc_soflags & PR_CONNREQUIRED) { - error = ENOTCONN; - goto bad; - } - } else { - error = soconnect(so, saddr, td); - if (error) - goto bad; - - /* - * Wait for the connection to complete. Cribbed from the - * connect system call but with the wait timing out so that - * interruptible mounts don't hang here for a long time. - */ -#ifdef __OpenBSD__ - s = splsoftnet(); -#else - s = splnet(); -#endif - while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - (void)tsleep((caddr_t) & so->so_timeo, PSOCK, - "rpc", 2 * hz); - - /* - * XXX needs to catch interrupt signals. something - * like this: if ((so->so_state & SS_ISCONNECTING) && - * so->so_error == 0 && rep && (error = - * nfs_sigintr(nmp, rep, rep->r_td)) != 0) { - * so->so_state &= ~SS_ISCONNECTING; splx(s); goto - * bad; } - */ - } - if (so->so_error) { - error = so->so_error; - so->so_error = 0; - splx(s); - goto bad; - } - splx(s); - } - if (rpc->rc_flag & (RPCCLNT_SOFT | RPCCLNT_INT)) { - so->so_rcv.sb_timeo = (5 * hz); - so->so_snd.sb_timeo = (5 * hz); - } else { - so->so_rcv.sb_timeo = 0; - so->so_snd.sb_timeo = 0; - } - - - if (rpc->rc_sotype == SOCK_DGRAM) { - sndreserve = rpc->rc_wsize + RPC_MAXPKTHDR; - rcvreserve = rpc->rc_rsize + RPC_MAXPKTHDR; - } else if (rpc->rc_sotype == SOCK_SEQPACKET) { - sndreserve = (rpc->rc_wsize + RPC_MAXPKTHDR) * 2; - rcvreserve = (rpc->rc_rsize + RPC_MAXPKTHDR) * 2; - } else { - if (rpc->rc_sotype != SOCK_STREAM) - panic("rpcclnt_connect() bad sotype"); - if (so->so_proto->pr_flags & PR_CONNREQUIRED) { -#ifdef __OpenBSD__ - MGET(m, M_TRYWAIT, MT_SOOPTS); - *mtod(m, int32_t *) = 1; - m->m_len = sizeof(int32_t); - sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); -#else - soarg = 1; - - bzero(&opt, sizeof(struct sockopt)); - opt.sopt_dir = SOPT_SET; - opt.sopt_level = SOL_SOCKET; - opt.sopt_name = SO_KEEPALIVE; - opt.sopt_val = &soarg; - opt.sopt_valsize = sizeof(soarg); - sosetopt(so, &opt); -#endif - } - if (so->so_proto->pr_protocol == IPPROTO_TCP) { -#ifdef __OpenBSD__ - MGET(m, M_TRYWAIT, MT_SOOPTS); - *mtod(m, int32_t *) = 1; - m->m_len = sizeof(int32_t); - sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); -#else - soarg = 1; - - bzero(&opt, sizeof(struct sockopt)); - opt.sopt_dir = SOPT_SET; - opt.sopt_level = IPPROTO_TCP; - opt.sopt_name = TCP_NODELAY; - opt.sopt_val = &soarg; - opt.sopt_valsize = sizeof(soarg); - sosetopt(so, &opt); -#endif - } - sndreserve = (rpc->rc_wsize + RPC_MAXPKTHDR + - sizeof(u_int32_t)) * 2; - rcvreserve = (rpc->rc_rsize + RPC_MAXPKTHDR + - sizeof(u_int32_t)) * 2; - } - error = soreserve(so, sndreserve, rcvreserve); - if (error) - goto bad; - so->so_rcv.sb_flags |= SB_NOINTR; - so->so_snd.sb_flags |= SB_NOINTR; - - /* Initialize other non-zero congestion variables */ - rpc->rc_srtt[0] = rpc->rc_srtt[1] = rpc->rc_srtt[2] = - rpc->rc_srtt[3] = (RPC_TIMEO << 3); - rpc->rc_sdrtt[0] = rpc->rc_sdrtt[1] = rpc->rc_sdrtt[2] = - rpc->rc_sdrtt[3] = 0; - rpc->rc_cwnd = RPC_MAXCWND / 2; /* Initial send window */ - rpc->rc_sent = 0; - rpc->rc_timeouts = 0; - RPC_RETURN(0); - -bad: - rpcclnt_disconnect(rpc); - RPC_RETURN(error); -} - - -/* - * Reconnect routine: - * Called when a connection is broken on a reliable protocol. - * - clean up the old socket - * - rpcclnt_connect() again - * - set R_MUSTRESEND for all outstanding requests on mount point - * If this fails the mount point is DEAD! - * nb: Must be called with the rpcclnt_sndlock() set on the mount point. - */ -int -rpcclnt_reconnect(rep, td) - struct rpctask *rep; - RPC_EXEC_CTX td; -{ - struct rpctask *rp; - struct rpcclnt *rpc = rep->r_rpcclnt; - int error; - - rpcclnt_disconnect(rpc); - while ((error = rpcclnt_connect(rpc, td)) != 0) { - if (error == EINTR || error == ERESTART) - RPC_RETURN(EINTR); - tsleep(&fake_wchan, PSOCK, "rpccon", hz); - } - - /* - * Loop through outstanding request list and fix up all requests on - * old socket. - */ - for (rp = TAILQ_FIRST(&rpctask_q); rp != NULL; - rp = TAILQ_NEXT(rp, r_chain)) { - if (rp->r_rpcclnt == rpc) - rp->r_flags |= R_MUSTRESEND; - } - RPC_RETURN(0); -} - -/* - * RPC transport disconnect. Clean up and unlink. - */ -void -rpcclnt_disconnect(rpc) - struct rpcclnt *rpc; -{ - struct socket *so; - - if (rpc->rc_so) { - so = rpc->rc_so; - rpc->rc_so = NULL; - soshutdown(so, 2); - soclose(so); - } -} - -void -rpcclnt_safedisconnect(struct rpcclnt * rpc) -{ - struct rpctask dummytask; - - bzero(&dummytask, sizeof(dummytask)); - dummytask.r_rpcclnt = rpc; - rpcclnt_rcvlock(&dummytask); - rpcclnt_disconnect(rpc); - rpcclnt_rcvunlock(&rpc->rc_flag); -} - -/* - * This is the rpc send routine. For connection based socket types, it - * must be called with an rpcclnt_sndlock() on the socket. - * "rep == NULL" indicates that it has been called from a server. - * For the client side: - * - return EINTR if the RPC is terminated, 0 otherwise - * - set R_MUSTRESEND if the send fails for any reason - * - do any cleanup required by recoverable socket errors (?) - * For the server side: - * - return EINTR or ERESTART if interrupted by a signal - * - return EPIPE if a connection is lost for connection based sockets (TCP...) - * - do any cleanup required by recoverable socket errors (?) - */ -static int -rpcclnt_send(so, nam, top, rep) - struct socket *so; -#ifdef __OpenBSD__ - struct mbuf *nam; -#else - struct sockaddr *nam; -#endif - struct mbuf *top; - struct rpctask *rep; -{ -#ifdef __OpenBSD__ - struct mbuf *sendnam; -#else - struct sockaddr *sendnam; - struct thread *td = curthread; -#endif - int error, soflags, flags; - - if (rep) { - if (rep->r_flags & R_SOFTTERM) { - m_freem(top); - RPC_RETURN(EINTR); - } - if ((so = rep->r_rpcclnt->rc_so) == NULL) { - rep->r_flags |= R_MUSTRESEND; - m_freem(top); - RPC_RETURN(0); - } - rep->r_flags &= ~R_MUSTRESEND; - soflags = rep->r_rpcclnt->rc_soflags; - } else - soflags = so->so_proto->pr_flags; - - if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED)) - sendnam = NULL; - else - sendnam = nam; - - if (so->so_type == SOCK_SEQPACKET) - flags = MSG_EOR; - else - flags = 0; - - /* - * XXXRW: If/when this code becomes MPSAFE itself, Giant might have - * to be conditionally acquired earlier for the stack so has to avoid - * lock order reversals with any locks held over rpcclnt_send(). - */ - error = sosend(so, sendnam, NULL, top, NULL, flags, td); - if (error) { - if (rep) { - log(LOG_INFO, "rpc send error %d for service %s\n", error, - rep->r_rpcclnt->rc_prog->prog_name); - /* - * Deal with errors for the client side. - */ - if (rep->r_flags & R_SOFTTERM) - error = EINTR; - else - rep->r_flags |= R_MUSTRESEND; - } else - log(LOG_INFO, "rpc service send error %d\n", error); - - /* - * Handle any recoverable (soft) socket errors here. - */ - if (error != EINTR && error != ERESTART && - error != EWOULDBLOCK && error != EPIPE) - error = 0; - } - RPC_RETURN(error); -} - -/* - * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all done by - * soreceive(), but for SOCK_STREAM we must deal with the Record Mark and - * consolidate the data into a new mbuf list. nb: Sometimes TCP passes the - * data up to soreceive() in long lists of small mbufs. For SOCK_STREAM we - * must be very careful to read an entire record once we have read any of it, - * even if the system call has been interrupted. - */ -static int -rpcclnt_receive(rep, aname, mp, td) - struct rpctask *rep; -#ifdef __OpenBSD__ - struct mbuf **aname; -#else - struct sockaddr **aname; -#endif - struct mbuf **mp; - RPC_EXEC_CTX td; -{ - struct socket *so; - struct uio auio; - struct iovec aio; - struct mbuf *m; - struct mbuf *control; - u_int32_t len; -#ifdef __OpenBSD__ - struct mbuf **getnam; -#else - struct sockaddr **getnam; -#endif - int error, sotype, rcvflg; - - /* - * Set up arguments for soreceive() - */ - *mp = NULL; - *aname = NULL; - sotype = rep->r_rpcclnt->rc_sotype; - - /* - * For reliable protocols, lock against other senders/receivers in - * case a reconnect is necessary. For SOCK_STREAM, first get the - * Record Mark to find out how much more there is to get. We must - * lock the socket against other receivers until we have an entire - * rpc request/reply. - */ - if (sotype != SOCK_DGRAM) { - error = rpcclnt_sndlock(&rep->r_rpcclnt->rc_flag, rep); - if (error) - RPC_RETURN(error); -tryagain: - /* - * Check for fatal errors and resending request. - */ - /* - * Ugh: If a reconnect attempt just happened, rc_so would - * have changed. NULL indicates a failed attempt that has - * essentially shut down this mount point. - */ - if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) { - rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - RPC_RETURN(EINTR); - } - so = rep->r_rpcclnt->rc_so; - if (!so) { - error = rpcclnt_reconnect(rep, td); - if (error) { - rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - RPC_RETURN(error); - } - goto tryagain; - } - while (rep->r_flags & R_MUSTRESEND) { - m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT); - rpcstats.rpcretries++; - error = rpcclnt_send(so, rep->r_rpcclnt->rc_name, m, rep); - if (error) { - if (error == EINTR || error == ERESTART || - (error = rpcclnt_reconnect(rep, td)) != 0) { - rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - RPC_RETURN(error); - } - goto tryagain; - } - } - rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - if (sotype == SOCK_STREAM) { - aio.iov_base = (caddr_t) & len; - aio.iov_len = sizeof(u_int32_t); - auio.uio_iov = &aio; - auio.uio_iovcnt = 1; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_rw = UIO_READ; - auio.uio_offset = 0; - auio.uio_resid = sizeof(u_int32_t); -#ifdef __OpenBSD__ - auio.uio_procp = td; -#else - auio.uio_td = td; -#endif - do { - rcvflg = MSG_WAITALL; - error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg); - if (error == EWOULDBLOCK && rep) { - if (rep->r_flags & R_SOFTTERM) - RPC_RETURN(EINTR); - } - } while (error == EWOULDBLOCK); - if (!error && auio.uio_resid > 0) { - log(LOG_INFO, - "short receive (%zu/%zu) from rpc server %s\n", - sizeof(u_int32_t) - auio.uio_resid, - sizeof(u_int32_t), - rep->r_rpcclnt->rc_prog->prog_name); - error = EPIPE; - } - if (error) - goto errout; - len = ntohl(len) & ~0x80000000; - /* - * This is SERIOUS! We are out of sync with the - * sender and forcing a disconnect/reconnect is all I - * can do. - */ - if (len > RPC_MAXPACKET) { - log(LOG_ERR, "%s (%d) from rpc server %s\n", - "impossible packet length", - len, - rep->r_rpcclnt->rc_prog->prog_name); - error = EFBIG; - goto errout; - } - auio.uio_resid = len; - do { - rcvflg = MSG_WAITALL; - error = soreceive(so, NULL, &auio, mp, NULL, &rcvflg); - } while (error == EWOULDBLOCK || error == EINTR || - error == ERESTART); - if (!error && auio.uio_resid > 0) { - log(LOG_INFO, - "short receive (%d/%d) from rpc server %s\n", - len - auio.uio_resid, len, - rep->r_rpcclnt->rc_prog->prog_name); - error = EPIPE; - } - } else { - /* - * NB: Since uio_resid is big, MSG_WAITALL is ignored - * and soreceive() will return when it has either a - * control msg or a data msg. We have no use for - * control msg., but must grab them and then throw - * them away so we know what is going on. - */ - auio.uio_resid = len = 100000000; /* Anything Big */ -#ifdef __OpenBSD__ - auio.uio_procp = td; -#else - auio.uio_td = td; -#endif - do { - rcvflg = 0; - error = soreceive(so, NULL, &auio, mp, &control, &rcvflg); - if (control) - m_freem(control); - if (error == EWOULDBLOCK && rep) { - if (rep->r_flags & R_SOFTTERM) - RPC_RETURN(EINTR); - } - } while (error == EWOULDBLOCK || - (!error && *mp == NULL && control)); - if ((rcvflg & MSG_EOR) == 0) - printf("Egad!!\n"); - if (!error && *mp == NULL) - error = EPIPE; - len -= auio.uio_resid; - } -errout: - if (error && error != EINTR && error != ERESTART) { - m_freem(*mp); - *mp = (struct mbuf *) 0; - if (error != EPIPE) - log(LOG_INFO, - "receive error %d from rpc server %s\n", - error, - rep->r_rpcclnt->rc_prog->prog_name); - error = rpcclnt_sndlock(&rep->r_rpcclnt->rc_flag, rep); - if (!error) - error = rpcclnt_reconnect(rep, td); - if (!error) - goto tryagain; - } - } else { - if ((so = rep->r_rpcclnt->rc_so) == NULL) - RPC_RETURN(EACCES); - if (so->so_state & SS_ISCONNECTED) - getnam = NULL; - else - getnam = aname; - auio.uio_resid = len = 1000000; -#ifdef __OpenBSD__ - auio.uio_procp = td; -#else - auio.uio_td = td; -#endif - - do { - rcvflg = 0; - error = soreceive(so, getnam, &auio, mp, NULL, &rcvflg); - RPCDEBUG("soreceive returns %d", error); - if (error == EWOULDBLOCK && (rep->r_flags & R_SOFTTERM)) { - RPCDEBUG("wouldblock && softerm -> EINTR"); - RPC_RETURN(EINTR); - } - } while (error == EWOULDBLOCK); - len -= auio.uio_resid; - } - if (error) { - m_freem(*mp); - *mp = NULL; - } else { - /* - * Search for any mbufs that are not a multiple of 4 bytes - * long or with m_data not longword aligned. These could - * cause pointer alignment problems, so copy them to well - * aligned mbufs. - */ - rpcclnt_realign(mp, 5 * RPCX_UNSIGNED); - } - RPC_RETURN(error); -} - - -/* - * Implement receipt of reply on a socket. We must search through the list of - * received datagrams matching them with outstanding requests using the xid, - * until ours is found. - */ -/* ARGSUSED */ -static int -rpcclnt_reply(myrep, td) - struct rpctask *myrep; - RPC_EXEC_CTX td; -{ - struct rpctask *rep; - struct rpcclnt *rpc = myrep->r_rpcclnt; - int32_t t1; - struct mbuf *mrep, *md; -#ifdef __OpenBSD__ - struct mbuf *nam; -#else - struct sockaddr *nam; -#endif - u_int32_t rxid, *tl; - caddr_t dpos, cp2; - int error; - - /* - * Loop around until we get our own reply - */ - for (;;) { - /* - * Lock against other receivers so that I don't get stuck in - * sbwait() after someone else has received my reply for me. - * Also necessary for connection based protocols to avoid - * race conditions during a reconnect. - */ - error = rpcclnt_rcvlock(myrep); - if (error) - RPC_RETURN(error); - /* Already received, bye bye */ - if (myrep->r_mrep != NULL) { - rpcclnt_rcvunlock(&rpc->rc_flag); - RPC_RETURN(0); - } - /* - * Get the next Rpc reply off the socket - */ - error = rpcclnt_receive(myrep, &nam, &mrep, td); - - rpcclnt_rcvunlock(&rpc->rc_flag); - - if (error) { - /* - * Ignore routing errors on connectionless - * protocols?? - */ - if (RPCIGNORE_SOERROR(rpc->rc_soflags, error)) { - rpc->rc_so->so_error = 0; - if (myrep->r_flags & R_GETONEREP) - RPC_RETURN(0); - RPCDEBUG("ingoring routing error on connectionless protocol."); - continue; - } - RPC_RETURN(error); - } -#ifdef __OpenBSD__ - if (nam) - m_freem(nam); -#else - if (nam) - free(nam, M_SONAME); -#endif - - /* - * Get the xid and check that it is an rpc reply - */ - md = mrep; - dpos = mtod(md, caddr_t); - rpcm_dissect(tl, u_int32_t *, 2 * RPCX_UNSIGNED); - rxid = *tl++; - if (*tl != rpc_reply) { - rpcstats.rpcinvalid++; - m_freem(mrep); -rpcmout: - if (myrep->r_flags & R_GETONEREP) - RPC_RETURN(0); - continue; - } - /* - * Loop through the request list to match up the reply Iff no - * match, just drop the datagram - */ - TAILQ_FOREACH(rep, &rpctask_q, r_chain) { - if (rep->r_mrep == NULL && rxid == rep->r_xid) { - /* Found it.. */ - rep->r_mrep = mrep; - rep->r_md = md; - rep->r_dpos = dpos; - - /* - * Update congestion window. Do the additive - * increase of one rpc/rtt. - */ - if (rpc->rc_cwnd <= rpc->rc_sent) { - rpc->rc_cwnd += - (RPC_CWNDSCALE * RPC_CWNDSCALE + - (rpc->rc_cwnd >> 1)) / rpc->rc_cwnd; - if (rpc->rc_cwnd > RPC_MAXCWND) - rpc->rc_cwnd = RPC_MAXCWND; - } - rep->r_flags &= ~R_SENT; - rpc->rc_sent -= RPC_CWNDSCALE; - /* - * Update rtt using a gain of 0.125 on the - * mean and a gain of 0.25 on the deviation. - */ - if (rep->r_flags & R_TIMING) { - /* - * Since the timer resolution of - * NFS_HZ is so course, it can often - * result in r_rtt == 0. Since r_rtt - * == N means that the actual rtt is - * between N+dt and N+2-dt ticks, add - * 1. - */ - t1 = rep->r_rtt + 1; - t1 -= (RPC_SRTT(rpc, rep) >> 3); - RPC_SRTT(rpc, rep) += t1; - if (t1 < 0) - t1 = -t1; - t1 -= (RPC_SDRTT(rpc, rep) >> 2); - RPC_SDRTT(rpc, rep) += t1; - } - rpc->rc_timeouts = 0; - break; - } - } - /* - * If not matched to a request, drop it. If it's mine, get - * out. - */ - if (rep == 0) { - rpcstats.rpcunexpected++; - RPCDEBUG("rpc reply not matched\n"); - m_freem(mrep); - } else if (rep == myrep) { - if (rep->r_mrep == NULL) - panic("rpcreply nil"); - RPC_RETURN(0); - } - if (myrep->r_flags & R_GETONEREP) - RPC_RETURN(0); - } -} - -/* XXX: ignores tryagain! */ -/* - * code from nfs_request - goes something like this - * - fill in task struct - * - links task into list - * - calls rpcclnt_send() for first transmit - * - calls rpcclnt_reply() to get reply - * - fills in reply (which should be initialized prior to - * calling), which is valid when 0 is returned and is - * NEVER freed in this function - * - * nb: always frees the request header, but NEVER frees 'mrest' - * - * rpcclnt_setauth() should be used before calling this. EAUTH is returned if - * authentication fails. - * - * note that reply->result_* are invalid unless reply->type == - * RPC_MSGACCEPTED and reply->status == RPC_SUCCESS and that reply->verf_* - * are invalid unless reply->type == RPC_MSGACCEPTED - */ -int -rpcclnt_request(rpc, mrest, procnum, td, cred, reply) - struct rpcclnt *rpc; - struct mbuf *mrest; - int procnum; - RPC_EXEC_CTX td; - struct ucred *cred; - struct rpc_reply *reply; -{ - struct mbuf *m, *mrep; - struct rpctask *task; - u_int32_t *tl; - struct mbuf *md, *mheadend; - caddr_t dpos, cp2; - int t1, s, error = 0, mrest_len; - u_int32_t xid; - -#ifdef __OpenBSD__ - task = pool_get(&rpctask_pool, PR_WAITOK); -#else - task = malloc(sizeof(struct rpctask), M_RPCCLNT, (M_WAITOK | M_ZERO)); -#endif - - task->r_rpcclnt = rpc; - task->r_procnum = procnum; - task->r_td = td; - - mrest_len = m_length(mrest, NULL); - - m = rpcclnt_buildheader(rpc, procnum, mrest, mrest_len, &xid, &mheadend, - cred); - /* - * This can happen if the auth_type is neither UNIX or NULL - */ - if (m == NULL) { -#ifdef __OpenBSD__ - pool_put(&rpctask_pool, task); -#else - free(task, M_RPCCLNT); -#endif - error = EPROTONOSUPPORT; - goto rpcmout; - } - - /* - * For stream protocols, insert a Sun RPC Record Mark. - */ - if (rpc->rc_sotype == SOCK_STREAM) { - M_PREPEND(m, RPCX_UNSIGNED, M_WAIT); - *mtod(m, u_int32_t *) = htonl(0x80000000 | - (m->m_pkthdr.len - RPCX_UNSIGNED)); - } - task->r_mreq = m; - task->r_xid = xid; - - if (rpc->rc_flag & RPCCLNT_SOFT) - task->r_retry = rpc->rc_retry; - else - task->r_retry = RPC_MAXREXMIT + 1; /* past clip limit */ - task->r_rtt = task->r_rexmit = 0; - - if (rpcclnt_proct(rpc, procnum) > 0) - task->r_flags = R_TIMING; - else - task->r_flags = 0; - task->r_mrep = NULL; - - /* - * Do the client side RPC. - */ - rpcstats.rpcrequests++; - - /* - * Chain request into list of outstanding requests. Be sure to put it - * LAST so timer finds oldest requests first. - */ - s = splsoftclock(); - if (TAILQ_EMPTY(&rpctask_q)) - callout_reset(&rpcclnt_callout, rpcclnt_ticks, rpcclnt_timer, - NULL); - TAILQ_INSERT_TAIL(&rpctask_q, task, r_chain); - - /* - * If backing off another request or avoiding congestion, don't send - * this one now but let timer do it. If not timing a request, do it - * now. - */ - if (rpc->rc_so && (rpc->rc_sotype != SOCK_DGRAM || - (rpc->rc_flag & RPCCLNT_DUMBTIMR) || - rpc->rc_sent < rpc->rc_cwnd)) { - splx(s); - - if (rpc->rc_soflags & PR_CONNREQUIRED) - error = rpcclnt_sndlock(&rpc->rc_flag, task); - if (!error) { - error = rpcclnt_send(rpc->rc_so, rpc->rc_name, - m_copym(m, 0, M_COPYALL, M_WAIT), - task); - if (rpc->rc_soflags & PR_CONNREQUIRED) - rpcclnt_sndunlock(&rpc->rc_flag); - } - if (!error && (task->r_flags & R_MUSTRESEND) == 0) { - rpc->rc_sent += RPC_CWNDSCALE; - task->r_flags |= R_SENT; - } - } else { - splx(s); - task->r_rtt = -1; - } - - /* - * Wait for the reply from our send or the timer's. - */ - if (!error || error == EPIPE) - error = rpcclnt_reply(task, td); - - /* - * RPC done, unlink the request. - */ - s = splsoftclock(); - TAILQ_REMOVE(&rpctask_q, task, r_chain); - if (TAILQ_EMPTY(&rpctask_q)) - callout_stop(&rpcclnt_callout); - splx(s); - - /* - * Decrement the outstanding request count. - */ - if (task->r_flags & R_SENT) { - task->r_flags &= ~R_SENT; /* paranoia */ - rpc->rc_sent -= RPC_CWNDSCALE; - } - /* - * If there was a successful reply and a tprintf msg. tprintf a - * response. - */ - if (!error && (task->r_flags & R_TPRINTFMSG)) { - mtx_lock(&Giant); - rpcclnt_msg(task->r_td, rpc->rc_prog->prog_name, - "is alive again"); - mtx_unlock(&Giant); - } - - /* free request header (leaving mrest) */ - mheadend->m_next = NULL; - m_freem(task->r_mreq); - - /* initialize reply */ - reply->mrep = task->r_mrep; - reply->verf_md = NULL; - reply->result_md = NULL; - - mrep = task->r_mrep; - md = task->r_md; - dpos = task->r_dpos; - - /* task structure is no longer needed */ -#ifdef __OpenBSD__ - pool_put(&rpctask_pool, task); -#else - free(task, M_RPCCLNT); -#endif - - if (error) - goto rpcmout; - - /* - * break down the rpc header and check if ok - */ - - rpcm_dissect(tl, u_int32_t *, RPCX_UNSIGNED); - reply->stat.type = fxdr_unsigned(u_int32_t, *tl); - - if (reply->stat.type == RPC_MSGDENIED) { - rpcm_dissect(tl, u_int32_t *, RPCX_UNSIGNED); - reply->stat.status = fxdr_unsigned(u_int32_t, *tl); - - switch (reply->stat.status) { - case RPC_MISMATCH: - rpcm_dissect(tl, u_int32_t *, 2 * RPCX_UNSIGNED); - reply->stat.mismatch_info.low = fxdr_unsigned(u_int32_t, *tl++); - reply->stat.mismatch_info.high = fxdr_unsigned(u_int32_t, *tl); - error = EOPNOTSUPP; - break; - case RPC_AUTHERR: - rpcm_dissect(tl, u_int32_t *, RPCX_UNSIGNED); - reply->stat.autherr = fxdr_unsigned(u_int32_t, *tl); - error = EACCES; - break; - default: - error = EBADRPC; - break; - } - goto rpcmout; - } else if (reply->stat.type != RPC_MSGACCEPTED) { - error = EBADRPC; - goto rpcmout; - } - - rpcm_dissect(tl, u_int32_t *, 2 * RPCX_UNSIGNED); - - reply->verf_md = md; - reply->verf_dpos = dpos; - - reply->verf_type = fxdr_unsigned(u_int32_t, *tl++); - reply->verf_size = fxdr_unsigned(u_int32_t, *tl); - - if (reply->verf_size != 0) - rpcm_adv(rpcm_rndup(reply->verf_size)); - - rpcm_dissect(tl, u_int32_t *, RPCX_UNSIGNED); - reply->stat.status = fxdr_unsigned(u_int32_t, *tl); - - if (reply->stat.status == RPC_SUCCESS) { - if ((uint32_t)(dpos - mtod(md, caddr_t)) >= md->m_len) { - RPCDEBUG("where is the next mbuf?"); - RPCDEBUG("%d -> %d", - (int)(dpos - mtod(md, caddr_t)), md->m_len); - if (md->m_next == NULL) { - error = EBADRPC; - goto rpcmout; - } else { - reply->result_md = md->m_next; - reply->result_dpos = mtod(reply->result_md, - caddr_t); - } - } else { - reply->result_md = md; - reply->result_dpos = dpos; - } - } else if (reply->stat.status == RPC_PROGMISMATCH) { - rpcm_dissect(tl, u_int32_t *, 2 * RPCX_UNSIGNED); - reply->stat.mismatch_info.low = fxdr_unsigned(u_int32_t, *tl++); - reply->stat.mismatch_info.high = fxdr_unsigned(u_int32_t, *tl); - error = EOPNOTSUPP; - goto rpcmout; - } else { - error = EPROTONOSUPPORT; - goto rpcmout; - } - error = 0; - -rpcmout: - RPC_RETURN(error); -} - - -/* - * RPC timer routine - * Scan the rpctask list and retranmit any requests that have timed out. - * To avoid retransmission attempts on STREAM sockets (in the future) make - * sure to set the r_retry field to 0 (implies nm_retry == 0). - */ -void -rpcclnt_timer(arg) - void *arg; -{ -#ifdef __OpenBSD__ - struct timeout *to = (struct timeout *) arg; -#endif - struct rpctask *rep; - struct mbuf *m; - struct socket *so; - struct rpcclnt *rpc; - int timeo; - int s, error; - -#ifndef __OpenBSD__ - struct thread *td = curthread; -#endif - -#ifdef __OpenBSD__ - s = splsoftnet(); -#else - s = splnet(); -#endif - mtx_lock(&Giant); /* rpc_msg -> tprintf */ - TAILQ_FOREACH(rep, &rpctask_q, r_chain) { - rpc = rep->r_rpcclnt; - if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) - continue; - if (rpcclnt_sigintr(rpc, rep, rep->r_td)) { - rep->r_flags |= R_SOFTTERM; - continue; - } - if (rep->r_rtt >= 0) { - rep->r_rtt++; - if (rpc->rc_flag & RPCCLNT_DUMBTIMR) - timeo = rpc->rc_timeo; - else - timeo = RPC_RTO(rpc, rpcclnt_proct(rep->r_rpcclnt, - rep->r_procnum)); - if (rpc->rc_timeouts > 0) - timeo *= rpcclnt_backoff[rpc->rc_timeouts - 1]; - if (rep->r_rtt <= timeo) - continue; - if (rpc->rc_timeouts < 8) - rpc->rc_timeouts++; - } - /* - * Check for server not responding - */ - if ((rep->r_flags & R_TPRINTFMSG) == 0 && - rep->r_rexmit > rpc->rc_deadthresh) { - rpcclnt_msg(rep->r_td, rpc->rc_prog->prog_name, - "not responding"); - rep->r_flags |= R_TPRINTFMSG; - } - if (rep->r_rexmit >= rep->r_retry) { /* too many */ - rpcstats.rpctimeouts++; - rep->r_flags |= R_SOFTTERM; - continue; - } - if (rpc->rc_sotype != SOCK_DGRAM) { - if (++rep->r_rexmit > RPC_MAXREXMIT) - rep->r_rexmit = RPC_MAXREXMIT; - continue; - } - if ((so = rpc->rc_so) == NULL) - continue; - - /* - * If there is enough space and the window allows.. Resend it - * Set r_rtt to -1 in case we fail to send it now. - */ - rep->r_rtt = -1; - if (sbspace(&so->so_snd) >= rep->r_mreq->m_pkthdr.len && - ((rpc->rc_flag & RPCCLNT_DUMBTIMR) || - (rep->r_flags & R_SENT) || - rpc->rc_sent < rpc->rc_cwnd) && - (m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))) { - if ((rpc->rc_flag & RPCCLNT_NOCONN) == 0) - error = (*so->so_proto->pr_usrreqs->pru_send) (so, 0, m, - NULL, NULL, td); - else - error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, rpc->rc_name, NULL, td); - if (error) { - if (RPCIGNORE_SOERROR(rpc->rc_soflags, error)) - so->so_error = 0; - } else { - /* - * Iff first send, start timing else turn - * timing off, backoff timer and divide - * congestion window by 2. - */ - if (rep->r_flags & R_SENT) { - rep->r_flags &= ~R_TIMING; - if (++rep->r_rexmit > RPC_MAXREXMIT) - rep->r_rexmit = RPC_MAXREXMIT; - rpc->rc_cwnd >>= 1; - if (rpc->rc_cwnd < RPC_CWNDSCALE) - rpc->rc_cwnd = RPC_CWNDSCALE; - rpcstats.rpcretries++; - } else { - rep->r_flags |= R_SENT; - rpc->rc_sent += RPC_CWNDSCALE; - } - rep->r_rtt = 0; - } - } - } - mtx_unlock(&Giant); /* rpc_msg -> tprintf */ - splx(s); - -#ifdef __OpenBSD__ - timeout_add(rpcclnt_timer, to, rpcclnt_ticks); -#else - callout_reset(&rpcclnt_callout, rpcclnt_ticks, rpcclnt_timer, NULL); -#endif -} - -/* - * Test for a termination condition pending on the process. This is used for - * RPCCLNT_INT mounts. - */ -int -rpcclnt_sigintr(rpc, task, pr) - struct rpcclnt *rpc; - struct rpctask *task; - RPC_EXEC_CTX pr; -{ - struct proc *p; - - sigset_t tmpset; - - if (rpc == NULL) - return EFAULT; - - /* XXX deal with forced unmounts */ - - if (task && (task->r_flags & R_SOFTTERM)) - RPC_RETURN(EINTR); - - if (!(rpc->rc_flag & RPCCLNT_INT)) - RPC_RETURN(0); - - if (pr == NULL) - return (0); - -#ifdef __OpenBSD__ - p = pr; - if (p && p->p_siglist && - (((p->p_siglist & ~p->p_sigmask) & ~p->p_sigignore) & - RPCINT_SIGMASK)) - RPC_RETURN(EINTR); -#else - p = pr->td_proc; - PROC_LOCK(p); - tmpset = p->p_siglist; - SIGSETNAND(tmpset, pr->td_sigmask); - mtx_lock(&p->p_sigacts->ps_mtx); - SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); - mtx_unlock(&p->p_sigacts->ps_mtx); - if (SIGNOTEMPTY(p->p_siglist) && RPCCLNTINT_SIGMASK(tmpset)) { - PROC_UNLOCK(p); - RPC_RETURN(EINTR); - } - PROC_UNLOCK(p); -#endif - RPC_RETURN(0); -} - -/* - * Lock a socket against others. Necessary for STREAM sockets to ensure you - * get an entire rpc request/reply and also to avoid race conditions between - * the processes with nfs requests in progress when a reconnect is necessary. - */ -static int -rpcclnt_sndlock(flagp, task) - int *flagp; - struct rpctask *task; -{ - RPC_EXEC_CTX p; - int slpflag = 0, slptimeo = 0; - - p = task->r_td; - if (task->r_rpcclnt->rc_flag & RPCCLNT_INT) - slpflag = PCATCH; - while (*flagp & RPCCLNT_SNDLOCK) { - if (rpcclnt_sigintr(task->r_rpcclnt, task, p)) - RPC_RETURN(EINTR); - *flagp |= RPCCLNT_WANTSND; - (void)tsleep((caddr_t) flagp, slpflag | (PZERO - 1), "rpcsndlck", - slptimeo); - if (slpflag == PCATCH) { - slpflag = 0; - slptimeo = 2 * hz; - } - } - *flagp |= RPCCLNT_SNDLOCK; - RPC_RETURN(0); -} - -/* - * Unlock the stream socket for others. - */ -static void -rpcclnt_sndunlock(flagp) - int *flagp; -{ - - if ((*flagp & RPCCLNT_SNDLOCK) == 0) - panic("rpc sndunlock"); - *flagp &= ~RPCCLNT_SNDLOCK; - if (*flagp & RPCCLNT_WANTSND) { - *flagp &= ~RPCCLNT_WANTSND; - wakeup((caddr_t) flagp); - } -} - -static int -rpcclnt_rcvlock(task) - struct rpctask *task; -{ - int *flagp = &task->r_rpcclnt->rc_flag; - int slpflag, slptimeo = 0; - - if (*flagp & RPCCLNT_INT) - slpflag = PCATCH; - else - slpflag = 0; - while (*flagp & RPCCLNT_RCVLOCK) { - if (rpcclnt_sigintr(task->r_rpcclnt, task, task->r_td)) - RPC_RETURN(EINTR); - *flagp |= RPCCLNT_WANTRCV; - (void)tsleep((caddr_t) flagp, slpflag | (PZERO - 1), "rpcrcvlk", - slptimeo); - if (slpflag == PCATCH) { - slpflag = 0; - slptimeo = 2 * hz; - } - } - *flagp |= RPCCLNT_RCVLOCK; - RPC_RETURN(0); -} - -/* - * Unlock the stream socket for others. - */ -static void -rpcclnt_rcvunlock(flagp) - int *flagp; -{ - - if ((*flagp & RPCCLNT_RCVLOCK) == 0) - panic("nfs rcvunlock"); - *flagp &= ~RPCCLNT_RCVLOCK; - if (*flagp & RPCCLNT_WANTRCV) { - *flagp &= ~RPCCLNT_WANTRCV; - wakeup((caddr_t) flagp); - } -} - -#if 0 -/* - * Check for badly aligned mbuf data areas and realign data in an mbuf list - * by copying the data areas up, as required. - */ -void -rpcclnt_realign(m, hsiz) - struct mbuf *m; - int hsiz; -{ - struct mbuf *m2; - int siz, mlen, olen; - caddr_t tcp, fcp; - struct mbuf *mnew; - - while (m) { - /* - * This never happens for UDP, rarely happens for TCP but - * frequently happens for iso transport. - */ - if ((m->m_len & 0x3) || (mtod(m, long)&0x3)) { - olen = m->m_len; - fcp = mtod(m, caddr_t); - if ((long)fcp & 0x3) { - if (m->m_flags & M_PKTHDR) - m_tag_delete_chain(m, NULL); - m->m_flags &= ~M_PKTHDR; - if (m->m_flags & M_EXT) - m->m_data = m->m_ext.ext_buf + - ((m->m_ext.ext_size - olen) & ~0x3); - else - m->m_data = m->m_dat; - } - m->m_len = 0; - tcp = mtod(m, caddr_t); - mnew = m; - m2 = m->m_next; - - /* - * If possible, only put the first invariant part of - * the RPC header in the first mbuf. - */ - mlen = M_TRAILINGSPACE(m); - if (olen <= hsiz && mlen > hsiz) - mlen = hsiz; - - /* Loop through the mbuf list consolidating data. */ - while (m) { - while (olen > 0) { - if (mlen == 0) { - if (m2->m_flags & M_PKTHDR) - m_tag_delete_chain(m2, NULL); - m2->m_flags &= ~M_PKTHDR; - if (m2->m_flags & M_EXT) - m2->m_data = m2->m_ext.ext_buf; - else - m2->m_data = m2->m_dat; - m2->m_len = 0; - mlen = M_TRAILINGSPACE(m2); - tcp = mtod(m2, caddr_t); - mnew = m2; - m2 = m2->m_next; - } - siz = min(mlen, olen); - if (tcp != fcp) - bcopy(fcp, tcp, siz); - mnew->m_len += siz; - mlen -= siz; - olen -= siz; - tcp += siz; - fcp += siz; - } - m = m->m_next; - if (m) { - olen = m->m_len; - fcp = mtod(m, caddr_t); - } - } - - /* - * Finally, set m_len == 0 for any trailing mbufs - * that have been copied out of. - */ - while (m2) { - m2->m_len = 0; - m2 = m2->m_next; - } - return; - } - m = m->m_next; - } -} -#else -static void -rpcclnt_realign(struct mbuf **pm, int hsiz) -{ - struct mbuf *m; - struct mbuf *n = NULL; - int off = 0; - - RPCDEBUG("in rpcclnt_realign()"); - - while ((m = *pm) != NULL) { - if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) { - MGET(n, M_WAIT, MT_DATA); - if (m->m_len >= MINCLSIZE) { - MCLGET(n, M_WAIT); - } - n->m_len = 0; - break; - } - pm = &m->m_next; - } - - /* - * If n is non-NULL, loop on m copying data, then replace the - * portion of the chain that had to be realigned. - */ - if (n != NULL) { - while (m) { - m_copyback(n, off, m->m_len, mtod(m, caddr_t)); - off += m->m_len; - m = m->m_next; - } - m_freem(*pm); - *pm = n; - } - - RPCDEBUG("leave rpcclnt_realign()"); -} -#endif - -static int -rpcclnt_msg(p, server, msg) - RPC_EXEC_CTX p; - const char *server; - char *msg; -{ -#ifdef __OpenBSD__ - tpr_t tpr; - struct proc *pr = p; - - if (p) - tpr = tprintf_open(p); - else - tpr = NULL; - tprintf(tpr, "rpc server %s: %s\n", server, msg); - tprintf_close(tpr); - RPC_RETURN(0); -#else - GIANT_REQUIRED; - - tprintf(p ? p->td_proc : NULL, LOG_INFO, - "nfs server %s: %s\n", server, msg); - RPC_RETURN(0); -#endif -} - -/* - * Build the RPC header and fill in the authorization info. The authorization - * string argument is only used when the credentials come from outside of the - * kernel (AUTH_KERB). (likewise, the ucred is only used when inside the - * kernel) Returns the head of the mbuf list. - */ -static struct mbuf * -rpcclnt_buildheader(rc, procid, mrest, mrest_len, xidp, mheadend, cred) - struct rpcclnt *rc; - int procid; - struct mbuf *mrest; - u_int32_t mrest_len; - int *xidp; - struct mbuf **mheadend; - struct ucred * cred; -{ - /* register */ struct mbuf *mb; - register u_int32_t *tl; - /* register */ caddr_t bpos; - struct mbuf *mreq, *mb2; - int error; - - MGETHDR(mb, M_WAIT, MT_DATA); - if (6 * RPCX_UNSIGNED >= MINCLSIZE) { - MCLGET(mb, M_WAIT); - } else if (6 * RPCX_UNSIGNED < MHLEN) { - MH_ALIGN(mb, 6 * RPCX_UNSIGNED); - } else { - RPCDEBUG("mbuf too small"); - panic("cheap bailout"); - } - mb->m_len = 0; - mreq = mb; - bpos = mtod(mb, caddr_t); - - /* - * First the RPC header. - */ - rpcm_build(tl, u_int32_t *, 6 * RPCX_UNSIGNED); - - /* Get a new (non-zero) xid */ - if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) { - rpcclnt_xid = arc4random(); - rpcclnt_xid_touched = 1; - } else { - while ((*xidp = arc4random() % 256) == 0); - rpcclnt_xid += *xidp; - } - - /* XXX: funky... */ - *tl++ = *xidp = txdr_unsigned(rpcclnt_xid); - - *tl++ = rpc_call; - *tl++ = rpc_vers; - *tl++ = txdr_unsigned(rc->rc_prog->prog_id); - *tl++ = txdr_unsigned(rc->rc_prog->prog_version); - *tl++ = txdr_unsigned(procid); - - if ((error = rpcauth_buildheader(rc->rc_auth, cred, &mb, &bpos))) { - m_freem(mreq); - RPCDEBUG("rpcauth_buildheader failed %d", error); - return NULL; - } - - mb->m_next = mrest; - *mheadend = mb; - mreq->m_pkthdr.len = m_length(mreq, NULL); - mreq->m_pkthdr.rcvif = NULL; - return (mreq); -} - -/* - * Help break down an mbuf chain by setting the first siz bytes contiguous - * pointed to by returned val. This is used by the macros rpcm_dissect and - * rpcm_dissecton for tough cases. (The macros use the vars. dpos and dpos2) - */ -static int -rpcm_disct(mdp, dposp, siz, left, cp2) - struct mbuf **mdp; - caddr_t *dposp; - int siz; - int left; - caddr_t *cp2; -{ - struct mbuf *mp, *mp2; - int siz2, xfer; - caddr_t p; - - mp = *mdp; - while (left == 0) { - *mdp = mp = mp->m_next; - if (mp == NULL) - RPC_RETURN(EBADRPC); - left = mp->m_len; - *dposp = mtod(mp, caddr_t); - } - if (left >= siz) { - *cp2 = *dposp; - *dposp += siz; - } else if (mp->m_next == NULL) { - RPC_RETURN(EBADRPC); - } else if (siz > MHLEN) { - panic("rpc S too big"); - } else { - MGET(mp2, M_WAIT, MT_DATA); - mp2->m_next = mp->m_next; - mp->m_next = mp2; - mp->m_len -= left; - mp = mp2; - *cp2 = p = mtod(mp, caddr_t); - bcopy(*dposp, p, left); /* Copy what was left */ - siz2 = siz - left; - p += left; - mp2 = mp->m_next; - /* Loop around copying up the siz2 bytes */ - while (siz2 > 0) { - if (mp2 == NULL) - RPC_RETURN(EBADRPC); - xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2; - if (xfer > 0) { - bcopy(mtod(mp2, caddr_t), p, xfer); - RPCMADV(mp2, xfer); - mp2->m_len -= xfer; - p += xfer; - siz2 -= xfer; - } - if (siz2 > 0) - mp2 = mp2->m_next; - } - mp->m_len = siz; - *mdp = mp2; - *dposp = mtod(mp2, caddr_t); - } - RPC_RETURN(0); -} - - - -static u_int32_t -rpcclnt_proct(rpc, procid) - struct rpcclnt *rpc; - u_int32_t procid; -{ - if (rpc->rc_proctlen != 0 && rpc->rc_proct != NULL && - procid < rpc->rc_proctlen) { - return rpc->rc_proct[procid]; - } - return (0); -} - -static int -rpc_adv(mdp, dposp, offs, left) - struct mbuf **mdp; - caddr_t *dposp; - int offs; - int left; -{ - struct mbuf *m; - int s; - - m = *mdp; - s = left; - while (s < offs) { - offs -= s; - m = m->m_next; - if (m == NULL) - RPC_RETURN(EBADRPC); - s = m->m_len; - } - *mdp = m; - *dposp = mtod(m, caddr_t) + offs; - RPC_RETURN(0); -} - -int -rpcclnt_cancelreqs(rpc) - struct rpcclnt *rpc; -{ - struct rpctask *task; - int i, s; - - s = splnet(); - TAILQ_FOREACH(task, &rpctask_q, r_chain) { - if (rpc != task->r_rpcclnt || task->r_mrep != NULL || - (task->r_flags & R_SOFTTERM)) - continue; - rpcclnt_softterm(task); - } - splx(s); - - for (i = 0; i < 30; i++) { - s = splnet(); - TAILQ_FOREACH(task, &rpctask_q, r_chain) { - if (rpc == task->r_rpcclnt) - break; - } - splx(s); - if (task == NULL) - return (0); - tsleep(&fake_wchan, PSOCK, "nfscancel", hz); - } - return (EBUSY); -} - -static void -rpcclnt_softterm(struct rpctask * task) -{ - task->r_flags |= R_SOFTTERM; - if (task->r_flags & R_SENT) { - task->r_rpcclnt->rc_sent -= RPC_CWNDSCALE; - task->r_flags &= ~R_SENT; - } -} - - -#ifndef __OpenBSD__ -/* called by rpcclnt_get() */ -void -rpcclnt_create(struct rpcclnt ** rpc) -{ - *rpc = malloc(sizeof(struct rpcclnt), M_RPCCLNT, M_WAITOK | M_ZERO); -} - -/* called by rpcclnt_put() */ -void -rpcclnt_destroy(struct rpcclnt * rpc) -{ - if (rpc != NULL) { - free(rpc, M_RPCCLNT); - } else { - RPCDEBUG("attempting to free a NULL rpcclnt (not dereferenced)"); - } -} -#endif /* !__OpenBSD__ */ - - -/* XXX: add a lock around the auth structure in struct rpcclnt and make this - * call safe for calling durring a connection */ -static int -rpcauth_buildheader(struct rpc_auth * auth, struct ucred * cred, struct mbuf ** mhdr, caddr_t * bp) -{ - size_t authsiz, verfsiz; - uint32_t mlen, grpsiz; - register struct mbuf *mb, *mb2; - caddr_t bpos; - register u_int32_t *tl; - register int i; - - if (auth == NULL || mhdr == NULL) - return EFAULT; - - switch (auth->auth_type) { - case RPCAUTH_NULL: - authsiz = 0; - verfsiz = 0; - break; - case RPCAUTH_UNIX: - authsiz = (5 + cred->cr_ngroups) * RPCX_UNSIGNED; - verfsiz = 0; - break; - default: - return EPROTONOSUPPORT; - break; - }; - - mlen = rpcm_rndup(authsiz) + rpcm_rndup(verfsiz) + 4 * RPCX_UNSIGNED; - - mb = *mhdr; - bpos = *bp; - - rpcm_build(tl, u_int32_t *, mlen); - - *bp = bpos; - *mhdr = mb; - - *tl++ = txdr_unsigned(auth->auth_type); - *tl++ = txdr_unsigned(authsiz); - switch (auth->auth_type) { - case RPCAUTH_UNIX: - *tl++ = 0; - *tl++ = 0; - - *tl++ = txdr_unsigned(cred->cr_uid); - *tl++ = txdr_unsigned(cred->cr_groups[0]); - grpsiz = cred->cr_ngroups; - *tl++ = txdr_unsigned(grpsiz); - /* XXX: groups[0] is already sent... */ - for (i = 0 ; i < grpsiz ; i++) { - *tl++ = txdr_unsigned(cred->cr_groups[i]); - } - - /* null verification header */ - *tl++ = txdr_unsigned(RPCAUTH_NULL); - *tl++ = 0; - break; - case RPCAUTH_NULL: - /* just a null verf header */ - *tl++ = txdr_unsigned(RPCAUTH_NULL); - *tl = 0; - break; - default: - panic("inconsistent rpc auth type"); - break; - } - - return 0; -} diff --git a/sys/rpc/rpcclnt.h b/sys/rpc/rpcclnt.h deleted file mode 100644 index f57c4dc..0000000 --- a/sys/rpc/rpcclnt.h +++ /dev/null @@ -1,354 +0,0 @@ -/* $FreeBSD$ */ -/* $OpenBSD: nfsmount.h,v 1.11 2002/03/14 01:27:13 millert Exp $ */ -/* $NetBSD: nfsmount.h,v 1.10 1996/02/18 11:54:03 fvdl 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. - */ - -/*- - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nfsmount.h 8.3 (Berkeley) 3/30/95 - */ - - -#ifndef _RPCCLNT_H_ -#define _RPCCLNT_H_ - -#include <sys/types.h> -#include <sys/malloc.h> -#include <sys/lock.h> -#include <sys/mutex.h> - -#ifdef __OpenBSD__ - #define RPC_EXEC_CTX struct proc * -#else - #define RPC_EXEC_CTX struct thread * -#endif - - -#ifdef RPCCLNT_DEBUG -#define RPCDEBUG(args...) do{ \ - if(rpcdebugon != 0){ \ - printf("%s(): ", __func__);\ - printf(args); \ - printf("\n"); \ - }}while(0) -#else -#define RPCDEBUG(args...) -#endif - -/* from nfs/nfs.h */ -#define RPC_TICKINTVL 10 - - -/* from nfs/nfsproto.h */ -#define RPC_MAXDATA 32768 -#define RPC_MAXPKTHDR 404 -#define RPC_MAXPACKET (RPC_MAXPKTHDR + RPC_MAXDATA) - -#define RPCX_UNSIGNED 4 - -/* defines for rpcclnt's rc_flags - XXX these flags came from the NFSMNT_* flags in OpenBSD's sys/mount.h */ -#define RPCCLNT_SOFT 0x001 /* soft mount (hard is details) */ -#define RPCCLNT_INT 0x002 /* allow interrupts on hard mounts */ -#define RPCCLNT_NOCONN 0x004 /* dont connect the socket (udp) */ -#define RPCCLNT_DUMBTIMR 0x010 - -#define RPCCLNT_SNDLOCK 0x100 -#define RPCCLNT_WANTSND 0x200 -#define RPCCLNT_RCVLOCK 0x400 -#define RPCCLNT_WANTRCV 0x800 - - -/* Flag values for r_flags */ -#define R_TIMING 0x01 /* timing request (in mntp) */ -#define R_SENT 0x02 /* request has been sent */ -#define R_SOFTTERM 0x04 /* soft mnt, too many retries */ -#define R_INTR 0x08 /* intr mnt, signal pending */ -#define R_SOCKERR 0x10 /* Fatal error on socket */ -#define R_TPRINTFMSG 0x20 /* Did a tprintf msg. */ -#define R_MUSTRESEND 0x40 /* Must resend request */ -#define R_GETONEREP 0x80 /* Probe for one reply only */ - - -#define RPC_HZ (hz / rpcclnt_ticks) /* Ticks/sec */ -#define RPC_TIMEO (1 * RPC_HZ) /* Default timeout = 1 second */ - -#define RPC_MAXREXMIT 100 /* Stop counting after this many */ - - -#define RPCIGNORE_SOERROR(s, e) \ - ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \ - ((s) & PR_CONNREQUIRED) == 0) - -#define RPCINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \ - sigmask(SIGHUP)|sigmask(SIGQUIT)) - -#define RPCMADV(m, s) (m)->m_data += (s) - -#define RPCAUTH_ROOTCREDS NULL - -#define RPCCLNTINT_SIGMASK(set) \ - (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \ - SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \ - SIGISMEMBER(set, SIGQUIT)) - - -#define fxdr_unsigned(t, v) ((t)ntohl((int32_t)(v))) -#define txdr_unsigned(v) (htonl((int32_t)(v))) - - -/* global rpcstats - * XXX should be per rpcclnt */ -struct rpcstats { - int rpcretries; - int rpcrequests; - int rpctimeouts; - int rpcunexpected; - int rpcinvalid; -}; - -struct rpc_program { - u_int32_t prog_id; - u_int32_t prog_version; - char * prog_name; -}; - -struct rpc_auth { - unsigned int auth_type; -}; - -struct rpctask { - TAILQ_ENTRY(rpctask) r_chain; - struct mbuf *r_mreq; - struct mbuf *r_mrep; - struct mbuf *r_md; - caddr_t r_dpos; - - struct rpcclnt *r_rpcclnt; - - u_int32_t r_xid; - int r_flags; /* flags on request, see below */ - int r_retry; /* max retransmission count */ - int r_rexmit; /* current retrans count */ - int r_timer; /* tick counter on reply */ - int r_procnum; /* NFS procedure number */ - int r_rtt; /* RTT for rpc */ - RPC_EXEC_CTX r_td; -}; - -struct rpc_reply { - struct { - u_int32_t type; - u_int32_t status; - - /* used only when reply == RPC_MSGDENIED and - * status == RPC_AUTHERR */ - u_int32_t autherr; - - /* rpc mismatch info if reply == RPC_MSGDENIED and - * status == RPC_MISMATCH */ - struct { - u_int32_t low; - u_int32_t high; - } mismatch_info; - } stat; - - /* head of the mbuf chain */ - struct mbuf * mrep; - - /* mbuf and position of the verification opaque data - * note that this is only valid when stat.reply == RPC_MSGACCEPTED */ - u_int32_t verf_type; - u_int32_t verf_size; - struct mbuf * verf_md; - caddr_t verf_dpos; - - /* mbuf and postion of the result of the rpc request */ - struct mbuf * result_md; - caddr_t result_dpos; -}; - - -/* - * RPC Client connection context. - * One allocated on every NFS mount. - * Holds RPC specific information for mount. - */ -/* XXX: please note that all pointer type variables are just set (not copied), - * so it is up to the user to free these values */ -struct rpcclnt { - int rc_flag; /* For RPCCLNT_* flags */ - - int rc_wsize; /* Max size of the request data */ - int rc_rsize; /* Max size of the response data */ - struct sockaddr *rc_name; - struct socket *rc_so; /* Rpc socket */ - int rc_sotype; /* Type of socket */ - int rc_soproto; /* and protocol */ - int rc_soflags; /* pr_flags for socket protocol */ - - int rc_timeo; /* Init timer for NFSMNT_DUMBTIMR */ - int rc_retry; /* Max retries */ - int rc_srtt[4]; /* Timers for rpcs */ - int rc_sdrtt[4]; - int rc_sent; /* Request send count */ - int rc_cwnd; /* Request send window */ - int rc_timeouts; /* Request timeouts */ - -/* XXX: this is not being set!!!! */ - int rc_deadthresh; /* Threshold of timeouts-->dead server*/ - - - /* authentication: */ - /* currently can be RPCAUTH_NULL, RPCAUTH_KERBV4, RPCAUTH_UNIX */ - /* should be kept in XDR form */ - int rc_authtype; /* Authenticator type */ - - -#if 0 - /* RPCAUTH_KERB4 */ - int rc_authlen; /* and length */ - char *rc_authstr; /* Authenticator string */ - int rc_verflen; - char *rc_verfstr; /* and the verifier */ -#endif - - /* RPCAUTH_UNIX*/ - struct rpc_auth * rc_auth; /* authentication */ - -#if 0 - /* stored in XDR form (network byte order) */ - unsigned int rc_progid; /* program id */ - unsigned int rc_progvers; /* program version */ - - /* name of server for log messages */ - const char *rc_servername; /* for printing error messages */ -#else - struct rpc_program * rc_prog; -#endif - - /* XXX: this should be removed */ - int rc_proctlen; /* if == 0 then rc_proct == NULL */ - int * rc_proct; -}; - -#ifdef __OpenBSD__ -extern struct pool rpcreply_pool; -extern struct pool rpcclnt_pool; -#else -/* MALLOC_DECLARE(M_RPC); */ -#endif -extern int rpcdebugon; - - -#ifdef __OpenBSD__ -#define rpcclnt_get(X) \ - do { \ - (X) = pool_get(&rpcclnt_pool, PR_WAITOK); \ - bzero((X), sizeof(struct rpcclnt)); \ - }while(0) - -#define rpcclnt_put(X) \ - do { \ - if ((X) != NULL){ \ - pool_put(&rpcclnt_pool, (X)); \ - }}while(0) - -#else /* !__OpenBSD__ */ - -/* usage count for module (un)loading */ -extern unsigned int rpcclnt_usage; -extern struct mtx rpcclnt_usage_mutex; - -void rpcclnt_create(struct rpcclnt ** rpc); -void rpcclnt_destroy(struct rpcclnt * rpc); - -#define rpcclnt_get(X) rpcclnt_create(&(X)) -#define rpcclnt_put(X) rpcclnt_destroy(X) - -#ifdef RPCCLNT_TEST -struct rpcclnt_test_args { - int nothing; -}; -int rpcclnt_test(struct thread *, struct rpcclnt_test_args *); - -#define RPC_RETURN(X) do { RPCDEBUG("returning %d", X); return X; }while(0) -#endif /* RPCCLNT_TEST */ - -#endif /* !__OpenBSD__ */ - -void rpcclnt_init(void); -void rpcclnt_uninit(void); -#if 0 -int rpcclnt_setup(struct rpcclnt *, int, struct sockaddr *, int, int, int, int, const char *, int, int); -#endif - -int rpcclnt_setup(struct rpcclnt *, struct rpc_program *, struct sockaddr *, int, int, struct rpc_auth *, int, int, int); - - -int rpcclnt_connect(struct rpcclnt *, RPC_EXEC_CTX td); -int rpcclnt_reconnect(struct rpctask *, RPC_EXEC_CTX td); -void rpcclnt_disconnect(struct rpcclnt *); -void rpcclnt_safedisconnect(struct rpcclnt *); - -void rpcclnt_setauth(struct rpcclnt *, u_int32_t, u_int32_t, char *, u_int32_t, char *, struct ucred *); -int rpcclnt_request(struct rpcclnt *, struct mbuf *, int, RPC_EXEC_CTX, struct ucred *, struct rpc_reply *); -int rpcclnt_err(struct rpc_reply *); - -int rpcclnt_cancelreqs(struct rpcclnt *); -int rpcclnt_sigintr(struct rpcclnt *, struct rpctask *, RPC_EXEC_CTX); - - -#endif /* _RPCCLNT_H_ */ |