summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/alpha/alpha/autoconf.c2
-rw-r--r--sys/alpha/conf/GENERIC3
-rw-r--r--sys/alpha/conf/NOTES3
-rw-r--r--sys/alpha/conf/SIMOS3
-rw-r--r--sys/amd64/amd64/autoconf.c36
-rw-r--r--sys/amd64/amd64/genassym.c6
-rw-r--r--sys/amd64/conf/GENERIC3
-rw-r--r--sys/amd64/include/md_var.h1
-rw-r--r--sys/conf/NOTES3
-rw-r--r--sys/conf/files30
-rw-r--r--sys/conf/options3
-rw-r--r--sys/i386/conf/GENERIC3
-rw-r--r--sys/i386/conf/NOTES3
-rw-r--r--sys/i386/i386/autoconf.c36
-rw-r--r--sys/i386/i386/genassym.c6
-rw-r--r--sys/i386/include/md_var.h1
-rw-r--r--sys/ia64/conf/GENERIC3
-rw-r--r--sys/ia64/ia64/autoconf.c4
-rw-r--r--sys/kern/syscalls.master1
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/nfsclient/Makefile15
-rw-r--r--sys/modules/nfsserver/Makefile18
-rw-r--r--sys/nfs/bootp_subr.c2042
-rw-r--r--sys/nfs/krpc.h31
-rw-r--r--sys/nfs/krpc_subr.c487
-rw-r--r--sys/nfs/nfs.h727
-rw-r--r--sys/nfs/nfs_bio.c1641
-rw-r--r--sys/nfs/nfs_common.c2069
-rw-r--r--sys/nfs/nfs_common.h563
-rw-r--r--sys/nfs/nfs_lock.c286
-rw-r--r--sys/nfs/nfs_lock.h112
-rw-r--r--sys/nfs/nfs_node.c468
-rw-r--r--sys/nfs/nfs_nqlease.c1288
-rw-r--r--sys/nfs/nfs_serv.c4235
-rw-r--r--sys/nfs/nfs_socket.c2296
-rw-r--r--sys/nfs/nfs_srvcache.c352
-rw-r--r--sys/nfs/nfs_subs.c2243
-rw-r--r--sys/nfs/nfs_syscalls.c1214
-rw-r--r--sys/nfs/nfs_vfsops.c1075
-rw-r--r--sys/nfs/nfs_vnops.c3344
-rw-r--r--sys/nfs/nfsdiskless.h124
-rw-r--r--sys/nfs/nfsmount.h106
-rw-r--r--sys/nfs/nfsproto.h21
-rw-r--r--sys/nfs/nfsrtt.h104
-rw-r--r--sys/nfs/nfsrvcache.h91
-rw-r--r--sys/nfs/nfsv2.h40
-rw-r--r--sys/nfs/nlminfo.h45
-rw-r--r--sys/nfs/nqnfs.h208
-rw-r--r--sys/nfs/rpcv2.h41
-rw-r--r--sys/nfsclient/bootp_subr.c471
-rw-r--r--sys/nfsclient/krpc.h10
-rw-r--r--sys/nfsclient/krpc_subr.c29
-rw-r--r--sys/nfsclient/nfs.h567
-rw-r--r--sys/nfsclient/nfs_bio.c294
-rw-r--r--sys/nfsclient/nfs_lock.c37
-rw-r--r--sys/nfsclient/nfs_lock.h26
-rw-r--r--sys/nfsclient/nfs_nfsiod.c1097
-rw-r--r--sys/nfsclient/nfs_node.c93
-rw-r--r--sys/nfsclient/nfs_socket.c1157
-rw-r--r--sys/nfsclient/nfs_subs.c1809
-rw-r--r--sys/nfsclient/nfs_vfsops.c266
-rw-r--r--sys/nfsclient/nfs_vnops.c971
-rw-r--r--sys/nfsclient/nfsargs.h641
-rw-r--r--sys/nfsclient/nfsdiskless.h11
-rw-r--r--sys/nfsclient/nfsm_subs.h571
-rw-r--r--sys/nfsclient/nfsmount.h18
-rw-r--r--sys/nfsclient/nfsnode.h44
-rw-r--r--sys/nfsclient/nfsstats.h664
-rw-r--r--sys/nfsclient/nlminfo.h3
-rw-r--r--sys/nfsserver/nfs.h530
-rw-r--r--sys/nfsserver/nfs_serv.c853
-rw-r--r--sys/nfsserver/nfs_srvcache.c72
-rw-r--r--sys/nfsserver/nfs_srvsock.c1807
-rw-r--r--sys/nfsserver/nfs_srvsubs.c1399
-rw-r--r--sys/nfsserver/nfs_syscalls.c694
-rw-r--r--sys/nfsserver/nfsm_subs.h561
-rw-r--r--sys/nfsserver/nfsrvcache.h8
-rw-r--r--sys/nfsserver/nfsrvstats.h680
-rw-r--r--sys/pc98/conf/GENERIC3
-rw-r--r--sys/powerpc/powerpc/autoconf.c2
80 files changed, 2805 insertions, 38022 deletions
diff --git a/sys/alpha/alpha/autoconf.c b/sys/alpha/alpha/autoconf.c
index e9fa26b..1b9d83f 100644
--- a/sys/alpha/alpha/autoconf.c
+++ b/sys/alpha/alpha/autoconf.c
@@ -69,7 +69,7 @@ static void configure_start __P((void));
device_t isa_bus_device = 0;
#endif
-extern int nfs_diskless_valid;
+extern int nfs_diskless_valid; /* XXX use include file */
dev_t rootdev = NODEV;
dev_t dumpdev = NODEV;
diff --git a/sys/alpha/conf/GENERIC b/sys/alpha/conf/GENERIC
index fb22f76..2b20775 100644
--- a/sys/alpha/conf/GENERIC
+++ b/sys/alpha/conf/GENERIC
@@ -53,7 +53,8 @@ options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MD_ROOT #MD is a potential root device
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options NFS_ROOT #NFS usable as root device
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
diff --git a/sys/alpha/conf/NOTES b/sys/alpha/conf/NOTES
index fb22f76..2b20775 100644
--- a/sys/alpha/conf/NOTES
+++ b/sys/alpha/conf/NOTES
@@ -53,7 +53,8 @@ options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MD_ROOT #MD is a potential root device
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options NFS_ROOT #NFS usable as root device
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
diff --git a/sys/alpha/conf/SIMOS b/sys/alpha/conf/SIMOS
index ec314be..a72864c 100644
--- a/sys/alpha/conf/SIMOS
+++ b/sys/alpha/conf/SIMOS
@@ -22,7 +22,8 @@ options "DEC_KN8AE"
options SIMOS
options INET #InterNETworking
options FFS #Berkeley Fast Filesystem
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options MSDOSFS #MSDOS Filesystem
options "CD9660" #ISO 9660 Filesystem
options NFS_ROOT #NFS usable as root device
diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c
index 6c370bd..5b7c42f 100644
--- a/sys/amd64/amd64/autoconf.c
+++ b/sys/amd64/amd64/autoconf.c
@@ -63,6 +63,20 @@
#include <sys/mount.h>
#include <sys/cons.h>
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsdiskless.h>
+#endif
+
#include <machine/bootinfo.h>
#include <machine/md_var.h>
#ifdef APIC_IO
@@ -81,7 +95,7 @@ static void configure_first __P((void *));
static void configure __P((void *));
static void configure_final __P((void *));
-#if defined(NFS) && defined(NFS_ROOT)
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
static void pxe_setup_nfsdiskless(void);
#endif
@@ -217,7 +231,7 @@ cpu_rootconf()
#ifdef BOOTP
bootpc_init();
#endif
-#if defined(NFS) && defined(NFS_ROOT)
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
#if !defined(BOOTP_NFSROOT)
pxe_setup_nfsdiskless();
if (nfs_diskless_valid)
@@ -229,21 +243,7 @@ SYSINIT(cpu_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, cpu_rootconf, NULL)
u_long bootdev = 0; /* not a dev_t - encoding is different */
-#if defined(NFS) && defined(NFS_ROOT)
-
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <net/if_var.h>
-#include <net/ethernet.h>
-#include <netinet/in.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsdiskless.h>
-
-extern struct nfs_diskless nfs_diskless;
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
static int
inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa)
@@ -325,7 +325,7 @@ decode_nfshandle(char *ev, u_char *fh)
* boot.nfsroot.nfshandle NFS handle for root filesystem on server
*/
static void
-pxe_setup_nfsdiskless()
+pxe_setup_nfsdiskless(void)
{
struct nfs_diskless *nd = &nfs_diskless;
struct ifnet *ifp;
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 8f4be92..ab8a32d 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -65,10 +65,10 @@
#include <sys/user.h>
#include <net/if.h>
#include <netinet/in.h>
-#include <nfs/nfsv2.h>
+#include <nfs/nfsproto.h>
#include <nfs/rpcv2.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsdiskless.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsdiskless.h>
#ifdef SMP
#include <machine/apic.h>
#endif
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 420dff6..c1bbde2 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -35,7 +35,8 @@ options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MD_ROOT #MD is a potential root device
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options NFS_ROOT #NFS usable as root device, NFS required
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index c3564c2..c2e2aa1 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -55,7 +55,6 @@ extern char kstack[];
extern int need_pre_dma_flush;
extern int need_post_dma_flush;
#endif
-extern int nfs_diskless_valid;
extern void (*ovbcopy_vector) __P((const void *from, void *to, size_t len));
extern char sigcode[];
extern int szsigcode, szosigcode;
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index ec085ac..644fdd4 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -685,7 +685,8 @@ device hfa #FORE PCA-200E ATM PCI
# One of these is mandatory:
options FFS #Fast filesystem
-options NFS #Network File System
+options NFSCLIENT #Network File System
+options NFSSERVER #Network File System
# The rest are optional:
#options NFS_NOSERVER #Disable the NFS-server code.
diff --git a/sys/conf/files b/sys/conf/files
index 72282a5..d97bb78 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1160,19 +1160,23 @@ netns/ns_pcb.c optional ns
netns/ns_proto.c optional ns
netns/spp_debug.c optional ns
netns/spp_usrreq.c optional ns
-nfs/bootp_subr.c optional bootp
-nfs/krpc_subr.c optional bootp
-nfs/nfs_bio.c optional nfs
-nfs/nfs_node.c optional nfs
-nfs/nfs_lock.c optional nfs
-nfs/nfs_nqlease.c optional nfs
-nfs/nfs_serv.c optional nfs
-nfs/nfs_socket.c optional nfs
-nfs/nfs_srvcache.c optional nfs
-nfs/nfs_subs.c optional nfs
-nfs/nfs_syscalls.c optional nfs
-nfs/nfs_vfsops.c optional nfs
-nfs/nfs_vnops.c optional nfs
+nfs/nfs_common.c optional nfsclient
+nfs/nfs_common.c optional nfsserver
+nfsclient/bootp_subr.c optional bootp nfsclient
+nfsclient/krpc_subr.c optional bootp nfsclient
+nfsclient/nfs_bio.c optional nfsclient
+nfsclient/nfs_node.c optional nfsclient
+nfsclient/nfs_socket.c optional nfsclient
+nfsclient/nfs_subs.c optional nfsclient
+nfsclient/nfs_nfsiod.c optional nfsclient
+nfsclient/nfs_vfsops.c optional nfsclient
+nfsclient/nfs_vnops.c optional nfsclient
+nfsclient/nfs_lock.c optional nfsclient
+nfsserver/nfs_serv.c optional nfsserver
+nfsserver/nfs_srvsock.c optional nfsserver
+nfsserver/nfs_srvcache.c optional nfsserver
+nfsserver/nfs_srvsubs.c optional nfsserver
+nfsserver/nfs_syscalls.c optional nfsserver
pccard/pccard.c count card
pccard/pccard_beep.c optional card
pccard/pccard_nbk.c optional card
diff --git a/sys/conf/options b/sys/conf/options
index f43d3d6..f6b9ccb 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -139,7 +139,8 @@ IFS opt_ffs_broken_fixme.h
# sys/i386/i386/autoconf.c. If any of these filesystems are
# statically compiled into the kernel, code for mounting them as root
# filesystems will be enabled - but look below.
-NFS
+NFSCLIENT opt_nfs.h
+NFSSERVER opt_nfs.h
# If you are following the conditions in the copyright,
# you can enable soft-updates which will speed up a lot of thigs
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 420dff6..c1bbde2 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -35,7 +35,8 @@ options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MD_ROOT #MD is a potential root device
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options NFS_ROOT #NFS usable as root device, NFS required
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index ec085ac..644fdd4 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -685,7 +685,8 @@ device hfa #FORE PCA-200E ATM PCI
# One of these is mandatory:
options FFS #Fast filesystem
-options NFS #Network File System
+options NFSCLIENT #Network File System
+options NFSSERVER #Network File System
# The rest are optional:
#options NFS_NOSERVER #Disable the NFS-server code.
diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c
index 6c370bd..5b7c42f 100644
--- a/sys/i386/i386/autoconf.c
+++ b/sys/i386/i386/autoconf.c
@@ -63,6 +63,20 @@
#include <sys/mount.h>
#include <sys/cons.h>
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsdiskless.h>
+#endif
+
#include <machine/bootinfo.h>
#include <machine/md_var.h>
#ifdef APIC_IO
@@ -81,7 +95,7 @@ static void configure_first __P((void *));
static void configure __P((void *));
static void configure_final __P((void *));
-#if defined(NFS) && defined(NFS_ROOT)
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
static void pxe_setup_nfsdiskless(void);
#endif
@@ -217,7 +231,7 @@ cpu_rootconf()
#ifdef BOOTP
bootpc_init();
#endif
-#if defined(NFS) && defined(NFS_ROOT)
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
#if !defined(BOOTP_NFSROOT)
pxe_setup_nfsdiskless();
if (nfs_diskless_valid)
@@ -229,21 +243,7 @@ SYSINIT(cpu_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, cpu_rootconf, NULL)
u_long bootdev = 0; /* not a dev_t - encoding is different */
-#if defined(NFS) && defined(NFS_ROOT)
-
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <net/if_var.h>
-#include <net/ethernet.h>
-#include <netinet/in.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsdiskless.h>
-
-extern struct nfs_diskless nfs_diskless;
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
static int
inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa)
@@ -325,7 +325,7 @@ decode_nfshandle(char *ev, u_char *fh)
* boot.nfsroot.nfshandle NFS handle for root filesystem on server
*/
static void
-pxe_setup_nfsdiskless()
+pxe_setup_nfsdiskless(void)
{
struct nfs_diskless *nd = &nfs_diskless;
struct ifnet *ifp;
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 8f4be92..ab8a32d 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -65,10 +65,10 @@
#include <sys/user.h>
#include <net/if.h>
#include <netinet/in.h>
-#include <nfs/nfsv2.h>
+#include <nfs/nfsproto.h>
#include <nfs/rpcv2.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsdiskless.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsdiskless.h>
#ifdef SMP
#include <machine/apic.h>
#endif
diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
index c3564c2..c2e2aa1 100644
--- a/sys/i386/include/md_var.h
+++ b/sys/i386/include/md_var.h
@@ -55,7 +55,6 @@ extern char kstack[];
extern int need_pre_dma_flush;
extern int need_post_dma_flush;
#endif
-extern int nfs_diskless_valid;
extern void (*ovbcopy_vector) __P((const void *from, void *to, size_t len));
extern char sigcode[];
extern int szsigcode, szosigcode;
diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC
index f78eaf7..6b6970c 100644
--- a/sys/ia64/conf/GENERIC
+++ b/sys/ia64/conf/GENERIC
@@ -37,7 +37,8 @@ options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MD_ROOT #MD is a potential root device
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options NFS_ROOT #NFS usable as root device
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c
index f8a8d81..5868253 100644
--- a/sys/ia64/ia64/autoconf.c
+++ b/sys/ia64/ia64/autoconf.c
@@ -62,7 +62,7 @@ SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL)
device_t isa_bus_device = 0;
#endif
-extern int nfs_diskless_valid;
+extern int nfs_diskless_valid; /* XXX use include file */
dev_t rootdev = NODEV;
dev_t dumpdev = NODEV;
@@ -104,7 +104,7 @@ void
cpu_rootconf()
{
int order = 0;
-#if defined(NFS) && defined(NFS_ROOT)
+#if defined(NFSCLIENT) && defined(NFS_ROOT)
#if !defined(BOOTP_NFSROOT)
if (nfs_diskless_valid)
#endif
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index d8f9fdc..31de61d 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -543,3 +543,4 @@
373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \
const char *attrname); }
374 MSTD BSD { int __setugid(int flag); }
+375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); }
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index a648db2..3cae877 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -49,7 +49,8 @@ SUBDIR= 3dfx \
mii \
mlx \
msdosfs \
- nfs \
+ nfsclient \
+ nfsserver \
nge \
nmdm \
ntfs \
diff --git a/sys/modules/nfsclient/Makefile b/sys/modules/nfsclient/Makefile
index 05ab424..9f806ac 100644
--- a/sys/modules/nfsclient/Makefile
+++ b/sys/modules/nfsclient/Makefile
@@ -1,17 +1,18 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../nfs
-
-KMOD= nfs
+.PATH: ${.CURDIR}/../../nfsclient ${.CURDIR}/../../nfs
+KMOD= nfsclient
SRCS= vnode_if.h \
- nfs_bio.c nfs_lock.c nfs_node.c nfs_nqlease.c nfs_serv.c nfs_socket.c \
- nfs_srvcache.c nfs_subs.c nfs_syscalls.c nfs_vfsops.c \
- nfs_vnops.c opt_inet.h opt_nfs.h opt_vmpage.h opt_bootp.h
+ nfs_bio.c nfs_node.c nfs_socket.c nfs_subs.c nfs_nfsiod.c \
+ nfs_vfsops.c nfs_vnops.c nfs_common.c \
+ opt_inet.h opt_nfs.h opt_bootp.h
+
NFS_INET?= 1 # 0/1 - requires INET to be configured in kernel
NOMAN=
-.if ${NFS_INET} > 0
opt_inet.h:
+ touch ${.TARGET}
+.if ${NFS_INET} > 0
echo "#define INET 1" > ${.TARGET}
.endif
diff --git a/sys/modules/nfsserver/Makefile b/sys/modules/nfsserver/Makefile
index 05ab424..9c9808d 100644
--- a/sys/modules/nfsserver/Makefile
+++ b/sys/modules/nfsserver/Makefile
@@ -1,18 +1,12 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../nfs
-
-KMOD= nfs
+.PATH: ${.CURDIR}/../../nfsserver ${.CURDIR}/../../nfs
+KMOD= nfsserver
SRCS= vnode_if.h \
- nfs_bio.c nfs_lock.c nfs_node.c nfs_nqlease.c nfs_serv.c nfs_socket.c \
- nfs_srvcache.c nfs_subs.c nfs_syscalls.c nfs_vfsops.c \
- nfs_vnops.c opt_inet.h opt_nfs.h opt_vmpage.h opt_bootp.h
-NFS_INET?= 1 # 0/1 - requires INET to be configured in kernel
-NOMAN=
+ nfs_serv.c nfs_srvsock.c nfs_srvcache.c nfs_srvsubs.c nfs_syscalls.c \
+ nfs_common.c \
+ opt_nfs.h
-.if ${NFS_INET} > 0
-opt_inet.h:
- echo "#define INET 1" > ${.TARGET}
-.endif
+NOMAN=
.include <bsd.kmod.mk>
diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
deleted file mode 100644
index 063f77f..0000000
--- a/sys/nfs/bootp_subr.c
+++ /dev/null
@@ -1,2042 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * Copyright (c) 1995 Gordon Ross, Adam Glass
- * Copyright (c) 1992 Regents of the University of California.
- * All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * 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, Lawrence Berkeley Laboratory 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.
- *
- * based on:
- * nfs/krpc_subr.c
- * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
- */
-
-#include "opt_bootp.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/sockio.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/uio.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <net/if_types.h>
-#include <net/if_dl.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsdiskless.h>
-#include <nfs/krpc.h>
-#include <nfs/xdr_subs.h>
-
-
-#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */
-
-#ifndef BOOTP_SETTLE_DELAY
-#define BOOTP_SETTLE_DELAY 3
-#endif
-
-/*
- * What is the longest we will wait before re-sending a request?
- * Note this is also the frequency of "RPC timeout" messages.
- * The re-send loop count sup linearly to this maximum, so the
- * first complaint will happen after (1+2+3+4+5)=15 seconds.
- */
-#define MAX_RESEND_DELAY 5 /* seconds */
-
-/* Definitions from RFC951 */
-struct bootp_packet {
- u_int8_t op;
- u_int8_t htype;
- u_int8_t hlen;
- u_int8_t hops;
- u_int32_t xid;
- u_int16_t secs;
- u_int16_t flags;
- struct in_addr ciaddr;
- struct in_addr yiaddr;
- struct in_addr siaddr;
- struct in_addr giaddr;
- unsigned char chaddr[16];
- char sname[64];
- char file[128];
- unsigned char vend[256];
-};
-
-struct bootpc_ifcontext {
- struct bootpc_ifcontext *next;
- struct bootp_packet call;
- struct bootp_packet reply;
- int replylen;
- int overload;
- struct socket *so;
- struct ifreq ireq;
- struct ifnet *ifp;
- struct sockaddr_dl *sdl;
- struct sockaddr_in myaddr;
- struct sockaddr_in netmask;
- struct sockaddr_in gw;
- struct sockaddr_in broadcast; /* Different for each interface */
- int gotgw;
- int gotnetmask;
- int gotrootpath;
- int outstanding;
- int sentmsg;
- u_int32_t xid;
- enum {
- IF_BOOTP_UNRESOLVED,
- IF_BOOTP_RESOLVED,
- IF_BOOTP_FAILED,
- IF_DHCP_UNRESOLVED,
- IF_DHCP_OFFERED,
- IF_DHCP_RESOLVED,
- IF_DHCP_FAILED,
- } state;
- int dhcpquerytype; /* dhcp type sent */
- struct in_addr dhcpserver;
- int gotdhcpserver;
-};
-
-#define TAG_MAXLEN 1024
-struct bootpc_tagcontext {
- char buf[TAG_MAXLEN + 1];
- int overload;
- int badopt;
- int badtag;
- int foundopt;
- int taglen;
-};
-
-struct bootpc_globalcontext {
- struct bootpc_ifcontext *interfaces;
- struct bootpc_ifcontext *lastinterface;
- u_int32_t xid;
- int gotrootpath;
- int gotswappath;
- int gotgw;
- int ifnum;
- int secs;
- int starttime;
- struct bootp_packet reply;
- int replylen;
- struct bootpc_ifcontext *setswapfs;
- struct bootpc_ifcontext *setrootfs;
- struct bootpc_ifcontext *sethostname;
- char lookup_path[24];
- struct bootpc_tagcontext tmptag;
- struct bootpc_tagcontext tag;
-};
-
-#define IPPORT_BOOTPC 68
-#define IPPORT_BOOTPS 67
-
-#define BOOTP_REQUEST 1
-#define BOOTP_REPLY 2
-
-/* Common tags */
-#define TAG_PAD 0 /* Pad option, implicit length 1 */
-#define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */
-#define TAG_ROUTERS 3 /* Routers (in order of preference) */
-#define TAG_HOSTNAME 12 /* Client host name */
-#define TAG_ROOT 17 /* Root path */
-
-/* DHCP specific tags */
-#define TAG_OVERLOAD 52 /* Option Overload */
-#define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */
-
-#define TAG_END 255 /* End Option (i.e. no more options) */
-
-/* Overload values */
-#define OVERLOAD_FILE 1
-#define OVERLOAD_SNAME 2
-
-/* Site specific tags: */
-#define TAG_SWAP 128
-#define TAG_SWAPSIZE 129
-#define TAG_ROOTOPTS 130
-#define TAG_SWAPOPTS 131
-
-#define TAG_DHCP_MSGTYPE 53
-#define TAG_DHCP_REQ_ADDR 50
-#define TAG_DHCP_SERVERID 54
-#define TAG_DHCP_LEASETIME 51
-
-#define DHCP_NOMSG 0
-#define DHCP_DISCOVER 1
-#define DHCP_OFFER 2
-#define DHCP_REQUEST 3
-#define DHCP_ACK 5
-
-extern int nfs_diskless_valid;
-extern struct nfsv3_diskless nfsv3_diskless;
-
-/* mountd RPC */
-static int md_mount(struct sockaddr_in *mdsin, char *path,
- u_char *fhp, int *fhsizep,
- struct nfs_args *args,struct thread *td);
-static int md_lookup_swap(struct sockaddr_in *mdsin,char *path,
- u_char *fhp, int *fhsizep,
- struct nfs_args *args,
- struct thread *td);
-static int setfs(struct sockaddr_in *addr, char *path, char *p);
-static int getdec(char **ptr);
-static char *substr(char *a,char *b);
-static void mountopts(struct nfs_args *args, char *p);
-static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
-static int xdr_int_decode(struct mbuf **ptr, int *iptr);
-static void print_in_addr(struct in_addr addr);
-static void print_sin_addr(struct sockaddr_in *addr);
-static void clear_sinaddr(struct sockaddr_in *sin);
-static
-struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx);
-static void bootpc_compose_query(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td);
-static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
- struct bootp_packet *bp, int len, int tag);
-static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
- unsigned char *start, int len, int tag);
-
-#ifdef BOOTP_DEBUG
-void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma);
-void bootpboot_p_ma(struct sockaddr *ma);
-void bootpboot_p_rtentry(struct rtentry *rt);
-void bootpboot_p_tree(struct radix_node *rn);
-void bootpboot_p_rtlist(void);
-void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa);
-void bootpboot_p_iflist(void);
-#endif
-
-static int bootpc_call(struct bootpc_globalcontext *gctx,
- struct thread *td);
-
-static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td);
-
-static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td);
-
-static void bootpc_decode_reply(struct nfsv3_diskless *nd,
- struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx);
-
-static int bootpc_received(struct bootpc_globalcontext *gctx,
- struct bootpc_ifcontext *ifctx);
-
-static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx);
-static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx);
-static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx);
-
-void bootpc_init(void);
-
-/*
- * In order to have multiple active interfaces with address 0.0.0.0
- * and be able to send data to a selected interface, we perform
- * some tricks:
- *
- * - The 'broadcast' address is different for each interface.
- *
- * - We temporarily add routing pointing 255.255.255.255 to the
- * selected interface broadcast address, thus the packet sent
- * goes to that interface.
- */
-
-#ifdef BOOTP_DEBUG
-void
-bootpboot_p_sa(struct sockaddr *sa,
- struct sockaddr *ma)
-{
- if (sa == NULL) {
- printf("(sockaddr *) <null>");
- return;
- }
- switch (sa->sa_family) {
- case AF_INET:
- {
- struct sockaddr_in *sin;
-
- sin = (struct sockaddr_in *) sa;
- printf("inet ");
- print_sin_addr(sin);
- if (ma != NULL) {
- sin = (struct sockaddr_in *) ma;
- printf(" mask ");
- print_sin_addr(sin);
- }
- }
- break;
- case AF_LINK:
- {
- struct sockaddr_dl *sli;
- int i;
-
- sli = (struct sockaddr_dl *) sa;
- printf("link %.*s ", sli->sdl_nlen, sli->sdl_data);
- for (i = 0; i < sli->sdl_alen; i++) {
- if (i > 0)
- printf(":");
- printf("%x", ((unsigned char *) LLADDR(sli))[i]);
- }
- }
- break;
- default:
- printf("af%d", sa->sa_family);
- }
-}
-
-
-void
-bootpboot_p_ma(struct sockaddr *ma)
-{
- if (ma == NULL) {
- printf("<null>");
- return;
- }
- printf("%x", *(int *)ma);
-}
-
-
-void
-bootpboot_p_rtentry(struct rtentry *rt)
-{
- bootpboot_p_sa(rt_key(rt), rt_mask(rt));
- printf(" ");
- bootpboot_p_ma(rt->rt_genmask);
- printf(" ");
- bootpboot_p_sa(rt->rt_gateway, NULL);
- printf(" ");
- printf("flags %x", (unsigned short) rt->rt_flags);
- printf(" %d", (int) rt->rt_rmx.rmx_expire);
- printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit);
-}
-
-
-void
-bootpboot_p_tree(struct radix_node *rn)
-{
- while (rn != NULL) {
- if (rn->rn_bit < 0) {
- if ((rn->rn_flags & RNF_ROOT) != 0) {
- } else {
- bootpboot_p_rtentry((struct rtentry *) rn);
- }
- rn = rn->rn_dupedkey;
- } else {
- bootpboot_p_tree(rn->rn_left);
- bootpboot_p_tree(rn->rn_right);
- return;
- }
- }
-}
-
-
-void
-bootpboot_p_rtlist(void)
-{
- printf("Routing table:\n");
- bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop);
-}
-
-
-void
-bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
-{
- printf("%s%d flags %x, addr ",
- ifp->if_name,
- ifp->if_unit,
- (unsigned short) ifp->if_flags);
- print_sin_addr((struct sockaddr_in *) ifa->ifa_addr);
- printf(", broadcast ");
- print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr);
- printf(", netmask ");
- print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask);
- printf("\n");
-}
-
-
-void
-bootpboot_p_iflist(void)
-{
- struct ifnet *ifp;
- struct ifaddr *ifa;
-
- printf("Interface list:\n");
- for (ifp = TAILQ_FIRST(&ifnet);
- ifp != NULL;
- ifp = TAILQ_NEXT(ifp, if_link)) {
- for (ifa = TAILQ_FIRST(&ifp->if_addrhead);
- ifa != NULL;
- ifa = TAILQ_NEXT(ifa, ifa_link))
- if (ifa->ifa_addr->sa_family == AF_INET)
- bootpboot_p_if(ifp, ifa);
- }
-}
-#endif /* defined(BOOTP_DEBUG) */
-
-
-static void
-clear_sinaddr(struct sockaddr_in *sin)
-{
- bzero(sin, sizeof(*sin));
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */
- sin->sin_port = 0;
-}
-
-
-static struct bootpc_ifcontext *
-allocifctx(struct bootpc_globalcontext *gctx)
-{
- struct bootpc_ifcontext *ifctx;
- ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx),
- M_TEMP, M_WAITOK);
- if (ifctx == NULL)
- panic("Failed to allocate bootp interface context structure");
-
- bzero(ifctx, sizeof(*ifctx));
- ifctx->xid = gctx->xid;
-#ifdef BOOTP_NO_DHCP
- ifctx->state = IF_BOOTP_UNRESOLVED;
-#else
- ifctx->state = IF_DHCP_UNRESOLVED;
-#endif
- gctx->xid += 0x100;
- return ifctx;
-}
-
-
-static __inline int
-bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx)
-{
- if (ifctx->state == IF_BOOTP_RESOLVED ||
- ifctx->state == IF_DHCP_RESOLVED)
- return 1;
- return 0;
-}
-
-
-static __inline int
-bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx)
-{
- if (ifctx->state == IF_BOOTP_UNRESOLVED ||
- ifctx->state == IF_DHCP_UNRESOLVED)
- return 1;
- return 0;
-}
-
-
-static __inline int
-bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx)
-{
- if (ifctx->state == IF_BOOTP_FAILED ||
- ifctx->state == IF_DHCP_FAILED)
- return 1;
- return 0;
-}
-
-
-static int
-bootpc_received(struct bootpc_globalcontext *gctx,
- struct bootpc_ifcontext *ifctx)
-{
- unsigned char dhcpreplytype;
- char *p;
- /*
- * Need timeout for fallback to less
- * desirable alternative.
- */
-
-
- /* This call used for the side effect (badopt flag) */
- (void) bootpc_tag(&gctx->tmptag, &gctx->reply,
- gctx->replylen,
- TAG_END);
-
- /* If packet is invalid, ignore it */
- if (gctx->tmptag.badopt != 0)
- return 0;
-
- p = bootpc_tag(&gctx->tmptag, &gctx->reply,
- gctx->replylen, TAG_DHCP_MSGTYPE);
- if (p != NULL)
- dhcpreplytype = *p;
- else
- dhcpreplytype = DHCP_NOMSG;
-
- switch (ifctx->dhcpquerytype) {
- case DHCP_DISCOVER:
- if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */
-#ifndef BOOTP_FORCE_DHCP
- && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */
-#endif
- )
- return 0;
- break;
- case DHCP_REQUEST:
- if (dhcpreplytype != DHCP_ACK)
- return 0;
- case DHCP_NOMSG:
- }
-
-
- /* Ignore packet unless it gives us a root tag we didn't have */
-
- if ((ifctx->state == IF_BOOTP_RESOLVED ||
- (ifctx->dhcpquerytype == DHCP_DISCOVER &&
- (ifctx->state == IF_DHCP_OFFERED ||
- ifctx->state == IF_DHCP_RESOLVED))) &&
- (bootpc_tag(&gctx->tmptag, &ifctx->reply,
- ifctx->replylen,
- TAG_ROOT) != NULL ||
- bootpc_tag(&gctx->tmptag, &gctx->reply,
- gctx->replylen,
- TAG_ROOT) == NULL))
- return 0;
-
- bcopy(&gctx->reply,
- &ifctx->reply,
- gctx->replylen);
- ifctx->replylen = gctx->replylen;
-
- /* XXX: Only reset if 'perfect' response */
- if (ifctx->state == IF_BOOTP_UNRESOLVED)
- ifctx->state = IF_BOOTP_RESOLVED;
- else if (ifctx->state == IF_DHCP_UNRESOLVED &&
- ifctx->dhcpquerytype == DHCP_DISCOVER) {
- if (dhcpreplytype == DHCP_OFFER)
- ifctx->state = IF_DHCP_OFFERED;
- else
- ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */
- } else if (ifctx->state == IF_DHCP_OFFERED &&
- ifctx->dhcpquerytype == DHCP_REQUEST)
- ifctx->state = IF_DHCP_RESOLVED;
-
-
- if (ifctx->dhcpquerytype == DHCP_DISCOVER &&
- ifctx->state != IF_BOOTP_RESOLVED) {
- p = bootpc_tag(&gctx->tmptag, &ifctx->reply,
- ifctx->replylen, TAG_DHCP_SERVERID);
- if (p != NULL && gctx->tmptag.taglen == 4) {
- memcpy(&ifctx->dhcpserver, p, 4);
- ifctx->gotdhcpserver = 1;
- } else
- ifctx->gotdhcpserver = 0;
- return 1;
- }
-
- ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
- ifctx->replylen,
- TAG_ROOT) != NULL);
- ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
- ifctx->replylen,
- TAG_ROUTERS) != NULL);
- ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
- ifctx->replylen,
- TAG_SUBNETMASK) != NULL);
- return 1;
-}
-
-static int
-bootpc_call(struct bootpc_globalcontext *gctx,
- struct thread *td)
-{
- struct socket *so;
- struct sockaddr_in *sin, dst;
- struct uio auio;
- struct sockopt sopt;
- struct iovec aio;
- int error, on, rcvflg, timo, len;
- time_t atimo;
- time_t rtimo;
- struct timeval tv;
- struct bootpc_ifcontext *ifctx;
- int outstanding;
- int gotrootpath;
- int retry;
- const char *s;
-
- /*
- * Create socket and set its recieve timeout.
- */
- error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td);
- if (error != 0)
- goto out;
-
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- bzero(&sopt, sizeof(sopt));
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_RCVTIMEO;
- sopt.sopt_val = &tv;
- sopt.sopt_valsize = sizeof tv;
-
- error = sosetopt(so, &sopt);
- if (error != 0)
- goto out;
-
- /*
- * Enable broadcast.
- */
- on = 1;
- sopt.sopt_name = SO_BROADCAST;
- sopt.sopt_val = &on;
- sopt.sopt_valsize = sizeof on;
-
- error = sosetopt(so, &sopt);
- if (error != 0)
- goto out;
-
- /*
- * Disable routing.
- */
-
- on = 1;
- sopt.sopt_name = SO_DONTROUTE;
- sopt.sopt_val = &on;
- sopt.sopt_valsize = sizeof on;
-
- error = sosetopt(so, &sopt);
- if (error != 0)
- goto out;
-
- /*
- * Bind the local endpoint to a bootp client port.
- */
- sin = &dst;
- clear_sinaddr(sin);
- sin->sin_port = htons(IPPORT_BOOTPC);
- error = sobind(so, (struct sockaddr *)sin, td);
- if (error != 0) {
- printf("bind failed\n");
- goto out;
- }
-
- /*
- * Setup socket address for the server.
- */
- sin = &dst;
- clear_sinaddr(sin);
- sin->sin_addr.s_addr = INADDR_BROADCAST;
- sin->sin_port = htons(IPPORT_BOOTPS);
-
- /*
- * Send it, repeatedly, until a reply is received,
- * but delay each re-send by an increasing amount.
- * If the delay hits the maximum, start complaining.
- */
- timo = 0;
- rtimo = 0;
- for (;;) {
-
- outstanding = 0;
- gotrootpath = 0;
-
- for (ifctx = gctx->interfaces;
- ifctx != NULL;
- ifctx = ifctx->next) {
- if (bootpc_ifctx_isresolved(ifctx) != 0 &&
- bootpc_tag(&gctx->tmptag, &ifctx->reply,
- ifctx->replylen,
- TAG_ROOT) != NULL)
- gotrootpath = 1;
- }
-
- for (ifctx = gctx->interfaces;
- ifctx != NULL;
- ifctx = ifctx->next) {
- ifctx->outstanding = 0;
- if (bootpc_ifctx_isresolved(ifctx) != 0 &&
- gotrootpath != 0) {
- continue;
- }
- if (bootpc_ifctx_isfailed(ifctx) != 0)
- continue;
-
- outstanding++;
- ifctx->outstanding = 1;
-
- /* Proceed to next step in DHCP negotiation */
- if ((ifctx->state == IF_DHCP_OFFERED &&
- ifctx->dhcpquerytype != DHCP_REQUEST) ||
- (ifctx->state == IF_DHCP_UNRESOLVED &&
- ifctx->dhcpquerytype != DHCP_DISCOVER) ||
- (ifctx->state == IF_BOOTP_UNRESOLVED &&
- ifctx->dhcpquerytype != DHCP_NOMSG)) {
- ifctx->sentmsg = 0;
- bootpc_compose_query(ifctx, gctx, td);
- }
-
- /* Send BOOTP request (or re-send). */
-
- if (ifctx->sentmsg == 0) {
- switch(ifctx->dhcpquerytype) {
- case DHCP_DISCOVER:
- s = "DHCP Discover";
- break;
- case DHCP_REQUEST:
- s = "DHCP Request";
- break;
- case DHCP_NOMSG:
- default:
- s = "BOOTP Query";
- break;
- }
- printf("Sending %s packet from "
- "interface %s (%*D)\n",
- s,
- ifctx->ireq.ifr_name,
- ifctx->sdl->sdl_alen,
- (unsigned char *) LLADDR(ifctx->sdl),
- ":");
- ifctx->sentmsg = 1;
- }
-
- aio.iov_base = (caddr_t) &ifctx->call;
- aio.iov_len = sizeof(ifctx->call);
-
- auio.uio_iov = &aio;
- auio.uio_iovcnt = 1;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_WRITE;
- auio.uio_offset = 0;
- auio.uio_resid = sizeof(ifctx->call);
- auio.uio_td = td;
-
- /* Set netmask to 0.0.0.0 */
-
- sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
- clear_sinaddr(sin);
- error = ifioctl(ifctx->so, SIOCSIFNETMASK,
- (caddr_t) &ifctx->ireq, td);
- if (error != 0)
- panic("bootpc_call:"
- "set if netmask, error=%d",
- error);
-
- error = sosend(so, (struct sockaddr *) &dst,
- &auio, NULL, NULL, 0, td);
- if (error != 0) {
- printf("bootpc_call: sosend: %d state %08x\n",
- error, (int) so->so_state);
- }
-
- /* XXX: Is this needed ? */
- tsleep(&error, PZERO + 8, "bootpw", 10);
-
- /* Set netmask to 255.0.0.0 */
-
- sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
- clear_sinaddr(sin);
- sin->sin_addr.s_addr = htonl(0xff000000u);
- error = ifioctl(ifctx->so, SIOCSIFNETMASK,
- (caddr_t) &ifctx->ireq, td);
- if (error != 0)
- panic("bootpc_call:"
- "set if netmask, error=%d",
- error);
-
- }
-
- if (outstanding == 0 &&
- (rtimo == 0 || time_second >= rtimo)) {
- error = 0;
- goto gotreply;
- }
-
- /* Determine new timeout. */
- if (timo < MAX_RESEND_DELAY)
- timo++;
- else {
- printf("DHCP/BOOTP timeout for server ");
- print_sin_addr(&dst);
- printf("\n");
- }
-
- /*
- * Wait for up to timo seconds for a reply.
- * The socket receive timeout was set to 1 second.
- */
- atimo = timo + time_second;
- while (time_second < atimo) {
- aio.iov_base = (caddr_t) &gctx->reply;
- aio.iov_len = sizeof(gctx->reply);
-
- 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(gctx->reply);
- auio.uio_td = td;
-
- rcvflg = 0;
- error = soreceive(so, NULL, &auio,
- NULL, NULL, &rcvflg);
- gctx->secs = time_second - gctx->starttime;
- for (ifctx = gctx->interfaces;
- ifctx != NULL;
- ifctx = ifctx->next) {
- if (bootpc_ifctx_isresolved(ifctx) != 0 ||
- bootpc_ifctx_isfailed(ifctx) != 0)
- continue;
-
- ifctx->call.secs = htons(gctx->secs);
- }
- if (error == EWOULDBLOCK)
- continue;
- if (error != 0)
- goto out;
- len = sizeof(gctx->reply) - auio.uio_resid;
-
- /* Do we have the required number of bytes ? */
- if (len < BOOTP_MIN_LEN)
- continue;
- gctx->replylen = len;
-
- /* Is it a reply? */
- if (gctx->reply.op != BOOTP_REPLY)
- continue;
-
- /* Is this an answer to our query */
- for (ifctx = gctx->interfaces;
- ifctx != NULL;
- ifctx = ifctx->next) {
- if (gctx->reply.xid != ifctx->call.xid)
- continue;
-
- /* Same HW address size ? */
- if (gctx->reply.hlen != ifctx->call.hlen)
- continue;
-
- /* Correct HW address ? */
- if (bcmp(gctx->reply.chaddr,
- ifctx->call.chaddr,
- ifctx->call.hlen) != 0)
- continue;
-
- break;
- }
-
- if (ifctx != NULL) {
- s = bootpc_tag(&gctx->tmptag,
- &gctx->reply,
- gctx->replylen,
- TAG_DHCP_MSGTYPE);
- if (s != NULL) {
- switch (*s) {
- case DHCP_OFFER:
- s = "DHCP Offer";
- break;
- case DHCP_ACK:
- s = "DHCP Ack";
- break;
- default:
- s = "DHCP (unexpected)";
- break;
- }
- } else
- s = "BOOTP Reply";
-
- printf("Received %s packet"
- " on %s from ",
- s,
- ifctx->ireq.ifr_name);
- print_in_addr(gctx->reply.siaddr);
- if (gctx->reply.giaddr.s_addr !=
- htonl(INADDR_ANY)) {
- printf(" via ");
- print_in_addr(gctx->reply.giaddr);
- }
- if (bootpc_received(gctx, ifctx) != 0) {
- printf(" (accepted)");
- if (ifctx->outstanding) {
- ifctx->outstanding = 0;
- outstanding--;
- }
- /* Network settle delay */
- if (outstanding == 0)
- atimo = time_second +
- BOOTP_SETTLE_DELAY;
- } else
- printf(" (ignored)");
- if (ifctx->gotrootpath) {
- gotrootpath = 1;
- rtimo = time_second +
- BOOTP_SETTLE_DELAY;
- printf(" (got root path)");
- } else
- printf(" (no root path)");
- printf("\n");
- }
- } /* while secs */
-#ifdef BOOTP_TIMEOUT
- if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
- break;
-#endif
- /* Force a retry if halfway in DHCP negotiation */
- retry = 0;
- for (ifctx = gctx->interfaces; ifctx != NULL;
- ifctx = ifctx->next) {
- if (ifctx->state == IF_DHCP_OFFERED) {
- if (ifctx->dhcpquerytype == DHCP_DISCOVER)
- retry = 1;
- else
- ifctx->state = IF_DHCP_UNRESOLVED;
- }
- }
-
- if (retry != 0)
- continue;
-
- if (gotrootpath != 0) {
- gctx->gotrootpath = gotrootpath;
- if (rtimo != 0 && time_second >= rtimo)
- break;
- }
- } /* forever send/receive */
-
- /*
- * XXX: These are errors of varying seriousness being silently
- * ignored
- */
-
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
- if (bootpc_ifctx_isresolved(ifctx) == 0) {
- printf("%s timeout for interface %s\n",
- ifctx->dhcpquerytype != DHCP_NOMSG ?
- "DHCP" : "BOOTP",
- ifctx->ireq.ifr_name);
- }
- }
- if (gctx->gotrootpath != 0) {
-#if 0
- printf("Got a root path, ignoring remaining timeout\n");
-#endif
- error = 0;
- goto out;
- }
-#ifndef BOOTP_NFSROOT
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
- if (bootpc_ifctx_isresolved(ifctx) != 0) {
- error = 0;
- goto out;
- }
- }
-#endif
- error = ETIMEDOUT;
- goto out;
-
-gotreply:
-out:
- soclose(so);
- return error;
-}
-
-
-static int
-bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td)
-{
- struct sockaddr_in *sin;
- int error;
-
- struct ifreq *ireq;
- struct socket *so;
- struct ifaddr *ifa;
- struct sockaddr_dl *sdl;
-
- error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td);
- if (error != 0)
- panic("nfs_boot: socreate, error=%d", error);
-
- ireq = &ifctx->ireq;
- so = ifctx->so;
-
- /*
- * Bring up the interface.
- *
- * Get the old interface flags and or IFF_UP into them; if
- * IFF_UP set blindly, interface selection can be clobbered.
- */
- error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
- if (error != 0)
- panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
- ireq->ifr_flags |= IFF_UP;
- error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
- if (error != 0)
- panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
-
- /*
- * Do enough of ifconfig(8) so that the chosen interface
- * can talk to the servers. (just set the address)
- */
-
- /* addr is 0.0.0.0 */
-
- sin = (struct sockaddr_in *) &ireq->ifr_addr;
- clear_sinaddr(sin);
- error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
- if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
- panic("bootpc_fakeup_interface: "
- "set if addr, error=%d", error);
-
- /* netmask is 255.0.0.0 */
-
- sin = (struct sockaddr_in *) &ireq->ifr_addr;
- clear_sinaddr(sin);
- sin->sin_addr.s_addr = htonl(0xff000000u);
- error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td);
- if (error != 0)
- panic("bootpc_fakeup_interface: set if netmask, error=%d",
- error);
-
- /* Broadcast is 255.255.255.255 */
-
- sin = (struct sockaddr_in *)&ireq->ifr_addr;
- clear_sinaddr(sin);
- clear_sinaddr(&ifctx->broadcast);
- sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
- ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr;
-
- error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td);
- if (error != 0)
- panic("bootpc_fakeup_interface: "
- "set if broadcast addr, error=%d",
- error);
-
- /* Get HW address */
-
- sdl = NULL;
- for (ifa = TAILQ_FIRST(&ifctx->ifp->if_addrhead);
- ifa != NULL;
- ifa = TAILQ_NEXT(ifa,ifa_link))
- if (ifa->ifa_addr->sa_family == AF_LINK &&
- (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL &&
- sdl->sdl_type == IFT_ETHER)
- break;
-
- if (sdl == NULL)
- panic("bootpc: Unable to find HW address for %s",
- ifctx->ireq.ifr_name);
- ifctx->sdl = sdl;
-
- return error;
-}
-
-
-static int
-bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td)
-{
- int error;
- struct sockaddr_in defdst;
- struct sockaddr_in defmask;
- struct sockaddr_in *sin;
-
- struct ifreq *ireq;
- struct socket *so;
- struct sockaddr_in *myaddr;
- struct sockaddr_in *netmask;
- struct sockaddr_in *gw;
-
- ireq = &ifctx->ireq;
- so = ifctx->so;
- myaddr = &ifctx->myaddr;
- netmask = &ifctx->netmask;
- gw = &ifctx->gw;
-
- if (bootpc_ifctx_isresolved(ifctx) == 0) {
-
- /* Shutdown interfaces where BOOTP failed */
-
- printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
- error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
- if (error != 0)
- panic("bootpc_adjust_interface: "
- "SIOCGIFFLAGS, error=%d", error);
- ireq->ifr_flags &= ~IFF_UP;
- error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
- if (error != 0)
- panic("bootpc_adjust_interface: "
- "SIOCSIFFLAGS, error=%d", error);
-
- sin = (struct sockaddr_in *) &ireq->ifr_addr;
- clear_sinaddr(sin);
- error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td);
- if (error != 0 && (error != EEXIST ||
- ifctx == gctx->interfaces))
- panic("bootpc_adjust_interface: "
- "SIOCDIFADDR, error=%d", error);
-
- return 0;
- }
-
- printf("Adjusted interface %s\n", ifctx->ireq.ifr_name);
- /*
- * Do enough of ifconfig(8) so that the chosen interface
- * can talk to the servers. (just set the address)
- */
- bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask));
- error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td);
- if (error != 0)
- panic("bootpc_adjust_interface: "
- "set if netmask, error=%d", error);
-
- /* Broadcast is with host part of IP address all 1's */
-
- sin = (struct sockaddr_in *) &ireq->ifr_addr;
- clear_sinaddr(sin);
- sin->sin_addr.s_addr = myaddr->sin_addr.s_addr |
- ~ netmask->sin_addr.s_addr;
- error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td);
- if (error != 0)
- panic("bootpc_adjust_interface: "
- "set if broadcast addr, error=%d", error);
-
- bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr));
- error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
- if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
- panic("bootpc_adjust_interface: "
- "set if addr, error=%d", error);
-
- /* Add new default route */
-
- if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
- clear_sinaddr(&defdst);
- clear_sinaddr(&defmask);
- error = rtrequest(RTM_ADD,
- (struct sockaddr *) &defdst,
- (struct sockaddr *) gw,
- (struct sockaddr *) &defmask,
- (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
- if (error != 0) {
- printf("bootpc_adjust_interface: "
- "add net route, error=%d\n", error);
- return error;
- }
- }
-
- return 0;
-}
-
-
-static int
-setfs(struct sockaddr_in *addr, char *path, char *p)
-{
- unsigned int ip;
- int val;
-
- ip = 0;
- if (((val = getdec(&p)) < 0) || (val > 255))
- return 0;
- ip = val << 24;
- if (*p != '.')
- return 0;
- p++;
- if (((val = getdec(&p)) < 0) || (val > 255))
- return 0;
- ip |= (val << 16);
- if (*p != '.')
- return 0;
- p++;
- if (((val = getdec(&p)) < 0) || (val > 255))
- return 0;
- ip |= (val << 8);
- if (*p != '.')
- return 0;
- p++;
- if (((val = getdec(&p)) < 0) || (val > 255))
- return 0;
- ip |= val;
- if (*p != ':')
- return 0;
- p++;
-
- addr->sin_addr.s_addr = htonl(ip);
- addr->sin_len = sizeof(struct sockaddr_in);
- addr->sin_family = AF_INET;
-
- strncpy(path, p, MNAMELEN - 1);
- return 1;
-}
-
-
-static int
-getdec(char **ptr)
-{
- char *p;
- int ret;
-
- p = *ptr;
- ret = 0;
- if ((*p < '0') || (*p > '9'))
- return -1;
- while ((*p >= '0') && (*p <= '9')) {
- ret = ret * 10 + (*p - '0');
- p++;
- }
- *ptr = p;
- return ret;
-}
-
-
-static char *
-substr(char *a, char *b)
-{
- char *loc1;
- char *loc2;
-
- while (*a != '\0') {
- loc1 = a;
- loc2 = b;
- while (*loc1 == *loc2++) {
- if (*loc1 == '\0')
- return 0;
- loc1++;
- if (*loc2 == '\0')
- return loc1;
- }
- a++;
- }
- return 0;
-}
-
-
-static void
-mountopts(struct nfs_args *args, char *p)
-{
- char *tmp;
-
- args->version = NFS_ARGSVERSION;
- args->rsize = 8192;
- args->wsize = 8192;
- args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
- args->sotype = SOCK_DGRAM;
- if (p == NULL)
- return;
- if ((tmp = (char *)substr(p, "rsize=")))
- args->rsize = getdec(&tmp);
- if ((tmp = (char *)substr(p, "wsize=")))
- args->wsize = getdec(&tmp);
- if ((tmp = (char *)substr(p, "intr")))
- args->flags |= NFSMNT_INT;
- if ((tmp = (char *)substr(p, "soft")))
- args->flags |= NFSMNT_SOFT;
- if ((tmp = (char *)substr(p, "noconn")))
- args->flags |= NFSMNT_NOCONN;
- if ((tmp = (char *)substr(p, "tcp")))
- args->sotype = SOCK_STREAM;
-}
-
-
-static int
-xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
-{
- struct mbuf *m;
- int alignedlen;
-
- m = *mptr;
- alignedlen = ( len + 3 ) & ~3;
-
- if (m->m_len < alignedlen) {
- m = m_pullup(m, alignedlen);
- if (m == NULL) {
- *mptr = NULL;
- return EBADRPC;
- }
- }
- bcopy(mtod(m, u_char *), buf, len);
- m_adj(m, alignedlen);
- *mptr = m;
- return 0;
-}
-
-
-static int
-xdr_int_decode(struct mbuf **mptr, int *iptr)
-{
- u_int32_t i;
- if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
- return EBADRPC;
- *iptr = fxdr_unsigned(u_int32_t, i);
- return 0;
-}
-
-
-static void
-print_sin_addr(struct sockaddr_in *sin)
-{
- print_in_addr(sin->sin_addr);
-}
-
-
-static void
-print_in_addr(struct in_addr addr)
-{
- unsigned int ip;
-
- ip = ntohl(addr.s_addr);
- printf("%d.%d.%d.%d",
- ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
-}
-
-static void
-bootpc_compose_query(ifctx, gctx, td)
- struct bootpc_ifcontext *ifctx;
- struct bootpc_globalcontext *gctx;
- struct thread *td;
-{
- unsigned char *vendp;
- uint32_t leasetime;
-
- ifctx->gotrootpath = 0;
-
- bzero((caddr_t) &ifctx->call, sizeof(ifctx->call));
-
- /* bootpc part */
- ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */
- ifctx->call.htype = 1; /* 10mb ethernet */
- ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */
- ifctx->call.hops = 0;
- if (bootpc_ifctx_isunresolved(ifctx) != 0)
- ifctx->xid++;
- ifctx->call.xid = txdr_unsigned(ifctx->xid);
- bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen);
-
- vendp = ifctx->call.vend;
- *vendp++ = 99; /* RFC1048 cookie */
- *vendp++ = 130;
- *vendp++ = 83;
- *vendp++ = 99;
- *vendp++ = TAG_MAXMSGSIZE;
- *vendp++ = 2;
- *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255;
- *vendp++ = sizeof(struct bootp_packet) & 255;
- ifctx->dhcpquerytype = DHCP_NOMSG;
- switch (ifctx->state) {
- case IF_DHCP_UNRESOLVED:
- *vendp++ = TAG_DHCP_MSGTYPE;
- *vendp++ = 1;
- *vendp++ = DHCP_DISCOVER;
- ifctx->dhcpquerytype = DHCP_DISCOVER;
- ifctx->gotdhcpserver = 0;
- break;
- case IF_DHCP_OFFERED:
- *vendp++ = TAG_DHCP_MSGTYPE;
- *vendp++ = 1;
- *vendp++ = DHCP_REQUEST;
- ifctx->dhcpquerytype = DHCP_REQUEST;
- *vendp++ = TAG_DHCP_REQ_ADDR;
- *vendp++ = 4;
- memcpy(vendp, &ifctx->reply.yiaddr, 4);
- vendp += 4;
- if (ifctx->gotdhcpserver != 0) {
- *vendp++ = TAG_DHCP_SERVERID;
- *vendp++ = 4;
- memcpy(vendp, &ifctx->dhcpserver, 4);
- vendp += 4;
- }
- *vendp++ = TAG_DHCP_LEASETIME;
- *vendp++ = 4;
- leasetime = htonl(300);
- memcpy(vendp, &leasetime, 4);
- vendp += 4;
- default:
- ;
- }
- *vendp = TAG_END;
-
- ifctx->call.secs = 0;
- ifctx->call.flags = htons(0x8000); /* We need an broadcast answer */
-}
-
-
-static int
-bootpc_hascookie(struct bootp_packet *bp)
-{
- return (bp->vend[0] == 99 && bp->vend[1] == 130 &&
- bp->vend[2] == 83 && bp->vend[3] == 99);
-}
-
-
-static void
-bootpc_tag_helper(struct bootpc_tagcontext *tctx,
- unsigned char *start,
- int len,
- int tag)
-{
- unsigned char *j;
- unsigned char *ej;
- unsigned char code;
-
- if (tctx->badtag != 0 || tctx->badopt != 0)
- return;
-
- j = start;
- ej = j + len;
-
- while (j < ej) {
- code = *j++;
- if (code == TAG_PAD)
- continue;
- if (code == TAG_END)
- return;
- if (j >= ej || j + *j + 1 > ej) {
- tctx->badopt = 1;
- return;
- }
- len = *j++;
- if (code == tag) {
- if (tctx->taglen + len > TAG_MAXLEN) {
- tctx->badtag = 1;
- return;
- }
- tctx->foundopt = 1;
- if (len > 0)
- memcpy(tctx->buf + tctx->taglen,
- j, len);
- tctx->taglen += len;
- }
- if (code == TAG_OVERLOAD)
- tctx->overload = *j;
-
- j += len;
- }
-}
-
-
-static unsigned char *
-bootpc_tag(struct bootpc_tagcontext *tctx,
- struct bootp_packet *bp,
- int len,
- int tag)
-{
- unsigned char *j;
- unsigned char *ej;
-
- tctx->overload = 0;
- tctx->badopt = 0;
- tctx->badtag = 0;
- tctx->foundopt = 0;
- tctx->taglen = 0;
-
- if (bootpc_hascookie(bp) == 0)
- return NULL;
-
- j = &bp->vend[4];
- ej = (unsigned char *) bp + len;
-
- bootpc_tag_helper(tctx, &bp->vend[4],
- (unsigned char *) bp + len - &bp->vend[4], tag);
-
- if ((tctx->overload & OVERLOAD_FILE) != 0)
- bootpc_tag_helper(tctx,
- (unsigned char *) bp->file,
- sizeof(bp->file),
- tag);
- if ((tctx->overload & OVERLOAD_SNAME) != 0)
- bootpc_tag_helper(tctx,
- (unsigned char *) bp->sname,
- sizeof(bp->sname),
- tag);
-
- if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0)
- return NULL;
- tctx->buf[tctx->taglen] = '\0';
- return tctx->buf;
-}
-
-
-static void
-bootpc_decode_reply(nd, ifctx, gctx)
- struct nfsv3_diskless *nd;
- struct bootpc_ifcontext *ifctx;
- struct bootpc_globalcontext *gctx;
-{
- char *p;
- unsigned int ip;
-
- ifctx->gotgw = 0;
- ifctx->gotnetmask = 0;
-
- clear_sinaddr(&ifctx->myaddr);
- clear_sinaddr(&ifctx->netmask);
- clear_sinaddr(&ifctx->gw);
-
- ifctx->myaddr.sin_addr = ifctx->reply.yiaddr;
-
- ip = ntohl(ifctx->myaddr.sin_addr.s_addr);
- snprintf(gctx->lookup_path, sizeof(gctx->lookup_path),
- "swap.%d.%d.%d.%d",
- ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
-
- printf("%s at ", ifctx->ireq.ifr_name);
- print_sin_addr(&ifctx->myaddr);
- printf(" server ");
- print_in_addr(ifctx->reply.siaddr);
-
- ifctx->gw.sin_addr = ifctx->reply.giaddr;
- if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) {
- printf(" via gateway ");
- print_in_addr(ifctx->reply.giaddr);
- }
-
- /* This call used for the side effect (overload flag) */
- (void) bootpc_tag(&gctx->tmptag,
- &ifctx->reply, ifctx->replylen, TAG_END);
-
- if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0)
- if (ifctx->reply.sname[0] != '\0')
- printf(" server name %s", ifctx->reply.sname);
- if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0)
- if (ifctx->reply.file[0] != '\0')
- printf(" boot file %s", ifctx->reply.file);
-
- printf("\n");
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
- TAG_SUBNETMASK);
- if (p != NULL) {
- if (gctx->tag.taglen != 4)
- panic("bootpc: subnet mask len is %d",
- gctx->tag.taglen);
- bcopy(p, &ifctx->netmask.sin_addr, 4);
- ifctx->gotnetmask = 1;
- printf("subnet mask ");
- print_sin_addr(&ifctx->netmask);
- printf(" ");
- }
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
- TAG_ROUTERS);
- if (p != NULL) {
- /* Routers */
- if (gctx->tag.taglen % 4)
- panic("bootpc: Router Len is %d", gctx->tag.taglen);
- if (gctx->tag.taglen > 0) {
- bcopy(p, &ifctx->gw.sin_addr, 4);
- printf("router ");
- print_sin_addr(&ifctx->gw);
- printf(" ");
- ifctx->gotgw = 1;
- gctx->gotgw = 1;
- }
- }
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
- TAG_ROOT);
- if (p != NULL) {
- if (gctx->setrootfs != NULL) {
- printf("rootfs %s (ignored) ", p);
- } else if (setfs(&nd->root_saddr,
- nd->root_hostnam, p)) {
- printf("rootfs %s ",p);
- gctx->gotrootpath = 1;
- ifctx->gotrootpath = 1;
- gctx->setrootfs = ifctx;
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply,
- ifctx->replylen,
- TAG_ROOTOPTS);
- if (p != NULL) {
- mountopts(&nd->root_args, p);
- printf("rootopts %s ", p);
- }
- } else
- panic("Failed to set rootfs to %s",p);
- }
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
- TAG_SWAP);
- if (p != NULL) {
- if (gctx->setswapfs != NULL) {
- printf("swapfs %s (ignored) ", p);
- } else if (setfs(&nd->swap_saddr,
- nd->swap_hostnam, p)) {
- gctx->gotswappath = 1;
- gctx->setswapfs = ifctx;
- printf("swapfs %s ", p);
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply,
- ifctx->replylen,
- TAG_SWAPOPTS);
- if (p != NULL) {
- /* swap mount options */
- mountopts(&nd->swap_args, p);
- printf("swapopts %s ", p);
- }
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply,
- ifctx->replylen,
- TAG_SWAPSIZE);
- if (p != NULL) {
- int swaplen;
- if (gctx->tag.taglen != 4)
- panic("bootpc: "
- "Expected 4 bytes for swaplen, "
- "not %d bytes",
- gctx->tag.taglen);
- bcopy(p, &swaplen, 4);
- nd->swap_nblks = ntohl(swaplen);
- printf("swapsize %d KB ",
- nd->swap_nblks);
- }
- } else
- panic("Failed to set swapfs to %s", p);
- }
-
- p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
- TAG_HOSTNAME);
- if (p != NULL) {
- if (gctx->tag.taglen >= MAXHOSTNAMELEN)
- panic("bootpc: hostname >= %d bytes",
- MAXHOSTNAMELEN);
- if (gctx->sethostname != NULL) {
- printf("hostname %s (ignored) ", p);
- } else {
- strcpy(nd->my_hostnam, p);
- strcpy(hostname, p);
- printf("hostname %s ",hostname);
- gctx->sethostname = ifctx;
- }
- }
-
- printf("\n");
-
- if (ifctx->gotnetmask == 0) {
- if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr)))
- ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
- else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr)))
- ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
- else
- ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
- }
- if (ifctx->gotgw == 0) {
- /* Use proxyarp */
- ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr;
- }
-}
-
-void
-bootpc_init(void)
-{
- struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */
- struct bootpc_globalcontext *gctx; /* Global BOOTP context */
- struct ifnet *ifp;
- int error;
- struct nfsv3_diskless *nd;
- struct thread *td;
-
- nd = &nfsv3_diskless;
- td = curthread;
-
- /*
- * If already filled in, don't touch it here
- */
- if (nfs_diskless_valid != 0)
- return;
-
- /*
- * Wait until arp entries can be handled.
- */
- while (time_second == 0)
- tsleep(&time_second, PZERO + 8, "arpkludge", 10);
-
- gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK);
- if (gctx == NULL)
- panic("Failed to allocate bootp global context structure");
-
- bzero(gctx, sizeof(*gctx));
- gctx->xid = ~0xFFFF;
- gctx->starttime = time_second;
-
- ifctx = allocifctx(gctx);
-
- /*
- * Find a network interface.
- */
-#ifdef BOOTP_WIRED_TO
- printf("bootpc_init: wired to interface '%s'\n",
- __XSTRING(BOOTP_WIRED_TO));
-#endif
- bzero(&ifctx->ireq, sizeof(ifctx->ireq));
- for (ifp = TAILQ_FIRST(&ifnet);
- ifp != NULL;
- ifp = TAILQ_NEXT(ifp, if_link)) {
- snprintf(ifctx->ireq.ifr_name, sizeof(ifctx->ireq.ifr_name),
- "%s%d", ifp->if_name, ifp->if_unit);
-#ifdef BOOTP_WIRED_TO
- if (strcmp(ifctx->ireq.ifr_name,
- __XSTRING(BOOTP_WIRED_TO)) != 0)
- continue;
-#else
- if ((ifp->if_flags &
- (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
- IFF_BROADCAST)
- continue;
-#endif
- if (gctx->interfaces != NULL)
- gctx->lastinterface->next = ifctx;
- else
- gctx->interfaces = ifctx;
- ifctx->ifp = ifp;
- gctx->lastinterface = ifctx;
- ifctx = allocifctx(gctx);
- }
- free(ifctx, M_TEMP);
-
- if (gctx->interfaces == NULL) {
-#ifdef BOOTP_WIRED_TO
- panic("bootpc_init: Could not find interface specified "
- "by BOOTP_WIRED_TO: "
- __XSTRING(BOOTP_WIRED_TO));
-#else
- panic("bootpc_init: no suitable interface");
-#endif
- }
-
- gctx->gotrootpath = 0;
- gctx->gotswappath = 0;
- gctx->gotgw = 0;
-
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
- bootpc_fakeup_interface(ifctx, gctx, td);
-
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
- bootpc_compose_query(ifctx, gctx, td);
-
- ifctx = gctx->interfaces;
- error = bootpc_call(gctx, td);
-
- if (error != 0) {
-#ifdef BOOTP_NFSROOT
- panic("BOOTP call failed");
-#else
- printf("BOOTP call failed\n");
-#endif
- }
-
- mountopts(&nd->root_args, NULL);
-
- mountopts(&nd->swap_args, NULL);
-
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
- if (bootpc_ifctx_isresolved(ifctx) != 0)
- bootpc_decode_reply(nd, ifctx, gctx);
-
- if (gctx->gotswappath == 0)
- nd->swap_nblks = 0;
-#ifdef BOOTP_NFSROOT
- if (gctx->gotrootpath == 0)
- panic("bootpc: No root path offered");
-#endif
-
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
- bootpc_adjust_interface(ifctx, gctx, td);
-
- soclose(ifctx->so);
- }
-
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
- if (ifctx->gotrootpath != 0)
- break;
- if (ifctx == NULL) {
- for (ifctx = gctx->interfaces;
- ifctx != NULL;
- ifctx = ifctx->next)
- if (bootpc_ifctx_isresolved(ifctx) != 0)
- break;
- }
- if (ifctx == NULL)
- goto out;
-
- if (gctx->gotrootpath != 0) {
-
- error = md_mount(&nd->root_saddr, nd->root_hostnam,
- nd->root_fh, &nd->root_fhsize,
- &nd->root_args, td);
- if (error != 0)
- panic("nfs_boot: mountd root, error=%d", error);
-
- if (gctx->gotswappath != 0) {
-
- error = md_mount(&nd->swap_saddr,
- nd->swap_hostnam,
- nd->swap_fh, &nd->swap_fhsize,
- &nd->swap_args, td);
- if (error != 0)
- panic("nfs_boot: mountd swap, error=%d",
- error);
-
- error = md_lookup_swap(&nd->swap_saddr,
- gctx->lookup_path,
- nd->swap_fh, &nd->swap_fhsize,
- &nd->swap_args, td);
- if (error != 0)
- panic("nfs_boot: lookup swap, error=%d",
- error);
- }
- nfs_diskless_valid = 3;
- }
-
- strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name);
- bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr));
- bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr));
- ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
- ifctx->myaddr.sin_addr.s_addr |
- ~ ifctx->netmask.sin_addr.s_addr;
- bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
-
-out:
- for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) {
- nctx = ifctx->next;
- free(ifctx, M_TEMP);
- }
- free(gctx, M_TEMP);
-}
-
-
-/*
- * RPC: mountd/mount
- * Given a server pathname, get an NFS file handle.
- * Also, sets sin->sin_port to the NFS service port.
- */
-static int
-md_mount(struct sockaddr_in *mdsin, /* mountd server address */
- char *path,
- u_char *fhp,
- int *fhsizep,
- struct nfs_args *args,
- struct thread *td)
-{
- struct mbuf *m;
- int error;
- int authunixok;
- int authcount;
- int authver;
-
-#ifdef BOOTP_NFSV3
- /* First try NFS v3 */
- /* Get port number for MOUNTD. */
- error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
- &mdsin->sin_port, td);
- if (error == 0) {
- m = xdr_string_encode(path, strlen(path));
-
- /* Do RPC to mountd. */
- error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
- RPCMNT_MOUNT, &m, NULL, td);
- }
- if (error == 0) {
- args->flags |= NFSMNT_NFSV3;
- } else {
-#endif
- /* Fallback to NFS v2 */
-
- /* Get port number for MOUNTD. */
- error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
- &mdsin->sin_port, td);
- if (error != 0)
- return error;
-
- m = xdr_string_encode(path, strlen(path));
-
- /* Do RPC to mountd. */
- error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
- RPCMNT_MOUNT, &m, NULL, td);
- if (error != 0)
- return error; /* message already freed */
-
-#ifdef BOOTP_NFSV3
- }
-#endif
-
- if (xdr_int_decode(&m, &error) != 0 || error != 0)
- goto bad;
-
- if ((args->flags & NFSMNT_NFSV3) != 0) {
- if (xdr_int_decode(&m, fhsizep) != 0 ||
- *fhsizep > NFSX_V3FHMAX ||
- *fhsizep <= 0)
- goto bad;
- } else
- *fhsizep = NFSX_V2FH;
-
- if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
- goto bad;
-
- if (args->flags & NFSMNT_NFSV3) {
- if (xdr_int_decode(&m, &authcount) != 0)
- goto bad;
- authunixok = 0;
- if (authcount < 0 || authcount > 100)
- goto bad;
- while (authcount > 0) {
- if (xdr_int_decode(&m, &authver) != 0)
- goto bad;
- if (authver == RPCAUTH_UNIX)
- authunixok = 1;
- authcount--;
- }
- if (authunixok == 0)
- goto bad;
- }
-
- /* Set port number for NFS use. */
- error = krpc_portmap(mdsin, NFS_PROG,
- (args->flags &
- NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
- &mdsin->sin_port, td);
-
- goto out;
-
-bad:
- error = EBADRPC;
-
-out:
- m_freem(m);
- return error;
-}
-
-
-static int
-md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
- char *path,
- u_char *fhp,
- int *fhsizep,
- struct nfs_args *args,
- struct thread *td)
-{
- struct mbuf *m;
- int error;
- int size = -1;
- int attribs_present;
- int status;
- union {
- u_int32_t v2[17];
- u_int32_t v3[21];
- } fattribs;
-
- m = m_get(M_TRYWAIT,MT_DATA);
- if (m == NULL)
- return ENOBUFS;
-
- if ((args->flags & NFSMNT_NFSV3) != 0) {
- *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep);
- bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep);
- m->m_len = *fhsizep + sizeof(u_int32_t);
- } else {
- bcopy(fhp, mtod(m, u_char *), NFSX_V2FH);
- m->m_len = NFSX_V2FH;
- }
-
- m->m_next = xdr_string_encode(path, strlen(path));
- if (m->m_next == NULL) {
- error = ENOBUFS;
- goto out;
- }
-
- /* Do RPC to nfsd. */
- if ((args->flags & NFSMNT_NFSV3) != 0)
- error = krpc_call(mdsin, NFS_PROG, NFS_VER3,
- NFSPROC_LOOKUP, &m, NULL, td);
- else
- error = krpc_call(mdsin, NFS_PROG, NFS_VER2,
- NFSV2PROC_LOOKUP, &m, NULL, td);
- if (error != 0)
- return error; /* message already freed */
-
- if (xdr_int_decode(&m, &status) != 0)
- goto bad;
- if (status != 0) {
- error = ENOENT;
- goto out;
- }
-
- if ((args->flags & NFSMNT_NFSV3) != 0) {
- if (xdr_int_decode(&m, fhsizep) != 0 ||
- *fhsizep > NFSX_V3FHMAX ||
- *fhsizep <= 0)
- goto bad;
- } else
- *fhsizep = NFSX_V2FH;
-
- if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
- goto bad;
-
- if ((args->flags & NFSMNT_NFSV3) != 0) {
- if (xdr_int_decode(&m, &attribs_present) != 0)
- goto bad;
- if (attribs_present != 0) {
- if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3,
- sizeof(u_int32_t) * 21) != 0)
- goto bad;
- size = fxdr_unsigned(u_int32_t, fattribs.v3[6]);
- }
- } else {
- if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2,
- sizeof(u_int32_t) * 17) != 0)
- goto bad;
- size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
- }
-
- if (nfsv3_diskless.swap_nblks == 0 && size != -1) {
- nfsv3_diskless.swap_nblks = size / 1024;
- printf("md_lookup_swap: Swap size is %d KB\n",
- nfsv3_diskless.swap_nblks);
- }
-
- goto out;
-
-bad:
- error = EBADRPC;
-
-out:
- m_freem(m);
- return error;
-}
diff --git a/sys/nfs/krpc.h b/sys/nfs/krpc.h
deleted file mode 100644
index b6136e3..0000000
--- a/sys/nfs/krpc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */
-/* $FreeBSD$ */
-
-#include <sys/cdefs.h>
-
-struct mbuf;
-struct thread;
-struct sockaddr;
-struct sockaddr_in;
-
-int krpc_call __P((struct sockaddr_in *_sin,
- u_int prog, u_int vers, u_int func,
- struct mbuf **data, struct sockaddr **from, struct thread *td));
-
-int krpc_portmap __P((struct sockaddr_in *_sin,
- u_int prog, u_int vers, u_int16_t *portp,struct thread *td));
-
-struct mbuf *xdr_string_encode __P((char *str, int len));
-
-/*
- * RPC definitions for the portmapper
- */
-#define PMAPPORT 111
-#define PMAPPROG 100000
-#define PMAPVERS 2
-#define PMAPPROC_NULL 0
-#define PMAPPROC_SET 1
-#define PMAPPROC_UNSET 2
-#define PMAPPROC_GETPORT 3
-#define PMAPPROC_DUMP 4
-#define PMAPPROC_CALLIT 5
diff --git a/sys/nfs/krpc_subr.c b/sys/nfs/krpc_subr.c
deleted file mode 100644
index 709af4a..0000000
--- a/sys/nfs/krpc_subr.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */
-/* $FreeBSD$ */
-
-/*
- * Copyright (c) 1995 Gordon Ross, Adam Glass
- * Copyright (c) 1992 Regents of the University of California.
- * All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * 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, Lawrence Berkeley Laboratory 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.
- *
- * partially based on:
- * libnetboot/rpc.c
- * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL)
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/uio.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/krpc.h>
-#include <nfs/xdr_subs.h>
-
-/*
- * Kernel support for Sun RPC
- *
- * Used currently for bootstrapping in nfs diskless configurations.
- */
-
-/*
- * Generic RPC headers
- */
-
-struct auth_info {
- u_int32_t authtype; /* auth type */
- u_int32_t authlen; /* auth length */
-};
-
-struct auth_unix {
- int32_t ua_time;
- int32_t ua_hostname; /* null */
- int32_t ua_uid;
- int32_t ua_gid;
- int32_t ua_gidlist; /* null */
-};
-
-struct rpc_call {
- u_int32_t rp_xid; /* request transaction id */
- int32_t rp_direction; /* call direction (0) */
- u_int32_t rp_rpcvers; /* rpc version (2) */
- u_int32_t rp_prog; /* program */
- u_int32_t rp_vers; /* version */
- u_int32_t rp_proc; /* procedure */
- struct auth_info rpc_auth;
- struct auth_unix rpc_unix;
- struct auth_info rpc_verf;
-};
-
-struct rpc_reply {
- u_int32_t rp_xid; /* request transaction id */
- int32_t rp_direction; /* call direction (1) */
- int32_t rp_astatus; /* accept status (0: accepted) */
- union {
- u_int32_t rpu_errno;
- struct {
- struct auth_info rok_auth;
- u_int32_t rok_status;
- } rpu_rok;
- } rp_u;
-};
-#define rp_errno rp_u.rpu_errno
-#define rp_auth rp_u.rpu_rok.rok_auth
-#define rp_status rp_u.rpu_rok.rok_status
-
-#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */
-
-/*
- * What is the longest we will wait before re-sending a request?
- * Note this is also the frequency of "RPC timeout" messages.
- * The re-send loop count sup linearly to this maximum, so the
- * first complaint will happen after (1+2+3+4+5)=15 seconds.
- */
-#define MAX_RESEND_DELAY 5 /* seconds */
-
-/*
- * Call portmap to lookup a port number for a particular rpc program
- * Returns non-zero error on failure.
- */
-int
-krpc_portmap(sin, prog, vers, portp, td)
- struct sockaddr_in *sin; /* server address */
- u_int prog, vers; /* host order */
- u_int16_t *portp; /* network order */
- struct thread *td;
-{
- struct sdata {
- u_int32_t prog; /* call program */
- u_int32_t vers; /* call version */
- u_int32_t proto; /* call protocol */
- u_int32_t port; /* call port (unused) */
- } *sdata;
- struct rdata {
- u_int16_t pad;
- u_int16_t port;
- } *rdata;
- struct mbuf *m;
- int error;
-
- /* The portmapper port is fixed. */
- if (prog == PMAPPROG) {
- *portp = htons(PMAPPORT);
- return 0;
- }
-
- m = m_get(M_TRYWAIT, MT_DATA);
- if (m == NULL)
- return ENOBUFS;
- sdata = mtod(m, struct sdata *);
- m->m_len = sizeof(*sdata);
-
- /* Do the RPC to get it. */
- sdata->prog = txdr_unsigned(prog);
- sdata->vers = txdr_unsigned(vers);
- sdata->proto = txdr_unsigned(IPPROTO_UDP);
- sdata->port = 0;
-
- sin->sin_port = htons(PMAPPORT);
- error = krpc_call(sin, PMAPPROG, PMAPVERS,
- PMAPPROC_GETPORT, &m, NULL, td);
- if (error)
- return error;
-
- if (m->m_len < sizeof(*rdata)) {
- m = m_pullup(m, sizeof(*rdata));
- if (m == NULL)
- return ENOBUFS;
- }
- rdata = mtod(m, struct rdata *);
- *portp = rdata->port;
-
- m_freem(m);
- return 0;
-}
-
-/*
- * Do a remote procedure call (RPC) and wait for its reply.
- * If from_p is non-null, then we are doing broadcast, and
- * the address from whence the response came is saved there.
- */
-int
-krpc_call(sa, prog, vers, func, data, from_p, td)
- struct sockaddr_in *sa;
- u_int prog, vers, func;
- struct mbuf **data; /* input/output */
- struct sockaddr **from_p; /* output */
- struct thread *td;
-{
- struct socket *so;
- struct sockaddr_in *sin, ssin;
- struct sockaddr *from;
- struct mbuf *m, *nam, *mhead;
- struct rpc_call *call;
- struct rpc_reply *reply;
- struct sockopt sopt;
- struct timeval tv;
- struct uio auio;
- int error, rcvflg, timo, secs, len;
- static u_int32_t xid = ~0xFF;
- u_int16_t tport;
- u_int32_t saddr;
-
- /*
- * Validate address family.
- * Sorry, this is INET specific...
- */
- if (sa->sin_family != AF_INET)
- return (EAFNOSUPPORT);
-
- /* Free at end if not null. */
- nam = mhead = NULL;
- from = NULL;
-
- /*
- * Create socket and set its recieve timeout.
- */
- if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td)))
- goto out;
-
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_RCVTIMEO;
- sopt.sopt_val = &tv;
- sopt.sopt_valsize = sizeof tv;
-
- if ((error = sosetopt(so, &sopt)) != 0)
- goto out;
-
- /*
- * Enable broadcast if necessary.
- */
- if (from_p) {
- int on = 1;
- sopt.sopt_name = SO_BROADCAST;
- sopt.sopt_val = &on;
- sopt.sopt_valsize = sizeof on;
- if ((error = sosetopt(so, &sopt)) != 0)
- goto out;
- }
-
- /*
- * Bind the local endpoint to a reserved port,
- * because some NFS servers refuse requests from
- * non-reserved (non-privileged) ports.
- */
- sin = &ssin;
- bzero(sin, sizeof *sin);
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = INADDR_ANY;
- tport = IPPORT_RESERVED;
- do {
- tport--;
- sin->sin_port = htons(tport);
- error = sobind(so, (struct sockaddr *)sin, td);
- } while (error == EADDRINUSE &&
- tport > IPPORT_RESERVED / 2);
- if (error) {
- printf("bind failed\n");
- goto out;
- }
-
- /*
- * Setup socket address for the server.
- */
-
- /*
- * Prepend RPC message header.
- */
- mhead = m_gethdr(M_TRYWAIT, MT_DATA);
- mhead->m_next = *data;
- call = mtod(mhead, struct rpc_call *);
- mhead->m_len = sizeof(*call);
- bzero((caddr_t)call, sizeof(*call));
- /* rpc_call part */
- xid++;
- call->rp_xid = txdr_unsigned(xid);
- /* call->rp_direction = 0; */
- call->rp_rpcvers = txdr_unsigned(2);
- call->rp_prog = txdr_unsigned(prog);
- call->rp_vers = txdr_unsigned(vers);
- call->rp_proc = txdr_unsigned(func);
- /* rpc_auth part (auth_unix as root) */
- call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX);
- call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix));
- /* rpc_verf part (auth_null) */
- call->rpc_verf.authtype = 0;
- call->rpc_verf.authlen = 0;
-
- /*
- * Setup packet header
- */
- len = 0;
- m = mhead;
- while (m) {
- len += m->m_len;
- m = m->m_next;
- }
- mhead->m_pkthdr.len = len;
- mhead->m_pkthdr.rcvif = NULL;
-
- /*
- * Send it, repeatedly, until a reply is received,
- * but delay each re-send by an increasing amount.
- * If the delay hits the maximum, start complaining.
- */
- timo = 0;
- for (;;) {
- /* Send RPC request (or re-send). */
- m = m_copym(mhead, 0, M_COPYALL, M_TRYWAIT);
- if (m == NULL) {
- error = ENOBUFS;
- goto out;
- }
- error = sosend(so, (struct sockaddr *)sa, NULL, m,
- NULL, 0, td);
- if (error) {
- printf("krpc_call: sosend: %d\n", error);
- goto out;
- }
- m = NULL;
-
- /* Determine new timeout. */
- if (timo < MAX_RESEND_DELAY)
- timo++;
- else {
- saddr = ntohl(sa->sin_addr.s_addr);
- printf("RPC timeout for server %d.%d.%d.%d\n",
- (saddr >> 24) & 255,
- (saddr >> 16) & 255,
- (saddr >> 8) & 255,
- saddr & 255);
- }
-
- /*
- * Wait for up to timo seconds for a reply.
- * The socket receive timeout was set to 1 second.
- */
- secs = timo;
- while (secs > 0) {
- if (from) {
- FREE(from, M_SONAME);
- from = NULL;
- }
- if (m) {
- m_freem(m);
- m = NULL;
- }
- bzero(&auio,sizeof(auio));
- auio.uio_resid = len = 1<<16;
- rcvflg = 0;
- error = soreceive(so, &from, &auio, &m, NULL, &rcvflg);
- if (error == EWOULDBLOCK) {
- secs--;
- continue;
- }
- if (error)
- goto out;
- len -= auio.uio_resid;
-
- /* Does the reply contain at least a header? */
- if (len < MIN_REPLY_HDR)
- continue;
- if (m->m_len < MIN_REPLY_HDR)
- continue;
- reply = mtod(m, struct rpc_reply *);
-
- /* Is it the right reply? */
- if (reply->rp_direction != txdr_unsigned(RPC_REPLY))
- continue;
-
- if (reply->rp_xid != txdr_unsigned(xid))
- continue;
-
- /* Was RPC accepted? (authorization OK) */
- if (reply->rp_astatus != 0) {
- error = fxdr_unsigned(u_int32_t, reply->rp_errno);
- printf("rpc denied, error=%d\n", error);
- continue;
- }
-
- /* Did the call succeed? */
- if (reply->rp_status != 0) {
- error = fxdr_unsigned(u_int32_t, reply->rp_status);
- if (error == RPC_PROGMISMATCH) {
- error = EBADRPC;
- goto out;
- }
- printf("rpc denied, status=%d\n", error);
- continue;
- }
-
- goto gotreply; /* break two levels */
-
- } /* while secs */
- } /* forever send/receive */
-
- error = ETIMEDOUT;
- goto out;
-
- gotreply:
-
- /*
- * Get RPC reply header into first mbuf,
- * get its length, then strip it off.
- */
- len = sizeof(*reply);
- if (m->m_len < len) {
- m = m_pullup(m, len);
- if (m == NULL) {
- error = ENOBUFS;
- goto out;
- }
- }
- reply = mtod(m, struct rpc_reply *);
- if (reply->rp_auth.authtype != 0) {
- len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen);
- len = (len + 3) & ~3; /* XXX? */
- }
- m_adj(m, len);
-
- /* result */
- *data = m;
- if (from_p) {
- *from_p = from;
- from = NULL;
- }
-
- out:
- if (mhead) m_freem(mhead);
- if (from) free(from, M_SONAME);
- soclose(so);
- return error;
-}
-
-/*
- * eXternal Data Representation routines.
- * (but with non-standard args...)
- */
-
-/*
- * String representation for RPC.
- */
-struct xdr_string {
- u_int32_t len; /* length without null or padding */
- char data[4]; /* data (longer, of course) */
- /* data is padded to a long-word boundary */
-};
-
-struct mbuf *
-xdr_string_encode(str, len)
- char *str;
- int len;
-{
- struct mbuf *m;
- struct xdr_string *xs;
- int dlen; /* padded string length */
- int mlen; /* message length */
-
- dlen = (len + 3) & ~3;
- mlen = dlen + 4;
-
- if (mlen > MCLBYTES) /* If too big, we just can't do it. */
- return (NULL);
-
- m = m_get(M_TRYWAIT, MT_DATA);
- if (mlen > MLEN) {
- MCLGET(m, M_TRYWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- (void) m_free(m); /* There can be only one. */
- return (NULL);
- }
- }
- xs = mtod(m, struct xdr_string *);
- m->m_len = mlen;
- xs->len = txdr_unsigned(len);
- bcopy(str, xs->data, len);
- return (m);
-}
diff --git a/sys/nfs/nfs.h b/sys/nfs/nfs.h
deleted file mode 100644
index da808f4..0000000
--- a/sys/nfs/nfs.h
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * 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.
- * 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.h 8.4 (Berkeley) 5/1/95
- * $FreeBSD$
- */
-
-#ifndef _NFS_NFS_H_
-#define _NFS_NFS_H_
-
-#ifdef _KERNEL
-#include "opt_nfs.h"
-#endif
-
-/*
- * Tunable constants for nfs
- */
-
-#define NFS_MAXIOVEC 34
-#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
-#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
-#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
-#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
-#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
-#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
-#define NFS_MAXREXMIT 100 /* Stop counting after this many */
-#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
-#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
-#define NFS_MAXGRPS 16 /* Max. size of groups list */
-#ifndef NFS_MINATTRTIMO
-#define NFS_MINATTRTIMO 3 /* VREG attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXATTRTIMO
-#define NFS_MAXATTRTIMO 60
-#endif
-#ifndef NFS_MINDIRATTRTIMO
-#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXDIRATTRTIMO
-#define NFS_MAXDIRATTRTIMO 60
-#endif
-#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
-#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
-#define NFS_READDIRSIZE 8192 /* Def. readdir size */
-#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
-#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
-#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
-#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
-#ifndef NFS_GATHERDELAY
-#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
-#endif
-#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
-#ifdef _KERNEL
-#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
-#endif
-
-/*
- * Oddballs
- */
-#define NMOD(a) ((a) % nfs_asyncdaemons)
-#define NFS_CMPFH(n, f, s) \
- ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
-#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
-#define NFS_SRVMAXDATA(n) \
- (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
- NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
-
-/*
- * XXX
- * The B_INVAFTERWRITE flag should be set to whatever is required by the
- * buffer cache code to say "Invalidate the block after it is written back".
- */
-#define B_INVAFTERWRITE B_NOCACHE
-
-/*
- * The IO_METASYNC flag should be implemented for local file systems.
- * (Until then, it is nothin at all.)
- */
-#ifndef IO_METASYNC
-#define IO_METASYNC 0
-#endif
-
-/*
- * Arguments to mount NFS
- */
-#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
-struct nfs_args {
- int version; /* args structure version number */
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
- int acregmin; /* cache attrs for reg files min time */
- int acregmax; /* cache attrs for reg files max time */
- int acdirmin; /* cache attrs for dirs min time */
- int acdirmax; /* cache attrs for dirs max time */
-};
-
-/*
- * NFS mount option flags
- */
-#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
-#define NFSMNT_WSIZE 0x00000002 /* set write size */
-#define NFSMNT_RSIZE 0x00000004 /* set read size */
-#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
-#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
-#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
-#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
-#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
-#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
-#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
-#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
-#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
-#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
-#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
-#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
-#define NFSMNT_ACREGMIN 0x00040000
-#define NFSMNT_ACREGMAX 0x00080000
-#define NFSMNT_ACDIRMIN 0x00100000
-#define NFSMNT_ACDIRMAX 0x00200000
-
-#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
-#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSSTA_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSSTA_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSSTA_DISMNT 0x00800000 /* Dismounted */
-#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
-#define NFSSTA_WANTSND 0x02000000 /* Want above */
-#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
-#define NFSSTA_WANTRCV 0x08000000 /* Want above */
-#define NFSSTA_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSSTA_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSSTA_AUTHERR 0x80000000 /* Authentication error */
-
-/*
- * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
- * should ever try and use it.
- */
-struct nfsd_args {
- int sock; /* Socket to serve */
- caddr_t name; /* Client addr for connection based sockets */
- int namelen; /* Length of name */
-};
-
-struct nfsd_srvargs {
- struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
- uid_t nsd_uid; /* Effective uid mapped to cred */
- u_int32_t nsd_haddr; /* Ip address of client */
- struct xucred nsd_cr; /* Cred. uid maps to */
- u_int nsd_authlen; /* Length of auth string (ret) */
- u_char *nsd_authstr; /* Auth string (ret) */
- u_int nsd_verflen; /* and the verfier */
- u_char *nsd_verfstr;
- struct timeval nsd_timestamp; /* timestamp from verifier */
- u_int32_t nsd_ttl; /* credential ttl (sec) */
- NFSKERBKEY_T nsd_key; /* Session key */
-};
-
-struct nfsd_cargs {
- char *ncd_dirp; /* Mount dir path */
- uid_t ncd_authuid; /* Effective uid */
- int ncd_authtype; /* Type of authenticator */
- u_int ncd_authlen; /* Length of authenticator string */
- u_char *ncd_authstr; /* Authenticator string */
- u_int ncd_verflen; /* and the verifier */
- u_char *ncd_verfstr;
- NFSKERBKEY_T ncd_key; /* Session key */
-};
-
-/*
- * XXX to allow amd to include nfs.h without nfsproto.h
- */
-#ifdef NFS_NPROCS
-/*
- * Stats structure
- */
-struct nfsstats {
- int attrcache_hits;
- int attrcache_misses;
- int lookupcache_hits;
- int lookupcache_misses;
- int direofcache_hits;
- int direofcache_misses;
- int biocache_reads;
- int read_bios;
- int read_physios;
- int biocache_writes;
- int write_bios;
- int write_physios;
- int biocache_readlinks;
- int readlink_bios;
- int biocache_readdirs;
- int readdir_bios;
- int rpccnt[NFS_NPROCS];
- int rpcretries;
- int srvrpccnt[NFS_NPROCS];
- int srvrpc_errs;
- int srv_errs;
- int rpcrequests;
- int rpctimeouts;
- int rpcunexpected;
- int rpcinvalid;
- int srvcache_inproghits;
- int srvcache_idemdonehits;
- int srvcache_nonidemdonehits;
- int srvcache_misses;
- int srvnqnfs_leases;
- int srvnqnfs_maxleases;
- int srvnqnfs_getleases;
- int srvvop_writes;
- int accesscache_hits;
- int accesscache_misses;
-};
-#endif
-
-/*
- * Flags for nfssvc() system call.
- */
-#define NFSSVC_BIOD 0x002
-#define NFSSVC_NFSD 0x004
-#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_AUTHIN 0x010
-#define NFSSVC_GOTAUTH 0x040
-#define NFSSVC_AUTHINFAIL 0x080
-#define NFSSVC_MNTD 0x100
-#define NFSSVC_LOCKDANS 0x200
-
-/*
- * fs.nfs sysctl(3) identifiers
- */
-#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
-#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
-
-#define FS_NFS_NAMES { \
- { 0, 0 }, \
- { "nfsstats", CTLTYPE_STRUCT }, \
- { "nfsprivport", CTLTYPE_INT }, \
-}
-
-#ifdef _KERNEL
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_NFSREQ);
-MALLOC_DECLARE(M_NFSDIROFF);
-MALLOC_DECLARE(M_NFSRVDESC);
-MALLOC_DECLARE(M_NFSUID);
-MALLOC_DECLARE(M_NQLEASE);
-MALLOC_DECLARE(M_NFSD);
-MALLOC_DECLARE(M_NFSBIGFH);
-MALLOC_DECLARE(M_NFSHASH);
-#endif
-
-#ifdef ZONE_INTERRUPT
-extern vm_zone_t nfsmount_zone;
-#endif
-
-extern struct callout_handle nfs_timer_handle;
-
-struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
-
-/*
- * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
- * What should be in this set is open to debate, but I believe that since
- * I/O system calls on ufs are never interrupted by signals the set should
- * be minimal. My reasoning is that many current programs that use signals
- * such as SIGALRM will not expect file I/O system calls to be interrupted
- * by them and break.
- */
-#define NFSINT_SIGMASK(set) \
- (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
- SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
- SIGISMEMBER(set, SIGQUIT))
-
-/*
- * Socket errors ignored for connectionless sockets??
- * For now, ignore them all
- */
-#define NFSIGNORE_SOERROR(s, e) \
- ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
- ((s) & PR_CONNREQUIRED) == 0)
-
-/*
- * Nfs outstanding request list element
- */
-struct nfsreq {
- TAILQ_ENTRY(nfsreq) r_chain;
- struct mbuf *r_mreq;
- struct mbuf *r_mrep;
- struct mbuf *r_md;
- caddr_t r_dpos;
- struct nfsmount *r_nmp;
- struct vnode *r_vp;
- 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 */
- u_int32_t r_procnum; /* NFS procedure number */
- int r_rtt; /* RTT for rpc */
- struct thread *r_td; /* Proc that did I/O system call */
-};
-
-/*
- * Queue head for nfsreq's
- */
-extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
-
-/* 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 */
-
-/*
- * A list of nfssvc_sock structures is maintained with all the sockets
- * that require service by the nfsd.
- * The nfsuid structs hang off of the nfssvc_sock structs in both lru
- * and uid hash lists.
- */
-#ifndef NFS_UIDHASHSIZ
-#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
-#endif
-#define NUIDHASH(sock, uid) \
- (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
-#ifndef NFS_WDELAYHASHSIZ
-#define NFS_WDELAYHASHSIZ 16 /* and with this */
-#endif
-#define NWDELAYHASH(sock, f) \
- (&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifndef NFS_MUIDHASHSIZ
-#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
-#endif
-#define NMUIDHASH(nmp, uid) \
- (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
-#define NFSNOHASH(fhsum) \
- (&nfsnodehashtbl[(fhsum) & nfsnodehash])
-
-/*
- * Network address hash list element
- */
-union nethostaddr {
- u_int32_t had_inetaddr;
- struct sockaddr *had_nam;
-};
-
-struct nfsuid {
- TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
- LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
- int nu_flag; /* Flags */
- union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
- struct ucred nu_cr; /* Cred uid mapped to */
- int nu_expire; /* Expiry time (sec) */
- struct timeval nu_timestamp; /* Kerb. timestamp */
- u_int32_t nu_nickname; /* Nickname on server */
- NFSKERBKEY_T nu_key; /* and session key */
-};
-
-#define nu_inetaddr nu_haddr.had_inetaddr
-#define nu_nam nu_haddr.had_nam
-/* Bits for nu_flag */
-#define NU_INETADDR 0x1
-#define NU_NAM 0x2
-#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
-
-struct nfsrv_rec {
- STAILQ_ENTRY(nfsrv_rec) nr_link;
- struct sockaddr *nr_address;
- struct mbuf *nr_packet;
-};
-
-struct nfssvc_sock {
- TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- TAILQ_HEAD(, nfsuid) ns_uidlruhead;
- struct file *ns_fp;
- struct socket *ns_so;
- struct sockaddr *ns_nam;
- struct mbuf *ns_raw;
- struct mbuf *ns_rawend;
- STAILQ_HEAD(, nfsrv_rec) ns_rec;
- struct mbuf *ns_frag;
- int ns_flag;
- int ns_solock;
- int ns_cc;
- int ns_reclen;
- int ns_numuids;
- u_int32_t ns_sref;
- LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
- LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
-};
-
-/* Bits for "ns_flag" */
-#define SLP_VALID 0x01
-#define SLP_DOREC 0x02
-#define SLP_NEEDQ 0x04
-#define SLP_DISCONN 0x08
-#define SLP_GETSTREAM 0x10
-#define SLP_LASTFRAG 0x20
-#define SLP_ALLFLAGS 0xff
-
-extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
-extern int nfssvc_sockhead_flag;
-#define SLP_INIT 0x01
-#define SLP_WANTINIT 0x02
-
-/*
- * One of these structures is allocated for each nfsd.
- */
-struct nfsd {
- TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
- int nfsd_flag; /* NFSD_ flags */
- struct nfssvc_sock *nfsd_slp; /* Current socket */
- int nfsd_authlen; /* Authenticator len */
- u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
- int nfsd_verflen; /* and the Verifier */
- u_char nfsd_verfstr[RPCVERF_MAXSIZ];
- struct thread *nfsd_td; /* daemon thread ptr */
- struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
-};
-
-/* Bits for "nfsd_flag" */
-#define NFSD_WAITING 0x01
-#define NFSD_REQINPROG 0x02
-#define NFSD_NEEDAUTH 0x04
-#define NFSD_AUTHFAIL 0x08
-
-/*
- * This structure is used by the server for describing each request.
- * Some fields are used only when write request gathering is performed.
- */
-struct nfsrv_descript {
- u_quad_t nd_time; /* Write deadline (usec) */
- off_t nd_off; /* Start byte offset */
- off_t nd_eoff; /* and end byte offset */
- LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
- LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
- LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
- struct mbuf *nd_mrep; /* Request mbuf list */
- struct mbuf *nd_md; /* Current dissect mbuf */
- struct mbuf *nd_mreq; /* Reply mbuf list */
- struct sockaddr *nd_nam; /* and socket addr */
- struct sockaddr *nd_nam2; /* return socket addr */
- caddr_t nd_dpos; /* Current dissect pos */
- u_int32_t nd_procnum; /* RPC # */
- int nd_stable; /* storage type */
- int nd_flag; /* nd_flag */
- int nd_len; /* Length of this write */
- int nd_repstat; /* Reply status */
- u_int32_t nd_retxid; /* Reply xid */
- u_int32_t nd_duration; /* Lease duration */
- struct timeval nd_starttime; /* Time RPC initiated */
- fhandle_t nd_fh; /* File handle */
- struct ucred nd_cr; /* Credentials */
-};
-
-/* Bits for "nd_flag" */
-#define ND_READ LEASE_READ
-#define ND_WRITE LEASE_WRITE
-#define ND_CHECK 0x04
-#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
-#define ND_NFSV3 0x08
-#define ND_NQNFS 0x10
-#define ND_KERBNICK 0x20
-#define ND_KERBFULL 0x40
-#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
-
-extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
-extern int nfsd_head_flag;
-#define NFSD_CHECKSLP 0x01
-
-/*
- * These macros compare nfsrv_descript structures.
- */
-#define NFSW_CONTIG(o, n) \
- ((o)->nd_eoff >= (n)->nd_off && \
- !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
-
-#define NFSW_SAMECRED(o, n) \
- (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
- !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
- sizeof (struct ucred)))
-
-/*
- * Defines for WebNFS
- */
-
-#define WEBNFS_ESC_CHAR '%'
-#define WEBNFS_SPECCHAR_START 0x80
-
-#define WEBNFS_NATIVE_CHAR 0x80
-/*
- * ..
- * Possibly more here in the future.
- */
-
-/*
- * Macro for converting escape characters in WebNFS pathnames.
- * Should really be in libkern.
- */
-
-#define HEXTOC(c) \
- ((c) >= 'a' ? ((c) - ('a' - 10)) : \
- ((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
-#define HEXSTRTOI(p) \
- ((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
-
-#ifdef NFS_DEBUG
-
-extern int nfs_debug;
-#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
-#define NFS_DEBUG_WG 2 /* server write gathering */
-#define NFS_DEBUG_RC 4 /* server request caching */
-
-#define NFS_DPF(cat, args) \
- do { \
- if (nfs_debug & NFS_DEBUG_##cat) printf args; \
- } while (0)
-
-#else
-
-#define NFS_DPF(cat, args)
-
-#endif
-
-u_quad_t nfs_curusec __P((void));
-int nfs_init __P((struct vfsconf *vfsp));
-int nfs_uninit __P((struct vfsconf *vfsp));
-int nfs_reply __P((struct nfsreq *));
-int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
-int nfs_send __P((struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *));
-int nfs_rephead __P((int, struct nfsrv_descript *, struct nfssvc_sock *,
- int, int, u_quad_t *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_sndlock __P((struct nfsreq *));
-void nfs_sndunlock __P((struct nfsreq *));
-int nfs_slplock __P((struct nfssvc_sock *, int));
-void nfs_slpunlock __P((struct nfssvc_sock *));
-int nfs_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-int nfs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct thread *,
- int));
-int nfs_readrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_writerpc __P((struct vnode *, struct uio *, struct ucred *, int *,
- int *));
-int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
- struct ucred *cred, struct thread *td));
-int nfs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_asyncio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_doio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_readlinkrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_sigintr __P((struct nfsmount *, struct nfsreq *, struct proc *));
-int nfs_readdirplusrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfsm_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-void nfsm_srvfattr __P((struct nfsrv_descript *, struct vattr *,
- struct nfs_fattr *));
-void nfsm_srvwcc __P((struct nfsrv_descript *, int, struct vattr *, int,
- struct vattr *, struct mbuf **, char **));
-void nfsm_srvpostopattr __P((struct nfsrv_descript *, int, struct vattr *,
- struct mbuf **, char **));
-int netaddr_match __P((int, union nethostaddr *, struct sockaddr *));
-int nfs_request __P((struct vnode *, struct mbuf *, int, struct thread *,
- struct ucred *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *, int));
-int nfs_namei __P((struct nameidata *, fhandle_t *, int,
- struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
- caddr_t *, struct vnode **, struct thread *, int, int));
-void nfsm_adj __P((struct mbuf *, int, int));
-int nfsm_mbuftouio __P((struct mbuf **, struct uio *, int, caddr_t *));
-void nfsrv_initcache __P((void));
-int nfs_getauth __P((struct nfsmount *, struct nfsreq *, struct ucred *,
- char **, int *, char *, int *, NFSKERBKEY_T));
-int nfs_getnickauth __P((struct nfsmount *, struct ucred *, char **,
- int *, char *, int));
-int nfs_savenickauth __P((struct nfsmount *, struct ucred *, int,
- NFSKERBKEY_T, struct mbuf **, char **,
- struct mbuf *));
-int nfs_adv __P((struct mbuf **, caddr_t *, int, int));
-void nfs_nhinit __P((void));
-void nfs_timer __P((void*));
-int nfsrv_dorec __P((struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **));
-int nfsrv_getcache __P((struct nfsrv_descript *, struct nfssvc_sock *,
- struct mbuf **));
-void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *));
-void nfsrv_cleancache __P((void));
-int nfs_connect __P((struct nfsmount *, struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *));
-void nfs_safedisconnect __P((struct nfsmount *));
-int nfs_getattrcache __P((struct vnode *, struct vattr *));
-int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long));
-int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *));
-int nfsm_uiotombuf __P((struct uio *, struct mbuf **, int, caddr_t *));
-void nfsrv_init __P((int));
-void nfs_clearcommit __P((struct mount *));
-int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrvw_sort __P((gid_t *, int));
-void nfsrv_setcred __P((struct ucred *, struct ucred *));
-int nfs_writebp __P((struct buf *, int, struct thread *));
-int nfsrv_object_create __P((struct vnode *));
-void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
-int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
- struct thread *, struct mbuf **));
-int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
- struct thread *td));
-
-int nfsrv3_access __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_fhtovp __P((fhandle_t *, int, struct vnode **, struct ucred *,
- struct nfssvc_sock *, struct sockaddr *, int *,
- int, int));
-int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
- struct export_args *));
-int nfs_ispublicfh __P((fhandle_t *));
-int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdir __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_setattr __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_statfs __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_symlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-void nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
-#endif /* _KERNEL */
-
-#endif
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c
deleted file mode 100644
index fa7274d..0000000
--- a/sys/nfs/nfs_bio.c
+++ /dev/null
@@ -1,1641 +0,0 @@
-/*
- * 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.
- * 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_bio.c 8.9 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/signalvar.h>
-#include <sys/vmmeter.h>
-#include <sys/vnode.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-#include <vm/vm_pager.h>
-#include <vm/vnode_pager.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsnode.h>
-
-/*
- * 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
-nfs_bwrite(struct buf *bp)
-{
- return (nfs_writebp(bp, 1, curthread));
-}
-
-struct buf_ops buf_ops_nfs = {
- "buf_ops_nfs",
- nfs_bwrite
-};
-
-
-static struct buf *nfs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size,
- struct thread *td));
-
-extern int nfs_numasync;
-extern int nfs_pbuf_freecnt;
-extern struct nfsstats nfsstats;
-
-/*
- * Vnode op for VM getpages.
- */
-int
-nfs_getpages(ap)
- struct vop_getpages_args /* {
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_reqpage;
- vm_ooffset_t a_offset;
- } */ *ap;
-{
- int i, error, nextoff, size, toff, count, npages;
- struct uio uio;
- struct iovec iov;
- vm_offset_t kva;
- struct buf *bp;
- struct vnode *vp;
- struct thread *td;
- struct ucred *cred;
- struct nfsmount *nmp;
- vm_page_t *pages;
-
- GIANT_REQUIRED;
-
- vp = ap->a_vp;
- td = curthread; /* XXX */
- cred = curthread->td_proc->p_ucred; /* XXX */
- nmp = VFSTONFS(vp->v_mount);
- pages = ap->a_m;
- count = ap->a_count;
-
- if (vp->v_object == NULL) {
- printf("nfs_getpages: called with non-merged cache vnode??\n");
- return VM_PAGER_ERROR;
- }
-
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- (void)nfs_fsinfo(nmp, vp, cred, td);
- }
-
- npages = btoc(count);
-
- /*
- * If the requested page is partially valid, just return it and
- * allow the pager to zero-out the blanks. Partially valid pages
- * can only occur at the file EOF.
- */
-
- {
- vm_page_t m = pages[ap->a_reqpage];
-
- if (m->valid != 0) {
- /* handled by vm_fault now */
- /* vm_page_zero_invalid(m, TRUE); */
- for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
- vm_page_free(pages[i]);
- }
- return(0);
- }
- }
-
- /*
- * We use only the kva address for the buffer, but this is extremely
- * convienient and fast.
- */
- bp = getpbuf(&nfs_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, pages, npages);
- cnt.v_vnodein++;
- cnt.v_vnodepgsin += npages;
-
- iov.iov_base = (caddr_t) kva;
- iov.iov_len = count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = IDX_TO_OFF(pages[0]->pindex);
- uio.uio_resid = count;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_READ;
- uio.uio_td = td;
-
- error = nfs_readrpc(vp, &uio, cred);
- pmap_qremove(kva, npages);
-
- relpbuf(bp, &nfs_pbuf_freecnt);
-
- if (error && (uio.uio_resid == count)) {
- printf("nfs_getpages: error %d\n", error);
- for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
- vm_page_free(pages[i]);
- }
- return VM_PAGER_ERROR;
- }
-
- /*
- * Calculate the number of bytes read and validate only that number
- * of bytes. Note that due to pending writes, size may be 0. This
- * does not mean that the remaining data is invalid!
- */
-
- size = count - uio.uio_resid;
-
- for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
- vm_page_t m;
- nextoff = toff + PAGE_SIZE;
- m = pages[i];
-
- m->flags &= ~PG_ZERO;
-
- if (nextoff <= size) {
- /*
- * Read operation filled an entire page
- */
- m->valid = VM_PAGE_BITS_ALL;
- vm_page_undirty(m);
- } else if (size > toff) {
- /*
- * Read operation filled a partial page.
- */
- m->valid = 0;
- vm_page_set_validclean(m, 0, size - toff);
- /* handled by vm_fault now */
- /* vm_page_zero_invalid(m, TRUE); */
- }
-
- if (i != ap->a_reqpage) {
- /*
- * Whether or not to leave the page activated is up in
- * the air, but we should put the page on a page queue
- * somewhere (it already is in the object). Result:
- * It appears that emperical results show that
- * deactivating pages is best.
- */
-
- /*
- * Just in case someone was asking for this page we
- * now tell them that it is ok to use.
- */
- if (!error) {
- if (m->flags & PG_WANTED)
- vm_page_activate(m);
- else
- vm_page_deactivate(m);
- vm_page_wakeup(m);
- } else {
- vm_page_free(m);
- }
- }
- }
- return 0;
-}
-
-/*
- * Vnode op for VM putpages.
- */
-int
-nfs_putpages(ap)
- struct vop_putpages_args /* {
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_sync;
- int *a_rtvals;
- vm_ooffset_t a_offset;
- } */ *ap;
-{
- struct uio uio;
- struct iovec iov;
- vm_offset_t kva;
- struct buf *bp;
- int iomode, must_commit, i, error, npages, count;
- off_t offset;
- int *rtvals;
- struct vnode *vp;
- struct thread *td;
- struct ucred *cred;
- struct nfsmount *nmp;
- struct nfsnode *np;
- vm_page_t *pages;
-
- GIANT_REQUIRED;
-
- vp = ap->a_vp;
- np = VTONFS(vp);
- td = curthread; /* XXX */
- cred = curthread->td_proc->p_ucred; /* XXX */
- nmp = VFSTONFS(vp->v_mount);
- pages = ap->a_m;
- count = ap->a_count;
- rtvals = ap->a_rtvals;
- npages = btoc(count);
- offset = IDX_TO_OFF(pages[0]->pindex);
-
- GIANT_REQUIRED;
-
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- (void)nfs_fsinfo(nmp, vp, cred, td);
- }
-
- for (i = 0; i < npages; i++) {
- rtvals[i] = VM_PAGER_AGAIN;
- }
-
- /*
- * When putting pages, do not extend file past EOF.
- */
-
- if (offset + count > np->n_size) {
- count = np->n_size - offset;
- if (count < 0)
- count = 0;
- }
-
- /*
- * We use only the kva address for the buffer, but this is extremely
- * convienient and fast.
- */
- bp = getpbuf(&nfs_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, pages, npages);
- cnt.v_vnodeout++;
- cnt.v_vnodepgsout += count;
-
- iov.iov_base = (caddr_t) kva;
- iov.iov_len = count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = offset;
- uio.uio_resid = count;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_WRITE;
- uio.uio_td = td;
-
- if ((ap->a_sync & VM_PAGER_PUT_SYNC) == 0)
- iomode = NFSV3WRITE_UNSTABLE;
- else
- iomode = NFSV3WRITE_FILESYNC;
-
- error = nfs_writerpc(vp, &uio, cred, &iomode, &must_commit);
-
- pmap_qremove(kva, npages);
- relpbuf(bp, &nfs_pbuf_freecnt);
-
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- if (must_commit) {
- nfs_clearcommit(vp->v_mount);
- }
- }
- return rtvals[0];
-}
-
-/*
- * Vnode op for read using bio
- */
-int
-nfs_bioread(vp, uio, ioflag, cred)
- register struct vnode *vp;
- register struct uio *uio;
- int ioflag;
- struct ucred *cred;
-{
- register struct nfsnode *np = VTONFS(vp);
- register int biosize, i;
- struct buf *bp = 0, *rabp;
- struct vattr vattr;
- struct thread *td;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- daddr_t lbn, rabn;
- int bcount;
- int seqcount;
- int nra, error = 0, n = 0, on = 0;
-
-#ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_READ)
- panic("nfs_read mode");
-#endif
- if (uio->uio_resid == 0)
- return (0);
- if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */
- return (EINVAL);
- td = uio->uio_td;
-
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
- (void)nfs_fsinfo(nmp, vp, cred, td);
- if (vp->v_type != VDIR &&
- (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
- return (EFBIG);
- biosize = vp->v_mount->mnt_stat.f_iosize;
- seqcount = (int)((off_t)(ioflag >> 16) * biosize / BKVASIZE);
- /*
- * For nfs, cache consistency can only be maintained approximately.
- * Although RFC1094 does not specify the criteria, the following is
- * believed to be compatible with the reference port.
- * For nqnfs, full cache consistency is maintained within the loop.
- * For nfs:
- * If the file's modify time on the server has changed since the
- * last read rpc or you have written to the file,
- * you may have lost data cache consistency with the
- * server, so flush all of the file's data out of the cache.
- * Then force a getattr rpc to ensure that you have up to date
- * attributes.
- * NB: This implies that cache data can be read when up to
- * NFS_ATTRTIMEO seconds out of date. If you find that you need current
- * attributes this could be forced by setting n_attrstamp to 0 before
- * the VOP_GETATTR() call.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) {
- if (np->n_flag & NMODIFIED) {
- if (vp->v_type != VREG) {
- if (vp->v_type != VDIR)
- panic("nfs: bioread, not dir");
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- }
- np->n_attrstamp = 0;
- error = VOP_GETATTR(vp, &vattr, cred, td);
- if (error)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- } else {
- error = VOP_GETATTR(vp, &vattr, cred, td);
- if (error)
- return (error);
- if (np->n_mtime != vattr.va_mtime.tv_sec) {
- if (vp->v_type == VDIR)
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- }
- }
- }
- do {
-
- /*
- * Get a valid lease. If cached data is stale, flush it.
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (NQNFS_CKINVALID(vp, np, ND_READ)) {
- do {
- error = nqnfs_getlease(vp, ND_READ, cred, td);
- } while (error == NQNFS_EXPIRED);
- if (error)
- return (error);
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE) ||
- ((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
- if (vp->v_type == VDIR)
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- np->n_brev = np->n_lrev;
- }
- } else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- }
- }
- if (np->n_flag & NQNFSNONCACHE) {
- switch (vp->v_type) {
- case VREG:
- return (nfs_readrpc(vp, uio, cred));
- case VLNK:
- return (nfs_readlinkrpc(vp, uio, cred));
- case VDIR:
- break;
- default:
- printf(" NQNFSNONCACHE: type %x unexpected\n",
- vp->v_type);
- };
- }
- switch (vp->v_type) {
- case VREG:
- nfsstats.biocache_reads++;
- lbn = uio->uio_offset / biosize;
- on = uio->uio_offset & (biosize - 1);
-
- /*
- * Start the read ahead(s), as required.
- */
- if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
- for (nra = 0; nra < nmp->nm_readahead && nra < seqcount &&
- (off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) {
- rabn = lbn + 1 + nra;
- if (!incore(vp, rabn)) {
- rabp = nfs_getcacheblk(vp, rabn, biosize, td);
- if (!rabp)
- return (EINTR);
- if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
- rabp->b_flags |= B_ASYNC;
- rabp->b_iocmd = BIO_READ;
- vfs_busy_pages(rabp, 0);
- if (nfs_asyncio(rabp, cred, td)) {
- rabp->b_flags |= B_INVAL;
- rabp->b_ioflags |= BIO_ERROR;
- vfs_unbusy_pages(rabp);
- brelse(rabp);
- break;
- }
- } else {
- brelse(rabp);
- }
- }
- }
- }
-
- /*
- * Obtain the buffer cache block. Figure out the buffer size
- * when we are at EOF. If we are modifying the size of the
- * buffer based on an EOF condition we need to hold
- * nfs_rslock() through obtaining the buffer to prevent
- * a potential writer-appender from messing with n_size.
- * Otherwise we may accidently truncate the buffer and
- * lose dirty data.
- *
- * Note that bcount is *not* DEV_BSIZE aligned.
- */
-
-again:
- bcount = biosize;
- if ((off_t)lbn * biosize >= np->n_size) {
- bcount = 0;
- } else if ((off_t)(lbn + 1) * biosize > np->n_size) {
- bcount = np->n_size - (off_t)lbn * biosize;
- }
- if (bcount != biosize) {
- switch(nfs_rslock(np, td)) {
- case ENOLCK:
- goto again;
- /* not reached */
- case EINTR:
- case ERESTART:
- return(EINTR);
- /* not reached */
- default:
- break;
- }
- }
-
- bp = nfs_getcacheblk(vp, lbn, bcount, td);
-
- if (bcount != biosize)
- nfs_rsunlock(np, td);
- if (!bp)
- return (EINTR);
-
- /*
- * If B_CACHE is not set, we must issue the read. If this
- * fails, we return an error.
- */
-
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(bp, cred, td);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
-
- /*
- * on is the offset into the current bp. Figure out how many
- * bytes we can copy out of the bp. Note that bcount is
- * NOT DEV_BSIZE aligned.
- *
- * Then figure out how many bytes we can copy into the uio.
- */
-
- n = 0;
- if (on < bcount)
- n = min((unsigned)(bcount - on), uio->uio_resid);
- break;
- case VLNK:
- nfsstats.biocache_readlinks++;
- bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, td);
- if (!bp)
- return (EINTR);
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(bp, cred, td);
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- brelse(bp);
- return (error);
- }
- }
- n = min(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
- on = 0;
- break;
- case VDIR:
- nfsstats.biocache_readdirs++;
- if (np->n_direofoffset
- && uio->uio_offset >= np->n_direofoffset) {
- return (0);
- }
- lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ;
- on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
- bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td);
- if (!bp)
- return (EINTR);
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(bp, cred, td);
- if (error) {
- brelse(bp);
- }
- while (error == NFSERR_BAD_COOKIE) {
- printf("got bad cookie vp %p bp %p\n", vp, bp);
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, 0, cred, td, 1);
- /*
- * Yuck! The directory has been modified on the
- * server. The only way to get the block is by
- * reading from the beginning to get all the
- * offset cookies.
- *
- * Leave the last bp intact unless there is an error.
- * Loop back up to the while if the error is another
- * NFSERR_BAD_COOKIE (double yuch!).
- */
- for (i = 0; i <= lbn && !error; i++) {
- if (np->n_direofoffset
- && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset)
- return (0);
- bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, td);
- if (!bp)
- return (EINTR);
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(bp, cred, td);
- /*
- * no error + B_INVAL == directory EOF,
- * use the block.
- */
- if (error == 0 && (bp->b_flags & B_INVAL))
- break;
- }
- /*
- * An error will throw away the block and the
- * for loop will break out. If no error and this
- * is not the block we want, we throw away the
- * block and go for the next one via the for loop.
- */
- if (error || i < lbn)
- brelse(bp);
- }
- }
- /*
- * The above while is repeated if we hit another cookie
- * error. If we hit an error and it wasn't a cookie error,
- * we give up.
- */
- if (error)
- return (error);
- }
-
- /*
- * If not eof and read aheads are enabled, start one.
- * (You need the current block first, so that you have the
- * directory offset cookie of the next block.)
- */
- if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
- (bp->b_flags & B_INVAL) == 0 &&
- (np->n_direofoffset == 0 ||
- (lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
- !(np->n_flag & NQNFSNONCACHE) &&
- !incore(vp, lbn + 1)) {
- rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, td);
- if (rabp) {
- if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
- rabp->b_flags |= B_ASYNC;
- rabp->b_iocmd = BIO_READ;
- vfs_busy_pages(rabp, 0);
- if (nfs_asyncio(rabp, cred, td)) {
- rabp->b_flags |= B_INVAL;
- rabp->b_ioflags |= BIO_ERROR;
- vfs_unbusy_pages(rabp);
- brelse(rabp);
- }
- } else {
- brelse(rabp);
- }
- }
- }
- /*
- * Unlike VREG files, whos buffer size ( bp->b_bcount ) is
- * chopped for the EOF condition, we cannot tell how large
- * NFS directories are going to be until we hit EOF. So
- * an NFS directory buffer is *not* chopped to its EOF. Now,
- * it just so happens that b_resid will effectively chop it
- * to EOF. *BUT* this information is lost if the buffer goes
- * away and is reconstituted into a B_CACHE state ( due to
- * being VMIO ) later. So we keep track of the directory eof
- * in np->n_direofoffset and chop it off as an extra step
- * right here.
- */
- n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
- if (np->n_direofoffset && n > np->n_direofoffset - uio->uio_offset)
- n = np->n_direofoffset - uio->uio_offset;
- break;
- default:
- printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
- break;
- };
-
- if (n > 0) {
- error = uiomove(bp->b_data + on, (int)n, uio);
- }
- switch (vp->v_type) {
- case VREG:
- break;
- case VLNK:
- n = 0;
- break;
- case VDIR:
- /*
- * Invalidate buffer if caching is disabled, forcing a
- * re-read from the remote later.
- */
- if (np->n_flag & NQNFSNONCACHE)
- bp->b_flags |= B_INVAL;
- break;
- default:
- printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
- }
- brelse(bp);
- } while (error == 0 && uio->uio_resid > 0 && n > 0);
- return (error);
-}
-
-/*
- * Vnode op for write using bio
- */
-int
-nfs_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- int biosize;
- struct uio *uio = ap->a_uio;
- struct thread *td = uio->uio_td;
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct ucred *cred = ap->a_cred;
- int ioflag = ap->a_ioflag;
- struct buf *bp;
- struct vattr vattr;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- daddr_t lbn;
- int bcount;
- int n, on, error = 0, iomode, must_commit;
- int haverslock = 0;
- struct proc *p = td?td->td_proc:NULL;
-
- GIANT_REQUIRED;
-
-#ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_WRITE)
- panic("nfs_write mode");
- if (uio->uio_segflg == UIO_USERSPACE && uio->uio_td != curthread)
- panic("nfs_write proc");
-#endif
- if (vp->v_type != VREG)
- return (EIO);
- if (np->n_flag & NWRITEERR) {
- np->n_flag &= ~NWRITEERR;
- return (np->n_error);
- }
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
- (void)nfs_fsinfo(nmp, vp, cred, td);
-
- /*
- * Synchronously flush pending buffers if we are in synchronous
- * mode or if we are appending.
- */
- if (ioflag & (IO_APPEND | IO_SYNC)) {
- if (np->n_flag & NMODIFIED) {
- np->n_attrstamp = 0;
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- }
- }
-
- /*
- * If IO_APPEND then load uio_offset. We restart here if we cannot
- * get the append lock.
- */
-restart:
- if (ioflag & IO_APPEND) {
- np->n_attrstamp = 0;
- error = VOP_GETATTR(vp, &vattr, cred, td);
- if (error)
- return (error);
- uio->uio_offset = np->n_size;
- }
-
- if (uio->uio_offset < 0)
- return (EINVAL);
- if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
- return (EFBIG);
- if (uio->uio_resid == 0)
- return (0);
-
- /*
- * We need to obtain the rslock if we intend to modify np->n_size
- * in order to guarentee the append point with multiple contending
- * writers, to guarentee that no other appenders modify n_size
- * while we are trying to obtain a truncated buffer (i.e. to avoid
- * accidently truncating data written by another appender due to
- * the race), and to ensure that the buffer is populated prior to
- * our extending of the file. We hold rslock through the entire
- * operation.
- *
- * Note that we do not synchronize the case where someone truncates
- * the file while we are appending to it because attempting to lock
- * this case may deadlock other parts of the system unexpectedly.
- */
- if ((ioflag & IO_APPEND) ||
- uio->uio_offset + uio->uio_resid > np->n_size) {
- switch(nfs_rslock(np, td)) {
- case ENOLCK:
- goto restart;
- /* not reached */
- case EINTR:
- case ERESTART:
- return(EINTR);
- /* not reached */
- default:
- break;
- }
- haverslock = 1;
- }
-
- /*
- * Maybe this should be above the vnode op call, but so long as
- * file servers have no limits, i don't think it matters
- */
- if (p && uio->uio_offset + uio->uio_resid >
- p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
- PROC_LOCK(p);
- psignal(p, SIGXFSZ);
- PROC_UNLOCK(p);
- if (haverslock)
- nfs_rsunlock(np, td);
- return (EFBIG);
- }
-
- biosize = vp->v_mount->mnt_stat.f_iosize;
-
- do {
- /*
- * Check for a valid write lease.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) &&
- NQNFS_CKINVALID(vp, np, ND_WRITE)) {
- do {
- error = nqnfs_getlease(vp, ND_WRITE, cred, td);
- } while (error == NQNFS_EXPIRED);
- if (error)
- break;
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE)) {
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- break;
- np->n_brev = np->n_lrev;
- }
- }
- if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
- iomode = NFSV3WRITE_FILESYNC;
- error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
- if (must_commit)
- nfs_clearcommit(vp->v_mount);
- break;
- }
- nfsstats.biocache_writes++;
- lbn = uio->uio_offset / biosize;
- on = uio->uio_offset & (biosize-1);
- n = min((unsigned)(biosize - on), uio->uio_resid);
-again:
- /*
- * Handle direct append and file extension cases, calculate
- * unaligned buffer size.
- */
-
- if (uio->uio_offset == np->n_size && n) {
- /*
- * Get the buffer (in its pre-append state to maintain
- * B_CACHE if it was previously set). Resize the
- * nfsnode after we have locked the buffer to prevent
- * readers from reading garbage.
- */
- bcount = on;
- bp = nfs_getcacheblk(vp, lbn, bcount, td);
-
- if (bp != NULL) {
- long save;
-
- np->n_size = uio->uio_offset + n;
- np->n_flag |= NMODIFIED;
- vnode_pager_setsize(vp, np->n_size);
-
- save = bp->b_flags & B_CACHE;
- bcount += n;
- allocbuf(bp, bcount);
- bp->b_flags |= save;
- bp->b_magic = B_MAGIC_NFS;
- bp->b_op = &buf_ops_nfs;
- }
- } else {
- /*
- * Obtain the locked cache block first, and then
- * adjust the file's size as appropriate.
- */
- bcount = on + n;
- if ((off_t)lbn * biosize + bcount < np->n_size) {
- if ((off_t)(lbn + 1) * biosize < np->n_size)
- bcount = biosize;
- else
- bcount = np->n_size - (off_t)lbn * biosize;
- }
-
- bp = nfs_getcacheblk(vp, lbn, bcount, td);
-
- if (uio->uio_offset + n > np->n_size) {
- np->n_size = uio->uio_offset + n;
- np->n_flag |= NMODIFIED;
- vnode_pager_setsize(vp, np->n_size);
- }
- }
-
- if (!bp) {
- error = EINTR;
- break;
- }
-
- /*
- * Issue a READ if B_CACHE is not set. In special-append
- * mode, B_CACHE is based on the buffer prior to the write
- * op and is typically set, avoiding the read. If a read
- * is required in special append mode, the server will
- * probably send us a short-read since we extended the file
- * on our end, resulting in b_resid == 0 and, thusly,
- * B_CACHE getting set.
- *
- * We can also avoid issuing the read if the write covers
- * the entire buffer. We have to make sure the buffer state
- * is reasonable in this case since we will not be initiating
- * I/O. See the comments in kern/vfs_bio.c's getblk() for
- * more information.
- *
- * B_CACHE may also be set due to the buffer being cached
- * normally.
- */
-
- if (on == 0 && n == bcount) {
- bp->b_flags |= B_CACHE;
- bp->b_flags &= ~B_INVAL;
- bp->b_ioflags &= ~BIO_ERROR;
- }
-
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(bp, cred, td);
- if (error) {
- brelse(bp);
- break;
- }
- }
- if (!bp) {
- error = EINTR;
- break;
- }
- if (bp->b_wcred == NOCRED) {
- crhold(cred);
- bp->b_wcred = cred;
- }
- np->n_flag |= NMODIFIED;
-
- /*
- * If dirtyend exceeds file size, chop it down. This should
- * not normally occur but there is an append race where it
- * might occur XXX, so we log it.
- *
- * If the chopping creates a reverse-indexed or degenerate
- * situation with dirtyoff/end, we 0 both of them.
- */
-
- if (bp->b_dirtyend > bcount) {
- printf("NFS append race @%lx:%d\n",
- (long)bp->b_blkno * DEV_BSIZE,
- bp->b_dirtyend - bcount);
- bp->b_dirtyend = bcount;
- }
-
- if (bp->b_dirtyoff >= bp->b_dirtyend)
- bp->b_dirtyoff = bp->b_dirtyend = 0;
-
- /*
- * If the new write will leave a contiguous dirty
- * area, just update the b_dirtyoff and b_dirtyend,
- * otherwise force a write rpc of the old dirty area.
- *
- * While it is possible to merge discontiguous writes due to
- * our having a B_CACHE buffer ( and thus valid read data
- * for the hole), we don't because it could lead to
- * significant cache coherency problems with multiple clients,
- * especially if locking is implemented later on.
- *
- * as an optimization we could theoretically maintain
- * a linked list of discontinuous areas, but we would still
- * have to commit them separately so there isn't much
- * advantage to it except perhaps a bit of asynchronization.
- */
-
- if (bp->b_dirtyend > 0 &&
- (on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) {
- if (BUF_WRITE(bp) == EINTR)
- return (EINTR);
- goto again;
- }
-
- /*
- * Check for valid write lease and get one as required.
- * In case getblk() and/or bwrite() delayed us.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) &&
- NQNFS_CKINVALID(vp, np, ND_WRITE)) {
- do {
- error = nqnfs_getlease(vp, ND_WRITE, cred, td);
- } while (error == NQNFS_EXPIRED);
- if (error) {
- brelse(bp);
- break;
- }
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE)) {
- brelse(bp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- break;
- np->n_brev = np->n_lrev;
- goto again;
- }
- }
-
- error = uiomove((char *)bp->b_data + on, n, uio);
-
- /*
- * Since this block is being modified, it must be written
- * again and not just committed. Since write clustering does
- * not work for the stage 1 data write, only the stage 2
- * commit rpc, we have to clear B_CLUSTEROK as well.
- */
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
-
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- brelse(bp);
- break;
- }
-
- /*
- * Only update dirtyoff/dirtyend if not a degenerate
- * condition.
- */
- if (n) {
- if (bp->b_dirtyend > 0) {
- bp->b_dirtyoff = min(on, bp->b_dirtyoff);
- bp->b_dirtyend = max((on + n), bp->b_dirtyend);
- } else {
- bp->b_dirtyoff = on;
- bp->b_dirtyend = on + n;
- }
- vfs_bio_set_validclean(bp, on, n);
- }
-
- /*
- * If the lease is non-cachable or IO_SYNC do bwrite().
- *
- * IO_INVAL appears to be unused. The idea appears to be
- * to turn off caching in this case. Very odd. XXX
- */
- if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) {
- if (ioflag & IO_INVAL)
- bp->b_flags |= B_NOCACHE;
- error = BUF_WRITE(bp);
- if (error)
- break;
- if (np->n_flag & NQNFSNONCACHE) {
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- break;
- }
- } else if ((n + on) == biosize &&
- (nmp->nm_flag & NFSMNT_NQNFS) == 0) {
- bp->b_flags |= B_ASYNC;
- (void)nfs_writebp(bp, 0, 0);
- } else {
- bdwrite(bp);
- }
- } while (uio->uio_resid > 0 && n > 0);
-
- if (haverslock)
- nfs_rsunlock(np, td);
-
- return (error);
-}
-
-/*
- * Get an nfs cache block.
- *
- * Allocate a new one if the block isn't currently in the cache
- * and return the block marked busy. If the calling process is
- * interrupted by a signal for an interruptible mount point, return
- * NULL.
- *
- * The caller must carefully deal with the possible B_INVAL state of
- * the buffer. nfs_doio() clears B_INVAL (and nfs_asyncio() clears it
- * indirectly), so synchronous reads can be issued without worrying about
- * the B_INVAL state. We have to be a little more careful when dealing
- * with writes (see comments in nfs_write()) when extending a file past
- * its EOF.
- */
-static struct buf *
-nfs_getcacheblk(vp, bn, size, td)
- struct vnode *vp;
- daddr_t bn;
- int size;
- struct thread *td;
-{
- register struct buf *bp;
- struct mount *mp;
- struct nfsmount *nmp;
-
- mp = vp->v_mount;
- nmp = VFSTONFS(mp);
-
- if (nmp->nm_flag & NFSMNT_INT) {
- bp = getblk(vp, bn, size, PCATCH, 0);
- while (bp == (struct buf *)0) {
- if (nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc))
- return ((struct buf *)0);
- bp = getblk(vp, bn, size, 0, 2 * hz);
- }
- } else {
- bp = getblk(vp, bn, size, 0, 0);
- }
-
- if (vp->v_type == VREG) {
- int biosize;
-
- biosize = mp->mnt_stat.f_iosize;
- bp->b_blkno = bn * (biosize / DEV_BSIZE);
- }
- return (bp);
-}
-
-/*
- * Flush and invalidate all dirty buffers. If another process is already
- * doing the flush, just wait for completion.
- */
-int
-nfs_vinvalbuf(vp, flags, cred, td, intrflg)
- struct vnode *vp;
- int flags;
- struct ucred *cred;
- struct thread *td;
- int intrflg;
-{
- register struct nfsnode *np = VTONFS(vp);
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- int error = 0, slpflag, slptimeo;
-
- if (vp->v_flag & VXLOCK) {
- return (0);
- }
-
- if ((nmp->nm_flag & NFSMNT_INT) == 0)
- intrflg = 0;
- if (intrflg) {
- slpflag = PCATCH;
- slptimeo = 2 * hz;
- } else {
- slpflag = 0;
- slptimeo = 0;
- }
- /*
- * First wait for any other process doing a flush to complete.
- */
- while (np->n_flag & NFLUSHINPROG) {
- np->n_flag |= NFLUSHWANT;
- error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "nfsvinval",
- slptimeo);
- if (error && intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc))
- return (EINTR);
- }
-
- /*
- * Now, flush as required.
- */
- np->n_flag |= NFLUSHINPROG;
- error = vinvalbuf(vp, flags, cred, td, slpflag, 0);
- while (error) {
- if (intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
- np->n_flag &= ~NFLUSHINPROG;
- if (np->n_flag & NFLUSHWANT) {
- np->n_flag &= ~NFLUSHWANT;
- wakeup((caddr_t)&np->n_flag);
- }
- return (EINTR);
- }
- error = vinvalbuf(vp, flags, cred, td, 0, slptimeo);
- }
- np->n_flag &= ~(NMODIFIED | NFLUSHINPROG);
- if (np->n_flag & NFLUSHWANT) {
- np->n_flag &= ~NFLUSHWANT;
- wakeup((caddr_t)&np->n_flag);
- }
- return (0);
-}
-
-/*
- * Initiate asynchronous I/O. Return an error if no nfsiods are available.
- * This is mainly to avoid queueing async I/O requests when the nfsiods
- * are all hung on a dead server.
- *
- * Note: nfs_asyncio() does not clear (BIO_ERROR|B_INVAL) but when the bp
- * is eventually dequeued by the async daemon, nfs_doio() *will*.
- */
-int
-nfs_asyncio(bp, cred, td)
- register struct buf *bp;
- struct ucred *cred;
- struct thread *td;
-{
- struct nfsmount *nmp;
- int i;
- int gotiod;
- int slpflag = 0;
- int slptimeo = 0;
- int error;
-
- /*
- * If no async daemons then return EIO to force caller to run the rpc
- * synchronously.
- */
- if (nfs_numasync == 0)
- return (EIO);
-
- nmp = VFSTONFS(bp->b_vp->v_mount);
-
- /*
- * Commits are usually short and sweet so lets save some cpu and
- * leave the async daemons for more important rpc's (such as reads
- * and writes).
- */
- if (bp->b_iocmd == BIO_WRITE && (bp->b_flags & B_NEEDCOMMIT) &&
- (nmp->nm_bufqiods > nfs_numasync / 2)) {
- return(EIO);
- }
-
-again:
- if (nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- gotiod = FALSE;
-
- /*
- * Find a free iod to process this request.
- */
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
- if (nfs_iodwant[i]) {
- /*
- * Found one, so wake it up and tell it which
- * mount to process.
- */
- NFS_DPF(ASYNCIO,
- ("nfs_asyncio: waking iod %d for mount %p\n",
- i, nmp));
- nfs_iodwant[i] = (struct proc *)0;
- nfs_iodmount[i] = nmp;
- nmp->nm_bufqiods++;
- wakeup((caddr_t)&nfs_iodwant[i]);
- gotiod = TRUE;
- break;
- }
-
- /*
- * If none are free, we may already have an iod working on this mount
- * point. If so, it will process our request.
- */
- if (!gotiod) {
- if (nmp->nm_bufqiods > 0) {
- NFS_DPF(ASYNCIO,
- ("nfs_asyncio: %d iods are already processing mount %p\n",
- nmp->nm_bufqiods, nmp));
- gotiod = TRUE;
- }
- }
-
- /*
- * If we have an iod which can process the request, then queue
- * the buffer.
- */
- if (gotiod) {
- /*
- * Ensure that the queue never grows too large. We still want
- * to asynchronize so we block rather then return EIO.
- */
- while (nmp->nm_bufqlen >= 2*nfs_numasync) {
- NFS_DPF(ASYNCIO,
- ("nfs_asyncio: waiting for mount %p queue to drain\n", nmp));
- nmp->nm_bufqwant = TRUE;
- error = tsleep(&nmp->nm_bufq, slpflag | PRIBIO,
- "nfsaio", slptimeo);
- if (error) {
- if (nfs_sigintr(nmp, NULL, td ? td->td_proc : NULL))
- return (EINTR);
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- /*
- * We might have lost our iod while sleeping,
- * so check and loop if nescessary.
- */
- if (nmp->nm_bufqiods == 0) {
- NFS_DPF(ASYNCIO,
- ("nfs_asyncio: no iods after mount %p queue was drained, looping\n", nmp));
- goto again;
- }
- }
-
- if (bp->b_iocmd == BIO_READ) {
- if (bp->b_rcred == NOCRED && cred != NOCRED) {
- crhold(cred);
- bp->b_rcred = cred;
- }
- } else {
- bp->b_flags |= B_WRITEINPROG;
- if (bp->b_wcred == NOCRED && cred != NOCRED) {
- crhold(cred);
- bp->b_wcred = cred;
- }
- }
-
- BUF_KERNPROC(bp);
- TAILQ_INSERT_TAIL(&nmp->nm_bufq, bp, b_freelist);
- nmp->nm_bufqlen++;
- return (0);
- }
-
- /*
- * All the iods are busy on other mounts, so return EIO to
- * force the caller to process the i/o synchronously.
- */
- NFS_DPF(ASYNCIO, ("nfs_asyncio: no iods available, i/o is synchronous\n"));
- return (EIO);
-}
-
-/*
- * Do an I/O operation to/from a cache block. This may be called
- * synchronously or from an nfsiod.
- */
-int
-nfs_doio(bp, cr, td)
- struct buf *bp;
- struct ucred *cr;
- struct thread *td;
-{
- struct uio *uiop;
- struct vnode *vp;
- struct nfsnode *np;
- struct nfsmount *nmp;
- int error = 0, iomode, must_commit = 0;
- struct uio uio;
- struct iovec io;
- struct proc *p = td?td->td_proc:NULL;
-
- vp = bp->b_vp;
- np = VTONFS(vp);
- nmp = VFSTONFS(vp->v_mount);
- uiop = &uio;
- uiop->uio_iov = &io;
- uiop->uio_iovcnt = 1;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = td;
-
- /*
- * clear BIO_ERROR and B_INVAL state prior to initiating the I/O. We
- * do this here so we do not have to do it in all the code that
- * calls us.
- */
- bp->b_flags &= ~B_INVAL;
- bp->b_ioflags &= ~BIO_ERROR;
-
- KASSERT(!(bp->b_flags & B_DONE), ("nfs_doio: bp %p already marked done", bp));
-
- /*
- * Historically, paging was done with physio, but no more.
- */
- if (bp->b_flags & B_PHYS) {
- /*
- * ...though reading /dev/drum still gets us here.
- */
- io.iov_len = uiop->uio_resid = bp->b_bcount;
- /* mapping was done by vmapbuf() */
- io.iov_base = bp->b_data;
- uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
- if (bp->b_iocmd == BIO_READ) {
- uiop->uio_rw = UIO_READ;
- nfsstats.read_physios++;
- error = nfs_readrpc(vp, uiop, cr);
- } else {
- int com;
-
- iomode = NFSV3WRITE_DATASYNC;
- uiop->uio_rw = UIO_WRITE;
- nfsstats.write_physios++;
- error = nfs_writerpc(vp, uiop, cr, &iomode, &com);
- }
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- bp->b_error = error;
- }
- } else if (bp->b_iocmd == BIO_READ) {
- io.iov_len = uiop->uio_resid = bp->b_bcount;
- io.iov_base = bp->b_data;
- uiop->uio_rw = UIO_READ;
- switch (vp->v_type) {
- case VREG:
- uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
- nfsstats.read_bios++;
- error = nfs_readrpc(vp, uiop, cr);
- if (!error) {
- if (uiop->uio_resid) {
- /*
- * If we had a short read with no error, we must have
- * hit a file hole. We should zero-fill the remainder.
- * This can also occur if the server hits the file EOF.
- *
- * Holes used to be able to occur due to pending
- * writes, but that is not possible any longer.
- */
- int nread = bp->b_bcount - uiop->uio_resid;
- int left = bp->b_bcount - nread;
-
- if (left > 0)
- bzero((char *)bp->b_data + nread, left);
- uiop->uio_resid = 0;
- }
- }
- if (p && (vp->v_flag & VTEXT) &&
- (((nmp->nm_flag & NFSMNT_NQNFS) &&
- NQNFS_CKINVALID(vp, np, ND_READ) &&
- np->n_lrev != np->n_brev) ||
- (!(nmp->nm_flag & NFSMNT_NQNFS) &&
- np->n_mtime != np->n_vattr.va_mtime.tv_sec))) {
- uprintf("Process killed due to text file modification\n");
- PROC_LOCK(p);
- psignal(p, SIGKILL);
- _PHOLD(p);
- PROC_UNLOCK(p);
- }
- break;
- case VLNK:
- uiop->uio_offset = (off_t)0;
- nfsstats.readlink_bios++;
- error = nfs_readlinkrpc(vp, uiop, cr);
- break;
- case VDIR:
- nfsstats.readdir_bios++;
- uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
- if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
- 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.
- */
- if (error == 0 && uiop->uio_resid == bp->b_bcount)
- bp->b_flags |= B_INVAL;
- break;
- default:
- printf("nfs_doio: type %x unexpected\n",vp->v_type);
- break;
- };
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- bp->b_error = error;
- }
- } else {
- /*
- * If we only need to commit, try to commit
- */
- if (bp->b_flags & B_NEEDCOMMIT) {
- int retv;
- off_t off;
-
- off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
- bp->b_flags |= B_WRITEINPROG;
- retv = nfs_commit(
- bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
- bp->b_wcred, td);
- bp->b_flags &= ~B_WRITEINPROG;
- if (retv == 0) {
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- bp->b_resid = 0;
- bufdone(bp);
- return (0);
- }
- if (retv == NFSERR_STALEWRITEVERF) {
- nfs_clearcommit(bp->b_vp->v_mount);
- }
- }
-
- /*
- * Setup for actual write
- */
-
- if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
- bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
-
- if (bp->b_dirtyend > bp->b_dirtyoff) {
- io.iov_len = uiop->uio_resid = bp->b_dirtyend
- - bp->b_dirtyoff;
- uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE
- + bp->b_dirtyoff;
- io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
- uiop->uio_rw = UIO_WRITE;
- nfsstats.write_bios++;
-
- if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE | B_CLUSTER)) == B_ASYNC)
- iomode = NFSV3WRITE_UNSTABLE;
- else
- iomode = NFSV3WRITE_FILESYNC;
-
- bp->b_flags |= B_WRITEINPROG;
- error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
-
- /*
- * When setting B_NEEDCOMMIT also set B_CLUSTEROK to try
- * to cluster the buffers needing commit. This will allow
- * the system to submit a single commit rpc for the whole
- * cluster. We can do this even if the buffer is not 100%
- * dirty (relative to the NFS blocksize), so we optimize the
- * append-to-file-case.
- *
- * (when clearing B_NEEDCOMMIT, B_CLUSTEROK must also be
- * cleared because write clustering only works for commit
- * rpc's, not for the data portion of the write).
- */
-
- if (!error && iomode == NFSV3WRITE_UNSTABLE) {
- bp->b_flags |= B_NEEDCOMMIT;
- if (bp->b_dirtyoff == 0
- && bp->b_dirtyend == bp->b_bcount)
- bp->b_flags |= B_CLUSTEROK;
- } else {
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- }
- bp->b_flags &= ~B_WRITEINPROG;
-
- /*
- * For an interrupted write, the buffer is still valid
- * and the write hasn't been pushed to the server yet,
- * so we can't set BIO_ERROR and report the interruption
- * by setting B_EINTR. For the B_ASYNC case, B_EINTR
- * is not relevant, so the rpc attempt is essentially
- * a noop. For the case of a V3 write rpc not being
- * committed to stable storage, the block is still
- * dirty and requires either a commit rpc or another
- * write rpc with iomode == NFSV3WRITE_FILESYNC before
- * the block is reused. This is indicated by setting
- * the B_DELWRI and B_NEEDCOMMIT flags.
- *
- * If the buffer is marked B_PAGING, it does not reside on
- * the vp's paging queues so we cannot call bdirty(). The
- * bp in this case is not an NFS cache block so we should
- * be safe. XXX
- */
- if (error == EINTR
- || (!error && (bp->b_flags & B_NEEDCOMMIT))) {
- int s;
-
- s = splbio();
- bp->b_flags &= ~(B_INVAL|B_NOCACHE);
- if ((bp->b_flags & B_PAGING) == 0) {
- bdirty(bp);
- bp->b_flags &= ~B_DONE;
- }
- if (error && (bp->b_flags & B_ASYNC) == 0)
- bp->b_flags |= B_EINTR;
- splx(s);
- } else {
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- bp->b_error = np->n_error = error;
- np->n_flag |= NWRITEERR;
- }
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- }
- } else {
- bp->b_resid = 0;
- bufdone(bp);
- return (0);
- }
- }
- bp->b_resid = uiop->uio_resid;
- if (must_commit)
- nfs_clearcommit(vp->v_mount);
- bufdone(bp);
- return (error);
-}
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
index 4425129..d51edc5 100644
--- a/sys/nfs/nfs_common.c
+++ b/sys/nfs/nfs_common.c
@@ -34,14 +34,17 @@
* SUCH DAMAGE.
*
* @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* These functions support the macros and help fiddle mbuf chains for
* the nfs op functions. They do things like create the rpc header and
* copy data between mbuf chains and uio lists.
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -65,729 +68,37 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
+#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
+#include <nfs/nfs_common.h>
#include <netinet/in.h>
-/*
- * Data items converted to xdr at startup, since they are constant
- * This is kinda hokey, but may save a little time doing byte swaps
- */
-u_int32_t nfs_xdrneg1;
-u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
- rpc_auth_kerb;
-u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false;
-
-/* And other global data */
-static u_int32_t nfs_xid = 0;
-static enum vtype nv2tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON
-};
enum vtype nv3tov_type[8]= {
VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
};
-
-int nfs_ticks;
-int nfs_pbuf_freecnt = -1; /* start out unlimited */
-
-struct nfs_reqq nfs_reqq;
-struct nfssvc_sockhead nfssvc_sockhead;
-int nfssvc_sockhead_flag;
-struct nfsd_head nfsd_head;
-int nfsd_head_flag;
-struct nfs_bufq nfs_bufq;
-struct nqtimerhead nqtimerhead;
-struct nqfhhashhead *nqfhhashtbl;
-u_long nqfhhash;
-
-static void (*nfs_prev_lease_updatetime) __P((int));
-static int nfs_prev_nfssvc_sy_narg;
-static sy_call_t *nfs_prev_nfssvc_sy_call;
-
-#ifndef NFS_NOSERVER
-
-static vop_t *nfs_prev_vop_lease_check;
-
-/*
- * Mapping of old NFS Version 2 RPC numbers to generic numbers.
- */
-int nfsv3_procid[NFS_NPROCS] = {
- NFSPROC_NULL,
- NFSPROC_GETATTR,
- NFSPROC_SETATTR,
- NFSPROC_NOOP,
- NFSPROC_LOOKUP,
- NFSPROC_READLINK,
- NFSPROC_READ,
- NFSPROC_NOOP,
- NFSPROC_WRITE,
- NFSPROC_CREATE,
- NFSPROC_REMOVE,
- NFSPROC_RENAME,
- NFSPROC_LINK,
- NFSPROC_SYMLINK,
- NFSPROC_MKDIR,
- NFSPROC_RMDIR,
- NFSPROC_READDIR,
- NFSPROC_FSSTAT,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP
-};
-
-#endif /* NFS_NOSERVER */
-/*
- * and the reverse mapping from generic to Version 2 procedure numbers
- */
-int nfsv2_procid[NFS_NPROCS] = {
- NFSV2PROC_NULL,
- NFSV2PROC_GETATTR,
- NFSV2PROC_SETATTR,
- NFSV2PROC_LOOKUP,
- NFSV2PROC_NOOP,
- NFSV2PROC_READLINK,
- NFSV2PROC_READ,
- NFSV2PROC_WRITE,
- NFSV2PROC_CREATE,
- NFSV2PROC_MKDIR,
- NFSV2PROC_SYMLINK,
- NFSV2PROC_CREATE,
- NFSV2PROC_REMOVE,
- NFSV2PROC_RMDIR,
- NFSV2PROC_RENAME,
- NFSV2PROC_LINK,
- NFSV2PROC_READDIR,
- NFSV2PROC_NOOP,
- NFSV2PROC_STATFS,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
-};
-
-#ifndef NFS_NOSERVER
-/*
- * Maps errno values to nfs error numbers.
- * Use NFSERR_IO as the catch all for ones not specifically defined in
- * RFC 1094.
- */
-static u_char nfsrv_v2errmap[ELAST] = {
- NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
- NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
- NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO /* << Last is 86 */
-};
-
-/*
- * Maps errno values to nfs error numbers.
- * Although it is not obvious whether or not NFS clients really care if
- * a returned error value is in the specified list for the procedure, the
- * safest thing to do is filter them appropriately. For Version 2, the
- * X/Open XNFS document is the only specification that defines error values
- * for each RPC (The RFC simply lists all possible error values for all RPCs),
- * so I have decided to not do this for Version 2.
- * The first entry is the default error return and the rest are the valid
- * errors for that RPC in increasing numeric order.
- */
-static short nfsv3err_null[] = {
- 0,
- 0,
-};
-
-static short nfsv3err_getattr[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_setattr[] = {
- NFSERR_IO,
- NFSERR_PERM,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOT_SYNC,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_lookup[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_access[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_read[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_NXIO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_write[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_FBIG,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_create[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_mkdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_symlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_mknod[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- NFSERR_BADTYPE,
- 0,
-};
-
-static short nfsv3err_remove[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_rmdir[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_rename[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_ISDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_link[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readdirplus[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_NOTSUPP,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_fsstat[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_fsinfo[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
+nfstype nfsv3_type[9] = {
+ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, NFFIFO, NFNON
};
-static short nfsv3err_pathconf[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_commit[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short *nfsrv_v3errmap[] = {
- nfsv3err_null,
- nfsv3err_getattr,
- nfsv3err_setattr,
- nfsv3err_lookup,
- nfsv3err_access,
- nfsv3err_readlink,
- nfsv3err_read,
- nfsv3err_write,
- nfsv3err_create,
- nfsv3err_mkdir,
- nfsv3err_symlink,
- nfsv3err_mknod,
- nfsv3err_remove,
- nfsv3err_rmdir,
- nfsv3err_rename,
- nfsv3err_link,
- nfsv3err_readdir,
- nfsv3err_readdirplus,
- nfsv3err_fsstat,
- nfsv3err_fsinfo,
- nfsv3err_pathconf,
- nfsv3err_commit,
-};
-
-#endif /* NFS_NOSERVER */
-
-extern struct nfsrtt nfsrtt;
-extern time_t nqnfsstarttime;
-extern int nqsrv_clockskew;
-extern int nqsrv_writeslack;
-extern int nqsrv_maxlease;
-extern struct nfsstats nfsstats;
-extern int nqnfs_piggy[NFS_NPROCS];
-extern nfstype nfsv2_type[9];
-extern nfstype nfsv3_type[9];
-extern struct nfsnodehashhead *nfsnodehashtbl;
-extern u_long nfsnodehash;
-
-struct nfssvc_args;
-extern int nfssvc(struct thread *, struct nfssvc_args *, int *);
-
-LIST_HEAD(nfsnodehashhead, nfsnode);
-
-int nfs_webnamei __P((struct nameidata *, struct vnode *, struct thread *));
-
u_quad_t
-nfs_curusec()
+nfs_curusec(void)
{
struct timeval tv;
-
+
getmicrotime(&tv);
return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
}
/*
- * Create the header for an rpc request packet
- * The hsiz is the size of the rest of the nfs request header.
- * (just used to decide if a cluster is a good idea)
- */
-struct mbuf *
-nfsm_reqh(vp, procid, hsiz, bposp)
- struct vnode *vp;
- u_long procid;
- int hsiz;
- caddr_t *bposp;
-{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- struct mbuf *mb2;
- struct nfsmount *nmp;
- int nqflag;
-
- MGET(mb, M_TRYWAIT, MT_DATA);
- if (hsiz >= MINCLSIZE)
- MCLGET(mb, M_TRYWAIT);
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
-
- /*
- * For NQNFS, add lease request.
- */
- if (vp) {
- nmp = VFSTONFS(vp->v_mount);
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nqflag = NQNFS_NEEDLEASE(vp, procid);
- if (nqflag) {
- nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nqflag);
- *tl = txdr_unsigned(nmp->nm_leaseterm);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- }
- /* Finally, return values */
- *bposp = bpos;
- return (mb);
-}
-
-/*
- * 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.
- * Returns the head of the mbuf list.
- */
-struct mbuf *
-nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
- verf_str, mrest, mrest_len, mbp, xidp)
- register struct ucred *cr;
- int nmflag;
- int procid;
- int auth_type;
- int auth_len;
- char *auth_str;
- int verf_len;
- char *verf_str;
- struct mbuf *mrest;
- int mrest_len;
- struct mbuf **mbp;
- u_int32_t *xidp;
-{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- register int i;
- struct mbuf *mreq, *mb2;
- int siz, grpsiz, authsiz;
-
- authsiz = nfsm_rndup(auth_len);
- MGETHDR(mb, M_TRYWAIT, MT_DATA);
- if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
- MCLGET(mb, M_TRYWAIT);
- } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
- MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
- } else {
- MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
- }
- mb->m_len = 0;
- mreq = mb;
- bpos = mtod(mb, caddr_t);
-
- /*
- * First the RPC header.
- */
- nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
-
- /* Get a pretty random xid to start with */
- if (!nfs_xid)
- nfs_xid = random();
- /*
- * Skip zero xid if it should ever happen.
- */
- if (++nfs_xid == 0)
- nfs_xid++;
-
- *tl++ = *xidp = txdr_unsigned(nfs_xid);
- *tl++ = rpc_call;
- *tl++ = rpc_vers;
- if (nmflag & NFSMNT_NQNFS) {
- *tl++ = txdr_unsigned(NQNFS_PROG);
- *tl++ = txdr_unsigned(NQNFS_VER3);
- } else {
- *tl++ = txdr_unsigned(NFS_PROG);
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(NFS_VER3);
- else
- *tl++ = txdr_unsigned(NFS_VER2);
- }
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(procid);
- else
- *tl++ = txdr_unsigned(nfsv2_procid[procid]);
-
- /*
- * And then the authorization cred.
- */
- *tl++ = txdr_unsigned(auth_type);
- *tl = txdr_unsigned(authsiz);
- switch (auth_type) {
- case RPCAUTH_UNIX:
- nfsm_build(tl, u_int32_t *, auth_len);
- *tl++ = 0; /* stamp ?? */
- *tl++ = 0; /* NULL hostname */
- *tl++ = txdr_unsigned(cr->cr_uid);
- *tl++ = txdr_unsigned(cr->cr_groups[0]);
- grpsiz = (auth_len >> 2) - 5;
- *tl++ = txdr_unsigned(grpsiz);
- for (i = 1; i <= grpsiz; i++)
- *tl++ = txdr_unsigned(cr->cr_groups[i]);
- break;
- case RPCAUTH_KERB4:
- siz = auth_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(auth_str, bpos, i);
- mb->m_len += i;
- auth_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- break;
- };
-
- /*
- * And the verifier...
- */
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (verf_str) {
- *tl++ = txdr_unsigned(RPCAUTH_KERB4);
- *tl = txdr_unsigned(verf_len);
- siz = verf_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(verf_str, bpos, i);
- mb->m_len += i;
- verf_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- } else {
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
- }
- mb->m_next = mrest;
- mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
- mreq->m_pkthdr.rcvif = (struct ifnet *)0;
- *mbp = mb;
- return (mreq);
-}
-
-/*
* copies mbuf chain to the uio scatter/gather list
*/
int
-nfsm_mbuftouio(mrep, uiop, siz, dpos)
- struct mbuf **mrep;
- register struct uio *uiop;
- int siz;
- caddr_t *dpos;
+nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
{
- register char *mbufcp, *uiocp;
- register int xfer, left, len;
- register struct mbuf *mp;
+ char *mbufcp, *uiocp;
+ int xfer, left, len;
+ struct mbuf *mp;
long uiosiz, rem;
int error = 0;
@@ -851,106 +162,17 @@ nfsm_mbuftouio(mrep, uiop, siz, dpos)
}
/*
- * copies a uio scatter/gather list to an mbuf chain.
- * NOTE: can ony handle iovcnt == 1
- */
-int
-nfsm_uiotombuf(uiop, mq, siz, bpos)
- register struct uio *uiop;
- struct mbuf **mq;
- int siz;
- caddr_t *bpos;
-{
- register char *uiocp;
- register struct mbuf *mp, *mp2;
- register int xfer, left, mlen;
- int uiosiz, clflg, rem;
- char *cp;
-
-#ifdef DIAGNOSTIC
- if (uiop->uio_iovcnt != 1)
- panic("nfsm_uiotombuf: iovcnt != 1");
-#endif
-
- if (siz > MLEN) /* or should it >= MCLBYTES ?? */
- clflg = 1;
- else
- clflg = 0;
- rem = nfsm_rndup(siz)-siz;
- mp = mp2 = *mq;
- while (siz > 0) {
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- mlen = M_TRAILINGSPACE(mp);
- if (mlen == 0) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- if (clflg)
- MCLGET(mp, M_TRYWAIT);
- mp->m_len = 0;
- mp2->m_next = mp;
- mp2 = mp;
- mlen = M_TRAILINGSPACE(mp);
- }
- xfer = (left > mlen) ? mlen : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
- copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- mp->m_len += xfer;
- left -= xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- siz -= uiosiz;
- }
- if (rem > 0) {
- if (rem > M_TRAILINGSPACE(mp)) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- mp->m_len = 0;
- mp2->m_next = mp;
- }
- cp = mtod(mp, caddr_t)+mp->m_len;
- for (left = 0; left < rem; left++)
- *cp++ = '\0';
- mp->m_len += rem;
- *bpos = cp;
- } else
- *bpos = mtod(mp, caddr_t)+mp->m_len;
- *mq = mp;
- return (0);
-}
-
-/*
* Help break down an mbuf chain by setting the first siz bytes contiguous
* pointed to by returned val.
* This is used by the macros nfsm_dissect and nfsm_dissecton for tough
* cases. (The macros use the vars. dpos and dpos2)
*/
int
-nfsm_disct(mdp, dposp, siz, left, cp2)
- struct mbuf **mdp;
- caddr_t *dposp;
- int siz;
- int left;
- caddr_t *cp2;
+nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
{
- register struct mbuf *mp, *mp2;
- register int siz2, xfer;
- register caddr_t ptr;
+ struct mbuf *mp, *mp2;
+ int siz2, xfer;
+ caddr_t ptr;
mp = *mdp;
while (left == 0) {
@@ -1004,14 +226,10 @@ nfsm_disct(mdp, dposp, siz, left, cp2)
* Advance the position in the mbuf chain.
*/
int
-nfs_adv(mdp, dposp, offs, left)
- struct mbuf **mdp;
- caddr_t *dposp;
- int offs;
- int left;
+nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
{
- register struct mbuf *m;
- register int s;
+ struct mbuf *m;
+ int s;
m = *mdp;
s = left;
@@ -1027,1217 +245,70 @@ nfs_adv(mdp, dposp, offs, left)
return (0);
}
-/*
- * Copy a string into mbufs for the hard cases...
- */
-int
-nfsm_strtmbuf(mb, bpos, cp, siz)
- struct mbuf **mb;
- char **bpos;
- const char *cp;
- long siz;
-{
- register struct mbuf *m1 = NULL, *m2;
- long left, xfer, len, tlen;
- u_int32_t *tl;
- int putsize;
-
- putsize = 1;
- m2 = *mb;
- left = M_TRAILINGSPACE(m2);
- if (left > 0) {
- tl = ((u_int32_t *)(*bpos));
- *tl++ = txdr_unsigned(siz);
- putsize = 0;
- left -= NFSX_UNSIGNED;
- m2->m_len += NFSX_UNSIGNED;
- if (left > 0) {
- bcopy(cp, (caddr_t) tl, left);
- siz -= left;
- cp += left;
- m2->m_len += left;
- left = 0;
- }
- }
- /* Loop around adding mbufs */
- while (siz > 0) {
- MGET(m1, M_TRYWAIT, MT_DATA);
- if (siz > MLEN)
- MCLGET(m1, M_TRYWAIT);
- m1->m_len = NFSMSIZ(m1);
- m2->m_next = m1;
- m2 = m1;
- tl = mtod(m1, u_int32_t *);
- tlen = 0;
- if (putsize) {
- *tl++ = txdr_unsigned(siz);
- m1->m_len -= NFSX_UNSIGNED;
- tlen = NFSX_UNSIGNED;
- putsize = 0;
- }
- if (siz < m1->m_len) {
- len = nfsm_rndup(siz);
- xfer = siz;
- if (xfer < len)
- *(tl+(xfer>>2)) = 0;
- } else {
- xfer = len = m1->m_len;
- }
- bcopy(cp, (caddr_t) tl, xfer);
- m1->m_len = len+tlen;
- siz -= xfer;
- cp += xfer;
- }
- *mb = m1;
- *bpos = mtod(m1, caddr_t)+m1->m_len;
- return (0);
-}
-
-/*
- * Called once to initialize data structures...
- */
-int
-nfs_init(vfsp)
- struct vfsconf *vfsp;
-{
- register int i;
-
- nfsmount_zone = zinit("NFSMOUNT", sizeof(struct nfsmount), 0, 0, 1);
-
- nfs_mount_type = vfsp->vfc_typenum;
- nfsrtt.pos = 0;
- rpc_vers = txdr_unsigned(RPC_VER2);
- rpc_call = txdr_unsigned(RPC_CALL);
- rpc_reply = txdr_unsigned(RPC_REPLY);
- 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);
- nfs_prog = txdr_unsigned(NFS_PROG);
- nqnfs_prog = txdr_unsigned(NQNFS_PROG);
- nfs_true = txdr_unsigned(TRUE);
- nfs_false = txdr_unsigned(FALSE);
- nfs_xdrneg1 = txdr_unsigned(-1);
- nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
- if (nfs_ticks < 1)
- nfs_ticks = 1;
- /* Ensure async daemons disabled */
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
- nfs_iodwant[i] = (struct proc *)0;
- nfs_iodmount[i] = (struct nfsmount *)0;
- }
- nfs_nhinit(); /* Init the nfsnode table */
-#ifndef NFS_NOSERVER
- nfsrv_init(0); /* Init server data structures */
- nfsrv_initcache(); /* Init the server request cache */
-#endif
-
- /*
- * Initialize the nqnfs server stuff.
- */
- if (nqnfsstarttime == 0) {
- nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
- + nqsrv_clockskew + nqsrv_writeslack;
- NQLOADNOVRAM(nqnfsstarttime);
- TAILQ_INIT(&nqtimerhead);
- nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
- }
-
- /*
- * Initialize reply list and start timer
- */
- TAILQ_INIT(&nfs_reqq);
-
- nfs_timer(0);
-
- /*
- * Set up lease_check and lease_updatetime so that other parts
- * of the system can call us, if we are loadable.
- */
-#ifndef NFS_NOSERVER
- nfs_prev_vop_lease_check = default_vnodeop_p[VOFFSET(vop_lease)];
- default_vnodeop_p[VOFFSET(vop_lease)] = (vop_t *)nqnfs_vop_lease_check;
-#endif
- nfs_prev_lease_updatetime = lease_updatetime;
- lease_updatetime = nfs_lease_updatetime;
- nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
- sysent[SYS_nfssvc].sy_narg = 2;
- nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call;
- sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc;
-
- nfs_pbuf_freecnt = nswbuf / 2 + 1;
-
- return (0);
-}
-
-int
-nfs_uninit(vfsp)
- struct vfsconf *vfsp;
-{
-
- untimeout(nfs_timer, (void *)NULL, nfs_timer_handle);
- nfs_mount_type = -1;
-#ifndef NFS_NOSERVER
- default_vnodeop_p[VOFFSET(vop_lease)] = nfs_prev_vop_lease_check;
-#endif
- lease_updatetime = nfs_prev_lease_updatetime;
- sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
- sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
- return (0);
-}
-
-/*
- * Attribute cache routines.
- * nfs_loadattrcache() - loads or updates the cache contents from attributes
- * that are on the mbuf list
- * nfs_getattrcache() - returns valid attributes if found in cache, returns
- * error otherwise
- */
-
-/*
- * Load the attribute cache (that lives in the nfsnode entry) with
- * the values on the mbuf list and
- * Iff vap not NULL
- * copy the attributes to *vaper
- */
-int
-nfs_loadattrcache(vpp, mdp, dposp, vaper, dontshrink)
- struct vnode **vpp;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vattr *vaper;
- int dontshrink;
-{
- register struct vnode *vp = *vpp;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
- register struct nfsnode *np;
- register int32_t t1;
- caddr_t cp2;
- int error = 0, rdev;
- struct mbuf *md;
- enum vtype vtyp;
- u_short vmode;
- struct timespec mtime;
- int v3 = NFS_ISV3(vp);
-
- md = *mdp;
- t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
- if ((error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)) != 0)
- return (error);
- fp = (struct nfs_fattr *)cp2;
- if (v3) {
- vtyp = nfsv3tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- rdev = makeudev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
- fxdr_unsigned(int, fp->fa3_rdev.specdata2));
- fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
- } else {
- vtyp = nfsv2tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- /*
- * XXX
- *
- * The duplicate information returned in fa_type and fa_mode
- * is an ambiguity in the NFS version 2 protocol.
- *
- * VREG should be taken literally as a regular file. If a
- * server intents to return some type information differently
- * in the upper bits of the mode field (e.g. for sockets, or
- * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
- * leave the examination of the mode bits even in the VREG
- * case to avoid breakage for bogus servers, but we make sure
- * that there are actually type bits set in the upper part of
- * fa_mode (and failing that, trust the va_type field).
- *
- * NFSv3 cleared the issue, and requires fa_mode to not
- * contain any type information (while also introduing sockets
- * and FIFOs for fa_type).
- */
- if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
- vtyp = IFTOVT(vmode);
- rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
- fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
-
- /*
- * Really ugly NFSv2 kludge.
- */
- if (vtyp == VCHR && rdev == 0xffffffff)
- vtyp = VFIFO;
- }
-
- /*
- * 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);
- if (vp->v_type != vtyp) {
- vp->v_type = vtyp;
- if (vp->v_type == VFIFO) {
- vp->v_op = fifo_nfsv2nodeop_p;
- }
- if (vp->v_type == VCHR || vp->v_type == VBLK) {
- vp->v_op = spec_nfsv2nodeop_p;
- vp = addaliasu(vp, rdev);
- np->n_vnode = vp;
- }
- np->n_mtime = mtime.tv_sec;
- }
- vap = &np->n_vattr;
- 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 (v3) {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_hyper(&fp->fa3_size);
- vap->va_blocksize = NFS_FABLKSIZE;
- vap->va_bytes = fxdr_hyper(&fp->fa3_used);
- vap->va_fileid = fxdr_unsigned(int32_t,
- fp->fa3_fileid.nfsuquad[1]);
- fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
- fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
- vap->va_flags = 0;
- vap->va_filerev = 0;
- } else {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
- vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
- vap->va_bytes = (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks)
- * NFS_FABLKSIZE;
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
- fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
- vap->va_flags = 0;
- vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
- fp->fa2_ctime.nfsv2_sec);
- vap->va_ctime.tv_nsec = 0;
- vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
- vap->va_filerev = 0;
- }
- np->n_attrstamp = time_second;
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (dontshrink && vap->va_size < np->n_size) {
- /*
- * We've been told not to shrink the file;
- * zero np->n_attrstamp to indicate that
- * the attributes are stale.
- */
- vap->va_size = np->n_size;
- np->n_attrstamp = 0;
- } else 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;
- }
- }
- 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;
- }
- }
- return (0);
-}
-
-#ifdef NFS_ACDEBUG
-#include <sys/sysctl.h>
-SYSCTL_DECL(_vfs_nfs);
-static int nfs_acdebug;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, acdebug, CTLFLAG_RW, &nfs_acdebug, 0, "");
-#endif
-
-/*
- * Check the time stamp
- * If the cache is valid, copy contents to *vap and return 0
- * otherwise return an error
- */
-int
-nfs_getattrcache(vp, vaper)
- register struct vnode *vp;
- struct vattr *vaper;
-{
- register struct nfsnode *np;
- register struct vattr *vap;
- struct nfsmount *nmp;
- int timeo;
-
- np = VTONFS(vp);
- vap = &np->n_vattr;
- nmp = VFSTONFS(vp->v_mount);
- /* XXX n_mtime doesn't seem to be updated on a miss-and-reload */
- timeo = (time_second - np->n_mtime) / 10;
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug>1)
- printf("nfs_getattrcache: initial timeo = %d\n", timeo);
-#endif
-
- if (vap->va_type == VDIR) {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acdirmin)
- timeo = nmp->nm_acdirmin;
- else if (timeo > nmp->nm_acdirmax)
- timeo = nmp->nm_acdirmax;
- } else {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acregmin)
- timeo = nmp->nm_acregmin;
- else if (timeo > nmp->nm_acregmax)
- timeo = nmp->nm_acregmax;
- }
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug > 2)
- printf("acregmin %d; acregmax %d; acdirmin %d; acdirmax %d\n",
- nmp->nm_acregmin, nmp->nm_acregmax,
- nmp->nm_acdirmin, nmp->nm_acdirmax);
-
- if (nfs_acdebug)
- printf("nfs_getattrcache: age = %d; final timeo = %d\n",
- (time_second - np->n_attrstamp), timeo);
-#endif
-
- if ((time_second - np->n_attrstamp) >= timeo) {
- nfsstats.attrcache_misses++;
- return (ENOENT);
- }
- nfsstats.attrcache_hits++;
- 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;
- }
- }
- bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
- 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;
- }
- return (0);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Set up nameidata for a lookup() call and do it.
- *
- * If pubflag is set, this call is done for a lookup operation on the
- * public filehandle. In that case we allow crossing mountpoints and
- * absolute pathnames. However, the caller is expected to check that
- * the lookup result is within the public fs, and deny access if
- * it is not.
- *
- * nfs_namei() clears out garbage fields that namei() might leave garbage.
- * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
- * error occurs but the parent was not requested.
- *
- * dirp may be set whether an error is returned or not, and must be
- * released by the caller.
- */
-int
-nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
- register struct nameidata *ndp;
- fhandle_t *fhp;
- int len;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vnode **retdirp;
- struct thread *td;
- int kerbflag, pubflag;
-{
- register int i, rem;
- register struct mbuf *md;
- register char *fromcp, *tocp, *cp;
- struct iovec aiov;
- struct uio auio;
- struct vnode *dp;
- int error, rdonly, linklen;
- struct componentname *cnp = &ndp->ni_cnd;
-
- *retdirp = (struct vnode *)0;
- cnp->cn_pnbuf = zalloc(namei_zone);
-
- /*
- * Copy the name from the mbuf list to ndp->ni_pnbuf
- * and set the various ndp fields appropriately.
- */
- fromcp = *dposp;
- tocp = cnp->cn_pnbuf;
- md = *mdp;
- rem = mtod(md, caddr_t) + md->m_len - fromcp;
- for (i = 0; i < len; i++) {
- while (rem == 0) {
- md = md->m_next;
- if (md == NULL) {
- error = EBADRPC;
- goto out;
- }
- fromcp = mtod(md, caddr_t);
- rem = md->m_len;
- }
- if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
- error = EACCES;
- goto out;
- }
- *tocp++ = *fromcp++;
- rem--;
- }
- *tocp = '\0';
- *mdp = md;
- *dposp = fromcp;
- len = nfsm_rndup(len)-len;
- if (len > 0) {
- if (rem >= len)
- *dposp += len;
- else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
- goto out;
- }
-
- /*
- * Extract and set starting directory.
- */
- error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly, kerbflag, pubflag);
- if (error)
- goto out;
- if (dp->v_type != VDIR) {
- vrele(dp);
- error = ENOTDIR;
- goto out;
- }
-
- if (rdonly)
- cnp->cn_flags |= RDONLY;
-
- /*
- * Set return directory. Reference to dp is implicitly transfered
- * to the returned pointer
- */
- *retdirp = dp;
-
- if (pubflag) {
- /*
- * Oh joy. For WebNFS, handle those pesky '%' escapes,
- * and the 'native path' indicator.
- */
- cp = zalloc(namei_zone);
- fromcp = cnp->cn_pnbuf;
- tocp = cp;
- if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
- switch ((unsigned char)*fromcp) {
- case WEBNFS_NATIVE_CHAR:
- /*
- * 'Native' path for us is the same
- * as a path according to the NFS spec,
- * just skip the escape char.
- */
- fromcp++;
- break;
- /*
- * More may be added in the future, range 0x80-0xff
- */
- default:
- error = EIO;
- zfree(namei_zone, cp);
- goto out;
- }
- }
- /*
- * Translate the '%' escapes, URL-style.
- */
- while (*fromcp != '\0') {
- if (*fromcp == WEBNFS_ESC_CHAR) {
- if (fromcp[1] != '\0' && fromcp[2] != '\0') {
- fromcp++;
- *tocp++ = HEXSTRTOI(fromcp);
- fromcp += 2;
- continue;
- } else {
- error = ENOENT;
- zfree(namei_zone, cp);
- goto out;
- }
- } else
- *tocp++ = *fromcp++;
- }
- *tocp = '\0';
- zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- }
-
- ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
- ndp->ni_segflg = UIO_SYSSPACE;
-
- if (pubflag) {
- ndp->ni_rootdir = rootvnode;
- ndp->ni_loopcnt = 0;
- if (cnp->cn_pnbuf[0] == '/')
- dp = rootvnode;
- } else {
- cnp->cn_flags |= NOCROSSMOUNT;
- }
-
- /*
- * Initialize for scan, set ni_startdir and bump ref on dp again
- * becuase lookup() will dereference ni_startdir.
- */
-
- cnp->cn_thread = td;
- VREF(dp);
- ndp->ni_startdir = dp;
-
- for (;;) {
- cnp->cn_nameptr = cnp->cn_pnbuf;
- /*
- * Call lookup() to do the real work. If an error occurs,
- * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
- * we do not have to dereference anything before returning.
- * In either case ni_startdir will be dereferenced and NULLed
- * out.
- */
- error = lookup(ndp);
- if (error)
- break;
-
- /*
- * Check for encountering a symbolic link. Trivial
- * termination occurs if no symlink encountered.
- * Note: zfree is safe because error is 0, so we will
- * not zfree it again when we break.
- */
- if ((cnp->cn_flags & ISSYMLINK) == 0) {
- nfsrv_object_create(ndp->ni_vp);
- if (cnp->cn_flags & (SAVENAME | SAVESTART))
- cnp->cn_flags |= HASBUF;
- else
- zfree(namei_zone, cnp->cn_pnbuf);
- break;
- }
-
- /*
- * Validate symlink
- */
- if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- VOP_UNLOCK(ndp->ni_dvp, 0, td);
- if (!pubflag) {
- error = EINVAL;
- goto badlink2;
- }
-
- if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
- error = ELOOP;
- goto badlink2;
- }
- if (ndp->ni_pathlen > 1)
- cp = zalloc(namei_zone);
- else
- cp = cnp->cn_pnbuf;
- aiov.iov_base = cp;
- aiov.iov_len = MAXPATHLEN;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_td = (struct thread *)0;
- auio.uio_resid = MAXPATHLEN;
- error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
- if (error) {
- badlink1:
- if (ndp->ni_pathlen > 1)
- zfree(namei_zone, cp);
- badlink2:
- vrele(ndp->ni_dvp);
- vput(ndp->ni_vp);
- break;
- }
- linklen = MAXPATHLEN - auio.uio_resid;
- if (linklen == 0) {
- error = ENOENT;
- goto badlink1;
- }
- if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
- error = ENAMETOOLONG;
- goto badlink1;
- }
-
- /*
- * Adjust or replace path
- */
- if (ndp->ni_pathlen > 1) {
- bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
- zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- } else
- cnp->cn_pnbuf[linklen] = '\0';
- ndp->ni_pathlen += linklen;
-
- /*
- * Cleanup refs for next loop and check if root directory
- * should replace current directory. Normally ni_dvp
- * becomes the new base directory and is cleaned up when
- * we loop. Explicitly null pointers after invalidation
- * to clarify operation.
- */
- vput(ndp->ni_vp);
- ndp->ni_vp = NULL;
-
- if (cnp->cn_pnbuf[0] == '/') {
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = ndp->ni_rootdir;
- VREF(ndp->ni_dvp);
- }
- ndp->ni_startdir = ndp->ni_dvp;
- ndp->ni_dvp = NULL;
- }
-
- /*
- * nfs_namei() guarentees that fields will not contain garbage
- * whether an error occurs or not. This allows the caller to track
- * cleanup state trivially.
- */
-out:
- if (error) {
- zfree(namei_zone, cnp->cn_pnbuf);
- ndp->ni_vp = NULL;
- ndp->ni_dvp = NULL;
- ndp->ni_startdir = NULL;
- cnp->cn_flags &= ~HASBUF;
- } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
- ndp->ni_dvp = NULL;
- }
- return (error);
-}
-
-/*
- * A fiddled version of m_adj() that ensures null fill to a long
- * boundary and only trims off the back end
- */
-void
-nfsm_adj(mp, len, nul)
- struct mbuf *mp;
- register int len;
- int nul;
-{
- register struct mbuf *m;
- register int count, i;
- register char *cp;
-
- /*
- * Trim from tail. Scan the mbuf chain,
- * calculating its length and finding the last mbuf.
- * If the adjustment only affects this mbuf, then just
- * adjust and return. Otherwise, rescan and truncate
- * after the remaining size.
- */
- count = 0;
- m = mp;
- for (;;) {
- count += m->m_len;
- if (m->m_next == (struct mbuf *)0)
- break;
- m = m->m_next;
- }
- if (m->m_len > len) {
- m->m_len -= len;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- return;
- }
- count -= len;
- if (count < 0)
- count = 0;
- /*
- * Correct length for chain is "count".
- * Find the mbuf with last data, adjust its length,
- * and toss data from remaining mbufs on chain.
- */
- for (m = mp; m; m = m->m_next) {
- if (m->m_len >= count) {
- m->m_len = count;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- break;
- }
- count -= m->m_len;
- }
- for (m = m->m_next;m;m = m->m_next)
- m->m_len = 0;
-}
-
-/*
- * Make these functions instead of macros, so that the kernel text size
- * doesn't get too big...
- */
-void
-nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int before_ret;
- register struct vattr *before_vap;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
-{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
-
- if (before_ret) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- txdr_hyper(before_vap->va_size, tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_mtime), tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_ctime), tl);
- }
- *bposp = bpos;
- *mbp = mb;
- nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
-}
-
-void
-nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
-{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
- register struct nfs_fattr *fp;
-
- if (after_ret) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
- *tl++ = nfs_true;
- fp = (struct nfs_fattr *)tl;
- nfsm_srvfattr(nfsd, after_vap, fp);
- }
- *mbp = mb;
- *bposp = bpos;
-}
-
void
-nfsm_srvfattr(nfsd, vap, fp)
- register struct nfsrv_descript *nfsd;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
+nfsm_build_xx(void **a, int s, struct mbuf **mb, caddr_t *bpos)
{
+ struct mbuf *mb2;
- fp->fa_nlink = txdr_unsigned(vap->va_nlink);
- fp->fa_uid = txdr_unsigned(vap->va_uid);
- fp->fa_gid = txdr_unsigned(vap->va_gid);
- if (nfsd->nd_flag & ND_NFSV3) {
- fp->fa_type = vtonfsv3_type(vap->va_type);
- fp->fa_mode = vtonfsv3_mode(vap->va_mode);
- txdr_hyper(vap->va_size, &fp->fa3_size);
- txdr_hyper(vap->va_bytes, &fp->fa3_used);
- fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev));
- fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev));
- fp->fa3_fsid.nfsuquad[0] = 0;
- fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
- fp->fa3_fileid.nfsuquad[0] = 0;
- fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
- txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
- txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
- txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
- } else {
- fp->fa_type = vtonfsv2_type(vap->va_type);
- fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- fp->fa2_size = txdr_unsigned(vap->va_size);
- fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
- if (vap->va_type == VFIFO)
- fp->fa2_rdev = 0xffffffff;
- else
- fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
- fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
- fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
- fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
- txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
- txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
- txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
- }
-}
-
-/*
- * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
- * - look up fsid in mount list (if not found ret error)
- * - get vp and export rights by calling VFS_FHTOVP()
- * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
- * - if not lockflag unlock it with VOP_UNLOCK()
- */
-int
-nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
- fhandle_t *fhp;
- int lockflag;
- struct vnode **vpp;
- struct ucred *cred;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- int *rdonlyp;
- int kerbflag;
- int pubflag;
-{
- struct thread *td = curthread; /* XXX */
- register struct mount *mp;
- register int i;
- struct ucred *credanon;
- int error, exflags;
-#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
- struct sockaddr_int *saddr;
-#endif
-
- *vpp = (struct vnode *)0;
-
- if (nfs_ispublicfh(fhp)) {
- if (!pubflag || !nfs_pub.np_valid)
- return (ESTALE);
- fhp = &nfs_pub.np_handle;
- }
-
- mp = vfs_getvfs(&fhp->fh_fsid);
- if (!mp)
- return (ESTALE);
- error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
- if (error)
- return (error);
- error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
- if (error)
- return (error);
-#ifdef MNT_EXNORESPORT
- if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
- saddr = (struct sockaddr_in *)nam;
- if (saddr->sin_family == AF_INET &&
- ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- }
-#endif
- /*
- * Check/setup credentials.
- */
- if (exflags & MNT_EXKERB) {
- if (!kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- } else if (kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
- cred->cr_uid = credanon->cr_uid;
- for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
- cred->cr_groups[i] = credanon->cr_groups[i];
- cred->cr_ngroups = i;
- }
- if (exflags & MNT_EXRDONLY)
- *rdonlyp = 1;
- else
- *rdonlyp = 0;
-
- nfsrv_object_create(*vpp);
-
- if (!lockflag)
- VOP_UNLOCK(*vpp, 0, td);
- return (0);
+ if (s > M_TRAILINGSPACE(*mb)) {
+ MGET(mb2, M_TRYWAIT, MT_DATA);
+ if (s > MLEN)
+ panic("build > MLEN");
+ (*mb)->m_next = mb2;
+ *mb = mb2;
+ (*mb)->m_len = 0;
+ *bpos = mtod(*mb, caddr_t);
+ }
+ *a = *bpos;
+ (*mb)->m_len += s;
+ *bpos += s;
}
-
-/*
- * WebNFS: check if a filehandle is a public filehandle. For v3, this
- * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
- * transformed this to all zeroes in both cases, so check for it.
- */
-int
-nfs_ispublicfh(fhp)
- fhandle_t *fhp;
-{
- char *cp = (char *)fhp;
- int i;
-
- for (i = 0; i < NFSX_V3FH; i++)
- if (*cp++ != 0)
- return (FALSE);
- return (TRUE);
-}
-
-#endif /* NFS_NOSERVER */
-/*
- * This function compares two net addresses by family and returns TRUE
- * if they are the same host.
- * If there is any doubt, return FALSE.
- * The AF_INET family is handled as a special case so that address mbufs
- * don't need to be saved to store "struct in_addr", which is only 4 bytes.
- */
int
-netaddr_match(family, haddr, nam)
- int family;
- union nethostaddr *haddr;
- struct sockaddr *nam;
-{
- register struct sockaddr_in *inetaddr;
-
- switch (family) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *)nam;
- if (inetaddr->sin_family == AF_INET &&
- inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
- return (1);
- break;
- default:
- break;
- };
- return (0);
-}
-
-static nfsuint64 nfs_nullcookie = { { 0, 0 } };
-/*
- * This function finds the directory cookie that corresponds to the
- * logical byte offset given.
- */
-nfsuint64 *
-nfs_getcookie(np, off, add)
- register struct nfsnode *np;
- off_t off;
- int add;
-{
- register struct nfsdmap *dp, *dp2;
- register 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 = np->n_cookies.lh_first;
- if (!dp) {
- if (add) {
- MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp->ndm_eocookie = 0;
- LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
- } else
- return ((nfsuint64 *)0);
- }
- while (pos >= NFSNUMCOOKIES) {
- pos -= NFSNUMCOOKIES;
- if (dp->ndm_list.le_next) {
- if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
- pos >= dp->ndm_eocookie)
- return ((nfsuint64 *)0);
- dp = dp->ndm_list.le_next;
- } else if (add) {
- MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp2->ndm_eocookie = 0;
- LIST_INSERT_AFTER(dp, dp2, ndm_list);
- dp = dp2;
- } else
- return ((nfsuint64 *)0);
- }
- if (pos >= dp->ndm_eocookie) {
- if (add)
- dp->ndm_eocookie = pos + 1;
- else
- return ((nfsuint64 *)0);
- }
- return (&dp->ndm_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
-nfs_invaldir(vp)
- register struct vnode *vp;
+nfsm_dissect_xx(void **a, int s, struct mbuf **md, caddr_t *dpos)
{
- register struct nfsnode *np = VTONFS(vp);
-
-#ifdef DIAGNOSTIC
- if (vp->v_type != VDIR)
- panic("nfs: invaldir not dir");
-#endif
- np->n_direofoffset = 0;
- np->n_cookieverf.nfsuquad[0] = 0;
- np->n_cookieverf.nfsuquad[1] = 0;
- if (np->n_cookies.lh_first)
- np->n_cookies.lh_first->ndm_eocookie = 0;
+ int t1;
+ char *cp2;
+
+ t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos;
+ if (t1 >= s) {
+ *a = *dpos;
+ *dpos += s;
+ return 0;
+ }
+ t1 = nfsm_disct(md, dpos, s, t1, &cp2);
+ if (t1 != 0)
+ return t1;
+ *a = cp2;
+ return 0;
}
-/*
- * The write verifier has changed (probably due to a server reboot), so all
- * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
- * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
- * and B_CLUSTEROK flags. Once done the new write verifier can be set for the
- * mount point.
- *
- * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data
- * writes are not clusterable.
- */
-void
-nfs_clearcommit(mp)
- struct mount *mp;
-{
- register struct vnode *vp, *nvp;
- register struct buf *bp, *nbp;
- int s;
-
- GIANT_REQUIRED;
-
- s = splbio();
- mtx_lock(&mntvnode_mtx);
-loop:
- for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
- if (vp->v_mount != mp) /* Paranoia */
- goto loop;
- nvp = LIST_NEXT(vp, v_mntvnodes);
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if (BUF_REFCNT(bp) == 0 &&
- (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
- == (B_DELWRI | B_NEEDCOMMIT))
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- }
- }
- mtx_unlock(&mntvnode_mtx);
- splx(s);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Map errnos to NFS error numbers. For Version 3 also filter out error
- * numbers not specified for the associated procedure.
- */
int
-nfsrv_errmap(nd, err)
- struct nfsrv_descript *nd;
- register int err;
+nfsm_strsiz_xx(int *s, int m, u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
{
- register short *defaulterrp, *errp;
-
- if (nd->nd_flag & ND_NFSV3) {
- if (nd->nd_procnum <= NFSPROC_COMMIT) {
- errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
- while (*++errp) {
- if (*errp == err)
- return (err);
- else if (*errp > err)
- break;
- }
- return ((int)*defaulterrp);
- } else
- return (err & 0xffff);
- }
- if (err <= ELAST)
- return ((int)nfsrv_v2errmap[err - 1]);
- return (NFSERR_IO);
+ int ret;
+
+ ret = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ if (ret)
+ return ret;
+ *s = fxdr_unsigned(int32_t, **tl);
+ if (*s > m)
+ return EBADRPC;
+ return 0;
}
int
-nfsrv_object_create(vp)
- struct vnode *vp;
+nfsm_adv_xx(int s, u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
{
+ int t1;
- if (vp == NULL || vp->v_type != VREG)
- return (1);
- return (vfs_object_create(vp, curthread,
- curthread ? curthread->td_proc->p_ucred : NULL));
-}
-
-/*
- * Sort the group list in increasing numerical order.
- * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
- * that used to be here.)
- */
-void
-nfsrvw_sort(list, num)
- register gid_t *list;
- register int num;
-{
- register int i, j;
- gid_t v;
-
- /* Insertion sort. */
- for (i = 1; i < num; i++) {
- v = list[i];
- /* find correct slot for value v, moving others up */
- for (j = i; --j >= 0 && v < list[j];)
- list[j + 1] = list[j];
- list[j + 1] = v;
+ t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos;
+ if (t1 > s) {
+ *dpos += s;
+ return 0;
}
+ t1 = nfs_adv(md, dpos, s, t1);
+ if (t1)
+ return t1;
+ return 0;
}
-
-/*
- * copy credentials making sure that the result can be compared with bcmp().
- */
-void
-nfsrv_setcred(incred, outcred)
- register struct ucred *incred, *outcred;
-{
- register int i;
-
- bzero((caddr_t)outcred, sizeof (struct ucred));
- outcred->cr_ref = 1;
- outcred->cr_uid = incred->cr_uid;
- outcred->cr_ngroups = incred->cr_ngroups;
- for (i = 0; i < incred->cr_ngroups; i++)
- outcred->cr_groups[i] = incred->cr_groups[i];
- nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
-}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfs/nfs_common.h b/sys/nfs/nfs_common.h
index d58ef15..825ab35 100644
--- a/sys/nfs/nfs_common.h
+++ b/sys/nfs/nfs_common.h
@@ -38,527 +38,86 @@
*/
-#ifndef _NFS_NFSM_SUBS_H_
-#define _NFS_NFSM_SUBS_H_
+#ifndef _NFS_NFS_COMMON_H_
+#define _NFS_NFS_COMMON_H_
-struct ucred;
-struct vnode;
+extern enum vtype nv3tov_type[];
+extern nfstype nfsv3_type[];
-/*
- * These macros do strange and peculiar things to mbuf chains for
- * the assistance of the nfs code. To attempt to use them for any
- * other purpose will be dangerous. (they make weird assumptions)
- */
+#define vtonfsv2_mode(t, m) \
+ txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : MAKEIMODE((t), (m)))
-/*
- * First define what the actual subs. return
- */
-struct mbuf *nfsm_reqh __P((struct vnode *vp, u_long procid, int hsiz,
- caddr_t *bposp));
-struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
- int auth_type, int auth_len, char *auth_str,
- int verf_len, char *verf_str,
- struct mbuf *mrest, int mrest_len,
- struct mbuf **mbp, u_int32_t *xidp));
+#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_int32_t,(a))&0x7]
+#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
-#define M_HASCL(m) ((m)->m_flags & M_EXT)
-#define NFSMINOFF(m) \
- do { \
- if (M_HASCL(m)) \
- (m)->m_data = (m)->m_ext.ext_buf; \
- else if ((m)->m_flags & M_PKTHDR) \
- (m)->m_data = (m)->m_pktdat; \
- else \
- (m)->m_data = (m)->m_dat; \
- } while (0)
-#define NFSMADV(m, s) \
+#define NFSMADV(m, s) \
do { \
(m)->m_data += (s); \
} while (0)
-#define NFSMSIZ(m) ((M_HASCL(m))?MCLBYTES: \
- (((m)->m_flags & M_PKTHDR)?MHLEN:MLEN))
-
-/*
- * Now for the macros that do the simple stuff and call the functions
- * for the hard stuff.
- * These macros use several vars. declared in nfsm_reqhead and these
- * vars. must not be used elsewhere unless you are careful not to corrupt
- * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries
- * that may be used so long as the value is not expected to retained
- * after a macro.
- * I know, this is kind of dorkey, but it makes the actual op functions
- * fairly clean and deals with the mess caused by the xdr discriminating
- * unions.
- */
-
-#define nfsm_build(a,c,s) \
- do { \
- if ((s) > M_TRAILINGSPACE(mb)) { \
- MGET(mb2, M_TRYWAIT, MT_DATA); \
- if ((s) > MLEN) \
- panic("build > MLEN"); \
- mb->m_next = mb2; \
- mb = mb2; \
- mb->m_len = 0; \
- bpos = mtod(mb, caddr_t); \
- } \
- (a) = (c)(bpos); \
- mb->m_len += (s); \
- bpos += (s); \
- } while (0)
-
-#define nfsm_dissect(a, c, s) \
- do { \
- t1 = mtod(md, caddr_t)+md->m_len-dpos; \
- if (t1 >= (s)) { \
- (a) = (c)(dpos); \
- dpos += (s); \
- } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } else { \
- (a) = (c)cp2; \
- } \
- } while (0)
-
-#define nfsm_fhtom(v, v3) \
- do { \
- if (v3) { \
- t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
- if (t2 <= M_TRAILINGSPACE(mb)) { \
- nfsm_build(tl, u_int32_t *, t2); \
- *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
- *(tl + ((t2>>2) - 2)) = 0; \
- bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
- VTONFS(v)->n_fhsize); \
- } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \
- (caddr_t)VTONFS(v)->n_fhp, \
- VTONFS(v)->n_fhsize)) != 0) { \
- error = t2; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } else { \
- nfsm_build(cp, caddr_t, NFSX_V2FH); \
- bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
- } \
- } while (0)
-
-#define nfsm_srvfhtom(f, v3) \
- do { \
- if (v3) { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH);\
- *tl++ = txdr_unsigned(NFSX_V3FH); \
- bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
- } else { \
- nfsm_build(cp, caddr_t, NFSX_V2FH); \
- bcopy((caddr_t)(f), cp, NFSX_V2FH); \
- } \
- } while (0)
-
-#define nfsm_srvpostop_fh(f) \
- do { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
- *tl++ = nfs_true; \
- *tl++ = txdr_unsigned(NFSX_V3FH); \
- bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
- } while (0)
-
-#define nfsm_mtofh(d, v, v3, f) \
- do { \
- struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (f) = fxdr_unsigned(int, *tl); \
- } else \
- (f) = 1; \
- if (f) { \
- nfsm_getfh(ttfhp, ttfhsize, (v3)); \
- if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
- &ttnp)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = NFSTOV(ttnp); \
- } \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (f) \
- (f) = fxdr_unsigned(int, *tl); \
- else if (fxdr_unsigned(int, *tl)) \
- nfsm_adv(NFSX_V3FATTR); \
- } \
- if (f) \
- nfsm_loadattr((v), (struct vattr *)0); \
- } while (0)
-
-#define nfsm_getfh(f, s, v3) \
- do { \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
- (s) > NFSX_V3FHMAX) { \
- m_freem(mrep); \
- error = EBADRPC; \
- goto nfsmout; \
- } \
- } else \
- (s) = NFSX_V2FH; \
- nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); \
- } while (0)
-
-#define nfsm_loadattr(v, a) \
- do { \
- struct vnode *ttvp = (v); \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = ttvp; \
- } while (0)
-#define nfsm_postop_attr(v, f) \
- do { \
- struct vnode *ttvp = (v); \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (((f) = fxdr_unsigned(int, *tl)) != 0) { \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
- (struct vattr *)0, 1)) != 0) { \
- error = t1; \
- (f) = 0; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = ttvp; \
- } \
- } while (0)
+int nfs_adv(struct mbuf **, caddr_t *, int, int);
+void nfsm_build_xx(void **a, int s, struct mbuf **mb, caddr_t *bpos);
+int nfsm_dissect_xx(void **a, int s, struct mbuf **md, caddr_t *dpos);
+int nfsm_strsiz_xx(int *s, int m, u_int32_t **tl, struct mbuf **mb,
+ caddr_t *bpos);
+int nfsm_adv_xx(int s, u_int32_t **tl, struct mbuf **md, caddr_t *dpos);
+u_quad_t nfs_curusec(void);
+int nfsm_disct(struct mbuf **, caddr_t *, int, int, caddr_t *);
-/* Used as (f) for nfsm_wcc_data() */
-#define NFSV3_WCCRATTR 0
-#define NFSV3_WCCCHK 1
+#define nfsm_build(a, c, s) \
+do { \
+ nfsm_build_xx((void **)&(a), (s), &mb, &bpos); \
+} while (0)
-#define nfsm_wcc_data(v, f) \
- do { \
- int ttattrf, ttretf = 0; \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \
- if (f) \
- ttretf = (VTONFS(v)->n_mtime == \
- fxdr_unsigned(u_int32_t, *(tl + 2))); \
- } \
- nfsm_postop_attr((v), ttattrf); \
- if (f) { \
- (f) = ttretf; \
- } else { \
- (f) = ttattrf; \
- } \
- } while (0)
-/* If full is true, set all fields, otherwise just set mode and time fields */
-#define nfsm_v3attrbuild(a, full) \
- do { \
- if ((a)->va_mode != (mode_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_mode); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_uid); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_gid); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_size != VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- txdr_hyper((a)->va_size, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((a)->va_atime.tv_sec != VNOVAL) { \
- if ((a)->va_atime.tv_sec != time_second) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
- txdr_nfsv3time(&(a)->va_atime, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
- } \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
- } \
- if ((a)->va_mtime.tv_sec != VNOVAL) { \
- if ((a)->va_mtime.tv_sec != time_second) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
- txdr_nfsv3time(&(a)->va_mtime, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
- } \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
- } \
- } while (0)
-
+/* XXX 'c' arg (type) is not used */
+#define nfsm_dissect(a, c, s) \
+do { \
+ int t1; \
+ t1 = nfsm_dissect_xx((void **)&(a), (s), &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mrep); \
+ mrep = NULL; \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_strsiz(s,m) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \
- m_freem(mrep); \
- error = EBADRPC; \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvstrsiz(s,m) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \
- error = EBADRPC; \
- nfsm_reply(0); \
- } \
- } while (0)
-
-#define nfsm_srvnamesiz(s) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \
- error = NFSERR_NAMETOL; \
- if ((s) <= 0) \
- error = EBADRPC; \
- if (error) \
- nfsm_reply(0); \
- } while (0)
+do { \
+ int t1; \
+ t1 = nfsm_strsiz_xx(&(s), (m), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mrep); \
+ mrep = NULL; \
+ goto nfsmout; \
+ } \
+} while(0)
#define nfsm_mtouio(p,s) \
- do {\
- if ((s) > 0 && \
- (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_uiotom(p,s) \
- do { \
- if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \
- error = t1; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_reqhead(v,a,s) \
- do { \
- mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \
- } while (0)
-
-#define nfsm_reqdone \
- do { \
+do {\
+ int32_t t1; \
+ if ((s) > 0 && (t1 = nfsm_mbuftouio(&md, (p), (s), &dpos)) != 0) { \
+ error = t1; \
m_freem(mrep); \
- nfsmout: \
- } while (0)
+ mrep = NULL; \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_rndup(a) (((a)+3)&(~0x3))
-#define nfsm_request(v, t, p, c) \
- do { \
- if ((error = nfs_request((v), mreq, (t), (p), \
- (c), &mrep, &md, &dpos)) != 0) { \
- if (error & NFSERR_RETERR) \
- error &= ~NFSERR_RETERR; \
- else \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_strtom(a,s,m) \
- do {\
- if ((s) > (m)) { \
- m_freem(mreq); \
- error = ENAMETOOLONG; \
- goto nfsmout; \
- } \
- t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
- if (t2 <= M_TRAILINGSPACE(mb)) { \
- nfsm_build(tl,u_int32_t *,t2); \
- *tl++ = txdr_unsigned(s); \
- *(tl+((t2>>2)-2)) = 0; \
- bcopy((const char *)(a), (caddr_t)tl, (s)); \
- } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \
- error = t2; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvdone \
- do { \
- nfsmout: \
- return (error); \
- } while (0)
-
-#define nfsm_reply(s) \
- do { \
- nfsd->nd_repstat = error; \
- if (error && !(nfsd->nd_flag & ND_NFSV3)) \
- (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
- mrq, &mb, &bpos); \
- else \
- (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
- mrq, &mb, &bpos); \
- if (mrep != NULL) { \
- m_freem(mrep); \
- mrep = NULL; \
- } \
- mreq = *mrq; \
- if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
- error == EBADRPC)) { \
- error = 0; \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_writereply(s, v3) \
- do { \
- nfsd->nd_repstat = error; \
- if (error && !(v3)) \
- (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
- &mreq, &mb, &bpos); \
- else \
- (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
- &mreq, &mb, &bpos); \
- } while (0)
-
#define nfsm_adv(s) \
- do { \
- t1 = mtod(md, caddr_t)+md->m_len-dpos; \
- if (t1 >= (s)) { \
- dpos += (s); \
- } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvmtofh(f) \
- do { \
- int fhlen; \
- if (nfsd->nd_flag & ND_NFSV3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- fhlen = fxdr_unsigned(int, *tl); \
- if (fhlen != 0 && fhlen != NFSX_V3FH) { \
- error = EBADRPC; \
- nfsm_reply(0); \
- } \
- } else { \
- fhlen = NFSX_V2FH; \
- } \
- if (fhlen != 0) { \
- nfsm_dissect(tl, u_int32_t *, fhlen); \
- bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \
- } else {\
- bzero((caddr_t)(f), NFSX_V3FH); \
- } \
- } while (0)
-
-#define nfsm_clget \
- do { \
- if (bp >= be) { \
- if (mp == mb) \
- mp->m_len += bp-bpos; \
- MGET(mp, M_TRYWAIT, MT_DATA); \
- MCLGET(mp, M_TRYWAIT); \
- mp->m_len = NFSMSIZ(mp); \
- mp2->m_next = mp; \
- mp2 = mp; \
- bp = mtod(mp, caddr_t); \
- be = bp+mp->m_len; \
- } \
- tl = (u_int32_t *)bp; \
- } while (0)
-
-#define nfsm_srvfillattr(a, f) \
- do { \
- nfsm_srvfattr(nfsd, (a), (f)); \
- } while (0)
-
-#define nfsm_srvwcc_data(br, b, ar, a) \
- do { \
- nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
- } while (0)
-
-#define nfsm_srvpostop_attr(r, a) \
- do { \
- nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
- } while (0)
-
-#define nfsm_srvsattr(a) \
- do { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_mode = nfstov_mode(*tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_uid = fxdr_unsigned(uid_t, *tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_gid = fxdr_unsigned(gid_t, *tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- (a)->va_size = fxdr_hyper(tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- switch (fxdr_unsigned(int, *tl)) { \
- case NFSV3SATTRTIME_TOCLIENT: \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- fxdr_nfsv3time(tl, &(a)->va_atime); \
- break; \
- case NFSV3SATTRTIME_TOSERVER: \
- getnanotime(&(a)->va_atime); \
- break; \
- }; \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- switch (fxdr_unsigned(int, *tl)) { \
- case NFSV3SATTRTIME_TOCLIENT: \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- fxdr_nfsv3time(tl, &(a)->va_mtime); \
- break; \
- case NFSV3SATTRTIME_TOSERVER: \
- getnanotime(&(a)->va_mtime); \
- break; \
- } \
- } while (0)
+do { \
+ int t1; \
+ t1 = nfsm_adv_xx((s), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mrep); \
+ mrep = NULL; \
+ goto nfsmout; \
+ } \
+} while (0)
#endif
diff --git a/sys/nfs/nfs_lock.c b/sys/nfs/nfs_lock.c
deleted file mode 100644
index b97b3b8..0000000
--- a/sys/nfs/nfs_lock.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*-
- * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
- *
- * 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. Berkeley Software Design Inc's name may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``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 BERKELEY SOFTWARE DESIGN INC 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.
- *
- * from BSDI nfs_lock.c,v 2.4 1998/12/14 23:49:56 jch Exp
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fcntl.h>
-#include <sys/kernel.h> /* for hz */
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/lockf.h> /* for hz */ /* Must come after sys/malloc.h */
-#include <sys/mbuf.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/socket.h>
-#include <sys/socket.h>
-#include <sys/unistd.h>
-#include <sys/vnode.h>
-
-#include <machine/limits.h>
-
-#include <net/if.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfs_lock.h>
-#include <nfs/nlminfo.h>
-
-#define NFSOWNER_1ST_LEVEL_START 1 /* initial entries */
-#define NFSOWNER_2ND_LEVEL 256 /* some power of 2 */
-
-#define NFSOWNER(tbl, i) \
- (tbl)[(i) / NFSOWNER_2ND_LEVEL][(i) % NFSOWNER_2ND_LEVEL]
-
-/*
- * XXX
- * We have to let the process know if the call succeeded. I'm using an extra
- * field in the p_nlminfo field in the proc structure, as it is already for
- * lockd stuff.
- */
-
-/*
- * nfs_advlock --
- * NFS advisory byte-level locks.
- */
-int
-nfs_dolock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
-{
- LOCKD_MSG msg;
- struct nameidata nd;
- struct thread *td;
- uid_t saved_uid;
- struct vnode *vp, *wvp;
- int error, error1;
- struct flock *fl;
- int fmode, ioflg;
- struct proc *p;
-
- td = curthread;
- p = td->td_proc;
-
- vp = ap->a_vp;
- fl = ap->a_fl;
-
- /*
- * the NLM protocol doesn't allow the server to return an error
- * on ranges, so we do it.
- */
- if (fl->l_whence != SEEK_END) {
- if ((fl->l_whence != SEEK_CUR && fl->l_whence != SEEK_SET) ||
- fl->l_start < 0 ||
- (fl->l_len < 0 &&
- (fl->l_start == 0 || fl->l_start + fl->l_len < 0)))
- return (EINVAL);
- if (fl->l_len > 0 &&
- (fl->l_len - 1 > OFF_MAX - fl->l_start))
- return (EOVERFLOW);
- }
-
- /*
- * Fill in the information structure.
- */
- msg.lm_version = LOCKD_MSG_VERSION;
- msg.lm_msg_ident.pid = p->p_pid;
- /*
- * if there is no nfsowner table yet, allocate one.
- */
- if (p->p_nlminfo == NULL) {
- MALLOC(p->p_nlminfo, struct nlminfo *,
- sizeof(struct nlminfo), M_LOCKF, M_WAITOK | M_ZERO);
- p->p_nlminfo->pid_start = p->p_stats->p_start;
- }
- msg.lm_msg_ident.pid_start = p->p_nlminfo->pid_start;
- msg.lm_msg_ident.msg_seq = ++(p->p_nlminfo->msg_seq);
-
- msg.lm_fl = *fl;
- msg.lm_wait = ap->a_flags & F_WAIT;
- msg.lm_getlk = ap->a_op == F_GETLK;
- /*
- * XXX -- I think this is wrong for anything other AF_INET.
- */
- msg.lm_addr = *(VFSTONFS(vp->v_mount)->nm_nam);
- msg.lm_fh_len = NFS_ISV3(vp) ? VTONFS(vp)->n_fhsize : NFSX_V2FH;
- bcopy(VTONFS(vp)->n_fhp, msg.lm_fh, msg.lm_fh_len);
- msg.lm_nfsv3 = NFS_ISV3(vp);
- msg.lm_cred = *(p->p_ucred);
-
- /*
- * Open the lock fifo. If for any reason we don't find the fifo, it
- * means that the lock daemon isn't running. Translate any missing
- * file error message for the user, otherwise the application will
- * complain that the user's file is missing, which isn't the case.
- * Note that we use proc0's cred, so the fifo is opened as root.
- */
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, _PATH_LCKFIFO, td);
-
- /*
- * XXX Hack to temporarily allow this process (regardless of it's creds)
- * to open the fifo we need to write to. vn_open() really should
- * take a ucred (and once it does, this code should be fixed to use
- * proc0's ucred.
- */
- saved_uid = p->p_ucred->cr_uid;
- p->p_ucred->cr_uid = 0; /* temporarly run the vn_open as root */
-
- fmode = FFLAGS(O_WRONLY);
- error = vn_open(&nd, &fmode, 0);
- p->p_ucred->cr_uid = saved_uid;
- if (error != 0) {
- return (error == ENOENT ? EOPNOTSUPP : error);
- }
- wvp = nd.ni_vp;
- VOP_UNLOCK(wvp, 0, td); /* vn_open leaves it locked */
-
-
- ioflg = IO_UNIT;
- for (;;) {
- VOP_LEASE(wvp, td, proc0.p_ucred, LEASE_WRITE);
-
- error = vn_rdwr(UIO_WRITE, wvp, (caddr_t)&msg, sizeof(msg), 0,
- UIO_SYSSPACE, ioflg, proc0.p_ucred, NULL, td);
-
- if (error && (((ioflg & IO_NDELAY) == 0) || error != EAGAIN)) {
- break;
- }
- /*
- * If we're locking a file, wait for an answer. Unlocks succeed
- * immediately.
- */
- if (fl->l_type == F_UNLCK)
- /*
- * XXX this isn't exactly correct. The client side
- * needs to continue sending it's unlock until
- * it gets a responce back.
- */
- break;
-
- /*
- * retry after 20 seconds if we haven't gotten a responce yet.
- * This number was picked out of thin air... but is longer
- * then even a reasonably loaded system should take (at least
- * on a local network). XXX Probably should use a back-off
- * scheme.
- */
- if ((error = tsleep((void *)p->p_nlminfo,
- PCATCH | PUSER, "lockd", 20*hz)) != 0) {
- if (error == EWOULDBLOCK) {
- /*
- * We timed out, so we rewrite the request
- * to the fifo, but only if it isn't already
- * full.
- */
- ioflg |= IO_NDELAY;
- continue;
- }
-
- break;
- }
-
- if (msg.lm_getlk && p->p_nlminfo->retcode == 0) {
- if (p->p_nlminfo->set_getlk_pid) {
- fl->l_pid = p->p_nlminfo->getlk_pid;
- } else {
- fl->l_type = F_UNLCK;
- }
- }
- error = p->p_nlminfo->retcode;
- break;
- }
-
- if ((error1 = vn_close(wvp, FWRITE, proc0.p_ucred, td)) && error == 0)
- return (error1);
-
- return (error);
-}
-
-/*
- * nfslockdans --
- * NFS advisory byte-level locks answer from the lock daemon.
- */
-int
-nfslockdans(p, ansp)
- struct proc *p;
- struct lockd_ans *ansp;
-{
- int error;
-
- /* Let root, or someone who once was root (lockd generally
- * switches to the daemon uid once it is done setting up) make
- * this call.
- *
- * XXX This authorization check is probably not right.
- */
- if ((error = suser(p)) != 0 && p->p_ucred->cr_svuid != 0)
- return (error);
-
- /* the version should match, or we're out of sync */
- if (ansp->la_vers != LOCKD_ANS_VERSION)
- return (EINVAL);
-
- /* Find the process, set its return errno and wake it up. */
- if ((p = pfind(ansp->la_msg_ident.pid)) == NULL)
- return (ESRCH);
-
- /* verify the pid hasn't been reused (if we can), and it isn't waiting
- * for an answer from a more recent request. We return an EPIPE if
- * the match fails, because we've already used ESRCH above, and this
- * is sort of like writing on a pipe after the reader has closed it.
- */
- if (p->p_nlminfo == NULL ||
- ((ansp->la_msg_ident.msg_seq != -1) &&
- (timevalcmp(&p->p_nlminfo->pid_start,
- &ansp->la_msg_ident.pid_start, !=) ||
- p->p_nlminfo->msg_seq != ansp->la_msg_ident.msg_seq))) {
- PROC_UNLOCK(p);
- return (EPIPE);
- }
-
- p->p_nlminfo->retcode = ansp->la_errno;
- p->p_nlminfo->set_getlk_pid = ansp->la_set_getlk_pid;
- p->p_nlminfo->getlk_pid = ansp->la_getlk_pid;
-
- (void)wakeup((void *)p->p_nlminfo);
-
- PROC_UNLOCK(p);
- return (0);
-}
diff --git a/sys/nfs/nfs_lock.h b/sys/nfs/nfs_lock.h
deleted file mode 100644
index 64b6c70..0000000
--- a/sys/nfs/nfs_lock.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*-
- * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved.
- * 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. Berkeley Software Design Inc's name may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``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 BERKELEY SOFTWARE DESIGN INC 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.
- *
- * from nfs_lock.h,v 2.2 1998/04/28 19:38:41 don Exp
- * $FreeBSD$
- */
-
-/*
- * lockd uses the nfssvc system call to get the unique kernel services it needs.
- * It passes in a request structure with a version number at the start.
- * This prevents libc from needing to change if the information passed
- * between lockd and the kernel needs to change.
- *
- * If a structure changes, you must bump the version number.
- */
-
-#include <nfs/nfsproto.h>
-
-
-#define LOCKD_REQ_VERSION 1
-
-struct lockd_req {
- int vers; /* keep in sync with kernel please */
- int op; /* F_GETLK | F_SETLK | F_UNLCK */
- int owner; /* owner of lock, -1 to allocate one */
- int owner_rel_ok; /* release owner if no locks left ? */
- int *owner_ret; /* owner alloc/free result target */
- void *fh; /* NFS file handle */
- size_t fh_len; /* NFS file handle length */
- u_quad_t offset; /* offset of where to start lock */
- u_quad_t len; /* length of range to lock */
- int type; /* F_RDLCK | F_WRLCK | F_UNLCK */
- struct ucred cred; /* user credentials to use for lock */
- struct sockaddr saddr; /* XXX how about non AF_INET ?? */
- int pid; /* pid of lock requester */
-};
-
-/*
- * The fifo where the kernel writes requests for locks on remote NFS files,
- * and where lockd reads these requests.
- *
- */
-#define _PATH_LCKFIFO "/var/run/lock"
-
-/*
- * This structure is used to uniquely identify the process which originated
- * a particular message to lockd. A sequence number is used to differentiate
- * multiple messages from the same process. A process start time is used to
- * detect the unlikely, but possible, event of the recycling of a pid.
- */
-struct lockd_msg_ident {
- pid_t pid; /* The process ID. */
- struct timeval pid_start; /* Start time of process id */
- int msg_seq; /* Sequence number of message */
-};
-
-#define LOCKD_MSG_VERSION 1
-
-/*
- * The structure that the kernel hands us for each lock request.
- */
-typedef struct __lock_msg {
- int lm_version; /* which version is this */
- struct lockd_msg_ident lm_msg_ident; /* originator of the message */
- struct flock lm_fl; /* The lock request. */
- int lm_wait; /* The F_WAIT flag. */
- int lm_getlk; /* is this a F_GETLK request */
- struct sockaddr lm_addr; /* The address. */
- int lm_nfsv3; /* If NFS version 3. */
- size_t lm_fh_len; /* The file handle length. */
- struct ucred lm_cred; /* user cred for lock req */
- u_int8_t lm_fh[NFS_SMALLFH];/* The file handle. */
-} LOCKD_MSG;
-
-#define LOCKD_ANS_VERSION 1
-
-struct lockd_ans {
- int la_vers;
- struct lockd_msg_ident la_msg_ident; /* originator of the message */
- int la_errno;
- int la_set_getlk_pid; /* use returned pid */
- int la_getlk_pid; /* returned pid for F_GETLK */
-};
-
-#ifdef _KERNEL
-int nfs_dolock(struct vop_advlock_args *ap);
-int nfslockdans(struct proc *p, struct lockd_ans *ansp);
-int nfslockdreq(struct proc *p, struct lockd_req *reqp);
-#endif
diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c
deleted file mode 100644
index 5fe3abc..0000000
--- a/sys/nfs/nfs_node.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * 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.
- * 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_node.c 8.6 (Berkeley) 5/22/95
- * $FreeBSD$
- */
-
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fnv_hash.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-
-#include <vm/vm_zone.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
-
-static vm_zone_t nfsnode_zone;
-static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
-static u_long nfsnodehash;
-
-#define TRUE 1
-#define FALSE 0
-
-/*
- * Grab an atomic snapshot of the nfsnode hash chain lengths
- */
-SYSCTL_DECL(_debug_hashstat);
-static int
-sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS)
-{
- int error;
- struct nfsnodehashhead *nnpp;
- struct nfsnode *nnp;
- int n_nfsnode;
- int count;
-
- n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */
- if (!req->oldptr)
- return SYSCTL_OUT(req, 0, n_nfsnode * sizeof(int));
-
- /* Scan hash tables for applicable entries */
- for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) {
- count = 0;
- LIST_FOREACH(nnp, nnpp, n_hash) {
- count++;
- }
- error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count));
- if (error)
- return (error);
- }
- return (0);
-}
-SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD,
- 0, 0, sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths");
-
-static int
-sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS)
-{
- int error;
- struct nfsnodehashhead *nnpp;
- struct nfsnode *nnp;
- int n_nfsnode;
- int count, maxlength, used, pct;
-
- if (!req->oldptr)
- return SYSCTL_OUT(req, 0, 4 * sizeof(int));
-
- n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */
- used = 0;
- maxlength = 0;
-
- /* Scan hash tables for applicable entries */
- for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) {
- count = 0;
- LIST_FOREACH(nnp, nnpp, n_hash) {
- count++;
- }
- if (count)
- used++;
- if (maxlength < count)
- maxlength = count;
- }
- n_nfsnode = nfsnodehash + 1;
- pct = (used * 100 * 100) / n_nfsnode;
- error = SYSCTL_OUT(req, (caddr_t)&n_nfsnode, sizeof(n_nfsnode));
- if (error)
- return (error);
- error = SYSCTL_OUT(req, (caddr_t)&used, sizeof(used));
- if (error)
- return (error);
- error = SYSCTL_OUT(req, (caddr_t)&maxlength, sizeof(maxlength));
- if (error)
- return (error);
- error = SYSCTL_OUT(req, (caddr_t)&pct, sizeof(pct));
- if (error)
- return (error);
- return (0);
-}
-SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD,
- 0, 0, sysctl_debug_hashstat_nfsnode, "I", "nfsnode chain lengths");
-
-/*
- * Initialize hash links for nfsnodes
- * and build nfsnode free list.
- */
-void
-nfs_nhinit()
-{
- nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1);
- nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash);
-}
-
-/*
- * Look up a vnode/nfsnode by file handle.
- * Callers must check for mount points!!
- * In all cases, a pointer to a
- * nfsnode structure is returned.
- */
-static int nfs_node_hash_lock;
-
-int
-nfs_nget(mntp, fhp, fhsize, npp)
- struct mount *mntp;
- register nfsfh_t *fhp;
- int fhsize;
- struct nfsnode **npp;
-{
- struct thread *td = curthread; /* XXX */
- struct nfsnode *np, *np2;
- struct nfsnodehashhead *nhpp;
- register struct vnode *vp;
- struct vnode *nvp;
- int error;
- int rsflags;
- struct nfsmount *nmp;
-
- /*
- * Calculate nfs mount point and figure out whether the rslock should
- * be interruptable or not.
- */
- nmp = VFSTONFS(mntp);
- if (nmp->nm_flag & NFSMNT_INT)
- rsflags = PCATCH;
- else
- rsflags = 0;
-
-retry:
- nhpp = NFSNOHASH(fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT));
-loop:
- for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
- if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
- bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
- continue;
- vp = NFSTOV(np);
- if (vget(vp, LK_EXCLUSIVE, td))
- goto loop;
- *npp = np;
- return(0);
- }
- /*
- * Obtain a lock to prevent a race condition if the getnewvnode()
- * or MALLOC() below happens to block.
- */
- if (nfs_node_hash_lock) {
- while (nfs_node_hash_lock) {
- nfs_node_hash_lock = -1;
- tsleep(&nfs_node_hash_lock, PVM, "nfsngt", 0);
- }
- goto loop;
- }
- nfs_node_hash_lock = 1;
-
- /*
- * Allocate before getnewvnode since doing so afterward
- * might cause a bogus v_data pointer to get dereferenced
- * elsewhere if zalloc should block.
- */
- np = zalloc(nfsnode_zone);
-
- error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
- if (error) {
- if (nfs_node_hash_lock < 0)
- wakeup(&nfs_node_hash_lock);
- nfs_node_hash_lock = 0;
- *npp = 0;
- zfree(nfsnode_zone, np);
- return (error);
- }
- vp = nvp;
- bzero((caddr_t)np, sizeof *np);
- vp->v_data = np;
- np->n_vnode = vp;
- /*
- * Insert the nfsnode in the hash queue for its new file handle
- */
- for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) {
- if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize ||
- bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize))
- continue;
- vrele(vp);
- if (nfs_node_hash_lock < 0)
- wakeup(&nfs_node_hash_lock);
- nfs_node_hash_lock = 0;
- zfree(nfsnode_zone, np);
- goto retry;
- }
- LIST_INSERT_HEAD(nhpp, np, n_hash);
- if (fhsize > NFS_SMALLFH) {
- MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
- } else
- np->n_fhp = &np->n_fh;
- bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
- np->n_fhsize = fhsize;
- lockinit(&np->n_rslock, PVFS | rsflags, "nfrslk", 0, LK_NOPAUSE);
- lockinit(&vp->v_lock, PVFS, "nfsnlk", 0, LK_NOPAUSE);
- *npp = np;
-
- if (nfs_node_hash_lock < 0)
- wakeup(&nfs_node_hash_lock);
- nfs_node_hash_lock = 0;
-
- /*
- * Lock the new nfsnode.
- */
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
-
- return (0);
-}
-
-int
-nfs_inactive(ap)
- struct vop_inactive_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- } */ *ap;
-{
- register struct nfsnode *np;
- register struct sillyrename *sp;
- struct thread *td = curthread; /* XXX */
-
- np = VTONFS(ap->a_vp);
- if (prtactive && ap->a_vp->v_usecount != 0)
- vprint("nfs_inactive: pushing active", ap->a_vp);
- if (ap->a_vp->v_type != VDIR) {
- sp = np->n_sillyrename;
- np->n_sillyrename = (struct sillyrename *)0;
- } else
- sp = (struct sillyrename *)0;
- if (sp) {
- /*
- * We need a reference to keep the vnode from being
- * recycled by getnewvnode while we do the I/O
- * associated with discarding the buffers unless we
- * are being forcibly unmounted in which case we already
- * have our own reference.
- */
- if (ap->a_vp->v_usecount > 0)
- (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, td, 1);
- else if (vget(ap->a_vp, 0, td))
- panic("nfs_inactive: lost vnode");
- else {
- (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, td, 1);
- vrele(ap->a_vp);
- }
- /*
- * Remove the silly file that was rename'd earlier
- */
- nfs_removeit(sp);
- crfree(sp->s_cred);
- vrele(sp->s_dvp);
- FREE((caddr_t)sp, M_NFSREQ);
- }
- np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
- NQNFSNONCACHE | NQNFSWRITE);
- VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
- return (0);
-}
-
-/*
- * Reclaim an nfsnode so that it can be used for other purposes.
- */
-int
-nfs_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- register struct nfsdmap *dp, *dp2;
-
- if (prtactive && vp->v_usecount != 0)
- vprint("nfs_reclaim: pushing active", vp);
-
- if (np->n_hash.le_prev != NULL)
- LIST_REMOVE(np, n_hash);
-
- /*
- * For nqnfs, take it off the timer queue as required.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) && TAILQ_NEXT(np, n_timer) != 0) {
- TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
- }
-
- /*
- * Free up any directory cookie structures and
- * large file handle structures that might be associated with
- * this nfs node.
- */
- if (vp->v_type == VDIR) {
- dp = np->n_cookies.lh_first;
- while (dp) {
- dp2 = dp;
- dp = dp->ndm_list.le_next;
- FREE((caddr_t)dp2, M_NFSDIROFF);
- }
- }
- if (np->n_fhsize > NFS_SMALLFH) {
- FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
- }
-
- lockdestroy(&np->n_rslock);
-
- cache_purge(vp);
- zfree(nfsnode_zone, vp->v_data);
- vp->v_data = (void *)0;
- return (0);
-}
-
-#if 0
-/*
- * Lock an nfsnode
- */
-int
-nfs_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
-
- /*
- * Ugh, another place where interruptible mounts will get hung.
- * If you make this sleep interruptible, then you have to fix all
- * the VOP_LOCK() calls to expect interruptibility.
- */
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "nfslck", 0);
- }
- if (vp->v_tag == VT_NON)
- return (ENOENT);
-
-#if 0
- /*
- * Only lock regular files. If a server crashed while we were
- * holding a directory lock, we could easily end up sleeping
- * until the server rebooted while holding a lock on the root.
- * Locks are only needed for protecting critical sections in
- * VMIO at the moment.
- * New vnodes will have type VNON but they should be locked
- * since they may become VREG. This is checked in loadattrcache
- * and unwanted locks are released there.
- */
- if (vp->v_type == VREG || vp->v_type == VNON) {
- while (np->n_flag & NLOCKED) {
- np->n_flag |= NWANTED;
- (void) tsleep((caddr_t) np, PINOD, "nfslck2", 0);
- /*
- * If the vnode has transmuted into a VDIR while we
- * were asleep, then skip the lock.
- */
- if (vp->v_type != VREG && vp->v_type != VNON)
- return (0);
- }
- np->n_flag |= NLOCKED;
- }
-#endif
-
- return (0);
-}
-
-/*
- * Unlock an nfsnode
- */
-int
-nfs_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-#if 0
- struct vnode* vp = ap->a_vp;
- struct nfsnode* np = VTONFS(vp);
-
- if (vp->v_type == VREG || vp->v_type == VNON) {
- if (!(np->n_flag & NLOCKED))
- panic("nfs_unlock: nfsnode not locked");
- np->n_flag &= ~NLOCKED;
- if (np->n_flag & NWANTED) {
- np->n_flag &= ~NWANTED;
- wakeup((caddr_t) np);
- }
- }
-#endif
-
- return (0);
-}
-
-/*
- * Check for a locked nfsnode
- */
-int
-nfs_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- } */ *ap;
-{
- return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
-}
-#endif
-
diff --git a/sys/nfs/nfs_nqlease.c b/sys/nfs/nfs_nqlease.c
deleted file mode 100644
index 86b5ef6..0000000
--- a/sys/nfs/nfs_nqlease.c
+++ /dev/null
@@ -1,1288 +0,0 @@
-/*
- * Copyright (c) 1992, 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.
- * 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_nqlease.c 8.9 (Berkeley) 5/20/95
- * $FreeBSD$
- */
-
-
-/*
- * References:
- * Cary G. Gray and David R. Cheriton, "Leases: An Efficient Fault-Tolerant
- * Mechanism for Distributed File Cache Consistency",
- * In Proc. of the Twelfth ACM Symposium on Operating Systems
- * Principals, pg. 202-210, Litchfield Park, AZ, Dec. 1989.
- * Michael N. Nelson, Brent B. Welch and John K. Ousterhout, "Caching
- * in the Sprite Network File System", ACM TOCS 6(1),
- * pages 134-154, February 1988.
- * V. Srinivasan and Jeffrey C. Mogul, "Spritely NFS: Implementation and
- * Performance of Cache-Consistency Protocols", Digital
- * Equipment Corporation WRL Research Report 89/5, May 1989.
- */
-#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/socket.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/vnode.h>
-
-#include <vm/vm_zone.h>
-
-#include <machine/mutex.h>
-
-#include <netinet/in.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
-
-static MALLOC_DEFINE(M_NQMHOST, "NQNFS Host", "Nqnfs host address table");
-
-time_t nqnfsstarttime = (time_t)0;
-int nqsrv_clockskew = NQ_CLOCKSKEW;
-int nqsrv_writeslack = NQ_WRITESLACK;
-int nqsrv_maxlease = NQ_MAXLEASE;
-#ifndef NFS_NOSERVER
-static int nqsrv_maxnumlease = NQ_MAXNUMLEASE;
-#endif
-
-struct vop_lease_args;
-
-#ifndef NFS_NOSERVER
-static int nqsrv_cmpnam __P((struct nfssvc_sock *, struct sockaddr *,
- struct nqhost *));
-static int nqnfs_vacated __P((struct vnode *vp, struct ucred *cred));
-static void nqsrv_addhost __P((struct nqhost *lph, struct nfssvc_sock *slp,
- struct sockaddr *nam));
-static void nqsrv_instimeq __P((struct nqlease *lp, u_int32_t duration));
-static void nqsrv_locklease __P((struct nqlease *lp));
-static void nqsrv_send_eviction __P((struct vnode *vp, struct nqlease *lp,
- struct nfssvc_sock *slp,
- struct sockaddr *nam,
- struct ucred *cred));
-static void nqsrv_unlocklease __P((struct nqlease *lp));
-static void nqsrv_waitfor_expiry __P((struct nqlease *lp));
-#endif
-extern void nqnfs_lease_updatetime __P((int deltat));
-
-/*
- * Signifies which rpcs can have piggybacked lease requests
- */
-int nqnfs_piggy[NFS_NPROCS] = {
- 0,
- 0,
- ND_WRITE,
- ND_READ,
- 0,
- ND_READ,
- ND_READ,
- ND_WRITE,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- ND_READ,
- ND_READ,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
-};
-
-extern nfstype nfsv2_type[9];
-extern nfstype nfsv3_type[9];
-extern int nfsd_waiting;
-extern struct nfsstats nfsstats;
-
-#define TRUE 1
-#define FALSE 0
-
-#ifndef NFS_NOSERVER
-/*
- * Get or check for a lease for "vp", based on ND_CHECK flag.
- * The rules are as follows:
- * - if a current non-caching lease, reply non-caching
- * - if a current lease for same host only, extend lease
- * - if a read cachable lease and a read lease request
- * add host to list any reply cachable
- * - else { set non-cachable for read-write sharing }
- * send eviction notice messages to all other hosts that have lease
- * wait for lease termination { either by receiving vacated messages
- * from all the other hosts or expiry
- * via. timeout }
- * modify lease to non-cachable
- * - else if no current lease, issue new one
- * - reply
- * - return boolean TRUE iff nam should be m_freem()'d
- * NB: Since nqnfs_serverd() is called from a timer, any potential tsleep()
- * in here must be framed by nqsrv_locklease() and nqsrv_unlocklease().
- * nqsrv_locklease() is coded such that at least one of LC_LOCKED and
- * LC_WANTED is set whenever a process is tsleeping in it. The exception
- * is when a new lease is being allocated, since it is not in the timer
- * queue yet. (Ditto for the splsoftclock() and splx(s) calls)
- */
-int
-nqsrv_getlease(vp, duration, flags, slp, td, nam, cachablep, frev, cred)
- struct vnode *vp;
- u_int32_t *duration;
- int flags;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct sockaddr *nam;
- int *cachablep;
- u_quad_t *frev;
- struct ucred *cred;
-{
- register struct nqlease *lp;
- register struct nqfhhashhead *lpp = NULL;
- register struct nqhost *lph = NULL;
- struct nqlease *tlp;
- struct nqm **lphp;
- struct vattr vattr;
- fhandle_t fh;
- int i, ok, error, s;
-
- if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
- return (0);
- if (*duration > nqsrv_maxlease)
- *duration = nqsrv_maxlease;
- error = VOP_GETATTR(vp, &vattr, cred, td);
- if (error)
- return (error);
- *frev = vattr.va_filerev;
- s = splsoftclock();
- tlp = vp->v_lease;
- if ((flags & ND_CHECK) == 0)
- nfsstats.srvnqnfs_getleases++;
- if (tlp == 0) {
- /*
- * Find the lease by searching the hash list.
- */
- fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- error = VFS_VPTOFH(vp, &fh.fh_fid);
- if (error) {
- splx(s);
- return (error);
- }
- lpp = NQFHHASH(fh.fh_fid.fid_data);
- for (lp = lpp->lh_first; lp != 0; lp = lp->lc_hash.le_next)
- if (fh.fh_fsid.val[0] == lp->lc_fsid.val[0] &&
- fh.fh_fsid.val[1] == lp->lc_fsid.val[1] &&
- !bcmp(fh.fh_fid.fid_data, lp->lc_fiddata,
- fh.fh_fid.fid_len - sizeof (int32_t))) {
- /* Found it */
- lp->lc_vp = vp;
- vp->v_lease = lp;
- tlp = lp;
- break;
- }
- } else
- lp = tlp;
- if (lp != 0) {
- if ((lp->lc_flag & LC_NONCACHABLE) ||
- (lp->lc_morehosts == (struct nqm *)0 &&
- nqsrv_cmpnam(slp, nam, &lp->lc_host)))
- goto doreply;
- if ((flags & ND_READ) && (lp->lc_flag & LC_WRITE) == 0) {
- if (flags & ND_CHECK)
- goto doreply;
- if (nqsrv_cmpnam(slp, nam, &lp->lc_host))
- goto doreply;
- i = 0;
- if (lp->lc_morehosts) {
- lph = lp->lc_morehosts->lpm_hosts;
- lphp = &lp->lc_morehosts->lpm_next;
- ok = 1;
- } else {
- lphp = &lp->lc_morehosts;
- ok = 0;
- }
- while (ok && (lph->lph_flag & LC_VALID)) {
- if (nqsrv_cmpnam(slp, nam, lph))
- goto doreply;
- if (++i == LC_MOREHOSTSIZ) {
- i = 0;
- if (*lphp) {
- lph = (*lphp)->lpm_hosts;
- lphp = &((*lphp)->lpm_next);
- } else
- ok = 0;
- } else
- lph++;
- }
- nqsrv_locklease(lp);
- if (!ok) {
- *lphp = (struct nqm *)
- malloc(sizeof (struct nqm),
- M_NQMHOST, M_WAITOK | M_ZERO);
- lph = (*lphp)->lpm_hosts;
- }
- nqsrv_addhost(lph, slp, nam);
- nqsrv_unlocklease(lp);
- } else {
- lp->lc_flag |= LC_NONCACHABLE;
- nqsrv_locklease(lp);
- nqsrv_send_eviction(vp, lp, slp, nam, cred);
- nqsrv_waitfor_expiry(lp);
- nqsrv_unlocklease(lp);
- }
-doreply:
- /*
- * Update the lease and return
- */
- if ((flags & ND_CHECK) == 0)
- nqsrv_instimeq(lp, *duration);
- if (lp->lc_flag & LC_NONCACHABLE)
- *cachablep = 0;
- else {
- *cachablep = 1;
- if (flags & ND_WRITE)
- lp->lc_flag |= LC_WRITTEN;
- }
- splx(s);
- return (0);
- }
- splx(s);
- if (flags & ND_CHECK)
- return (0);
-
- /*
- * Allocate new lease
- * The value of nqsrv_maxnumlease should be set generously, so that
- * the following "printf" happens infrequently.
- */
- if (nfsstats.srvnqnfs_leases > nqsrv_maxnumlease) {
- printf("Nqnfs server, too many leases\n");
- do {
- (void) tsleep((caddr_t)&lbolt, PSOCK,
- "nqsrvnuml", 0);
- } while (nfsstats.srvnqnfs_leases > nqsrv_maxnumlease);
- }
- MALLOC(lp, struct nqlease *, sizeof (struct nqlease), M_NQLEASE,
- M_WAITOK | M_ZERO);
- if (flags & ND_WRITE)
- lp->lc_flag |= (LC_WRITE | LC_WRITTEN);
- nqsrv_addhost(&lp->lc_host, slp, nam);
- lp->lc_vp = vp;
- lp->lc_fsid = fh.fh_fsid;
- bcopy(fh.fh_fid.fid_data, lp->lc_fiddata,
- fh.fh_fid.fid_len - sizeof (int32_t));
- if(!lpp)
- panic("nfs_nqlease.c: Phoney lpp");
- LIST_INSERT_HEAD(lpp, lp, lc_hash);
- vp->v_lease = lp;
- s = splsoftclock();
- nqsrv_instimeq(lp, *duration);
- splx(s);
- *cachablep = 1;
- if (++nfsstats.srvnqnfs_leases > nfsstats.srvnqnfs_maxleases)
- nfsstats.srvnqnfs_maxleases = nfsstats.srvnqnfs_leases;
- return (0);
-}
-
-/*
- * Local lease check for server syscalls.
- * Just set up args and let nqsrv_getlease() do the rest.
- * nqnfs_vop_lease_check() is the VOP_LEASE() form of the same routine.
- * Ifdef'd code in nfsnode.h renames these routines to whatever a particular
- * OS needs.
- */
-void
-nqnfs_lease_check(vp, td, cred, flag)
- struct vnode *vp;
- struct thread *td;
- struct ucred *cred;
- int flag;
-{
- u_int32_t duration = 0;
- int cache;
- u_quad_t frev;
-
- (void) nqsrv_getlease(vp, &duration, ND_CHECK | flag, NQLOCALSLP,
- td, (struct sockaddr *)0, &cache, &frev, cred);
-}
-
-int
-nqnfs_vop_lease_check(ap)
- struct vop_lease_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- struct ucred *a_cred;
- int a_flag;
- } */ *ap;
-{
- u_int32_t duration = 0;
- int cache;
- u_quad_t frev;
-
- (void) nqsrv_getlease(ap->a_vp, &duration, ND_CHECK | ap->a_flag,
- NQLOCALSLP, ap->a_td, (struct sockaddr *)0,
- &cache, &frev, ap->a_cred);
- return (0);
-}
-
-
-/*
- * Add a host to an nqhost structure for a lease.
- */
-static void
-nqsrv_addhost(lph, slp, nam)
- register struct nqhost *lph;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
-{
- struct sockaddr_in *saddr;
- struct socket *nsso;
-
- if (slp == NQLOCALSLP) {
- lph->lph_flag |= (LC_VALID | LC_LOCAL);
- return;
- }
- nsso = slp->ns_so;
- lph->lph_slp = slp;
- if (nsso && nsso->so_proto->pr_protocol == IPPROTO_UDP) {
- saddr = (struct sockaddr_in *)nam;
- lph->lph_flag |= (LC_VALID | LC_UDP);
- lph->lph_inetaddr = saddr->sin_addr.s_addr;
- lph->lph_port = saddr->sin_port;
- } else {
- lph->lph_flag |= (LC_VALID | LC_SREF);
- slp->ns_sref++;
- }
-}
-
-/*
- * Update the lease expiry time and position it in the timer queue correctly.
- */
-static void
-nqsrv_instimeq(lp, duration)
- register struct nqlease *lp;
- u_int32_t duration;
-{
- register struct nqlease *tlp;
- time_t newexpiry;
-
- newexpiry = time_second + duration + nqsrv_clockskew;
- if (lp->lc_expiry == newexpiry)
- return;
- if (TAILQ_NEXT(lp, lc_timer) != 0) {
- TAILQ_REMOVE(&nqtimerhead, lp, lc_timer);
- }
- lp->lc_expiry = newexpiry;
-
- /*
- * Find where in the queue it should be.
- */
- TAILQ_FOREACH_REVERSE(tlp, &nqtimerhead, nqtimerhead, lc_timer)
- if (tlp->lc_expiry <= newexpiry)
- break;
-#ifdef HASNVRAM
- if (tlp == TAILQ_LAST(&nqtimerhead))
- NQSTORENOVRAM(newexpiry);
-#endif /* HASNVRAM */
- if (tlp == NULL) {
- TAILQ_INSERT_HEAD(&nqtimerhead, lp, lc_timer);
- } else {
- TAILQ_INSERT_AFTER(&nqtimerhead, tlp, lp, lc_timer);
- }
-}
-
-/*
- * Compare the requesting host address with the lph entry in the lease.
- * Return true iff it is the same.
- * This is somewhat messy due to the union in the nqhost structure.
- * The local host is indicated by the special value of NQLOCALSLP for slp.
- */
-static int
-nqsrv_cmpnam(slp, nam, lph)
- register struct nfssvc_sock *slp;
- struct sockaddr *nam;
- register struct nqhost *lph;
-{
- register struct sockaddr_in *saddr;
- struct sockaddr *addr;
- union nethostaddr lhaddr;
- struct socket *nsso;
- int ret;
-
- if (slp == NQLOCALSLP) {
- if (lph->lph_flag & LC_LOCAL)
- return (1);
- else
- return (0);
- }
- nsso = slp->ns_so;
- if (nsso && nsso->so_proto->pr_protocol == IPPROTO_UDP) {
- addr = nam;
- } else {
- addr = slp->ns_nam;
- }
- if (lph->lph_flag & LC_UDP) {
- ret = netaddr_match(AF_INET, &lph->lph_haddr, addr);
- } else {
- if ((lph->lph_slp->ns_flag & SLP_VALID) == 0)
- return (0);
- saddr = (struct sockaddr_in *)lph->lph_slp->ns_nam;
- if (saddr->sin_family == AF_INET)
- lhaddr.had_inetaddr = saddr->sin_addr.s_addr;
- else
- lhaddr.had_nam = lph->lph_slp->ns_nam;
- ret = netaddr_match(saddr->sin_family, &lhaddr, addr);
- }
- return (ret);
-}
-
-/*
- * Send out eviction notice messages to all other hosts for the lease.
- */
-static void
-nqsrv_send_eviction(vp, lp, slp, nam, cred)
- struct vnode *vp;
- register struct nqlease *lp;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- struct ucred *cred;
-{
- register struct nqhost *lph = &lp->lc_host;
- register int siz;
- struct nqm *lphnext = lp->lc_morehosts;
- struct mbuf *m, *mreq, *mb, *mb2, *mheadend;
- struct sockaddr *nam2;
- struct sockaddr_in *saddr;
- nfsfh_t nfh;
- fhandle_t *fhp;
- caddr_t bpos, cp;
- u_int32_t xid, *tl;
- int len = 1, ok = 1, i = 0;
-
- while (ok && (lph->lph_flag & LC_VALID)) {
- if (nqsrv_cmpnam(slp, nam, lph)) {
- lph->lph_flag |= LC_VACATED;
- } else if ((lph->lph_flag & (LC_LOCAL | LC_VACATED)) == 0) {
- struct socket *so;
- int sotype;
- int *solockp = NULL;
-
- so = lph->lph_slp->ns_so;
- if (lph->lph_flag & LC_UDP) {
- MALLOC(nam2, struct sockaddr *,
- sizeof *nam2, M_SONAME, M_WAITOK);
- saddr = (struct sockaddr_in *)nam2;
- saddr->sin_len = sizeof *saddr;
- saddr->sin_family = AF_INET;
- saddr->sin_addr.s_addr = lph->lph_inetaddr;
- saddr->sin_port = lph->lph_port;
- } else if (lph->lph_slp->ns_flag & SLP_VALID) {
- nam2 = (struct sockaddr *)0;
- } else {
- goto nextone;
- }
- sotype = so->so_type;
- if (so->so_proto->pr_flags & PR_CONNREQUIRED)
- solockp = &lph->lph_slp->ns_solock;
- nfsm_reqhead((struct vnode *)0, NQNFSPROC_EVICTED,
- NFSX_V3FH + NFSX_UNSIGNED);
- fhp = &nfh.fh_generic;
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- VFS_VPTOFH(vp, &fhp->fh_fid);
- nfsm_srvfhtom(fhp, 1);
- m = mreq;
- siz = 0;
- while (m) {
- siz += m->m_len;
- m = m->m_next;
- }
- if (siz <= 0 || siz > NFS_MAXPACKET) {
- printf("mbuf siz=%d\n",siz);
- panic("Bad nfs svc reply");
- }
- m = nfsm_rpchead(cred, (NFSMNT_NFSV3 | NFSMNT_NQNFS),
- NQNFSPROC_EVICTED,
- RPCAUTH_UNIX, 5 * NFSX_UNSIGNED, (char *)0,
- 0, (char *)NULL, mreq, siz, &mheadend, &xid);
- /*
- * For stream protocols, prepend a Sun RPC
- * Record Mark.
- */
- if (sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 |
- (m->m_pkthdr.len - NFSX_UNSIGNED));
- }
- /*
- * nfs_sndlock if PR_CONNREQUIRED XXX
- */
-
- if ((lph->lph_flag & LC_UDP) == 0 &&
- ((lph->lph_slp->ns_flag & SLP_VALID) == 0 ||
- nfs_slplock(lph->lph_slp, 0) == 0)) {
- m_freem(m);
- } else {
- (void) nfs_send(so, nam2, m,
- (struct nfsreq *)0);
- if (solockp)
- nfs_slpunlock(lph->lph_slp);
- }
- if (lph->lph_flag & LC_UDP)
- FREE(nam2, M_SONAME);
- }
-nextone:
- if (++i == len) {
- if (lphnext) {
- i = 0;
- len = LC_MOREHOSTSIZ;
- lph = lphnext->lpm_hosts;
- lphnext = lphnext->lpm_next;
- } else
- ok = 0;
- } else
- lph++;
- }
-}
-
-/*
- * Wait for the lease to expire.
- * This will occur when all clients have sent "vacated" messages to
- * this server OR when it expires do to timeout.
- */
-static void
-nqsrv_waitfor_expiry(lp)
- register struct nqlease *lp;
-{
- register struct nqhost *lph;
- register int i;
- struct nqm *lphnext;
- int len, ok;
-
-tryagain:
- if (time_second > lp->lc_expiry)
- return;
- lph = &lp->lc_host;
- lphnext = lp->lc_morehosts;
- len = 1;
- i = 0;
- ok = 1;
- while (ok && (lph->lph_flag & LC_VALID)) {
- if ((lph->lph_flag & (LC_LOCAL | LC_VACATED)) == 0) {
- lp->lc_flag |= LC_EXPIREDWANTED;
- (void) tsleep((caddr_t)&lp->lc_flag, PSOCK,
- "nqexp", 0);
- goto tryagain;
- }
- if (++i == len) {
- if (lphnext) {
- i = 0;
- len = LC_MOREHOSTSIZ;
- lph = lphnext->lpm_hosts;
- lphnext = lphnext->lpm_next;
- } else
- ok = 0;
- } else
- lph++;
- }
-}
-
-/*
- * Nqnfs server timer that maintains the server lease queue.
- * Scan the lease queue for expired entries:
- * - when one is found, wakeup anyone waiting for it
- * else dequeue and free
- */
-void
-nqnfs_serverd()
-{
- register struct nqlease *lp;
- register struct nqhost *lph;
- struct nqlease *nextlp;
- struct nqm *lphnext, *olphnext;
- int i, len, ok;
-
- for (lp = TAILQ_FIRST(&nqtimerhead); lp; lp = nextlp) {
- if (lp->lc_expiry >= time_second)
- break;
- nextlp = TAILQ_NEXT(lp, lc_timer);
- if (lp->lc_flag & LC_EXPIREDWANTED) {
- lp->lc_flag &= ~LC_EXPIREDWANTED;
- wakeup((caddr_t)&lp->lc_flag);
- } else if ((lp->lc_flag & (LC_LOCKED | LC_WANTED)) == 0) {
- /*
- * Make a best effort at keeping a write caching lease long
- * enough by not deleting it until it has been explicitly
- * vacated or there have been no writes in the previous
- * write_slack seconds since expiry and the nfsds are not
- * all busy. The assumption is that if the nfsds are not
- * all busy now (no queue of nfs requests), then the client
- * would have been able to do at least one write to the
- * file during the last write_slack seconds if it was still
- * trying to push writes to the server.
- */
- if ((lp->lc_flag & (LC_WRITE | LC_VACATED)) == LC_WRITE &&
- ((lp->lc_flag & LC_WRITTEN) || nfsd_waiting == 0)) {
- lp->lc_flag &= ~LC_WRITTEN;
- nqsrv_instimeq(lp, nqsrv_writeslack);
- } else {
- TAILQ_REMOVE(&nqtimerhead, lp, lc_timer);
- LIST_REMOVE(lp, lc_hash);
- /*
- * This soft reference may no longer be valid, but
- * no harm done. The worst case is if the vnode was
- * recycled and has another valid lease reference,
- * which is dereferenced prematurely.
- */
- lp->lc_vp->v_lease = (struct nqlease *)0;
- lph = &lp->lc_host;
- lphnext = lp->lc_morehosts;
- olphnext = (struct nqm *)0;
- len = 1;
- i = 0;
- ok = 1;
- while (ok && (lph->lph_flag & LC_VALID)) {
- if (lph->lph_flag & LC_SREF)
- nfsrv_slpderef(lph->lph_slp);
- if (++i == len) {
- if (olphnext) {
- free((caddr_t)olphnext, M_NQMHOST);
- olphnext = (struct nqm *)0;
- }
- if (lphnext) {
- olphnext = lphnext;
- i = 0;
- len = LC_MOREHOSTSIZ;
- lph = lphnext->lpm_hosts;
- lphnext = lphnext->lpm_next;
- } else
- ok = 0;
- } else
- lph++;
- }
- FREE((caddr_t)lp, M_NQLEASE);
- if (olphnext)
- free((caddr_t)olphnext, M_NQMHOST);
- nfsstats.srvnqnfs_leases--;
- }
- }
- }
-}
-
-/*
- * Called from nfssvc_nfsd() for a getlease rpc request.
- * Do the from/to xdr translation and call nqsrv_getlease() to
- * do the real work.
- */
-int
-nqnfsrv_getlease(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
- struct vattr va;
- register struct vattr *vap = &va;
- struct vnode *vp;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
- u_quad_t frev;
- caddr_t bpos;
- int error = 0;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- int flags, rdonly, cache;
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- flags = fxdr_unsigned(int, *tl++);
- nfsd->nd_duration = fxdr_unsigned(int, *tl);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(0);
- goto nfsmout;
- }
- if (rdonly && flags == ND_WRITE) {
- error = EROFS;
- vput(vp);
- nfsm_reply(0);
- }
- (void) nqsrv_getlease(vp, &nfsd->nd_duration, flags, slp, td,
- nam, &cache, &frev, cred);
- error = VOP_GETATTR(vp, vap, cred, td);
- vput(vp);
- nfsm_reply(NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
- nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(cache);
- *tl++ = txdr_unsigned(nfsd->nd_duration);
- txdr_hyper(frev, tl);
- nfsm_build(fp, struct nfs_fattr *, NFSX_V3FATTR);
- nfsm_srvfillattr(vap, fp);
- nfsm_srvdone;
-}
-
-/*
- * Called from nfssvc_nfsd() when a "vacated" message is received from a
- * client. Find the entry and expire it.
- */
-int
-nqnfsrv_vacated(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- register struct nqlease *lp;
- register struct nqhost *lph;
- struct nqlease *tlp = (struct nqlease *)0;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
- struct nqm *lphnext;
- struct mbuf *mreq, *mb;
- int error = 0, i, len, ok, gotit = 0, cache = 0;
- char *cp2, *bpos;
- u_quad_t frev;
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- m_freem(mrep);
- /*
- * Find the lease by searching the hash list.
- */
- for (lp = NQFHHASH(fhp->fh_fid.fid_data)->lh_first; lp != 0;
- lp = lp->lc_hash.le_next)
- if (fhp->fh_fsid.val[0] == lp->lc_fsid.val[0] &&
- fhp->fh_fsid.val[1] == lp->lc_fsid.val[1] &&
- !bcmp(fhp->fh_fid.fid_data, lp->lc_fiddata,
- MAXFIDSZ)) {
- /* Found it */
- tlp = lp;
- break;
- }
- if (tlp != 0) {
- lp = tlp;
- len = 1;
- i = 0;
- lph = &lp->lc_host;
- lphnext = lp->lc_morehosts;
- ok = 1;
- while (ok && (lph->lph_flag & LC_VALID)) {
- if (nqsrv_cmpnam(slp, nam, lph)) {
- lph->lph_flag |= LC_VACATED;
- gotit++;
- break;
- }
- if (++i == len) {
- if (lphnext) {
- len = LC_MOREHOSTSIZ;
- i = 0;
- lph = lphnext->lpm_hosts;
- lphnext = lphnext->lpm_next;
- } else
- ok = 0;
- } else
- lph++;
- }
- if ((lp->lc_flag & LC_EXPIREDWANTED) && gotit) {
- lp->lc_flag &= ~LC_EXPIREDWANTED;
- wakeup((caddr_t)&lp->lc_flag);
- }
-nfsmout:
- return (EPERM);
- }
- return (EPERM);
-}
-
-#endif /* NFS_NOSERVER */
-
-/*
- * Client get lease rpc function.
- */
-int
-nqnfs_getlease(vp, rwflag, cred, td)
- register struct vnode *vp;
- int rwflag;
- struct ucred *cred;
- struct thread *td;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register struct nfsnode *np;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- caddr_t bpos, dpos, cp2;
- time_t reqtime;
- int error = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int cachable;
- u_quad_t frev;
-
- nfsstats.rpccnt[NQNFSPROC_GETLEASE]++;
- mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_V3FH+2*NFSX_UNSIGNED,
- &bpos);
- nfsm_fhtom(vp, 1);
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(rwflag);
- *tl = txdr_unsigned(nmp->nm_leaseterm);
- reqtime = time_second;
- nfsm_request(vp, NQNFSPROC_GETLEASE, td, cred);
- np = VTONFS(vp);
- nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- cachable = fxdr_unsigned(int, *tl++);
- reqtime += fxdr_unsigned(int, *tl++);
- if (reqtime > time_second) {
- frev = fxdr_hyper(tl);
- nqnfs_clientlease(nmp, np, rwflag, cachable, reqtime, frev);
- nfsm_loadattr(vp, (struct vattr *)0);
- } else
- error = NQNFS_EXPIRED;
- nfsm_reqdone;
- return (error);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Client vacated message function.
- */
-static int
-nqnfs_vacated(vp, cred)
- register struct vnode *vp;
- struct ucred *cred;
-{
- register caddr_t cp;
- register int i;
- register u_int32_t *tl;
- register int32_t t2;
- caddr_t bpos;
- u_int32_t xid;
- int error = 0;
- struct mbuf *m, *mreq, *mb, *mb2, *mheadend;
- struct nfsmount *nmp;
- struct nfsreq myrep;
-
- nmp = VFSTONFS(vp->v_mount);
- nfsstats.rpccnt[NQNFSPROC_VACATED]++;
- nfsm_reqhead(vp, NQNFSPROC_VACATED, NFSX_FH(1));
- nfsm_fhtom(vp, 1);
- m = mreq;
- i = 0;
- while (m) {
- i += m->m_len;
- m = m->m_next;
- }
- m = nfsm_rpchead(cred, nmp->nm_flag, NQNFSPROC_VACATED,
- RPCAUTH_UNIX, 5 * NFSX_UNSIGNED, (char *)0,
- 0, (char *)NULL, mreq, i, &mheadend, &xid);
- if (nmp->nm_sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 | (m->m_pkthdr.len -
- NFSX_UNSIGNED));
- }
- myrep.r_flags = 0;
- myrep.r_nmp = nmp;
- if (nmp->nm_soflags & PR_CONNREQUIRED)
- (void) nfs_sndlock(&myrep);
- (void) nfs_send(nmp->nm_so, nmp->nm_nam, m, &myrep);
- if (nmp->nm_soflags & PR_CONNREQUIRED)
- nfs_sndunlock(&myrep);
-nfsmout:
- return (error);
-}
-
-/*
- * Called for client side callbacks
- */
-int
-nqnfs_callback(nmp, mrep, md, dpos)
- struct nfsmount *nmp;
- struct mbuf *mrep, *md;
- caddr_t dpos;
-{
- register struct vnode *vp;
- register u_int32_t *tl;
- register int32_t t1;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct nfsnode *np;
- struct nfsd tnfsd;
- struct nfssvc_sock *slp;
- struct nfsrv_descript ndesc;
- register struct nfsrv_descript *nfsd = &ndesc;
- struct mbuf **mrq = (struct mbuf **)0, *mb, *mreq;
- int error = 0, cache = 0;
- char *cp2, *bpos;
- u_quad_t frev;
-
-#ifndef nolint
- slp = NULL;
-#endif
- nfsd->nd_mrep = mrep;
- nfsd->nd_md = md;
- nfsd->nd_dpos = dpos;
- error = nfs_getreq(nfsd, &tnfsd, FALSE);
- if (error)
- return (error);
- md = nfsd->nd_md;
- dpos = nfsd->nd_dpos;
- if (nfsd->nd_procnum != NQNFSPROC_EVICTED) {
- m_freem(mrep);
- return (EPERM);
- }
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- m_freem(mrep);
- error = nfs_nget(nmp->nm_mountp, (nfsfh_t *)fhp, NFSX_V3FH, &np);
- if (error)
- return (error);
- vp = NFSTOV(np);
- if (TAILQ_NEXT(np, n_timer) != 0) {
- np->n_expiry = 0;
- np->n_flag |= NQNFSEVICTED;
- if (TAILQ_FIRST(&nmp->nm_timerhead) != np) {
- TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
- TAILQ_INSERT_HEAD(&nmp->nm_timerhead, np, n_timer);
- }
- }
- vput(vp);
- nfsm_srvdone;
-}
-
-
-/*
- * Nqnfs client helper daemon. Runs once a second to expire leases.
- * It also get authorization strings for "kerb" mounts.
- * It must start at the beginning of the list again after any potential
- * "sleep" since nfs_reclaim() called from vclean() can pull a node off
- * the list asynchronously.
- */
-int
-nqnfs_clientd(nmp, cred, ncd, flag, argp, td)
- register struct nfsmount *nmp;
- struct ucred *cred;
- struct nfsd_cargs *ncd;
- int flag;
- caddr_t argp;
- struct thread *td;
-{
- register struct nfsnode *np;
- struct vnode *vp;
- struct nfsreq myrep;
- struct nfsuid *nuidp, *nnuidp;
- int error = 0, vpid;
-
- /*
- * First initialize some variables
- */
-
- /*
- * If an authorization string is being passed in, get it.
- */
- if ((flag & NFSSVC_GOTAUTH) &&
- (nmp->nm_state & (NFSSTA_WAITAUTH | NFSSTA_DISMNT)) == 0) {
- if (nmp->nm_state & NFSSTA_HASAUTH)
- panic("cld kerb");
- if ((flag & NFSSVC_AUTHINFAIL) == 0) {
- if (ncd->ncd_authlen <= nmp->nm_authlen &&
- ncd->ncd_verflen <= nmp->nm_verflen &&
- !copyin(ncd->ncd_authstr,nmp->nm_authstr,ncd->ncd_authlen)&&
- !copyin(ncd->ncd_verfstr,nmp->nm_verfstr,ncd->ncd_verflen)){
- nmp->nm_authtype = ncd->ncd_authtype;
- nmp->nm_authlen = ncd->ncd_authlen;
- nmp->nm_verflen = ncd->ncd_verflen;
-#ifdef NFSKERB
- nmp->nm_key = ncd->ncd_key;
-#endif
- } else
- nmp->nm_state |= NFSSTA_AUTHERR;
- } else
- nmp->nm_state |= NFSSTA_AUTHERR;
- nmp->nm_state |= NFSSTA_HASAUTH;
- wakeup((caddr_t)&nmp->nm_authlen);
- } else
- nmp->nm_state |= NFSSTA_WAITAUTH;
-
- /*
- * Loop every second updating queue until there is a termination sig.
- */
- while ((nmp->nm_state & NFSSTA_DISMNT) == 0) {
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- /*
- * If there are no outstanding requests (and therefore no
- * processes in nfs_reply) and there is data in the receive
- * queue, poke for callbacks.
- */
- if (nfs_reqq.tqh_first == 0 && nmp->nm_so &&
- nmp->nm_so->so_rcv.sb_cc > 0) {
- myrep.r_flags = R_GETONEREP;
- myrep.r_nmp = nmp;
- myrep.r_mrep = (struct mbuf *)0;
- myrep.r_td = (struct thread *)0;
- (void) nfs_reply(&myrep);
- }
-
- /*
- * Loop through the leases, updating as required.
- */
- while ((np = TAILQ_FIRST(&nmp->nm_timerhead)) != NULL) {
- if (nmp->nm_state & NFSSTA_DISMINPROG)
- break;
- vp = NFSTOV(np);
- vpid = vp->v_id;
- if (np->n_expiry < time_second) {
- if (vget(vp, LK_EXCLUSIVE, td) == 0) {
- nmp->nm_inprog = vp;
- if (vpid == vp->v_id) {
- TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
- TAILQ_NEXT(np, n_timer) = 0;
- if (np->n_flag & (NMODIFIED | NQNFSEVICTED)) {
- if (np->n_flag & NQNFSEVICTED) {
- if (vp->v_type == VDIR)
- nfs_invaldir(vp);
- cache_purge(vp);
- (void) nfs_vinvalbuf(vp,
- V_SAVE, cred, td, 0);
- np->n_flag &= ~NQNFSEVICTED;
- (void) nqnfs_vacated(vp, cred);
- } else if (vp->v_type == VREG) {
- (void) VOP_FSYNC(vp, cred,
- MNT_WAIT, td);
- np->n_flag &= ~NMODIFIED;
- }
- }
- }
- vput(vp);
- nmp->nm_inprog = NULLVP;
- }
- } else if ((np->n_expiry - NQ_RENEWAL) < time_second) {
- if ((np->n_flag & (NQNFSWRITE | NQNFSNONCACHE))
- == NQNFSWRITE &&
- !TAILQ_EMPTY(&vp->v_dirtyblkhd) &&
- vget(vp, LK_EXCLUSIVE, td) == 0) {
- nmp->nm_inprog = vp;
- if (vpid == vp->v_id &&
- nqnfs_getlease(vp, ND_WRITE, cred, td)==0)
- np->n_brev = np->n_lrev;
- vput(vp);
- nmp->nm_inprog = NULLVP;
- }
- } else
- break;
- }
- }
-
- /*
- * Get an authorization string, if required.
- */
- if ((nmp->nm_state & (NFSSTA_WAITAUTH | NFSSTA_DISMNT | NFSSTA_HASAUTH)) == 0) {
- ncd->ncd_authuid = nmp->nm_authuid;
- if (copyout((caddr_t)ncd, argp, sizeof (struct nfsd_cargs)))
- nmp->nm_state |= NFSSTA_WAITAUTH;
- else
- return (ENEEDAUTH);
- }
-
- /*
- * Wait a bit (no pun) and do it again.
- */
- if ((nmp->nm_state & NFSSTA_DISMNT) == 0 &&
- (nmp->nm_state & (NFSSTA_WAITAUTH | NFSSTA_HASAUTH))) {
- error = tsleep((caddr_t)&nmp->nm_authstr, PSOCK | PCATCH,
- "nqnfstimr", hz / 3);
- if (error == EINTR || error == ERESTART)
- (void) dounmount(nmp->nm_mountp, 0, td);
- }
- }
-
- /*
- * Finally, we can free up the mount structure.
- */
- for (nuidp = nmp->nm_uidlruhead.tqh_first; nuidp != 0; nuidp = nnuidp) {
- nnuidp = nuidp->nu_lru.tqe_next;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
- free((caddr_t)nuidp, M_NFSUID);
- }
- zfree(nfsmount_zone, nmp);
- if (error == EWOULDBLOCK)
- error = 0;
- return (error);
-}
-
-#endif /* NFS_NOSERVER */
-
-/*
- * Adjust all timer queue expiry times when the time of day clock is changed.
- * Called from the settimeofday() syscall.
- */
-void
-nqnfs_lease_updatetime(deltat)
- register int deltat;
-{
- struct thread *td = curthread; /* XXX */
- struct nqlease *lp;
- struct nfsnode *np;
- struct mount *mp, *nxtmp;
- struct nfsmount *nmp;
- int s;
-
- if (nqnfsstarttime != 0)
- nqnfsstarttime += deltat;
- s = splsoftclock();
- TAILQ_FOREACH(lp, &nqtimerhead, lc_timer)
- lp->lc_expiry += deltat;
- splx(s);
-
- /*
- * Search the mount list for all nqnfs mounts and do their timer
- * queues.
- */
- mtx_lock(&mountlist_mtx);
- for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nxtmp) {
- if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
- nxtmp = TAILQ_NEXT(mp, mnt_list);
- continue;
- }
- if (mp->mnt_stat.f_type == nfs_mount_type) {
- nmp = VFSTONFS(mp);
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- TAILQ_FOREACH(np, &nmp->nm_timerhead, n_timer) {
- np->n_expiry += deltat;
- }
- }
- }
- mtx_lock(&mountlist_mtx);
- nxtmp = TAILQ_NEXT(mp, mnt_list);
- vfs_unbusy(mp, td);
- }
- mtx_unlock(&mountlist_mtx);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Lock a server lease.
- */
-static void
-nqsrv_locklease(lp)
- struct nqlease *lp;
-{
-
- while (lp->lc_flag & LC_LOCKED) {
- lp->lc_flag |= LC_WANTED;
- (void) tsleep((caddr_t)lp, PSOCK, "nqlc", 0);
- }
- lp->lc_flag |= LC_LOCKED;
- lp->lc_flag &= ~LC_WANTED;
-}
-
-/*
- * Unlock a server lease.
- */
-static void
-nqsrv_unlocklease(lp)
- struct nqlease *lp;
-{
-
- lp->lc_flag &= ~LC_LOCKED;
- if (lp->lc_flag & LC_WANTED)
- wakeup((caddr_t)lp);
-}
-#endif /* NFS_NOSERVER */
-
-/*
- * Update a client lease.
- */
-void
-nqnfs_clientlease(nmp, np, rwflag, cachable, expiry, frev)
- register struct nfsmount *nmp;
- register struct nfsnode *np;
- int rwflag, cachable;
- time_t expiry;
- u_quad_t frev;
-{
- register struct nfsnode *tp;
-
- if (TAILQ_NEXT(np, n_timer) != 0) {
- TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
- if (rwflag == ND_WRITE)
- np->n_flag |= NQNFSWRITE;
- } else if (rwflag == ND_READ)
- np->n_flag &= ~NQNFSWRITE;
- else
- np->n_flag |= NQNFSWRITE;
- if (cachable)
- np->n_flag &= ~NQNFSNONCACHE;
- else
- np->n_flag |= NQNFSNONCACHE;
- np->n_expiry = expiry;
- np->n_lrev = frev;
- TAILQ_FOREACH_REVERSE(tp, &nmp->nm_timerhead, timhd, n_timer)
- if (tp->n_expiry <= np->n_expiry)
- break;
- if (tp == NULL) {
- TAILQ_INSERT_HEAD(&nmp->nm_timerhead, np, n_timer);
- } else {
- TAILQ_INSERT_AFTER(&nmp->nm_timerhead, tp, np, n_timer);
- }
-}
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
deleted file mode 100644
index 0469388..0000000
--- a/sys/nfs/nfs_serv.c
+++ /dev/null
@@ -1,4235 +0,0 @@
-/*
- * 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.
- * 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_serv.c 8.8 (Berkeley) 7/31/95
- * $FreeBSD$
- */
-
-/*
- * nfs version 2 and 3 server calls to vnode ops
- * - these routines generally have 3 phases
- * 1 - break down and validate rpc request in mbuf list
- * 2 - do the vnode ops for the request
- * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
- * 3 - build the rpc reply in an mbuf list
- * nb:
- * - do not mix the phases, since the nfsm_?? macros can return failures
- * on a bad rpc or similar and do not do any vrele() or vput()'s
- *
- * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
- * error number iff error != 0 whereas
- * returning an error from the server function implies a fatal error
- * such as a badly constructed rpc request that should be dropped without
- * a reply.
- * For Version 3, nfsm_reply() does not return for the error case, since
- * most version 3 rpcs return more than the status for error cases.
- *
- * Other notes:
- * Warning: always pay careful attention to resource cleanup on return
- * and note that nfsm_*() macros can terminate a procedure on certain
- * errors.
- *
- * lookup() and namei()
- * may return garbage in various structural fields/return elements
- * if an error is returned, and may garbage up nd.ni_dvp even if no
- * error is returned and you did not request LOCKPARENT or WANTPARENT.
- *
- * We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
- * buffer has been freed or not.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/namei.h>
-#include <sys/unistd.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/dirent.h>
-#include <sys/stat.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-
-#include <nfs/nfsproto.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nqnfs.h>
-
-#ifdef NFSRV_DEBUG
-#define nfsdbprintf(info) printf info
-#else
-#define nfsdbprintf(info)
-#endif
-
-#define MAX_COMMIT_COUNT (1024 * 1024)
-
-#define NUM_HEURISTIC 64
-#define NHUSE_INIT 64
-#define NHUSE_INC 16
-#define NHUSE_MAX 2048
-
-static struct nfsheur {
- struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
- off_t nh_nextr; /* next offset for sequential detection */
- int nh_use; /* use count for selection */
- int nh_seqcount; /* heuristic */
-} nfsheur[NUM_HEURISTIC];
-
-nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
- NFFIFO, NFNON };
-#ifndef NFS_NOSERVER
-nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
- NFCHR, NFNON };
-/* Global vars */
-extern u_int32_t nfs_xdrneg1;
-extern u_int32_t nfs_false, nfs_true;
-extern enum vtype nv3tov_type[8];
-extern struct nfsstats nfsstats;
-
-int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
-int nfsrvw_procrastinate_v3 = 0;
-
-static struct timeval nfsver = { 0 };
-
-SYSCTL_DECL(_vfs_nfs);
-
-static int nfs_async;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
-static int nfs_commit_blks;
-static int nfs_commit_miss;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
-
-static int nfsrv_access __P((struct vnode *,int,struct ucred *,int,
- struct thread *, int));
-static void nfsrvw_coalesce __P((struct nfsrv_descript *,
- struct nfsrv_descript *));
-
-/*
- * Clear nameidata fields that are tested in nsfmout cleanup code prior
- * to using first nfsm macro (that might jump to the cleanup code).
- */
-
-static __inline
-void
-ndclear(struct nameidata *nd)
-{
- nd->ni_cnd.cn_flags = 0;
- nd->ni_vp = NULL;
- nd->ni_dvp = NULL;
- nd->ni_startdir = NULL;
-}
-
-/*
- * nfs v3 access service
- */
-int
-nfsrv3_access(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, getret;
- char *cp2;
- struct mbuf *mb, *mreq, *mb2;
- struct vattr vattr, *vap = &vattr;
- u_long testmode, nfsmode;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(1, (struct vattr *)0);
- error = 0;
- goto nfsmout;
- }
- nfsmode = fxdr_unsigned(u_int32_t, *tl);
- if ((nfsmode & NFSV3ACCESS_READ) &&
- nfsrv_access(vp, VREAD, cred, rdonly, td, 0))
- nfsmode &= ~NFSV3ACCESS_READ;
- if (vp->v_type == VDIR)
- testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
- NFSV3ACCESS_DELETE);
- else
- testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
- if ((nfsmode & testmode) &&
- nfsrv_access(vp, VWRITE, cred, rdonly, td, 0))
- nfsmode &= ~testmode;
- if (vp->v_type == VDIR)
- testmode = NFSV3ACCESS_LOOKUP;
- else
- testmode = NFSV3ACCESS_EXECUTE;
- if ((nfsmode & testmode) &&
- nfsrv_access(vp, VEXEC, cred, rdonly, td, 0))
- nfsmode &= ~testmode;
- getret = VOP_GETATTR(vp, vap, cred, td);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, vap);
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(nfsmode);
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs getattr service
- */
-int
-nfsrv_getattr(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
- struct vattr va;
- register struct vattr *vap = &va;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(0);
- error = 0;
- goto nfsmout;
- }
- nqsrv_getl(vp, ND_READ);
- error = VOP_GETATTR(vp, vap, cred, td);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
- if (error) {
- error = 0;
- goto nfsmout;
- }
- nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
- nfsm_srvfillattr(vap, fp);
- /* fall through */
-
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs setattr service
- */
-int
-nfsrv_setattr(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct vattr va, preat;
- register struct vattr *vap = &va;
- register struct nfsv2_sattr *sp;
- register struct nfs_fattr *fp;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- u_quad_t frev;
- struct timespec guard;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto out;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- VATTR_NULL(vap);
- if (v3) {
- nfsm_srvsattr(vap);
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- gcheck = fxdr_unsigned(int, *tl);
- if (gcheck) {
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- fxdr_nfsv3time(tl, &guard);
- }
- } else {
- nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- /*
- * Nah nah nah nah na nah
- * There is a bug in the Sun client that puts 0xffff in the mode
- * field of sattr when it should put in 0xffffffff. The u_short
- * doesn't sign extend.
- * --> check the low order 2 bytes for 0xffff
- */
- if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
- vap->va_mode = nfstov_mode(sp->sa_mode);
- if (sp->sa_uid != nfs_xdrneg1)
- vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
- if (sp->sa_gid != nfs_xdrneg1)
- vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
- if (sp->sa_size != nfs_xdrneg1)
- vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
- if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
-#ifdef notyet
- fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
-#else
- vap->va_atime.tv_sec =
- fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
- vap->va_atime.tv_nsec = 0;
-#endif
- }
- if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
- fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
-
- }
-
- /*
- * Now that we have all the fields, lets do it.
- */
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * vp now an active resource, pay careful attention to cleanup
- */
-
- nqsrv_getl(vp, ND_WRITE);
- if (v3) {
- error = preat_ret = VOP_GETATTR(vp, &preat, cred, td);
- if (!error && gcheck &&
- (preat.va_ctime.tv_sec != guard.tv_sec ||
- preat.va_ctime.tv_nsec != guard.tv_nsec))
- error = NFSERR_NOT_SYNC;
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
- error = 0;
- goto nfsmout;
- }
- }
-
- /*
- * If the size is being changed write acces is required, otherwise
- * just check for a read only file system.
- */
- if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
- if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- error = EROFS;
- goto out;
- }
- } else {
- if (vp->v_type == VDIR) {
- error = EISDIR;
- goto out;
- } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
- td, 0)) != 0)
- goto out;
- }
- error = VOP_SETATTR(vp, vap, cred, td);
- postat_ret = VOP_GETATTR(vp, vap, cred, td);
- if (!error)
- error = postat_ret;
-out:
- if (vp != NULL)
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_WCCORFATTR(v3));
- if (v3) {
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
- error = 0;
- goto nfsmout;
- } else {
- /* v2 non-error case (see nfsm_reply). */
- nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- /* fall through */
-
-nfsmout:
- if (vp)
- vput(vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs lookup rpc
- */
-int
-nfsrv_lookup(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
- struct nameidata nd, ind, *ndp = &nd;
- struct vnode *vp, *dirp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, cache, len, dirattr_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vattr va, dirattr, *vap = &va;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- nfsm_srvnamesiz(len);
-
- pubflag = nfs_ispublicfh(fhp);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
-
- /*
- * namei failure, only dirp to cleanup. Clear out garbarge from
- * structure in case macros jump to nfsmout.
- */
-
- if (error) {
- if (dirp) {
- if (v3)
- dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
- td);
- vrele(dirp);
- dirp = NULL;
- }
- nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Locate index file for public filehandle
- *
- * error is 0 on entry and 0 on exit from this block.
- */
-
- if (pubflag) {
- if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
- /*
- * Setup call to lookup() to see if we can find
- * the index file. Arguably, this doesn't belong
- * in a kernel.. Ugh. If an error occurs, do not
- * try to install an index file and then clear the
- * error.
- *
- * When we replace nd with ind and redirect ndp,
- * maintenance of ni_startdir and ni_vp shift to
- * ind and we have to clean them up in the old nd.
- * However, the cnd resource continues to be maintained
- * via the original nd. Confused? You aren't alone!
- */
- ind = nd;
- VOP_UNLOCK(nd.ni_vp, 0, td);
- ind.ni_pathlen = strlen(nfs_pub.np_index);
- ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
- nfs_pub.np_index;
- ind.ni_startdir = nd.ni_vp;
- VREF(ind.ni_startdir);
-
- error = lookup(&ind);
- ind.ni_dvp = NULL;
-
- if (error == 0) {
- /*
- * Found an index file. Get rid of
- * the old references. transfer nd.ni_vp'
- */
- if (dirp)
- vrele(dirp);
- dirp = nd.ni_vp;
- nd.ni_vp = NULL;
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- ndp = &ind;
- }
- error = 0;
- }
- /*
- * If the public filehandle was used, check that this lookup
- * didn't result in a filehandle outside the publicly exported
- * filesystem. We clear the poor vp here to avoid lockups due
- * to NFS I/O.
- */
-
- if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
- error = EPERM;
- }
- }
-
- if (dirp) {
- if (v3)
- dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
- td);
- vrele(dirp);
- dirp = NULL;
- }
-
- /*
- * Resources at this point:
- * ndp->ni_vp may not be NULL
- *
- */
-
- if (error) {
- nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- error = 0;
- goto nfsmout;
- }
-
- nqsrv_getl(ndp->ni_startdir, ND_READ);
-
- /*
- * Clear out some resources prior to potentially blocking. This
- * is not as critical as ni_dvp resources in other routines, but
- * it helps.
- */
- vrele(ndp->ni_startdir);
- ndp->ni_startdir = NULL;
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- /*
- * Get underlying attribute, then release remaining resources ( for
- * the same potential blocking reason ) and reply.
- */
- vp = ndp->ni_vp;
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- error = VFS_VPTOFH(vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(vp, vap, cred, td);
-
- vput(vp);
- ndp->ni_vp = NULL;
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
- if (error) {
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- error = 0;
- goto nfsmout;
- }
- nfsm_srvfhtom(fhp, v3);
- if (v3) {
- nfsm_srvpostop_attr(0, vap);
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- } else {
- nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
-
-nfsmout:
- if (dirp)
- vrele(dirp);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (ndp->ni_startdir)
- vrele(ndp->ni_startdir);
- if (ndp->ni_vp)
- vput(ndp->ni_vp);
- return (error);
-}
-
-/*
- * nfs readlink service
- */
-int
-nfsrv_readlink(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
- register struct iovec *ivp = iv;
- register struct mbuf *mp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, i, tlen, len, getret;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
- struct vnode *vp = NULL;
- struct vattr attr;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io, *uiop = &io;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- mp2 = (struct mbuf *)0;
-#endif
- mp3 = NULL;
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- len = 0;
- i = 0;
- while (len < NFS_MAXPATHLEN) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- MCLGET(mp, M_TRYWAIT);
- mp->m_len = NFSMSIZ(mp);
- if (len == 0)
- mp3 = mp2 = mp;
- else {
- mp2->m_next = mp;
- mp2 = mp;
- }
- if ((len+mp->m_len) > NFS_MAXPATHLEN) {
- mp->m_len = NFS_MAXPATHLEN-len;
- len = NFS_MAXPATHLEN;
- } else
- len += mp->m_len;
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- i++;
- ivp++;
- }
- uiop->uio_iov = iv;
- uiop->uio_iovcnt = i;
- uiop->uio_offset = 0;
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_READ;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = (struct thread *)0;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvpostop_attr(1, (struct vattr *)0);
- error = 0;
- goto nfsmout;
- }
- if (vp->v_type != VLNK) {
- if (v3)
- error = EINVAL;
- else
- error = ENXIO;
- goto out;
- }
- nqsrv_getl(vp, ND_READ);
- error = VOP_READLINK(vp, uiop, cred);
-out:
- getret = VOP_GETATTR(vp, &attr, cred, td);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
- if (v3) {
- nfsm_srvpostop_attr(getret, &attr);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- }
- if (uiop->uio_resid > 0) {
- len -= uiop->uio_resid;
- tlen = nfsm_rndup(len);
- nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
- }
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(len);
- mb->m_next = mp3;
- mp3 = NULL;
-nfsmout:
- if (mp3)
- m_freem(mp3);
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs read service
- */
-int
-nfsrv_read(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct iovec *iv;
- struct iovec *iv2;
- register struct mbuf *m;
- register struct nfs_fattr *fp;
- register u_int32_t *tl;
- register int32_t t1;
- register int i;
- caddr_t bpos;
- int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret;
- int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct mbuf *m2;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io, *uiop = &io;
- struct vattr va, *vap = &va;
- struct nfsheur *nh;
- off_t off;
- int ioflag = 0;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if (v3) {
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- off = fxdr_hyper(tl);
- } else {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- off = (off_t)fxdr_unsigned(u_int32_t, *tl);
- }
- nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
-
- /*
- * Reference vp. If an error occurs, vp will be invalid, but we
- * have to NULL it just in case. The macros might goto nfsmout
- * as well.
- */
-
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- vp = NULL;
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvpostop_attr(1, (struct vattr *)0);
- error = 0;
- goto nfsmout;
- }
-
- if (vp->v_type != VREG) {
- if (v3)
- error = EINVAL;
- else
- error = (vp->v_type == VDIR) ? EISDIR : EACCES;
- }
- if (!error) {
- nqsrv_getl(vp, ND_READ);
- if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1);
- }
- getret = VOP_GETATTR(vp, vap, cred, td);
- if (!error)
- error = getret;
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, vap);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Calculate byte count to read
- */
-
- if (off >= vap->va_size)
- cnt = 0;
- else if ((off + reqlen) > vap->va_size)
- cnt = vap->va_size - off;
- else
- cnt = reqlen;
-
- /*
- * Calculate seqcount for heuristic
- */
-
- {
- int hi;
- int try = 4;
-
- /*
- * Locate best candidate
- */
-
- hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) & (NUM_HEURISTIC - 1);
- nh = &nfsheur[hi];
-
- while (try--) {
- if (nfsheur[hi].nh_vp == vp) {
- nh = &nfsheur[hi];
- break;
- }
- if (nfsheur[hi].nh_use > 0)
- --nfsheur[hi].nh_use;
- hi = (hi + 1) & (NUM_HEURISTIC - 1);
- if (nfsheur[hi].nh_use < nh->nh_use)
- nh = &nfsheur[hi];
- }
-
- if (nh->nh_vp != vp) {
- nh->nh_vp = vp;
- nh->nh_nextr = off;
- nh->nh_use = NHUSE_INIT;
- if (off == 0)
- nh->nh_seqcount = 4;
- else
- nh->nh_seqcount = 1;
- }
-
- /*
- * Calculate heuristic
- */
-
- if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) {
- if (++nh->nh_seqcount > 127)
- nh->nh_seqcount = 127;
- } else if (nh->nh_seqcount > 1) {
- nh->nh_seqcount = 1;
- } else {
- nh->nh_seqcount = 0;
- }
- nh->nh_use += NHUSE_INC;
- if (nh->nh_use > NHUSE_MAX)
- nh->nh_use = NHUSE_MAX;
- ioflag |= nh->nh_seqcount << 16;
- }
-
- nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
- if (v3) {
- nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- fp = (struct nfs_fattr *)tl;
- tl += (NFSX_V3FATTR / sizeof (u_int32_t));
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
- fp = (struct nfs_fattr *)tl;
- tl += (NFSX_V2FATTR / sizeof (u_int32_t));
- }
- len = left = nfsm_rndup(cnt);
- if (cnt > 0) {
- /*
- * Generate the mbuf list with the uio_iov ref. to it.
- */
- i = 0;
- m = m2 = mb;
- while (left > 0) {
- siz = min(M_TRAILINGSPACE(m), left);
- if (siz > 0) {
- left -= siz;
- i++;
- }
- if (left > 0) {
- MGET(m, M_TRYWAIT, MT_DATA);
- MCLGET(m, M_TRYWAIT);
- m->m_len = 0;
- m2->m_next = m;
- m2 = m;
- }
- }
- MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
- M_TEMP, M_WAITOK);
- uiop->uio_iov = iv2 = iv;
- m = mb;
- left = len;
- i = 0;
- while (left > 0) {
- if (m == NULL)
- panic("nfsrv_read iov");
- siz = min(M_TRAILINGSPACE(m), left);
- if (siz > 0) {
- iv->iov_base = mtod(m, caddr_t) + m->m_len;
- iv->iov_len = siz;
- m->m_len += siz;
- left -= siz;
- iv++;
- i++;
- }
- m = m->m_next;
- }
- uiop->uio_iovcnt = i;
- uiop->uio_offset = off;
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_READ;
- uiop->uio_segflg = UIO_SYSSPACE;
- error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
- off = uiop->uio_offset;
- nh->nh_nextr = off;
- FREE((caddr_t)iv2, M_TEMP);
- if (error || (getret = VOP_GETATTR(vp, vap, cred, td))) {
- if (!error)
- error = getret;
- m_freem(mreq);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, vap);
- error = 0;
- goto nfsmout;
- }
- } else {
- uiop->uio_resid = 0;
- }
- vput(vp);
- vp = NULL;
- nfsm_srvfillattr(vap, fp);
- tlen = len - uiop->uio_resid;
- cnt = cnt < tlen ? cnt : tlen;
- tlen = nfsm_rndup(cnt);
- if (len != tlen || tlen != cnt)
- nfsm_adj(mb, len - tlen, tlen - cnt);
- if (v3) {
- *tl++ = txdr_unsigned(cnt);
- if (len < reqlen)
- *tl++ = nfs_true;
- else
- *tl++ = nfs_false;
- }
- *tl = txdr_unsigned(cnt);
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs write service
- */
-int
-nfsrv_write(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct iovec *ivp;
- register int i, cnt;
- register struct mbuf *mp;
- register struct nfs_fattr *fp;
- struct iovec *iv;
- struct vattr va, forat;
- register struct vattr *vap = &va;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, len, forat_ret = 1;
- int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
- int stable = NFSV3WRITE_FILESYNC;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io, *uiop = &io;
- off_t off;
- u_quad_t frev;
- struct mount *mntp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (mrep == NULL) {
- *mrq = NULL;
- error = 0;
- goto nfsmout;
- }
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- if ((error = VFS_FHTOVP(mntp, &fhp->fh_fid, &vp)) != 0) {
- mntp = NULL;
- goto ereply;
- }
- (void) vn_start_write(vp, &mntp, V_WAIT);
- vput(vp);
- vp = NULL;
- if (v3) {
- nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- off = fxdr_hyper(tl);
- tl += 3;
- stable = fxdr_unsigned(int, *tl++);
- } else {
- nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
- tl += 2;
- if (nfs_async)
- stable = NFSV3WRITE_UNSTABLE;
- }
- retlen = len = fxdr_unsigned(int32_t, *tl);
- cnt = i = 0;
-
- /*
- * For NFS Version 2, it is not obvious what a write of zero length
- * should do, but I might as well be consistent with Version 3,
- * which is to return ok so long as there are no permission problems.
- */
- if (len > 0) {
- zeroing = 1;
- mp = mrep;
- while (mp) {
- if (mp == md) {
- zeroing = 0;
- adjust = dpos - mtod(mp, caddr_t);
- mp->m_len -= adjust;
- if (mp->m_len > 0 && adjust > 0)
- NFSMADV(mp, adjust);
- }
- if (zeroing)
- mp->m_len = 0;
- else if (mp->m_len > 0) {
- i += mp->m_len;
- if (i > len) {
- mp->m_len -= (i - len);
- zeroing = 1;
- }
- if (mp->m_len > 0)
- cnt++;
- }
- mp = mp->m_next;
- }
- }
- if (len > NFS_MAXDATA || len < 0 || i < len) {
- error = EIO;
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- error = 0;
- goto nfsmout;
- }
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- vp = NULL;
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- error = 0;
- goto nfsmout;
- }
- if (v3)
- forat_ret = VOP_GETATTR(vp, &forat, cred, td);
- if (vp->v_type != VREG) {
- if (v3)
- error = EINVAL;
- else
- error = (vp->v_type == VDIR) ? EISDIR : EACCES;
- }
- if (!error) {
- nqsrv_getl(vp, ND_WRITE);
- error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
- }
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- error = 0;
- goto nfsmout;
- }
-
- if (len > 0) {
- MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
- M_WAITOK);
- uiop->uio_iov = iv = ivp;
- uiop->uio_iovcnt = cnt;
- mp = mrep;
- while (mp) {
- if (mp->m_len > 0) {
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- ivp++;
- }
- mp = mp->m_next;
- }
-
- /*
- * XXX
- * The IO_METASYNC flag indicates that all metadata (and not just
- * enough to ensure data integrity) mus be written to stable storage
- * synchronously.
- * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
- */
- if (stable == NFSV3WRITE_UNSTABLE)
- ioflags = IO_NODELOCKED;
- else if (stable == NFSV3WRITE_DATASYNC)
- ioflags = (IO_SYNC | IO_NODELOCKED);
- else
- ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_WRITE;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = (struct thread *)0;
- uiop->uio_offset = off;
- error = VOP_WRITE(vp, uiop, ioflags, cred);
- nfsstats.srvvop_writes++;
- FREE((caddr_t)iv, M_TEMP);
- }
- aftat_ret = VOP_GETATTR(vp, vap, cred, td);
- vput(vp);
- vp = NULL;
- if (!error)
- error = aftat_ret;
-ereply:
- nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
- 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
- if (v3) {
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(retlen);
- /*
- * If nfs_async is set, then pretend the write was FILESYNC.
- */
- if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
- *tl++ = txdr_unsigned(stable);
- else
- *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
- /*
- * Actually, there is no need to txdr these fields,
- * but it may make the values more human readable,
- * for debugging purposes.
- */
- if (nfsver.tv_sec == 0)
- nfsver = boottime;
- *tl++ = txdr_unsigned(nfsver.tv_sec);
- *tl = txdr_unsigned(nfsver.tv_usec);
- } else {
- /* v2, non-error case (see nfsm_reply). */
- nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
-nfsmout:
- if (vp)
- vput(vp);
- vn_finished_write(mntp);
- return(error);
-}
-
-/*
- * NFS write service with write gathering support. Called when
- * nfsrvw_procrastinate > 0.
- * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
- * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
- * Jan. 1994.
- */
-int
-nfsrv_writegather(ndp, slp, td, mrq)
- struct nfsrv_descript **ndp;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- register struct iovec *ivp;
- register struct mbuf *mp;
- register struct nfsrv_descript *wp, *nfsd, *owp, *swp;
- register struct nfs_fattr *fp;
- register int i;
- struct iovec *iov;
- struct nfsrvw_delayhash *wpp;
- struct ucred *cred;
- struct vattr va, forat;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos, dpos;
- int error = 0, rdonly, cache, len, forat_ret = 1;
- int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq, *mrep, *md;
- struct vnode *vp = NULL;
- struct uio io, *uiop = &io;
- u_quad_t frev, cur_usec;
- struct mount *mntp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- i = 0;
- len = 0;
-#endif
- *mrq = NULL;
- if (*ndp) {
- nfsd = *ndp;
- *ndp = NULL;
- mrep = nfsd->nd_mrep;
- md = nfsd->nd_md;
- dpos = nfsd->nd_dpos;
- cred = &nfsd->nd_cr;
- v3 = (nfsd->nd_flag & ND_NFSV3);
- LIST_INIT(&nfsd->nd_coalesce);
- nfsd->nd_mreq = NULL;
- nfsd->nd_stable = NFSV3WRITE_FILESYNC;
- cur_usec = nfs_curusec();
- nfsd->nd_time = cur_usec +
- (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
-
- /*
- * Now, get the write header..
- */
- nfsm_srvmtofh(&nfsd->nd_fh);
- if (v3) {
- nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- nfsd->nd_off = fxdr_hyper(tl);
- tl += 3;
- nfsd->nd_stable = fxdr_unsigned(int, *tl++);
- } else {
- nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
- tl += 2;
- if (nfs_async)
- nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
- }
- len = fxdr_unsigned(int32_t, *tl);
- nfsd->nd_len = len;
- nfsd->nd_eoff = nfsd->nd_off + len;
-
- /*
- * Trim the header out of the mbuf list and trim off any trailing
- * junk so that the mbuf list has only the write data.
- */
- zeroing = 1;
- i = 0;
- mp = mrep;
- while (mp) {
- if (mp == md) {
- zeroing = 0;
- adjust = dpos - mtod(mp, caddr_t);
- mp->m_len -= adjust;
- if (mp->m_len > 0 && adjust > 0)
- NFSMADV(mp, adjust);
- }
- if (zeroing)
- mp->m_len = 0;
- else {
- i += mp->m_len;
- if (i > len) {
- mp->m_len -= (i - len);
- zeroing = 1;
- }
- }
- mp = mp->m_next;
- }
- if (len > NFS_MAXDATA || len < 0 || i < len) {
-nfsmout:
- m_freem(mrep);
- error = EIO;
- nfsm_writereply(2 * NFSX_UNSIGNED, v3);
- if (v3)
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
- nfsd->nd_mreq = mreq;
- nfsd->nd_mrep = NULL;
- nfsd->nd_time = 0;
- }
-
- /*
- * Add this entry to the hash and time queues.
- */
- s = splsoftclock();
- owp = NULL;
- wp = slp->ns_tq.lh_first;
- while (wp && wp->nd_time < nfsd->nd_time) {
- owp = wp;
- wp = wp->nd_tq.le_next;
- }
- NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
- if (owp) {
- LIST_INSERT_AFTER(owp, nfsd, nd_tq);
- } else {
- LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
- }
- if (nfsd->nd_mrep) {
- wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
- owp = NULL;
- wp = wpp->lh_first;
- while (wp &&
- bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
- owp = wp;
- wp = wp->nd_hash.le_next;
- }
- while (wp && wp->nd_off < nfsd->nd_off &&
- !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
- owp = wp;
- wp = wp->nd_hash.le_next;
- }
- if (owp) {
- LIST_INSERT_AFTER(owp, nfsd, nd_hash);
-
- /*
- * Search the hash list for overlapping entries and
- * coalesce.
- */
- for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
- wp = nfsd->nd_hash.le_next;
- if (NFSW_SAMECRED(owp, nfsd))
- nfsrvw_coalesce(owp, nfsd);
- }
- } else {
- LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
- }
- }
- splx(s);
- }
-
- /*
- * Now, do VOP_WRITE()s for any one(s) that need to be done now
- * and generate the associated reply mbuf list(s).
- */
-loop1:
- cur_usec = nfs_curusec();
- s = splsoftclock();
- for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) {
- owp = nfsd->nd_tq.le_next;
- if (nfsd->nd_time > cur_usec)
- break;
- if (nfsd->nd_mreq)
- continue;
- NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
- LIST_REMOVE(nfsd, nd_tq);
- LIST_REMOVE(nfsd, nd_hash);
- splx(s);
- mrep = nfsd->nd_mrep;
- nfsd->nd_mrep = NULL;
- cred = &nfsd->nd_cr;
- v3 = (nfsd->nd_flag & ND_NFSV3);
- forat_ret = aftat_ret = 1;
- error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
- nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (!error) {
- if (v3)
- forat_ret = VOP_GETATTR(vp, &forat, cred, td);
- if (vp->v_type != VREG) {
- if (v3)
- error = EINVAL;
- else
- error = (vp->v_type == VDIR) ? EISDIR : EACCES;
- }
- } else {
- vp = NULL;
- }
- if (!error) {
- nqsrv_getl(vp, ND_WRITE);
- error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
- }
-
- if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
- ioflags = IO_NODELOCKED;
- else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
- ioflags = (IO_SYNC | IO_NODELOCKED);
- else
- ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
- uiop->uio_rw = UIO_WRITE;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = (struct thread *)0;
- uiop->uio_offset = nfsd->nd_off;
- uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
- if (uiop->uio_resid > 0) {
- mp = mrep;
- i = 0;
- while (mp) {
- if (mp->m_len > 0)
- i++;
- mp = mp->m_next;
- }
- uiop->uio_iovcnt = i;
- MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
- M_TEMP, M_WAITOK);
- uiop->uio_iov = ivp = iov;
- mp = mrep;
- while (mp) {
- if (mp->m_len > 0) {
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- ivp++;
- }
- mp = mp->m_next;
- }
- if (!error) {
- if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
- VOP_UNLOCK(vp, 0, td);
- error = vn_start_write(NULL, &mntp, V_WAIT);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- }
- }
- if (!error) {
- error = VOP_WRITE(vp, uiop, ioflags, cred);
- nfsstats.srvvop_writes++;
- vn_finished_write(mntp);
- }
- FREE((caddr_t)iov, M_TEMP);
- }
- m_freem(mrep);
- if (vp) {
- aftat_ret = VOP_GETATTR(vp, &va, cred, td);
- vput(vp);
- vp = NULL;
- }
-
- /*
- * Loop around generating replies for all write rpcs that have
- * now been completed.
- */
- swp = nfsd;
- do {
- NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
- if (error) {
- nfsm_writereply(NFSX_WCCDATA(v3), v3);
- if (v3) {
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
- }
- } else {
- nfsm_writereply(NFSX_PREOPATTR(v3) +
- NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
- NFSX_WRITEVERF(v3), v3);
- if (v3) {
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
- nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nfsd->nd_len);
- *tl++ = txdr_unsigned(swp->nd_stable);
- /*
- * Actually, there is no need to txdr these fields,
- * but it may make the values more human readable,
- * for debugging purposes.
- */
- if (nfsver.tv_sec == 0)
- nfsver = boottime;
- *tl++ = txdr_unsigned(nfsver.tv_sec);
- *tl = txdr_unsigned(nfsver.tv_usec);
- } else {
- nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(&va, fp);
- }
- }
- nfsd->nd_mreq = mreq;
- if (nfsd->nd_mrep)
- panic("nfsrv_write: nd_mrep not free");
-
- /*
- * Done. Put it at the head of the timer queue so that
- * the final phase can return the reply.
- */
- s = splsoftclock();
- if (nfsd != swp) {
- nfsd->nd_time = 0;
- LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
- }
- nfsd = swp->nd_coalesce.lh_first;
- if (nfsd) {
- LIST_REMOVE(nfsd, nd_tq);
- }
- splx(s);
- } while (nfsd);
- s = splsoftclock();
- swp->nd_time = 0;
- LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
- splx(s);
- goto loop1;
- }
- splx(s);
-
- /*
- * Search for a reply to return.
- */
- s = splsoftclock();
- for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next)
- if (nfsd->nd_mreq) {
- NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
- LIST_REMOVE(nfsd, nd_tq);
- *mrq = nfsd->nd_mreq;
- *ndp = nfsd;
- break;
- }
- splx(s);
- return (0);
-}
-
-/*
- * Coalesce the write request nfsd into owp. To do this we must:
- * - remove nfsd from the queues
- * - merge nfsd->nd_mrep into owp->nd_mrep
- * - update the nd_eoff and nd_stable for owp
- * - put nfsd on owp's nd_coalesce list
- * NB: Must be called at splsoftclock().
- */
-static void
-nfsrvw_coalesce(owp, nfsd)
- register struct nfsrv_descript *owp;
- register struct nfsrv_descript *nfsd;
-{
- register int overlap;
- register struct mbuf *mp;
- struct nfsrv_descript *p;
-
- NFS_DPF(WG, ("C%03x-%03x",
- nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
- LIST_REMOVE(nfsd, nd_hash);
- LIST_REMOVE(nfsd, nd_tq);
- if (owp->nd_eoff < nfsd->nd_eoff) {
- overlap = owp->nd_eoff - nfsd->nd_off;
- if (overlap < 0)
- panic("nfsrv_coalesce: bad off");
- if (overlap > 0)
- m_adj(nfsd->nd_mrep, overlap);
- mp = owp->nd_mrep;
- while (mp->m_next)
- mp = mp->m_next;
- mp->m_next = nfsd->nd_mrep;
- owp->nd_eoff = nfsd->nd_eoff;
- } else
- m_freem(nfsd->nd_mrep);
- nfsd->nd_mrep = NULL;
- if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
- owp->nd_stable = NFSV3WRITE_FILESYNC;
- else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
- owp->nd_stable == NFSV3WRITE_UNSTABLE)
- owp->nd_stable = NFSV3WRITE_DATASYNC;
- LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
-
- /*
- * If nfsd had anything else coalesced into it, transfer them
- * to owp, otherwise their replies will never get sent.
- */
- for (p = nfsd->nd_coalesce.lh_first; p;
- p = nfsd->nd_coalesce.lh_first) {
- LIST_REMOVE(p, nd_tq);
- LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
- }
-}
-
-/*
- * nfs create service
- * now does a truncate to 0 length via. setattr if it already exists
- */
-int
-nfsrv_create(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
- struct vattr va, dirfor, diraft;
- register struct vattr *vap = &va;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- struct nameidata nd;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdev, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
- caddr_t cp;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *dirp = (struct vnode *)0;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev, tempsize;
- u_char cverf[NFSX_V3CREATEVERF];
- struct mount *mp = NULL;
- struct vnode *vp;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- rdev = 0;
-#endif
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto ereply;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- nfsm_srvnamesiz(len);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
-
- /*
- * Call namei and do initial cleanup to get a few things
- * out of the way. If we get an initial error we cleanup
- * and return here to avoid special-casing the invalid nd
- * structure through the rest of the case. dirp may be
- * set even if an error occurs, but the nd structure will not
- * be valid at all if an error occurs so we have to invalidate it
- * prior to calling nfsm_reply ( which might goto nfsmout ).
- */
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp) {
- if (v3) {
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
- td);
- } else {
- vrele(dirp);
- dirp = NULL;
- }
- }
- if (error) {
- nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * No error. Continue. State:
- *
- * startdir is valid ( we release this immediately )
- * dirp may be valid
- * nd.ni_vp may be valid
- * nd.ni_dvp is valid
- *
- * The error state is set through the code and we may also do some
- * opportunistic releasing of vnodes to avoid holding locks through
- * NFS I/O. The cleanup at the end is a catch-all
- */
-
- VATTR_NULL(vap);
- if (v3) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- how = fxdr_unsigned(int, *tl);
- switch (how) {
- case NFSV3CREATE_GUARDED:
- if (nd.ni_vp) {
- error = EEXIST;
- break;
- }
- /* fall through */
- case NFSV3CREATE_UNCHECKED:
- nfsm_srvsattr(vap);
- break;
- case NFSV3CREATE_EXCLUSIVE:
- nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
- bcopy(cp, cverf, NFSX_V3CREATEVERF);
- exclusive_flag = 1;
- if (nd.ni_vp == NULL)
- vap->va_mode = 0;
- break;
- };
- vap->va_type = VREG;
- } else {
- nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
- if (vap->va_type == VNON)
- vap->va_type = VREG;
- vap->va_mode = nfstov_mode(sp->sa_mode);
- switch (vap->va_type) {
- case VREG:
- tsize = fxdr_unsigned(int32_t, sp->sa_size);
- if (tsize != -1)
- vap->va_size = (u_quad_t)tsize;
- break;
- case VCHR:
- case VBLK:
- case VFIFO:
- rdev = fxdr_unsigned(long, sp->sa_size);
- break;
- default:
- break;
- };
- }
-
- /*
- * Iff doesn't exist, create it
- * otherwise just truncate to 0 length
- * should I set the mode too ?
- *
- * The only possible error we can have at this point is EEXIST.
- * nd.ni_vp will also be non-NULL in that case.
- */
- if (nd.ni_vp == NULL) {
- if (vap->va_type == VREG || vap->va_type == VSOCK) {
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error)
- NDFREE(&nd, NDF_ONLY_PNBUF);
- else {
- nfsrv_object_create(nd.ni_vp);
- if (exclusive_flag) {
- exclusive_flag = 0;
- VATTR_NULL(vap);
- bcopy(cverf, (caddr_t)&vap->va_atime,
- NFSX_V3CREATEVERF);
- error = VOP_SETATTR(nd.ni_vp, vap, cred,
- td);
- }
- }
- } else if (
- vap->va_type == VCHR ||
- vap->va_type == VBLK ||
- vap->va_type == VFIFO
- ) {
- /*
- * Handle SysV FIFO node special cases. All other
- * devices require super user to access.
- */
- if (vap->va_type == VCHR && rdev == 0xffffffff)
- vap->va_type = VFIFO;
- if (vap->va_type != VFIFO &&
- (error = suser_xxx(cred, 0, 0))) {
- goto nfsmreply0;
- }
- vap->va_rdev = rdev;
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
-
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- goto nfsmreply0;
- }
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
-
- /*
- * release dvp prior to lookup
- */
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- /*
- * Setup for lookup.
- *
- * Even though LOCKPARENT was cleared, ni_dvp may
- * be garbage.
- */
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
- nd.ni_cnd.cn_thread = td;
- nd.ni_cnd.cn_cred = cred;
-
- error = lookup(&nd);
- nd.ni_dvp = NULL;
-
- if (error != 0) {
- nfsm_reply(0);
- /* fall through on certain errors */
- }
- nfsrv_object_create(nd.ni_vp);
- if (nd.ni_cnd.cn_flags & ISSYMLINK) {
- error = EINVAL;
- goto nfsmreply0;
- }
- } else {
- error = ENXIO;
- }
- } else {
- if (vap->va_size != -1) {
- error = nfsrv_access(nd.ni_vp, VWRITE, cred,
- (nd.ni_cnd.cn_flags & RDONLY), td, 0);
- if (!error) {
- nqsrv_getl(nd.ni_vp, ND_WRITE);
- tempsize = vap->va_size;
- VATTR_NULL(vap);
- vap->va_size = tempsize;
- error = VOP_SETATTR(nd.ni_vp, vap, cred,
- td);
- }
- }
- }
-
- if (!error) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
- error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
- }
- if (v3) {
- if (exclusive_flag && !error &&
- bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
- error = EEXIST;
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
- vrele(dirp);
- dirp = NULL;
- }
-ereply:
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- } else {
- /* v2 non-error case (see nfsm_reply). */
- nfsm_srvfhtom(fhp, v3);
- nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- goto nfsmout;
-
-nfsmreply0:
- nfsm_reply(0);
- error = 0;
- /* fall through */
-
-nfsmout:
- if (nd.ni_startdir) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- }
- if (dirp)
- vrele(dirp);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs v3 mknod service
- */
-int
-nfsrv_mknod(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct vattr va, dirfor, diraft;
- register struct vattr *vap = &va;
- register u_int32_t *tl;
- struct nameidata nd;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
- u_int32_t major, minor;
- enum vtype vtyp;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *vp, *dirp = (struct vnode *)0;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto ereply;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvnamesiz(len);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
-
- /*
- * Handle nfs_namei() call. If an error occurs, the nd structure
- * is not valid. However, nfsm_*() routines may still jump to
- * nfsmout.
- */
-
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp)
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, td);
- if (error) {
- nfsm_reply(NFSX_WCCDATA(1));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- vtyp = nfsv3tov_type(*tl);
- if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
- error = NFSERR_BADTYPE;
- goto out;
- }
- VATTR_NULL(vap);
- nfsm_srvsattr(vap);
- if (vtyp == VCHR || vtyp == VBLK) {
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- major = fxdr_unsigned(u_int32_t, *tl++);
- minor = fxdr_unsigned(u_int32_t, *tl);
- vap->va_rdev = makeudev(major, minor);
- }
-
- /*
- * Iff doesn't exist, create it.
- */
- if (nd.ni_vp) {
- error = EEXIST;
- goto out;
- }
- vap->va_type = vtyp;
- if (vtyp == VSOCK) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error)
- NDFREE(&nd, NDF_ONLY_PNBUF);
- } else {
- if (vtyp != VFIFO && (error = suser_xxx(cred, 0, 0)))
- goto out;
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
-
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- goto out;
- }
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
-
- /*
- * Release dvp prior to lookup
- */
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
- nd.ni_cnd.cn_thread = td;
- nd.ni_cnd.cn_cred = td->td_proc->p_ucred;
-
- error = lookup(&nd);
- nd.ni_dvp = NULL;
-
- if (error)
- goto out;
- if (nd.ni_cnd.cn_flags & ISSYMLINK)
- error = EINVAL;
- }
-
- /*
- * send response, cleanup, return.
- */
-out:
- if (nd.ni_startdir) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- }
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
- }
- vp = nd.ni_vp;
- if (!error) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- error = VFS_VPTOFH(vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(vp, vap, cred, td);
- vput(vp);
- vp = NULL;
- nd.ni_vp = NULL;
- }
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
- if (dirp) {
- vrele(dirp);
- dirp = NULL;
- }
-ereply:
- nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- vn_finished_write(mp);
- return (0);
-nfsmout:
- if (dirp)
- vrele(dirp);
- if (nd.ni_startdir)
- vrele(nd.ni_startdir);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs remove service
- */
-int
-nfsrv_remove(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct nameidata nd;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mreq;
- struct vnode *dirp;
- struct vattr dirfor, diraft;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev;
- struct mount *mp = NULL;
- struct vnode *vp;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto ereply;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvnamesiz(len);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = DELETE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp) {
- if (v3) {
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
- td);
- } else {
- vrele(dirp);
- dirp = NULL;
- }
- }
- if (error == 0) {
- if (nd.ni_vp->v_type == VDIR) {
- error = EPERM; /* POSIX */
- goto out;
- }
- /*
- * The root of a mounted filesystem cannot be deleted.
- */
- if (nd.ni_vp->v_flag & VROOT) {
- error = EBUSY;
- goto out;
- }
-out:
- if (!error) {
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- nqsrv_getl(nd.ni_vp, ND_WRITE);
- error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- }
- }
- if (dirp && v3) {
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
- vrele(dirp);
- dirp = NULL;
- }
-ereply:
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- }
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs rename service
- */
-int
-nfsrv_rename(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, cache, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
- int tdirfor_ret = 1, tdiraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mreq;
- struct nameidata fromnd, tond;
- struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
- struct vnode *tdirp = (struct vnode *)0;
- struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
- nfsfh_t fnfh, tnfh;
- fhandle_t *ffhp, *tfhp;
- u_quad_t frev;
- uid_t saved_uid;
- struct mount *mp = NULL;
- struct vnode *vp;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- fvp = (struct vnode *)0;
-#endif
- ffhp = &fnfh.fh_generic;
- tfhp = &tnfh.fh_generic;
-
- /*
- * Clear fields incase goto nfsmout occurs from macro.
- */
-
- ndclear(&fromnd);
- ndclear(&tond);
-
- nfsm_srvmtofh(ffhp);
- if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out1;
- }
- if ((error = VFS_FHTOVP(mp, &ffhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto out1;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvnamesiz(len);
- /*
- * Remember our original uid so that we can reset cr_uid before
- * the second nfs_namei() call, in case it is remapped.
- */
- saved_uid = cred->cr_uid;
- fromnd.ni_cnd.cn_cred = cred;
- fromnd.ni_cnd.cn_nameiop = DELETE;
- fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
- error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
- &dpos, &fdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (fdirp) {
- if (v3) {
- fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
- td);
- } else {
- vrele(fdirp);
- fdirp = NULL;
- }
- }
- if (error) {
- nfsm_reply(2 * NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
- nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
- error = 0;
- goto nfsmout;
- }
- fvp = fromnd.ni_vp;
- nfsm_srvmtofh(tfhp);
- nfsm_strsiz(len2, NFS_MAXNAMLEN);
- cred->cr_uid = saved_uid;
- tond.ni_cnd.cn_cred = cred;
- tond.ni_cnd.cn_nameiop = RENAME;
- tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
- error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
- &dpos, &tdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (tdirp) {
- if (v3) {
- tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
- td);
- } else {
- vrele(tdirp);
- tdirp = NULL;
- }
- }
- if (error)
- goto out1;
-
- tdvp = tond.ni_dvp;
- tvp = tond.ni_vp;
- if (tvp != NULL) {
- if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
- if (v3)
- error = EEXIST;
- else
- error = EISDIR;
- goto out;
- } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
- if (v3)
- error = EEXIST;
- else
- error = ENOTDIR;
- goto out;
- }
- if (tvp->v_type == VDIR && tvp->v_mountedhere) {
- if (v3)
- error = EXDEV;
- else
- error = ENOTEMPTY;
- goto out;
- }
- }
- if (fvp->v_type == VDIR && fvp->v_mountedhere) {
- if (v3)
- error = EXDEV;
- else
- error = ENOTEMPTY;
- goto out;
- }
- if (fvp->v_mount != tdvp->v_mount) {
- if (v3)
- error = EXDEV;
- else
- error = ENOTEMPTY;
- goto out;
- }
- if (fvp == tdvp) {
- if (v3)
- error = EINVAL;
- else
- error = ENOTEMPTY;
- }
- /*
- * If source is the same as the destination (that is the
- * same vnode with the same name in the same directory),
- * then there is nothing to do.
- */
- if (fvp == tvp && fromnd.ni_dvp == tdvp &&
- fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
- !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
- fromnd.ni_cnd.cn_namelen))
- error = -1;
-out:
- if (!error) {
- /*
- * The VOP_RENAME function releases all vnode references &
- * locks prior to returning so we need to clear the pointers
- * to bypass cleanup code later on.
- */
- nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
- nqsrv_getl(tdvp, ND_WRITE);
- if (tvp) {
- nqsrv_getl(tvp, ND_WRITE);
- }
- error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
- tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
- fromnd.ni_dvp = NULL;
- fromnd.ni_vp = NULL;
- tond.ni_dvp = NULL;
- tond.ni_vp = NULL;
- if (error) {
- fromnd.ni_cnd.cn_flags &= ~HASBUF;
- tond.ni_cnd.cn_flags &= ~HASBUF;
- }
- } else {
- if (error == -1)
- error = 0;
- }
- /* fall through */
-
-out1:
- if (fdirp)
- fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, td);
- if (tdirp)
- tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td);
- nfsm_reply(2 * NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
- nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- /*
- * Clear out tond related fields
- */
- if (tdirp)
- vrele(tdirp);
- if (tond.ni_startdir)
- vrele(tond.ni_startdir);
- NDFREE(&tond, NDF_ONLY_PNBUF);
- if (tond.ni_dvp) {
- if (tond.ni_dvp == tond.ni_vp)
- vrele(tond.ni_dvp);
- else
- vput(tond.ni_dvp);
- }
- if (tond.ni_vp)
- vput(tond.ni_vp);
-
- /*
- * Clear out fromnd related fields
- */
- if (fdirp)
- vrele(fdirp);
- if (fromnd.ni_startdir)
- vrele(fromnd.ni_startdir);
- NDFREE(&fromnd, NDF_ONLY_PNBUF);
- if (fromnd.ni_dvp)
- vrele(fromnd.ni_dvp);
- if (fromnd.ni_vp)
- vrele(fromnd.ni_vp);
-
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs link service
- */
-int
-nfsrv_link(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct nameidata nd;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
- int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mreq;
- struct vnode *vp = NULL, *xp, *dirp = (struct vnode *)0;
- struct vattr dirfor, diraft, at;
- nfsfh_t nfh, dnfh;
- fhandle_t *fhp, *dfhp;
- u_quad_t frev;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- dfhp = &dnfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto ereply;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvmtofh(dfhp);
- nfsm_srvnamesiz(len);
-
- error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- nfsm_srvpostop_attr(getret, &at);
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- vp = NULL;
- error = 0;
- goto nfsmout;
- }
- if (vp->v_type == VDIR) {
- error = EPERM; /* POSIX */
- goto out1;
- }
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT;
- error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp) {
- if (v3) {
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
- td);
- } else {
- vrele(dirp);
- dirp = NULL;
- }
- }
- if (error)
- goto out1;
-
- xp = nd.ni_vp;
- if (xp != NULL) {
- error = EEXIST;
- goto out;
- }
- xp = nd.ni_dvp;
- if (vp->v_mount != xp->v_mount)
- error = EXDEV;
-out:
- if (!error) {
- nqsrv_getl(vp, ND_WRITE);
- nqsrv_getl(xp, ND_WRITE);
- error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- }
- /* fall through */
-
-out1:
- if (v3)
- getret = VOP_GETATTR(vp, &at, cred, td);
- if (dirp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
-ereply:
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- }
- /* fall through */
-
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (dirp)
- vrele(dirp);
- if (vp)
- vrele(vp);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vrele(nd.ni_vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs symbolic link service
- */
-int
-nfsrv_symlink(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct vattr va, dirfor, diraft;
- struct nameidata nd;
- register struct vattr *vap = &va;
- register u_int32_t *tl;
- register int32_t t1;
- struct nfsv2_sattr *sp;
- char *bpos, *pathcp = (char *)0, *cp2;
- struct uio io;
- struct iovec iv;
- int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq, *mb2;
- struct vnode *dirp = (struct vnode *)0;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev;
- struct mount *mp = NULL;
- struct vnode *vp;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto out;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvnamesiz(len);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp) {
- if (v3) {
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
- td);
- } else {
- vrele(dirp);
- dirp = NULL;
- }
- }
- if (error)
- goto out;
-
- VATTR_NULL(vap);
- if (v3)
- nfsm_srvsattr(vap);
- nfsm_strsiz(len2, NFS_MAXPATHLEN);
- MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
- iv.iov_base = pathcp;
- iv.iov_len = len2;
- io.uio_resid = len2;
- io.uio_offset = 0;
- io.uio_iov = &iv;
- io.uio_iovcnt = 1;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = (struct thread *)0;
- nfsm_mtouio(&io, len2);
- if (!v3) {
- nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- vap->va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
- }
- *(pathcp + len2) = '\0';
- if (nd.ni_vp) {
- error = EEXIST;
- goto out;
- }
-
- /*
- * issue symlink op. SAVESTART is set so the underlying path component
- * is only freed by the VOP if an error occurs.
- */
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
- if (error)
- NDFREE(&nd, NDF_ONLY_PNBUF);
- else {
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
- }
- /*
- * releases directory prior to potential lookup op.
- */
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- if (error == 0) {
- if (v3) {
- /*
- * Issue lookup. Leave SAVESTART set so we can easily free
- * the name buffer later on.
- *
- * since LOCKPARENT is not set, ni_dvp will be garbage on
- * return whether an error occurs or not.
- */
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
- nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
- nd.ni_cnd.cn_thread = td;
- nd.ni_cnd.cn_cred = cred;
-
- error = lookup(&nd);
- nd.ni_dvp = NULL;
-
- if (error == 0) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
- error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(nd.ni_vp, vap, cred,
- td);
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
- }
- }
- }
-out:
- /*
- * These releases aren't strictly required, does even doing them
- * make any sense? XXX can nfsm_reply() block?
- */
- if (pathcp) {
- FREE(pathcp, M_TEMP);
- pathcp = NULL;
- }
- if (dirp) {
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
- vrele(dirp);
- dirp = NULL;
- }
- if (nd.ni_startdir) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- }
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vrele(nd.ni_vp);
- if (nd.ni_startdir)
- vrele(nd.ni_startdir);
- if (dirp)
- vrele(dirp);
- if (pathcp)
- FREE(pathcp, M_TEMP);
-
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs mkdir service
- */
-int
-nfsrv_mkdir(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct vattr va, dirfor, diraft;
- register struct vattr *vap = &va;
- register struct nfs_fattr *fp;
- struct nameidata nd;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *dirp = NULL;
- int vpexcl = 0;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev;
- struct mount *mp = NULL;
- struct vnode *vp;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto out;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvnamesiz(len);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT;
-
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp) {
- if (v3) {
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
- td);
- } else {
- vrele(dirp);
- dirp = NULL;
- }
- }
- if (error) {
- nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
- VATTR_NULL(vap);
- if (v3) {
- nfsm_srvsattr(vap);
- } else {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- vap->va_mode = nfstov_mode(*tl++);
- }
-
- /*
- * At this point nd.ni_dvp is referenced and exclusively locked and
- * nd.ni_vp, if it exists, is referenced but not locked.
- */
-
- vap->va_type = VDIR;
- if (nd.ni_vp != NULL) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- error = EEXIST;
- goto out;
- }
-
- /*
- * Issue mkdir op. Since SAVESTART is not set, the pathname
- * component is freed by the VOP call. This will fill-in
- * nd.ni_vp, reference, and exclusively lock it.
- */
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vpexcl = 1;
-
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- if (!error) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
- error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
- }
-out:
- if (dirp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- } else {
- /* v2, non-error case (see nfsm_reply) */
- nfsm_srvfhtom(fhp, v3);
- nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- if (dirp)
- vrele(dirp);
- if (nd.ni_dvp) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp == nd.ni_vp && vpexcl)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp) {
- if (vpexcl)
- vput(nd.ni_vp);
- else
- vrele(nd.ni_vp);
- }
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs rmdir service
- */
-int
-nfsrv_rmdir(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mreq;
- struct vnode *vp, *dirp = (struct vnode *)0;
- struct vattr dirfor, diraft;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct nameidata nd;
- u_quad_t frev;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto out;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_srvnamesiz(len);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = DELETE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
- error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
- if (dirp) {
- if (v3) {
- dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
- td);
- } else {
- vrele(dirp);
- dirp = NULL;
- }
- }
- if (error) {
- nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
- vp = nd.ni_vp;
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- goto out;
- }
- /*
- * No rmdir "." please.
- */
- if (nd.ni_dvp == vp) {
- error = EINVAL;
- goto out;
- }
- /*
- * The root of a mounted filesystem cannot be deleted.
- */
- if (vp->v_flag & VROOT)
- error = EBUSY;
-out:
- /*
- * Issue or abort op. Since SAVESTART is not set, path name
- * component is freed by the VOP after either.
- */
- if (!error) {
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- nqsrv_getl(vp, ND_WRITE);
- error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
- }
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- if (dirp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- }
- /* fall through */
-
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (dirp)
- vrele(dirp);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
-
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs readdir service
- * - mallocs what it thinks is enough to read
- * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
- * - calls VOP_READDIR()
- * - loops around building the reply
- * if the output generated exceeds count break out of loop
- * The nfsm_clget macro is used here so that the reply will be packed
- * tightly in mbuf clusters.
- * - it only knows that it has encountered eof when the VOP_READDIR()
- * reads nothing
- * - as such one readdir rpc will return eof false although you are there
- * and then the next will return eof
- * - it trims out records with d_fileno == 0
- * this doesn't matter for Unix clients, but they might confuse clients
- * for other os'.
- * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
- * than requested, but this may not apply to all filesystems. For
- * example, client NFS does not { although it is never remote mounted
- * anyhow }
- * The alternate call nfsrv_readdirplus() does lookups as well.
- * PS: The NFS protocol spec. does not clarify what the "count" byte
- * argument is a count of.. just name strings and file id's or the
- * entire reply rpc or ...
- * I tried just file name and id sizes and it confused the Sun client,
- * so I am using the full rpc size now. The "paranoia.." comment refers
- * to including the status longwords that are not a part of the dir.
- * "entry" structures, but are in the rpc.
- */
-struct flrep {
- nfsuint64 fl_off;
- u_int32_t fl_postopok;
- u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
- u_int32_t fl_fhok;
- u_int32_t fl_fhsize;
- u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
-};
-
-int
-nfsrv_readdir(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register char *bp, *be;
- register struct mbuf *mp;
- register struct dirent *dp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- struct mbuf *mb, *mb2, *mreq, *mp2;
- char *cpos, *cend, *cp2, *rbuf;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io;
- struct iovec iv;
- int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
- int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- u_quad_t frev, off, toff, verf;
- u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if (v3) {
- nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- toff = fxdr_hyper(tl);
- tl += 2;
- verf = fxdr_hyper(tl);
- tl += 2;
- } else {
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- toff = fxdr_unsigned(u_quad_t, *tl++);
- verf = 0; /* shut up gcc */
- }
- off = toff;
- cnt = fxdr_unsigned(int, *tl);
- siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
- xfer = NFS_SRVMAXDATA(nfsd);
- if (siz > xfer)
- siz = xfer;
- fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (!error && vp->v_type != VDIR) {
- error = ENOTDIR;
- vput(vp);
- vp = NULL;
- }
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Obtain lock on vnode for this section of the code
- */
-
- nqsrv_getl(vp, ND_READ);
- if (v3) {
- error = getret = VOP_GETATTR(vp, &at, cred, td);
-#if 0
- /*
- * XXX This check may be too strict for Solaris 2.5 clients.
- */
- if (!error && toff && verf && verf != at.va_filerev)
- error = NFSERR_BAD_COOKIE;
-#endif
- }
- if (!error)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- VOP_UNLOCK(vp, 0, td);
-
- /*
- * end section. Allocate rbuf and continue
- */
- MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
-again:
- iv.iov_base = rbuf;
- iv.iov_len = fullsiz;
- io.uio_iov = &iv;
- io.uio_iovcnt = 1;
- io.uio_offset = (off_t)off;
- io.uio_resid = fullsiz;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = (struct thread *)0;
- eofflag = 0;
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- if (cookies) {
- free((caddr_t)cookies, M_TEMP);
- cookies = NULL;
- }
- error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
- off = (off_t)io.uio_offset;
- if (!cookies && !error)
- error = NFSERR_PERM;
- if (v3) {
- getret = VOP_GETATTR(vp, &at, cred, td);
- if (!error)
- error = getret;
- }
- VOP_UNLOCK(vp, 0, td);
- if (error) {
- vrele(vp);
- vp = NULL;
- free((caddr_t)rbuf, M_TEMP);
- if (cookies)
- free((caddr_t)cookies, M_TEMP);
- nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- if (io.uio_resid) {
- siz -= io.uio_resid;
-
- /*
- * If nothing read, return eof
- * rpc reply
- */
- if (siz == 0) {
- vrele(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
- 2 * NFSX_UNSIGNED);
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- tl += 2;
- } else
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = nfs_false;
- *tl = nfs_true;
- FREE((caddr_t)rbuf, M_TEMP);
- FREE((caddr_t)cookies, M_TEMP);
- error = 0;
- goto nfsmout;
- }
- }
-
- /*
- * Check for degenerate cases of nothing useful read.
- * If so go try again
- */
- cpos = rbuf;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
- cookiep = cookies;
- /*
- * For some reason FreeBSD's ufs_readdir() chooses to back the
- * directory offset up to a block boundary, so it is necessary to
- * skip over the records that precede the requested offset. This
- * requires the assumption that file offset cookies monotonically
- * increase.
- */
- while (cpos < cend && ncookies > 0 &&
- (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
- ((u_quad_t)(*cookiep)) <= toff)) {
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- if (cpos >= cend || ncookies == 0) {
- toff = off;
- siz = fullsiz;
- goto again;
- }
-
- len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- }
- mp = mp2 = mb;
- bp = bpos;
- be = bp + M_TRAILINGSPACE(mp);
-
- /* Loop through the records and build reply */
- while (cpos < cend && ncookies > 0) {
- if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
- nlen = dp->d_namlen;
- rem = nfsm_rndup(nlen) - nlen;
- len += (4 * NFSX_UNSIGNED + nlen + rem);
- if (v3)
- len += 2 * NFSX_UNSIGNED;
- if (len > cnt) {
- eofflag = 0;
- break;
- }
- /*
- * Build the directory record xdr from
- * the dirent entry.
- */
- nfsm_clget;
- *tl = nfs_true;
- bp += NFSX_UNSIGNED;
- if (v3) {
- nfsm_clget;
- *tl = 0;
- bp += NFSX_UNSIGNED;
- }
- nfsm_clget;
- *tl = txdr_unsigned(dp->d_fileno);
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = txdr_unsigned(nlen);
- bp += NFSX_UNSIGNED;
-
- /* And loop around copying the name */
- xfer = nlen;
- cp = dp->d_name;
- while (xfer > 0) {
- nfsm_clget;
- if ((bp+xfer) > be)
- tsiz = be-bp;
- else
- tsiz = xfer;
- bcopy(cp, bp, tsiz);
- bp += tsiz;
- xfer -= tsiz;
- if (xfer > 0)
- cp += tsiz;
- }
- /* And null pad to a int32_t boundary */
- for (i = 0; i < rem; i++)
- *bp++ = '\0';
- nfsm_clget;
-
- /* Finish off the record */
- if (v3) {
- *tl = 0;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- }
- *tl = txdr_unsigned(*cookiep);
- bp += NFSX_UNSIGNED;
- }
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- vrele(vp);
- vp = NULL;
- nfsm_clget;
- *tl = nfs_false;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- if (eofflag)
- *tl = nfs_true;
- else
- *tl = nfs_false;
- bp += NFSX_UNSIGNED;
- if (mp != mb) {
- if (bp < be)
- mp->m_len = bp - mtod(mp, caddr_t);
- } else
- mp->m_len += bp - bpos;
- FREE((caddr_t)rbuf, M_TEMP);
- FREE((caddr_t)cookies, M_TEMP);
-
-nfsmout:
- if (vp)
- vrele(vp);
- return(error);
-}
-
-int
-nfsrv_readdirplus(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register char *bp, *be;
- register struct mbuf *mp;
- register struct dirent *dp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- struct mbuf *mb, *mb2, *mreq, *mp2;
- char *cpos, *cend, *cp2, *rbuf;
- struct vnode *vp = NULL, *nvp;
- struct flrep fl;
- nfsfh_t nfh;
- fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
- struct uio io;
- struct iovec iv;
- struct vattr va, at, *vap = &va;
- struct nfs_fattr *fp;
- int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
- int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
- u_quad_t frev, off, toff, verf;
- u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
- toff = fxdr_hyper(tl);
- tl += 2;
- verf = fxdr_hyper(tl);
- tl += 2;
- siz = fxdr_unsigned(int, *tl++);
- cnt = fxdr_unsigned(int, *tl);
- off = toff;
- siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
- xfer = NFS_SRVMAXDATA(nfsd);
- if (siz > xfer)
- siz = xfer;
- fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (!error && vp->v_type != VDIR) {
- error = ENOTDIR;
- vput(vp);
- vp = NULL;
- }
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- error = getret = VOP_GETATTR(vp, &at, cred, td);
-#if 0
- /*
- * XXX This check may be too strict for Solaris 2.5 clients.
- */
- if (!error && toff && verf && verf != at.va_filerev)
- error = NFSERR_BAD_COOKIE;
-#endif
- if (!error) {
- nqsrv_getl(vp, ND_READ);
- error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
- }
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- VOP_UNLOCK(vp, 0, td);
- MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
-again:
- iv.iov_base = rbuf;
- iv.iov_len = fullsiz;
- io.uio_iov = &iv;
- io.uio_iovcnt = 1;
- io.uio_offset = (off_t)off;
- io.uio_resid = fullsiz;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = (struct thread *)0;
- eofflag = 0;
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- if (cookies) {
- free((caddr_t)cookies, M_TEMP);
- cookies = NULL;
- }
- error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
- off = (u_quad_t)io.uio_offset;
- getret = VOP_GETATTR(vp, &at, cred, td);
- VOP_UNLOCK(vp, 0, td);
- if (!cookies && !error)
- error = NFSERR_PERM;
- if (!error)
- error = getret;
- if (error) {
- vrele(vp);
- vp = NULL;
- if (cookies)
- free((caddr_t)cookies, M_TEMP);
- free((caddr_t)rbuf, M_TEMP);
- nfsm_reply(NFSX_V3POSTOPATTR);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- if (io.uio_resid) {
- siz -= io.uio_resid;
-
- /*
- * If nothing read, return eof
- * rpc reply
- */
- if (siz == 0) {
- vrele(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
- 2 * NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- tl += 2;
- *tl++ = nfs_false;
- *tl = nfs_true;
- FREE((caddr_t)cookies, M_TEMP);
- FREE((caddr_t)rbuf, M_TEMP);
- error = 0;
- goto nfsmout;
- }
- }
-
- /*
- * Check for degenerate cases of nothing useful read.
- * If so go try again
- */
- cpos = rbuf;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
- cookiep = cookies;
- /*
- * For some reason FreeBSD's ufs_readdir() chooses to back the
- * directory offset up to a block boundary, so it is necessary to
- * skip over the records that precede the requested offset. This
- * requires the assumption that file offset cookies monotonically
- * increase.
- */
- while (cpos < cend && ncookies > 0 &&
- (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
- ((u_quad_t)(*cookiep)) <= toff)) {
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- if (cpos >= cend || ncookies == 0) {
- toff = off;
- siz = fullsiz;
- goto again;
- }
-
- /*
- * Probe one of the directory entries to see if the filesystem
- * supports VGET.
- */
- if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp) == EOPNOTSUPP) {
- error = NFSERR_NOTSUPP;
- vrele(vp);
- vp = NULL;
- free((caddr_t)cookies, M_TEMP);
- free((caddr_t)rbuf, M_TEMP);
- nfsm_reply(NFSX_V3POSTOPATTR);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- vput(nvp);
- nvp = NULL;
-
- dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
- nfsm_reply(cnt);
- nfsm_srvpostop_attr(getret, &at);
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- mp = mp2 = mb;
- bp = bpos;
- be = bp + M_TRAILINGSPACE(mp);
-
- /* Loop through the records and build reply */
- while (cpos < cend && ncookies > 0) {
- if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
- nlen = dp->d_namlen;
- rem = nfsm_rndup(nlen)-nlen;
-
- /*
- * For readdir_and_lookup get the vnode using
- * the file number.
- */
- if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
- goto invalid;
- bzero((caddr_t)nfhp, NFSX_V3FH);
- nfhp->fh_fsid =
- nvp->v_mount->mnt_stat.f_fsid;
- if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
- vput(nvp);
- nvp = NULL;
- goto invalid;
- }
- if (VOP_GETATTR(nvp, vap, cred, td)) {
- vput(nvp);
- nvp = NULL;
- goto invalid;
- }
- vput(nvp);
- nvp = NULL;
-
- /*
- * If either the dircount or maxcount will be
- * exceeded, get out now. Both of these lengths
- * are calculated conservatively, including all
- * XDR overheads.
- */
- len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
- NFSX_V3POSTOPATTR);
- dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
- if (len > cnt || dirlen > fullsiz) {
- eofflag = 0;
- break;
- }
-
- /*
- * Build the directory record xdr from
- * the dirent entry.
- */
- fp = (struct nfs_fattr *)&fl.fl_fattr;
- nfsm_srvfillattr(vap, fp);
- fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
- fl.fl_fhok = nfs_true;
- fl.fl_postopok = nfs_true;
- fl.fl_off.nfsuquad[0] = 0;
- fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
-
- nfsm_clget;
- *tl = nfs_true;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = 0;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = txdr_unsigned(dp->d_fileno);
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = txdr_unsigned(nlen);
- bp += NFSX_UNSIGNED;
-
- /* And loop around copying the name */
- xfer = nlen;
- cp = dp->d_name;
- while (xfer > 0) {
- nfsm_clget;
- if ((bp + xfer) > be)
- tsiz = be - bp;
- else
- tsiz = xfer;
- bcopy(cp, bp, tsiz);
- bp += tsiz;
- xfer -= tsiz;
- if (xfer > 0)
- cp += tsiz;
- }
- /* And null pad to a int32_t boundary */
- for (i = 0; i < rem; i++)
- *bp++ = '\0';
-
- /*
- * Now copy the flrep structure out.
- */
- xfer = sizeof (struct flrep);
- cp = (caddr_t)&fl;
- while (xfer > 0) {
- nfsm_clget;
- if ((bp + xfer) > be)
- tsiz = be - bp;
- else
- tsiz = xfer;
- bcopy(cp, bp, tsiz);
- bp += tsiz;
- xfer -= tsiz;
- if (xfer > 0)
- cp += tsiz;
- }
- }
-invalid:
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- vrele(vp);
- vp = NULL;
- nfsm_clget;
- *tl = nfs_false;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- if (eofflag)
- *tl = nfs_true;
- else
- *tl = nfs_false;
- bp += NFSX_UNSIGNED;
- if (mp != mb) {
- if (bp < be)
- mp->m_len = bp - mtod(mp, caddr_t);
- } else
- mp->m_len += bp - bpos;
- FREE((caddr_t)cookies, M_TEMP);
- FREE((caddr_t)rbuf, M_TEMP);
-nfsmout:
- if (vp)
- vrele(vp);
- return(error);
-}
-
-/*
- * nfs commit service
- */
-int
-nfsrv_commit(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- struct vattr bfor, aft;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- u_quad_t frev, off;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- if ((error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp)) != 0) {
- mp = NULL;
- goto ereply;
- }
- (void) vn_start_write(vp, &mp, V_WAIT);
- vput(vp);
- vp = NULL;
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
-
- /*
- * XXX At this time VOP_FSYNC() does not accept offset and byte
- * count parameters, so these arguments are useless (someday maybe).
- */
- off = fxdr_hyper(tl);
- tl += 2;
- cnt = fxdr_unsigned(int, *tl);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
- error = 0;
- goto nfsmout;
- }
- for_ret = VOP_GETATTR(vp, &bfor, cred, td);
-
- if (cnt > MAX_COMMIT_COUNT) {
- /*
- * Give up and do the whole thing
- */
- if (vp->v_object &&
- (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
- }
- error = VOP_FSYNC(vp, cred, MNT_WAIT, td);
- } else {
- /*
- * Locate and synchronously write any buffers that fall
- * into the requested range. Note: we are assuming that
- * f_iosize is a power of 2.
- */
- int iosize = vp->v_mount->mnt_stat.f_iosize;
- int iomask = iosize - 1;
- int s;
- daddr_t lblkno;
-
- /*
- * Align to iosize boundry, super-align to page boundry.
- */
- if (off & iomask) {
- cnt += off & iomask;
- off &= ~(u_quad_t)iomask;
- }
- if (off & PAGE_MASK) {
- cnt += off & PAGE_MASK;
- off &= ~(u_quad_t)PAGE_MASK;
- }
- lblkno = off / iosize;
-
- if (vp->v_object &&
- (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
- }
-
- s = splbio();
- while (cnt > 0) {
- struct buf *bp;
-
- /*
- * If we have a buffer and it is marked B_DELWRI we
- * have to lock and write it. Otherwise the prior
- * write is assumed to have already been committed.
- */
- if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) {
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
- BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL);
- continue; /* retry */
- }
- bremfree(bp);
- bp->b_flags &= ~B_ASYNC;
- BUF_WRITE(bp);
- ++nfs_commit_miss;
- }
- ++nfs_commit_blks;
- if (cnt < iosize)
- break;
- cnt -= iosize;
- ++lblkno;
- }
- splx(s);
- }
-
- aft_ret = VOP_GETATTR(vp, &aft, cred, td);
- vput(vp);
- vp = NULL;
-ereply:
- nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
- nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
- if (!error) {
- nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
- if (nfsver.tv_sec == 0)
- nfsver = boottime;
- *tl++ = txdr_unsigned(nfsver.tv_sec);
- *tl = txdr_unsigned(nfsver.tv_usec);
- } else {
- error = 0;
- }
-nfsmout:
- if (vp)
- vput(vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs statfs service
- */
-int
-nfsrv_statfs(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register struct statfs *sf;
- register struct nfs_statfs *sfp;
- register u_int32_t *tl;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, getret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct statfs statfs;
- u_quad_t frev, tval;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- sf = &statfs;
- error = VFS_STATFS(vp->v_mount, sf, td);
- getret = VOP_GETATTR(vp, &at, cred, td);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
- if (v3)
- nfsm_srvpostop_attr(getret, &at);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
- if (v3) {
- tval = (u_quad_t)sf->f_blocks;
- tval *= (u_quad_t)sf->f_bsize;
- txdr_hyper(tval, &sfp->sf_tbytes);
- tval = (u_quad_t)sf->f_bfree;
- tval *= (u_quad_t)sf->f_bsize;
- txdr_hyper(tval, &sfp->sf_fbytes);
- tval = (u_quad_t)sf->f_bavail;
- tval *= (u_quad_t)sf->f_bsize;
- txdr_hyper(tval, &sfp->sf_abytes);
- sfp->sf_tfiles.nfsuquad[0] = 0;
- sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
- sfp->sf_ffiles.nfsuquad[0] = 0;
- sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
- sfp->sf_afiles.nfsuquad[0] = 0;
- sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
- sfp->sf_invarsec = 0;
- } else {
- sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
- sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
- sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
- sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
- sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
- }
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs fsinfo service
- */
-int
-nfsrv_fsinfo(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register struct nfsv3_fsinfo *sip;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, getret = 1, pref;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev, maxfsize;
- struct statfs sb;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
-
- /* XXX Try to make a guess on the max file size. */
- VFS_STATFS(vp->v_mount, &sb, td);
- maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
-
- getret = VOP_GETATTR(vp, &at, cred, td);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
- nfsm_srvpostop_attr(getret, &at);
- nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
-
- /*
- * XXX
- * There should be file system VFS OP(s) to get this information.
- * For now, assume ufs.
- */
- if (slp->ns_so->so_type == SOCK_DGRAM)
- pref = NFS_MAXDGRAMDATA;
- else
- pref = NFS_MAXDATA;
- sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
- sip->fs_rtpref = txdr_unsigned(pref);
- sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
- sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
- sip->fs_wtpref = txdr_unsigned(pref);
- sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
- sip->fs_dtpref = txdr_unsigned(pref);
- txdr_hyper(maxfsize, &sip->fs_maxfilesize);
- sip->fs_timedelta.nfsv3_sec = 0;
- sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
- sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
- NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
- NFSV3FSINFO_CANSETTIME);
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs pathconf service
- */
-int
-nfsrv_pathconf(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register struct nfsv3_pathconf *pc;
- register int32_t t1;
- caddr_t bpos;
- int error = 0, rdonly, cache, getret = 1;
- register_t linkmax, namemax, chownres, notrunc;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
- if (!error)
- error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
- if (!error)
- error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
- if (!error)
- error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
- getret = VOP_GETATTR(vp, &at, cred, td);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
- nfsm_srvpostop_attr(getret, &at);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
-
- pc->pc_linkmax = txdr_unsigned(linkmax);
- pc->pc_namemax = txdr_unsigned(namemax);
- pc->pc_notrunc = txdr_unsigned(notrunc);
- pc->pc_chownrestricted = txdr_unsigned(chownres);
-
- /*
- * These should probably be supported by VOP_PATHCONF(), but
- * until msdosfs is exportable (why would you want to?), the
- * Unix defaults should be ok.
- */
- pc->pc_caseinsensitive = nfs_false;
- pc->pc_casepreserving = nfs_true;
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * Null operation, used by clients to ping server
- */
-/* ARGSUSED */
-int
-nfsrv_null(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep;
- caddr_t bpos;
- int error = NFSERR_RETVOID, cache;
- struct mbuf *mb, *mreq;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- nfsm_reply(0);
- nfsm_srvdone;
-}
-
-/*
- * No operation, used for obsolete procedures
- */
-/* ARGSUSED */
-int
-nfsrv_noop(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
-{
- struct mbuf *mrep = nfsd->nd_mrep;
- caddr_t bpos;
- int error, cache;
- struct mbuf *mb, *mreq;
- u_quad_t frev;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
- if (nfsd->nd_repstat)
- error = nfsd->nd_repstat;
- else
- error = EPROCUNAVAIL;
- nfsm_reply(0);
- nfsm_srvdone;
-}
-
-/*
- * Perform access checking for vnodes obtained from file handles that would
- * refer to files already opened by a Unix client. You cannot just use
- * vn_writechk() and VOP_ACCESS() for two reasons.
- * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
- * 2 - The owner is to be given access irrespective of mode bits for some
- * operations, so that processes that chmod after opening a file don't
- * break. I don't like this because it opens a security hole, but since
- * the nfs server opens a security hole the size of a barn door anyhow,
- * what the heck.
- *
- * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
- * will return EPERM instead of EACCESS. EPERM is always an error.
- */
-static int
-nfsrv_access(vp, flags, cred, rdonly, td, override)
- register struct vnode *vp;
- int flags;
- register struct ucred *cred;
- int rdonly;
- struct thread *td;
- int override;
-{
- struct vattr vattr;
- int error;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (flags & VWRITE) {
- /* Just vn_writechk() changed to check rdonly */
- /*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket or a block or character
- * device resident on the file system.
- */
- if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- switch (vp->v_type) {
- case VREG:
- case VDIR:
- case VLNK:
- return (EROFS);
- default:
- break;
- }
- }
- /*
- * If there's shared text associated with
- * the inode, we can't allow writing.
- */
- if (vp->v_flag & VTEXT)
- return (ETXTBSY);
- }
- error = VOP_GETATTR(vp, &vattr, cred, td);
- if (error)
- return (error);
- error = VOP_ACCESS(vp, flags, cred, td);
- /*
- * Allow certain operations for the owner (reads and writes
- * on files that are already open).
- */
- if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
- error = 0;
- return error;
-}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c
deleted file mode 100644
index 8991672..0000000
--- a/sys/nfs/nfs_socket.c
+++ /dev/null
@@ -1,2296 +0,0 @@
-/*
- * 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
- * $FreeBSD$
- */
-
-/*
- * Socket operations for use by nfs
- */
-
-#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/sysctl.h>
-#include <sys/syslog.h>
-#include <sys/vnode.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nqnfs.h>
-
-#define TRUE 1
-#define FALSE 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 NFS_RTO(n, t) \
- ((t) == 0 ? (n)->nm_timeo : \
- ((t) < 3 ? \
- (((((n)->nm_srtt[t-1] + 3) >> 2) + (n)->nm_sdrtt[t-1] + 1) >> 1) : \
- ((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
-#define NFS_SRTT(r) (r)->r_nmp->nm_srtt[proct[(r)->r_procnum] - 1]
-#define NFS_SDRTT(r) (r)->r_nmp->nm_sdrtt[proct[(r)->r_procnum] - 1]
-/*
- * External data, mostly RPC constants in XDR form
- */
-extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers,
- rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr,
- rpc_auth_kerb;
-extern u_int32_t nfs_prog, nqnfs_prog;
-extern time_t nqnfsstarttime;
-extern struct nfsstats nfsstats;
-extern int nfsv3_procid[NFS_NPROCS];
-extern int nfs_ticks;
-
-/*
- * Defines which timer to use for the procnum.
- * 0 - default
- * 1 - getattr
- * 2 - lookup
- * 3 - read
- * 4 - write
- */
-static int proct[NFS_NPROCS] = {
- 0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
- 0, 0, 0,
-};
-
-static int nfs_realign_test;
-static int nfs_realign_count;
-static int nfs_bufpackets = 4;
-
-SYSCTL_DECL(_vfs_nfs);
-
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, "");
-
-
-/*
- * 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 NFS_CWNDSCALE 256
-#define NFS_MAXCWND (NFS_CWNDSCALE * 32)
-static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
-int nfsrtton = 0;
-struct nfsrtt nfsrtt;
-struct callout_handle nfs_timer_handle;
-
-static int nfs_msg __P((struct thread *,char *,char *));
-static int nfs_rcvlock __P((struct nfsreq *));
-static void nfs_rcvunlock __P((struct nfsreq *));
-static void nfs_realign __P((struct mbuf **pm, int hsiz));
-static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
- struct mbuf **mp));
-static void nfs_softterm __P((struct nfsreq *rep));
-static int nfs_reconnect __P((struct nfsreq *rep));
-#ifndef NFS_NOSERVER
-static int nfsrv_getstream __P((struct nfssvc_sock *,int));
-
-int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp)) = {
- nfsrv_null,
- nfsrv_getattr,
- nfsrv_setattr,
- nfsrv_lookup,
- nfsrv3_access,
- nfsrv_readlink,
- nfsrv_read,
- nfsrv_write,
- nfsrv_create,
- nfsrv_mkdir,
- nfsrv_symlink,
- nfsrv_mknod,
- nfsrv_remove,
- nfsrv_rmdir,
- nfsrv_rename,
- nfsrv_link,
- nfsrv_readdir,
- nfsrv_readdirplus,
- nfsrv_statfs,
- nfsrv_fsinfo,
- nfsrv_pathconf,
- nfsrv_commit,
- nqnfsrv_getlease,
- nqnfsrv_vacated,
- nfsrv_noop,
- nfsrv_noop
-};
-#endif /* NFS_NOSERVER */
-
-/*
- * Initialize sockets and congestion for a new NFS connection.
- * We do not free the sockaddr if error.
- */
-int
-nfs_connect(nmp, rep)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
-{
- register struct socket *so;
- int s, error, rcvreserve, sndreserve;
- int pktscale;
- struct sockaddr *saddr;
- struct sockaddr_in *sin;
- struct thread *td = thread0; /* only used for socreate and sobind */
-
- nmp->nm_so = (struct socket *)0;
- saddr = nmp->nm_nam;
- error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype,
- nmp->nm_soproto, td);
- if (error)
- goto bad;
- so = nmp->nm_so;
- nmp->nm_soflags = so->so_proto->pr_flags;
-
- /*
- * Some servers require that the client port be a reserved port number.
- */
- if (saddr->sa_family == AF_INET && (nmp->nm_flag & NFSMNT_RESVPORT)) {
- struct sockopt sopt;
- int ip;
- struct sockaddr_in ssin;
-
- bzero(&sopt, sizeof sopt);
- ip = IP_PORTRANGE_LOW;
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = IPPROTO_IP;
- sopt.sopt_name = IP_PORTRANGE;
- sopt.sopt_val = (void *)&ip;
- sopt.sopt_valsize = sizeof(ip);
- sopt.sopt_td = NULL;
- error = sosetopt(so, &sopt);
- if (error)
- goto bad;
- bzero(&ssin, sizeof ssin);
- sin = &ssin;
- sin->sin_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, (struct sockaddr *)sin, td);
- if (error)
- goto bad;
- bzero(&sopt, sizeof sopt);
- ip = IP_PORTRANGE_DEFAULT;
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = IPPROTO_IP;
- sopt.sopt_name = IP_PORTRANGE;
- sopt.sopt_val = (void *)&ip;
- sopt.sopt_valsize = sizeof(ip);
- sopt.sopt_td = NULL;
- error = sosetopt(so, &sopt);
- 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 (nmp->nm_flag & NFSMNT_NOCONN) {
- if (nmp->nm_soflags & PR_CONNREQUIRED) {
- error = ENOTCONN;
- goto bad;
- }
- } else {
- error = soconnect(so, nmp->nm_nam, 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.
- */
- s = splnet();
- while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
- (void) tsleep((caddr_t)&so->so_timeo, PSOCK,
- "nfscon", 2 * hz);
- if ((so->so_state & SS_ISCONNECTING) &&
- so->so_error == 0 && rep &&
- (error = nfs_sigintr(nmp, rep,
- (rep->r_td ? rep->r_td->td_proc : NULL))) != 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 (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_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;
- }
-
- /*
- * Get buffer reservation size from sysctl, but impose reasonable
- * limits.
- */
- pktscale = nfs_bufpackets;
- if (pktscale < 2)
- pktscale = 2;
- if (pktscale > 64)
- pktscale = 64;
-
- if (nmp->nm_sotype == SOCK_DGRAM) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else if (nmp->nm_sotype == SOCK_SEQPACKET) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else {
- if (nmp->nm_sotype != SOCK_STREAM)
- panic("nfscon sotype");
- if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_KEEPALIVE;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- if (so->so_proto->pr_protocol == IPPROTO_TCP) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = IPPROTO_TCP;
- sopt.sopt_name = TCP_NODELAY;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- }
- 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 */
- nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] =
- nmp->nm_srtt[3] = (NFS_TIMEO << 3);
- nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] =
- nmp->nm_sdrtt[3] = 0;
- nmp->nm_cwnd = NFS_MAXCWND / 2; /* Initial send window */
- nmp->nm_sent = 0;
- nmp->nm_timeouts = 0;
- return (0);
-
-bad:
- nfs_disconnect(nmp);
- return (error);
-}
-
-/*
- * Reconnect routine:
- * Called when a connection is broken on a reliable protocol.
- * - clean up the old socket
- * - nfs_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 nfs_sndlock() set on the mount point.
- */
-static int
-nfs_reconnect(rep)
- register struct nfsreq *rep;
-{
- register struct nfsreq *rp;
- register struct nfsmount *nmp = rep->r_nmp;
- int error;
-
- nfs_disconnect(nmp);
- while ((error = nfs_connect(nmp, rep)) != 0) {
- if (error == EINTR || error == ERESTART)
- return (EINTR);
- (void) tsleep((caddr_t)&lbolt, PSOCK, "nfscon", 0);
- }
-
- /*
- * Loop through outstanding request list and fix up all requests
- * on old socket.
- */
- for (rp = nfs_reqq.tqh_first; rp != 0; rp = rp->r_chain.tqe_next) {
- if (rp->r_nmp == nmp)
- rp->r_flags |= R_MUSTRESEND;
- }
- return (0);
-}
-
-/*
- * NFS disconnect. Clean up and unlink.
- */
-void
-nfs_disconnect(nmp)
- register struct nfsmount *nmp;
-{
- register struct socket *so;
-
- if (nmp->nm_so) {
- so = nmp->nm_so;
- nmp->nm_so = (struct socket *)0;
- soshutdown(so, 2);
- soclose(so);
- }
-}
-
-void
-nfs_safedisconnect(nmp)
- struct nfsmount *nmp;
-{
- struct nfsreq dummyreq;
-
- bzero(&dummyreq, sizeof(dummyreq));
- dummyreq.r_nmp = nmp;
- nfs_rcvlock(&dummyreq);
- nfs_disconnect(nmp);
- nfs_rcvunlock(&dummyreq);
-}
-
-/*
- * This is the nfs send routine. For connection based socket types, it
- * must be called with an nfs_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 (?)
- */
-int
-nfs_send(so, nam, top, rep)
- register struct socket *so;
- struct sockaddr *nam;
- register struct mbuf *top;
- struct nfsreq *rep;
-{
- struct sockaddr *sendnam;
- int error, soflags, flags;
-
- if (rep) {
- if (rep->r_flags & R_SOFTTERM) {
- m_freem(top);
- return (EINTR);
- }
- if ((so = rep->r_nmp->nm_so) == NULL) {
- rep->r_flags |= R_MUSTRESEND;
- m_freem(top);
- return (0);
- }
- rep->r_flags &= ~R_MUSTRESEND;
- soflags = rep->r_nmp->nm_soflags;
- } else
- soflags = so->so_proto->pr_flags;
- if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
- sendnam = (struct sockaddr *)0;
- else
- sendnam = nam;
- if (so->so_type == SOCK_SEQPACKET)
- flags = MSG_EOR;
- else
- flags = 0;
-
- error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
- flags, curthread /*XXX*/);
- /*
- * ENOBUFS for dgram sockets is transient and non fatal.
- * No need to log, and no need to break a soft mount.
- */
- if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
- error = 0;
- if (rep) /* do backoff retransmit on client */
- rep->r_flags |= R_MUSTRESEND;
- }
-
- if (error) {
- if (rep) {
- log(LOG_INFO, "nfs send error %d for server %s\n",error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- /*
- * 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, "nfsd send error %d\n", error);
-
- /*
- * Handle any recoverable (soft) socket errors here. (?)
- */
- if (error != EINTR && error != ERESTART &&
- error != EWOULDBLOCK && error != EPIPE)
- error = 0;
- }
- 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
-nfs_receive(rep, aname, mp)
- register struct nfsreq *rep;
- struct sockaddr **aname;
- struct mbuf **mp;
-{
- register struct socket *so;
- struct uio auio;
- struct iovec aio;
- register struct mbuf *m;
- struct mbuf *control;
- u_int32_t len;
- struct sockaddr **getnam;
- int error, sotype, rcvflg;
- struct thread *td = curthread; /* XXX */
-
- /*
- * Set up arguments for soreceive()
- */
- *mp = (struct mbuf *)0;
- *aname = (struct sockaddr *)0;
- sotype = rep->r_nmp->nm_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 = nfs_sndlock(rep);
- if (error)
- return (error);
-tryagain:
- /*
- * Check for fatal errors and resending request.
- */
- /*
- * Ugh: If a reconnect attempt just happened, nm_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)) {
- nfs_sndunlock(rep);
- return (EINTR);
- }
- so = rep->r_nmp->nm_so;
- if (!so) {
- error = nfs_reconnect(rep);
- if (error) {
- nfs_sndunlock(rep);
- return (error);
- }
- goto tryagain;
- }
- while (rep->r_flags & R_MUSTRESEND) {
- m = m_copym(rep->r_mreq, 0, M_COPYALL, M_TRYWAIT);
- nfsstats.rpcretries++;
- error = nfs_send(so, rep->r_nmp->nm_nam, m, rep);
- if (error) {
- if (error == EINTR || error == ERESTART ||
- (error = nfs_reconnect(rep)) != 0) {
- nfs_sndunlock(rep);
- return (error);
- }
- goto tryagain;
- }
- }
- nfs_sndunlock(rep);
- 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);
- auio.uio_td = td;
- do {
- rcvflg = MSG_WAITALL;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, (struct sockaddr **)0, &auio,
- (struct mbuf **)0, (struct mbuf **)0,
- &rcvflg);
- if (error == EWOULDBLOCK && rep) {
- if (rep->r_flags & R_SOFTTERM)
- return (EINTR);
- }
- } while (error == EWOULDBLOCK);
- if (!error && auio.uio_resid > 0) {
- /*
- * Don't log a 0 byte receive; it means
- * that the socket has been closed, and
- * can happen during normal operation
- * (forcible unmount or Solaris server).
- */
- if (auio.uio_resid != sizeof (u_int32_t))
- log(LOG_INFO,
- "short receive (%d/%d) from nfs server %s\n",
- (int)(sizeof(u_int32_t) - auio.uio_resid),
- (int)sizeof(u_int32_t),
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- 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 > NFS_MAXPACKET) {
- log(LOG_ERR, "%s (%d) from nfs server %s\n",
- "impossible packet length",
- len,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- error = EFBIG;
- goto errout;
- }
- auio.uio_resid = len;
- do {
- rcvflg = MSG_WAITALL;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, (struct sockaddr **)0,
- &auio, mp, (struct mbuf **)0, &rcvflg);
- } while (error == EWOULDBLOCK || error == EINTR ||
- error == ERESTART);
- if (!error && auio.uio_resid > 0) {
- if (len != auio.uio_resid)
- log(LOG_INFO,
- "short receive (%d/%d) from nfs server %s\n",
- len - auio.uio_resid, len,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- 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 */
- auio.uio_td = td;
- do {
- rcvflg = 0;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, (struct sockaddr **)0,
- &auio, mp, &control, &rcvflg);
- if (control)
- m_freem(control);
- if (error == EWOULDBLOCK && rep) {
- if (rep->r_flags & R_SOFTTERM)
- 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 nfs server %s\n",
- error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- error = nfs_sndlock(rep);
- if (!error)
- error = nfs_reconnect(rep);
- if (!error)
- goto tryagain;
- else
- nfs_sndunlock(rep);
- }
- } else {
- if ((so = rep->r_nmp->nm_so) == NULL)
- return (EACCES);
- if (so->so_state & SS_ISCONNECTED)
- getnam = (struct sockaddr **)0;
- else
- getnam = aname;
- auio.uio_resid = len = 1000000;
- auio.uio_td = td;
- do {
- rcvflg = 0;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, getnam, &auio, mp,
- (struct mbuf **)0, &rcvflg);
- if (error == EWOULDBLOCK &&
- (rep->r_flags & R_SOFTTERM))
- return (EINTR);
- } while (error == EWOULDBLOCK);
- len -= auio.uio_resid;
- }
- if (error) {
- m_freem(*mp);
- *mp = (struct mbuf *)0;
- }
- /*
- * 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.
- */
- nfs_realign(mp, 5 * NFSX_UNSIGNED);
- 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 */
-int
-nfs_reply(myrep)
- struct nfsreq *myrep;
-{
- register struct nfsreq *rep;
- register struct nfsmount *nmp = myrep->r_nmp;
- register int32_t t1;
- struct mbuf *mrep, *md;
- struct sockaddr *nam;
- 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.
- * If nfs_rcvlock() returns EALREADY, that means that
- * the reply has already been recieved by another
- * process and we can return immediately. In this
- * case, the lock is not taken to avoid races with
- * other processes.
- */
- error = nfs_rcvlock(myrep);
- if (error == EALREADY)
- return (0);
- if (error)
- return (error);
- /*
- * Get the next Rpc reply off the socket
- */
- error = nfs_receive(myrep, &nam, &mrep);
- nfs_rcvunlock(myrep);
- if (error) {
-
- /*
- * Ignore routing errors on connectionless protocols??
- */
- if (NFSIGNORE_SOERROR(nmp->nm_soflags, error)) {
- nmp->nm_so->so_error = 0;
- if (myrep->r_flags & R_GETONEREP)
- return (0);
- continue;
- }
- return (error);
- }
- if (nam)
- FREE(nam, M_SONAME);
-
- /*
- * Get the xid and check that it is an rpc reply
- */
- md = mrep;
- dpos = mtod(md, caddr_t);
- nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- rxid = *tl++;
- if (*tl != rpc_reply) {
-#ifndef NFS_NOSERVER
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (nqnfs_callback(nmp, mrep, md, dpos))
- nfsstats.rpcinvalid++;
- } else {
- nfsstats.rpcinvalid++;
- m_freem(mrep);
- }
-#else
- nfsstats.rpcinvalid++;
- m_freem(mrep);
-#endif
-nfsmout:
- if (myrep->r_flags & R_GETONEREP)
- return (0);
- continue;
- }
-
- /*
- * Loop through the request list to match up the reply
- * Iff no match, just drop the datagram
- */
- for (rep = nfs_reqq.tqh_first; rep != 0;
- rep = rep->r_chain.tqe_next) {
- if (rep->r_mrep == NULL && rxid == rep->r_xid) {
- /* Found it.. */
- rep->r_mrep = mrep;
- rep->r_md = md;
- rep->r_dpos = dpos;
- if (nfsrtton) {
- struct rttl *rt;
-
- rt = &nfsrtt.rttl[nfsrtt.pos];
- rt->proc = rep->r_procnum;
- rt->rto = NFS_RTO(nmp, proct[rep->r_procnum]);
- rt->sent = nmp->nm_sent;
- rt->cwnd = nmp->nm_cwnd;
- rt->srtt = nmp->nm_srtt[proct[rep->r_procnum] - 1];
- rt->sdrtt = nmp->nm_sdrtt[proct[rep->r_procnum] - 1];
- rt->fsid = nmp->nm_mountp->mnt_stat.f_fsid;
- getmicrotime(&rt->tstamp);
- if (rep->r_flags & R_TIMING)
- rt->rtt = rep->r_rtt;
- else
- rt->rtt = 1000000;
- nfsrtt.pos = (nfsrtt.pos + 1) % NFSRTTLOGSIZ;
- }
- /*
- * Update congestion window.
- * Do the additive increase of
- * one rpc/rtt.
- */
- if (nmp->nm_cwnd <= nmp->nm_sent) {
- nmp->nm_cwnd +=
- (NFS_CWNDSCALE * NFS_CWNDSCALE +
- (nmp->nm_cwnd >> 1)) / nmp->nm_cwnd;
- if (nmp->nm_cwnd > NFS_MAXCWND)
- nmp->nm_cwnd = NFS_MAXCWND;
- }
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_SENT;
- nmp->nm_sent -= NFS_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 -= (NFS_SRTT(rep) >> 3);
- NFS_SRTT(rep) += t1;
- if (t1 < 0)
- t1 = -t1;
- t1 -= (NFS_SDRTT(rep) >> 2);
- NFS_SDRTT(rep) += t1;
- }
- nmp->nm_timeouts = 0;
- break;
- }
- }
- /*
- * If not matched to a request, drop it.
- * If it's mine, get out.
- */
- if (rep == 0) {
- nfsstats.rpcunexpected++;
- m_freem(mrep);
- } else if (rep == myrep) {
- if (rep->r_mrep == NULL)
- panic("nfsreply nil");
- return (0);
- }
- if (myrep->r_flags & R_GETONEREP)
- return (0);
- }
-}
-
-/*
- * 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
- */
-int
-nfs_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp)
- struct vnode *vp;
- struct mbuf *mrest;
- int procnum;
- struct thread *td;
- struct ucred *cred;
- struct mbuf **mrp;
- struct mbuf **mdp;
- caddr_t *dposp;
-{
- register struct mbuf *mrep, *m2;
- register struct nfsreq *rep;
- register u_int32_t *tl;
- register int i;
- struct nfsmount *nmp;
- struct mbuf *m, *md, *mheadend;
- struct nfsnode *np;
- char nickv[RPCX_NICKVERF];
- time_t reqtime, waituntil;
- caddr_t dpos, cp2;
- int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
- int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
- int verf_len, verf_type;
- u_int32_t xid;
- u_quad_t frev;
- char *auth_str, *verf_str;
- NFSKERBKEY_T key; /* save session key */
-
- nmp = VFSTONFS(vp->v_mount);
- MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
- rep->r_nmp = nmp;
- rep->r_vp = vp;
- rep->r_td = td;
- rep->r_procnum = procnum;
- i = 0;
- m = mrest;
- while (m) {
- i += m->m_len;
- m = m->m_next;
- }
- mrest_len = i;
-
- /*
- * Get the RPC header with authorization.
- */
-kerbauth:
- verf_str = auth_str = (char *)0;
- if (nmp->nm_flag & NFSMNT_KERB) {
- verf_str = nickv;
- verf_len = sizeof (nickv);
- auth_type = RPCAUTH_KERB4;
- bzero((caddr_t)key, sizeof (key));
- if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
- &auth_len, verf_str, verf_len)) {
- error = nfs_getauth(nmp, rep, cred, &auth_str,
- &auth_len, verf_str, &verf_len, key);
- if (error) {
- free((caddr_t)rep, M_NFSREQ);
- m_freem(mrest);
- return (error);
- }
- }
- } else {
- auth_type = RPCAUTH_UNIX;
- if (cred->cr_ngroups < 1)
- panic("nfsreq nogrps");
- auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
- nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
- 5 * NFSX_UNSIGNED;
- }
- m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
- auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
- if (auth_str)
- free(auth_str, M_TEMP);
-
- /*
- * For stream protocols, insert a Sun RPC Record Mark.
- */
- if (nmp->nm_sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 |
- (m->m_pkthdr.len - NFSX_UNSIGNED));
- }
- rep->r_mreq = m;
- rep->r_xid = xid;
-tryagain:
- if (nmp->nm_flag & NFSMNT_SOFT)
- rep->r_retry = nmp->nm_retry;
- else
- rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */
- rep->r_rtt = rep->r_rexmit = 0;
- if (proct[procnum] > 0)
- rep->r_flags = R_TIMING;
- else
- rep->r_flags = 0;
- rep->r_mrep = NULL;
-
- /*
- * Do the client side RPC.
- */
- nfsstats.rpcrequests++;
- /*
- * Chain request into list of outstanding requests. Be sure
- * to put it LAST so timer finds oldest requests first.
- */
- s = splsoftclock();
- TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
-
- /* Get send time for nqnfs */
- reqtime = time_second;
-
- /*
- * 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 (nmp->nm_so && (nmp->nm_sotype != SOCK_DGRAM ||
- (nmp->nm_flag & NFSMNT_DUMBTIMR) ||
- nmp->nm_sent < nmp->nm_cwnd)) {
- splx(s);
- if (nmp->nm_soflags & PR_CONNREQUIRED)
- error = nfs_sndlock(rep);
- if (!error) {
- m2 = m_copym(m, 0, M_COPYALL, M_TRYWAIT);
- error = nfs_send(nmp->nm_so, nmp->nm_nam, m2, rep);
- if (nmp->nm_soflags & PR_CONNREQUIRED)
- nfs_sndunlock(rep);
- }
- if (!error && (rep->r_flags & R_MUSTRESEND) == 0) {
- nmp->nm_sent += NFS_CWNDSCALE;
- rep->r_flags |= R_SENT;
- }
- } else {
- splx(s);
- rep->r_rtt = -1;
- }
-
- /*
- * Wait for the reply from our send or the timer's.
- */
- if (!error || error == EPIPE)
- error = nfs_reply(rep);
-
- /*
- * RPC done, unlink the request.
- */
- s = splsoftclock();
- TAILQ_REMOVE(&nfs_reqq, rep, r_chain);
- splx(s);
-
- /*
- * Decrement the outstanding request count.
- */
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_SENT; /* paranoia */
- nmp->nm_sent -= NFS_CWNDSCALE;
- }
-
- /*
- * If there was a successful reply and a tprintf msg.
- * tprintf a response.
- */
- if (!error && (rep->r_flags & R_TPRINTFMSG))
- nfs_msg(rep->r_td, nmp->nm_mountp->mnt_stat.f_mntfromname,
- "is alive again");
- mrep = rep->r_mrep;
- md = rep->r_md;
- dpos = rep->r_dpos;
- if (error) {
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * break down the rpc header and check if ok
- */
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- if (*tl++ == rpc_msgdenied) {
- if (*tl == rpc_mismatch)
- error = EOPNOTSUPP;
- else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
- if (!failed_auth) {
- failed_auth++;
- mheadend->m_next = (struct mbuf *)0;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- goto kerbauth;
- } else
- error = EAUTH;
- } else
- error = EACCES;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * Grab any Kerberos verifier, otherwise just throw it away.
- */
- verf_type = fxdr_unsigned(int, *tl++);
- i = fxdr_unsigned(int32_t, *tl);
- if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
- error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
- if (error)
- goto nfsmout;
- } else if (i > 0)
- nfsm_adv(nfsm_rndup(i));
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- /* 0 == ok */
- if (*tl == 0) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl != 0) {
- error = fxdr_unsigned(int, *tl);
- 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((caddr_t)&lbolt,
- PSOCK, "nqnfstry", 0);
- trylater_delay *= nfs_backoff[trylater_cnt];
- if (trylater_cnt < 7)
- trylater_cnt++;
- goto tryagain;
- }
-
- /*
- * If the File Handle was stale, invalidate the
- * lookup cache, just in case.
- */
- if (error == ESTALE)
- cache_purge(vp);
- if (nmp->nm_flag & NFSMNT_NFSV3) {
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- error |= NFSERR_RETERR;
- } else
- m_freem(mrep);
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * For nqnfs, get any lease in reply
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl) {
- np = VTONFS(vp);
- nqlflag = fxdr_unsigned(int, *tl);
- nfsm_dissect(tl, u_int32_t *, 4*NFSX_UNSIGNED);
- cachable = fxdr_unsigned(int, *tl++);
- reqtime += fxdr_unsigned(int, *tl++);
- if (reqtime > time_second) {
- frev = fxdr_hyper(tl);
- nqnfs_clientlease(nmp, np, nqlflag,
- cachable, reqtime, frev);
- }
- }
- }
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- m_freem(rep->r_mreq);
- FREE((caddr_t)rep, M_NFSREQ);
- return (0);
- }
- m_freem(mrep);
- error = EPROTONOSUPPORT;
-nfsmout:
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Generate the rpc reply header
- * siz arg. is used to decide if adding a cluster is worthwhile
- */
-int
-nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
- int siz;
- struct nfsrv_descript *nd;
- struct nfssvc_sock *slp;
- int err;
- int cache;
- u_quad_t *frev;
- struct mbuf **mrq;
- struct mbuf **mbp;
- caddr_t *bposp;
-{
- register u_int32_t *tl;
- register struct mbuf *mreq;
- caddr_t bpos;
- struct mbuf *mb, *mb2;
-
- MGETHDR(mreq, M_TRYWAIT, MT_DATA);
- mb = mreq;
- /*
- * If this is a big reply, use a cluster else
- * try and leave leading space for the lower level headers.
- */
- siz += RPC_REPLYSIZ;
- if ((max_hdr + siz) >= MINCLSIZE) {
- MCLGET(mreq, M_TRYWAIT);
- } else
- mreq->m_data += max_hdr;
- tl = mtod(mreq, u_int32_t *);
- mreq->m_len = 6 * NFSX_UNSIGNED;
- bpos = ((caddr_t)tl) + mreq->m_len;
- *tl++ = txdr_unsigned(nd->nd_retxid);
- *tl++ = rpc_reply;
- if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
- *tl++ = rpc_msgdenied;
- if (err & NFSERR_AUTHERR) {
- *tl++ = rpc_autherr;
- *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
- mreq->m_len -= NFSX_UNSIGNED;
- bpos -= NFSX_UNSIGNED;
- } else {
- *tl++ = rpc_mismatch;
- *tl++ = txdr_unsigned(RPC_VER2);
- *tl = txdr_unsigned(RPC_VER2);
- }
- } else {
- *tl++ = rpc_msgaccepted;
-
- /*
- * For Kerberos authentication, we must send the nickname
- * verifier back, otherwise just RPCAUTH_NULL.
- */
- if (nd->nd_flag & ND_KERBFULL) {
- register struct nfsuid *nuidp;
- struct timeval ktvin, ktvout;
-
- for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
- (!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- ktvin.tv_sec =
- txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
- ktvin.tv_usec =
- txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Encrypt the timestamp in ecb mode using the
- * session key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *tl++ = rpc_auth_kerb;
- *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
- *tl = ktvout.tv_sec;
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- *tl++ = ktvout.tv_usec;
- *tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- switch (err) {
- case EPROGUNAVAIL:
- *tl = txdr_unsigned(RPC_PROGUNAVAIL);
- break;
- case EPROGMISMATCH:
- *tl = txdr_unsigned(RPC_PROGMISMATCH);
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (nd->nd_flag & ND_NQNFS) {
- *tl++ = txdr_unsigned(3);
- *tl = txdr_unsigned(3);
- } else {
- *tl++ = txdr_unsigned(2);
- *tl = txdr_unsigned(3);
- }
- break;
- case EPROCUNAVAIL:
- *tl = txdr_unsigned(RPC_PROCUNAVAIL);
- break;
- case EBADRPC:
- *tl = txdr_unsigned(RPC_GARBAGE);
- break;
- default:
- *tl = 0;
- if (err != NFSERR_RETVOID) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- if (err)
- *tl = txdr_unsigned(nfsrv_errmap(nd, err));
- else
- *tl = 0;
- }
- break;
- };
- }
-
- /*
- * For nqnfs, piggyback lease as requested.
- */
- if ((nd->nd_flag & ND_NQNFS) && err == 0) {
- if (nd->nd_flag & ND_LEASE) {
- nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
- *tl++ = txdr_unsigned(cache);
- *tl++ = txdr_unsigned(nd->nd_duration);
- txdr_hyper(*frev, tl);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- if (mrq != NULL)
- *mrq = mreq;
- *mbp = mb;
- *bposp = bpos;
- if (err != 0 && err != NFSERR_RETVOID)
- nfsstats.srvrpc_errs++;
- return (0);
-}
-
-
-#endif /* NFS_NOSERVER */
-/*
- * Nfs timer routine
- * Scan the nfsreq 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
-nfs_timer(arg)
- void *arg; /* never used */
-{
- register struct nfsreq *rep;
- register struct mbuf *m;
- register struct socket *so;
- register struct nfsmount *nmp;
- register int timeo;
- int s, error;
-#ifndef NFS_NOSERVER
- static long lasttime = 0;
- register struct nfssvc_sock *slp;
- u_quad_t cur_usec;
-#endif /* NFS_NOSERVER */
- struct thread *td = thread0; /* XXX for credentials, will break if sleep */
-
- s = splnet();
- for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
- nmp = rep->r_nmp;
- if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
- continue;
- if (nfs_sigintr(nmp, rep,
- (rep->r_td ? rep->r_td->td_proc : NULL))) {
- nfs_softterm(rep);
- continue;
- }
- if (rep->r_rtt >= 0) {
- rep->r_rtt++;
- if (nmp->nm_flag & NFSMNT_DUMBTIMR)
- timeo = nmp->nm_timeo;
- else
- timeo = NFS_RTO(nmp, proct[rep->r_procnum]);
- if (nmp->nm_timeouts > 0)
- timeo *= nfs_backoff[nmp->nm_timeouts - 1];
- if (rep->r_rtt <= timeo)
- continue;
- if (nmp->nm_timeouts < 8)
- nmp->nm_timeouts++;
- }
- /*
- * Check for server not responding
- */
- if ((rep->r_flags & R_TPRINTFMSG) == 0 &&
- rep->r_rexmit > nmp->nm_deadthresh) {
- nfs_msg(rep->r_td,
- nmp->nm_mountp->mnt_stat.f_mntfromname,
- "not responding");
- rep->r_flags |= R_TPRINTFMSG;
- }
- if (rep->r_rexmit >= rep->r_retry) { /* too many */
- nfsstats.rpctimeouts++;
- nfs_softterm(rep);
- continue;
- }
- if (nmp->nm_sotype != SOCK_DGRAM) {
- if (++rep->r_rexmit > NFS_MAXREXMIT)
- rep->r_rexmit = NFS_MAXREXMIT;
- continue;
- }
- if ((so = nmp->nm_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 &&
- ((nmp->nm_flag & NFSMNT_DUMBTIMR) ||
- (rep->r_flags & R_SENT) ||
- nmp->nm_sent < nmp->nm_cwnd) &&
- (m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))){
- if ((nmp->nm_flag & NFSMNT_NOCONN) == 0)
- error = (*so->so_proto->pr_usrreqs->pru_send)
- (so, 0, m, (struct sockaddr *)0,
- (struct mbuf *)0, td);
- else
- error = (*so->so_proto->pr_usrreqs->pru_send)
- (so, 0, m, nmp->nm_nam, (struct mbuf *)0,
- td);
- if (error) {
- if (NFSIGNORE_SOERROR(nmp->nm_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 > NFS_MAXREXMIT)
- rep->r_rexmit = NFS_MAXREXMIT;
- nmp->nm_cwnd >>= 1;
- if (nmp->nm_cwnd < NFS_CWNDSCALE)
- nmp->nm_cwnd = NFS_CWNDSCALE;
- nfsstats.rpcretries++;
- } else {
- rep->r_flags |= R_SENT;
- nmp->nm_sent += NFS_CWNDSCALE;
- }
- rep->r_rtt = 0;
- }
- }
- }
-#ifndef NFS_NOSERVER
- /*
- * Call the nqnfs server timer once a second to handle leases.
- */
- if (lasttime != time_second) {
- lasttime = time_second;
- nqnfs_serverd();
- }
-
- /*
- * Scan the write gathering queues for writes that need to be
- * completed now.
- */
- cur_usec = nfs_curusec();
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
- if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
- nfsrv_wakenfsd(slp);
- }
-#endif /* NFS_NOSERVER */
- splx(s);
- nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
-}
-
-/*
- * Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT).
- * The nm_send count is decremented now to avoid deadlocks when the process in
- * soreceive() hasn't yet managed to send its own request.
- */
-
-static void
-nfs_softterm(rep)
- struct nfsreq *rep;
-{
- rep->r_flags |= R_SOFTTERM;
-
- if (rep->r_flags & R_SENT) {
- rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
- rep->r_flags &= ~R_SENT;
- }
-}
-
-/*
- * Test for a termination condition pending on the process.
- * This is used for NFSMNT_INT mounts.
- */
-int
-nfs_sigintr(nmp, rep, p)
- struct nfsmount *nmp;
- struct nfsreq *rep;
- register struct proc *p;
-{
- sigset_t tmpset;
-
- if (rep && (rep->r_flags & R_SOFTTERM))
- return (EINTR);
- if (!(nmp->nm_flag & NFSMNT_INT))
- return (0);
- if (p == NULL)
- return (0);
-
- tmpset = p->p_siglist;
- SIGSETNAND(tmpset, p->p_sigmask);
- SIGSETNAND(tmpset, p->p_sigignore);
- if (SIGNOTEMPTY(p->p_siglist) && NFSINT_SIGMASK(tmpset))
- return (EINTR);
-
- 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.
- */
-int
-nfs_sndlock(rep)
- struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
- struct thread *td;
- int slpflag = 0, slptimeo = 0;
-
- if (rep) {
- td = rep->r_td;
- if (rep->r_nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- } else
- td = (struct thread *)0;
- while (*statep & NFSSTA_SNDLOCK) {
- if (nfs_sigintr(rep->r_nmp, rep, td ? td->td_proc : NULL))
- return (EINTR);
- *statep |= NFSSTA_WANTSND;
- (void) tsleep((caddr_t)statep, slpflag | (PZERO - 1),
- "nfsndlck", slptimeo);
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- *statep |= NFSSTA_SNDLOCK;
- return (0);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-void
-nfs_sndunlock(rep)
- struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
-
- if ((*statep & NFSSTA_SNDLOCK) == 0)
- panic("nfs sndunlock");
- *statep &= ~NFSSTA_SNDLOCK;
- if (*statep & NFSSTA_WANTSND) {
- *statep &= ~NFSSTA_WANTSND;
- wakeup((caddr_t)statep);
- }
-}
-
-static int
-nfs_rcvlock(rep)
- register struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
- int slpflag, slptimeo = 0;
-
- if (rep->r_nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- else
- slpflag = 0;
- while (*statep & NFSSTA_RCVLOCK) {
- if (nfs_sigintr(rep->r_nmp, rep,
- (rep->r_td ? rep->r_td->td_proc : NULL)))
- return (EINTR);
- *statep |= NFSSTA_WANTRCV;
- (void) tsleep((caddr_t)statep, slpflag | (PZERO - 1), "nfsrcvlk",
- slptimeo);
- /*
- * If our reply was recieved while we were sleeping,
- * then just return without taking the lock to avoid a
- * situation where a single iod could 'capture' the
- * recieve lock.
- */
- if (rep->r_mrep != NULL)
- return (EALREADY);
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- *statep |= NFSSTA_RCVLOCK;
- return (0);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-static void
-nfs_rcvunlock(rep)
- register struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
-
- if ((*statep & NFSSTA_RCVLOCK) == 0)
- panic("nfs rcvunlock");
- *statep &= ~NFSSTA_RCVLOCK;
- if (*statep & NFSSTA_WANTRCV) {
- *statep &= ~NFSSTA_WANTRCV;
- wakeup((caddr_t)statep);
- }
-}
-
-/*
- * nfs_realign:
- *
- * Check for badly aligned mbuf data and realign by copying the unaligned
- * portion of the data into a new mbuf chain and freeing the portions
- * of the old chain that were replaced.
- *
- * We cannot simply realign the data within the existing mbuf chain
- * because the underlying buffers may contain other rpc commands and
- * we cannot afford to overwrite them.
- *
- * We would prefer to avoid this situation entirely. The situation does
- * not occur with NFS/UDP and is supposed to only occassionally occur
- * with TCP. Use vfs.nfs.realign_count and realign_test to check this.
- */
-static void
-nfs_realign(pm, hsiz)
- register struct mbuf **pm;
- int hsiz;
-{
- struct mbuf *m;
- struct mbuf *n = NULL;
- int off = 0;
-
- ++nfs_realign_test;
-
- while ((m = *pm) != NULL) {
- if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
- MGET(n, M_TRYWAIT, MT_DATA);
- if (m->m_len >= MINCLSIZE) {
- MCLGET(n, M_TRYWAIT);
- }
- 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) {
- ++nfs_realign_count;
- 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;
- }
-}
-
-#ifndef NFS_NOSERVER
-
-/*
- * Parse an RPC request
- * - verify it
- * - fill in the cred struct.
- */
-int
-nfs_getreq(nd, nfsd, has_header)
- register struct nfsrv_descript *nd;
- struct nfsd *nfsd;
- int has_header;
-{
- register int len, i;
- register u_int32_t *tl;
- register int32_t t1;
- struct uio uio;
- struct iovec iov;
- caddr_t dpos, cp2, cp;
- u_int32_t nfsvers, auth_type;
- uid_t nickuid;
- int error = 0, nqnfs = 0, ticklen;
- struct mbuf *mrep, *md;
- register struct nfsuid *nuidp;
- struct timeval tvin, tvout;
-#if 0 /* until encrypted keys are implemented */
- NFSKERBKEYSCHED_T keys; /* stores key schedule */
-#endif
-
- mrep = nd->nd_mrep;
- md = nd->nd_md;
- dpos = nd->nd_dpos;
- if (has_header) {
- nfsm_dissect(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
- nd->nd_retxid = fxdr_unsigned(u_int32_t, *tl++);
- if (*tl++ != rpc_call) {
- m_freem(mrep);
- return (EBADRPC);
- }
- } else
- nfsm_dissect(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
- nd->nd_repstat = 0;
- nd->nd_flag = 0;
- if (*tl++ != rpc_vers) {
- nd->nd_repstat = ERPCMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (*tl != nfs_prog) {
- if (*tl == nqnfs_prog)
- nqnfs++;
- else {
- nd->nd_repstat = EPROGUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- }
- tl++;
- nfsvers = fxdr_unsigned(u_int32_t, *tl++);
- if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
- (nfsvers != NQNFS_VER3 && nqnfs)) {
- nd->nd_repstat = EPROGMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (nqnfs)
- nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
- else if (nfsvers == NFS_VER3)
- nd->nd_flag = ND_NFSV3;
- nd->nd_procnum = fxdr_unsigned(u_int32_t, *tl++);
- if (nd->nd_procnum == NFSPROC_NULL)
- return (0);
- if (nd->nd_procnum >= NFS_NPROCS ||
- (!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
- (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
- nd->nd_repstat = EPROCUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if ((nd->nd_flag & ND_NFSV3) == 0)
- nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
- auth_type = *tl++;
- len = fxdr_unsigned(int, *tl++);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
-
- nd->nd_flag &= ~ND_KERBAUTH;
- /*
- * Handle auth_unix or auth_kerb.
- */
- if (auth_type == rpc_auth_unix) {
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > NFS_MAXNAMLEN) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_adv(nfsm_rndup(len));
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
- nd->nd_cr.cr_ref = 1;
- nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
- nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
- len = fxdr_unsigned(int, *tl);
- if (len < 0 || len > RPCAUTH_UNIXGIDS) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_dissect(tl, u_int32_t *, (len + 2) * NFSX_UNSIGNED);
- for (i = 1; i <= len; i++)
- if (i < NGROUPS)
- nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
- else
- tl++;
- nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
- if (nd->nd_cr.cr_ngroups > 1)
- nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
- if (len > 0)
- nfsm_adv(nfsm_rndup(len));
- } else if (auth_type == rpc_auth_kerb) {
- switch (fxdr_unsigned(int, *tl++)) {
- case RPCAKN_FULLNAME:
- ticklen = fxdr_unsigned(int, *tl);
- *((u_int32_t *)nfsd->nfsd_authstr) = *tl;
- uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
- nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
- if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
- m_freem(mrep);
- return (EBADRPC);
- }
- uio.uio_offset = 0;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_segflg = UIO_SYSSPACE;
- iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
- iov.iov_len = RPCAUTH_MAXSIZ - 4;
- nfsm_mtouio(&uio, uio.uio_resid);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
- printf("Bad kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
- tl = (u_int32_t *)cp;
- if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
- printf("Not fullname kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- cp += NFSX_UNSIGNED;
- bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
- nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
- nd->nd_flag |= ND_KERBFULL;
- nfsd->nfsd_flag |= NFSD_NEEDAUTH;
- break;
- case RPCAKN_NICKNAME:
- if (len != 2 * NFSX_UNSIGNED) {
- printf("Kerb nickname short\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nickuid = fxdr_unsigned(uid_t, *tl);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
- printf("Kerb nick verifier bad\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- tvin.tv_sec = *tl++;
- tvin.tv_usec = *tl;
-
- for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nickuid &&
- (!nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (!nuidp) {
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * Now, decrypt the timestamp using the session key
- * and validate it.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
- tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
- if (nuidp->nu_expire < time_second ||
- nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
- (nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
- nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
- nuidp->nu_expire = 0;
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
- nd->nd_flag |= ND_KERBNICK;
- };
- } else {
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * For nqnfs, get piggybacked lease request.
- */
- if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_flag |= fxdr_unsigned(int, *tl);
- if (nd->nd_flag & ND_LEASE) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_duration = fxdr_unsigned(int32_t, *tl);
- } else
- nd->nd_duration = NQ_MINLEASE;
- } else
- nd->nd_duration = NQ_MINLEASE;
- nd->nd_md = md;
- nd->nd_dpos = dpos;
- return (0);
-nfsmout:
- return (error);
-}
-
-#endif
-
-static int
-nfs_msg(td, server, msg)
- struct thread *td;
- char *server, *msg;
-{
-
- tprintf(td->td_proc, LOG_INFO, "nfs server %s: %s\n", server, msg);
- return (0);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Socket upcall routine for the nfsd sockets.
- * The caddr_t arg is a pointer to the "struct nfssvc_sock".
- * Essentially do as much as possible non-blocking, else punt and it will
- * be called with M_TRYWAIT from an nfsd.
- */
-void
-nfsrv_rcv(so, arg, waitflag)
- struct socket *so;
- void *arg;
- int waitflag;
-{
- register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
- register struct mbuf *m;
- struct mbuf *mp;
- struct sockaddr *nam;
- struct uio auio;
- int flags, error;
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
-#ifdef notdef
- /*
- * Define this to test for nfsds handling this under heavy load.
- */
- if (waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ; goto dorecs;
- }
-#endif
- auio.uio_td = NULL;
- if (so->so_type == SOCK_STREAM) {
- /*
- * If there are already records on the queue, defer soreceive()
- * to an nfsd so that there is feedback to the TCP layer that
- * the nfs servers are heavily loaded.
- */
- if (STAILQ_FIRST(&slp->ns_rec) && waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ;
- goto dorecs;
- }
-
- /*
- * Do soreceive().
- */
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, &nam, &auio, &mp, (struct mbuf **)0, &flags);
- if (error || mp == (struct mbuf *)0) {
- if (error == EWOULDBLOCK)
- slp->ns_flag |= SLP_NEEDQ;
- else
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- m = mp;
- if (slp->ns_rawend) {
- slp->ns_rawend->m_next = m;
- slp->ns_cc += 1000000000 - auio.uio_resid;
- } else {
- slp->ns_raw = m;
- slp->ns_cc = 1000000000 - auio.uio_resid;
- }
- while (m->m_next)
- m = m->m_next;
- slp->ns_rawend = m;
-
- /*
- * Now try and parse record(s) out of the raw stream data.
- */
- error = nfsrv_getstream(slp, waitflag);
- if (error) {
- if (error == EPERM)
- slp->ns_flag |= SLP_DISCONN;
- else
- slp->ns_flag |= SLP_NEEDQ;
- }
- } else {
- do {
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, &nam, &auio, &mp,
- (struct mbuf **)0, &flags);
- if (mp) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec),
- M_NFSRVDESC, waitflag);
- if (!rec) {
- if (nam)
- FREE(nam, M_SONAME);
- m_freem(mp);
- continue;
- }
- nfs_realign(&mp, 10 * NFSX_UNSIGNED);
- rec->nr_address = nam;
- rec->nr_packet = mp;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- }
- if (error) {
- if ((so->so_proto->pr_flags & PR_CONNREQUIRED)
- && error != EWOULDBLOCK) {
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- }
- } while (mp);
- }
-
- /*
- * Now try and process the request records, non-blocking.
- */
-dorecs:
- if (waitflag == M_DONTWAIT &&
- (STAILQ_FIRST(&slp->ns_rec)
- || (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))))
- nfsrv_wakenfsd(slp);
-}
-
-/*
- * Try and extract an RPC request from the mbuf data list received on a
- * stream socket. The "waitflag" argument indicates whether or not it
- * can sleep.
- */
-static int
-nfsrv_getstream(slp, waitflag)
- register struct nfssvc_sock *slp;
- int waitflag;
-{
- register struct mbuf *m, **mpp;
- register char *cp1, *cp2;
- register int len;
- struct mbuf *om, *m2, *recm = NULL;
- u_int32_t recmark;
-
- if (slp->ns_flag & SLP_GETSTREAM)
- panic("nfs getstream");
- slp->ns_flag |= SLP_GETSTREAM;
- for (;;) {
- if (slp->ns_reclen == 0) {
- if (slp->ns_cc < NFSX_UNSIGNED) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
- m = slp->ns_raw;
- if (m->m_len >= NFSX_UNSIGNED) {
- bcopy(mtod(m, caddr_t), (caddr_t)&recmark, NFSX_UNSIGNED);
- m->m_data += NFSX_UNSIGNED;
- m->m_len -= NFSX_UNSIGNED;
- } else {
- cp1 = (caddr_t)&recmark;
- cp2 = mtod(m, caddr_t);
- while (cp1 < ((caddr_t)&recmark) + NFSX_UNSIGNED) {
- while (m->m_len == 0) {
- m = m->m_next;
- cp2 = mtod(m, caddr_t);
- }
- *cp1++ = *cp2++;
- m->m_data++;
- m->m_len--;
- }
- }
- slp->ns_cc -= NFSX_UNSIGNED;
- recmark = ntohl(recmark);
- slp->ns_reclen = recmark & ~0x80000000;
- if (recmark & 0x80000000)
- slp->ns_flag |= SLP_LASTFRAG;
- else
- slp->ns_flag &= ~SLP_LASTFRAG;
- if (slp->ns_reclen > NFS_MAXPACKET) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EPERM);
- }
- }
-
- /*
- * Now get the record part.
- */
- if (slp->ns_cc == slp->ns_reclen) {
- recm = slp->ns_raw;
- slp->ns_raw = slp->ns_rawend = (struct mbuf *)0;
- slp->ns_cc = slp->ns_reclen = 0;
- } else if (slp->ns_cc > slp->ns_reclen) {
- len = 0;
- m = slp->ns_raw;
- om = (struct mbuf *)0;
- while (len < slp->ns_reclen) {
- if ((len + m->m_len) > slp->ns_reclen) {
- m2 = m_copym(m, 0, slp->ns_reclen - len,
- waitflag);
- if (m2) {
- if (om) {
- om->m_next = m2;
- recm = slp->ns_raw;
- } else
- recm = m2;
- m->m_data += slp->ns_reclen - len;
- m->m_len -= slp->ns_reclen - len;
- len = slp->ns_reclen;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EWOULDBLOCK);
- }
- } else if ((len + m->m_len) == slp->ns_reclen) {
- om = m;
- len += m->m_len;
- m = m->m_next;
- recm = slp->ns_raw;
- om->m_next = (struct mbuf *)0;
- } else {
- om = m;
- len += m->m_len;
- m = m->m_next;
- }
- }
- slp->ns_raw = m;
- slp->ns_cc -= len;
- slp->ns_reclen = 0;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
-
- /*
- * Accumulate the fragments into a record.
- */
- mpp = &slp->ns_frag;
- while (*mpp)
- mpp = &((*mpp)->m_next);
- *mpp = recm;
- if (slp->ns_flag & SLP_LASTFRAG) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec), M_NFSRVDESC, waitflag);
- if (!rec) {
- m_freem(slp->ns_frag);
- } else {
- nfs_realign(&slp->ns_frag, 10 * NFSX_UNSIGNED);
- rec->nr_address = (struct sockaddr *)0;
- rec->nr_packet = slp->ns_frag;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- }
- slp->ns_frag = (struct mbuf *)0;
- }
- }
-}
-
-/*
- * Parse an RPC header.
- */
-int
-nfsrv_dorec(slp, nfsd, ndp)
- register struct nfssvc_sock *slp;
- struct nfsd *nfsd;
- struct nfsrv_descript **ndp;
-{
- struct nfsrv_rec *rec;
- register struct mbuf *m;
- struct sockaddr *nam;
- register struct nfsrv_descript *nd;
- int error;
-
- *ndp = NULL;
- if ((slp->ns_flag & SLP_VALID) == 0 || !STAILQ_FIRST(&slp->ns_rec))
- return (ENOBUFS);
- rec = STAILQ_FIRST(&slp->ns_rec);
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- nam = rec->nr_address;
- m = rec->nr_packet;
- free(rec, M_NFSRVDESC);
- MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
- M_NFSRVDESC, M_WAITOK);
- nd->nd_md = nd->nd_mrep = m;
- nd->nd_nam2 = nam;
- nd->nd_dpos = mtod(m, caddr_t);
- error = nfs_getreq(nd, nfsd, TRUE);
- if (error) {
- if (nam) {
- FREE(nam, M_SONAME);
- }
- free((caddr_t)nd, M_NFSRVDESC);
- return (error);
- }
- *ndp = nd;
- nfsd->nfsd_nd = nd;
- return (0);
-}
-
-/*
- * Search for a sleeping nfsd and wake it up.
- * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the
- * running nfsds will go look for the work in the nfssvc_sock list.
- */
-void
-nfsrv_wakenfsd(slp)
- struct nfssvc_sock *slp;
-{
- register struct nfsd *nd;
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
- for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
- if (nd->nfsd_flag & NFSD_WAITING) {
- nd->nfsd_flag &= ~NFSD_WAITING;
- if (nd->nfsd_slp)
- panic("nfsd wakeup");
- slp->ns_sref++;
- nd->nfsd_slp = slp;
- wakeup((caddr_t)nd);
- return;
- }
- }
- slp->ns_flag |= SLP_DOREC;
- nfsd_head_flag |= NFSD_CHECKSLP;
-}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfs/nfs_srvcache.c b/sys/nfs/nfs_srvcache.c
deleted file mode 100644
index e7b10dd..0000000
--- a/sys/nfs/nfs_srvcache.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * 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.
- * 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_srvcache.c 8.3 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-/*
- * Reference: Chet Juszczak, "Improving the Performance and Correctness
- * of an NFS Server", in Proc. Winter 1989 USENIX Conference,
- * pages 53-63. San Diego, February 1989.
- */
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h> /* for dup_sockaddr */
-
-#include <netinet/in.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsrvcache.h>
-
-#ifndef NFS_NOSERVER
-extern struct nfsstats nfsstats;
-extern int nfsv2_procid[NFS_NPROCS];
-static long numnfsrvcache;
-static long desirednfsrvcache = NFSRVCACHESIZ;
-
-#define NFSRCHASH(xid) \
- (&nfsrvhashtbl[((xid) + ((xid) >> 24)) & nfsrvhash])
-static LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl;
-static TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead;
-static u_long nfsrvhash;
-
-#define TRUE 1
-#define FALSE 0
-
-#define NETFAMILY(rp) \
- (((rp)->rc_flag & RC_INETADDR) ? AF_INET : AF_ISO)
-
-/*
- * Static array that defines which nfs rpc's are nonidempotent
- */
-static int nonidempotent[NFS_NPROCS] = {
- FALSE,
- FALSE,
- TRUE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
-};
-
-/* True iff the rpc reply is an nfs status ONLY! */
-static int nfsv2_repstat[NFS_NPROCS] = {
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- FALSE,
- TRUE,
- FALSE,
- FALSE,
-};
-
-/*
- * Initialize the server request cache list
- */
-void
-nfsrv_initcache()
-{
-
- nfsrvhashtbl = hashinit(desirednfsrvcache, M_NFSD, &nfsrvhash);
- TAILQ_INIT(&nfsrvlruhead);
-}
-
-/*
- * Look for the request in the cache
- * If found then
- * return action and optionally reply
- * else
- * insert it in the cache
- *
- * The rules are as follows:
- * - if in progress, return DROP request
- * - if completed within DELAY of the current time, return DROP it
- * - if completed a longer time ago return REPLY if the reply was cached or
- * return DOIT
- * Update/add new request at end of lru list
- */
-int
-nfsrv_getcache(nd, slp, repp)
- register struct nfsrv_descript *nd;
- struct nfssvc_sock *slp;
- struct mbuf **repp;
-{
- register struct nfsrvcache *rp;
- struct mbuf *mb;
- struct sockaddr_in *saddr;
- caddr_t bpos;
- int ret;
-
- /*
- * Don't cache recent requests for reliable transport protocols.
- * (Maybe we should for the case of a reconnect, but..)
- */
- if (!nd->nd_nam2)
- return (RC_DOIT);
-loop:
- for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
- rp = rp->rc_hash.le_next) {
- if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
- netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
- NFS_DPF(RC, ("H%03x", rp->rc_xid & 0xfff));
- if ((rp->rc_flag & RC_LOCKED) != 0) {
- rp->rc_flag |= RC_WANTED;
- (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
- goto loop;
- }
- rp->rc_flag |= RC_LOCKED;
- /* If not at end of LRU chain, move it there */
- if (rp->rc_lru.tqe_next) {
- TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
- TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
- }
- if (rp->rc_state == RC_UNUSED)
- panic("nfsrv cache");
- if (rp->rc_state == RC_INPROG) {
- nfsstats.srvcache_inproghits++;
- ret = RC_DROPIT;
- } else if (rp->rc_flag & RC_REPSTATUS) {
- nfsstats.srvcache_nonidemdonehits++;
- nfs_rephead(0, nd, slp, rp->rc_status,
- 0, (u_quad_t *)0, repp, &mb, &bpos);
- ret = RC_REPLY;
- } else if (rp->rc_flag & RC_REPMBUF) {
- nfsstats.srvcache_nonidemdonehits++;
- *repp = m_copym(rp->rc_reply, 0, M_COPYALL,
- M_TRYWAIT);
- ret = RC_REPLY;
- } else {
- nfsstats.srvcache_idemdonehits++;
- rp->rc_state = RC_INPROG;
- ret = RC_DOIT;
- }
- rp->rc_flag &= ~RC_LOCKED;
- if (rp->rc_flag & RC_WANTED) {
- rp->rc_flag &= ~RC_WANTED;
- wakeup((caddr_t)rp);
- }
- return (ret);
- }
- }
- nfsstats.srvcache_misses++;
- NFS_DPF(RC, ("M%03x", nd->nd_retxid & 0xfff));
- if (numnfsrvcache < desirednfsrvcache) {
- rp = (struct nfsrvcache *)malloc((u_long)sizeof *rp,
- M_NFSD, M_WAITOK | M_ZERO);
- numnfsrvcache++;
- rp->rc_flag = RC_LOCKED;
- } else {
- rp = nfsrvlruhead.tqh_first;
- while ((rp->rc_flag & RC_LOCKED) != 0) {
- rp->rc_flag |= RC_WANTED;
- (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
- rp = nfsrvlruhead.tqh_first;
- }
- rp->rc_flag |= RC_LOCKED;
- LIST_REMOVE(rp, rc_hash);
- TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
- if (rp->rc_flag & RC_REPMBUF)
- m_freem(rp->rc_reply);
- if (rp->rc_flag & RC_NAM)
- FREE(rp->rc_nam, M_SONAME);
- rp->rc_flag &= (RC_LOCKED | RC_WANTED);
- }
- TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
- rp->rc_state = RC_INPROG;
- rp->rc_xid = nd->nd_retxid;
- saddr = (struct sockaddr_in *)nd->nd_nam;
- switch (saddr->sin_family) {
- case AF_INET:
- rp->rc_flag |= RC_INETADDR;
- rp->rc_inetaddr = saddr->sin_addr.s_addr;
- break;
- case AF_ISO:
- default:
- rp->rc_flag |= RC_NAM;
- rp->rc_nam = dup_sockaddr(nd->nd_nam, 1);
- break;
- };
- rp->rc_proc = nd->nd_procnum;
- LIST_INSERT_HEAD(NFSRCHASH(nd->nd_retxid), rp, rc_hash);
- rp->rc_flag &= ~RC_LOCKED;
- if (rp->rc_flag & RC_WANTED) {
- rp->rc_flag &= ~RC_WANTED;
- wakeup((caddr_t)rp);
- }
- return (RC_DOIT);
-}
-
-/*
- * Update a request cache entry after the rpc has been done
- */
-void
-nfsrv_updatecache(nd, repvalid, repmbuf)
- register struct nfsrv_descript *nd;
- int repvalid;
- struct mbuf *repmbuf;
-{
- register struct nfsrvcache *rp;
-
- if (!nd->nd_nam2)
- return;
-loop:
- for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
- rp = rp->rc_hash.le_next) {
- if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
- netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
- NFS_DPF(RC, ("U%03x", rp->rc_xid & 0xfff));
- if ((rp->rc_flag & RC_LOCKED) != 0) {
- rp->rc_flag |= RC_WANTED;
- (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
- goto loop;
- }
- rp->rc_flag |= RC_LOCKED;
- if (rp->rc_state == RC_DONE) {
- /*
- * This can occur if the cache is too small.
- * Retransmits of the same request aren't
- * dropped so we may see the operation
- * complete more then once.
- */
- if (rp->rc_flag & RC_REPMBUF) {
- m_freem(rp->rc_reply);
- rp->rc_flag &= ~RC_REPMBUF;
- }
- }
- rp->rc_state = RC_DONE;
- /*
- * If we have a valid reply update status and save
- * the reply for non-idempotent rpc's.
- */
- if (repvalid && nonidempotent[nd->nd_procnum]) {
- if ((nd->nd_flag & ND_NFSV3) == 0 &&
- nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
- rp->rc_status = nd->nd_repstat;
- rp->rc_flag |= RC_REPSTATUS;
- } else {
- rp->rc_reply = m_copym(repmbuf,
- 0, M_COPYALL, M_TRYWAIT);
- rp->rc_flag |= RC_REPMBUF;
- }
- }
- rp->rc_flag &= ~RC_LOCKED;
- if (rp->rc_flag & RC_WANTED) {
- rp->rc_flag &= ~RC_WANTED;
- wakeup((caddr_t)rp);
- }
- return;
- }
- }
- NFS_DPF(RC, ("L%03x", nd->nd_retxid & 0xfff));
-}
-
-/*
- * Clean out the cache. Called when the last nfsd terminates.
- */
-void
-nfsrv_cleancache()
-{
- register struct nfsrvcache *rp, *nextrp;
-
- for (rp = nfsrvlruhead.tqh_first; rp != 0; rp = nextrp) {
- nextrp = rp->rc_lru.tqe_next;
- LIST_REMOVE(rp, rc_hash);
- TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
- if (rp->rc_flag & RC_REPMBUF)
- m_freem(rp->rc_reply);
- if (rp->rc_flag & RC_NAM)
- free(rp->rc_nam, M_SONAME);
- free(rp, M_NFSD);
- }
- numnfsrvcache = 0;
-}
-
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c
deleted file mode 100644
index 4425129..0000000
--- a/sys/nfs/nfs_subs.c
+++ /dev/null
@@ -1,2243 +0,0 @@
-/*
- * 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.
- * 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_subs.c 8.8 (Berkeley) 5/22/95
- * $FreeBSD$
- */
-
-/*
- * These functions support the macros and help fiddle mbuf chains for
- * the nfs op functions. They do things like create the rpc header and
- * copy data between mbuf chains and uio lists.
- */
-#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 <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_zone.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
-
-#include <netinet/in.h>
-
-/*
- * Data items converted to xdr at startup, since they are constant
- * This is kinda hokey, but may save a little time doing byte swaps
- */
-u_int32_t nfs_xdrneg1;
-u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
- rpc_auth_kerb;
-u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false;
-
-/* And other global data */
-static u_int32_t nfs_xid = 0;
-static enum vtype nv2tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON
-};
-enum vtype nv3tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
-};
-
-int nfs_ticks;
-int nfs_pbuf_freecnt = -1; /* start out unlimited */
-
-struct nfs_reqq nfs_reqq;
-struct nfssvc_sockhead nfssvc_sockhead;
-int nfssvc_sockhead_flag;
-struct nfsd_head nfsd_head;
-int nfsd_head_flag;
-struct nfs_bufq nfs_bufq;
-struct nqtimerhead nqtimerhead;
-struct nqfhhashhead *nqfhhashtbl;
-u_long nqfhhash;
-
-static void (*nfs_prev_lease_updatetime) __P((int));
-static int nfs_prev_nfssvc_sy_narg;
-static sy_call_t *nfs_prev_nfssvc_sy_call;
-
-#ifndef NFS_NOSERVER
-
-static vop_t *nfs_prev_vop_lease_check;
-
-/*
- * Mapping of old NFS Version 2 RPC numbers to generic numbers.
- */
-int nfsv3_procid[NFS_NPROCS] = {
- NFSPROC_NULL,
- NFSPROC_GETATTR,
- NFSPROC_SETATTR,
- NFSPROC_NOOP,
- NFSPROC_LOOKUP,
- NFSPROC_READLINK,
- NFSPROC_READ,
- NFSPROC_NOOP,
- NFSPROC_WRITE,
- NFSPROC_CREATE,
- NFSPROC_REMOVE,
- NFSPROC_RENAME,
- NFSPROC_LINK,
- NFSPROC_SYMLINK,
- NFSPROC_MKDIR,
- NFSPROC_RMDIR,
- NFSPROC_READDIR,
- NFSPROC_FSSTAT,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP
-};
-
-#endif /* NFS_NOSERVER */
-/*
- * and the reverse mapping from generic to Version 2 procedure numbers
- */
-int nfsv2_procid[NFS_NPROCS] = {
- NFSV2PROC_NULL,
- NFSV2PROC_GETATTR,
- NFSV2PROC_SETATTR,
- NFSV2PROC_LOOKUP,
- NFSV2PROC_NOOP,
- NFSV2PROC_READLINK,
- NFSV2PROC_READ,
- NFSV2PROC_WRITE,
- NFSV2PROC_CREATE,
- NFSV2PROC_MKDIR,
- NFSV2PROC_SYMLINK,
- NFSV2PROC_CREATE,
- NFSV2PROC_REMOVE,
- NFSV2PROC_RMDIR,
- NFSV2PROC_RENAME,
- NFSV2PROC_LINK,
- NFSV2PROC_READDIR,
- NFSV2PROC_NOOP,
- NFSV2PROC_STATFS,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
-};
-
-#ifndef NFS_NOSERVER
-/*
- * Maps errno values to nfs error numbers.
- * Use NFSERR_IO as the catch all for ones not specifically defined in
- * RFC 1094.
- */
-static u_char nfsrv_v2errmap[ELAST] = {
- NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
- NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
- NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO /* << Last is 86 */
-};
-
-/*
- * Maps errno values to nfs error numbers.
- * Although it is not obvious whether or not NFS clients really care if
- * a returned error value is in the specified list for the procedure, the
- * safest thing to do is filter them appropriately. For Version 2, the
- * X/Open XNFS document is the only specification that defines error values
- * for each RPC (The RFC simply lists all possible error values for all RPCs),
- * so I have decided to not do this for Version 2.
- * The first entry is the default error return and the rest are the valid
- * errors for that RPC in increasing numeric order.
- */
-static short nfsv3err_null[] = {
- 0,
- 0,
-};
-
-static short nfsv3err_getattr[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_setattr[] = {
- NFSERR_IO,
- NFSERR_PERM,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOT_SYNC,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_lookup[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_access[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_read[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_NXIO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_write[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_FBIG,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_create[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_mkdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_symlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_mknod[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- NFSERR_BADTYPE,
- 0,
-};
-
-static short nfsv3err_remove[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_rmdir[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_rename[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_ISDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_link[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readdirplus[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_NOTSUPP,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_fsstat[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_fsinfo[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_pathconf[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_commit[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short *nfsrv_v3errmap[] = {
- nfsv3err_null,
- nfsv3err_getattr,
- nfsv3err_setattr,
- nfsv3err_lookup,
- nfsv3err_access,
- nfsv3err_readlink,
- nfsv3err_read,
- nfsv3err_write,
- nfsv3err_create,
- nfsv3err_mkdir,
- nfsv3err_symlink,
- nfsv3err_mknod,
- nfsv3err_remove,
- nfsv3err_rmdir,
- nfsv3err_rename,
- nfsv3err_link,
- nfsv3err_readdir,
- nfsv3err_readdirplus,
- nfsv3err_fsstat,
- nfsv3err_fsinfo,
- nfsv3err_pathconf,
- nfsv3err_commit,
-};
-
-#endif /* NFS_NOSERVER */
-
-extern struct nfsrtt nfsrtt;
-extern time_t nqnfsstarttime;
-extern int nqsrv_clockskew;
-extern int nqsrv_writeslack;
-extern int nqsrv_maxlease;
-extern struct nfsstats nfsstats;
-extern int nqnfs_piggy[NFS_NPROCS];
-extern nfstype nfsv2_type[9];
-extern nfstype nfsv3_type[9];
-extern struct nfsnodehashhead *nfsnodehashtbl;
-extern u_long nfsnodehash;
-
-struct nfssvc_args;
-extern int nfssvc(struct thread *, struct nfssvc_args *, int *);
-
-LIST_HEAD(nfsnodehashhead, nfsnode);
-
-int nfs_webnamei __P((struct nameidata *, struct vnode *, struct thread *));
-
-u_quad_t
-nfs_curusec()
-{
- struct timeval tv;
-
- getmicrotime(&tv);
- return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
-}
-
-/*
- * Create the header for an rpc request packet
- * The hsiz is the size of the rest of the nfs request header.
- * (just used to decide if a cluster is a good idea)
- */
-struct mbuf *
-nfsm_reqh(vp, procid, hsiz, bposp)
- struct vnode *vp;
- u_long procid;
- int hsiz;
- caddr_t *bposp;
-{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- struct mbuf *mb2;
- struct nfsmount *nmp;
- int nqflag;
-
- MGET(mb, M_TRYWAIT, MT_DATA);
- if (hsiz >= MINCLSIZE)
- MCLGET(mb, M_TRYWAIT);
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
-
- /*
- * For NQNFS, add lease request.
- */
- if (vp) {
- nmp = VFSTONFS(vp->v_mount);
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nqflag = NQNFS_NEEDLEASE(vp, procid);
- if (nqflag) {
- nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nqflag);
- *tl = txdr_unsigned(nmp->nm_leaseterm);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- }
- /* Finally, return values */
- *bposp = bpos;
- return (mb);
-}
-
-/*
- * 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.
- * Returns the head of the mbuf list.
- */
-struct mbuf *
-nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
- verf_str, mrest, mrest_len, mbp, xidp)
- register struct ucred *cr;
- int nmflag;
- int procid;
- int auth_type;
- int auth_len;
- char *auth_str;
- int verf_len;
- char *verf_str;
- struct mbuf *mrest;
- int mrest_len;
- struct mbuf **mbp;
- u_int32_t *xidp;
-{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- register int i;
- struct mbuf *mreq, *mb2;
- int siz, grpsiz, authsiz;
-
- authsiz = nfsm_rndup(auth_len);
- MGETHDR(mb, M_TRYWAIT, MT_DATA);
- if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
- MCLGET(mb, M_TRYWAIT);
- } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
- MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
- } else {
- MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
- }
- mb->m_len = 0;
- mreq = mb;
- bpos = mtod(mb, caddr_t);
-
- /*
- * First the RPC header.
- */
- nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
-
- /* Get a pretty random xid to start with */
- if (!nfs_xid)
- nfs_xid = random();
- /*
- * Skip zero xid if it should ever happen.
- */
- if (++nfs_xid == 0)
- nfs_xid++;
-
- *tl++ = *xidp = txdr_unsigned(nfs_xid);
- *tl++ = rpc_call;
- *tl++ = rpc_vers;
- if (nmflag & NFSMNT_NQNFS) {
- *tl++ = txdr_unsigned(NQNFS_PROG);
- *tl++ = txdr_unsigned(NQNFS_VER3);
- } else {
- *tl++ = txdr_unsigned(NFS_PROG);
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(NFS_VER3);
- else
- *tl++ = txdr_unsigned(NFS_VER2);
- }
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(procid);
- else
- *tl++ = txdr_unsigned(nfsv2_procid[procid]);
-
- /*
- * And then the authorization cred.
- */
- *tl++ = txdr_unsigned(auth_type);
- *tl = txdr_unsigned(authsiz);
- switch (auth_type) {
- case RPCAUTH_UNIX:
- nfsm_build(tl, u_int32_t *, auth_len);
- *tl++ = 0; /* stamp ?? */
- *tl++ = 0; /* NULL hostname */
- *tl++ = txdr_unsigned(cr->cr_uid);
- *tl++ = txdr_unsigned(cr->cr_groups[0]);
- grpsiz = (auth_len >> 2) - 5;
- *tl++ = txdr_unsigned(grpsiz);
- for (i = 1; i <= grpsiz; i++)
- *tl++ = txdr_unsigned(cr->cr_groups[i]);
- break;
- case RPCAUTH_KERB4:
- siz = auth_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(auth_str, bpos, i);
- mb->m_len += i;
- auth_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- break;
- };
-
- /*
- * And the verifier...
- */
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (verf_str) {
- *tl++ = txdr_unsigned(RPCAUTH_KERB4);
- *tl = txdr_unsigned(verf_len);
- siz = verf_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(verf_str, bpos, i);
- mb->m_len += i;
- verf_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- } else {
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
- }
- mb->m_next = mrest;
- mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
- mreq->m_pkthdr.rcvif = (struct ifnet *)0;
- *mbp = mb;
- return (mreq);
-}
-
-/*
- * copies mbuf chain to the uio scatter/gather list
- */
-int
-nfsm_mbuftouio(mrep, uiop, siz, dpos)
- struct mbuf **mrep;
- register struct uio *uiop;
- int siz;
- caddr_t *dpos;
-{
- register char *mbufcp, *uiocp;
- register int xfer, left, len;
- register struct mbuf *mp;
- long uiosiz, rem;
- int error = 0;
-
- mp = *mrep;
- mbufcp = *dpos;
- len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
- rem = nfsm_rndup(siz)-siz;
- while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EFBIG);
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- while (len == 0) {
- mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- mbufcp = mtod(mp, caddr_t);
- len = mp->m_len;
- }
- xfer = (left > len) ? len : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (mbufcp, uiocp, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(mbufcp, uiocp, xfer);
- else
- copyout(mbufcp, uiocp, xfer);
- left -= xfer;
- len -= xfer;
- mbufcp += xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- if (uiop->uio_iov->iov_len <= siz) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- }
- siz -= uiosiz;
- }
- *dpos = mbufcp;
- *mrep = mp;
- if (rem > 0) {
- if (len < rem)
- error = nfs_adv(mrep, dpos, rem, len);
- else
- *dpos += rem;
- }
- return (error);
-}
-
-/*
- * copies a uio scatter/gather list to an mbuf chain.
- * NOTE: can ony handle iovcnt == 1
- */
-int
-nfsm_uiotombuf(uiop, mq, siz, bpos)
- register struct uio *uiop;
- struct mbuf **mq;
- int siz;
- caddr_t *bpos;
-{
- register char *uiocp;
- register struct mbuf *mp, *mp2;
- register int xfer, left, mlen;
- int uiosiz, clflg, rem;
- char *cp;
-
-#ifdef DIAGNOSTIC
- if (uiop->uio_iovcnt != 1)
- panic("nfsm_uiotombuf: iovcnt != 1");
-#endif
-
- if (siz > MLEN) /* or should it >= MCLBYTES ?? */
- clflg = 1;
- else
- clflg = 0;
- rem = nfsm_rndup(siz)-siz;
- mp = mp2 = *mq;
- while (siz > 0) {
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- mlen = M_TRAILINGSPACE(mp);
- if (mlen == 0) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- if (clflg)
- MCLGET(mp, M_TRYWAIT);
- mp->m_len = 0;
- mp2->m_next = mp;
- mp2 = mp;
- mlen = M_TRAILINGSPACE(mp);
- }
- xfer = (left > mlen) ? mlen : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
- copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- mp->m_len += xfer;
- left -= xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- siz -= uiosiz;
- }
- if (rem > 0) {
- if (rem > M_TRAILINGSPACE(mp)) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- mp->m_len = 0;
- mp2->m_next = mp;
- }
- cp = mtod(mp, caddr_t)+mp->m_len;
- for (left = 0; left < rem; left++)
- *cp++ = '\0';
- mp->m_len += rem;
- *bpos = cp;
- } else
- *bpos = mtod(mp, caddr_t)+mp->m_len;
- *mq = mp;
- return (0);
-}
-
-/*
- * Help break down an mbuf chain by setting the first siz bytes contiguous
- * pointed to by returned val.
- * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
- * cases. (The macros use the vars. dpos and dpos2)
- */
-int
-nfsm_disct(mdp, dposp, siz, left, cp2)
- struct mbuf **mdp;
- caddr_t *dposp;
- int siz;
- int left;
- caddr_t *cp2;
-{
- register struct mbuf *mp, *mp2;
- register int siz2, xfer;
- register caddr_t ptr;
-
- mp = *mdp;
- while (left == 0) {
- *mdp = mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- left = mp->m_len;
- *dposp = mtod(mp, caddr_t);
- }
- if (left >= siz) {
- *cp2 = *dposp;
- *dposp += siz;
- } else if (mp->m_next == NULL) {
- return (EBADRPC);
- } else if (siz > MHLEN) {
- panic("nfs S too big");
- } else {
- MGET(mp2, M_TRYWAIT, MT_DATA);
- mp2->m_next = mp->m_next;
- mp->m_next = mp2;
- mp->m_len -= left;
- mp = mp2;
- *cp2 = ptr = mtod(mp, caddr_t);
- bcopy(*dposp, ptr, left); /* Copy what was left */
- siz2 = siz-left;
- ptr += left;
- mp2 = mp->m_next;
- /* Loop around copying up the siz2 bytes */
- while (siz2 > 0) {
- if (mp2 == NULL)
- return (EBADRPC);
- xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
- if (xfer > 0) {
- bcopy(mtod(mp2, caddr_t), ptr, xfer);
- NFSMADV(mp2, xfer);
- mp2->m_len -= xfer;
- ptr += xfer;
- siz2 -= xfer;
- }
- if (siz2 > 0)
- mp2 = mp2->m_next;
- }
- mp->m_len = siz;
- *mdp = mp2;
- *dposp = mtod(mp2, caddr_t);
- }
- return (0);
-}
-
-/*
- * Advance the position in the mbuf chain.
- */
-int
-nfs_adv(mdp, dposp, offs, left)
- struct mbuf **mdp;
- caddr_t *dposp;
- int offs;
- int left;
-{
- register struct mbuf *m;
- register int s;
-
- m = *mdp;
- s = left;
- while (s < offs) {
- offs -= s;
- m = m->m_next;
- if (m == NULL)
- return (EBADRPC);
- s = m->m_len;
- }
- *mdp = m;
- *dposp = mtod(m, caddr_t)+offs;
- return (0);
-}
-
-/*
- * Copy a string into mbufs for the hard cases...
- */
-int
-nfsm_strtmbuf(mb, bpos, cp, siz)
- struct mbuf **mb;
- char **bpos;
- const char *cp;
- long siz;
-{
- register struct mbuf *m1 = NULL, *m2;
- long left, xfer, len, tlen;
- u_int32_t *tl;
- int putsize;
-
- putsize = 1;
- m2 = *mb;
- left = M_TRAILINGSPACE(m2);
- if (left > 0) {
- tl = ((u_int32_t *)(*bpos));
- *tl++ = txdr_unsigned(siz);
- putsize = 0;
- left -= NFSX_UNSIGNED;
- m2->m_len += NFSX_UNSIGNED;
- if (left > 0) {
- bcopy(cp, (caddr_t) tl, left);
- siz -= left;
- cp += left;
- m2->m_len += left;
- left = 0;
- }
- }
- /* Loop around adding mbufs */
- while (siz > 0) {
- MGET(m1, M_TRYWAIT, MT_DATA);
- if (siz > MLEN)
- MCLGET(m1, M_TRYWAIT);
- m1->m_len = NFSMSIZ(m1);
- m2->m_next = m1;
- m2 = m1;
- tl = mtod(m1, u_int32_t *);
- tlen = 0;
- if (putsize) {
- *tl++ = txdr_unsigned(siz);
- m1->m_len -= NFSX_UNSIGNED;
- tlen = NFSX_UNSIGNED;
- putsize = 0;
- }
- if (siz < m1->m_len) {
- len = nfsm_rndup(siz);
- xfer = siz;
- if (xfer < len)
- *(tl+(xfer>>2)) = 0;
- } else {
- xfer = len = m1->m_len;
- }
- bcopy(cp, (caddr_t) tl, xfer);
- m1->m_len = len+tlen;
- siz -= xfer;
- cp += xfer;
- }
- *mb = m1;
- *bpos = mtod(m1, caddr_t)+m1->m_len;
- return (0);
-}
-
-/*
- * Called once to initialize data structures...
- */
-int
-nfs_init(vfsp)
- struct vfsconf *vfsp;
-{
- register int i;
-
- nfsmount_zone = zinit("NFSMOUNT", sizeof(struct nfsmount), 0, 0, 1);
-
- nfs_mount_type = vfsp->vfc_typenum;
- nfsrtt.pos = 0;
- rpc_vers = txdr_unsigned(RPC_VER2);
- rpc_call = txdr_unsigned(RPC_CALL);
- rpc_reply = txdr_unsigned(RPC_REPLY);
- 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);
- nfs_prog = txdr_unsigned(NFS_PROG);
- nqnfs_prog = txdr_unsigned(NQNFS_PROG);
- nfs_true = txdr_unsigned(TRUE);
- nfs_false = txdr_unsigned(FALSE);
- nfs_xdrneg1 = txdr_unsigned(-1);
- nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
- if (nfs_ticks < 1)
- nfs_ticks = 1;
- /* Ensure async daemons disabled */
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
- nfs_iodwant[i] = (struct proc *)0;
- nfs_iodmount[i] = (struct nfsmount *)0;
- }
- nfs_nhinit(); /* Init the nfsnode table */
-#ifndef NFS_NOSERVER
- nfsrv_init(0); /* Init server data structures */
- nfsrv_initcache(); /* Init the server request cache */
-#endif
-
- /*
- * Initialize the nqnfs server stuff.
- */
- if (nqnfsstarttime == 0) {
- nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
- + nqsrv_clockskew + nqsrv_writeslack;
- NQLOADNOVRAM(nqnfsstarttime);
- TAILQ_INIT(&nqtimerhead);
- nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
- }
-
- /*
- * Initialize reply list and start timer
- */
- TAILQ_INIT(&nfs_reqq);
-
- nfs_timer(0);
-
- /*
- * Set up lease_check and lease_updatetime so that other parts
- * of the system can call us, if we are loadable.
- */
-#ifndef NFS_NOSERVER
- nfs_prev_vop_lease_check = default_vnodeop_p[VOFFSET(vop_lease)];
- default_vnodeop_p[VOFFSET(vop_lease)] = (vop_t *)nqnfs_vop_lease_check;
-#endif
- nfs_prev_lease_updatetime = lease_updatetime;
- lease_updatetime = nfs_lease_updatetime;
- nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
- sysent[SYS_nfssvc].sy_narg = 2;
- nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call;
- sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc;
-
- nfs_pbuf_freecnt = nswbuf / 2 + 1;
-
- return (0);
-}
-
-int
-nfs_uninit(vfsp)
- struct vfsconf *vfsp;
-{
-
- untimeout(nfs_timer, (void *)NULL, nfs_timer_handle);
- nfs_mount_type = -1;
-#ifndef NFS_NOSERVER
- default_vnodeop_p[VOFFSET(vop_lease)] = nfs_prev_vop_lease_check;
-#endif
- lease_updatetime = nfs_prev_lease_updatetime;
- sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
- sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
- return (0);
-}
-
-/*
- * Attribute cache routines.
- * nfs_loadattrcache() - loads or updates the cache contents from attributes
- * that are on the mbuf list
- * nfs_getattrcache() - returns valid attributes if found in cache, returns
- * error otherwise
- */
-
-/*
- * Load the attribute cache (that lives in the nfsnode entry) with
- * the values on the mbuf list and
- * Iff vap not NULL
- * copy the attributes to *vaper
- */
-int
-nfs_loadattrcache(vpp, mdp, dposp, vaper, dontshrink)
- struct vnode **vpp;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vattr *vaper;
- int dontshrink;
-{
- register struct vnode *vp = *vpp;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
- register struct nfsnode *np;
- register int32_t t1;
- caddr_t cp2;
- int error = 0, rdev;
- struct mbuf *md;
- enum vtype vtyp;
- u_short vmode;
- struct timespec mtime;
- int v3 = NFS_ISV3(vp);
-
- md = *mdp;
- t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
- if ((error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)) != 0)
- return (error);
- fp = (struct nfs_fattr *)cp2;
- if (v3) {
- vtyp = nfsv3tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- rdev = makeudev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
- fxdr_unsigned(int, fp->fa3_rdev.specdata2));
- fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
- } else {
- vtyp = nfsv2tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- /*
- * XXX
- *
- * The duplicate information returned in fa_type and fa_mode
- * is an ambiguity in the NFS version 2 protocol.
- *
- * VREG should be taken literally as a regular file. If a
- * server intents to return some type information differently
- * in the upper bits of the mode field (e.g. for sockets, or
- * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
- * leave the examination of the mode bits even in the VREG
- * case to avoid breakage for bogus servers, but we make sure
- * that there are actually type bits set in the upper part of
- * fa_mode (and failing that, trust the va_type field).
- *
- * NFSv3 cleared the issue, and requires fa_mode to not
- * contain any type information (while also introduing sockets
- * and FIFOs for fa_type).
- */
- if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
- vtyp = IFTOVT(vmode);
- rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
- fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
-
- /*
- * Really ugly NFSv2 kludge.
- */
- if (vtyp == VCHR && rdev == 0xffffffff)
- vtyp = VFIFO;
- }
-
- /*
- * 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);
- if (vp->v_type != vtyp) {
- vp->v_type = vtyp;
- if (vp->v_type == VFIFO) {
- vp->v_op = fifo_nfsv2nodeop_p;
- }
- if (vp->v_type == VCHR || vp->v_type == VBLK) {
- vp->v_op = spec_nfsv2nodeop_p;
- vp = addaliasu(vp, rdev);
- np->n_vnode = vp;
- }
- np->n_mtime = mtime.tv_sec;
- }
- vap = &np->n_vattr;
- 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 (v3) {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_hyper(&fp->fa3_size);
- vap->va_blocksize = NFS_FABLKSIZE;
- vap->va_bytes = fxdr_hyper(&fp->fa3_used);
- vap->va_fileid = fxdr_unsigned(int32_t,
- fp->fa3_fileid.nfsuquad[1]);
- fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
- fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
- vap->va_flags = 0;
- vap->va_filerev = 0;
- } else {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
- vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
- vap->va_bytes = (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks)
- * NFS_FABLKSIZE;
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
- fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
- vap->va_flags = 0;
- vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
- fp->fa2_ctime.nfsv2_sec);
- vap->va_ctime.tv_nsec = 0;
- vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
- vap->va_filerev = 0;
- }
- np->n_attrstamp = time_second;
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (dontshrink && vap->va_size < np->n_size) {
- /*
- * We've been told not to shrink the file;
- * zero np->n_attrstamp to indicate that
- * the attributes are stale.
- */
- vap->va_size = np->n_size;
- np->n_attrstamp = 0;
- } else 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;
- }
- }
- 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;
- }
- }
- return (0);
-}
-
-#ifdef NFS_ACDEBUG
-#include <sys/sysctl.h>
-SYSCTL_DECL(_vfs_nfs);
-static int nfs_acdebug;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, acdebug, CTLFLAG_RW, &nfs_acdebug, 0, "");
-#endif
-
-/*
- * Check the time stamp
- * If the cache is valid, copy contents to *vap and return 0
- * otherwise return an error
- */
-int
-nfs_getattrcache(vp, vaper)
- register struct vnode *vp;
- struct vattr *vaper;
-{
- register struct nfsnode *np;
- register struct vattr *vap;
- struct nfsmount *nmp;
- int timeo;
-
- np = VTONFS(vp);
- vap = &np->n_vattr;
- nmp = VFSTONFS(vp->v_mount);
- /* XXX n_mtime doesn't seem to be updated on a miss-and-reload */
- timeo = (time_second - np->n_mtime) / 10;
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug>1)
- printf("nfs_getattrcache: initial timeo = %d\n", timeo);
-#endif
-
- if (vap->va_type == VDIR) {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acdirmin)
- timeo = nmp->nm_acdirmin;
- else if (timeo > nmp->nm_acdirmax)
- timeo = nmp->nm_acdirmax;
- } else {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acregmin)
- timeo = nmp->nm_acregmin;
- else if (timeo > nmp->nm_acregmax)
- timeo = nmp->nm_acregmax;
- }
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug > 2)
- printf("acregmin %d; acregmax %d; acdirmin %d; acdirmax %d\n",
- nmp->nm_acregmin, nmp->nm_acregmax,
- nmp->nm_acdirmin, nmp->nm_acdirmax);
-
- if (nfs_acdebug)
- printf("nfs_getattrcache: age = %d; final timeo = %d\n",
- (time_second - np->n_attrstamp), timeo);
-#endif
-
- if ((time_second - np->n_attrstamp) >= timeo) {
- nfsstats.attrcache_misses++;
- return (ENOENT);
- }
- nfsstats.attrcache_hits++;
- 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;
- }
- }
- bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
- 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;
- }
- return (0);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Set up nameidata for a lookup() call and do it.
- *
- * If pubflag is set, this call is done for a lookup operation on the
- * public filehandle. In that case we allow crossing mountpoints and
- * absolute pathnames. However, the caller is expected to check that
- * the lookup result is within the public fs, and deny access if
- * it is not.
- *
- * nfs_namei() clears out garbage fields that namei() might leave garbage.
- * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
- * error occurs but the parent was not requested.
- *
- * dirp may be set whether an error is returned or not, and must be
- * released by the caller.
- */
-int
-nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
- register struct nameidata *ndp;
- fhandle_t *fhp;
- int len;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vnode **retdirp;
- struct thread *td;
- int kerbflag, pubflag;
-{
- register int i, rem;
- register struct mbuf *md;
- register char *fromcp, *tocp, *cp;
- struct iovec aiov;
- struct uio auio;
- struct vnode *dp;
- int error, rdonly, linklen;
- struct componentname *cnp = &ndp->ni_cnd;
-
- *retdirp = (struct vnode *)0;
- cnp->cn_pnbuf = zalloc(namei_zone);
-
- /*
- * Copy the name from the mbuf list to ndp->ni_pnbuf
- * and set the various ndp fields appropriately.
- */
- fromcp = *dposp;
- tocp = cnp->cn_pnbuf;
- md = *mdp;
- rem = mtod(md, caddr_t) + md->m_len - fromcp;
- for (i = 0; i < len; i++) {
- while (rem == 0) {
- md = md->m_next;
- if (md == NULL) {
- error = EBADRPC;
- goto out;
- }
- fromcp = mtod(md, caddr_t);
- rem = md->m_len;
- }
- if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
- error = EACCES;
- goto out;
- }
- *tocp++ = *fromcp++;
- rem--;
- }
- *tocp = '\0';
- *mdp = md;
- *dposp = fromcp;
- len = nfsm_rndup(len)-len;
- if (len > 0) {
- if (rem >= len)
- *dposp += len;
- else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
- goto out;
- }
-
- /*
- * Extract and set starting directory.
- */
- error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly, kerbflag, pubflag);
- if (error)
- goto out;
- if (dp->v_type != VDIR) {
- vrele(dp);
- error = ENOTDIR;
- goto out;
- }
-
- if (rdonly)
- cnp->cn_flags |= RDONLY;
-
- /*
- * Set return directory. Reference to dp is implicitly transfered
- * to the returned pointer
- */
- *retdirp = dp;
-
- if (pubflag) {
- /*
- * Oh joy. For WebNFS, handle those pesky '%' escapes,
- * and the 'native path' indicator.
- */
- cp = zalloc(namei_zone);
- fromcp = cnp->cn_pnbuf;
- tocp = cp;
- if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
- switch ((unsigned char)*fromcp) {
- case WEBNFS_NATIVE_CHAR:
- /*
- * 'Native' path for us is the same
- * as a path according to the NFS spec,
- * just skip the escape char.
- */
- fromcp++;
- break;
- /*
- * More may be added in the future, range 0x80-0xff
- */
- default:
- error = EIO;
- zfree(namei_zone, cp);
- goto out;
- }
- }
- /*
- * Translate the '%' escapes, URL-style.
- */
- while (*fromcp != '\0') {
- if (*fromcp == WEBNFS_ESC_CHAR) {
- if (fromcp[1] != '\0' && fromcp[2] != '\0') {
- fromcp++;
- *tocp++ = HEXSTRTOI(fromcp);
- fromcp += 2;
- continue;
- } else {
- error = ENOENT;
- zfree(namei_zone, cp);
- goto out;
- }
- } else
- *tocp++ = *fromcp++;
- }
- *tocp = '\0';
- zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- }
-
- ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
- ndp->ni_segflg = UIO_SYSSPACE;
-
- if (pubflag) {
- ndp->ni_rootdir = rootvnode;
- ndp->ni_loopcnt = 0;
- if (cnp->cn_pnbuf[0] == '/')
- dp = rootvnode;
- } else {
- cnp->cn_flags |= NOCROSSMOUNT;
- }
-
- /*
- * Initialize for scan, set ni_startdir and bump ref on dp again
- * becuase lookup() will dereference ni_startdir.
- */
-
- cnp->cn_thread = td;
- VREF(dp);
- ndp->ni_startdir = dp;
-
- for (;;) {
- cnp->cn_nameptr = cnp->cn_pnbuf;
- /*
- * Call lookup() to do the real work. If an error occurs,
- * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
- * we do not have to dereference anything before returning.
- * In either case ni_startdir will be dereferenced and NULLed
- * out.
- */
- error = lookup(ndp);
- if (error)
- break;
-
- /*
- * Check for encountering a symbolic link. Trivial
- * termination occurs if no symlink encountered.
- * Note: zfree is safe because error is 0, so we will
- * not zfree it again when we break.
- */
- if ((cnp->cn_flags & ISSYMLINK) == 0) {
- nfsrv_object_create(ndp->ni_vp);
- if (cnp->cn_flags & (SAVENAME | SAVESTART))
- cnp->cn_flags |= HASBUF;
- else
- zfree(namei_zone, cnp->cn_pnbuf);
- break;
- }
-
- /*
- * Validate symlink
- */
- if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- VOP_UNLOCK(ndp->ni_dvp, 0, td);
- if (!pubflag) {
- error = EINVAL;
- goto badlink2;
- }
-
- if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
- error = ELOOP;
- goto badlink2;
- }
- if (ndp->ni_pathlen > 1)
- cp = zalloc(namei_zone);
- else
- cp = cnp->cn_pnbuf;
- aiov.iov_base = cp;
- aiov.iov_len = MAXPATHLEN;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_td = (struct thread *)0;
- auio.uio_resid = MAXPATHLEN;
- error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
- if (error) {
- badlink1:
- if (ndp->ni_pathlen > 1)
- zfree(namei_zone, cp);
- badlink2:
- vrele(ndp->ni_dvp);
- vput(ndp->ni_vp);
- break;
- }
- linklen = MAXPATHLEN - auio.uio_resid;
- if (linklen == 0) {
- error = ENOENT;
- goto badlink1;
- }
- if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
- error = ENAMETOOLONG;
- goto badlink1;
- }
-
- /*
- * Adjust or replace path
- */
- if (ndp->ni_pathlen > 1) {
- bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
- zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- } else
- cnp->cn_pnbuf[linklen] = '\0';
- ndp->ni_pathlen += linklen;
-
- /*
- * Cleanup refs for next loop and check if root directory
- * should replace current directory. Normally ni_dvp
- * becomes the new base directory and is cleaned up when
- * we loop. Explicitly null pointers after invalidation
- * to clarify operation.
- */
- vput(ndp->ni_vp);
- ndp->ni_vp = NULL;
-
- if (cnp->cn_pnbuf[0] == '/') {
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = ndp->ni_rootdir;
- VREF(ndp->ni_dvp);
- }
- ndp->ni_startdir = ndp->ni_dvp;
- ndp->ni_dvp = NULL;
- }
-
- /*
- * nfs_namei() guarentees that fields will not contain garbage
- * whether an error occurs or not. This allows the caller to track
- * cleanup state trivially.
- */
-out:
- if (error) {
- zfree(namei_zone, cnp->cn_pnbuf);
- ndp->ni_vp = NULL;
- ndp->ni_dvp = NULL;
- ndp->ni_startdir = NULL;
- cnp->cn_flags &= ~HASBUF;
- } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
- ndp->ni_dvp = NULL;
- }
- return (error);
-}
-
-/*
- * A fiddled version of m_adj() that ensures null fill to a long
- * boundary and only trims off the back end
- */
-void
-nfsm_adj(mp, len, nul)
- struct mbuf *mp;
- register int len;
- int nul;
-{
- register struct mbuf *m;
- register int count, i;
- register char *cp;
-
- /*
- * Trim from tail. Scan the mbuf chain,
- * calculating its length and finding the last mbuf.
- * If the adjustment only affects this mbuf, then just
- * adjust and return. Otherwise, rescan and truncate
- * after the remaining size.
- */
- count = 0;
- m = mp;
- for (;;) {
- count += m->m_len;
- if (m->m_next == (struct mbuf *)0)
- break;
- m = m->m_next;
- }
- if (m->m_len > len) {
- m->m_len -= len;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- return;
- }
- count -= len;
- if (count < 0)
- count = 0;
- /*
- * Correct length for chain is "count".
- * Find the mbuf with last data, adjust its length,
- * and toss data from remaining mbufs on chain.
- */
- for (m = mp; m; m = m->m_next) {
- if (m->m_len >= count) {
- m->m_len = count;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- break;
- }
- count -= m->m_len;
- }
- for (m = m->m_next;m;m = m->m_next)
- m->m_len = 0;
-}
-
-/*
- * Make these functions instead of macros, so that the kernel text size
- * doesn't get too big...
- */
-void
-nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int before_ret;
- register struct vattr *before_vap;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
-{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
-
- if (before_ret) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- txdr_hyper(before_vap->va_size, tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_mtime), tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_ctime), tl);
- }
- *bposp = bpos;
- *mbp = mb;
- nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
-}
-
-void
-nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
-{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
- register struct nfs_fattr *fp;
-
- if (after_ret) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
- *tl++ = nfs_true;
- fp = (struct nfs_fattr *)tl;
- nfsm_srvfattr(nfsd, after_vap, fp);
- }
- *mbp = mb;
- *bposp = bpos;
-}
-
-void
-nfsm_srvfattr(nfsd, vap, fp)
- register struct nfsrv_descript *nfsd;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
-{
-
- fp->fa_nlink = txdr_unsigned(vap->va_nlink);
- fp->fa_uid = txdr_unsigned(vap->va_uid);
- fp->fa_gid = txdr_unsigned(vap->va_gid);
- if (nfsd->nd_flag & ND_NFSV3) {
- fp->fa_type = vtonfsv3_type(vap->va_type);
- fp->fa_mode = vtonfsv3_mode(vap->va_mode);
- txdr_hyper(vap->va_size, &fp->fa3_size);
- txdr_hyper(vap->va_bytes, &fp->fa3_used);
- fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev));
- fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev));
- fp->fa3_fsid.nfsuquad[0] = 0;
- fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
- fp->fa3_fileid.nfsuquad[0] = 0;
- fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
- txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
- txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
- txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
- } else {
- fp->fa_type = vtonfsv2_type(vap->va_type);
- fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- fp->fa2_size = txdr_unsigned(vap->va_size);
- fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
- if (vap->va_type == VFIFO)
- fp->fa2_rdev = 0xffffffff;
- else
- fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
- fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
- fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
- fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
- txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
- txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
- txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
- }
-}
-
-/*
- * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
- * - look up fsid in mount list (if not found ret error)
- * - get vp and export rights by calling VFS_FHTOVP()
- * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
- * - if not lockflag unlock it with VOP_UNLOCK()
- */
-int
-nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
- fhandle_t *fhp;
- int lockflag;
- struct vnode **vpp;
- struct ucred *cred;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- int *rdonlyp;
- int kerbflag;
- int pubflag;
-{
- struct thread *td = curthread; /* XXX */
- register struct mount *mp;
- register int i;
- struct ucred *credanon;
- int error, exflags;
-#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
- struct sockaddr_int *saddr;
-#endif
-
- *vpp = (struct vnode *)0;
-
- if (nfs_ispublicfh(fhp)) {
- if (!pubflag || !nfs_pub.np_valid)
- return (ESTALE);
- fhp = &nfs_pub.np_handle;
- }
-
- mp = vfs_getvfs(&fhp->fh_fsid);
- if (!mp)
- return (ESTALE);
- error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
- if (error)
- return (error);
- error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
- if (error)
- return (error);
-#ifdef MNT_EXNORESPORT
- if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
- saddr = (struct sockaddr_in *)nam;
- if (saddr->sin_family == AF_INET &&
- ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- }
-#endif
- /*
- * Check/setup credentials.
- */
- if (exflags & MNT_EXKERB) {
- if (!kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- } else if (kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
- cred->cr_uid = credanon->cr_uid;
- for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
- cred->cr_groups[i] = credanon->cr_groups[i];
- cred->cr_ngroups = i;
- }
- if (exflags & MNT_EXRDONLY)
- *rdonlyp = 1;
- else
- *rdonlyp = 0;
-
- nfsrv_object_create(*vpp);
-
- if (!lockflag)
- VOP_UNLOCK(*vpp, 0, td);
- return (0);
-}
-
-
-/*
- * WebNFS: check if a filehandle is a public filehandle. For v3, this
- * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
- * transformed this to all zeroes in both cases, so check for it.
- */
-int
-nfs_ispublicfh(fhp)
- fhandle_t *fhp;
-{
- char *cp = (char *)fhp;
- int i;
-
- for (i = 0; i < NFSX_V3FH; i++)
- if (*cp++ != 0)
- return (FALSE);
- return (TRUE);
-}
-
-#endif /* NFS_NOSERVER */
-/*
- * This function compares two net addresses by family and returns TRUE
- * if they are the same host.
- * If there is any doubt, return FALSE.
- * The AF_INET family is handled as a special case so that address mbufs
- * don't need to be saved to store "struct in_addr", which is only 4 bytes.
- */
-int
-netaddr_match(family, haddr, nam)
- int family;
- union nethostaddr *haddr;
- struct sockaddr *nam;
-{
- register struct sockaddr_in *inetaddr;
-
- switch (family) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *)nam;
- if (inetaddr->sin_family == AF_INET &&
- inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
- return (1);
- break;
- default:
- break;
- };
- return (0);
-}
-
-static nfsuint64 nfs_nullcookie = { { 0, 0 } };
-/*
- * This function finds the directory cookie that corresponds to the
- * logical byte offset given.
- */
-nfsuint64 *
-nfs_getcookie(np, off, add)
- register struct nfsnode *np;
- off_t off;
- int add;
-{
- register struct nfsdmap *dp, *dp2;
- register 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 = np->n_cookies.lh_first;
- if (!dp) {
- if (add) {
- MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp->ndm_eocookie = 0;
- LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
- } else
- return ((nfsuint64 *)0);
- }
- while (pos >= NFSNUMCOOKIES) {
- pos -= NFSNUMCOOKIES;
- if (dp->ndm_list.le_next) {
- if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
- pos >= dp->ndm_eocookie)
- return ((nfsuint64 *)0);
- dp = dp->ndm_list.le_next;
- } else if (add) {
- MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp2->ndm_eocookie = 0;
- LIST_INSERT_AFTER(dp, dp2, ndm_list);
- dp = dp2;
- } else
- return ((nfsuint64 *)0);
- }
- if (pos >= dp->ndm_eocookie) {
- if (add)
- dp->ndm_eocookie = pos + 1;
- else
- return ((nfsuint64 *)0);
- }
- return (&dp->ndm_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
-nfs_invaldir(vp)
- register struct vnode *vp;
-{
- register struct nfsnode *np = VTONFS(vp);
-
-#ifdef DIAGNOSTIC
- if (vp->v_type != VDIR)
- panic("nfs: invaldir not dir");
-#endif
- np->n_direofoffset = 0;
- np->n_cookieverf.nfsuquad[0] = 0;
- np->n_cookieverf.nfsuquad[1] = 0;
- if (np->n_cookies.lh_first)
- np->n_cookies.lh_first->ndm_eocookie = 0;
-}
-
-/*
- * The write verifier has changed (probably due to a server reboot), so all
- * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
- * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
- * and B_CLUSTEROK flags. Once done the new write verifier can be set for the
- * mount point.
- *
- * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data
- * writes are not clusterable.
- */
-void
-nfs_clearcommit(mp)
- struct mount *mp;
-{
- register struct vnode *vp, *nvp;
- register struct buf *bp, *nbp;
- int s;
-
- GIANT_REQUIRED;
-
- s = splbio();
- mtx_lock(&mntvnode_mtx);
-loop:
- for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
- if (vp->v_mount != mp) /* Paranoia */
- goto loop;
- nvp = LIST_NEXT(vp, v_mntvnodes);
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if (BUF_REFCNT(bp) == 0 &&
- (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
- == (B_DELWRI | B_NEEDCOMMIT))
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- }
- }
- mtx_unlock(&mntvnode_mtx);
- splx(s);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Map errnos to NFS error numbers. For Version 3 also filter out error
- * numbers not specified for the associated procedure.
- */
-int
-nfsrv_errmap(nd, err)
- struct nfsrv_descript *nd;
- register int err;
-{
- register short *defaulterrp, *errp;
-
- if (nd->nd_flag & ND_NFSV3) {
- if (nd->nd_procnum <= NFSPROC_COMMIT) {
- errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
- while (*++errp) {
- if (*errp == err)
- return (err);
- else if (*errp > err)
- break;
- }
- return ((int)*defaulterrp);
- } else
- return (err & 0xffff);
- }
- if (err <= ELAST)
- return ((int)nfsrv_v2errmap[err - 1]);
- return (NFSERR_IO);
-}
-
-int
-nfsrv_object_create(vp)
- struct vnode *vp;
-{
-
- if (vp == NULL || vp->v_type != VREG)
- return (1);
- return (vfs_object_create(vp, curthread,
- curthread ? curthread->td_proc->p_ucred : NULL));
-}
-
-/*
- * Sort the group list in increasing numerical order.
- * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
- * that used to be here.)
- */
-void
-nfsrvw_sort(list, num)
- register gid_t *list;
- register int num;
-{
- register int i, j;
- gid_t v;
-
- /* Insertion sort. */
- for (i = 1; i < num; i++) {
- v = list[i];
- /* find correct slot for value v, moving others up */
- for (j = i; --j >= 0 && v < list[j];)
- list[j + 1] = list[j];
- list[j + 1] = v;
- }
-}
-
-/*
- * copy credentials making sure that the result can be compared with bcmp().
- */
-void
-nfsrv_setcred(incred, outcred)
- register struct ucred *incred, *outcred;
-{
- register int i;
-
- bzero((caddr_t)outcred, sizeof (struct ucred));
- outcred->cr_ref = 1;
- outcred->cr_uid = incred->cr_uid;
- outcred->cr_ngroups = incred->cr_ngroups;
- for (i = 0; i < incred->cr_ngroups; i++)
- outcred->cr_groups[i] = incred->cr_groups[i];
- nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
-}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c
deleted file mode 100644
index 657f299..0000000
--- a/sys/nfs/nfs_syscalls.c
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- * 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.
- * 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_syscalls.c 8.5 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/namei.h>
-#include <sys/fcntl.h>
-#include <sys/lockf.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsrvcache.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nfs_lock.h>
-
-static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure");
-
-/* Global defs. */
-extern int32_t (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp));
-extern int nfs_numasync;
-extern time_t nqnfsstarttime;
-extern int nqsrv_writeslack;
-extern int nfsrtton;
-extern struct nfsstats nfsstats;
-extern int nfsrvw_procrastinate;
-extern int nfsrvw_procrastinate_v3;
-static int nuidhash_max = NFS_MAXUIDHASH;
-
-#ifndef NFS_NOSERVER
-static void nfsrv_zapsock __P((struct nfssvc_sock *slp));
-#endif
-static int nfssvc_iod __P((struct thread *));
-
-#define TRUE 1
-#define FALSE 0
-
-static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
-
-SYSCTL_DECL(_vfs_nfs);
-
-#ifndef NFS_NOSERVER
-int nfsd_waiting = 0;
-static struct nfsdrt nfsdrt;
-static int nfs_numnfsd = 0;
-static int notstarted = 1;
-static int modify_flag = 0;
-static void nfsd_rt __P((int sotype, struct nfsrv_descript *nd,
- int cacherep));
-static int nfssvc_addsock __P((struct file *, struct sockaddr *,
- struct thread *));
-static int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,
- struct thread *));
-
-static int nfs_privport = 0;
-SYSCTL_INT(_vfs_nfs, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW, &nfs_privport, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay, CTLFLAG_RW, &nfsrvw_procrastinate, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay_v3, CTLFLAG_RW, &nfsrvw_procrastinate_v3, 0, "");
-
-/*
- * NFS server system calls
- */
-
-#endif /* NFS_NOSERVER */
-/*
- * Nfs server psuedo system call for the nfsd's
- * Based on the flag value it either:
- * - adds a socket to the selection list
- * - remains in the kernel as an nfsd
- * - remains in the kernel as an nfsiod
- */
-#ifndef _SYS_SYSPROTO_H_
-struct nfssvc_args {
- int flag;
- caddr_t argp;
-};
-#endif
-/*
- * MPSAFE
- */
-int
-nfssvc(td, uap)
- struct thread *td;
- register struct nfssvc_args *uap;
-{
-#ifndef NFS_NOSERVER
- struct nameidata nd;
- struct file *fp;
- struct sockaddr *nam;
- struct nfsd_args nfsdarg;
- struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;
- struct nfsd_cargs ncd;
- struct nfsd *nfsd;
- struct nfssvc_sock *slp;
- struct nfsuid *nuidp;
- struct nfsmount *nmp;
-#endif /* NFS_NOSERVER */
- int error;
-
- mtx_lock(&Giant);
-
- if ((uap->flag & NFSSVC_LOCKDANS) != 0) {
- struct lockd_ans la;
-
- error = copyin(uap->argp, &la, sizeof(la));
- if (error == 0)
- error = nfslockdans(td->td_proc, &la);
- goto done2;
- }
- /*
- * Must be super user
- */
- error = suser_td(td);
- if (error)
- goto done2;
- while (nfssvc_sockhead_flag & SLP_INIT) {
- nfssvc_sockhead_flag |= SLP_WANTINIT;
- (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0);
- }
- if (uap->flag & NFSSVC_BIOD)
- error = nfssvc_iod(td);
-#ifdef NFS_NOSERVER
- else
- error = ENXIO;
-#else /* !NFS_NOSERVER */
- else if (uap->flag & NFSSVC_MNTD) {
- error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd));
- if (error)
- goto done2;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
- ncd.ncd_dirp, td);
- error = namei(&nd);
- if (error)
- goto done2;
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if ((nd.ni_vp->v_flag & VROOT) == 0)
- error = EINVAL;
- nmp = VFSTONFS(nd.ni_vp->v_mount);
- vput(nd.ni_vp);
- if (error)
- goto done2;
- if ((nmp->nm_state & NFSSTA_MNTD) &&
- (uap->flag & NFSSVC_GOTAUTH) == 0) {
- error = 0;
- goto done2;
- }
- nmp->nm_state |= NFSSTA_MNTD;
- error = nqnfs_clientd(nmp, td->td_proc->p_ucred, &ncd, uap->flag,
- uap->argp, td);
- } else if (uap->flag & NFSSVC_ADDSOCK) {
- error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg));
- if (error)
- goto done2;
- error = holdsock(td->td_proc->p_fd, nfsdarg.sock, &fp);
- if (error)
- goto done2;
- /*
- * Get the client address for connected sockets.
- */
- if (nfsdarg.name == NULL || nfsdarg.namelen == 0)
- nam = (struct sockaddr *)0;
- else {
- error = getsockaddr(&nam, nfsdarg.name,
- nfsdarg.namelen);
- if (error) {
- fdrop(fp, td);
- goto done2;
- }
- }
- error = nfssvc_addsock(fp, nam, td);
- fdrop(fp, td);
- } else {
- error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd));
- if (error)
- goto done2;
- if ((uap->flag & NFSSVC_AUTHIN) &&
- ((nfsd = nsd->nsd_nfsd)) != NULL &&
- (nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
- slp = nfsd->nfsd_slp;
-
- /*
- * First check to see if another nfsd has already
- * added this credential.
- */
- for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
- (!nfsd->nfsd_nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
- nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
- } else {
- /*
- * Nope, so we will.
- */
- if (slp->ns_numuids < nuidhash_max) {
- slp->ns_numuids++;
- nuidp = (struct nfsuid *)
- malloc(sizeof (struct nfsuid), M_NFSUID,
- M_WAITOK);
- } else
- nuidp = (struct nfsuid *)0;
- if ((slp->ns_flag & SLP_VALID) == 0) {
- if (nuidp)
- free((caddr_t)nuidp, M_NFSUID);
- } else {
- if (nuidp == (struct nfsuid *)0) {
- nuidp = slp->ns_uidlruhead.tqh_first;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
- nu_lru);
- if (nuidp->nu_flag & NU_NAM)
- FREE(nuidp->nu_nam, M_SONAME);
- }
- nuidp->nu_flag = 0;
- bzero(&nuidp->nu_cr, sizeof(nuidp->nu_cr));
- nuidp->nu_cr.cr_uid = nsd->nsd_cr.cr_uid;
- nuidp->nu_cr.cr_ngroups =
- nsd->nsd_cr.cr_ngroups;
- bcopy(nsd->nsd_cr.cr_groups,
- nuidp->nu_cr.cr_groups,
- sizeof(nuidp->nu_cr.cr_groups));
- if (nuidp->nu_cr.cr_ngroups > NGROUPS)
- nuidp->nu_cr.cr_ngroups = NGROUPS;
- nuidp->nu_cr.cr_ref = 1;
- nuidp->nu_timestamp = nsd->nsd_timestamp;
- nuidp->nu_expire = time_second + nsd->nsd_ttl;
- /*
- * and save the session key in nu_key.
- */
- bcopy(nsd->nsd_key, nuidp->nu_key,
- sizeof (nsd->nsd_key));
- if (nfsd->nfsd_nd->nd_nam2) {
- struct sockaddr_in *saddr;
-
- saddr = (struct sockaddr_in *)
- nfsd->nfsd_nd->nd_nam2;
- switch (saddr->sin_family) {
- case AF_INET:
- nuidp->nu_flag |= NU_INETADDR;
- nuidp->nu_inetaddr =
- saddr->sin_addr.s_addr;
- break;
- case AF_ISO:
- default:
- nuidp->nu_flag |= NU_NAM;
- nuidp->nu_nam =
- dup_sockaddr(nfsd->nfsd_nd->
- nd_nam2, 1);
- break;
- };
- }
- TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
- nu_lru);
- LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
- nuidp, nu_hash);
- nfsrv_setcred(&nuidp->nu_cr,
- &nfsd->nfsd_nd->nd_cr);
- nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
- }
- }
- }
- if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
- nfsd->nfsd_flag |= NFSD_AUTHFAIL;
- error = nfssvc_nfsd(nsd, uap->argp, td);
- }
-#endif /* NFS_NOSERVER */
- if (error == EINTR || error == ERESTART)
- error = 0;
-done2:
- mtx_unlock(&Giant);
- return (error);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Adds a socket to the list for servicing by nfsds.
- */
-static int
-nfssvc_addsock(fp, mynam, td)
- struct file *fp;
- struct sockaddr *mynam;
- struct thread *td;
-{
- register int siz;
- register struct nfssvc_sock *slp;
- register struct socket *so;
- int error, s;
-
- so = (struct socket *)fp->f_data;
-#if 0
- tslp = (struct nfssvc_sock *)0;
- /*
- * Add it to the list, as required.
- */
- if (so->so_proto->pr_protocol == IPPROTO_UDP) {
- tslp = nfs_udpsock;
- if (tslp->ns_flag & SLP_VALID) {
- if (mynam != NULL)
- FREE(mynam, M_SONAME);
- return (EPERM);
- }
- }
-#endif
- if (so->so_type == SOCK_STREAM)
- siz = NFS_MAXPACKET + sizeof (u_long);
- else
- siz = NFS_MAXPACKET;
- error = soreserve(so, siz, siz);
- if (error) {
- if (mynam != NULL)
- FREE(mynam, M_SONAME);
- return (error);
- }
-
- /*
- * Set protocol specific options { for now TCP only } and
- * reserve some space. For datagram sockets, this can get called
- * repeatedly for the same socket, but that isn't harmful.
- */
- if (so->so_type == SOCK_STREAM) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_KEEPALIVE;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- if (so->so_proto->pr_domain->dom_family == AF_INET &&
- so->so_proto->pr_protocol == IPPROTO_TCP) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = IPPROTO_TCP;
- sopt.sopt_name = TCP_NODELAY;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- so->so_rcv.sb_flags &= ~SB_NOINTR;
- so->so_rcv.sb_timeo = 0;
- so->so_snd.sb_flags &= ~SB_NOINTR;
- so->so_snd.sb_timeo = 0;
-
- slp = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC,
- M_WAITOK | M_ZERO);
- STAILQ_INIT(&slp->ns_rec);
- TAILQ_INIT(&slp->ns_uidlruhead);
- TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
-
- slp->ns_so = so;
- slp->ns_nam = mynam;
- fp->f_count++;
- slp->ns_fp = fp;
- s = splnet();
- so->so_upcallarg = (caddr_t)slp;
- so->so_upcall = nfsrv_rcv;
- so->so_rcv.sb_flags |= SB_UPCALL;
- slp->ns_flag = (SLP_VALID | SLP_NEEDQ);
- nfsrv_wakenfsd(slp);
- splx(s);
- return (0);
-}
-
-/*
- * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
- * until it is killed by a signal.
- */
-static int
-nfssvc_nfsd(nsd, argp, td)
- struct nfsd_srvargs *nsd;
- caddr_t argp;
- struct thread *td;
-{
- register int siz;
- register struct nfssvc_sock *slp;
- struct nfsd *nfsd = nsd->nsd_nfsd;
- struct nfsrv_descript *nd = NULL;
- struct mbuf *m, *mreq;
- int error = 0, cacherep, s, sotype, writes_todo;
- int procrastinate;
- u_quad_t cur_usec;
-
-#ifndef nolint
- cacherep = RC_DOIT;
- writes_todo = 0;
-#endif
- if (nfsd == (struct nfsd *)0) {
- nsd->nsd_nfsd = nfsd = (struct nfsd *)
- malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK | M_ZERO);
- s = splnet();
- nfsd->nfsd_td = td;
- TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
- nfs_numnfsd++;
- } else
- s = splnet();
-
- /*
- * Loop getting rpc requests until SIGKILL.
- */
- for (;;) {
- if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
- while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
- (nfsd_head_flag & NFSD_CHECKSLP) == 0) {
- nfsd->nfsd_flag |= NFSD_WAITING;
- nfsd_waiting++;
- error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
- "nfsd", 0);
- nfsd_waiting--;
- if (error)
- goto done;
- }
- if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
- (nfsd_head_flag & NFSD_CHECKSLP) != 0) {
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
- if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
- == (SLP_VALID | SLP_DOREC)) {
- slp->ns_flag &= ~SLP_DOREC;
- slp->ns_sref++;
- nfsd->nfsd_slp = slp;
- break;
- }
- }
- if (slp == 0)
- nfsd_head_flag &= ~NFSD_CHECKSLP;
- }
- if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
- continue;
- if (slp->ns_flag & SLP_VALID) {
- if (slp->ns_flag & SLP_DISCONN)
- nfsrv_zapsock(slp);
- else if (slp->ns_flag & SLP_NEEDQ) {
- slp->ns_flag &= ~SLP_NEEDQ;
- (void) nfs_slplock(slp, 1);
- nfsrv_rcv(slp->ns_so, (caddr_t)slp,
- M_TRYWAIT);
- nfs_slpunlock(slp);
- }
- error = nfsrv_dorec(slp, nfsd, &nd);
- cur_usec = nfs_curusec();
- if (error && slp->ns_tq.lh_first &&
- slp->ns_tq.lh_first->nd_time <= cur_usec) {
- error = 0;
- cacherep = RC_DOIT;
- writes_todo = 1;
- } else
- writes_todo = 0;
- nfsd->nfsd_flag |= NFSD_REQINPROG;
- }
- } else {
- error = 0;
- slp = nfsd->nfsd_slp;
- }
- if (error || (slp->ns_flag & SLP_VALID) == 0) {
- if (nd) {
- free((caddr_t)nd, M_NFSRVDESC);
- nd = NULL;
- }
- nfsd->nfsd_slp = (struct nfssvc_sock *)0;
- nfsd->nfsd_flag &= ~NFSD_REQINPROG;
- nfsrv_slpderef(slp);
- continue;
- }
- splx(s);
- sotype = slp->ns_so->so_type;
- if (nd) {
- getmicrotime(&nd->nd_starttime);
- if (nd->nd_nam2)
- nd->nd_nam = nd->nd_nam2;
- else
- nd->nd_nam = slp->ns_nam;
-
- /*
- * Check to see if authorization is needed.
- */
- if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
- nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
- nsd->nsd_haddr =
- ((struct sockaddr_in *)
- nd->nd_nam)->sin_addr.s_addr;
- nsd->nsd_authlen = nfsd->nfsd_authlen;
- nsd->nsd_verflen = nfsd->nfsd_verflen;
- if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
- nfsd->nfsd_authlen) &&
- !copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
- nfsd->nfsd_verflen) &&
- !copyout((caddr_t)nsd, argp, sizeof (*nsd)))
- return (ENEEDAUTH);
- cacherep = RC_DROPIT;
- } else
- cacherep = nfsrv_getcache(nd, slp, &mreq);
-
- /*
- * Check for just starting up for NQNFS and send
- * fake "try again later" replies to the NQNFS clients.
- */
- if (notstarted && nqnfsstarttime <= time_second) {
- if (modify_flag) {
- nqnfsstarttime = time_second + nqsrv_writeslack;
- modify_flag = 0;
- } else
- notstarted = 0;
- }
- if (notstarted) {
- if ((nd->nd_flag & ND_NQNFS) == 0)
- cacherep = RC_DROPIT;
- else if (nd->nd_procnum != NFSPROC_WRITE) {
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = NQNFS_TRYLATER;
- cacherep = RC_DOIT;
- } else
- modify_flag = 1;
- } else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
- nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- cacherep = RC_DOIT;
- } else if (nfs_privport) {
- /* Check if source port is privileged */
- u_short port;
- struct sockaddr *nam = nd->nd_nam;
- struct sockaddr_in *sin;
-
- sin = (struct sockaddr_in *)nam;
- port = ntohs(sin->sin_port);
- if (port >= IPPORT_RESERVED &&
- nd->nd_procnum != NFSPROC_NULL) {
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- cacherep = RC_DOIT;
- printf("NFS request from unprivileged port (%s:%d)\n",
- inet_ntoa(sin->sin_addr), port);
- }
- }
-
- }
-
- /*
- * Loop to get all the write rpc relies that have been
- * gathered together.
- */
- do {
- switch (cacherep) {
- case RC_DOIT:
- if (nd && (nd->nd_flag & ND_NFSV3))
- procrastinate = nfsrvw_procrastinate_v3;
- else
- procrastinate = nfsrvw_procrastinate;
- if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
- procrastinate > 0 && !notstarted))
- error = nfsrv_writegather(&nd, slp,
- nfsd->nfsd_td, &mreq);
- else
- error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
- slp, nfsd->nfsd_td, &mreq);
- if (mreq == NULL)
- break;
- if (error != 0 && error != NFSERR_RETVOID) {
- if (nd->nd_procnum != NQNFSPROC_VACATED)
- nfsstats.srv_errs++;
- nfsrv_updatecache(nd, FALSE, mreq);
- if (nd->nd_nam2)
- FREE(nd->nd_nam2, M_SONAME);
- break;
- }
- nfsstats.srvrpccnt[nd->nd_procnum]++;
- nfsrv_updatecache(nd, TRUE, mreq);
- nd->nd_mrep = (struct mbuf *)0;
- case RC_REPLY:
- m = mreq;
- siz = 0;
- while (m) {
- siz += m->m_len;
- m = m->m_next;
- }
- if (siz <= 0 || siz > NFS_MAXPACKET) {
- printf("mbuf siz=%d\n",siz);
- panic("Bad nfs svc reply");
- }
- m = mreq;
- m->m_pkthdr.len = siz;
- m->m_pkthdr.rcvif = (struct ifnet *)0;
- /*
- * For stream protocols, prepend a Sun RPC
- * Record Mark.
- */
- if (sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 | siz);
- }
- if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
- (void) nfs_slplock(slp, 1);
- if (slp->ns_flag & SLP_VALID)
- error = nfs_send(slp->ns_so, nd->nd_nam2, m, NULL);
- else {
- error = EPIPE;
- m_freem(m);
- }
- if (nfsrtton)
- nfsd_rt(sotype, nd, cacherep);
- if (nd->nd_nam2)
- FREE(nd->nd_nam2, M_SONAME);
- if (nd->nd_mrep)
- m_freem(nd->nd_mrep);
- if (error == EPIPE)
- nfsrv_zapsock(slp);
- if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
- nfs_slpunlock(slp);
- if (error == EINTR || error == ERESTART) {
- free((caddr_t)nd, M_NFSRVDESC);
- nfsrv_slpderef(slp);
- s = splnet();
- goto done;
- }
- break;
- case RC_DROPIT:
- if (nfsrtton)
- nfsd_rt(sotype, nd, cacherep);
- m_freem(nd->nd_mrep);
- if (nd->nd_nam2)
- FREE(nd->nd_nam2, M_SONAME);
- break;
- };
- if (nd) {
- FREE((caddr_t)nd, M_NFSRVDESC);
- nd = NULL;
- }
-
- /*
- * Check to see if there are outstanding writes that
- * need to be serviced.
- */
- cur_usec = nfs_curusec();
- s = splsoftclock();
- if (slp->ns_tq.lh_first &&
- slp->ns_tq.lh_first->nd_time <= cur_usec) {
- cacherep = RC_DOIT;
- writes_todo = 1;
- } else
- writes_todo = 0;
- splx(s);
- } while (writes_todo);
- s = splnet();
- if (nfsrv_dorec(slp, nfsd, &nd)) {
- nfsd->nfsd_flag &= ~NFSD_REQINPROG;
- nfsd->nfsd_slp = NULL;
- nfsrv_slpderef(slp);
- }
- }
-done:
- TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
- splx(s);
- free((caddr_t)nfsd, M_NFSD);
- nsd->nsd_nfsd = (struct nfsd *)0;
- if (--nfs_numnfsd == 0)
- nfsrv_init(TRUE); /* Reinitialize everything */
- return (error);
-}
-
-/*
- * Shut down a socket associated with an nfssvc_sock structure.
- * Should be called with the send lock set, if required.
- * The trick here is to increment the sref at the start, so that the nfsds
- * will stop using it and clear ns_flag at the end so that it will not be
- * reassigned during cleanup.
- */
-static void
-nfsrv_zapsock(slp)
- register struct nfssvc_sock *slp;
-{
- register struct nfsuid *nuidp, *nnuidp;
- register struct nfsrv_descript *nwp, *nnwp;
- struct socket *so;
- struct file *fp;
- struct nfsrv_rec *rec;
- int s;
-
- slp->ns_flag &= ~SLP_ALLFLAGS;
- fp = slp->ns_fp;
- if (fp) {
- slp->ns_fp = (struct file *)0;
- so = slp->ns_so;
- so->so_rcv.sb_flags &= ~SB_UPCALL;
- so->so_upcall = NULL;
- so->so_upcallarg = NULL;
- soshutdown(so, 2);
- closef(fp, (struct thread *)0);
- if (slp->ns_nam)
- FREE(slp->ns_nam, M_SONAME);
- m_freem(slp->ns_raw);
- while ((rec = STAILQ_FIRST(&slp->ns_rec)) != NULL) {
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- if (rec->nr_address)
- FREE(rec->nr_address, M_SONAME);
- m_freem(rec->nr_packet);
- free(rec, M_NFSRVDESC);
- }
- for (nuidp = slp->ns_uidlruhead.tqh_first; nuidp != 0;
- nuidp = nnuidp) {
- nnuidp = nuidp->nu_lru.tqe_next;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
- if (nuidp->nu_flag & NU_NAM)
- FREE(nuidp->nu_nam, M_SONAME);
- free((caddr_t)nuidp, M_NFSUID);
- }
- s = splsoftclock();
- for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
- nnwp = nwp->nd_tq.le_next;
- LIST_REMOVE(nwp, nd_tq);
- free((caddr_t)nwp, M_NFSRVDESC);
- }
- LIST_INIT(&slp->ns_tq);
- splx(s);
- }
-}
-
-/*
- * Derefence a server socket structure. If it has no more references and
- * is no longer valid, you can throw it away.
- */
-void
-nfsrv_slpderef(slp)
- register struct nfssvc_sock *slp;
-{
- if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
- TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
- free((caddr_t)slp, M_NFSSVC);
- }
-}
-
-/*
- * Lock a socket against others.
- */
-int
-nfs_slplock(slp, wait)
- register struct nfssvc_sock *slp;
- int wait;
-{
- int *statep = &slp->ns_solock;
-
- if (!wait && (*statep & NFSSTA_SNDLOCK))
- return(0); /* already locked, fail */
- while (*statep & NFSSTA_SNDLOCK) {
- *statep |= NFSSTA_WANTSND;
- (void) tsleep((caddr_t)statep, PZERO - 1, "nfsslplck", 0);
- }
- *statep |= NFSSTA_SNDLOCK;
- return (1);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-void
-nfs_slpunlock(slp)
- register struct nfssvc_sock *slp;
-{
- int *statep = &slp->ns_solock;
-
- if ((*statep & NFSSTA_SNDLOCK) == 0)
- panic("nfs slpunlock");
- *statep &= ~NFSSTA_SNDLOCK;
- if (*statep & NFSSTA_WANTSND) {
- *statep &= ~NFSSTA_WANTSND;
- wakeup((caddr_t)statep);
- }
-}
-
-/*
- * Initialize the data structures for the server.
- * Handshake with any new nfsds starting up to avoid any chance of
- * corruption.
- */
-void
-nfsrv_init(terminating)
- int terminating;
-{
- register struct nfssvc_sock *slp, *nslp;
-
- if (nfssvc_sockhead_flag & SLP_INIT)
- panic("nfsd init");
- nfssvc_sockhead_flag |= SLP_INIT;
- if (terminating) {
- for (slp = nfssvc_sockhead.tqh_first; slp != 0; slp = nslp) {
- nslp = slp->ns_chain.tqe_next;
- if (slp->ns_flag & SLP_VALID)
- nfsrv_zapsock(slp);
- TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
- free((caddr_t)slp, M_NFSSVC);
- }
- nfsrv_cleancache(); /* And clear out server cache */
- } else
- nfs_pub.np_valid = 0;
-
- TAILQ_INIT(&nfssvc_sockhead);
- nfssvc_sockhead_flag &= ~SLP_INIT;
- if (nfssvc_sockhead_flag & SLP_WANTINIT) {
- nfssvc_sockhead_flag &= ~SLP_WANTINIT;
- wakeup((caddr_t)&nfssvc_sockhead);
- }
-
- TAILQ_INIT(&nfsd_head);
- nfsd_head_flag &= ~NFSD_CHECKSLP;
-
-#if 0
- nfs_udpsock = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
- STAILQ_INIT(&nfs_udpsock->ns_rec);
- TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
- TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
-
- nfs_cltpsock = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
- STAILQ_INIT(&nfs_cltpsock->ns_rec);
- TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
- TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
-#endif
-}
-
-/*
- * Add entries to the server monitor log.
- */
-static void
-nfsd_rt(sotype, nd, cacherep)
- int sotype;
- register struct nfsrv_descript *nd;
- int cacherep;
-{
- register struct drt *rt;
-
- rt = &nfsdrt.drt[nfsdrt.pos];
- if (cacherep == RC_DOIT)
- rt->flag = 0;
- else if (cacherep == RC_REPLY)
- rt->flag = DRT_CACHEREPLY;
- else
- rt->flag = DRT_CACHEDROP;
- if (sotype == SOCK_STREAM)
- rt->flag |= DRT_TCP;
- if (nd->nd_flag & ND_NQNFS)
- rt->flag |= DRT_NQNFS;
- else if (nd->nd_flag & ND_NFSV3)
- rt->flag |= DRT_NFSV3;
- rt->proc = nd->nd_procnum;
- if (nd->nd_nam->sa_family == AF_INET)
- rt->ipadr = ((struct sockaddr_in *)nd->nd_nam)->sin_addr.s_addr;
- else
- rt->ipadr = INADDR_ANY;
- rt->resptime = nfs_curusec() - (nd->nd_starttime.tv_sec * 1000000 + nd->nd_starttime.tv_usec);
- getmicrotime(&rt->tstamp);
- nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
-}
-#endif /* NFS_NOSERVER */
-
-static int nfs_defect = 0;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0, "");
-
-/*
- * Asynchronous I/O daemons for client nfs.
- * They do read-ahead and write-behind operations on the block I/O cache.
- * Never returns unless it fails or gets killed.
- */
-static int
-nfssvc_iod(td)
- struct thread *td;
-{
- register struct buf *bp;
- register int i, myiod;
- struct nfsmount *nmp;
- int error = 0;
-
- /*
- * Assign my position or return error if too many already running
- */
- myiod = -1;
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
- if (nfs_asyncdaemon[i] == 0) {
- nfs_asyncdaemon[i]++;
- myiod = i;
- break;
- }
- if (myiod == -1)
- return (EBUSY);
- nfs_numasync++;
- /*
- * Just loop around doin our stuff until SIGKILL
- */
- for (;;) {
- while (((nmp = nfs_iodmount[myiod]) == NULL
- || nmp->nm_bufq.tqh_first == NULL)
- && error == 0) {
- if (nmp)
- nmp->nm_bufqiods--;
- nfs_iodwant[myiod] = td->td_proc;
- nfs_iodmount[myiod] = NULL;
- error = tsleep((caddr_t)&nfs_iodwant[myiod],
- PWAIT | PCATCH, "nfsidl", 0);
- }
- if (error) {
- nfs_asyncdaemon[myiod] = 0;
- if (nmp)
- nmp->nm_bufqiods--;
- nfs_iodwant[myiod] = NULL;
- nfs_iodmount[myiod] = NULL;
- nfs_numasync--;
- return (error);
- }
- while ((bp = nmp->nm_bufq.tqh_first) != NULL) {
- /* Take one off the front of the list */
- TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist);
- nmp->nm_bufqlen--;
- if (nmp->nm_bufqwant && nmp->nm_bufqlen <= nfs_numasync) {
- nmp->nm_bufqwant = FALSE;
- wakeup(&nmp->nm_bufq);
- }
- if (bp->b_iocmd == BIO_READ)
- (void) nfs_doio(bp, bp->b_rcred, (struct thread *)0);
- else
- (void) nfs_doio(bp, bp->b_wcred, (struct thread *)0);
- /*
- * If there are more than one iod on this mount, then defect
- * so that the iods can be shared out fairly between the mounts
- */
- if (nfs_defect && nmp->nm_bufqiods > 1) {
- NFS_DPF(ASYNCIO,
- ("nfssvc_iod: iod %d defecting from mount %p\n",
- myiod, nmp));
- nfs_iodmount[myiod] = NULL;
- nmp->nm_bufqiods--;
- break;
- }
- }
- }
-}
-
-
-/*
- * Get an authorization string for the uid by having the mount_nfs sitting
- * on this mount point porpous out of the kernel and do it.
- */
-int
-nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
- struct ucred *cred;
- char **auth_str;
- int *auth_len;
- char *verf_str;
- int *verf_len;
- NFSKERBKEY_T key; /* return session key */
-{
- int error = 0;
-
- while ((nmp->nm_state & NFSSTA_WAITAUTH) == 0) {
- nmp->nm_state |= NFSSTA_WANTAUTH;
- (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK,
- "nfsauth1", 2 * hz);
- error = nfs_sigintr(nmp, rep, rep->r_td->td_proc);
- if (error) {
- nmp->nm_state &= ~NFSSTA_WANTAUTH;
- return (error);
- }
- }
- nmp->nm_state &= ~(NFSSTA_WAITAUTH | NFSSTA_WANTAUTH);
- nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
- nmp->nm_authlen = RPCAUTH_MAXSIZ;
- nmp->nm_verfstr = verf_str;
- nmp->nm_verflen = *verf_len;
- nmp->nm_authuid = cred->cr_uid;
- wakeup((caddr_t)&nmp->nm_authstr);
-
- /*
- * And wait for mount_nfs to do its stuff.
- */
- while ((nmp->nm_state & NFSSTA_HASAUTH) == 0 && error == 0) {
- (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK,
- "nfsauth2", 2 * hz);
- error = nfs_sigintr(nmp, rep, rep->r_td->td_proc);
- }
- if (nmp->nm_state & NFSSTA_AUTHERR) {
- nmp->nm_state &= ~NFSSTA_AUTHERR;
- error = EAUTH;
- }
- if (error)
- free((caddr_t)*auth_str, M_TEMP);
- else {
- *auth_len = nmp->nm_authlen;
- *verf_len = nmp->nm_verflen;
- bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
- }
- nmp->nm_state &= ~NFSSTA_HASAUTH;
- nmp->nm_state |= NFSSTA_WAITAUTH;
- if (nmp->nm_state & NFSSTA_WANTAUTH) {
- nmp->nm_state &= ~NFSSTA_WANTAUTH;
- wakeup((caddr_t)&nmp->nm_authtype);
- }
- return (error);
-}
-
-/*
- * Get a nickname authenticator and verifier.
- */
-int
-nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
- struct nfsmount *nmp;
- struct ucred *cred;
- char **auth_str;
- int *auth_len;
- char *verf_str;
- int verf_len;
-{
- register struct nfsuid *nuidp;
- register u_int32_t *nickp, *verfp;
- struct timeval ktvin, ktvout;
-
-#ifdef DIAGNOSTIC
- if (verf_len < (4 * NFSX_UNSIGNED))
- panic("nfs_getnickauth verf too small");
-#endif
- for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == cred->cr_uid)
- break;
- }
- if (!nuidp || nuidp->nu_expire < time_second)
- return (EACCES);
-
- /*
- * Move to the end of the lru list (end of lru == most recently used).
- */
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
- TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
-
- nickp = (u_int32_t *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
- *nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
- *nickp = txdr_unsigned(nuidp->nu_nickname);
- *auth_str = (char *)nickp;
- *auth_len = 2 * NFSX_UNSIGNED;
-
- /*
- * Now we must encrypt the verifier and package it up.
- */
- verfp = (u_int32_t *)verf_str;
- *verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
- if (time_second > nuidp->nu_timestamp.tv_sec ||
- (time_second == nuidp->nu_timestamp.tv_sec &&
- time_second > nuidp->nu_timestamp.tv_usec))
- getmicrotime(&nuidp->nu_timestamp);
- else
- nuidp->nu_timestamp.tv_usec++;
- ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
- ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Now encrypt the timestamp verifier in ecb mode using the session
- * key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *verfp++ = ktvout.tv_sec;
- *verfp++ = ktvout.tv_usec;
- *verfp = 0;
- return (0);
-}
-
-/*
- * Save the current nickname in a hash list entry on the mount point.
- */
-int
-nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
- register struct nfsmount *nmp;
- struct ucred *cred;
- int len;
- NFSKERBKEY_T key;
- struct mbuf **mdp;
- char **dposp;
- struct mbuf *mrep;
-{
- register struct nfsuid *nuidp;
- register u_int32_t *tl;
- register int32_t t1;
- struct mbuf *md = *mdp;
- struct timeval ktvin, ktvout;
- u_int32_t nick;
- char *dpos = *dposp, *cp2;
- int deltasec, error = 0;
-
- if (len == (3 * NFSX_UNSIGNED)) {
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- ktvin.tv_sec = *tl++;
- ktvin.tv_usec = *tl++;
- nick = fxdr_unsigned(u_int32_t, *tl);
-
- /*
- * Decrypt the timestamp in ecb mode.
- */
-#ifdef NFSKERB
- XXX
-#endif
- ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
- ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
- deltasec = time_second - ktvout.tv_sec;
- if (deltasec < 0)
- deltasec = -deltasec;
- /*
- * If ok, add it to the hash list for the mount point.
- */
- if (deltasec <= NFS_KERBCLOCKSKEW) {
- if (nmp->nm_numuids < nuidhash_max) {
- nmp->nm_numuids++;
- nuidp = (struct nfsuid *)
- malloc(sizeof (struct nfsuid), M_NFSUID,
- M_WAITOK);
- } else {
- nuidp = nmp->nm_uidlruhead.tqh_first;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
- nu_lru);
- }
- nuidp->nu_flag = 0;
- nuidp->nu_cr.cr_uid = cred->cr_uid;
- nuidp->nu_expire = time_second + NFS_KERBTTL;
- nuidp->nu_timestamp = ktvout;
- nuidp->nu_nickname = nick;
- bcopy(key, nuidp->nu_key, sizeof (key));
- TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
- nu_lru);
- LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
- nuidp, nu_hash);
- }
- } else
- nfsm_adv(nfsm_rndup(len));
-nfsmout:
- *mdp = md;
- *dposp = dpos;
- return (error);
-}
diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c
deleted file mode 100644
index c70600f..0000000
--- a/sys/nfs/nfs_vfsops.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- * 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.
- * 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_vfsops.c 8.12 (Berkeley) 5/20/95
- * $FreeBSD$
- */
-
-#include "opt_bootp.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/proc.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_zone.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <netinet/in.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsdiskless.h>
-#include <nfs/nqnfs.h>
-
-extern int nfs_mountroot __P((struct mount *mp));
-
-extern int nfs_ticks;
-
-MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
-MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle");
-MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
-MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data");
-MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
-MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure");
-MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease");
-MALLOC_DEFINE(M_NFSHASH, "NFS hash", "NFS hash tables");
-
-vm_zone_t nfsmount_zone;
-
-struct nfsstats nfsstats;
-SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
-SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
- &nfsstats, nfsstats, "");
-#ifdef NFS_DEBUG
-int nfs_debug;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
-#endif
-
-static int nfs_iosize __P((struct nfsmount *nmp));
-static void nfs_decode_args __P((struct nfsmount *nmp,
- struct nfs_args *argp));
-static int mountnfs __P((struct nfs_args *,struct mount *,
- struct sockaddr *,char *,char *,struct vnode **));
-static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct thread *p));
-static int nfs_unmount __P(( struct mount *mp, int mntflags,
- struct thread *p));
-static int nfs_root __P(( struct mount *mp, struct vnode **vpp));
-static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp,
- struct thread *p));
-static int nfs_sync __P(( struct mount *mp, int waitfor,
- struct ucred *cred, struct thread *p));
-
-/*
- * nfs vfs operations.
- */
-static struct vfsops nfs_vfsops = {
- nfs_mount,
- vfs_stdstart,
- nfs_unmount,
- nfs_root,
- vfs_stdquotactl,
- nfs_statfs,
- nfs_sync,
- vfs_stdvget,
- vfs_stdfhtovp, /* shouldn't happen */
- vfs_stdcheckexp,
- vfs_stdvptofh, /* shouldn't happen */
- nfs_init,
- nfs_uninit,
- vfs_stdextattrctl,
-};
-VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
-
-/*
- * This structure must be filled in by a primary bootstrap or bootstrap
- * server for a diskless/dataless machine. It is initialized below just
- * to ensure that it is allocated to initialized data (.data not .bss).
- */
-struct nfs_diskless nfs_diskless = { { { 0 } } };
-struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
-int nfs_diskless_valid = 0;
-
-SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
- &nfs_diskless_valid, 0, "");
-
-SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
- nfsv3_diskless.root_hostnam, 0, "");
-
-SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
- &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
- "%Ssockaddr_in", "");
-
-SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD,
- nfsv3_diskless.swap_hostnam, 0, "");
-
-SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
- &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr,
- "%Ssockaddr_in","");
-
-
-void nfsargs_ntoh __P((struct nfs_args *));
-static int nfs_mountdiskless __P((char *, char *, int,
- struct sockaddr_in *, struct nfs_args *,
- struct thread *, struct vnode **,
- struct mount **));
-static void nfs_convert_diskless __P((void));
-static void nfs_convert_oargs __P((struct nfs_args *args,
- struct onfs_args *oargs));
-
-static int
-nfs_iosize(nmp)
- struct nfsmount* nmp;
-{
- int iosize;
-
- /*
- * Calculate the size used for io buffers. Use the larger
- * of the two sizes to minimise nfs requests but make sure
- * that it is at least one VM page to avoid wasting buffer
- * space.
- */
- iosize = max(nmp->nm_rsize, nmp->nm_wsize);
- if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
- return iosize;
-}
-
-static void
-nfs_convert_oargs(args, oargs)
- struct nfs_args *args;
- struct onfs_args *oargs;
-{
- args->version = NFS_ARGSVERSION;
- args->addr = oargs->addr;
- args->addrlen = oargs->addrlen;
- args->sotype = oargs->sotype;
- args->proto = oargs->proto;
- args->fh = oargs->fh;
- args->fhsize = oargs->fhsize;
- args->flags = oargs->flags;
- args->wsize = oargs->wsize;
- args->rsize = oargs->rsize;
- args->readdirsize = oargs->readdirsize;
- args->timeo = oargs->timeo;
- args->retrans = oargs->retrans;
- args->maxgrouplist = oargs->maxgrouplist;
- args->readahead = oargs->readahead;
- args->leaseterm = oargs->leaseterm;
- args->deadthresh = oargs->deadthresh;
- args->hostname = oargs->hostname;
-}
-
-static void
-nfs_convert_diskless()
-{
- bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
- sizeof(struct ifaliasreq));
- bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
- sizeof(struct sockaddr_in));
- nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
- nfsv3_diskless.swap_fhsize = NFSX_V2FH;
- bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
- bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
- sizeof(struct sockaddr_in));
- bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, MNAMELEN);
- nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
- bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
- sizeof(struct ucred));
- nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
- nfsv3_diskless.root_fhsize = NFSX_V2FH;
- bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
- bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
- sizeof(struct sockaddr_in));
- bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, MNAMELEN);
- nfsv3_diskless.root_time = nfs_diskless.root_time;
- bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam,
- MAXHOSTNAMELEN);
- nfs_diskless_valid = 3;
-}
-
-/*
- * nfs statfs call
- */
-int
-nfs_statfs(mp, sbp, td)
- struct mount *mp;
- register struct statfs *sbp;
- struct thread *td;
-{
- register struct vnode *vp;
- register struct nfs_statfs *sfp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- struct nfsmount *nmp = VFSTONFS(mp);
- int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- struct nfsnode *np;
- u_quad_t tquad;
-
-#ifndef nolint
- sfp = (struct nfs_statfs *)0;
-#endif
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
- if (error)
- return (error);
- vp = NFSTOV(np);
- if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
- (void)nfs_fsinfo(nmp, vp, td->td_proc->p_ucred, td);
- nfsstats.rpccnt[NFSPROC_FSSTAT]++;
- nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
- nfsm_fhtom(vp, v3);
- nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_proc->p_ucred);
- if (v3)
- nfsm_postop_attr(vp, retattr);
- if (error) {
- if (mrep != NULL)
- m_freem(mrep);
- goto nfsmout;
- }
- nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
- sbp->f_flags = nmp->nm_flag;
- sbp->f_iosize = nfs_iosize(nmp);
- if (v3) {
- sbp->f_bsize = NFS_FABLKSIZE;
- tquad = fxdr_hyper(&sfp->sf_tbytes);
- sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
- tquad = fxdr_hyper(&sfp->sf_fbytes);
- sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
- tquad = fxdr_hyper(&sfp->sf_abytes);
- sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
- sbp->f_files = (fxdr_unsigned(int32_t,
- sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
- sbp->f_ffree = (fxdr_unsigned(int32_t,
- sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
- } else {
- sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
- sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
- sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
- sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
- sbp->f_files = 0;
- sbp->f_ffree = 0;
- }
- if (sbp != &mp->mnt_stat) {
- sbp->f_type = mp->mnt_vfc->vfc_typenum;
- bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
- bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
- }
- nfsm_reqdone;
- vput(vp);
- return (error);
-}
-
-/*
- * nfs version 3 fsinfo rpc call
- */
-int
-nfs_fsinfo(nmp, vp, cred, td)
- register struct nfsmount *nmp;
- register struct vnode *vp;
- struct ucred *cred;
- struct thread *td;
-{
- register struct nfsv3_fsinfo *fsp;
- register caddr_t cp;
- register int32_t t1, t2;
- register u_int32_t *tl, pref, max;
- caddr_t bpos, dpos, cp2;
- int error = 0, retattr;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- u_int64_t maxfsize;
-
- nfsstats.rpccnt[NFSPROC_FSINFO]++;
- nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
- nfsm_fhtom(vp, 1);
- nfsm_request(vp, NFSPROC_FSINFO, td, cred);
- nfsm_postop_attr(vp, retattr);
- if (!error) {
- nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
- pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
- if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
- nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
- ~(NFS_FABLKSIZE - 1);
- max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
- if (max < nmp->nm_wsize && max > 0) {
- nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_wsize == 0)
- nmp->nm_wsize = max;
- }
- pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
- if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
- nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
- ~(NFS_FABLKSIZE - 1);
- max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
- if (max < nmp->nm_rsize && max > 0) {
- nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_rsize == 0)
- nmp->nm_rsize = max;
- }
- pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
- if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
- nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
- ~(NFS_DIRBLKSIZ - 1);
- if (max < nmp->nm_readdirsize && max > 0) {
- nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
- if (nmp->nm_readdirsize == 0)
- nmp->nm_readdirsize = max;
- }
- maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
- if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
- nmp->nm_maxfilesize = maxfsize;
- nmp->nm_state |= NFSSTA_GOTFSINFO;
- }
- nfsm_reqdone;
- return (error);
-}
-
-/*
- * Mount a remote root fs via. nfs. This depends on the info in the
- * nfs_diskless structure that has been filled in properly by some primary
- * bootstrap.
- * It goes something like this:
- * - do enough of "ifconfig" by calling ifioctl() so that the system
- * can talk to the server
- * - If nfs_diskless.mygateway is filled in, use that address as
- * a default gateway.
- * - build the rootfs mount point and call mountnfs() to do the rest.
- */
-int
-nfs_mountroot(mp)
- struct mount *mp;
-{
- struct mount *swap_mp;
- struct nfsv3_diskless *nd = &nfsv3_diskless;
- struct socket *so;
- struct vnode *vp;
- struct thread *td = curthread; /* XXX */
- int error, i;
- u_long l;
- char buf[128];
-
-#if defined(BOOTP_NFSROOT) && defined(BOOTP)
- bootpc_init(); /* use bootp to get nfs_diskless filled in */
-#endif
-
- /*
- * XXX time must be non-zero when we init the interface or else
- * the arp code will wedge...
- */
- while (time_second == 0)
- tsleep(&time_second, PZERO+8, "arpkludge", 10);
-
- if (nfs_diskless_valid==1)
- nfs_convert_diskless();
-
- /*
- * XXX splnet, so networks will receive...
- */
- splnet();
-
-#ifdef notyet
- /* Set up swap credentials. */
- proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
- proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
- if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
- NGROUPS)
- proc0.p_ucred->cr_ngroups = NGROUPS;
- for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
- proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
-#endif
-
- /*
- * Do enough of ifconfig(8) so that the critical net interface can
- * talk to the server.
- */
- error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td);
- if (error)
- panic("nfs_mountroot: socreate(%04x): %d",
- nd->myif.ifra_addr.sa_family, error);
-
-#if 0 /* XXX Bad idea */
- /*
- * We might not have been told the right interface, so we pass
- * over the first ten interfaces of the same kind, until we get
- * one of them configured.
- */
-
- for (i = strlen(nd->myif.ifra_name) - 1;
- nd->myif.ifra_name[i] >= '0' &&
- nd->myif.ifra_name[i] <= '9';
- nd->myif.ifra_name[i] ++) {
- error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
- if(!error)
- break;
- }
-#endif
- error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
- if (error)
- panic("nfs_mountroot: SIOCAIFADDR: %d", error);
- soclose(so);
-
- /*
- * If the gateway field is filled in, set it as the default route.
- */
- if (nd->mygateway.sin_len != 0) {
- struct sockaddr_in mask, sin;
-
- bzero((caddr_t)&mask, sizeof(mask));
- sin = mask;
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
- error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
- (struct sockaddr *)&nd->mygateway,
- (struct sockaddr *)&mask,
- RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
- if (error)
- panic("nfs_mountroot: RTM_ADD: %d", error);
- }
-
- /*
- * Create the rootfs mount point.
- */
- nd->root_args.fh = nd->root_fh;
- nd->root_args.fhsize = nd->root_fhsize;
- l = ntohl(nd->root_saddr.sin_addr.s_addr);
- snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
- (l >> 24) & 0xff, (l >> 16) & 0xff,
- (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
- printf("NFS ROOT: %s\n",buf);
- if ((error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
- &nd->root_saddr, &nd->root_args, td, &vp, &mp)) != 0) {
- if (swap_mp) {
- mp->mnt_vfc->vfc_refcount--;
- free(swap_mp, M_MOUNT);
- }
- return (error);
- }
-
- swap_mp = NULL;
- if (nd->swap_nblks) {
-
- /* Convert to DEV_BSIZE instead of Kilobyte */
- nd->swap_nblks *= 2;
-
- /*
- * Create a fake mount point just for the swap vnode so that the
- * swap file can be on a different server from the rootfs.
- */
- nd->swap_args.fh = nd->swap_fh;
- nd->swap_args.fhsize = nd->swap_fhsize;
- l = ntohl(nd->swap_saddr.sin_addr.s_addr);
- snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
- (l >> 24) & 0xff, (l >> 16) & 0xff,
- (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam);
- printf("NFS SWAP: %s\n",buf);
- if ((error = nfs_mountdiskless(buf, "/swap", 0,
- &nd->swap_saddr, &nd->swap_args, td, &vp, &swap_mp)) != 0)
- return (error);
- vfs_unbusy(swap_mp, td);
-
- VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
- nd->swap_nblks * DEV_BSIZE ;
-
- /*
- * Since the swap file is not the root dir of a file system,
- * hack it to a regular file.
- */
- vp->v_type = VREG;
- vp->v_flag = 0;
- VREF(vp);
- swaponvp(td, vp, NODEV, nd->swap_nblks);
- }
-
- mp->mnt_flag |= MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
- rootvp = vp;
- vfs_unbusy(mp, td);
-
- /*
- * This is not really an nfs issue, but it is much easier to
- * set hostname here and then let the "/etc/rc.xxx" files
- * mount the right /var based upon its preset value.
- */
- bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
- hostname[MAXHOSTNAMELEN - 1] = '\0';
- for (i = 0; i < MAXHOSTNAMELEN; i++)
- if (hostname[i] == '\0')
- break;
- inittodr(ntohl(nd->root_time));
- return (0);
-}
-
-/*
- * Internal version of mount system call for diskless setup.
- */
-static int
-nfs_mountdiskless(path, which, mountflag, sin, args, td, vpp, mpp)
- char *path;
- char *which;
- int mountflag;
- struct sockaddr_in *sin;
- struct nfs_args *args;
- struct thread *td;
- struct vnode **vpp;
- struct mount **mpp;
-{
- struct mount *mp;
- struct sockaddr *nam;
- int error;
-
- mp = *mpp;
-
- if (!mp && (error = vfs_rootmountalloc("nfs", path, &mp))) {
- printf("nfs_mountroot: NFS not configured");
- return (error);
- }
-
- mp->mnt_kern_flag = 0;
- mp->mnt_flag = mountflag;
- nam = dup_sockaddr((struct sockaddr *)sin, 1);
- if ((error = mountnfs(args, mp, nam, which, path, vpp)) != 0) {
- printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
- mp->mnt_vfc->vfc_refcount--;
- vfs_unbusy(mp, td);
- free(mp, M_MOUNT);
- FREE(nam, M_SONAME);
- return (error);
- }
- (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
- *mpp = mp;
- return (0);
-}
-
-static void
-nfs_decode_args(nmp, argp)
- 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.
- */
- if (argp->sotype == SOCK_STREAM)
- nmp->nm_flag &= ~NFSMNT_NOCONN;
-
- /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
- if ((argp->flags & NFSMNT_NFSV3) == 0)
- 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_LEASETERM) && argp->leaseterm >= 2) {
- if (argp->leaseterm <= NQ_MAXLEASE)
- nmp->nm_leaseterm = argp->leaseterm;
- else
- nmp->nm_leaseterm = NQ_MAXLEASE;
- }
- if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1) {
- if (argp->deadthresh <= NQ_NEVERDEAD)
- nmp->nm_deadthresh = argp->deadthresh;
- else
- nmp->nm_deadthresh = NQ_NEVERDEAD;
- }
-
- adjsock |= ((nmp->nm_sotype != argp->sotype) ||
- (nmp->nm_soproto != argp->proto));
- nmp->nm_sotype = argp->sotype;
- nmp->nm_soproto = argp->proto;
-
- if (nmp->nm_so && adjsock) {
- nfs_safedisconnect(nmp);
- if (nmp->nm_sotype == SOCK_DGRAM)
- while (nfs_connect(nmp, (struct nfsreq *)0)) {
- printf("nfs_args: retrying connect\n");
- (void) tsleep((caddr_t)&lbolt,
- PSOCK, "nfscon", 0);
- }
- }
-}
-
-/*
- * 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
-nfs_mount(mp, path, data, ndp, td)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct thread *td;
-{
- int error;
- struct nfs_args args;
- struct sockaddr *nam;
- struct vnode *vp;
- char hst[MNAMELEN];
- size_t len;
- u_char nfh[NFSX_V3FHMAX];
-
- if (path == NULL) {
- nfs_mountroot(mp);
- return (0);
- }
- error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
- if (error)
- return (error);
- if (args.version != NFS_ARGSVERSION) {
-#ifdef COMPAT_PRELITE2
- /*
- * If the argument version is unknown, then assume the
- * caller is a pre-lite2 4.4BSD client and convert its
- * arguments.
- */
- struct onfs_args oargs;
- error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
- if (error)
- return (error);
- nfs_convert_oargs(&args,&oargs);
-#else /* !COMPAT_PRELITE2 */
- return (EPROGMISMATCH);
-#endif /* COMPAT_PRELITE2 */
- }
- if (mp->mnt_flag & MNT_UPDATE) {
- register struct nfsmount *nmp = VFSTONFS(mp);
-
- if (nmp == NULL)
- return (EIO);
- /*
- * When doing an update, we can't change from or to
- * v3 and/or nqnfs, or change cookie translation
- */
- args.flags = (args.flags &
- ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
- (nmp->nm_flag &
- (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
- nfs_decode_args(nmp, &args);
- return (0);
- }
- if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
- return (EINVAL);
- error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
- if (error)
- return (error);
- 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);
- args.fh = nfh;
- error = mountnfs(&args, mp, nam, path, hst, &vp);
- return (error);
-}
-
-/*
- * Common code for mount and mountroot
- */
-static int
-mountnfs(argp, mp, nam, pth, hst, vpp)
- register struct nfs_args *argp;
- register struct mount *mp;
- struct sockaddr *nam;
- char *pth, *hst;
- struct vnode **vpp;
-{
- register struct nfsmount *nmp;
- struct nfsnode *np;
- int error;
- struct vattr attrs;
-
- if (mp->mnt_flag & MNT_UPDATE) {
- nmp = VFSTONFS(mp);
- /* update paths, file handles, etc, here XXX */
- FREE(nam, M_SONAME);
- return (0);
- } else {
- nmp = zalloc(nfsmount_zone);
- bzero((caddr_t)nmp, sizeof (struct nfsmount));
- TAILQ_INIT(&nmp->nm_uidlruhead);
- TAILQ_INIT(&nmp->nm_bufq);
- mp->mnt_data = (qaddr_t)nmp;
- }
- vfs_getnewfsid(mp);
- nmp->nm_mountp = mp;
- if (argp->flags & NFSMNT_NQNFS)
- /*
- * We have to set mnt_maxsymlink to a non-zero value so
- * that COMPAT_43 routines will know that we are setting
- * the d_type field in directories (and can zero it for
- * unsuspecting binaries).
- */
- mp->mnt_maxsymlinklen = 1;
-
- /*
- * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
- * high, depending on whether we end up with negative offsets in
- * the client or server somewhere. 2GB-1 may be safer.
- *
- * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
- * that we can handle until we find out otherwise.
- * XXX Our "safe" limit on the client is what we can store in our
- * buffer cache using signed(!) block numbers.
- */
- if ((argp->flags & NFSMNT_NFSV3) == 0)
- nmp->nm_maxfilesize = 0xffffffffLL;
- else
- nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
-
- 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_leaseterm = NQ_DEFLEASE;
- nmp->nm_deadthresh = NQ_DEADTHRESH;
- TAILQ_INIT(&nmp->nm_timerhead);
- nmp->nm_inprog = NULLVP;
- nmp->nm_fhsize = argp->fhsize;
- bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
- bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
- bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
- nmp->nm_nam = nam;
- /* Set up the sockets and per-host congestion */
- nmp->nm_sotype = argp->sotype;
- nmp->nm_soproto = argp->proto;
-
- nfs_decode_args(nmp, argp);
-
- /*
- * For Connection based sockets (TCP,...) defer the connect until
- * the first request, in case the server is not responding.
- */
- if (nmp->nm_sotype == SOCK_DGRAM &&
- (error = nfs_connect(nmp, (struct nfsreq *)0)))
- goto bad;
-
- /*
- * This is silly, but it has to be set so that vinifod() works.
- * We do not want to do an nfs_statfs() here since we can get
- * stuck on a dead server and we are holding a lock on the mount
- * point.
- */
- mp->mnt_stat.f_iosize = nfs_iosize(nmp);
- /*
- * A reference count is needed on the nfsnode representing the
- * remote root. If this object is not persistent, then backward
- * traversals of the mount point (i.e. "..") will not work if
- * the nfsnode gets flushed out of the cache. Ufs does not have
- * this problem, because one can identify root inodes by their
- * number == ROOTINO (2).
- */
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
- if (error)
- goto bad;
- *vpp = NFSTOV(np);
-
- /*
- * Get file attributes for the mountpoint. This has the side
- * effect of filling in (*vpp)->v_type with the correct value.
- */
- VOP_GETATTR(*vpp, &attrs, curthread->td_proc->p_ucred, curthread);
-
- /*
- * Lose the lock but keep the ref.
- */
- VOP_UNLOCK(*vpp, 0, curthread);
-
- return (0);
-bad:
- nfs_disconnect(nmp);
- zfree(nfsmount_zone, nmp);
- FREE(nam, M_SONAME);
- return (error);
-}
-
-/*
- * unmount system call
- */
-static int
-nfs_unmount(mp, mntflags, td)
- struct mount *mp;
- int mntflags;
- struct thread *td;
-{
- register 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 file system
- * - Close the socket
- * - Free up the data structures
- */
- /*
- * Must handshake with nqnfs_clientd() if it is active.
- */
- nmp->nm_state |= NFSSTA_DISMINPROG;
- while (nmp->nm_inprog != NULLVP)
- (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
-
- /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
- error = vflush(mp, 1, flags);
- if (error) {
- nmp->nm_state &= ~NFSSTA_DISMINPROG;
- return (error);
- }
-
- /*
- * We are now committed to the unmount.
- * For NQNFS, let the server daemon free the nfsmount structure.
- */
- if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
- nmp->nm_state |= NFSSTA_DISMNT;
-
- nfs_disconnect(nmp);
- FREE(nmp->nm_nam, M_SONAME);
-
- if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
- zfree(nfsmount_zone, nmp);
- return (0);
-}
-
-/*
- * Return root of a filesystem
- */
-static int
-nfs_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
-{
- register 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);
- if (error)
- return (error);
- vp = NFSTOV(np);
- if (vp->v_type == VNON)
- vp->v_type = VDIR;
- vp->v_flag = VROOT;
- *vpp = vp;
- return (0);
-}
-
-extern int syncprt;
-
-/*
- * Flush out the buffer cache
- */
-/* ARGSUSED */
-static int
-nfs_sync(mp, waitfor, cred, td)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct thread *td;
-{
- struct vnode *vp, *vnp;
- int error, allerror = 0;
-
- /*
- * Force stale buffer cache information to be flushed.
- */
- mtx_lock(&mntvnode_mtx);
-loop:
- for (vp = LIST_FIRST(&mp->mnt_vnodelist);
- vp != NULL;
- vp = vnp) {
- /*
- * If the vnode that we are about to sync is no longer
- * associated with this mount point, start over.
- */
- if (vp->v_mount != mp)
- goto loop;
- vnp = LIST_NEXT(vp, v_mntvnodes);
- mtx_unlock(&mntvnode_mtx);
- mtx_lock(&vp->v_interlock);
- if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
- waitfor == MNT_LAZY) {
- mtx_unlock(&vp->v_interlock);
- mtx_lock(&mntvnode_mtx);
- continue;
- }
- if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
- mtx_lock(&mntvnode_mtx);
- goto loop;
- }
- error = VOP_FSYNC(vp, cred, waitfor, td);
- if (error)
- allerror = error;
- vput(vp);
- mtx_lock(&mntvnode_mtx);
- }
- mtx_unlock(&mntvnode_mtx);
- return (allerror);
-}
-
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
deleted file mode 100644
index 8f9ff7d..0000000
--- a/sys/nfs/nfs_vnops.c
+++ /dev/null
@@ -1,3344 +0,0 @@
-/*
- * 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.
- * 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_vnops.c 8.16 (Berkeley) 5/27/95
- * $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 <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include <fs/fifofs/fifo.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfs_lock.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_var.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 nfsspec_read __P((struct vop_read_args *));
-static int nfsspec_write __P((struct vop_write_args *));
-static int nfsfifo_read __P((struct vop_read_args *));
-static int nfsfifo_write __P((struct vop_write_args *));
-static int nfsspec_close __P((struct vop_close_args *));
-static int nfsfifo_close __P((struct vop_close_args *));
-#define nfs_poll vop_nopoll
-static int nfs_flush __P((struct vnode *,struct ucred *,int,struct thread *,int));
-static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct thread *));
-static int nfs_lookup __P((struct vop_lookup_args *));
-static int nfs_create __P((struct vop_create_args *));
-static int nfs_mknod __P((struct vop_mknod_args *));
-static int nfs_open __P((struct vop_open_args *));
-static int nfs_close __P((struct vop_close_args *));
-static int nfs_access __P((struct vop_access_args *));
-static int nfs_getattr __P((struct vop_getattr_args *));
-static int nfs_setattr __P((struct vop_setattr_args *));
-static int nfs_read __P((struct vop_read_args *));
-static int nfs_fsync __P((struct vop_fsync_args *));
-static int nfs_remove __P((struct vop_remove_args *));
-static int nfs_link __P((struct vop_link_args *));
-static int nfs_rename __P((struct vop_rename_args *));
-static int nfs_mkdir __P((struct vop_mkdir_args *));
-static int nfs_rmdir __P((struct vop_rmdir_args *));
-static int nfs_symlink __P((struct vop_symlink_args *));
-static int nfs_readdir __P((struct vop_readdir_args *));
-static int nfs_strategy __P((struct vop_strategy_args *));
-static int nfs_lookitup __P((struct vnode *, const char *, int,
- struct ucred *, struct thread *, struct nfsnode **));
-static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
-static int nfsspec_access __P((struct vop_access_args *));
-static int nfs_readlink __P((struct vop_readlink_args *));
-static int nfs_print __P((struct vop_print_args *));
-static int nfs_advlock __P((struct vop_advlock_args *));
-/*
- * Global vfs data structures for nfs
- */
-vop_t **nfsv2_vnodeop_p;
-static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) nfs_access },
- { &vop_advlock_desc, (vop_t *) nfs_advlock },
- { &vop_close_desc, (vop_t *) nfs_close },
- { &vop_create_desc, (vop_t *) nfs_create },
- { &vop_fsync_desc, (vop_t *) nfs_fsync },
- { &vop_getattr_desc, (vop_t *) nfs_getattr },
- { &vop_getpages_desc, (vop_t *) nfs_getpages },
- { &vop_putpages_desc, (vop_t *) nfs_putpages },
- { &vop_inactive_desc, (vop_t *) nfs_inactive },
- { &vop_islocked_desc, (vop_t *) vop_stdislocked },
- { &vop_lease_desc, (vop_t *) vop_null },
- { &vop_link_desc, (vop_t *) nfs_link },
- { &vop_lock_desc, (vop_t *) vop_sharedlock },
- { &vop_lookup_desc, (vop_t *) nfs_lookup },
- { &vop_mkdir_desc, (vop_t *) nfs_mkdir },
- { &vop_mknod_desc, (vop_t *) nfs_mknod },
- { &vop_open_desc, (vop_t *) nfs_open },
- { &vop_poll_desc, (vop_t *) nfs_poll },
- { &vop_print_desc, (vop_t *) nfs_print },
- { &vop_read_desc, (vop_t *) nfs_read },
- { &vop_readdir_desc, (vop_t *) nfs_readdir },
- { &vop_readlink_desc, (vop_t *) nfs_readlink },
- { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
- { &vop_remove_desc, (vop_t *) nfs_remove },
- { &vop_rename_desc, (vop_t *) nfs_rename },
- { &vop_rmdir_desc, (vop_t *) nfs_rmdir },
- { &vop_setattr_desc, (vop_t *) nfs_setattr },
- { &vop_strategy_desc, (vop_t *) nfs_strategy },
- { &vop_symlink_desc, (vop_t *) nfs_symlink },
- { &vop_unlock_desc, (vop_t *) vop_stdunlock },
- { &vop_write_desc, (vop_t *) nfs_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
- { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
-VNODEOP_SET(nfsv2_vnodeop_opv_desc);
-
-/*
- * Special device vnode ops
- */
-vop_t **spec_nfsv2nodeop_p;
-static struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
- { &vop_default_desc, (vop_t *) spec_vnoperate },
- { &vop_access_desc, (vop_t *) nfsspec_access },
- { &vop_close_desc, (vop_t *) nfsspec_close },
- { &vop_fsync_desc, (vop_t *) nfs_fsync },
- { &vop_getattr_desc, (vop_t *) nfs_getattr },
- { &vop_islocked_desc, (vop_t *) vop_stdislocked },
- { &vop_inactive_desc, (vop_t *) nfs_inactive },
- { &vop_lock_desc, (vop_t *) vop_sharedlock },
- { &vop_print_desc, (vop_t *) nfs_print },
- { &vop_read_desc, (vop_t *) nfsspec_read },
- { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
- { &vop_setattr_desc, (vop_t *) nfs_setattr },
- { &vop_unlock_desc, (vop_t *) vop_stdunlock },
- { &vop_write_desc, (vop_t *) nfsspec_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
- { &spec_nfsv2nodeop_p, nfsv2_specop_entries };
-VNODEOP_SET(spec_nfsv2nodeop_opv_desc);
-
-vop_t **fifo_nfsv2nodeop_p;
-static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
- { &vop_default_desc, (vop_t *) fifo_vnoperate },
- { &vop_access_desc, (vop_t *) nfsspec_access },
- { &vop_close_desc, (vop_t *) nfsfifo_close },
- { &vop_fsync_desc, (vop_t *) nfs_fsync },
- { &vop_getattr_desc, (vop_t *) nfs_getattr },
- { &vop_inactive_desc, (vop_t *) nfs_inactive },
- { &vop_islocked_desc, (vop_t *) vop_stdislocked },
- { &vop_lock_desc, (vop_t *) vop_sharedlock },
- { &vop_print_desc, (vop_t *) nfs_print },
- { &vop_read_desc, (vop_t *) nfsfifo_read },
- { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
- { &vop_setattr_desc, (vop_t *) nfs_setattr },
- { &vop_unlock_desc, (vop_t *) vop_stdunlock },
- { &vop_write_desc, (vop_t *) nfsfifo_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
- { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries };
-VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
-
-static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap));
-static int nfs_removerpc __P((struct vnode *dvp, const char *name,
- int namelen,
- struct ucred *cred, struct thread *td));
-static int nfs_renamerpc __P((struct vnode *fdvp, const char *fnameptr,
- int fnamelen, struct vnode *tdvp,
- const char *tnameptr, int tnamelen,
- struct ucred *cred, struct thread *td));
-static int nfs_renameit __P((struct vnode *sdvp,
- struct componentname *scnp,
- struct sillyrename *sp));
-
-/*
- * Global variables
- */
-extern u_int32_t nfs_true, nfs_false;
-extern u_int32_t nfs_xdrneg1;
-extern struct nfsstats nfsstats;
-extern nfstype nfsv3_type[9];
-struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
-struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
-int nfs_numasync = 0;
-#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
-
-SYSCTL_DECL(_vfs_nfs);
-
-static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
- &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
-
-static int nfsv3_commit_on_close = 0;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW,
- &nfsv3_commit_on_close, 0, "write+commit on close, else only write");
-#if 0
-SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_hits, CTLFLAG_RD,
- &nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
-
-SYSCTL_INT(_vfs_nfs, 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
-nfs3_access_otw(struct vnode *vp,
- int wmode,
- struct thread *td,
- struct ucred *cred)
-{
- const int v3 = 1;
- u_int32_t *tl;
- int error = 0, attrflag;
-
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- caddr_t bpos, dpos, cp2;
- register int32_t t1, t2;
- register caddr_t cp;
- u_int32_t rmode;
- struct nfsnode *np = VTONFS(vp);
-
- nfsstats.rpccnt[NFSPROC_ACCESS]++;
- nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
- nfsm_fhtom(vp, v3);
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(wmode);
- nfsm_request(vp, NFSPROC_ACCESS, td, cred);
- nfsm_postop_attr(vp, attrflag);
- if (!error) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- rmode = fxdr_unsigned(u_int32_t, *tl);
- np->n_mode = rmode;
- np->n_modeuid = cred->cr_uid;
- np->n_modestamp = time_second;
- }
- nfsm_reqdone;
- 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
-nfs_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- int error = 0;
- u_int32_t mode, wmode;
- int v3 = NFS_ISV3(vp);
- struct nfsnode *np = VTONFS(vp);
-
- /*
- * 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_mode & 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.
- */
- if (v3) {
- if (ap->a_mode & VREAD)
- mode = NFSV3ACCESS_READ;
- else
- mode = 0;
- if (vp->v_type != VDIR) {
- if (ap->a_mode & VWRITE)
- mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
- if (ap->a_mode & VEXEC)
- mode |= NFSV3ACCESS_EXECUTE;
- } else {
- if (ap->a_mode & VWRITE)
- mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
- NFSV3ACCESS_DELETE);
- if (ap->a_mode & VEXEC)
- mode |= NFSV3ACCESS_LOOKUP;
- }
- /* XXX safety belt, only make blanket request if caching */
- if (nfsaccess_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?
- */
- if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) &&
- (ap->a_cred->cr_uid == np->n_modeuid) &&
- ((np->n_mode & mode) == mode)) {
- nfsstats.accesscache_hits++;
- } else {
- /*
- * Either a no, or a don't know. Go to the wire.
- */
- nfsstats.accesscache_misses++;
- error = nfs3_access_otw(vp, wmode, ap->a_td,ap->a_cred);
- if (!error) {
- if ((np->n_mode & mode) != mode) {
- error = EACCES;
- }
- }
- }
- return (error);
- } else {
- if ((error = nfsspec_access(ap)) != 0)
- return (error);
-
- /*
- * Attempt to prevent a mapped root from accessing a file
- * which it shouldn't. We try to read a byte from the file
- * if the user is root and the file is not zero length.
- * After calling nfsspec_access, we should have the correct
- * file size cached.
- */
- if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD)
- && VTONFS(vp)->n_size > 0) {
- struct iovec aiov;
- struct uio auio;
- char buf[1];
-
- aiov.iov_base = buf;
- aiov.iov_len = 1;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_resid = 1;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_td = ap->a_td;
-
- if (vp->v_type == VREG)
- error = nfs_readrpc(vp, &auio, ap->a_cred);
- else if (vp->v_type == VDIR) {
- char* bp;
- bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
- aiov.iov_base = bp;
- aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
- error = nfs_readdirrpc(vp, &auio, ap->a_cred);
- free(bp, M_TEMP);
- } else if (vp->v_type == VLNK)
- error = nfs_readlinkrpc(vp, &auio, ap->a_cred);
- else
- error = EACCES;
- }
- 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
-nfs_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- struct vattr vattr;
- int error;
-
- if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
-#ifdef DIAGNOSTIC
- printf("open eacces vtyp=%d\n",vp->v_type);
-#endif
- return (EACCES);
- }
- /*
- * Get a valid lease. If cached data is stale, flush it.
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (NQNFS_CKINVALID(vp, np, ND_READ)) {
- do {
- error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
- ap->a_td);
- } while (error == NQNFS_EXPIRED);
- if (error)
- return (error);
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE)) {
- if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
- ap->a_td, 1)) == EINTR)
- return (error);
- np->n_brev = np->n_lrev;
- }
- }
- } else {
- if (np->n_flag & NMODIFIED) {
- if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
- ap->a_td, 1)) == EINTR)
- return (error);
- np->n_attrstamp = 0;
- if (vp->v_type == VDIR)
- np->n_direofoffset = 0;
- error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- } else {
- error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- if (np->n_mtime != vattr.va_mtime.tv_sec) {
- if (vp->v_type == VDIR)
- np->n_direofoffset = 0;
- if ((error = nfs_vinvalbuf(vp, V_SAVE,
- ap->a_cred, ap->a_td, 1)) == EINTR)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- }
- }
- }
- if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
- np->n_attrstamp = 0; /* For Open/Close consistency */
- return (0);
-}
-
-/*
- * nfs close vnode op
- * What an NFS client should do upon close after writing is a debatable issue.
- * Most NFS clients push delayed writes to the server upon close, basically for
- * two reasons:
- * 1 - So that any write errors may be reported back to the client process
- * doing the close system call. By far the two most likely errors are
- * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
- * 2 - To put a worst case upper bound on cache inconsistency between
- * multiple clients for the file.
- * There is also a consistency problem for Version 2 of the protocol w.r.t.
- * not being able to tell if other clients are writing a file concurrently,
- * since there is no way of knowing if the changed modify time in the reply
- * is only due to the write for this client.
- * (NFS Version 3 provides weak cache consistency data in the reply that
- * should be sufficient to detect and handle this case.)
- *
- * The current code does the following:
- * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
- * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
- * or commit them (this satisfies 1 and 2 except for the
- * case where the server crashes after this close but
- * before the commit RPC, which is felt to be "good
- * enough". Changing the last argument to nfs_flush() to
- * a 1 would force a commit operation, if it is felt a
- * commit is necessary now.
- * for NQNFS - do nothing now, since 2 is dealt with via leases and
- * 1 should be dealt with via an fsync() system call for
- * cases where write errors are important.
- */
-/* ARGSUSED */
-static int
-nfs_close(ap)
- struct vop_close_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- int error = 0;
-
- if (vp->v_type == VREG) {
- if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
- (np->n_flag & NMODIFIED)) {
- if (NFS_ISV3(vp)) {
- /*
- * Under NFSv3 we have dirty buffers to dispose of. We
- * must flush them to the NFS server. We have the option
- * of waiting all the way through the commit rpc or just
- * waiting for the initial write. The default is to only
- * wait through the initial write so the data is in the
- * server's cache, which is roughly similar to the state
- * a standard disk subsystem leaves the file in on close().
- *
- * We cannot clear the NMODIFIED bit in np->n_flag due to
- * potential races with other processes, and certainly
- * cannot clear it if we don't commit.
- */
- int cm = nfsv3_commit_on_close ? 1 : 0;
- error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_td, cm);
- /* np->n_flag &= ~NMODIFIED; */
- } else {
- error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_td, 1);
- }
- np->n_attrstamp = 0;
- }
- if (np->n_flag & NWRITEERR) {
- np->n_flag &= ~NWRITEERR;
- error = np->n_error;
- }
- }
- return (error);
-}
-
-/*
- * nfs getattr call from vfs.
- */
-static int
-nfs_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1, t2;
- caddr_t bpos, dpos;
- int error = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3 = NFS_ISV3(vp);
-
- /*
- * 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);
-
- if (v3 && nfsaccess_cache_timeout > 0) {
- nfsstats.accesscache_misses++;
- nfs3_access_otw(vp, NFSV3ACCESS_ALL, ap->a_td, ap->a_cred);
- if (nfs_getattrcache(vp, ap->a_vap) == 0)
- return (0);
- }
-
- nfsstats.rpccnt[NFSPROC_GETATTR]++;
- nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
- nfsm_fhtom(vp, v3);
- nfsm_request(vp, NFSPROC_GETATTR, ap->a_td, ap->a_cred);
- if (!error) {
- nfsm_loadattr(vp, ap->a_vap);
- }
- nfsm_reqdone;
- return (error);
-}
-
-/*
- * nfs setattr call.
- */
-static int
-nfs_setattr(ap)
- struct vop_setattr_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register struct vattr *vap = ap->a_vap;
- 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);
- vnode_pager_setsize(vp, vap->va_size);
- if (np->n_flag & NMODIFIED) {
- if (vap->va_size == 0)
- error = nfs_vinvalbuf(vp, 0,
- ap->a_cred, ap->a_td, 1);
- else
- error = nfs_vinvalbuf(vp, V_SAVE,
- ap->a_cred, ap->a_td, 1);
- if (error) {
- vnode_pager_setsize(vp, np->n_size);
- return (error);
- }
- }
- tsize = np->n_size;
- np->n_size = np->n_vattr.va_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, ap->a_cred,
- ap->a_td, 1)) == EINTR)
- return (error);
- error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_td);
- 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
-nfs_setattrrpc(vp, vap, cred, td)
- register struct vnode *vp;
- register struct vattr *vap;
- struct ucred *cred;
- struct thread *td;
-{
- register struct nfsv2_sattr *sp;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- u_int32_t *tl;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3 = NFS_ISV3(vp);
-
- nfsstats.rpccnt[NFSPROC_SETATTR]++;
- nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
- nfsm_fhtom(vp, v3);
- if (v3) {
- nfsm_v3attrbuild(vap, TRUE);
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- if (vap->va_mode == (mode_t)VNOVAL)
- sp->sa_mode = nfs_xdrneg1;
- else
- sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
- if (vap->va_uid == (uid_t)VNOVAL)
- sp->sa_uid = nfs_xdrneg1;
- else
- sp->sa_uid = txdr_unsigned(vap->va_uid);
- if (vap->va_gid == (gid_t)VNOVAL)
- sp->sa_gid = nfs_xdrneg1;
- else
- sp->sa_gid = txdr_unsigned(vap->va_gid);
- sp->sa_size = txdr_unsigned(vap->va_size);
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(vp, NFSPROC_SETATTR, td, cred);
- if (v3) {
- nfsm_wcc_data(vp, wccflag);
- } else
- nfsm_loadattr(vp, (struct vattr *)0);
- nfsm_reqdone;
- 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
-nfs_lookup(ap)
- struct vop_lookup_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- struct componentname *cnp = ap->a_cnp;
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- int flags = cnp->cn_flags;
- struct vnode *newvp;
- u_int32_t *tl;
- caddr_t cp;
- int32_t t1, t2;
- struct nfsmount *nmp;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- long len;
- nfsfh_t *fhp;
- struct nfsnode *np;
- int lockparent, wantparent, error = 0, attrflag, fhsize;
- int v3 = NFS_ISV3(dvp);
- struct thread *td = cnp->cn_thread;
-
- *vpp = NULLVP;
- cnp->cn_flags &= ~PDIRUNLOCK;
- 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);
- lockparent = flags & LOCKPARENT;
- wantparent = flags & (LOCKPARENT|WANTPARENT);
- nmp = VFSTONFS(dvp->v_mount);
- np = VTONFS(dvp);
- if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
- struct vattr vattr;
- int vpid;
-
- if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) {
- *vpp = NULLVP;
- return (error);
- }
-
- newvp = *vpp;
- vpid = newvp->v_id;
- /*
- * See the comment starting `Step through' in ufs/ufs_lookup.c
- * for an explanation of the locking protocol
- */
- if (dvp == newvp) {
- VREF(newvp);
- error = 0;
- } else if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp, 0, td);
- cnp->cn_flags |= PDIRUNLOCK;
- error = vget(newvp, LK_EXCLUSIVE, td);
- if (!error && lockparent && (flags & ISLASTCN)) {
- error = vn_lock(dvp, LK_EXCLUSIVE, td);
- if (error == 0)
- cnp->cn_flags &= ~PDIRUNLOCK;
- }
- } else {
- error = vget(newvp, LK_EXCLUSIVE, td);
- if (!lockparent || error || !(flags & ISLASTCN)) {
- VOP_UNLOCK(dvp, 0, td);
- cnp->cn_flags |= PDIRUNLOCK;
- }
- }
- if (!error) {
- if (vpid == newvp->v_id) {
- if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td)
- && 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);
- }
- vput(newvp);
- if (lockparent && dvp != newvp && (flags & ISLASTCN))
- VOP_UNLOCK(dvp, 0, td);
- }
- error = vn_lock(dvp, LK_EXCLUSIVE, td);
- *vpp = NULLVP;
- if (error) {
- cnp->cn_flags |= PDIRUNLOCK;
- return (error);
- }
- cnp->cn_flags &= ~PDIRUNLOCK;
- }
- error = 0;
- newvp = NULLVP;
- nfsstats.lookupcache_misses++;
- nfsstats.rpccnt[NFSPROC_LOOKUP]++;
- len = cnp->cn_namelen;
- nfsm_reqhead(dvp, NFSPROC_LOOKUP,
- NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred);
- if (error) {
- nfsm_postop_attr(dvp, attrflag);
- m_freem(mrep);
- goto nfsmout;
- }
- nfsm_getfh(fhp, fhsize, v3);
-
- /*
- * Handle RENAME case...
- */
- if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
- if (NFS_CMPFH(np, fhp, fhsize)) {
- m_freem(mrep);
- return (EISDIR);
- }
- error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
- if (error) {
- m_freem(mrep);
- return (error);
- }
- newvp = NFSTOV(np);
- if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- nfsm_postop_attr(dvp, attrflag);
- } else
- nfsm_loadattr(newvp, (struct vattr *)0);
- *vpp = newvp;
- m_freem(mrep);
- cnp->cn_flags |= SAVENAME;
- if (!lockparent) {
- VOP_UNLOCK(dvp, 0, td);
- cnp->cn_flags |= PDIRUNLOCK;
- }
- return (0);
- }
-
- if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp, 0, td);
- error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
- if (error) {
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
- return (error);
- }
- newvp = NFSTOV(np);
- if (lockparent && (flags & ISLASTCN)) {
- error = vn_lock(dvp, LK_EXCLUSIVE, td);
- if (error) {
- cnp->cn_flags |= PDIRUNLOCK;
- vput(newvp);
- return (error);
- }
- } else
- cnp->cn_flags |= PDIRUNLOCK;
- } else if (NFS_CMPFH(np, fhp, fhsize)) {
- VREF(dvp);
- newvp = dvp;
- } else {
- error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
- if (error) {
- m_freem(mrep);
- return (error);
- }
- if (!lockparent || !(flags & ISLASTCN)) {
- cnp->cn_flags |= PDIRUNLOCK;
- VOP_UNLOCK(dvp, 0, td);
- }
- newvp = NFSTOV(np);
- }
- if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- nfsm_postop_attr(dvp, attrflag);
- } else
- nfsm_loadattr(newvp, (struct vattr *)0);
- 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;
- nfsm_reqdone;
- if (error) {
- if (newvp != NULLVP) {
- vrele(newvp);
- *vpp = NULLVP;
- }
- if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
- (flags & ISLASTCN) && error == ENOENT) {
- if (!lockparent) {
- VOP_UNLOCK(dvp, 0, td);
- cnp->cn_flags |= PDIRUNLOCK;
- }
- 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
-nfs_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
-
- if (vp->v_type != VREG)
- return (EPERM);
- return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
-}
-
-/*
- * nfs readlink call
- */
-static int
-nfs_readlink(ap)
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
-{
- register 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
-nfs_readlinkrpc(vp, uiop, cred)
- register struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- int error = 0, len, attrflag;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3 = NFS_ISV3(vp);
-
- nfsstats.rpccnt[NFSPROC_READLINK]++;
- nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
- nfsm_fhtom(vp, v3);
- nfsm_request(vp, NFSPROC_READLINK, uiop->uio_td, cred);
- if (v3)
- nfsm_postop_attr(vp, attrflag);
- if (!error) {
- nfsm_strsiz(len, NFS_MAXPATHLEN);
- if (len == NFS_MAXPATHLEN) {
- struct nfsnode *np = VTONFS(vp);
- if (np->n_size && np->n_size < NFS_MAXPATHLEN)
- len = np->n_size;
- }
- nfsm_mtouio(uiop, len);
- }
- nfsm_reqdone;
- return (error);
-}
-
-/*
- * nfs read rpc call
- * Ditto above
- */
-int
-nfs_readrpc(vp, uiop, cred)
- register struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- struct nfsmount *nmp;
- int error = 0, len, retlen, tsiz, eof, attrflag;
- int v3 = NFS_ISV3(vp);
-
-#ifndef nolint
- eof = 0;
-#endif
- nmp = VFSTONFS(vp->v_mount);
- tsiz = uiop->uio_resid;
- if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
- return (EFBIG);
- while (tsiz > 0) {
- nfsstats.rpccnt[NFSPROC_READ]++;
- len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
- nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
- nfsm_fhtom(vp, v3);
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
- if (v3) {
- txdr_hyper(uiop->uio_offset, tl);
- *(tl + 2) = txdr_unsigned(len);
- } else {
- *tl++ = txdr_unsigned(uiop->uio_offset);
- *tl++ = txdr_unsigned(len);
- *tl = 0;
- }
- nfsm_request(vp, NFSPROC_READ, uiop->uio_td, cred);
- if (v3) {
- nfsm_postop_attr(vp, attrflag);
- if (error) {
- m_freem(mrep);
- goto nfsmout;
- }
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- eof = fxdr_unsigned(int, *(tl + 1));
- } else
- nfsm_loadattr(vp, (struct vattr *)0);
- nfsm_strsiz(retlen, nmp->nm_rsize);
- nfsm_mtouio(uiop, retlen);
- m_freem(mrep);
- tsiz -= retlen;
- if (v3) {
- if (eof || retlen == 0)
- tsiz = 0;
- } else if (retlen < len)
- tsiz = 0;
- }
-nfsmout:
- return (error);
-}
-
-/*
- * nfs write call
- */
-int
-nfs_writerpc(vp, uiop, cred, iomode, must_commit)
- register struct vnode *vp;
- register struct uio *uiop;
- struct ucred *cred;
- int *iomode, *must_commit;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2, backup;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
- int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
-
-#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);
- while (tsiz > 0) {
- nfsstats.rpccnt[NFSPROC_WRITE]++;
- len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
- nfsm_reqhead(vp, NFSPROC_WRITE,
- NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
- nfsm_fhtom(vp, v3);
- if (v3) {
- nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- txdr_hyper(uiop->uio_offset, tl);
- tl += 2;
- *tl++ = txdr_unsigned(len);
- *tl++ = txdr_unsigned(*iomode);
- *tl = txdr_unsigned(len);
- } else {
- register u_int32_t x;
-
- nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- /* Set both "begin" and "current" to non-garbage. */
- x = txdr_unsigned((u_int32_t)uiop->uio_offset);
- *tl++ = x; /* "begin offset" */
- *tl++ = x; /* "current offset" */
- x = txdr_unsigned(len);
- *tl++ = x; /* total to this offset */
- *tl = x; /* size of this write */
- }
- nfsm_uiotom(uiop, len);
- nfsm_request(vp, NFSPROC_WRITE, uiop->uio_td, cred);
- if (v3) {
- wccflag = NFSV3_WCCCHK;
- nfsm_wcc_data(vp, wccflag);
- if (!error) {
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
- + NFSX_V3WRITEVERF);
- rlen = fxdr_unsigned(int, *tl++);
- if (rlen == 0) {
- error = NFSERR_IO;
- m_freem(mrep);
- break;
- } else if (rlen < len) {
- backup = len - rlen;
- uiop->uio_iov->iov_base -= backup;
- uiop->uio_iov->iov_len += backup;
- uiop->uio_offset -= backup;
- uiop->uio_resid += backup;
- len = rlen;
- }
- commit = fxdr_unsigned(int, *tl++);
-
- /*
- * Return the lowest committment level
- * obtained by any of the RPCs.
- */
- if (committed == NFSV3WRITE_FILESYNC)
- committed = commit;
- else if (committed == NFSV3WRITE_DATASYNC &&
- commit == NFSV3WRITE_UNSTABLE)
- committed = commit;
- if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){
- bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
- NFSX_V3WRITEVERF);
- nmp->nm_state |= NFSSTA_HASWRITEVERF;
- } else if (bcmp((caddr_t)tl,
- (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
- *must_commit = 1;
- bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
- NFSX_V3WRITEVERF);
- }
- }
- } else
- nfsm_loadattr(vp, (struct vattr *)0);
- if (wccflag)
- VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
- m_freem(mrep);
- if (error)
- break;
- tsiz -= len;
- }
-nfsmout:
- if (vp->v_mount->mnt_flag & MNT_ASYNC)
- committed = NFSV3WRITE_FILESYNC;
- *iomode = committed;
- if (error)
- uiop->uio_resid = tsiz;
- return (error);
-}
-
-/*
- * nfs mknod rpc
- * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
- * mode set to specify the file type and the size field for rdev.
- */
-static int
-nfs_mknodrpc(dvp, vpp, cnp, vap)
- register struct vnode *dvp;
- register struct vnode **vpp;
- register struct componentname *cnp;
- register struct vattr *vap;
-{
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- struct vnode *newvp = (struct vnode *)0;
- struct nfsnode *np = (struct nfsnode *)0;
- struct vattr vattr;
- char *cp2;
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- u_int32_t rdev;
- int v3 = NFS_ISV3(dvp);
-
- if (vap->va_type == VCHR || vap->va_type == VBLK)
- rdev = txdr_unsigned(vap->va_rdev);
- else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
- rdev = nfs_xdrneg1;
- else {
- return (EOPNOTSUPP);
- }
- if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0) {
- return (error);
- }
- nfsstats.rpccnt[NFSPROC_MKNOD]++;
- nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
- + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- if (v3) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl++ = vtonfsv3_type(vap->va_type);
- nfsm_v3attrbuild(vap, FALSE);
- if (vap->va_type == VCHR || vap->va_type == VBLK) {
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(umajor(vap->va_rdev));
- *tl = txdr_unsigned(uminor(vap->va_rdev));
- }
- } else {
- nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = rdev;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_thread, cnp->cn_cred);
- if (!error) {
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- if (!gotvp) {
- if (newvp) {
- vput(newvp);
- newvp = (struct vnode *)0;
- }
- error = nfs_lookitup(dvp, cnp->cn_nameptr,
- cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, &np);
- if (!error)
- newvp = NFSTOV(np);
- }
- }
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
- if (error) {
- if (newvp)
- vput(newvp);
- } else {
- if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, newvp, cnp);
- *vpp = newvp;
- }
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
- VTONFS(dvp)->n_attrstamp = 0;
- return (error);
-}
-
-/*
- * nfs mknod vop
- * just call nfs_mknodrpc() to do the work.
- */
-/* ARGSUSED */
-static int
-nfs_mknod(ap)
- struct vop_mknod_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- return nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
-}
-
-static u_long create_verf;
-/*
- * nfs file create call
- */
-static int
-nfs_create(ap)
- struct vop_create_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- struct nfsnode *np = (struct nfsnode *)0;
- struct vnode *newvp = (struct vnode *)0;
- caddr_t bpos, dpos, cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- struct vattr vattr;
- int v3 = NFS_ISV3(dvp);
-
- /*
- * Oops, not for me..
- */
- if (vap->va_type == VSOCK)
- return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
-
- if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0) {
- return (error);
- }
- if (vap->va_vaflags & VA_EXCLUSIVE)
- fmode |= O_EXCL;
-again:
- nfsstats.rpccnt[NFSPROC_CREATE]++;
- nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- if (v3) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- if (fmode & O_EXCL) {
- *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
- nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
-#ifdef INET
- if (!TAILQ_EMPTY(&in_ifaddrhead))
- *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr;
- else
-#endif
- *tl++ = create_verf;
- *tl = ++create_verf;
- } else {
- *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
- nfsm_v3attrbuild(vap, FALSE);
- }
- } else {
- nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = 0;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_thread, cnp->cn_cred);
- if (!error) {
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- if (!gotvp) {
- if (newvp) {
- vput(newvp);
- newvp = (struct vnode *)0;
- }
- error = nfs_lookitup(dvp, cnp->cn_nameptr,
- cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, &np);
- if (!error)
- newvp = NFSTOV(np);
- }
- }
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
- if (error) {
- if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
- fmode &= ~O_EXCL;
- goto again;
- }
- if (newvp)
- vput(newvp);
- } else if (v3 && (fmode & O_EXCL)) {
- /*
- * We are normally called with only a partially initialized
- * VAP. Since the NFSv3 spec says that server may use the
- * file attributes to store the verifier, the spec requires
- * us to do a SETATTR RPC. FreeBSD servers store the verifier
- * in atime, but we can't really assume that all servers will
- * so we ensure that our SETATTR sets both atime and mtime.
- */
- if (vap->va_mtime.tv_sec == VNOVAL)
- vfs_timestamp(&vap->va_mtime);
- if (vap->va_atime.tv_sec == VNOVAL)
- vap->va_atime = vap->va_mtime;
- error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_thread);
- }
- if (!error) {
- if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, newvp, cnp);
- *ap->a_vpp = newvp;
- }
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
- VTONFS(dvp)->n_attrstamp = 0;
- 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 nfs_sillyrename() to set it up
- * else
- * do the remove rpc
- */
-static int
-nfs_remove(ap)
- struct vop_remove_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode * a_dvp;
- struct vnode * a_vp;
- struct componentname * a_cnp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsnode *np = VTONFS(vp);
- int error = 0;
- struct vattr vattr;
-
-#ifndef DIAGNOSTIC
- if ((cnp->cn_flags & HASBUF) == 0)
- panic("nfs_remove: no name");
- if (vp->v_usecount < 1)
- panic("nfs_remove: bad v_usecount");
-#endif
- if (vp->v_type == VDIR)
- error = EPERM;
- else if (vp->v_usecount == 1 || (np->n_sillyrename &&
- VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_thread) == 0 &&
- 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_cred, cnp->cn_thread, 1);
- /* Do the rpc */
- if (error != EINTR)
- error = nfs_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 = nfs_sillyrename(dvp, vp, cnp);
- np->n_attrstamp = 0;
- return (error);
-}
-
-/*
- * nfs file remove rpc called from nfs_inactive
- */
-int
-nfs_removeit(sp)
- register struct sillyrename *sp;
-{
-
- return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
- (struct thread *)0));
-}
-
-/*
- * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
- */
-static int
-nfs_removerpc(dvp, name, namelen, cred, td)
- register struct vnode *dvp;
- const char *name;
- int namelen;
- struct ucred *cred;
- struct thread *td;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3 = NFS_ISV3(dvp);
-
- nfsstats.rpccnt[NFSPROC_REMOVE]++;
- nfsm_reqhead(dvp, NFSPROC_REMOVE,
- NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_REMOVE, td, cred);
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
- VTONFS(dvp)->n_attrstamp = 0;
- return (error);
-}
-
-/*
- * nfs file rename call
- */
-static int
-nfs_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
-{
- register struct vnode *fvp = ap->a_fvp;
- register struct vnode *tvp = ap->a_tvp;
- register struct vnode *fdvp = ap->a_fdvp;
- register struct vnode *tdvp = ap->a_tdvp;
- register struct componentname *tcnp = ap->a_tcnp;
- register struct componentname *fcnp = ap->a_fcnp;
- int error;
-
-#ifndef DIAGNOSTIC
- if ((tcnp->cn_flags & HASBUF) == 0 ||
- (fcnp->cn_flags & HASBUF) == 0)
- panic("nfs_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;
- }
-
- /*
- * 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, fcnp->cn_cred, MNT_WAIT, fcnp->cn_thread);
- if (tvp)
- VOP_FSYNC(tvp, tcnp->cn_cred, 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 && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
- tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
- vput(tvp);
- tvp = NULL;
- }
-
- error = nfs_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 nfs_remove() above
- */
-static int
-nfs_renameit(sdvp, scnp, sp)
- struct vnode *sdvp;
- struct componentname *scnp;
- register struct sillyrename *sp;
-{
- return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
- sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread));
-}
-
-/*
- * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
- */
-static int
-nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, td)
- register struct vnode *fdvp;
- const char *fnameptr;
- int fnamelen;
- register struct vnode *tdvp;
- const char *tnameptr;
- int tnamelen;
- struct ucred *cred;
- struct thread *td;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3 = NFS_ISV3(fdvp);
-
- nfsstats.rpccnt[NFSPROC_RENAME]++;
- nfsm_reqhead(fdvp, NFSPROC_RENAME,
- (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
- nfsm_rndup(tnamelen));
- nfsm_fhtom(fdvp, v3);
- nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
- nfsm_fhtom(tdvp, v3);
- nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
- nfsm_request(fdvp, NFSPROC_RENAME, td, cred);
- if (v3) {
- nfsm_wcc_data(fdvp, fwccflag);
- nfsm_wcc_data(tdvp, twccflag);
- }
- nfsm_reqdone;
- VTONFS(fdvp)->n_flag |= NMODIFIED;
- VTONFS(tdvp)->n_flag |= NMODIFIED;
- if (!fwccflag)
- VTONFS(fdvp)->n_attrstamp = 0;
- if (!twccflag)
- VTONFS(tdvp)->n_attrstamp = 0;
- return (error);
-}
-
-/*
- * nfs hard link create call
- */
-static int
-nfs_link(ap)
- struct vop_link_args /* {
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct vnode *tdvp = ap->a_tdvp;
- register struct componentname *cnp = ap->a_cnp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3;
-
- 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, cnp->cn_cred, MNT_WAIT, cnp->cn_thread);
-
- v3 = NFS_ISV3(vp);
- nfsstats.rpccnt[NFSPROC_LINK]++;
- nfsm_reqhead(vp, NFSPROC_LINK,
- NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
- nfsm_fhtom(vp, v3);
- nfsm_fhtom(tdvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- nfsm_request(vp, NFSPROC_LINK, cnp->cn_thread, cnp->cn_cred);
- if (v3) {
- nfsm_postop_attr(vp, attrflag);
- nfsm_wcc_data(tdvp, wccflag);
- }
- nfsm_reqdone;
- VTONFS(tdvp)->n_flag |= NMODIFIED;
- if (!attrflag)
- VTONFS(vp)->n_attrstamp = 0;
- if (!wccflag)
- VTONFS(tdvp)->n_attrstamp = 0;
- /*
- * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
- */
- if (error == EEXIST)
- error = 0;
- return (error);
-}
-
-/*
- * nfs symbolic link create call
- */
-static int
-nfs_symlink(ap)
- struct vop_symlink_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
- } */ *ap;
-{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- struct vnode *newvp = (struct vnode *)0;
- int v3 = NFS_ISV3(dvp);
-
- nfsstats.rpccnt[NFSPROC_SYMLINK]++;
- slen = strlen(ap->a_target);
- nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- if (v3) {
- nfsm_v3attrbuild(vap, FALSE);
- }
- nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
- if (!v3) {
- nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = nfs_xdrneg1;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
-
- /*
- * Issue the NFS request and get the rpc response.
- *
- * Only NFSv3 responses returning an error of 0 actually return
- * a file handle that can be converted into newvp without having
- * to do an extra lookup rpc.
- */
- nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_thread, cnp->cn_cred);
- if (v3) {
- if (error == 0)
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- nfsm_wcc_data(dvp, wccflag);
- }
-
- /*
- * out code jumps -> here, mrep is also freed.
- */
-
- nfsm_reqdone;
-
- /*
- * If we get an EEXIST error, silently convert it to no-error
- * in case of an NFS retry.
- */
- if (error == EEXIST)
- error = 0;
-
- /*
- * If we do not have (or no longer have) an error, and we could
- * not extract the newvp from the response due to the request being
- * NFSv2 or the error being EEXIST. We have to do a lookup in order
- * to obtain a newvp to return.
- */
- if (error == 0 && newvp == NULL) {
- struct nfsnode *np = NULL;
-
- error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
- cnp->cn_cred, cnp->cn_thread, &np);
- if (!error)
- newvp = NFSTOV(np);
- }
- if (error) {
- if (newvp)
- vput(newvp);
- } else {
- *ap->a_vpp = newvp;
- }
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
- VTONFS(dvp)->n_attrstamp = 0;
- return (error);
-}
-
-/*
- * nfs make dir call
- */
-static int
-nfs_mkdir(ap)
- struct vop_mkdir_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register int len;
- struct nfsnode *np = (struct nfsnode *)0;
- struct vnode *newvp = (struct vnode *)0;
- caddr_t bpos, dpos, cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- int gotvp = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- struct vattr vattr;
- int v3 = NFS_ISV3(dvp);
-
- if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0) {
- return (error);
- }
- len = cnp->cn_namelen;
- nfsstats.rpccnt[NFSPROC_MKDIR]++;
- nfsm_reqhead(dvp, NFSPROC_MKDIR,
- NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
- if (v3) {
- nfsm_v3attrbuild(vap, FALSE);
- } else {
- nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = nfs_xdrneg1;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_thread, cnp->cn_cred);
- if (!error)
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
- VTONFS(dvp)->n_attrstamp = 0;
- /*
- * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
- * if we can succeed in looking up the directory.
- */
- if (error == EEXIST || (!error && !gotvp)) {
- if (newvp) {
- vrele(newvp);
- newvp = (struct vnode *)0;
- }
- error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
- cnp->cn_thread, &np);
- if (!error) {
- newvp = NFSTOV(np);
- if (newvp->v_type != VDIR)
- error = EEXIST;
- }
- }
- if (error) {
- if (newvp)
- vrele(newvp);
- } else
- *ap->a_vpp = newvp;
- return (error);
-}
-
-/*
- * nfs remove directory call
- */
-static int
-nfs_rmdir(ap)
- struct vop_rmdir_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
- register struct componentname *cnp = ap->a_cnp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- int v3 = NFS_ISV3(dvp);
-
- if (dvp == vp)
- return (EINVAL);
- nfsstats.rpccnt[NFSPROC_RMDIR]++;
- nfsm_reqhead(dvp, NFSPROC_RMDIR,
- NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_thread, cnp->cn_cred);
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
- VTONFS(dvp)->n_attrstamp = 0;
- cache_purge(dvp);
- cache_purge(vp);
- /*
- * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
- */
- if (error == ENOENT)
- error = 0;
- return (error);
-}
-
-/*
- * nfs readdir call
- */
-static int
-nfs_readdir(ap)
- struct vop_readdir_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register 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 (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
- if (NQNFS_CKCACHABLE(vp, ND_READ)) {
- nfsstats.direofcache_hits++;
- return (0);
- }
- } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
- np->n_mtime == vattr.va_mtime.tv_sec) {
- 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);
-}
-
-/*
- * Readdir rpc call.
- * Called from below the buffer cache by nfs_doio().
- */
-int
-nfs_readdirrpc(vp, uiop, cred)
- struct vnode *vp;
- register struct uio *uiop;
- struct ucred *cred;
-
-{
- register int len, left;
- register struct dirent *dp = NULL;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register nfsuint64 *cookiep;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- nfsuint64 cookie;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- struct nfsnode *dnp = VTONFS(vp);
- u_quad_t fileno;
- int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
- int attrflag;
- int v3 = NFS_ISV3(vp);
-
-#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 = nfs_getcookie(dnp, uiop->uio_offset, 0);
- if (cookiep)
- cookie = *cookiep;
- else
- return (NFSERR_BAD_COOKIE);
- /*
- * Loop around doing readdir rpc's of size nm_readdirsize
- * truncated to a multiple of DIRBLKSIZ.
- * The stopping criteria is EOF or buffer full.
- */
- while (more_dirs && bigenough) {
- nfsstats.rpccnt[NFSPROC_READDIR]++;
- nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
- NFSX_READDIR(v3));
- nfsm_fhtom(vp, v3);
- if (v3) {
- nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- *tl++ = cookie.nfsuquad[0];
- *tl++ = cookie.nfsuquad[1];
- *tl++ = dnp->n_cookieverf.nfsuquad[0];
- *tl++ = dnp->n_cookieverf.nfsuquad[1];
- } else {
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = cookie.nfsuquad[0];
- }
- *tl = txdr_unsigned(nmp->nm_readdirsize);
- nfsm_request(vp, NFSPROC_READDIR, uiop->uio_td, cred);
- if (v3) {
- nfsm_postop_attr(vp, attrflag);
- if (!error) {
- nfsm_dissect(tl, u_int32_t *,
- 2 * NFSX_UNSIGNED);
- dnp->n_cookieverf.nfsuquad[0] = *tl++;
- dnp->n_cookieverf.nfsuquad[1] = *tl;
- } else {
- m_freem(mrep);
- goto nfsmout;
- }
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- more_dirs = fxdr_unsigned(int, *tl);
-
- /* loop thru the dir entries, doctoring them to 4bsd form */
- while (more_dirs && bigenough) {
- if (v3) {
- nfsm_dissect(tl, u_int32_t *,
- 3 * NFSX_UNSIGNED);
- fileno = fxdr_hyper(tl);
- len = fxdr_unsigned(int, *(tl + 2));
- } else {
- nfsm_dissect(tl, u_int32_t *,
- 2 * NFSX_UNSIGNED);
- fileno = fxdr_unsigned(u_quad_t, *tl++);
- len = fxdr_unsigned(int, *tl);
- }
- if (len <= 0 || len > NFS_MAXNAMLEN) {
- error = EBADRPC;
- m_freem(mrep);
- 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 += 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_fileno = (int)fileno;
- dp->d_namlen = len;
- dp->d_reclen = tlen + DIRHDSIZ;
- dp->d_type = DT_UNKNOWN;
- blksiz += dp->d_reclen;
- if (blksiz == DIRBLKSIZ)
- blksiz = 0;
- uiop->uio_offset += DIRHDSIZ;
- uiop->uio_resid -= DIRHDSIZ;
- uiop->uio_iov->iov_base += DIRHDSIZ;
- uiop->uio_iov->iov_len -= DIRHDSIZ;
- nfsm_mtouio(uiop, len);
- cp = uiop->uio_iov->iov_base;
- tlen -= len;
- *cp = '\0'; /* null terminate */
- uiop->uio_iov->iov_base += tlen;
- uiop->uio_iov->iov_len -= tlen;
- uiop->uio_offset += tlen;
- uiop->uio_resid -= tlen;
- } else
- nfsm_adv(nfsm_rndup(len));
- if (v3) {
- nfsm_dissect(tl, u_int32_t *,
- 3 * NFSX_UNSIGNED);
- } else {
- nfsm_dissect(tl, u_int32_t *,
- 2 * NFSX_UNSIGNED);
- }
- if (bigenough) {
- cookie.nfsuquad[0] = *tl++;
- if (v3)
- cookie.nfsuquad[1] = *tl++;
- } else if (v3)
- tl += 2;
- else
- tl++;
- more_dirs = fxdr_unsigned(int, *tl);
- }
- /*
- * If at end of rpc data, get the eof boolean
- */
- if (!more_dirs) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- more_dirs = (fxdr_unsigned(int, *tl) == 0);
- }
- m_freem(mrep);
- }
- /*
- * 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 += 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 = nfs_getcookie(dnp, uiop->uio_offset, 1);
- *cookiep = cookie;
- }
-nfsmout:
- return (error);
-}
-
-/*
- * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
- */
-int
-nfs_readdirplusrpc(vp, uiop, cred)
- struct vnode *vp;
- register struct uio *uiop;
- struct ucred *cred;
-{
- register int len, left;
- register struct dirent *dp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register struct vnode *newvp;
- register nfsuint64 *cookiep;
- caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
- struct nameidata nami, *ndp = &nami;
- struct componentname *cnp = &ndp->ni_cnd;
- nfsuint64 cookie;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- struct nfsnode *dnp = VTONFS(vp), *np;
- nfsfh_t *fhp;
- u_quad_t fileno;
- int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
- int attrflag, fhsize;
-
-#ifndef nolint
- dp = (struct dirent *)0;
-#endif
-#ifndef DIAGNOSTIC
- if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
- (uiop->uio_resid & (DIRBLKSIZ - 1)))
- panic("nfs readdirplusrpc bad uio");
-#endif
- ndp->ni_dvp = vp;
- newvp = NULLVP;
-
- /*
- * If there is no cookie, assume directory was stale.
- */
- cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
- if (cookiep)
- cookie = *cookiep;
- else
- return (NFSERR_BAD_COOKIE);
- /*
- * Loop around doing readdir rpc's of size nm_readdirsize
- * truncated to a multiple of DIRBLKSIZ.
- * The stopping criteria is EOF or buffer full.
- */
- while (more_dirs && bigenough) {
- nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
- nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
- NFSX_FH(1) + 6 * NFSX_UNSIGNED);
- nfsm_fhtom(vp, 1);
- nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
- *tl++ = cookie.nfsuquad[0];
- *tl++ = cookie.nfsuquad[1];
- *tl++ = dnp->n_cookieverf.nfsuquad[0];
- *tl++ = dnp->n_cookieverf.nfsuquad[1];
- *tl++ = txdr_unsigned(nmp->nm_readdirsize);
- *tl = txdr_unsigned(nmp->nm_rsize);
- nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, cred);
- nfsm_postop_attr(vp, attrflag);
- if (error) {
- m_freem(mrep);
- goto nfsmout;
- }
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- dnp->n_cookieverf.nfsuquad[0] = *tl++;
- dnp->n_cookieverf.nfsuquad[1] = *tl++;
- more_dirs = fxdr_unsigned(int, *tl);
-
- /* loop thru the dir entries, doctoring them to 4bsd form */
- while (more_dirs && bigenough) {
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- fileno = fxdr_hyper(tl);
- len = fxdr_unsigned(int, *(tl + 2));
- if (len <= 0 || len > NFS_MAXNAMLEN) {
- error = EBADRPC;
- m_freem(mrep);
- 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 += 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_fileno = (int)fileno;
- dp->d_namlen = len;
- dp->d_reclen = tlen + DIRHDSIZ;
- dp->d_type = DT_UNKNOWN;
- blksiz += dp->d_reclen;
- if (blksiz == DIRBLKSIZ)
- blksiz = 0;
- uiop->uio_offset += DIRHDSIZ;
- uiop->uio_resid -= DIRHDSIZ;
- uiop->uio_iov->iov_base += DIRHDSIZ;
- uiop->uio_iov->iov_len -= DIRHDSIZ;
- cnp->cn_nameptr = uiop->uio_iov->iov_base;
- cnp->cn_namelen = len;
- nfsm_mtouio(uiop, len);
- cp = uiop->uio_iov->iov_base;
- tlen -= len;
- *cp = '\0';
- uiop->uio_iov->iov_base += tlen;
- uiop->uio_iov->iov_len -= tlen;
- uiop->uio_offset += tlen;
- uiop->uio_resid -= tlen;
- } else
- nfsm_adv(nfsm_rndup(len));
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- if (bigenough) {
- cookie.nfsuquad[0] = *tl++;
- cookie.nfsuquad[1] = *tl++;
- } else
- tl += 2;
-
- /*
- * Since the attributes are before the file handle
- * (sigh), we must skip over the attributes and then
- * come back and get them.
- */
- attrflag = fxdr_unsigned(int, *tl);
- if (attrflag) {
- dpossav1 = dpos;
- mdsav1 = md;
- nfsm_adv(NFSX_V3FATTR);
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- doit = fxdr_unsigned(int, *tl);
- if (doit) {
- nfsm_getfh(fhp, fhsize, 1);
- if (NFS_CMPFH(dnp, fhp, fhsize)) {
- VREF(vp);
- newvp = vp;
- np = dnp;
- } else {
- error = nfs_nget(vp->v_mount, fhp,
- fhsize, &np);
- if (error)
- doit = 0;
- else
- newvp = NFSTOV(np);
- }
- }
- if (doit && bigenough) {
- dpossav2 = dpos;
- dpos = dpossav1;
- mdsav2 = md;
- md = mdsav1;
- nfsm_loadattr(newvp, (struct vattr *)0);
- dpos = dpossav2;
- md = mdsav2;
- dp->d_type =
- IFTODT(VTTOIF(np->n_vattr.va_type));
- ndp->ni_vp = newvp;
- cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
- }
- } else {
- /* Just skip over the file handle */
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- i = fxdr_unsigned(int, *tl);
- nfsm_adv(nfsm_rndup(i));
- }
- if (newvp != NULLVP) {
- if (newvp == vp)
- vrele(newvp);
- else
- vput(newvp);
- newvp = NULLVP;
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- more_dirs = fxdr_unsigned(int, *tl);
- }
- /*
- * If at end of rpc data, get the eof boolean
- */
- if (!more_dirs) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- more_dirs = (fxdr_unsigned(int, *tl) == 0);
- }
- m_freem(mrep);
- }
- /*
- * 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 += 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! readdirplusrpc resid > 0\n");
- cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
- *cookiep = cookie;
- }
-nfsmout:
- if (newvp != NULLVP) {
- if (newvp == vp)
- vrele(newvp);
- else
- vput(newvp);
- newvp = NULLVP;
- }
- 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
-nfs_sillyrename(dvp, vp, cnp)
- struct vnode *dvp, *vp;
- struct componentname *cnp;
-{
- register 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
- MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
- M_NFSREQ, M_WAITOK);
- sp->s_cred = crdup(cnp->cn_cred);
- sp->s_dvp = dvp;
- 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 (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
- cnp->cn_thread, (struct nfsnode **)0) == 0) {
- sp->s_name[4]++;
- if (sp->s_name[4] > 'z') {
- error = EINVAL;
- goto bad;
- }
- }
- error = nfs_renameit(dvp, cnp, sp);
- if (error)
- goto bad;
- error = nfs_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
-nfs_lookitup(dvp, name, len, cred, td, npp)
- register struct vnode *dvp;
- const char *name;
- int len;
- struct ucred *cred;
- struct thread *td;
- struct nfsnode **npp;
-{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- struct vnode *newvp = (struct vnode *)0;
- struct nfsnode *np, *dnp = VTONFS(dvp);
- caddr_t bpos, dpos, cp2;
- int error = 0, fhlen, attrflag;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- nfsfh_t *nfhp;
- int v3 = NFS_ISV3(dvp);
-
- nfsstats.rpccnt[NFSPROC_LOOKUP]++;
- nfsm_reqhead(dvp, NFSPROC_LOOKUP,
- NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(name, len, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_LOOKUP, td, cred);
- if (npp && !error) {
- nfsm_getfh(nfhp, fhlen, v3);
- if (*npp) {
- 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);
- if (error) {
- m_freem(mrep);
- return (error);
- }
- newvp = NFSTOV(np);
- }
- if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- if (!attrflag && *npp == NULL) {
- m_freem(mrep);
- if (newvp == dvp)
- vrele(newvp);
- else
- vput(newvp);
- return (ENOENT);
- }
- } else
- nfsm_loadattr(newvp, (struct vattr *)0);
- }
- nfsm_reqdone;
- 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
-nfs_commit(vp, offset, cnt, cred, td)
- struct vnode *vp;
- u_quad_t offset;
- int cnt;
- struct ucred *cred;
- struct thread *td;
-{
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1, t2;
- register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- caddr_t bpos, dpos, cp2;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-
- if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
- return (0);
- nfsstats.rpccnt[NFSPROC_COMMIT]++;
- nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
- nfsm_fhtom(vp, 1);
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- txdr_hyper(offset, tl);
- tl += 2;
- *tl = txdr_unsigned(cnt);
- nfsm_request(vp, NFSPROC_COMMIT, td, cred);
- nfsm_wcc_data(vp, wccflag);
- if (!error) {
- nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
- if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
- NFSX_V3WRITEVERF)) {
- bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
- NFSX_V3WRITEVERF);
- error = NFSERR_STALEWRITEVERF;
- }
- }
- nfsm_reqdone;
- 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
-nfs_strategy(ap)
- struct vop_strategy_args *ap;
-{
- register struct buf *bp = ap->a_bp;
- struct ucred *cr;
- struct thread *td;
- int error = 0;
-
- KASSERT(!(bp->b_flags & B_DONE), ("nfs_strategy: buffer %p unexpectedly marked B_DONE", bp));
- KASSERT(BUF_REFCNT(bp) > 0, ("nfs_strategy: buffer %p not locked", bp));
-
- if (bp->b_flags & B_PHYS)
- panic("nfs physio");
-
- if (bp->b_flags & B_ASYNC)
- td = (struct thread *)0;
- else
- td = curthread; /* XXX */
-
- 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(bp, NOCRED, td))
- error = nfs_doio(bp, cr, td);
- return (error);
-}
-
-/*
- * fsync vnode op. Just call nfs_flush() with commit == 1.
- */
-/* ARGSUSED */
-static int
-nfs_fsync(ap)
- struct vop_fsync_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode * a_vp;
- struct ucred * a_cred;
- int a_waitfor;
- struct thread * a_td;
- } */ *ap;
-{
-
- return (nfs_flush(ap->a_vp, ap->a_cred, 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
-nfs_flush(vp, cred, waitfor, td, commit)
- register struct vnode *vp;
- struct ucred *cred;
- int waitfor;
- struct thread *td;
- int commit;
-{
- register struct nfsnode *np = VTONFS(vp);
- register struct buf *bp;
- register int i;
- struct buf *nbp;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- int s, 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;
-
- 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) {
- s = splbio();
- /*
- * Count up how many buffers waiting for a commit.
- */
- bveccount = 0;
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if (BUF_REFCNT(bp) == 0 &&
- (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 nfs_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 (bvec != NULL && bvec != bvec_on_stack)
- free(bvec, M_TEMP);
- if (bveccount > NFS_COMMITBVECSIZ) {
- bvec = (struct buf **)
- malloc(bveccount * sizeof(struct buf *),
- M_TEMP, M_NOWAIT);
- if (bvec == NULL) {
- bvec = bvec_on_stack;
- bvecsize = NFS_COMMITBVECSIZ;
- } else
- bvecsize = bveccount;
- } else {
- bvec = bvec_on_stack;
- bvecsize = NFS_COMMITBVECSIZ;
- }
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if (bvecpos >= bvecsize)
- break;
- if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) !=
- (B_DELWRI | B_NEEDCOMMIT) ||
- BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
- continue;
- 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;
- bp->b_flags |= B_WRITEINPROG;
- vfs_busy_pages(bp, 1);
-
- /*
- * 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_vnbufs);
-
- /*
- * 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;
- }
- splx(s);
- }
- 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 = nfs_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 = nfs_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_WRITEINPROG | 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
- */
- s = splbio();
- vp->v_numoutput++;
- bp->b_flags |= B_ASYNC;
- bundirty(bp);
- bp->b_flags &= ~B_DONE;
- bp->b_ioflags &= ~BIO_ERROR;
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- splx(s);
- bufdone(bp);
- }
- }
- }
-
- /*
- * Start/do any write(s) that are required.
- */
-loop:
- s = splbio();
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
- if (waitfor != MNT_WAIT || passone)
- continue;
- error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL,
- "nfsfsync", slpflag, slptimeo);
- splx(s);
- if (error == 0)
- panic("nfs_fsync: inconsistent lock");
- if (error == ENOLCK)
- goto loop;
- if (nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
- error = EINTR;
- goto done;
- }
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- goto loop;
- }
- if ((bp->b_flags & B_DELWRI) == 0)
- panic("nfs_fsync: not dirty");
- if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) {
- BUF_UNLOCK(bp);
- continue;
- }
- bremfree(bp);
- if (passone || !commit)
- bp->b_flags |= B_ASYNC;
- else
- bp->b_flags |= B_ASYNC | B_WRITEINPROG;
- splx(s);
- BUF_WRITE(bp);
- goto loop;
- }
- splx(s);
- if (passone) {
- passone = 0;
- goto again;
- }
- if (waitfor == MNT_WAIT) {
- while (vp->v_numoutput) {
- vp->v_flag |= VBWAIT;
- error = tsleep((caddr_t)&vp->v_numoutput,
- slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
- if (error) {
- if (nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
- error = EINTR;
- goto done;
- }
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- }
- if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) && commit) {
- goto loop;
- }
- }
- 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
-nfs_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
-{
-
- return (nfs_dolock(ap));
-}
-
-/*
- * Print out the contents of an nfsnode.
- */
-static int
-nfs_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
-
- printf("tag VT_NFS, fileid %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*).
- * B_WRITEINPROG isn't set unless the force flag is one and it
- * handles the B_NEEDCOMMIT flag.
- * We set B_CACHE if this is a VMIO buffer.
- */
-int
-nfs_writebp(bp, force, td)
- register struct buf *bp;
- int force;
- struct thread *td;
-{
- int s;
- int oldflags = bp->b_flags;
-#if 0
- int retv = 1;
- off_t off;
-#endif
-
- if (BUF_REFCNT(bp) == 0)
- panic("bwrite: buffer is not locked???");
-
- 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;
-
- bp->b_vp->v_numoutput++;
- curthread->td_proc->p_stats->p_ru.ru_oublock++;
- splx(s);
-
- /*
- * Note: to avoid loopback deadlocks, we do not
- * assign b_runningbufspace.
- */
- vfs_busy_pages(bp, 1);
-
- if (force)
- bp->b_flags |= B_WRITEINPROG;
- BUF_KERNPROC(bp);
- BUF_STRATEGY(bp);
-
- if( (oldflags & B_ASYNC) == 0) {
- int rtval = bufwait(bp);
-
- if (oldflags & B_DELWRI) {
- s = splbio();
- reassignbuf(bp, bp->b_vp);
- splx(s);
- }
-
- brelse(bp);
- return (rtval);
- }
-
- return (0);
-}
-
-/*
- * nfs special file access vnode op.
- * Essentially just get vattr and then imitate iaccess() since the device is
- * local to the client.
- */
-static int
-nfsspec_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vattr *vap;
- register gid_t *gp;
- register struct ucred *cred = ap->a_cred;
- struct vnode *vp = ap->a_vp;
- mode_t mode = ap->a_mode;
- struct vattr vattr;
- register int i;
- int error;
-
- /*
- * 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 ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- switch (vp->v_type) {
- case VREG:
- case VDIR:
- case VLNK:
- return (EROFS);
- default:
- break;
- }
- }
- /*
- * If you're the super-user,
- * you always get access.
- */
- if (cred->cr_uid == 0)
- return (0);
- vap = &vattr;
- error = VOP_GETATTR(vp, vap, cred, ap->a_td);
- if (error)
- return (error);
- /*
- * Access check is based on only one of owner, group, public.
- * If not owner, then check group. If not a member of the
- * group, then check public access.
- */
- if (cred->cr_uid != vap->va_uid) {
- mode >>= 3;
- gp = cred->cr_groups;
- for (i = 0; i < cred->cr_ngroups; i++, gp++)
- if (vap->va_gid == *gp)
- goto found;
- mode >>= 3;
-found:
- ;
- }
- error = (vap->va_mode & mode) == mode ? 0 : EACCES;
- return (error);
-}
-
-/*
- * Read wrapper for special devices.
- */
-static int
-nfsspec_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct nfsnode *np = VTONFS(ap->a_vp);
-
- /*
- * Set access flag.
- */
- np->n_flag |= NACC;
- getnanotime(&np->n_atim);
- return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
-}
-
-/*
- * Write wrapper for special devices.
- */
-static int
-nfsspec_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct nfsnode *np = VTONFS(ap->a_vp);
-
- /*
- * Set update flag.
- */
- np->n_flag |= NUPD;
- getnanotime(&np->n_mtim);
- return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
-}
-
-/*
- * Close wrapper for special devices.
- *
- * Update the times on the nfsnode then do device close.
- */
-static int
-nfsspec_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- struct vattr vattr;
-
- if (np->n_flag & (NACC | NUPD)) {
- np->n_flag |= NCHG;
- if (vp->v_usecount == 1 &&
- (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
- VATTR_NULL(&vattr);
- if (np->n_flag & NACC)
- vattr.va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vattr.va_mtime = np->n_mtim;
- (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_td);
- }
- }
- return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
-}
-
-/*
- * Read wrapper for fifos.
- */
-static int
-nfsfifo_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct nfsnode *np = VTONFS(ap->a_vp);
-
- /*
- * Set access flag.
- */
- np->n_flag |= NACC;
- getnanotime(&np->n_atim);
- return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
-}
-
-/*
- * Write wrapper for fifos.
- */
-static int
-nfsfifo_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct nfsnode *np = VTONFS(ap->a_vp);
-
- /*
- * Set update flag.
- */
- np->n_flag |= NUPD;
- getnanotime(&np->n_mtim);
- return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
-}
-
-/*
- * Close wrapper for fifos.
- *
- * Update the times on the nfsnode then do fifo close.
- */
-static int
-nfsfifo_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- struct vattr vattr;
- struct timespec ts;
-
- if (np->n_flag & (NACC | NUPD)) {
- getnanotime(&ts);
- if (np->n_flag & NACC)
- np->n_atim = ts;
- if (np->n_flag & NUPD)
- np->n_mtim = ts;
- np->n_flag |= NCHG;
- if (vp->v_usecount == 1 &&
- (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
- VATTR_NULL(&vattr);
- if (np->n_flag & NACC)
- vattr.va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vattr.va_mtime = np->n_mtim;
- (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_td);
- }
- }
- return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
-}
diff --git a/sys/nfs/nfsdiskless.h b/sys/nfs/nfsdiskless.h
deleted file mode 100644
index 487e0bf..0000000
--- a/sys/nfs/nfsdiskless.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 1991, 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.
- * 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.
- *
- * @(#)nfsdiskless.h 8.2 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#ifndef _NFS_NFSDISKLESS_H_
-#define _NFS_NFSDISKLESS_H_
-
-/*
- * Structure that must be initialized for a diskless nfs client.
- * This structure is used by nfs_mountroot() to set up the root vnode,
- * and to do a partial ifconfig(8) and route(8) so that the critical net
- * interface can communicate with the server.
- * The primary bootstrap is expected to fill in the appropriate fields before
- * starting the kernel. Whether or not the swap area is nfs mounted is
- * determined by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
- * Currently only works for AF_INET protocols.
- * NB: All fields are stored in net byte order to avoid hassles with
- * client/server byte ordering differences.
- */
-
-/*
- * I have defined a new structure that can handle an NFS Version 3 file handle
- * but the kernel still expects the old Version 2 one to be provided. The
- * changes required in nfs_vfsops.c for using the new are documented there in
- * comments. (I felt that breaking network booting code by changing this
- * structure would not be prudent at this time, since almost all servers are
- * still Version 2 anyhow.)
- */
-struct nfsv3_diskless {
- struct ifaliasreq myif; /* Default interface */
- struct sockaddr_in mygateway; /* Default gateway */
- struct nfs_args swap_args; /* Mount args for swap file */
- int swap_fhsize; /* Size of file handle */
- u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
- struct sockaddr_in swap_saddr; /* Address of swap server */
- char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
- int swap_nblks; /* Size of server swap file */
- struct ucred swap_ucred; /* Swap credentials */
- struct nfs_args root_args; /* Mount args for root fs */
- int root_fhsize; /* Size of root file handle */
- u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
- struct sockaddr_in root_saddr; /* Address of root server */
- char root_hostnam[MNAMELEN]; /* Host name for mount pt */
- long root_time; /* Timestamp of root fs */
- char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
-};
-
-/*
- * Old arguments to mount NFS
- */
-struct onfs_args {
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
-};
-
-struct nfs_diskless {
- struct ifaliasreq myif; /* Default interface */
- struct sockaddr_in mygateway; /* Default gateway */
- struct onfs_args swap_args; /* Mount args for swap file */
- u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
- struct sockaddr_in swap_saddr; /* Address of swap server */
- char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
- int swap_nblks; /* Size of server swap file */
- struct ucred swap_ucred; /* Swap credentials */
- struct onfs_args root_args; /* Mount args for root fs */
- u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
- struct sockaddr_in root_saddr; /* Address of root server */
- char root_hostnam[MNAMELEN]; /* Host name for mount pt */
- long root_time; /* Timestamp of root fs */
- char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
-};
-
-#endif
diff --git a/sys/nfs/nfsmount.h b/sys/nfs/nfsmount.h
deleted file mode 100644
index d6f8a8b..0000000
--- a/sys/nfs/nfsmount.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.
- * 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.
- *
- * @(#)nfsmount.h 8.3 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#ifndef _NFS_NFSMOUNT_H_
-#define _NFS_NFSMOUNT_H_
-
-/*
- * Mount structure.
- * One allocated on every NFS mount.
- * Holds NFS specific information for mount.
- */
-struct nfsmount {
- int nm_flag; /* Flags for soft/hard... */
- int nm_state; /* Internal state flags */
- struct mount *nm_mountp; /* Vfs structure for this filesystem */
- int nm_numgrps; /* Max. size of groupslist */
- u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
- int nm_fhsize; /* Size of root file handle */
- struct socket *nm_so; /* Rpc socket */
- int nm_sotype; /* Type of socket */
- int nm_soproto; /* and protocol */
- int nm_soflags; /* pr_flags for socket protocol */
- struct sockaddr *nm_nam; /* Addr of server */
- int nm_timeo; /* Init timer for NFSMNT_DUMBTIMR */
- int nm_retry; /* Max retries */
- int nm_srtt[4]; /* Timers for rpcs */
- int nm_sdrtt[4];
- int nm_sent; /* Request send count */
- int nm_cwnd; /* Request send window */
- int nm_timeouts; /* Request timeouts */
- int nm_deadthresh; /* Threshold of timeouts-->dead server*/
- int nm_rsize; /* Max size of read rpc */
- int nm_wsize; /* Max size of write rpc */
- int nm_readdirsize; /* Size of a readdir rpc */
- int nm_readahead; /* Num. of blocks to readahead */
- int nm_leaseterm; /* Term (sec) for NQNFS lease */
- int nm_acdirmin; /* Directory attr cache min lifetime */
- int nm_acdirmax; /* Directory attr cache max lifetime */
- int nm_acregmin; /* Reg file attr cache min lifetime */
- int nm_acregmax; /* Reg file attr cache max lifetime */
- TAILQ_HEAD(timhd, nfsnode) nm_timerhead; /* Head of lease timer queue */
- struct vnode *nm_inprog; /* Vnode in prog by nqnfs_clientd() */
- uid_t nm_authuid; /* Uid for authenticator */
- int nm_authtype; /* Authenticator type */
- int nm_authlen; /* and length */
- char *nm_authstr; /* Authenticator string */
- char *nm_verfstr; /* and the verifier */
- int nm_verflen;
- u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
- NFSKERBKEY_T nm_key; /* and the session key */
- int nm_numuids; /* Number of nfsuid mappings */
- TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
- LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
- TAILQ_HEAD(, buf) nm_bufq; /* async io buffer queue */
- short nm_bufqlen; /* number of buffers in queue */
- short nm_bufqwant; /* process wants to add to the queue */
- int nm_bufqiods; /* number of iods processing queue */
- u_int64_t nm_maxfilesize; /* maximum file size */
-};
-
-#if defined(_KERNEL)
-/*
- * Convert mount ptr to nfsmount ptr.
- */
-#define VFSTONFS(mp) ((struct nfsmount *)((mp)->mnt_data))
-
-#endif
-
-#endif
diff --git a/sys/nfs/nfsproto.h b/sys/nfs/nfsproto.h
index cbb2832..8f62ab1 100644
--- a/sys/nfs/nfsproto.h
+++ b/sys/nfs/nfsproto.h
@@ -169,14 +169,8 @@
#define NFSPROC_FSINFO 19
#define NFSPROC_PATHCONF 20
#define NFSPROC_COMMIT 21
-
-/* And leasing (nqnfs) procedure numbers (must be last) */
-#define NQNFSPROC_GETLEASE 22
-#define NQNFSPROC_VACATED 23
-#define NQNFSPROC_EVICTED 24
-
-#define NFSPROC_NOOP 25
-#define NFS_NPROCS 26
+#define NFSPROC_NOOP 22
+#define NFS_NPROCS 23
/* Actual Version 2 procedure numbers */
#define NFSV2PROC_NULL 0
@@ -226,17 +220,6 @@
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
-/* Conversion macros */
-#define vtonfsv2_mode(t,m) \
- txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
- MAKEIMODE((t), (m)))
-#define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS)
-#define nfstov_mode(a) (fxdr_unsigned(u_int32_t, (a)) & ALLPERMS)
-#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))])
-#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
-#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_int32_t,(a))&0x7]
-#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_int32_t,(a))&0x7]
-
/* File types */
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
NFSOCK=6, NFFIFO=7 } nfstype;
diff --git a/sys/nfs/nfsrtt.h b/sys/nfs/nfsrtt.h
deleted file mode 100644
index 4473086..0000000
--- a/sys/nfs/nfsrtt.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 1992, 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.
- * 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.
- *
- * @(#)nfsrtt.h 8.2 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#ifndef _NFS_NFSRTT_H_
-#define _NFS_NFSRTT_H_
-
-/*
- * Definitions for performance monitor.
- * The client and server logging are turned on by setting the global
- * constant "nfsrtton" to 1.
- */
-#define NFSRTTLOGSIZ 128
-
-/*
- * Circular log of client side rpc activity. Each log entry is for one
- * rpc filled in upon completion. (ie. in order of completion)
- * The "pos" is the table index for the "next" entry, therefore the
- * list goes from nfsrtt.rttl[pos] --> nfsrtt.rttl[pos - 1] in
- * chronological order of completion.
- */
-struct nfsrtt {
- int pos; /* Position in array for next entry */
- struct rttl {
- u_int32_t proc; /* NFS procedure number */
- int rtt; /* Measured round trip time */
- int rto; /* Round Trip Timeout */
- int sent; /* # rpcs in progress */
- int cwnd; /* Send window */
- int srtt; /* Ave Round Trip Time */
- int sdrtt; /* Ave mean deviation of RTT */
- fsid_t fsid; /* Fsid for mount point */
- struct timeval tstamp; /* Timestamp of log entry */
- } rttl[NFSRTTLOGSIZ];
-};
-
-/*
- * And definitions for server side performance monitor.
- * The log organization is the same as above except it is filled in at the
- * time the server sends the rpc reply.
- */
-
-/*
- * Bits for the flags field.
- */
-#define DRT_NQNFS 0x01 /* Rpc used Nqnfs protocol */
-#define DRT_TCP 0x02 /* Client used TCP transport */
-#define DRT_CACHEREPLY 0x04 /* Reply was from recent request cache */
-#define DRT_CACHEDROP 0x08 /* Rpc request dropped, due to recent reply */
-#define DRT_NFSV3 0x10 /* Rpc used NFS Version 3 */
-
-/*
- * Server log structure
- * NB: ipadr == INADDR_ANY indicates a client using a non IP protocol.
- * (ISO perhaps?)
- */
-struct nfsdrt {
- int pos; /* Position of next log entry */
- struct drt {
- int flag; /* Bits as defined above */
- u_int32_t proc; /* NFS procedure number */
- u_int32_t ipadr; /* IP address of client */
- int resptime; /* Response time (usec) */
- struct timeval tstamp; /* Timestamp of log entry */
- } drt[NFSRTTLOGSIZ];
-};
-
-#endif
diff --git a/sys/nfs/nfsrvcache.h b/sys/nfs/nfsrvcache.h
deleted file mode 100644
index eec5850..0000000
--- a/sys/nfs/nfsrvcache.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- * 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.
- *
- * @(#)nfsrvcache.h 8.3 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#ifndef _NFS_NFSRVCACHE_H_
-#define _NFS_NFSRVCACHE_H_
-
-#include <sys/queue.h>
-
-/*
- * Definitions for the server recent request cache
- */
-
-#define NFSRVCACHESIZ 64
-
-struct nfsrvcache {
- TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */
- LIST_ENTRY(nfsrvcache) rc_hash; /* Hash chain */
- u_int32_t rc_xid; /* rpc id number */
- union {
- struct mbuf *ru_repmb; /* Reply mbuf list OR */
- int ru_repstat; /* Reply status */
- } rc_un;
- union nethostaddr rc_haddr; /* Host address */
- u_int32_t rc_proc; /* rpc proc number */
- u_char rc_state; /* Current state of request */
- u_char rc_flag; /* Flag bits */
-};
-
-#define rc_reply rc_un.ru_repmb
-#define rc_status rc_un.ru_repstat
-#define rc_inetaddr rc_haddr.had_inetaddr
-#define rc_nam rc_haddr.had_nam
-
-/* Cache entry states */
-#define RC_UNUSED 0
-#define RC_INPROG 1
-#define RC_DONE 2
-
-/* Return values */
-#define RC_DROPIT 0
-#define RC_REPLY 1
-#define RC_DOIT 2
-#define RC_CHECKIT 3
-
-/* Flag bits */
-#define RC_LOCKED 0x01
-#define RC_WANTED 0x02
-#define RC_REPSTATUS 0x04
-#define RC_REPMBUF 0x08
-#define RC_NQNFS 0x10
-#define RC_INETADDR 0x20
-#define RC_NAM 0x40
-
-#endif
diff --git a/sys/nfs/nfsv2.h b/sys/nfs/nfsv2.h
deleted file mode 100644
index 6f8f85e..0000000
--- a/sys/nfs/nfsv2.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- * 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.
- *
- * @(#)nfsv2.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD$
- */
-
-#include <nfs/nfsproto.h>
diff --git a/sys/nfs/nlminfo.h b/sys/nfs/nlminfo.h
deleted file mode 100644
index 79c6e17..0000000
--- a/sys/nfs/nlminfo.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved.
- * 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. Berkeley Software Design Inc's name may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``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 BERKELEY SOFTWARE DESIGN INC 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.
- *
- * from BSDI nlminfo.h,v 2.1 1998/03/18 01:30:38 don Exp
- * $FreeBSD$
- */
-
-/*
- * Misc NLM informationi, some needed for the master lockd process, and some
- * needed by every process doing nlm based locking.
- */
-struct nlminfo {
- /* these are used by any process doing nlm locking */
- int msg_seq; /* sequence counter for lock requests */
- int retcode; /* return code for lock requests */
- int set_getlk_pid;
- int getlk_pid;
- struct timeval pid_start; /* process starting time */
-};
-
-extern void nlminfo_release __P((struct proc *p));
-
diff --git a/sys/nfs/nqnfs.h b/sys/nfs/nqnfs.h
deleted file mode 100644
index ce8d692..0000000
--- a/sys/nfs/nqnfs.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 1992, 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.
- * 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.
- *
- * @(#)nqnfs.h 8.3 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#ifndef _NFS_NQNFS_H_
-#define _NFS_NQNFS_H_
-
-/*
- * Definitions for NQNFS (Not Quite NFS) cache consistency protocol.
- */
-
-/* Tunable constants */
-#define NQ_CLOCKSKEW 3 /* Clock skew factor (sec) */
-#define NQ_WRITESLACK 5 /* Delay for write cache flushing */
-#define NQ_MAXLEASE 60 /* Max lease duration (sec) */
-#define NQ_MINLEASE 5 /* Min lease duration (sec) */
-#define NQ_DEFLEASE 30 /* Default lease duration (sec) */
-#define NQ_RENEWAL 3 /* Time before expiry (sec) to renew */
-#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
-#define NQ_MAXNUMLEASE 2048 /* Upper bound on number of server leases */
-#define NQ_DEADTHRESH NQ_NEVERDEAD /* Default nm_deadthresh */
-#define NQ_NEVERDEAD 9 /* Greater than max. nm_timeouts */
-#define NQLCHSZ 256 /* Server hash table size */
-
-#define NQNFS_PROG 300105 /* As assigned by Sun */
-#define NQNFS_VER3 3
-#define NQNFS_EVICTSIZ 156 /* Size of eviction request in bytes */
-
-#if defined(_KERNEL)
-/*
- * Definitions used for saving the "last lease expires" time in Non-volatile
- * RAM on the server. The default definitions below assume that NOVRAM is not
- * available.
- */
-#ifdef HASNVRAM
-# undef HASNVRAM
-#endif
-#define NQSTORENOVRAM(t)
-#define NQLOADNOVRAM(t)
-
-/*
- * Defn and structs used on the server to maintain state for current leases.
- * The list of host(s) that hold the lease are kept as nqhost structures.
- * The first one lives in nqlease and any others are held in a linked
- * list of nqm structures hanging off of nqlease.
- *
- * Each nqlease structure is chained into two lists. The first is a list
- * ordered by increasing expiry time for nqsrv_timer() and the second is a chain
- * hashed on lc_fh.
- */
-#define LC_MOREHOSTSIZ 10
-
-struct nqhost {
- u_int16_t lph_flag;
- u_int16_t lph_port;
- struct nfssvc_sock *lph_slp;
-
- union {
- struct {
- union nethostaddr udp_haddr;
- } un_udp;
- struct {
- int dummy;
- } un_conn;
- } lph_un;
-};
-#define lph_haddr lph_un.un_udp.udp_haddr
-#define lph_inetaddr lph_un.un_udp.udp_haddr.had_inetaddr
-
-struct nqlease {
- LIST_ENTRY(nqlease) lc_hash; /* Fhandle hash list */
- TAILQ_ENTRY(nqlease) lc_timer; /* Timer queue list */
- time_t lc_expiry; /* Expiry time (sec) */
- struct nqhost lc_host; /* Host that got lease */
- struct nqm *lc_morehosts; /* Other hosts that share read lease */
- fsid_t lc_fsid; /* Fhandle */
- char lc_fiddata[MAXFIDSZ];
- struct vnode *lc_vp; /* Soft reference to associated vnode */
-};
-#define lc_flag lc_host.lph_flag
-
-/* lc_flag bits */
-#define LC_VALID 0x0001 /* Host address valid */
-#define LC_WRITE 0x0002 /* Write cache */
-#define LC_NONCACHABLE 0x0004 /* Non-cachable lease */
-#define LC_LOCKED 0x0008 /* Locked */
-#define LC_WANTED 0x0010 /* Lock wanted */
-#define LC_EXPIREDWANTED 0x0020 /* Want lease when expired */
-#define LC_UDP 0x0040 /* Host address for udp socket */
-/* 0x0080 free */
-#define LC_LOCAL 0x0100 /* Host is server */
-#define LC_VACATED 0x0200 /* Host has vacated lease */
-#define LC_WRITTEN 0x0400 /* Recently wrote to the leased file */
-#define LC_SREF 0x0800 /* Holds a nfssvc_sock reference */
-
-struct nqm {
- struct nqm *lpm_next;
- struct nqhost lpm_hosts[LC_MOREHOSTSIZ];
-};
-
-/*
- * Special value for slp for local server calls.
- */
-#define NQLOCALSLP ((struct nfssvc_sock *) -1)
-
-/*
- * Server side macros.
- */
-#define nqsrv_getl(v, l) \
- (void) nqsrv_getlease((v), &nfsd->nd_duration, \
- ((nfsd->nd_flag & ND_LEASE) ? (nfsd->nd_flag & ND_LEASE) : \
- ((l) | ND_CHECK)), \
- slp, td, nfsd->nd_nam, &cache, &frev, cred)
-
-/*
- * Client side macros that check for a valid lease.
- */
-#define NQNFS_CKINVALID(v, n, f) \
- ((time_second > (n)->n_expiry && \
- VFSTONFS((v)->v_mount)->nm_timeouts < VFSTONFS((v)->v_mount)->nm_deadthresh) \
- || ((f) == ND_WRITE && ((n)->n_flag & NQNFSWRITE) == 0))
-
-#define NQNFS_CKCACHABLE(v, f) \
- ((time_second <= VTONFS(v)->n_expiry || \
- VFSTONFS((v)->v_mount)->nm_timeouts >= VFSTONFS((v)->v_mount)->nm_deadthresh) \
- && (VTONFS(v)->n_flag & NQNFSNONCACHE) == 0 && \
- ((f) == ND_READ || (VTONFS(v)->n_flag & NQNFSWRITE)))
-
-#define NQNFS_NEEDLEASE(v, p) \
- (time_second > VTONFS(v)->n_expiry ? \
- ((VTONFS(v)->n_flag & NQNFSEVICTED) ? 0 : nqnfs_piggy[p]) : \
- (((time_second + NQ_RENEWAL) > VTONFS(v)->n_expiry && \
- nqnfs_piggy[p]) ? \
- ((VTONFS(v)->n_flag & NQNFSWRITE) ? \
- ND_WRITE : nqnfs_piggy[p]) : 0))
-
-/*
- * List head for timer queue.
- */
-extern TAILQ_HEAD(nqtimerhead, nqlease) nqtimerhead;
-
-/*
- * List head for the file handle hash table.
- */
-#define NQFHHASH(f) \
- (&nqfhhashtbl[(*((u_int32_t *)(f))) & nqfhhash])
-extern LIST_HEAD(nqfhhashhead, nqlease) *nqfhhashtbl;
-extern u_long nqfhhash;
-
-/*
- * Nqnfs return status numbers.
- */
-#define NQNFS_EXPIRED 500
-#define NQNFS_TRYLATER 501
-
-void nqnfs_lease_check __P((struct vnode *, struct thread *, struct ucred *, int));
-void nqnfs_lease_updatetime __P((int));
-int nqsrv_getlease __P((struct vnode *, u_int32_t *, int,
- struct nfssvc_sock *, struct thread *,
- struct sockaddr *, int *, u_quad_t *,
- struct ucred *));
-int nqnfs_getlease __P((struct vnode *,int,struct ucred *,struct thread *));
-int nqnfs_callback __P((struct nfsmount *,struct mbuf *,struct mbuf *,caddr_t));
-int nqnfs_clientd __P((struct nfsmount *,struct ucred *,struct nfsd_cargs *,int,caddr_t,struct thread *));
-struct nfsnode;
-void nqnfs_clientlease __P((struct nfsmount *, struct nfsnode *, int, int, time_t, u_quad_t));
-void nqnfs_serverd __P((void));
-int nqnfsrv_getlease __P((struct nfsrv_descript *, struct nfssvc_sock *, struct thread *, struct mbuf **));
-int nqnfsrv_vacated __P((struct nfsrv_descript *, struct nfssvc_sock *, struct thread *, struct mbuf **));
-#endif
-
-#endif
diff --git a/sys/nfs/rpcv2.h b/sys/nfs/rpcv2.h
index 525df09..977a8d3 100644
--- a/sys/nfs/rpcv2.h
+++ b/sys/nfs/rpcv2.h
@@ -53,8 +53,6 @@
#define RPCAUTH_NULL 0
#define RPCAUTH_UNIX 1
#define RPCAUTH_SHORT 2
-#define RPCAUTH_KERB4 4
-#define RPCAUTH_NQNFS 300000
#define RPCAUTH_MAXSIZ 400
#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
#define RPCAUTH_UNIXGIDS 16
@@ -101,43 +99,4 @@
#define RPCMNT_PATHLEN 1024
#define RPCPROG_NFS 100003
-/*
- * Structures used for RPCAUTH_KERB4.
- */
-struct nfsrpc_fullverf {
- u_int32_t t1;
- u_int32_t t2;
- u_int32_t w2;
-};
-
-struct nfsrpc_fullblock {
- u_int32_t t1;
- u_int32_t t2;
- u_int32_t w1;
- u_int32_t w2;
-};
-
-struct nfsrpc_nickverf {
- u_int32_t kind;
- struct nfsrpc_fullverf verf;
-};
-
-/*
- * and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these
- * constants, well then things will break in mount_nfs and nfsd.
- */
-#define RPCX_FULLVERF 12
-#define RPCX_FULLBLOCK 16
-#define RPCX_NICKVERF 16
-
-#ifdef NFSKERB
-XXX
-#else
-typedef u_char NFSKERBKEY_T[2];
-typedef u_char NFSKERBKEYSCHED_T[2];
-#endif
-#define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */
-#define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */
-#define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */
-#define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3]))))
#endif
diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c
index 063f77f..8d3ad2a 100644
--- a/sys/nfsclient/bootp_subr.c
+++ b/sys/nfsclient/bootp_subr.c
@@ -1,5 +1,3 @@
-/* $FreeBSD$ */
-
/*
* Copyright (c) 1995 Gordon Ross, Adam Glass
* Copyright (c) 1992 Regents of the University of California.
@@ -42,6 +40,9 @@
* $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include "opt_bootp.h"
#include <sys/param.h>
@@ -64,9 +65,9 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsdiskless.h>
-#include <nfs/krpc.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsdiskless.h>
+#include <nfsclient/krpc.h>
#include <nfs/xdr_subs.h>
@@ -207,38 +208,31 @@ struct bootpc_globalcontext {
#define DHCP_REQUEST 3
#define DHCP_ACK 5
-extern int nfs_diskless_valid;
-extern struct nfsv3_diskless nfsv3_diskless;
-
/* mountd RPC */
-static int md_mount(struct sockaddr_in *mdsin, char *path,
- u_char *fhp, int *fhsizep,
- struct nfs_args *args,struct thread *td);
-static int md_lookup_swap(struct sockaddr_in *mdsin,char *path,
- u_char *fhp, int *fhsizep,
- struct nfs_args *args,
- struct thread *td);
-static int setfs(struct sockaddr_in *addr, char *path, char *p);
-static int getdec(char **ptr);
-static char *substr(char *a,char *b);
-static void mountopts(struct nfs_args *args, char *p);
-static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
-static int xdr_int_decode(struct mbuf **ptr, int *iptr);
-static void print_in_addr(struct in_addr addr);
-static void print_sin_addr(struct sockaddr_in *addr);
-static void clear_sinaddr(struct sockaddr_in *sin);
-static
-struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx);
-static void bootpc_compose_query(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td);
+static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp,
+ int *fhsizep, struct nfs_args *args, struct thread *td);
+static int md_lookup_swap(struct sockaddr_in *mdsin, char *path,
+ u_char *fhp, int *fhsizep, struct nfs_args *args,
+ struct thread *td);
+static int setfs(struct sockaddr_in *addr, char *path, char *p);
+static int getdec(char **ptr);
+static char *substr(char *a, char *b);
+static void mountopts(struct nfs_args *args, char *p);
+static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
+static int xdr_int_decode(struct mbuf **ptr, int *iptr);
+static void print_in_addr(struct in_addr addr);
+static void print_sin_addr(struct sockaddr_in *addr);
+static void clear_sinaddr(struct sockaddr_in *sin);
+static struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx);
+static void bootpc_compose_query(struct bootpc_ifcontext *ifctx,
+ struct bootpc_globalcontext *gctx, struct thread *td);
static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
- struct bootp_packet *bp, int len, int tag);
+ struct bootp_packet *bp, int len, int tag);
static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
- unsigned char *start, int len, int tag);
+ unsigned char *start, int len, int tag);
#ifdef BOOTP_DEBUG
-void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma);
+void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma);
void bootpboot_p_ma(struct sockaddr *ma);
void bootpboot_p_rtentry(struct rtentry *rt);
void bootpboot_p_tree(struct radix_node *rn);
@@ -247,23 +241,21 @@ void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa);
void bootpboot_p_iflist(void);
#endif
-static int bootpc_call(struct bootpc_globalcontext *gctx,
- struct thread *td);
+static int bootpc_call(struct bootpc_globalcontext *gctx,
+ struct thread *td);
-static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td);
+static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
+ struct bootpc_globalcontext *gctx, struct thread *td);
-static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td);
+static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
+ struct bootpc_globalcontext *gctx, struct thread *td);
-static void bootpc_decode_reply(struct nfsv3_diskless *nd,
- struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx);
+static void bootpc_decode_reply(struct nfsv3_diskless *nd,
+ struct bootpc_ifcontext *ifctx,
+ struct bootpc_globalcontext *gctx);
-static int bootpc_received(struct bootpc_globalcontext *gctx,
- struct bootpc_ifcontext *ifctx);
+static int bootpc_received(struct bootpc_globalcontext *gctx,
+ struct bootpc_ifcontext *ifctx);
static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx);
static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx);
@@ -275,7 +267,7 @@ void bootpc_init(void);
* In order to have multiple active interfaces with address 0.0.0.0
* and be able to send data to a selected interface, we perform
* some tricks:
- *
+ *
* - The 'broadcast' address is different for each interface.
*
* - We temporarily add routing pointing 255.255.255.255 to the
@@ -285,9 +277,9 @@ void bootpc_init(void);
#ifdef BOOTP_DEBUG
void
-bootpboot_p_sa(struct sockaddr *sa,
- struct sockaddr *ma)
+bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma)
{
+
if (sa == NULL) {
printf("(sockaddr *) <null>");
return;
@@ -296,7 +288,7 @@ bootpboot_p_sa(struct sockaddr *sa,
case AF_INET:
{
struct sockaddr_in *sin;
-
+
sin = (struct sockaddr_in *) sa;
printf("inet ");
print_sin_addr(sin);
@@ -311,7 +303,7 @@ bootpboot_p_sa(struct sockaddr *sa,
{
struct sockaddr_dl *sli;
int i;
-
+
sli = (struct sockaddr_dl *) sa;
printf("link %.*s ", sli->sdl_nlen, sli->sdl_data);
for (i = 0; i < sli->sdl_alen; i++) {
@@ -326,10 +318,10 @@ bootpboot_p_sa(struct sockaddr *sa,
}
}
-
void
bootpboot_p_ma(struct sockaddr *ma)
{
+
if (ma == NULL) {
printf("<null>");
return;
@@ -337,10 +329,10 @@ bootpboot_p_ma(struct sockaddr *ma)
printf("%x", *(int *)ma);
}
-
void
bootpboot_p_rtentry(struct rtentry *rt)
{
+
bootpboot_p_sa(rt_key(rt), rt_mask(rt));
printf(" ");
bootpboot_p_ma(rt->rt_genmask);
@@ -352,10 +344,10 @@ bootpboot_p_rtentry(struct rtentry *rt)
printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit);
}
-
void
bootpboot_p_tree(struct radix_node *rn)
{
+
while (rn != NULL) {
if (rn->rn_bit < 0) {
if ((rn->rn_flags & RNF_ROOT) != 0) {
@@ -371,18 +363,18 @@ bootpboot_p_tree(struct radix_node *rn)
}
}
-
void
bootpboot_p_rtlist(void)
{
+
printf("Routing table:\n");
bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop);
}
-
void
bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
{
+
printf("%s%d flags %x, addr ",
ifp->if_name,
ifp->if_unit,
@@ -395,13 +387,12 @@ bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
printf("\n");
}
-
void
bootpboot_p_iflist(void)
{
struct ifnet *ifp;
struct ifaddr *ifa;
-
+
printf("Interface list:\n");
for (ifp = TAILQ_FIRST(&ifnet);
ifp != NULL;
@@ -415,10 +406,10 @@ bootpboot_p_iflist(void)
}
#endif /* defined(BOOTP_DEBUG) */
-
static void
clear_sinaddr(struct sockaddr_in *sin)
{
+
bzero(sin, sizeof(*sin));
sin->sin_len = sizeof(*sin);
sin->sin_family = AF_INET;
@@ -426,7 +417,6 @@ clear_sinaddr(struct sockaddr_in *sin)
sin->sin_port = 0;
}
-
static struct bootpc_ifcontext *
allocifctx(struct bootpc_globalcontext *gctx)
{
@@ -435,7 +425,7 @@ allocifctx(struct bootpc_globalcontext *gctx)
M_TEMP, M_WAITOK);
if (ifctx == NULL)
panic("Failed to allocate bootp interface context structure");
-
+
bzero(ifctx, sizeof(*ifctx));
ifctx->xid = gctx->xid;
#ifdef BOOTP_NO_DHCP
@@ -447,49 +437,48 @@ allocifctx(struct bootpc_globalcontext *gctx)
return ifctx;
}
-
static __inline int
bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx)
{
+
if (ifctx->state == IF_BOOTP_RESOLVED ||
ifctx->state == IF_DHCP_RESOLVED)
return 1;
return 0;
}
-
static __inline int
bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx)
{
+
if (ifctx->state == IF_BOOTP_UNRESOLVED ||
ifctx->state == IF_DHCP_UNRESOLVED)
return 1;
return 0;
}
-
static __inline int
bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx)
{
+
if (ifctx->state == IF_BOOTP_FAILED ||
ifctx->state == IF_DHCP_FAILED)
return 1;
return 0;
}
-
static int
bootpc_received(struct bootpc_globalcontext *gctx,
- struct bootpc_ifcontext *ifctx)
+ struct bootpc_ifcontext *ifctx)
{
unsigned char dhcpreplytype;
char *p;
+
/*
* Need timeout for fallback to less
* desirable alternative.
*/
-
/* This call used for the side effect (badopt flag) */
(void) bootpc_tag(&gctx->tmptag, &gctx->reply,
gctx->replylen,
@@ -498,14 +487,14 @@ bootpc_received(struct bootpc_globalcontext *gctx,
/* If packet is invalid, ignore it */
if (gctx->tmptag.badopt != 0)
return 0;
-
+
p = bootpc_tag(&gctx->tmptag, &gctx->reply,
gctx->replylen, TAG_DHCP_MSGTYPE);
if (p != NULL)
dhcpreplytype = *p;
else
dhcpreplytype = DHCP_NOMSG;
-
+
switch (ifctx->dhcpquerytype) {
case DHCP_DISCOVER:
if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */
@@ -520,10 +509,9 @@ bootpc_received(struct bootpc_globalcontext *gctx,
return 0;
case DHCP_NOMSG:
}
-
-
+
/* Ignore packet unless it gives us a root tag we didn't have */
-
+
if ((ifctx->state == IF_BOOTP_RESOLVED ||
(ifctx->dhcpquerytype == DHCP_DISCOVER &&
(ifctx->state == IF_DHCP_OFFERED ||
@@ -535,12 +523,10 @@ bootpc_received(struct bootpc_globalcontext *gctx,
gctx->replylen,
TAG_ROOT) == NULL))
return 0;
-
- bcopy(&gctx->reply,
- &ifctx->reply,
- gctx->replylen);
+
+ bcopy(&gctx->reply, &ifctx->reply, gctx->replylen);
ifctx->replylen = gctx->replylen;
-
+
/* XXX: Only reset if 'perfect' response */
if (ifctx->state == IF_BOOTP_UNRESOLVED)
ifctx->state = IF_BOOTP_RESOLVED;
@@ -553,8 +539,8 @@ bootpc_received(struct bootpc_globalcontext *gctx,
} else if (ifctx->state == IF_DHCP_OFFERED &&
ifctx->dhcpquerytype == DHCP_REQUEST)
ifctx->state = IF_DHCP_RESOLVED;
-
-
+
+
if (ifctx->dhcpquerytype == DHCP_DISCOVER &&
ifctx->state != IF_BOOTP_RESOLVED) {
p = bootpc_tag(&gctx->tmptag, &ifctx->reply,
@@ -566,7 +552,7 @@ bootpc_received(struct bootpc_globalcontext *gctx,
ifctx->gotdhcpserver = 0;
return 1;
}
-
+
ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
ifctx->replylen,
TAG_ROOT) != NULL);
@@ -580,8 +566,7 @@ bootpc_received(struct bootpc_globalcontext *gctx,
}
static int
-bootpc_call(struct bootpc_globalcontext *gctx,
- struct thread *td)
+bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
{
struct socket *so;
struct sockaddr_in *sin, dst;
@@ -597,14 +582,14 @@ bootpc_call(struct bootpc_globalcontext *gctx,
int gotrootpath;
int retry;
const char *s;
-
+
/*
* Create socket and set its recieve timeout.
*/
error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td);
if (error != 0)
goto out;
-
+
tv.tv_sec = 1;
tv.tv_usec = 0;
bzero(&sopt, sizeof(sopt));
@@ -612,11 +597,11 @@ bootpc_call(struct bootpc_globalcontext *gctx,
sopt.sopt_name = SO_RCVTIMEO;
sopt.sopt_val = &tv;
sopt.sopt_valsize = sizeof tv;
-
+
error = sosetopt(so, &sopt);
if (error != 0)
goto out;
-
+
/*
* Enable broadcast.
*/
@@ -641,7 +626,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
error = sosetopt(so, &sopt);
if (error != 0)
goto out;
-
+
/*
* Bind the local endpoint to a bootp client port.
*/
@@ -653,7 +638,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
printf("bind failed\n");
goto out;
}
-
+
/*
* Setup socket address for the server.
*/
@@ -661,7 +646,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
clear_sinaddr(sin);
sin->sin_addr.s_addr = INADDR_BROADCAST;
sin->sin_port = htons(IPPORT_BOOTPS);
-
+
/*
* Send it, repeatedly, until a reply is received,
* but delay each re-send by an increasing amount.
@@ -670,7 +655,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
timo = 0;
rtimo = 0;
for (;;) {
-
+
outstanding = 0;
gotrootpath = 0;
@@ -683,7 +668,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
TAG_ROOT) != NULL)
gotrootpath = 1;
}
-
+
for (ifctx = gctx->interfaces;
ifctx != NULL;
ifctx = ifctx->next) {
@@ -708,9 +693,9 @@ bootpc_call(struct bootpc_globalcontext *gctx,
ifctx->sentmsg = 0;
bootpc_compose_query(ifctx, gctx, td);
}
-
+
/* Send BOOTP request (or re-send). */
-
+
if (ifctx->sentmsg == 0) {
switch(ifctx->dhcpquerytype) {
case DHCP_DISCOVER:
@@ -736,7 +721,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
aio.iov_base = (caddr_t) &ifctx->call;
aio.iov_len = sizeof(ifctx->call);
-
+
auio.uio_iov = &aio;
auio.uio_iovcnt = 1;
auio.uio_segflg = UIO_SYSSPACE;
@@ -744,9 +729,9 @@ bootpc_call(struct bootpc_globalcontext *gctx,
auio.uio_offset = 0;
auio.uio_resid = sizeof(ifctx->call);
auio.uio_td = td;
-
+
/* Set netmask to 0.0.0.0 */
-
+
sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
clear_sinaddr(sin);
error = ifioctl(ifctx->so, SIOCSIFNETMASK,
@@ -755,7 +740,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
panic("bootpc_call:"
"set if netmask, error=%d",
error);
-
+
error = sosend(so, (struct sockaddr *) &dst,
&auio, NULL, NULL, 0, td);
if (error != 0) {
@@ -765,9 +750,9 @@ bootpc_call(struct bootpc_globalcontext *gctx,
/* XXX: Is this needed ? */
tsleep(&error, PZERO + 8, "bootpw", 10);
-
+
/* Set netmask to 255.0.0.0 */
-
+
sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
clear_sinaddr(sin);
sin->sin_addr.s_addr = htonl(0xff000000u);
@@ -777,15 +762,15 @@ bootpc_call(struct bootpc_globalcontext *gctx,
panic("bootpc_call:"
"set if netmask, error=%d",
error);
-
+
}
-
+
if (outstanding == 0 &&
(rtimo == 0 || time_second >= rtimo)) {
error = 0;
goto gotreply;
}
-
+
/* Determine new timeout. */
if (timo < MAX_RESEND_DELAY)
timo++;
@@ -794,7 +779,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
print_sin_addr(&dst);
printf("\n");
}
-
+
/*
* Wait for up to timo seconds for a reply.
* The socket receive timeout was set to 1 second.
@@ -803,7 +788,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
while (time_second < atimo) {
aio.iov_base = (caddr_t) &gctx->reply;
aio.iov_len = sizeof(gctx->reply);
-
+
auio.uio_iov = &aio;
auio.uio_iovcnt = 1;
auio.uio_segflg = UIO_SYSSPACE;
@@ -811,7 +796,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
auio.uio_offset = 0;
auio.uio_resid = sizeof(gctx->reply);
auio.uio_td = td;
-
+
rcvflg = 0;
error = soreceive(so, NULL, &auio,
NULL, NULL, &rcvflg);
@@ -822,7 +807,7 @@ bootpc_call(struct bootpc_globalcontext *gctx,
if (bootpc_ifctx_isresolved(ifctx) != 0 ||
bootpc_ifctx_isfailed(ifctx) != 0)
continue;
-
+
ifctx->call.secs = htons(gctx->secs);
}
if (error == EWOULDBLOCK)
@@ -830,27 +815,27 @@ bootpc_call(struct bootpc_globalcontext *gctx,
if (error != 0)
goto out;
len = sizeof(gctx->reply) - auio.uio_resid;
-
+
/* Do we have the required number of bytes ? */
if (len < BOOTP_MIN_LEN)
continue;
gctx->replylen = len;
-
+
/* Is it a reply? */
if (gctx->reply.op != BOOTP_REPLY)
continue;
-
+
/* Is this an answer to our query */
for (ifctx = gctx->interfaces;
ifctx != NULL;
ifctx = ifctx->next) {
if (gctx->reply.xid != ifctx->call.xid)
continue;
-
+
/* Same HW address size ? */
if (gctx->reply.hlen != ifctx->call.hlen)
continue;
-
+
/* Correct HW address ? */
if (bcmp(gctx->reply.chaddr,
ifctx->call.chaddr,
@@ -927,18 +912,18 @@ bootpc_call(struct bootpc_globalcontext *gctx,
ifctx->state = IF_DHCP_UNRESOLVED;
}
}
-
+
if (retry != 0)
continue;
-
+
if (gotrootpath != 0) {
gctx->gotrootpath = gotrootpath;
if (rtimo != 0 && time_second >= rtimo)
break;
}
} /* forever send/receive */
-
- /*
+
+ /*
* XXX: These are errors of varying seriousness being silently
* ignored
*/
@@ -968,22 +953,19 @@ bootpc_call(struct bootpc_globalcontext *gctx,
#endif
error = ETIMEDOUT;
goto out;
-
+
gotreply:
out:
soclose(so);
return error;
}
-
static int
bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td)
+ struct bootpc_globalcontext *gctx, struct thread *td)
{
struct sockaddr_in *sin;
int error;
-
struct ifreq *ireq;
struct socket *so;
struct ifaddr *ifa;
@@ -992,7 +974,7 @@ bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td);
if (error != 0)
panic("nfs_boot: socreate, error=%d", error);
-
+
ireq = &ifctx->ireq;
so = ifctx->so;
@@ -1009,23 +991,23 @@ bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
if (error != 0)
panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
-
+
/*
* Do enough of ifconfig(8) so that the chosen interface
* can talk to the servers. (just set the address)
*/
-
+
/* addr is 0.0.0.0 */
-
+
sin = (struct sockaddr_in *) &ireq->ifr_addr;
clear_sinaddr(sin);
error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
panic("bootpc_fakeup_interface: "
"set if addr, error=%d", error);
-
+
/* netmask is 255.0.0.0 */
-
+
sin = (struct sockaddr_in *) &ireq->ifr_addr;
clear_sinaddr(sin);
sin->sin_addr.s_addr = htonl(0xff000000u);
@@ -1033,51 +1015,49 @@ bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
if (error != 0)
panic("bootpc_fakeup_interface: set if netmask, error=%d",
error);
-
+
/* Broadcast is 255.255.255.255 */
-
+
sin = (struct sockaddr_in *)&ireq->ifr_addr;
clear_sinaddr(sin);
clear_sinaddr(&ifctx->broadcast);
sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr;
-
+
error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td);
if (error != 0)
panic("bootpc_fakeup_interface: "
"set if broadcast addr, error=%d",
error);
-
+
/* Get HW address */
-
+
sdl = NULL;
for (ifa = TAILQ_FIRST(&ifctx->ifp->if_addrhead);
ifa != NULL;
- ifa = TAILQ_NEXT(ifa,ifa_link))
+ ifa = TAILQ_NEXT(ifa, ifa_link))
if (ifa->ifa_addr->sa_family == AF_LINK &&
(sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL &&
sdl->sdl_type == IFT_ETHER)
break;
-
+
if (sdl == NULL)
panic("bootpc: Unable to find HW address for %s",
ifctx->ireq.ifr_name);
ifctx->sdl = sdl;
-
+
return error;
}
static int
bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
- struct bootpc_globalcontext *gctx,
- struct thread *td)
+ struct bootpc_globalcontext *gctx, struct thread *td)
{
int error;
struct sockaddr_in defdst;
struct sockaddr_in defmask;
struct sockaddr_in *sin;
-
struct ifreq *ireq;
struct socket *so;
struct sockaddr_in *myaddr;
@@ -1093,7 +1073,7 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
if (bootpc_ifctx_isresolved(ifctx) == 0) {
/* Shutdown interfaces where BOOTP failed */
-
+
printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
if (error != 0)
@@ -1104,7 +1084,7 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
if (error != 0)
panic("bootpc_adjust_interface: "
"SIOCSIFFLAGS, error=%d", error);
-
+
sin = (struct sockaddr_in *) &ireq->ifr_addr;
clear_sinaddr(sin);
error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td);
@@ -1112,7 +1092,7 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
ifctx == gctx->interfaces))
panic("bootpc_adjust_interface: "
"SIOCDIFADDR, error=%d", error);
-
+
return 0;
}
@@ -1126,9 +1106,9 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
if (error != 0)
panic("bootpc_adjust_interface: "
"set if netmask, error=%d", error);
-
+
/* Broadcast is with host part of IP address all 1's */
-
+
sin = (struct sockaddr_in *) &ireq->ifr_addr;
clear_sinaddr(sin);
sin->sin_addr.s_addr = myaddr->sin_addr.s_addr |
@@ -1137,13 +1117,13 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
if (error != 0)
panic("bootpc_adjust_interface: "
"set if broadcast addr, error=%d", error);
-
+
bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr));
error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
panic("bootpc_adjust_interface: "
"set if addr, error=%d", error);
-
+
/* Add new default route */
if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
@@ -1160,17 +1140,16 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
return error;
}
}
-
+
return 0;
}
-
static int
setfs(struct sockaddr_in *addr, char *path, char *p)
{
unsigned int ip;
int val;
-
+
ip = 0;
if (((val = getdec(&p)) < 0) || (val > 255))
return 0;
@@ -1196,16 +1175,15 @@ setfs(struct sockaddr_in *addr, char *path, char *p)
if (*p != ':')
return 0;
p++;
-
+
addr->sin_addr.s_addr = htonl(ip);
addr->sin_len = sizeof(struct sockaddr_in);
addr->sin_family = AF_INET;
-
+
strncpy(path, p, MNAMELEN - 1);
return 1;
}
-
static int
getdec(char **ptr)
{
@@ -1224,13 +1202,12 @@ getdec(char **ptr)
return ret;
}
-
static char *
substr(char *a, char *b)
{
char *loc1;
char *loc2;
-
+
while (*a != '\0') {
loc1 = a;
loc2 = b;
@@ -1246,12 +1223,11 @@ substr(char *a, char *b)
return 0;
}
-
static void
mountopts(struct nfs_args *args, char *p)
{
char *tmp;
-
+
args->version = NFS_ARGSVERSION;
args->rsize = 8192;
args->wsize = 8192;
@@ -1273,16 +1249,15 @@ mountopts(struct nfs_args *args, char *p)
args->sotype = SOCK_STREAM;
}
-
static int
xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
{
struct mbuf *m;
int alignedlen;
-
+
m = *mptr;
alignedlen = ( len + 3 ) & ~3;
-
+
if (m->m_len < alignedlen) {
m = m_pullup(m, alignedlen);
if (m == NULL) {
@@ -1296,40 +1271,37 @@ xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
return 0;
}
-
static int
xdr_int_decode(struct mbuf **mptr, int *iptr)
{
u_int32_t i;
+
if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
return EBADRPC;
*iptr = fxdr_unsigned(u_int32_t, i);
return 0;
}
-
static void
print_sin_addr(struct sockaddr_in *sin)
{
+
print_in_addr(sin->sin_addr);
}
-
static void
print_in_addr(struct in_addr addr)
{
unsigned int ip;
-
+
ip = ntohl(addr.s_addr);
printf("%d.%d.%d.%d",
ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
}
static void
-bootpc_compose_query(ifctx, gctx, td)
- struct bootpc_ifcontext *ifctx;
- struct bootpc_globalcontext *gctx;
- struct thread *td;
+bootpc_compose_query(struct bootpc_ifcontext *ifctx,
+ struct bootpc_globalcontext *gctx, struct thread *td)
{
unsigned char *vendp;
uint32_t leasetime;
@@ -1337,7 +1309,7 @@ bootpc_compose_query(ifctx, gctx, td)
ifctx->gotrootpath = 0;
bzero((caddr_t) &ifctx->call, sizeof(ifctx->call));
-
+
/* bootpc part */
ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */
ifctx->call.htype = 1; /* 10mb ethernet */
@@ -1347,7 +1319,7 @@ bootpc_compose_query(ifctx, gctx, td)
ifctx->xid++;
ifctx->call.xid = txdr_unsigned(ifctx->xid);
bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen);
-
+
vendp = ifctx->call.vend;
*vendp++ = 99; /* RFC1048 cookie */
*vendp++ = 130;
@@ -1390,25 +1362,22 @@ bootpc_compose_query(ifctx, gctx, td)
;
}
*vendp = TAG_END;
-
+
ifctx->call.secs = 0;
ifctx->call.flags = htons(0x8000); /* We need an broadcast answer */
}
-
static int
bootpc_hascookie(struct bootp_packet *bp)
{
+
return (bp->vend[0] == 99 && bp->vend[1] == 130 &&
bp->vend[2] == 83 && bp->vend[3] == 99);
}
-
static void
bootpc_tag_helper(struct bootpc_tagcontext *tctx,
- unsigned char *start,
- int len,
- int tag)
+ unsigned char *start, int len, int tag)
{
unsigned char *j;
unsigned char *ej;
@@ -1416,10 +1385,10 @@ bootpc_tag_helper(struct bootpc_tagcontext *tctx,
if (tctx->badtag != 0 || tctx->badopt != 0)
return;
-
+
j = start;
ej = j + len;
-
+
while (j < ej) {
code = *j++;
if (code == TAG_PAD)
@@ -1444,17 +1413,14 @@ bootpc_tag_helper(struct bootpc_tagcontext *tctx,
}
if (code == TAG_OVERLOAD)
tctx->overload = *j;
-
+
j += len;
}
}
-
static unsigned char *
bootpc_tag(struct bootpc_tagcontext *tctx,
- struct bootp_packet *bp,
- int len,
- int tag)
+ struct bootp_packet *bp, int len, int tag)
{
unsigned char *j;
unsigned char *ej;
@@ -1467,13 +1433,13 @@ bootpc_tag(struct bootpc_tagcontext *tctx,
if (bootpc_hascookie(bp) == 0)
return NULL;
-
+
j = &bp->vend[4];
ej = (unsigned char *) bp + len;
bootpc_tag_helper(tctx, &bp->vend[4],
(unsigned char *) bp + len - &bp->vend[4], tag);
-
+
if ((tctx->overload & OVERLOAD_FILE) != 0)
bootpc_tag_helper(tctx,
(unsigned char *) bp->file,
@@ -1484,19 +1450,16 @@ bootpc_tag(struct bootpc_tagcontext *tctx,
(unsigned char *) bp->sname,
sizeof(bp->sname),
tag);
-
+
if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0)
return NULL;
tctx->buf[tctx->taglen] = '\0';
return tctx->buf;
}
-
static void
-bootpc_decode_reply(nd, ifctx, gctx)
- struct nfsv3_diskless *nd;
- struct bootpc_ifcontext *ifctx;
- struct bootpc_globalcontext *gctx;
+bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
+ struct bootpc_globalcontext *gctx)
{
char *p;
unsigned int ip;
@@ -1507,19 +1470,19 @@ bootpc_decode_reply(nd, ifctx, gctx)
clear_sinaddr(&ifctx->myaddr);
clear_sinaddr(&ifctx->netmask);
clear_sinaddr(&ifctx->gw);
-
+
ifctx->myaddr.sin_addr = ifctx->reply.yiaddr;
-
+
ip = ntohl(ifctx->myaddr.sin_addr.s_addr);
snprintf(gctx->lookup_path, sizeof(gctx->lookup_path),
"swap.%d.%d.%d.%d",
ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
-
+
printf("%s at ", ifctx->ireq.ifr_name);
print_sin_addr(&ifctx->myaddr);
printf(" server ");
print_in_addr(ifctx->reply.siaddr);
-
+
ifctx->gw.sin_addr = ifctx->reply.giaddr;
if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) {
printf(" via gateway ");
@@ -1529,14 +1492,14 @@ bootpc_decode_reply(nd, ifctx, gctx)
/* This call used for the side effect (overload flag) */
(void) bootpc_tag(&gctx->tmptag,
&ifctx->reply, ifctx->replylen, TAG_END);
-
+
if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0)
if (ifctx->reply.sname[0] != '\0')
printf(" server name %s", ifctx->reply.sname);
if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0)
if (ifctx->reply.file[0] != '\0')
printf(" boot file %s", ifctx->reply.file);
-
+
printf("\n");
p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
@@ -1551,7 +1514,7 @@ bootpc_decode_reply(nd, ifctx, gctx)
print_sin_addr(&ifctx->netmask);
printf(" ");
}
-
+
p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
TAG_ROUTERS);
if (p != NULL) {
@@ -1567,7 +1530,7 @@ bootpc_decode_reply(nd, ifctx, gctx)
gctx->gotgw = 1;
}
}
-
+
p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
TAG_ROOT);
if (p != NULL) {
@@ -1575,11 +1538,11 @@ bootpc_decode_reply(nd, ifctx, gctx)
printf("rootfs %s (ignored) ", p);
} else if (setfs(&nd->root_saddr,
nd->root_hostnam, p)) {
- printf("rootfs %s ",p);
+ printf("rootfs %s ", p);
gctx->gotrootpath = 1;
ifctx->gotrootpath = 1;
gctx->setrootfs = ifctx;
-
+
p = bootpc_tag(&gctx->tag, &ifctx->reply,
ifctx->replylen,
TAG_ROOTOPTS);
@@ -1588,7 +1551,7 @@ bootpc_decode_reply(nd, ifctx, gctx)
printf("rootopts %s ", p);
}
} else
- panic("Failed to set rootfs to %s",p);
+ panic("Failed to set rootfs to %s", p);
}
p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
@@ -1610,7 +1573,7 @@ bootpc_decode_reply(nd, ifctx, gctx)
mountopts(&nd->swap_args, p);
printf("swapopts %s ", p);
}
-
+
p = bootpc_tag(&gctx->tag, &ifctx->reply,
ifctx->replylen,
TAG_SWAPSIZE);
@@ -1641,13 +1604,13 @@ bootpc_decode_reply(nd, ifctx, gctx)
} else {
strcpy(nd->my_hostnam, p);
strcpy(hostname, p);
- printf("hostname %s ",hostname);
+ printf("hostname %s ", hostname);
gctx->sethostname = ifctx;
}
}
printf("\n");
-
+
if (ifctx->gotnetmask == 0) {
if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr)))
ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
@@ -1674,7 +1637,7 @@ bootpc_init(void)
nd = &nfsv3_diskless;
td = curthread;
-
+
/*
* If already filled in, don't touch it here
*/
@@ -1686,15 +1649,15 @@ bootpc_init(void)
*/
while (time_second == 0)
tsleep(&time_second, PZERO + 8, "arpkludge", 10);
-
+
gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK);
if (gctx == NULL)
panic("Failed to allocate bootp global context structure");
-
+
bzero(gctx, sizeof(*gctx));
gctx->xid = ~0xFFFF;
gctx->starttime = time_second;
-
+
ifctx = allocifctx(gctx);
/*
@@ -1729,7 +1692,7 @@ bootpc_init(void)
ifctx = allocifctx(gctx);
}
free(ifctx, M_TEMP);
-
+
if (gctx->interfaces == NULL) {
#ifdef BOOTP_WIRED_TO
panic("bootpc_init: Could not find interface specified "
@@ -1739,20 +1702,20 @@ bootpc_init(void)
panic("bootpc_init: no suitable interface");
#endif
}
-
+
gctx->gotrootpath = 0;
gctx->gotswappath = 0;
gctx->gotgw = 0;
-
+
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
bootpc_fakeup_interface(ifctx, gctx, td);
-
+
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
bootpc_compose_query(ifctx, gctx, td);
-
+
ifctx = gctx->interfaces;
error = bootpc_call(gctx, td);
-
+
if (error != 0) {
#ifdef BOOTP_NFSROOT
panic("BOOTP call failed");
@@ -1760,25 +1723,25 @@ bootpc_init(void)
printf("BOOTP call failed\n");
#endif
}
-
+
mountopts(&nd->root_args, NULL);
-
+
mountopts(&nd->swap_args, NULL);
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
if (bootpc_ifctx_isresolved(ifctx) != 0)
bootpc_decode_reply(nd, ifctx, gctx);
-
+
if (gctx->gotswappath == 0)
nd->swap_nblks = 0;
#ifdef BOOTP_NFSROOT
if (gctx->gotrootpath == 0)
panic("bootpc: No root path offered");
#endif
-
+
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
bootpc_adjust_interface(ifctx, gctx, td);
-
+
soclose(ifctx->so);
}
@@ -1794,17 +1757,17 @@ bootpc_init(void)
}
if (ifctx == NULL)
goto out;
-
+
if (gctx->gotrootpath != 0) {
-
+
error = md_mount(&nd->root_saddr, nd->root_hostnam,
nd->root_fh, &nd->root_fhsize,
&nd->root_args, td);
if (error != 0)
panic("nfs_boot: mountd root, error=%d", error);
-
+
if (gctx->gotswappath != 0) {
-
+
error = md_mount(&nd->swap_saddr,
nd->swap_hostnam,
nd->swap_fh, &nd->swap_fhsize,
@@ -1812,7 +1775,7 @@ bootpc_init(void)
if (error != 0)
panic("nfs_boot: mountd swap, error=%d",
error);
-
+
error = md_lookup_swap(&nd->swap_saddr,
gctx->lookup_path,
nd->swap_fh, &nd->swap_fhsize,
@@ -1823,7 +1786,7 @@ bootpc_init(void)
}
nfs_diskless_valid = 3;
}
-
+
strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name);
bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr));
bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr));
@@ -1831,7 +1794,7 @@ bootpc_init(void)
ifctx->myaddr.sin_addr.s_addr |
~ ifctx->netmask.sin_addr.s_addr;
bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
-
+
out:
for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) {
nctx = ifctx->next;
@@ -1840,26 +1803,21 @@ out:
free(gctx, M_TEMP);
}
-
/*
* RPC: mountd/mount
* Given a server pathname, get an NFS file handle.
* Also, sets sin->sin_port to the NFS service port.
*/
static int
-md_mount(struct sockaddr_in *mdsin, /* mountd server address */
- char *path,
- u_char *fhp,
- int *fhsizep,
- struct nfs_args *args,
- struct thread *td)
+md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
+ struct nfs_args *args, struct thread *td)
{
struct mbuf *m;
int error;
int authunixok;
int authcount;
int authver;
-
+
#ifdef BOOTP_NFSV3
/* First try NFS v3 */
/* Get port number for MOUNTD. */
@@ -1867,7 +1825,7 @@ md_mount(struct sockaddr_in *mdsin, /* mountd server address */
&mdsin->sin_port, td);
if (error == 0) {
m = xdr_string_encode(path, strlen(path));
-
+
/* Do RPC to mountd. */
error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
RPCMNT_MOUNT, &m, NULL, td);
@@ -1877,28 +1835,28 @@ md_mount(struct sockaddr_in *mdsin, /* mountd server address */
} else {
#endif
/* Fallback to NFS v2 */
-
+
/* Get port number for MOUNTD. */
error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
&mdsin->sin_port, td);
if (error != 0)
return error;
-
+
m = xdr_string_encode(path, strlen(path));
-
+
/* Do RPC to mountd. */
error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
RPCMNT_MOUNT, &m, NULL, td);
if (error != 0)
return error; /* message already freed */
-
+
#ifdef BOOTP_NFSV3
}
#endif
if (xdr_int_decode(&m, &error) != 0 || error != 0)
goto bad;
-
+
if ((args->flags & NFSMNT_NFSV3) != 0) {
if (xdr_int_decode(&m, fhsizep) != 0 ||
*fhsizep > NFSX_V3FHMAX ||
@@ -1926,31 +1884,26 @@ md_mount(struct sockaddr_in *mdsin, /* mountd server address */
if (authunixok == 0)
goto bad;
}
-
+
/* Set port number for NFS use. */
error = krpc_portmap(mdsin, NFS_PROG,
(args->flags &
NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
&mdsin->sin_port, td);
-
+
goto out;
-
+
bad:
error = EBADRPC;
-
+
out:
m_freem(m);
return error;
}
-
static int
-md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
- char *path,
- u_char *fhp,
- int *fhsizep,
- struct nfs_args *args,
- struct thread *td)
+md_lookup_swap(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
+ struct nfs_args *args, struct thread *td)
{
struct mbuf *m;
int error;
@@ -1961,11 +1914,11 @@ md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
u_int32_t v2[17];
u_int32_t v3[21];
} fattribs;
-
- m = m_get(M_TRYWAIT,MT_DATA);
+
+ m = m_get(M_TRYWAIT, MT_DATA);
if (m == NULL)
return ENOBUFS;
-
+
if ((args->flags & NFSMNT_NFSV3) != 0) {
*mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep);
bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep);
@@ -1974,7 +1927,7 @@ md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
bcopy(fhp, mtod(m, u_char *), NFSX_V2FH);
m->m_len = NFSX_V2FH;
}
-
+
m->m_next = xdr_string_encode(path, strlen(path));
if (m->m_next == NULL) {
error = ENOBUFS;
@@ -1997,7 +1950,7 @@ md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
error = ENOENT;
goto out;
}
-
+
if ((args->flags & NFSMNT_NFSV3) != 0) {
if (xdr_int_decode(&m, fhsizep) != 0 ||
*fhsizep > NFSX_V3FHMAX ||
@@ -2005,10 +1958,10 @@ md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
goto bad;
} else
*fhsizep = NFSX_V2FH;
-
+
if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
goto bad;
-
+
if ((args->flags & NFSMNT_NFSV3) != 0) {
if (xdr_int_decode(&m, &attribs_present) != 0)
goto bad;
@@ -2024,18 +1977,18 @@ md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
goto bad;
size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
}
-
+
if (nfsv3_diskless.swap_nblks == 0 && size != -1) {
nfsv3_diskless.swap_nblks = size / 1024;
printf("md_lookup_swap: Swap size is %d KB\n",
nfsv3_diskless.swap_nblks);
}
-
+
goto out;
-
+
bad:
error = EBADRPC;
-
+
out:
m_freem(m);
return error;
diff --git a/sys/nfsclient/krpc.h b/sys/nfsclient/krpc.h
index b6136e3..44b84e0 100644
--- a/sys/nfsclient/krpc.h
+++ b/sys/nfsclient/krpc.h
@@ -8,14 +8,14 @@ struct thread;
struct sockaddr;
struct sockaddr_in;
-int krpc_call __P((struct sockaddr_in *_sin,
+int krpc_call(struct sockaddr_in *_sin,
u_int prog, u_int vers, u_int func,
- struct mbuf **data, struct sockaddr **from, struct thread *td));
+ struct mbuf **data, struct sockaddr **from, struct thread *td);
-int krpc_portmap __P((struct sockaddr_in *_sin,
- u_int prog, u_int vers, u_int16_t *portp,struct thread *td));
+int krpc_portmap(struct sockaddr_in *_sin,
+ u_int prog, u_int vers, u_int16_t *portp, struct thread *td);
-struct mbuf *xdr_string_encode __P((char *str, int len));
+struct mbuf *xdr_string_encode(char *str, int len);
/*
* RPC definitions for the portmapper
diff --git a/sys/nfsclient/krpc_subr.c b/sys/nfsclient/krpc_subr.c
index 709af4a..06b9c81 100644
--- a/sys/nfsclient/krpc_subr.c
+++ b/sys/nfsclient/krpc_subr.c
@@ -1,5 +1,4 @@
/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */
-/* $FreeBSD$ */
/*
* Copyright (c) 1995 Gordon Ross, Adam Glass
@@ -43,6 +42,9 @@
* @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL)
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -55,7 +57,7 @@
#include <netinet/in.h>
#include <nfs/rpcv2.h>
-#include <nfs/krpc.h>
+#include <nfsclient/krpc.h>
#include <nfs/xdr_subs.h>
/*
@@ -124,11 +126,8 @@ struct rpc_reply {
* Returns non-zero error on failure.
*/
int
-krpc_portmap(sin, prog, vers, portp, td)
- struct sockaddr_in *sin; /* server address */
- u_int prog, vers; /* host order */
- u_int16_t *portp; /* network order */
- struct thread *td;
+krpc_portmap(struct sockaddr_in *sin, u_int prog, u_int vers, u_int16_t *portp,
+ struct thread *td)
{
struct sdata {
u_int32_t prog; /* call program */
@@ -164,7 +163,7 @@ krpc_portmap(sin, prog, vers, portp, td)
sin->sin_port = htons(PMAPPORT);
error = krpc_call(sin, PMAPPROG, PMAPVERS,
PMAPPROC_GETPORT, &m, NULL, td);
- if (error)
+ if (error)
return error;
if (m->m_len < sizeof(*rdata)) {
@@ -185,12 +184,8 @@ krpc_portmap(sin, prog, vers, portp, td)
* the address from whence the response came is saved there.
*/
int
-krpc_call(sa, prog, vers, func, data, from_p, td)
- struct sockaddr_in *sa;
- u_int prog, vers, func;
- struct mbuf **data; /* input/output */
- struct sockaddr **from_p; /* output */
- struct thread *td;
+krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
+ struct mbuf **data, struct sockaddr **from_p, struct thread *td)
{
struct socket *so;
struct sockaddr_in *sin, ssin;
@@ -354,7 +349,7 @@ krpc_call(sa, prog, vers, func, data, from_p, td)
m_freem(m);
m = NULL;
}
- bzero(&auio,sizeof(auio));
+ bzero(&auio, sizeof(auio));
auio.uio_resid = len = 1<<16;
rcvflg = 0;
error = soreceive(so, &from, &auio, &m, NULL, &rcvflg);
@@ -456,9 +451,7 @@ struct xdr_string {
};
struct mbuf *
-xdr_string_encode(str, len)
- char *str;
- int len;
+xdr_string_encode(char *str, int len)
{
struct mbuf *m;
struct xdr_string *xs;
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h
index da808f4..5811883 100644
--- a/sys/nfsclient/nfs.h
+++ b/sys/nfsclient/nfs.h
@@ -37,18 +37,19 @@
* $FreeBSD$
*/
-#ifndef _NFS_NFS_H_
-#define _NFS_NFS_H_
+#ifndef _NFSCLIENT_NFS_H_
+#define _NFSCLIENT_NFS_H_
#ifdef _KERNEL
#include "opt_nfs.h"
#endif
+#include <nfsclient/nfsargs.h>
+
/*
* Tunable constants for nfs
*/
-#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
@@ -56,7 +57,6 @@
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
-#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
#define NFS_MAXGRPS 16 /* Max. size of groups list */
#ifndef NFS_MINATTRTIMO
@@ -76,227 +76,48 @@
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
-#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
-#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
-#ifndef NFS_GATHERDELAY
-#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
-#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
#ifdef _KERNEL
#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
#endif
+#define NFS_MAXDEADTHRESH 9 /* How long till we say 'server not responding' */
/*
* Oddballs
*/
-#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
-#define NFS_SRVMAXDATA(n) \
- (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
- NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
-
-/*
- * XXX
- * The B_INVAFTERWRITE flag should be set to whatever is required by the
- * buffer cache code to say "Invalidate the block after it is written back".
- */
-#define B_INVAFTERWRITE B_NOCACHE
-
-/*
- * The IO_METASYNC flag should be implemented for local file systems.
- * (Until then, it is nothin at all.)
- */
-#ifndef IO_METASYNC
-#define IO_METASYNC 0
-#endif
-
-/*
- * Arguments to mount NFS
- */
-#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
-struct nfs_args {
- int version; /* args structure version number */
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
- int acregmin; /* cache attrs for reg files min time */
- int acregmax; /* cache attrs for reg files max time */
- int acdirmin; /* cache attrs for dirs min time */
- int acdirmax; /* cache attrs for dirs max time */
-};
-
-/*
- * NFS mount option flags
- */
-#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
-#define NFSMNT_WSIZE 0x00000002 /* set write size */
-#define NFSMNT_RSIZE 0x00000004 /* set read size */
-#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
-#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
-#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
-#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
-#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
-#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
-#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
-#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
-#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
-#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
-#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
-#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
-#define NFSMNT_ACREGMIN 0x00040000
-#define NFSMNT_ACREGMAX 0x00080000
-#define NFSMNT_ACDIRMIN 0x00100000
-#define NFSMNT_ACDIRMAX 0x00200000
#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSSTA_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSSTA_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSSTA_DISMNT 0x00800000 /* Dismounted */
#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
#define NFSSTA_WANTSND 0x02000000 /* Want above */
#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
#define NFSSTA_WANTRCV 0x08000000 /* Want above */
-#define NFSSTA_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSSTA_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSSTA_AUTHERR 0x80000000 /* Authentication error */
-
-/*
- * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
- * should ever try and use it.
- */
-struct nfsd_args {
- int sock; /* Socket to serve */
- caddr_t name; /* Client addr for connection based sockets */
- int namelen; /* Length of name */
-};
-
-struct nfsd_srvargs {
- struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
- uid_t nsd_uid; /* Effective uid mapped to cred */
- u_int32_t nsd_haddr; /* Ip address of client */
- struct xucred nsd_cr; /* Cred. uid maps to */
- u_int nsd_authlen; /* Length of auth string (ret) */
- u_char *nsd_authstr; /* Auth string (ret) */
- u_int nsd_verflen; /* and the verfier */
- u_char *nsd_verfstr;
- struct timeval nsd_timestamp; /* timestamp from verifier */
- u_int32_t nsd_ttl; /* credential ttl (sec) */
- NFSKERBKEY_T nsd_key; /* Session key */
-};
-
-struct nfsd_cargs {
- char *ncd_dirp; /* Mount dir path */
- uid_t ncd_authuid; /* Effective uid */
- int ncd_authtype; /* Type of authenticator */
- u_int ncd_authlen; /* Length of authenticator string */
- u_char *ncd_authstr; /* Authenticator string */
- u_int ncd_verflen; /* and the verifier */
- u_char *ncd_verfstr;
- NFSKERBKEY_T ncd_key; /* Session key */
-};
/*
* XXX to allow amd to include nfs.h without nfsproto.h
*/
#ifdef NFS_NPROCS
-/*
- * Stats structure
- */
-struct nfsstats {
- int attrcache_hits;
- int attrcache_misses;
- int lookupcache_hits;
- int lookupcache_misses;
- int direofcache_hits;
- int direofcache_misses;
- int biocache_reads;
- int read_bios;
- int read_physios;
- int biocache_writes;
- int write_bios;
- int write_physios;
- int biocache_readlinks;
- int readlink_bios;
- int biocache_readdirs;
- int readdir_bios;
- int rpccnt[NFS_NPROCS];
- int rpcretries;
- int srvrpccnt[NFS_NPROCS];
- int srvrpc_errs;
- int srv_errs;
- int rpcrequests;
- int rpctimeouts;
- int rpcunexpected;
- int rpcinvalid;
- int srvcache_inproghits;
- int srvcache_idemdonehits;
- int srvcache_nonidemdonehits;
- int srvcache_misses;
- int srvnqnfs_leases;
- int srvnqnfs_maxleases;
- int srvnqnfs_getleases;
- int srvvop_writes;
- int accesscache_hits;
- int accesscache_misses;
-};
+#include <nfsclient/nfsstats.h>
#endif
-
/*
- * Flags for nfssvc() system call.
+ * Flags for nfsclnt() system call.
*/
-#define NFSSVC_BIOD 0x002
-#define NFSSVC_NFSD 0x004
-#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_AUTHIN 0x010
-#define NFSSVC_GOTAUTH 0x040
-#define NFSSVC_AUTHINFAIL 0x080
-#define NFSSVC_MNTD 0x100
-#define NFSSVC_LOCKDANS 0x200
+#define NFSCLNT_LOCKDANS 0x200
/*
- * fs.nfs sysctl(3) identifiers
+ * vfs.nfs sysctl(3) identifiers
*/
#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
-#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
-
-#define FS_NFS_NAMES { \
- { 0, 0 }, \
- { "nfsstats", CTLTYPE_STRUCT }, \
- { "nfsprivport", CTLTYPE_INT }, \
-}
#ifdef _KERNEL
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_NFSREQ);
MALLOC_DECLARE(M_NFSDIROFF);
-MALLOC_DECLARE(M_NFSRVDESC);
-MALLOC_DECLARE(M_NFSUID);
-MALLOC_DECLARE(M_NQLEASE);
-MALLOC_DECLARE(M_NFSD);
MALLOC_DECLARE(M_NFSBIGFH);
MALLOC_DECLARE(M_NFSHASH);
#endif
@@ -306,8 +127,23 @@ extern vm_zone_t nfsmount_zone;
#endif
extern struct callout_handle nfs_timer_handle;
+extern struct nfsstats nfsstats;
-struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
+extern int nfs_numasync;
+extern int nfs_pbuf_freecnt;
+extern int nfs_ticks;
+
+/* Data constants in XDR form */
+extern u_int32_t nfs_true, nfs_false, nfs_xdrneg1;
+extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers;
+extern u_int32_t rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr;
+
+extern int nfsv3_procid[NFS_NPROCS];
+
+struct uio;
+struct buf;
+struct vattr;
+struct nameidata;
/*
* The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
@@ -366,176 +202,13 @@ extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
-/*
- * A list of nfssvc_sock structures is maintained with all the sockets
- * that require service by the nfsd.
- * The nfsuid structs hang off of the nfssvc_sock structs in both lru
- * and uid hash lists.
- */
-#ifndef NFS_UIDHASHSIZ
-#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
-#endif
-#define NUIDHASH(sock, uid) \
- (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
-#ifndef NFS_WDELAYHASHSIZ
-#define NFS_WDELAYHASHSIZ 16 /* and with this */
-#endif
-#define NWDELAYHASH(sock, f) \
- (&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifndef NFS_MUIDHASHSIZ
-#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
-#endif
-#define NMUIDHASH(nmp, uid) \
- (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
+extern struct nfsnodehashhead *nfsnodehashtbl;
+extern u_long nfsnodehash;
+
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
- * Network address hash list element
- */
-union nethostaddr {
- u_int32_t had_inetaddr;
- struct sockaddr *had_nam;
-};
-
-struct nfsuid {
- TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
- LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
- int nu_flag; /* Flags */
- union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
- struct ucred nu_cr; /* Cred uid mapped to */
- int nu_expire; /* Expiry time (sec) */
- struct timeval nu_timestamp; /* Kerb. timestamp */
- u_int32_t nu_nickname; /* Nickname on server */
- NFSKERBKEY_T nu_key; /* and session key */
-};
-
-#define nu_inetaddr nu_haddr.had_inetaddr
-#define nu_nam nu_haddr.had_nam
-/* Bits for nu_flag */
-#define NU_INETADDR 0x1
-#define NU_NAM 0x2
-#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
-
-struct nfsrv_rec {
- STAILQ_ENTRY(nfsrv_rec) nr_link;
- struct sockaddr *nr_address;
- struct mbuf *nr_packet;
-};
-
-struct nfssvc_sock {
- TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- TAILQ_HEAD(, nfsuid) ns_uidlruhead;
- struct file *ns_fp;
- struct socket *ns_so;
- struct sockaddr *ns_nam;
- struct mbuf *ns_raw;
- struct mbuf *ns_rawend;
- STAILQ_HEAD(, nfsrv_rec) ns_rec;
- struct mbuf *ns_frag;
- int ns_flag;
- int ns_solock;
- int ns_cc;
- int ns_reclen;
- int ns_numuids;
- u_int32_t ns_sref;
- LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
- LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
-};
-
-/* Bits for "ns_flag" */
-#define SLP_VALID 0x01
-#define SLP_DOREC 0x02
-#define SLP_NEEDQ 0x04
-#define SLP_DISCONN 0x08
-#define SLP_GETSTREAM 0x10
-#define SLP_LASTFRAG 0x20
-#define SLP_ALLFLAGS 0xff
-
-extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
-extern int nfssvc_sockhead_flag;
-#define SLP_INIT 0x01
-#define SLP_WANTINIT 0x02
-
-/*
- * One of these structures is allocated for each nfsd.
- */
-struct nfsd {
- TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
- int nfsd_flag; /* NFSD_ flags */
- struct nfssvc_sock *nfsd_slp; /* Current socket */
- int nfsd_authlen; /* Authenticator len */
- u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
- int nfsd_verflen; /* and the Verifier */
- u_char nfsd_verfstr[RPCVERF_MAXSIZ];
- struct thread *nfsd_td; /* daemon thread ptr */
- struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
-};
-
-/* Bits for "nfsd_flag" */
-#define NFSD_WAITING 0x01
-#define NFSD_REQINPROG 0x02
-#define NFSD_NEEDAUTH 0x04
-#define NFSD_AUTHFAIL 0x08
-
-/*
- * This structure is used by the server for describing each request.
- * Some fields are used only when write request gathering is performed.
- */
-struct nfsrv_descript {
- u_quad_t nd_time; /* Write deadline (usec) */
- off_t nd_off; /* Start byte offset */
- off_t nd_eoff; /* and end byte offset */
- LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
- LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
- LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
- struct mbuf *nd_mrep; /* Request mbuf list */
- struct mbuf *nd_md; /* Current dissect mbuf */
- struct mbuf *nd_mreq; /* Reply mbuf list */
- struct sockaddr *nd_nam; /* and socket addr */
- struct sockaddr *nd_nam2; /* return socket addr */
- caddr_t nd_dpos; /* Current dissect pos */
- u_int32_t nd_procnum; /* RPC # */
- int nd_stable; /* storage type */
- int nd_flag; /* nd_flag */
- int nd_len; /* Length of this write */
- int nd_repstat; /* Reply status */
- u_int32_t nd_retxid; /* Reply xid */
- u_int32_t nd_duration; /* Lease duration */
- struct timeval nd_starttime; /* Time RPC initiated */
- fhandle_t nd_fh; /* File handle */
- struct ucred nd_cr; /* Credentials */
-};
-
-/* Bits for "nd_flag" */
-#define ND_READ LEASE_READ
-#define ND_WRITE LEASE_WRITE
-#define ND_CHECK 0x04
-#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
-#define ND_NFSV3 0x08
-#define ND_NQNFS 0x10
-#define ND_KERBNICK 0x20
-#define ND_KERBFULL 0x40
-#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
-
-extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
-extern int nfsd_head_flag;
-#define NFSD_CHECKSLP 0x01
-
-/*
- * These macros compare nfsrv_descript structures.
- */
-#define NFSW_CONTIG(o, n) \
- ((o)->nd_eoff >= (n)->nd_off && \
- !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
-
-#define NFSW_SAMECRED(o, n) \
- (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
- !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
- sizeof (struct ucred)))
-
-/*
* Defines for WebNFS
*/
@@ -577,151 +250,45 @@ extern int nfs_debug;
#endif
-u_quad_t nfs_curusec __P((void));
-int nfs_init __P((struct vfsconf *vfsp));
-int nfs_uninit __P((struct vfsconf *vfsp));
-int nfs_reply __P((struct nfsreq *));
-int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
-int nfs_send __P((struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *));
-int nfs_rephead __P((int, struct nfsrv_descript *, struct nfssvc_sock *,
- int, int, u_quad_t *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_sndlock __P((struct nfsreq *));
-void nfs_sndunlock __P((struct nfsreq *));
-int nfs_slplock __P((struct nfssvc_sock *, int));
-void nfs_slpunlock __P((struct nfssvc_sock *));
-int nfs_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-int nfs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct thread *,
- int));
-int nfs_readrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_writerpc __P((struct vnode *, struct uio *, struct ucred *, int *,
- int *));
-int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
- struct ucred *cred, struct thread *td));
-int nfs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_asyncio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_doio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_readlinkrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_sigintr __P((struct nfsmount *, struct nfsreq *, struct proc *));
-int nfs_readdirplusrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfsm_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-void nfsm_srvfattr __P((struct nfsrv_descript *, struct vattr *,
- struct nfs_fattr *));
-void nfsm_srvwcc __P((struct nfsrv_descript *, int, struct vattr *, int,
- struct vattr *, struct mbuf **, char **));
-void nfsm_srvpostopattr __P((struct nfsrv_descript *, int, struct vattr *,
- struct mbuf **, char **));
-int netaddr_match __P((int, union nethostaddr *, struct sockaddr *));
-int nfs_request __P((struct vnode *, struct mbuf *, int, struct thread *,
- struct ucred *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *, int));
-int nfs_namei __P((struct nameidata *, fhandle_t *, int,
- struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
- caddr_t *, struct vnode **, struct thread *, int, int));
-void nfsm_adj __P((struct mbuf *, int, int));
-int nfsm_mbuftouio __P((struct mbuf **, struct uio *, int, caddr_t *));
-void nfsrv_initcache __P((void));
-int nfs_getauth __P((struct nfsmount *, struct nfsreq *, struct ucred *,
- char **, int *, char *, int *, NFSKERBKEY_T));
-int nfs_getnickauth __P((struct nfsmount *, struct ucred *, char **,
- int *, char *, int));
-int nfs_savenickauth __P((struct nfsmount *, struct ucred *, int,
- NFSKERBKEY_T, struct mbuf **, char **,
- struct mbuf *));
-int nfs_adv __P((struct mbuf **, caddr_t *, int, int));
-void nfs_nhinit __P((void));
-void nfs_timer __P((void*));
-int nfsrv_dorec __P((struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **));
-int nfsrv_getcache __P((struct nfsrv_descript *, struct nfssvc_sock *,
- struct mbuf **));
-void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *));
-void nfsrv_cleancache __P((void));
-int nfs_connect __P((struct nfsmount *, struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *));
-void nfs_safedisconnect __P((struct nfsmount *));
-int nfs_getattrcache __P((struct vnode *, struct vattr *));
-int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long));
-int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *));
-int nfsm_uiotombuf __P((struct uio *, struct mbuf **, int, caddr_t *));
-void nfsrv_init __P((int));
-void nfs_clearcommit __P((struct mount *));
-int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrvw_sort __P((gid_t *, int));
-void nfsrv_setcred __P((struct ucred *, struct ucred *));
-int nfs_writebp __P((struct buf *, int, struct thread *));
-int nfsrv_object_create __P((struct vnode *));
-void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
-int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
- struct thread *, struct mbuf **));
-int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
- struct thread *td));
-
-int nfsrv3_access __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_fhtovp __P((fhandle_t *, int, struct vnode **, struct ucred *,
- struct nfssvc_sock *, struct sockaddr *, int *,
- int, int));
-int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
- struct export_args *));
-int nfs_ispublicfh __P((fhandle_t *));
-int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdir __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_setattr __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_statfs __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_symlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-void nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
+int nfs_init(struct vfsconf *vfsp);
+int nfs_uninit(struct vfsconf *vfsp);
+int nfs_mountroot(struct mount *mp);
+int nfs_send(struct socket *, struct sockaddr *, struct mbuf *,
+ struct nfsreq *);
+int nfs_sndlock(struct nfsreq *);
+void nfs_sndunlock(struct nfsreq *);
+int nfs_vinvalbuf(struct vnode *, int, struct ucred *, struct thread *,
+ int);
+int nfs_readrpc(struct vnode *, struct uio *, struct ucred *);
+int nfs_writerpc(struct vnode *, struct uio *, struct ucred *, int *,
+ int *);
+int nfs_commit(struct vnode *vp, u_quad_t offset, int cnt,
+ struct ucred *cred, struct thread *td);
+int nfs_readdirrpc(struct vnode *, struct uio *, struct ucred *);
+int nfs_asyncio(struct buf *, struct ucred *, struct thread *);
+int nfs_doio(struct buf *, struct ucred *, struct thread *);
+int nfs_readlinkrpc(struct vnode *, struct uio *, struct ucred *);
+int nfs_sigintr(struct nfsmount *, struct nfsreq *, struct proc *);
+int nfs_readdirplusrpc(struct vnode *, struct uio *, struct ucred *);
+int nfs_request(struct vnode *, struct mbuf *, int, struct thread *,
+ struct ucred *, struct mbuf **, struct mbuf **, caddr_t *);
+int nfs_loadattrcache(struct vnode **, struct mbuf **, caddr_t *,
+ struct vattr *, int);
+int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *);
+void nfs_nhinit(void);
+void nfs_timer(void*);
+int nfs_connect(struct nfsmount *, struct nfsreq *);
+void nfs_disconnect(struct nfsmount *);
+void nfs_safedisconnect(struct nfsmount *);
+int nfs_getattrcache(struct vnode *, struct vattr *);
+int nfsm_strtmbuf(struct mbuf **, char **, const char *, long);
+int nfs_bioread(struct vnode *, struct uio *, int, struct ucred *);
+int nfsm_uiotombuf(struct uio *, struct mbuf **, int, caddr_t *);
+void nfs_clearcommit(struct mount *);
+int nfs_writebp(struct buf *, int, struct thread *);
+int nfs_fsinfo(struct nfsmount *, struct vnode *, struct ucred *,
+ struct thread *);
+
#endif /* _KERNEL */
#endif
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index fa7274d..769ac35 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -34,9 +34,10 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$);
#include <sys/param.h>
#include <sys/systm.h>
@@ -59,10 +60,9 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsnode.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfsnode.h>
/*
* Just call nfs_writebp() with the force argument set to 1.
@@ -72,6 +72,7 @@
static int
nfs_bwrite(struct buf *bp)
{
+
return (nfs_writebp(bp, 1, curthread));
}
@@ -80,26 +81,14 @@ struct buf_ops buf_ops_nfs = {
nfs_bwrite
};
-
-static struct buf *nfs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size,
- struct thread *td));
-
-extern int nfs_numasync;
-extern int nfs_pbuf_freecnt;
-extern struct nfsstats nfsstats;
+static struct buf *nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size,
+ struct thread *td);
/*
* Vnode op for VM getpages.
*/
int
-nfs_getpages(ap)
- struct vop_getpages_args /* {
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_reqpage;
- vm_ooffset_t a_offset;
- } */ *ap;
+nfs_getpages(struct vop_getpages_args *ap)
{
int i, error, nextoff, size, toff, count, npages;
struct uio uio;
@@ -218,7 +207,7 @@ nfs_getpages(ap)
/* handled by vm_fault now */
/* vm_page_zero_invalid(m, TRUE); */
}
-
+
if (i != ap->a_reqpage) {
/*
* Whether or not to leave the page activated is up in
@@ -250,15 +239,7 @@ nfs_getpages(ap)
* Vnode op for VM putpages.
*/
int
-nfs_putpages(ap)
- struct vop_putpages_args /* {
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_sync;
- int *a_rtvals;
- vm_ooffset_t a_offset;
- } */ *ap;
+nfs_putpages(struct vop_putpages_args *ap)
{
struct uio uio;
struct iovec iov;
@@ -287,16 +268,13 @@ nfs_putpages(ap)
npages = btoc(count);
offset = IDX_TO_OFF(pages[0]->pindex);
- GIANT_REQUIRED;
-
if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
(nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
(void)nfs_fsinfo(nmp, vp, cred, td);
}
- for (i = 0; i < npages; i++) {
+ for (i = 0; i < npages; i++)
rtvals[i] = VM_PAGER_AGAIN;
- }
/*
* When putting pages, do not extend file past EOF.
@@ -356,14 +334,10 @@ nfs_putpages(ap)
* Vnode op for read using bio
*/
int
-nfs_bioread(vp, uio, ioflag, cred)
- register struct vnode *vp;
- register struct uio *uio;
- int ioflag;
- struct ucred *cred;
+nfs_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
{
- register struct nfsnode *np = VTONFS(vp);
- register int biosize, i;
+ struct nfsnode *np = VTONFS(vp);
+ int biosize, i;
struct buf *bp = 0, *rabp;
struct vattr vattr;
struct thread *td;
@@ -395,7 +369,6 @@ nfs_bioread(vp, uio, ioflag, cred)
* For nfs, cache consistency can only be maintained approximately.
* Although RFC1094 does not specify the criteria, the following is
* believed to be compatible with the reference port.
- * For nqnfs, full cache consistency is maintained within the loop.
* For nfs:
* If the file's modify time on the server has changed since the
* last read rpc or you have written to the file,
@@ -408,77 +381,34 @@ nfs_bioread(vp, uio, ioflag, cred)
* attributes this could be forced by setting n_attrstamp to 0 before
* the VOP_GETATTR() call.
*/
- if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) {
- if (np->n_flag & NMODIFIED) {
- if (vp->v_type != VREG) {
- if (vp->v_type != VDIR)
- panic("nfs: bioread, not dir");
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- }
- np->n_attrstamp = 0;
- error = VOP_GETATTR(vp, &vattr, cred, td);
- if (error)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- } else {
- error = VOP_GETATTR(vp, &vattr, cred, td);
+ if (np->n_flag & NMODIFIED) {
+ if (vp->v_type != VREG) {
+ if (vp->v_type != VDIR)
+ panic("nfs: bioread, not dir");
+ nfs_invaldir(vp);
+ error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
if (error)
return (error);
- if (np->n_mtime != vattr.va_mtime.tv_sec) {
- if (vp->v_type == VDIR)
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- }
}
- }
- do {
-
- /*
- * Get a valid lease. If cached data is stale, flush it.
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (NQNFS_CKINVALID(vp, np, ND_READ)) {
- do {
- error = nqnfs_getlease(vp, ND_READ, cred, td);
- } while (error == NQNFS_EXPIRED);
- if (error)
+ np->n_attrstamp = 0;
+ error = VOP_GETATTR(vp, &vattr, cred, td);
+ if (error)
+ return (error);
+ np->n_mtime = vattr.va_mtime.tv_sec;
+ } else {
+ error = VOP_GETATTR(vp, &vattr, cred, td);
+ if (error)
return (error);
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE) ||
- ((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
+ if (np->n_mtime != vattr.va_mtime.tv_sec) {
if (vp->v_type == VDIR)
- nfs_invaldir(vp);
+ nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
if (error)
- return (error);
- np->n_brev = np->n_lrev;
- }
- } else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
- nfs_invaldir(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- return (error);
+ return (error);
+ np->n_mtime = vattr.va_mtime.tv_sec;
}
- }
- if (np->n_flag & NQNFSNONCACHE) {
- switch (vp->v_type) {
- case VREG:
- return (nfs_readrpc(vp, uio, cred));
- case VLNK:
- return (nfs_readlinkrpc(vp, uio, cred));
- case VDIR:
- break;
- default:
- printf(" NQNFSNONCACHE: type %x unexpected\n",
- vp->v_type);
- };
- }
+ }
+ do {
switch (vp->v_type) {
case VREG:
nfsstats.biocache_reads++;
@@ -517,7 +447,7 @@ nfs_bioread(vp, uio, ioflag, cred)
/*
* Obtain the buffer cache block. Figure out the buffer size
* when we are at EOF. If we are modifying the size of the
- * buffer based on an EOF condition we need to hold
+ * buffer based on an EOF condition we need to hold
* nfs_rslock() through obtaining the buffer to prevent
* a potential writer-appender from messing with n_size.
* Otherwise we may accidently truncate the buffer and
@@ -677,7 +607,6 @@ again:
(bp->b_flags & B_INVAL) == 0 &&
(np->n_direofoffset == 0 ||
(lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
- !(np->n_flag & NQNFSNONCACHE) &&
!incore(vp, lbn + 1)) {
rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, td);
if (rabp) {
@@ -705,7 +634,7 @@ again:
* to EOF. *BUT* this information is lost if the buffer goes
* away and is reconstituted into a B_CACHE state ( due to
* being VMIO ) later. So we keep track of the directory eof
- * in np->n_direofoffset and chop it off as an extra step
+ * in np->n_direofoffset and chop it off as an extra step
* right here.
*/
n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
@@ -713,7 +642,7 @@ again:
n = np->n_direofoffset - uio->uio_offset;
break;
default:
- printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
+ printf(" nfs_bioread: type %x unexpected\n", vp->v_type);
break;
};
@@ -727,15 +656,9 @@ again:
n = 0;
break;
case VDIR:
- /*
- * Invalidate buffer if caching is disabled, forcing a
- * re-read from the remote later.
- */
- if (np->n_flag & NQNFSNONCACHE)
- bp->b_flags |= B_INVAL;
break;
default:
- printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
+ printf(" nfs_bioread: type %x unexpected\n", vp->v_type);
}
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n > 0);
@@ -746,13 +669,7 @@ again:
* Vnode op for write using bio
*/
int
-nfs_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+nfs_write(struct vop_write_args *ap)
{
int biosize;
struct uio *uio = ap->a_uio;
@@ -766,7 +683,7 @@ nfs_write(ap)
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn;
int bcount;
- int n, on, error = 0, iomode, must_commit;
+ int n, on, error = 0;
int haverslock = 0;
struct proc *p = td?td->td_proc:NULL;
@@ -868,31 +785,6 @@ restart:
biosize = vp->v_mount->mnt_stat.f_iosize;
do {
- /*
- * Check for a valid write lease.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) &&
- NQNFS_CKINVALID(vp, np, ND_WRITE)) {
- do {
- error = nqnfs_getlease(vp, ND_WRITE, cred, td);
- } while (error == NQNFS_EXPIRED);
- if (error)
- break;
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE)) {
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- break;
- np->n_brev = np->n_lrev;
- }
- }
- if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
- iomode = NFSV3WRITE_FILESYNC;
- error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
- if (must_commit)
- nfs_clearcommit(vp->v_mount);
- break;
- }
nfsstats.biocache_writes++;
lbn = uio->uio_offset / biosize;
on = uio->uio_offset & (biosize-1);
@@ -929,7 +821,7 @@ again:
}
} else {
/*
- * Obtain the locked cache block first, and then
+ * Obtain the locked cache block first, and then
* adjust the file's size as appropriate.
*/
bcount = on + n;
@@ -960,7 +852,7 @@ again:
* op and is typically set, avoiding the read. If a read
* is required in special append mode, the server will
* probably send us a short-read since we extended the file
- * on our end, resulting in b_resid == 0 and, thusly,
+ * on our end, resulting in b_resid == 0 and, thusly,
* B_CACHE getting set.
*
* We can also avoid issuing the read if the write covers
@@ -1001,15 +893,15 @@ again:
/*
* If dirtyend exceeds file size, chop it down. This should
* not normally occur but there is an append race where it
- * might occur XXX, so we log it.
+ * might occur XXX, so we log it.
*
* If the chopping creates a reverse-indexed or degenerate
* situation with dirtyoff/end, we 0 both of them.
*/
if (bp->b_dirtyend > bcount) {
- printf("NFS append race @%lx:%d\n",
- (long)bp->b_blkno * DEV_BSIZE,
+ printf("NFS append race @%lx:%d\n",
+ (long)bp->b_blkno * DEV_BSIZE,
bp->b_dirtyend - bcount);
bp->b_dirtyend = bcount;
}
@@ -1022,9 +914,9 @@ again:
* area, just update the b_dirtyoff and b_dirtyend,
* otherwise force a write rpc of the old dirty area.
*
- * While it is possible to merge discontiguous writes due to
+ * While it is possible to merge discontiguous writes due to
* our having a B_CACHE buffer ( and thus valid read data
- * for the hole), we don't because it could lead to
+ * for the hole), we don't because it could lead to
* significant cache coherency problems with multiple clients,
* especially if locking is implemented later on.
*
@@ -1041,30 +933,6 @@ again:
goto again;
}
- /*
- * Check for valid write lease and get one as required.
- * In case getblk() and/or bwrite() delayed us.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) &&
- NQNFS_CKINVALID(vp, np, ND_WRITE)) {
- do {
- error = nqnfs_getlease(vp, ND_WRITE, cred, td);
- } while (error == NQNFS_EXPIRED);
- if (error) {
- brelse(bp);
- break;
- }
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE)) {
- brelse(bp);
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- break;
- np->n_brev = np->n_lrev;
- goto again;
- }
- }
-
error = uiomove((char *)bp->b_data + on, n, uio);
/*
@@ -1082,7 +950,7 @@ again:
}
/*
- * Only update dirtyoff/dirtyend if not a degenerate
+ * Only update dirtyoff/dirtyend if not a degenerate
* condition.
*/
if (n) {
@@ -1097,24 +965,18 @@ again:
}
/*
- * If the lease is non-cachable or IO_SYNC do bwrite().
+ * If IO_SYNC do bwrite().
*
* IO_INVAL appears to be unused. The idea appears to be
* to turn off caching in this case. Very odd. XXX
*/
- if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) {
+ if ((ioflag & IO_SYNC)) {
if (ioflag & IO_INVAL)
bp->b_flags |= B_NOCACHE;
error = BUF_WRITE(bp);
if (error)
break;
- if (np->n_flag & NQNFSNONCACHE) {
- error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
- if (error)
- break;
- }
- } else if ((n + on) == biosize &&
- (nmp->nm_flag & NFSMNT_NQNFS) == 0) {
+ } else if ((n + on) == biosize) {
bp->b_flags |= B_ASYNC;
(void)nfs_writebp(bp, 0, 0);
} else {
@@ -1144,13 +1006,9 @@ again:
* its EOF.
*/
static struct buf *
-nfs_getcacheblk(vp, bn, size, td)
- struct vnode *vp;
- daddr_t bn;
- int size;
- struct thread *td;
+nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, struct thread *td)
{
- register struct buf *bp;
+ struct buf *bp;
struct mount *mp;
struct nfsmount *nmp;
@@ -1182,14 +1040,10 @@ nfs_getcacheblk(vp, bn, size, td)
* doing the flush, just wait for completion.
*/
int
-nfs_vinvalbuf(vp, flags, cred, td, intrflg)
- struct vnode *vp;
- int flags;
- struct ucred *cred;
- struct thread *td;
- int intrflg;
+nfs_vinvalbuf(struct vnode *vp, int flags, struct ucred *cred,
+ struct thread *td, int intrflg)
{
- register struct nfsnode *np = VTONFS(vp);
+ struct nfsnode *np = VTONFS(vp);
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
int error = 0, slpflag, slptimeo;
@@ -1213,7 +1067,8 @@ nfs_vinvalbuf(vp, flags, cred, td, intrflg)
np->n_flag |= NFLUSHWANT;
error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "nfsvinval",
slptimeo);
- if (error && intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc))
+ if (error && intrflg &&
+ nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc))
return (EINTR);
}
@@ -1223,7 +1078,8 @@ nfs_vinvalbuf(vp, flags, cred, td, intrflg)
np->n_flag |= NFLUSHINPROG;
error = vinvalbuf(vp, flags, cred, td, slpflag, 0);
while (error) {
- if (intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
+ if (intrflg &&
+ nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
np->n_flag &= ~NFLUSHINPROG;
if (np->n_flag & NFLUSHWANT) {
np->n_flag &= ~NFLUSHWANT;
@@ -1250,10 +1106,7 @@ nfs_vinvalbuf(vp, flags, cred, td, intrflg)
* is eventually dequeued by the async daemon, nfs_doio() *will*.
*/
int
-nfs_asyncio(bp, cred, td)
- register struct buf *bp;
- struct ucred *cred;
- struct thread *td;
+nfs_asyncio(struct buf *bp, struct ucred *cred, struct thread *td)
{
struct nfsmount *nmp;
int i;
@@ -1272,7 +1125,7 @@ nfs_asyncio(bp, cred, td)
nmp = VFSTONFS(bp->b_vp->v_mount);
/*
- * Commits are usually short and sweet so lets save some cpu and
+ * Commits are usually short and sweet so lets save some cpu and
* leave the async daemons for more important rpc's (such as reads
* and writes).
*/
@@ -1385,10 +1238,7 @@ again:
* synchronously or from an nfsiod.
*/
int
-nfs_doio(bp, cr, td)
- struct buf *bp;
- struct ucred *cr;
- struct thread *td;
+nfs_doio(struct buf *bp, struct ucred *cr, struct thread *td)
{
struct uio *uiop;
struct vnode *vp;
@@ -1397,7 +1247,7 @@ nfs_doio(bp, cr, td)
int error = 0, iomode, must_commit = 0;
struct uio uio;
struct iovec io;
- struct proc *p = td?td->td_proc:NULL;
+ struct proc *p = td ? td->td_proc : NULL;
vp = bp->b_vp;
np = VTONFS(vp);
@@ -1461,7 +1311,7 @@ nfs_doio(bp, cr, td)
* hit a file hole. We should zero-fill the remainder.
* This can also occur if the server hits the file EOF.
*
- * Holes used to be able to occur due to pending
+ * Holes used to be able to occur due to pending
* writes, but that is not possible any longer.
*/
int nread = bp->b_bcount - uiop->uio_resid;
@@ -1473,11 +1323,7 @@ nfs_doio(bp, cr, td)
}
}
if (p && (vp->v_flag & VTEXT) &&
- (((nmp->nm_flag & NFSMNT_NQNFS) &&
- NQNFS_CKINVALID(vp, np, ND_READ) &&
- np->n_lrev != np->n_brev) ||
- (!(nmp->nm_flag & NFSMNT_NQNFS) &&
- np->n_mtime != np->n_vattr.va_mtime.tv_sec))) {
+ (np->n_mtime != np->n_vattr.va_mtime.tv_sec)) {
uprintf("Process killed due to text file modification\n");
PROC_LOCK(p);
psignal(p, SIGKILL);
@@ -1508,7 +1354,7 @@ nfs_doio(bp, cr, td)
bp->b_flags |= B_INVAL;
break;
default:
- printf("nfs_doio: type %x unexpected\n",vp->v_type);
+ printf("nfs_doio: type %x unexpected\n", vp->v_type);
break;
};
if (error) {
@@ -1516,7 +1362,7 @@ nfs_doio(bp, cr, td)
bp->b_error = error;
}
} else {
- /*
+ /*
* If we only need to commit, try to commit
*/
if (bp->b_flags & B_NEEDCOMMIT) {
@@ -1569,7 +1415,7 @@ nfs_doio(bp, cr, td)
* When setting B_NEEDCOMMIT also set B_CLUSTEROK to try
* to cluster the buffers needing commit. This will allow
* the system to submit a single commit rpc for the whole
- * cluster. We can do this even if the buffer is not 100%
+ * cluster. We can do this even if the buffer is not 100%
* dirty (relative to the NFS blocksize), so we optimize the
* append-to-file-case.
*
diff --git a/sys/nfsclient/nfs_lock.c b/sys/nfsclient/nfs_lock.c
index b97b3b8..ce047ba 100644
--- a/sys/nfsclient/nfs_lock.c
+++ b/sys/nfsclient/nfs_lock.c
@@ -26,9 +26,11 @@
* SUCH DAMAGE.
*
* from BSDI nfs_lock.c,v 2.4 1998/12/14 23:49:56 jch Exp
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/fcntl.h>
@@ -52,11 +54,11 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfs_lock.h>
-#include <nfs/nlminfo.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfs_lock.h>
+#include <nfsclient/nlminfo.h>
#define NFSOWNER_1ST_LEVEL_START 1 /* initial entries */
#define NFSOWNER_2ND_LEVEL 256 /* some power of 2 */
@@ -67,7 +69,7 @@
/*
* XXX
* We have to let the process know if the call succeeded. I'm using an extra
- * field in the p_nlminfo field in the proc structure, as it is already for
+ * field in the p_nlminfo field in the proc structure, as it is already for
* lockd stuff.
*/
@@ -76,14 +78,7 @@
* NFS advisory byte-level locks.
*/
int
-nfs_dolock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
+nfs_dolock(struct vop_advlock_args *ap)
{
LOCKD_MSG msg;
struct nameidata nd;
@@ -198,10 +193,10 @@ nfs_dolock(ap)
* retry after 20 seconds if we haven't gotten a responce yet.
* This number was picked out of thin air... but is longer
* then even a reasonably loaded system should take (at least
- * on a local network). XXX Probably should use a back-off
+ * on a local network). XXX Probably should use a back-off
* scheme.
*/
- if ((error = tsleep((void *)p->p_nlminfo,
+ if ((error = tsleep((void *)p->p_nlminfo,
PCATCH | PUSER, "lockd", 20*hz)) != 0) {
if (error == EWOULDBLOCK) {
/*
@@ -238,14 +233,12 @@ nfs_dolock(ap)
* NFS advisory byte-level locks answer from the lock daemon.
*/
int
-nfslockdans(p, ansp)
- struct proc *p;
- struct lockd_ans *ansp;
+nfslockdans(struct proc *p, struct lockd_ans *ansp)
{
int error;
/* Let root, or someone who once was root (lockd generally
- * switches to the daemon uid once it is done setting up) make
+ * switches to the daemon uid once it is done setting up) make
* this call.
*
* XXX This authorization check is probably not right.
@@ -261,7 +254,7 @@ nfslockdans(p, ansp)
if ((p = pfind(ansp->la_msg_ident.pid)) == NULL)
return (ESRCH);
- /* verify the pid hasn't been reused (if we can), and it isn't waiting
+ /* verify the pid hasn't been reused (if we can), and it isn't waiting
* for an answer from a more recent request. We return an EPIPE if
* the match fails, because we've already used ESRCH above, and this
* is sort of like writing on a pipe after the reader has closed it.
diff --git a/sys/nfsclient/nfs_lock.h b/sys/nfsclient/nfs_lock.h
index 64b6c70..0d081c4 100644
--- a/sys/nfsclient/nfs_lock.h
+++ b/sys/nfsclient/nfs_lock.h
@@ -31,7 +31,7 @@
/*
* lockd uses the nfssvc system call to get the unique kernel services it needs.
* It passes in a request structure with a version number at the start.
- * This prevents libc from needing to change if the information passed
+ * This prevents libc from needing to change if the information passed
* between lockd and the kernel needs to change.
*
* If a structure changes, you must bump the version number.
@@ -39,26 +39,7 @@
#include <nfs/nfsproto.h>
-
-#define LOCKD_REQ_VERSION 1
-
-struct lockd_req {
- int vers; /* keep in sync with kernel please */
- int op; /* F_GETLK | F_SETLK | F_UNLCK */
- int owner; /* owner of lock, -1 to allocate one */
- int owner_rel_ok; /* release owner if no locks left ? */
- int *owner_ret; /* owner alloc/free result target */
- void *fh; /* NFS file handle */
- size_t fh_len; /* NFS file handle length */
- u_quad_t offset; /* offset of where to start lock */
- u_quad_t len; /* length of range to lock */
- int type; /* F_RDLCK | F_WRLCK | F_UNLCK */
- struct ucred cred; /* user credentials to use for lock */
- struct sockaddr saddr; /* XXX how about non AF_INET ?? */
- int pid; /* pid of lock requester */
-};
-
-/*
+/*
* The fifo where the kernel writes requests for locks on remote NFS files,
* and where lockd reads these requests.
*
@@ -107,6 +88,5 @@ struct lockd_ans {
#ifdef _KERNEL
int nfs_dolock(struct vop_advlock_args *ap);
-int nfslockdans(struct proc *p, struct lockd_ans *ansp);
-int nfslockdreq(struct proc *p, struct lockd_req *reqp);
+int nfslockdans(struct proc *p, struct lockd_ans *ansp);
#endif
diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c
index 657f299..4e0ac10 100644
--- a/sys/nfsclient/nfs_nfsiod.c
+++ b/sys/nfsclient/nfs_nfsiod.c
@@ -34,9 +34,11 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
@@ -56,43 +58,26 @@
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/namei.h>
+#include <sys/unistd.h>
+#include <sys/kthread.h>
#include <sys/fcntl.h>
#include <sys/lockf.h>
+#include <sys/mutex.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <nfs/xdr_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsrvcache.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nfs_lock.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsm_subs.h>
+#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfs_lock.h>
static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure");
-/* Global defs. */
-extern int32_t (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp));
-extern int nfs_numasync;
-extern time_t nqnfsstarttime;
-extern int nqsrv_writeslack;
-extern int nfsrtton;
-extern struct nfsstats nfsstats;
-extern int nfsrvw_procrastinate;
-extern int nfsrvw_procrastinate_v3;
-static int nuidhash_max = NFS_MAXUIDHASH;
-
-#ifndef NFS_NOSERVER
-static void nfsrv_zapsock __P((struct nfssvc_sock *slp));
-#endif
-static int nfssvc_iod __P((struct thread *));
+static void nfssvc_iod(void *);
#define TRUE 1
#define FALSE 0
@@ -101,849 +86,52 @@ static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
SYSCTL_DECL(_vfs_nfs);
-#ifndef NFS_NOSERVER
-int nfsd_waiting = 0;
-static struct nfsdrt nfsdrt;
-static int nfs_numnfsd = 0;
-static int notstarted = 1;
-static int modify_flag = 0;
-static void nfsd_rt __P((int sotype, struct nfsrv_descript *nd,
- int cacherep));
-static int nfssvc_addsock __P((struct file *, struct sockaddr *,
- struct thread *));
-static int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,
- struct thread *));
-
-static int nfs_privport = 0;
-SYSCTL_INT(_vfs_nfs, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW, &nfs_privport, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay, CTLFLAG_RW, &nfsrvw_procrastinate, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay_v3, CTLFLAG_RW, &nfsrvw_procrastinate_v3, 0, "");
-
-/*
- * NFS server system calls
- */
-
-#endif /* NFS_NOSERVER */
-/*
- * Nfs server psuedo system call for the nfsd's
- * Based on the flag value it either:
- * - adds a socket to the selection list
- * - remains in the kernel as an nfsd
- * - remains in the kernel as an nfsiod
- */
-#ifndef _SYS_SYSPROTO_H_
-struct nfssvc_args {
- int flag;
- caddr_t argp;
-};
-#endif
-/*
- * MPSAFE
- */
-int
-nfssvc(td, uap)
- struct thread *td;
- register struct nfssvc_args *uap;
+static void
+nfsiod_setup(void *dummy)
{
-#ifndef NFS_NOSERVER
- struct nameidata nd;
- struct file *fp;
- struct sockaddr *nam;
- struct nfsd_args nfsdarg;
- struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;
- struct nfsd_cargs ncd;
- struct nfsd *nfsd;
- struct nfssvc_sock *slp;
- struct nfsuid *nuidp;
- struct nfsmount *nmp;
-#endif /* NFS_NOSERVER */
+ int i;
int error;
+ struct proc *p;
- mtx_lock(&Giant);
-
- if ((uap->flag & NFSSVC_LOCKDANS) != 0) {
- struct lockd_ans la;
-
- error = copyin(uap->argp, &la, sizeof(la));
- if (error == 0)
- error = nfslockdans(td->td_proc, &la);
- goto done2;
- }
- /*
- * Must be super user
- */
- error = suser_td(td);
- if (error)
- goto done2;
- while (nfssvc_sockhead_flag & SLP_INIT) {
- nfssvc_sockhead_flag |= SLP_WANTINIT;
- (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0);
- }
- if (uap->flag & NFSSVC_BIOD)
- error = nfssvc_iod(td);
-#ifdef NFS_NOSERVER
- else
- error = ENXIO;
-#else /* !NFS_NOSERVER */
- else if (uap->flag & NFSSVC_MNTD) {
- error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd));
- if (error)
- goto done2;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
- ncd.ncd_dirp, td);
- error = namei(&nd);
- if (error)
- goto done2;
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if ((nd.ni_vp->v_flag & VROOT) == 0)
- error = EINVAL;
- nmp = VFSTONFS(nd.ni_vp->v_mount);
- vput(nd.ni_vp);
+ for (i = 0; i < 4; i++) {
+ error = kthread_create(nfssvc_iod, NULL, &p, RFHIGHPID,
+ "nfsiod %d", i);
if (error)
- goto done2;
- if ((nmp->nm_state & NFSSTA_MNTD) &&
- (uap->flag & NFSSVC_GOTAUTH) == 0) {
- error = 0;
- goto done2;
- }
- nmp->nm_state |= NFSSTA_MNTD;
- error = nqnfs_clientd(nmp, td->td_proc->p_ucred, &ncd, uap->flag,
- uap->argp, td);
- } else if (uap->flag & NFSSVC_ADDSOCK) {
- error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg));
- if (error)
- goto done2;
- error = holdsock(td->td_proc->p_fd, nfsdarg.sock, &fp);
- if (error)
- goto done2;
- /*
- * Get the client address for connected sockets.
- */
- if (nfsdarg.name == NULL || nfsdarg.namelen == 0)
- nam = (struct sockaddr *)0;
- else {
- error = getsockaddr(&nam, nfsdarg.name,
- nfsdarg.namelen);
- if (error) {
- fdrop(fp, td);
- goto done2;
- }
- }
- error = nfssvc_addsock(fp, nam, td);
- fdrop(fp, td);
- } else {
- error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd));
- if (error)
- goto done2;
- if ((uap->flag & NFSSVC_AUTHIN) &&
- ((nfsd = nsd->nsd_nfsd)) != NULL &&
- (nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
- slp = nfsd->nfsd_slp;
-
- /*
- * First check to see if another nfsd has already
- * added this credential.
- */
- for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
- (!nfsd->nfsd_nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
- nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
- } else {
- /*
- * Nope, so we will.
- */
- if (slp->ns_numuids < nuidhash_max) {
- slp->ns_numuids++;
- nuidp = (struct nfsuid *)
- malloc(sizeof (struct nfsuid), M_NFSUID,
- M_WAITOK);
- } else
- nuidp = (struct nfsuid *)0;
- if ((slp->ns_flag & SLP_VALID) == 0) {
- if (nuidp)
- free((caddr_t)nuidp, M_NFSUID);
- } else {
- if (nuidp == (struct nfsuid *)0) {
- nuidp = slp->ns_uidlruhead.tqh_first;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
- nu_lru);
- if (nuidp->nu_flag & NU_NAM)
- FREE(nuidp->nu_nam, M_SONAME);
- }
- nuidp->nu_flag = 0;
- bzero(&nuidp->nu_cr, sizeof(nuidp->nu_cr));
- nuidp->nu_cr.cr_uid = nsd->nsd_cr.cr_uid;
- nuidp->nu_cr.cr_ngroups =
- nsd->nsd_cr.cr_ngroups;
- bcopy(nsd->nsd_cr.cr_groups,
- nuidp->nu_cr.cr_groups,
- sizeof(nuidp->nu_cr.cr_groups));
- if (nuidp->nu_cr.cr_ngroups > NGROUPS)
- nuidp->nu_cr.cr_ngroups = NGROUPS;
- nuidp->nu_cr.cr_ref = 1;
- nuidp->nu_timestamp = nsd->nsd_timestamp;
- nuidp->nu_expire = time_second + nsd->nsd_ttl;
- /*
- * and save the session key in nu_key.
- */
- bcopy(nsd->nsd_key, nuidp->nu_key,
- sizeof (nsd->nsd_key));
- if (nfsd->nfsd_nd->nd_nam2) {
- struct sockaddr_in *saddr;
-
- saddr = (struct sockaddr_in *)
- nfsd->nfsd_nd->nd_nam2;
- switch (saddr->sin_family) {
- case AF_INET:
- nuidp->nu_flag |= NU_INETADDR;
- nuidp->nu_inetaddr =
- saddr->sin_addr.s_addr;
- break;
- case AF_ISO:
- default:
- nuidp->nu_flag |= NU_NAM;
- nuidp->nu_nam =
- dup_sockaddr(nfsd->nfsd_nd->
- nd_nam2, 1);
- break;
- };
- }
- TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
- nu_lru);
- LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
- nuidp, nu_hash);
- nfsrv_setcred(&nuidp->nu_cr,
- &nfsd->nfsd_nd->nd_cr);
- nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
- }
- }
- }
- if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
- nfsd->nfsd_flag |= NFSD_AUTHFAIL;
- error = nfssvc_nfsd(nsd, uap->argp, td);
- }
-#endif /* NFS_NOSERVER */
- if (error == EINTR || error == ERESTART)
- error = 0;
-done2:
- mtx_unlock(&Giant);
- return (error);
-}
-
-#ifndef NFS_NOSERVER
-/*
- * Adds a socket to the list for servicing by nfsds.
- */
-static int
-nfssvc_addsock(fp, mynam, td)
- struct file *fp;
- struct sockaddr *mynam;
- struct thread *td;
-{
- register int siz;
- register struct nfssvc_sock *slp;
- register struct socket *so;
- int error, s;
-
- so = (struct socket *)fp->f_data;
-#if 0
- tslp = (struct nfssvc_sock *)0;
- /*
- * Add it to the list, as required.
- */
- if (so->so_proto->pr_protocol == IPPROTO_UDP) {
- tslp = nfs_udpsock;
- if (tslp->ns_flag & SLP_VALID) {
- if (mynam != NULL)
- FREE(mynam, M_SONAME);
- return (EPERM);
- }
- }
-#endif
- if (so->so_type == SOCK_STREAM)
- siz = NFS_MAXPACKET + sizeof (u_long);
- else
- siz = NFS_MAXPACKET;
- error = soreserve(so, siz, siz);
- if (error) {
- if (mynam != NULL)
- FREE(mynam, M_SONAME);
- return (error);
- }
-
- /*
- * Set protocol specific options { for now TCP only } and
- * reserve some space. For datagram sockets, this can get called
- * repeatedly for the same socket, but that isn't harmful.
- */
- if (so->so_type == SOCK_STREAM) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_KEEPALIVE;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- if (so->so_proto->pr_domain->dom_family == AF_INET &&
- so->so_proto->pr_protocol == IPPROTO_TCP) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = IPPROTO_TCP;
- sopt.sopt_name = TCP_NODELAY;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- so->so_rcv.sb_flags &= ~SB_NOINTR;
- so->so_rcv.sb_timeo = 0;
- so->so_snd.sb_flags &= ~SB_NOINTR;
- so->so_snd.sb_timeo = 0;
-
- slp = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC,
- M_WAITOK | M_ZERO);
- STAILQ_INIT(&slp->ns_rec);
- TAILQ_INIT(&slp->ns_uidlruhead);
- TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
-
- slp->ns_so = so;
- slp->ns_nam = mynam;
- fp->f_count++;
- slp->ns_fp = fp;
- s = splnet();
- so->so_upcallarg = (caddr_t)slp;
- so->so_upcall = nfsrv_rcv;
- so->so_rcv.sb_flags |= SB_UPCALL;
- slp->ns_flag = (SLP_VALID | SLP_NEEDQ);
- nfsrv_wakenfsd(slp);
- splx(s);
- return (0);
-}
-
-/*
- * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
- * until it is killed by a signal.
- */
-static int
-nfssvc_nfsd(nsd, argp, td)
- struct nfsd_srvargs *nsd;
- caddr_t argp;
- struct thread *td;
-{
- register int siz;
- register struct nfssvc_sock *slp;
- struct nfsd *nfsd = nsd->nsd_nfsd;
- struct nfsrv_descript *nd = NULL;
- struct mbuf *m, *mreq;
- int error = 0, cacherep, s, sotype, writes_todo;
- int procrastinate;
- u_quad_t cur_usec;
-
-#ifndef nolint
- cacherep = RC_DOIT;
- writes_todo = 0;
-#endif
- if (nfsd == (struct nfsd *)0) {
- nsd->nsd_nfsd = nfsd = (struct nfsd *)
- malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK | M_ZERO);
- s = splnet();
- nfsd->nfsd_td = td;
- TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
- nfs_numnfsd++;
- } else
- s = splnet();
-
- /*
- * Loop getting rpc requests until SIGKILL.
- */
- for (;;) {
- if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
- while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
- (nfsd_head_flag & NFSD_CHECKSLP) == 0) {
- nfsd->nfsd_flag |= NFSD_WAITING;
- nfsd_waiting++;
- error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
- "nfsd", 0);
- nfsd_waiting--;
- if (error)
- goto done;
- }
- if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
- (nfsd_head_flag & NFSD_CHECKSLP) != 0) {
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
- if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
- == (SLP_VALID | SLP_DOREC)) {
- slp->ns_flag &= ~SLP_DOREC;
- slp->ns_sref++;
- nfsd->nfsd_slp = slp;
- break;
- }
- }
- if (slp == 0)
- nfsd_head_flag &= ~NFSD_CHECKSLP;
- }
- if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
- continue;
- if (slp->ns_flag & SLP_VALID) {
- if (slp->ns_flag & SLP_DISCONN)
- nfsrv_zapsock(slp);
- else if (slp->ns_flag & SLP_NEEDQ) {
- slp->ns_flag &= ~SLP_NEEDQ;
- (void) nfs_slplock(slp, 1);
- nfsrv_rcv(slp->ns_so, (caddr_t)slp,
- M_TRYWAIT);
- nfs_slpunlock(slp);
- }
- error = nfsrv_dorec(slp, nfsd, &nd);
- cur_usec = nfs_curusec();
- if (error && slp->ns_tq.lh_first &&
- slp->ns_tq.lh_first->nd_time <= cur_usec) {
- error = 0;
- cacherep = RC_DOIT;
- writes_todo = 1;
- } else
- writes_todo = 0;
- nfsd->nfsd_flag |= NFSD_REQINPROG;
- }
- } else {
- error = 0;
- slp = nfsd->nfsd_slp;
- }
- if (error || (slp->ns_flag & SLP_VALID) == 0) {
- if (nd) {
- free((caddr_t)nd, M_NFSRVDESC);
- nd = NULL;
- }
- nfsd->nfsd_slp = (struct nfssvc_sock *)0;
- nfsd->nfsd_flag &= ~NFSD_REQINPROG;
- nfsrv_slpderef(slp);
- continue;
- }
- splx(s);
- sotype = slp->ns_so->so_type;
- if (nd) {
- getmicrotime(&nd->nd_starttime);
- if (nd->nd_nam2)
- nd->nd_nam = nd->nd_nam2;
- else
- nd->nd_nam = slp->ns_nam;
-
- /*
- * Check to see if authorization is needed.
- */
- if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
- nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
- nsd->nsd_haddr =
- ((struct sockaddr_in *)
- nd->nd_nam)->sin_addr.s_addr;
- nsd->nsd_authlen = nfsd->nfsd_authlen;
- nsd->nsd_verflen = nfsd->nfsd_verflen;
- if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
- nfsd->nfsd_authlen) &&
- !copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
- nfsd->nfsd_verflen) &&
- !copyout((caddr_t)nsd, argp, sizeof (*nsd)))
- return (ENEEDAUTH);
- cacherep = RC_DROPIT;
- } else
- cacherep = nfsrv_getcache(nd, slp, &mreq);
-
- /*
- * Check for just starting up for NQNFS and send
- * fake "try again later" replies to the NQNFS clients.
- */
- if (notstarted && nqnfsstarttime <= time_second) {
- if (modify_flag) {
- nqnfsstarttime = time_second + nqsrv_writeslack;
- modify_flag = 0;
- } else
- notstarted = 0;
- }
- if (notstarted) {
- if ((nd->nd_flag & ND_NQNFS) == 0)
- cacherep = RC_DROPIT;
- else if (nd->nd_procnum != NFSPROC_WRITE) {
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = NQNFS_TRYLATER;
- cacherep = RC_DOIT;
- } else
- modify_flag = 1;
- } else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
- nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- cacherep = RC_DOIT;
- } else if (nfs_privport) {
- /* Check if source port is privileged */
- u_short port;
- struct sockaddr *nam = nd->nd_nam;
- struct sockaddr_in *sin;
-
- sin = (struct sockaddr_in *)nam;
- port = ntohs(sin->sin_port);
- if (port >= IPPORT_RESERVED &&
- nd->nd_procnum != NFSPROC_NULL) {
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- cacherep = RC_DOIT;
- printf("NFS request from unprivileged port (%s:%d)\n",
- inet_ntoa(sin->sin_addr), port);
- }
- }
-
- }
-
- /*
- * Loop to get all the write rpc relies that have been
- * gathered together.
- */
- do {
- switch (cacherep) {
- case RC_DOIT:
- if (nd && (nd->nd_flag & ND_NFSV3))
- procrastinate = nfsrvw_procrastinate_v3;
- else
- procrastinate = nfsrvw_procrastinate;
- if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
- procrastinate > 0 && !notstarted))
- error = nfsrv_writegather(&nd, slp,
- nfsd->nfsd_td, &mreq);
- else
- error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
- slp, nfsd->nfsd_td, &mreq);
- if (mreq == NULL)
- break;
- if (error != 0 && error != NFSERR_RETVOID) {
- if (nd->nd_procnum != NQNFSPROC_VACATED)
- nfsstats.srv_errs++;
- nfsrv_updatecache(nd, FALSE, mreq);
- if (nd->nd_nam2)
- FREE(nd->nd_nam2, M_SONAME);
- break;
- }
- nfsstats.srvrpccnt[nd->nd_procnum]++;
- nfsrv_updatecache(nd, TRUE, mreq);
- nd->nd_mrep = (struct mbuf *)0;
- case RC_REPLY:
- m = mreq;
- siz = 0;
- while (m) {
- siz += m->m_len;
- m = m->m_next;
- }
- if (siz <= 0 || siz > NFS_MAXPACKET) {
- printf("mbuf siz=%d\n",siz);
- panic("Bad nfs svc reply");
- }
- m = mreq;
- m->m_pkthdr.len = siz;
- m->m_pkthdr.rcvif = (struct ifnet *)0;
- /*
- * For stream protocols, prepend a Sun RPC
- * Record Mark.
- */
- if (sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 | siz);
- }
- if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
- (void) nfs_slplock(slp, 1);
- if (slp->ns_flag & SLP_VALID)
- error = nfs_send(slp->ns_so, nd->nd_nam2, m, NULL);
- else {
- error = EPIPE;
- m_freem(m);
- }
- if (nfsrtton)
- nfsd_rt(sotype, nd, cacherep);
- if (nd->nd_nam2)
- FREE(nd->nd_nam2, M_SONAME);
- if (nd->nd_mrep)
- m_freem(nd->nd_mrep);
- if (error == EPIPE)
- nfsrv_zapsock(slp);
- if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
- nfs_slpunlock(slp);
- if (error == EINTR || error == ERESTART) {
- free((caddr_t)nd, M_NFSRVDESC);
- nfsrv_slpderef(slp);
- s = splnet();
- goto done;
- }
- break;
- case RC_DROPIT:
- if (nfsrtton)
- nfsd_rt(sotype, nd, cacherep);
- m_freem(nd->nd_mrep);
- if (nd->nd_nam2)
- FREE(nd->nd_nam2, M_SONAME);
- break;
- };
- if (nd) {
- FREE((caddr_t)nd, M_NFSRVDESC);
- nd = NULL;
- }
-
- /*
- * Check to see if there are outstanding writes that
- * need to be serviced.
- */
- cur_usec = nfs_curusec();
- s = splsoftclock();
- if (slp->ns_tq.lh_first &&
- slp->ns_tq.lh_first->nd_time <= cur_usec) {
- cacherep = RC_DOIT;
- writes_todo = 1;
- } else
- writes_todo = 0;
- splx(s);
- } while (writes_todo);
- s = splnet();
- if (nfsrv_dorec(slp, nfsd, &nd)) {
- nfsd->nfsd_flag &= ~NFSD_REQINPROG;
- nfsd->nfsd_slp = NULL;
- nfsrv_slpderef(slp);
- }
+ panic("nfsiod_setup: kthread_create error %d", error);
}
-done:
- TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
- splx(s);
- free((caddr_t)nfsd, M_NFSD);
- nsd->nsd_nfsd = (struct nfsd *)0;
- if (--nfs_numnfsd == 0)
- nfsrv_init(TRUE); /* Reinitialize everything */
- return (error);
}
+SYSINIT(nfsiod, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, nfsiod_setup, NULL);
-/*
- * Shut down a socket associated with an nfssvc_sock structure.
- * Should be called with the send lock set, if required.
- * The trick here is to increment the sref at the start, so that the nfsds
- * will stop using it and clear ns_flag at the end so that it will not be
- * reassigned during cleanup.
- */
-static void
-nfsrv_zapsock(slp)
- register struct nfssvc_sock *slp;
-{
- register struct nfsuid *nuidp, *nnuidp;
- register struct nfsrv_descript *nwp, *nnwp;
- struct socket *so;
- struct file *fp;
- struct nfsrv_rec *rec;
- int s;
-
- slp->ns_flag &= ~SLP_ALLFLAGS;
- fp = slp->ns_fp;
- if (fp) {
- slp->ns_fp = (struct file *)0;
- so = slp->ns_so;
- so->so_rcv.sb_flags &= ~SB_UPCALL;
- so->so_upcall = NULL;
- so->so_upcallarg = NULL;
- soshutdown(so, 2);
- closef(fp, (struct thread *)0);
- if (slp->ns_nam)
- FREE(slp->ns_nam, M_SONAME);
- m_freem(slp->ns_raw);
- while ((rec = STAILQ_FIRST(&slp->ns_rec)) != NULL) {
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- if (rec->nr_address)
- FREE(rec->nr_address, M_SONAME);
- m_freem(rec->nr_packet);
- free(rec, M_NFSRVDESC);
- }
- for (nuidp = slp->ns_uidlruhead.tqh_first; nuidp != 0;
- nuidp = nnuidp) {
- nnuidp = nuidp->nu_lru.tqe_next;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
- if (nuidp->nu_flag & NU_NAM)
- FREE(nuidp->nu_nam, M_SONAME);
- free((caddr_t)nuidp, M_NFSUID);
- }
- s = splsoftclock();
- for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
- nnwp = nwp->nd_tq.le_next;
- LIST_REMOVE(nwp, nd_tq);
- free((caddr_t)nwp, M_NFSRVDESC);
- }
- LIST_INIT(&slp->ns_tq);
- splx(s);
- }
-}
-
-/*
- * Derefence a server socket structure. If it has no more references and
- * is no longer valid, you can throw it away.
- */
-void
-nfsrv_slpderef(slp)
- register struct nfssvc_sock *slp;
-{
- if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
- TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
- free((caddr_t)slp, M_NFSSVC);
- }
-}
+static int nfs_defect = 0;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0, "");
-/*
- * Lock a socket against others.
- */
int
-nfs_slplock(slp, wait)
- register struct nfssvc_sock *slp;
- int wait;
+nfsclnt(struct thread *td, struct nfsclnt_args *uap)
{
- int *statep = &slp->ns_solock;
-
- if (!wait && (*statep & NFSSTA_SNDLOCK))
- return(0); /* already locked, fail */
- while (*statep & NFSSTA_SNDLOCK) {
- *statep |= NFSSTA_WANTSND;
- (void) tsleep((caddr_t)statep, PZERO - 1, "nfsslplck", 0);
- }
- *statep |= NFSSTA_SNDLOCK;
- return (1);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-void
-nfs_slpunlock(slp)
- register struct nfssvc_sock *slp;
-{
- int *statep = &slp->ns_solock;
-
- if ((*statep & NFSSTA_SNDLOCK) == 0)
- panic("nfs slpunlock");
- *statep &= ~NFSSTA_SNDLOCK;
- if (*statep & NFSSTA_WANTSND) {
- *statep &= ~NFSSTA_WANTSND;
- wakeup((caddr_t)statep);
- }
-}
-
-/*
- * Initialize the data structures for the server.
- * Handshake with any new nfsds starting up to avoid any chance of
- * corruption.
- */
-void
-nfsrv_init(terminating)
- int terminating;
-{
- register struct nfssvc_sock *slp, *nslp;
-
- if (nfssvc_sockhead_flag & SLP_INIT)
- panic("nfsd init");
- nfssvc_sockhead_flag |= SLP_INIT;
- if (terminating) {
- for (slp = nfssvc_sockhead.tqh_first; slp != 0; slp = nslp) {
- nslp = slp->ns_chain.tqe_next;
- if (slp->ns_flag & SLP_VALID)
- nfsrv_zapsock(slp);
- TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
- free((caddr_t)slp, M_NFSSVC);
- }
- nfsrv_cleancache(); /* And clear out server cache */
- } else
- nfs_pub.np_valid = 0;
+ struct lockd_ans la;
+ int error;
- TAILQ_INIT(&nfssvc_sockhead);
- nfssvc_sockhead_flag &= ~SLP_INIT;
- if (nfssvc_sockhead_flag & SLP_WANTINIT) {
- nfssvc_sockhead_flag &= ~SLP_WANTINIT;
- wakeup((caddr_t)&nfssvc_sockhead);
+ if ((uap->flag & NFSCLNT_LOCKDANS) != 0) {
+ error = copyin(uap->argp, &la, sizeof(la));
+ return (error != 0 ? error : nfslockdans(td->td_proc, &la));
}
-
- TAILQ_INIT(&nfsd_head);
- nfsd_head_flag &= ~NFSD_CHECKSLP;
-
-#if 0
- nfs_udpsock = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
- STAILQ_INIT(&nfs_udpsock->ns_rec);
- TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
- TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
-
- nfs_cltpsock = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
- STAILQ_INIT(&nfs_cltpsock->ns_rec);
- TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
- TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
-#endif
+ return EINVAL;
}
/*
- * Add entries to the server monitor log.
- */
-static void
-nfsd_rt(sotype, nd, cacherep)
- int sotype;
- register struct nfsrv_descript *nd;
- int cacherep;
-{
- register struct drt *rt;
-
- rt = &nfsdrt.drt[nfsdrt.pos];
- if (cacherep == RC_DOIT)
- rt->flag = 0;
- else if (cacherep == RC_REPLY)
- rt->flag = DRT_CACHEREPLY;
- else
- rt->flag = DRT_CACHEDROP;
- if (sotype == SOCK_STREAM)
- rt->flag |= DRT_TCP;
- if (nd->nd_flag & ND_NQNFS)
- rt->flag |= DRT_NQNFS;
- else if (nd->nd_flag & ND_NFSV3)
- rt->flag |= DRT_NFSV3;
- rt->proc = nd->nd_procnum;
- if (nd->nd_nam->sa_family == AF_INET)
- rt->ipadr = ((struct sockaddr_in *)nd->nd_nam)->sin_addr.s_addr;
- else
- rt->ipadr = INADDR_ANY;
- rt->resptime = nfs_curusec() - (nd->nd_starttime.tv_sec * 1000000 + nd->nd_starttime.tv_usec);
- getmicrotime(&rt->tstamp);
- nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
-}
-#endif /* NFS_NOSERVER */
-
-static int nfs_defect = 0;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0, "");
-
-/*
* Asynchronous I/O daemons for client nfs.
* They do read-ahead and write-behind operations on the block I/O cache.
* Never returns unless it fails or gets killed.
*/
-static int
-nfssvc_iod(td)
- struct thread *td;
+static void
+nfssvc_iod(void *dummy)
{
- register struct buf *bp;
- register int i, myiod;
+ struct buf *bp;
+ int i, myiod;
struct nfsmount *nmp;
int error = 0;
+ mtx_lock(&Giant);
/*
* Assign my position or return error if too many already running
*/
@@ -955,18 +143,18 @@ nfssvc_iod(td)
break;
}
if (myiod == -1)
- return (EBUSY);
+ return /* XXX (EBUSY) */;
nfs_numasync++;
/*
* Just loop around doin our stuff until SIGKILL
*/
for (;;) {
while (((nmp = nfs_iodmount[myiod]) == NULL
- || nmp->nm_bufq.tqh_first == NULL)
+ || !TAILQ_FIRST(&nmp->nm_bufq))
&& error == 0) {
if (nmp)
nmp->nm_bufqiods--;
- nfs_iodwant[myiod] = td->td_proc;
+ nfs_iodwant[myiod] = curthread->td_proc;
nfs_iodmount[myiod] = NULL;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
@@ -978,9 +166,9 @@ nfssvc_iod(td)
nfs_iodwant[myiod] = NULL;
nfs_iodmount[myiod] = NULL;
nfs_numasync--;
- return (error);
+ return /* XXX (error) */;
}
- while ((bp = nmp->nm_bufq.tqh_first) != NULL) {
+ while ((bp = TAILQ_FIRST(&nmp->nm_bufq)) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist);
nmp->nm_bufqlen--;
@@ -1007,208 +195,3 @@ nfssvc_iod(td)
}
}
}
-
-
-/*
- * Get an authorization string for the uid by having the mount_nfs sitting
- * on this mount point porpous out of the kernel and do it.
- */
-int
-nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
- struct ucred *cred;
- char **auth_str;
- int *auth_len;
- char *verf_str;
- int *verf_len;
- NFSKERBKEY_T key; /* return session key */
-{
- int error = 0;
-
- while ((nmp->nm_state & NFSSTA_WAITAUTH) == 0) {
- nmp->nm_state |= NFSSTA_WANTAUTH;
- (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK,
- "nfsauth1", 2 * hz);
- error = nfs_sigintr(nmp, rep, rep->r_td->td_proc);
- if (error) {
- nmp->nm_state &= ~NFSSTA_WANTAUTH;
- return (error);
- }
- }
- nmp->nm_state &= ~(NFSSTA_WAITAUTH | NFSSTA_WANTAUTH);
- nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
- nmp->nm_authlen = RPCAUTH_MAXSIZ;
- nmp->nm_verfstr = verf_str;
- nmp->nm_verflen = *verf_len;
- nmp->nm_authuid = cred->cr_uid;
- wakeup((caddr_t)&nmp->nm_authstr);
-
- /*
- * And wait for mount_nfs to do its stuff.
- */
- while ((nmp->nm_state & NFSSTA_HASAUTH) == 0 && error == 0) {
- (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK,
- "nfsauth2", 2 * hz);
- error = nfs_sigintr(nmp, rep, rep->r_td->td_proc);
- }
- if (nmp->nm_state & NFSSTA_AUTHERR) {
- nmp->nm_state &= ~NFSSTA_AUTHERR;
- error = EAUTH;
- }
- if (error)
- free((caddr_t)*auth_str, M_TEMP);
- else {
- *auth_len = nmp->nm_authlen;
- *verf_len = nmp->nm_verflen;
- bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
- }
- nmp->nm_state &= ~NFSSTA_HASAUTH;
- nmp->nm_state |= NFSSTA_WAITAUTH;
- if (nmp->nm_state & NFSSTA_WANTAUTH) {
- nmp->nm_state &= ~NFSSTA_WANTAUTH;
- wakeup((caddr_t)&nmp->nm_authtype);
- }
- return (error);
-}
-
-/*
- * Get a nickname authenticator and verifier.
- */
-int
-nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
- struct nfsmount *nmp;
- struct ucred *cred;
- char **auth_str;
- int *auth_len;
- char *verf_str;
- int verf_len;
-{
- register struct nfsuid *nuidp;
- register u_int32_t *nickp, *verfp;
- struct timeval ktvin, ktvout;
-
-#ifdef DIAGNOSTIC
- if (verf_len < (4 * NFSX_UNSIGNED))
- panic("nfs_getnickauth verf too small");
-#endif
- for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == cred->cr_uid)
- break;
- }
- if (!nuidp || nuidp->nu_expire < time_second)
- return (EACCES);
-
- /*
- * Move to the end of the lru list (end of lru == most recently used).
- */
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
- TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
-
- nickp = (u_int32_t *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
- *nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
- *nickp = txdr_unsigned(nuidp->nu_nickname);
- *auth_str = (char *)nickp;
- *auth_len = 2 * NFSX_UNSIGNED;
-
- /*
- * Now we must encrypt the verifier and package it up.
- */
- verfp = (u_int32_t *)verf_str;
- *verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
- if (time_second > nuidp->nu_timestamp.tv_sec ||
- (time_second == nuidp->nu_timestamp.tv_sec &&
- time_second > nuidp->nu_timestamp.tv_usec))
- getmicrotime(&nuidp->nu_timestamp);
- else
- nuidp->nu_timestamp.tv_usec++;
- ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
- ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Now encrypt the timestamp verifier in ecb mode using the session
- * key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *verfp++ = ktvout.tv_sec;
- *verfp++ = ktvout.tv_usec;
- *verfp = 0;
- return (0);
-}
-
-/*
- * Save the current nickname in a hash list entry on the mount point.
- */
-int
-nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
- register struct nfsmount *nmp;
- struct ucred *cred;
- int len;
- NFSKERBKEY_T key;
- struct mbuf **mdp;
- char **dposp;
- struct mbuf *mrep;
-{
- register struct nfsuid *nuidp;
- register u_int32_t *tl;
- register int32_t t1;
- struct mbuf *md = *mdp;
- struct timeval ktvin, ktvout;
- u_int32_t nick;
- char *dpos = *dposp, *cp2;
- int deltasec, error = 0;
-
- if (len == (3 * NFSX_UNSIGNED)) {
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- ktvin.tv_sec = *tl++;
- ktvin.tv_usec = *tl++;
- nick = fxdr_unsigned(u_int32_t, *tl);
-
- /*
- * Decrypt the timestamp in ecb mode.
- */
-#ifdef NFSKERB
- XXX
-#endif
- ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
- ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
- deltasec = time_second - ktvout.tv_sec;
- if (deltasec < 0)
- deltasec = -deltasec;
- /*
- * If ok, add it to the hash list for the mount point.
- */
- if (deltasec <= NFS_KERBCLOCKSKEW) {
- if (nmp->nm_numuids < nuidhash_max) {
- nmp->nm_numuids++;
- nuidp = (struct nfsuid *)
- malloc(sizeof (struct nfsuid), M_NFSUID,
- M_WAITOK);
- } else {
- nuidp = nmp->nm_uidlruhead.tqh_first;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
- nu_lru);
- }
- nuidp->nu_flag = 0;
- nuidp->nu_cr.cr_uid = cred->cr_uid;
- nuidp->nu_expire = time_second + NFS_KERBTTL;
- nuidp->nu_timestamp = ktvout;
- nuidp->nu_nickname = nick;
- bcopy(key, nuidp->nu_key, sizeof (key));
- TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
- nu_lru);
- LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
- nuidp, nu_hash);
- }
- } else
- nfsm_adv(nfsm_rndup(len));
-nfsmout:
- *mdp = md;
- *dposp = dpos;
- return (error);
-}
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index 5fe3abc..21769e2 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -34,9 +34,10 @@
* SUCH DAMAGE.
*
* @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
@@ -54,21 +55,23 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfsmount.h>
static vm_zone_t nfsnode_zone;
static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
static u_long nfsnodehash;
+static int nfs_node_hash_lock;
#define TRUE 1
#define FALSE 0
+SYSCTL_DECL(_debug_hashstat);
+
/*
* Grab an atomic snapshot of the nfsnode hash chain lengths
*/
-SYSCTL_DECL(_debug_hashstat);
static int
sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS)
{
@@ -94,8 +97,8 @@ sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS)
}
return (0);
}
-SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD,
- 0, 0, sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths");
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD, 0, 0,
+ sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths");
static int
sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS)
@@ -148,8 +151,9 @@ SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD,
* and build nfsnode free list.
*/
void
-nfs_nhinit()
+nfs_nhinit(void)
{
+
nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1);
nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash);
}
@@ -160,19 +164,13 @@ nfs_nhinit()
* In all cases, a pointer to a
* nfsnode structure is returned.
*/
-static int nfs_node_hash_lock;
-
int
-nfs_nget(mntp, fhp, fhsize, npp)
- struct mount *mntp;
- register nfsfh_t *fhp;
- int fhsize;
- struct nfsnode **npp;
+nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
{
struct thread *td = curthread; /* XXX */
struct nfsnode *np, *np2;
struct nfsnodehashhead *nhpp;
- register struct vnode *vp;
+ struct vnode *vp;
struct vnode *nvp;
int error;
int rsflags;
@@ -191,7 +189,7 @@ nfs_nget(mntp, fhp, fhsize, npp)
retry:
nhpp = NFSNOHASH(fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT));
loop:
- for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
+ LIST_FOREACH(np, nhpp, n_hash) {
if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
continue;
@@ -220,7 +218,7 @@ loop:
* elsewhere if zalloc should block.
*/
np = zalloc(nfsnode_zone);
-
+
error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
if (error) {
if (nfs_node_hash_lock < 0)
@@ -237,7 +235,7 @@ loop:
/*
* Insert the nfsnode in the hash queue for its new file handle
*/
- for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) {
+ LIST_FOREACH(np2, nhpp, n_hash) {
if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize ||
bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize))
continue;
@@ -272,14 +270,10 @@ loop:
}
int
-nfs_inactive(ap)
- struct vop_inactive_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- } */ *ap;
+nfs_inactive(struct vop_inactive_args *ap)
{
- register struct nfsnode *np;
- register struct sillyrename *sp;
+ struct nfsnode *np;
+ struct sillyrename *sp;
struct thread *td = curthread; /* XXX */
np = VTONFS(ap->a_vp);
@@ -314,8 +308,7 @@ nfs_inactive(ap)
vrele(sp->s_dvp);
FREE((caddr_t)sp, M_NFSREQ);
}
- np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
- NQNFSNONCACHE | NQNFSWRITE);
+ np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT);
VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
return (0);
}
@@ -324,39 +317,28 @@ nfs_inactive(ap)
* Reclaim an nfsnode so that it can be used for other purposes.
*/
int
-nfs_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
+nfs_reclaim(struct vop_reclaim_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- register struct nfsdmap *dp, *dp2;
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
+ struct nfsdmap *dp, *dp2;
if (prtactive && vp->v_usecount != 0)
vprint("nfs_reclaim: pushing active", vp);
- if (np->n_hash.le_prev != NULL)
+ if (np->n_hash.le_prev != NULL) /* XXX beware */
LIST_REMOVE(np, n_hash);
/*
- * For nqnfs, take it off the timer queue as required.
- */
- if ((nmp->nm_flag & NFSMNT_NQNFS) && TAILQ_NEXT(np, n_timer) != 0) {
- TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
- }
-
- /*
* Free up any directory cookie structures and
* large file handle structures that might be associated with
* this nfs node.
*/
if (vp->v_type == VDIR) {
- dp = np->n_cookies.lh_first;
+ dp = LIST_FIRST(&np->n_cookies);
while (dp) {
dp2 = dp;
- dp = dp->ndm_list.le_next;
+ dp = LIST_NEXT(dp, ndm_list);
FREE((caddr_t)dp2, M_NFSDIROFF);
}
}
@@ -377,12 +359,9 @@ nfs_reclaim(ap)
* Lock an nfsnode
*/
int
-nfs_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
+nfs_lock(struct vop_lock_args *ap)
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
/*
* Ugh, another place where interruptible mounts will get hung.
@@ -429,10 +408,7 @@ nfs_lock(ap)
* Unlock an nfsnode
*/
int
-nfs_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
+nfs_unlock(struct vop_unlock_args *ap)
{
#if 0
struct vnode* vp = ap->a_vp;
@@ -456,12 +432,9 @@ nfs_unlock(ap)
* Check for a locked nfsnode
*/
int
-nfs_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- } */ *ap;
+nfs_islocked(struct vop_islocked_args *ap)
{
+
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
}
#endif
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index 8991672..4bf50e4 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -34,9 +34,11 @@
* SUCH DAMAGE.
*
* @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* Socket operations for use by nfs
*/
@@ -63,13 +65,11 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
+#include <nfsclient/nfs.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nqnfs.h>
+#include <nfsclient/nfsm_subs.h>
+#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfsnode.h>
#define TRUE 1
#define FALSE 0
@@ -93,17 +93,6 @@
((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
#define NFS_SRTT(r) (r)->r_nmp->nm_srtt[proct[(r)->r_procnum] - 1]
#define NFS_SDRTT(r) (r)->r_nmp->nm_sdrtt[proct[(r)->r_procnum] - 1]
-/*
- * External data, mostly RPC constants in XDR form
- */
-extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers,
- rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr,
- rpc_auth_kerb;
-extern u_int32_t nfs_prog, nqnfs_prog;
-extern time_t nqnfsstarttime;
-extern struct nfsstats nfsstats;
-extern int nfsv3_procid[NFS_NPROCS];
-extern int nfs_ticks;
/*
* Defines which timer to use for the procnum.
@@ -115,12 +104,11 @@ extern int nfs_ticks;
*/
static int proct[NFS_NPROCS] = {
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
- 0, 0, 0,
};
-static int nfs_realign_test;
-static int nfs_realign_count;
-static int nfs_bufpackets = 4;
+static int nfs_realign_test;
+static int nfs_realign_count;
+static int nfs_bufpackets = 4;
SYSCTL_DECL(_vfs_nfs);
@@ -145,64 +133,26 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, "");
#define NFS_CWNDSCALE 256
#define NFS_MAXCWND (NFS_CWNDSCALE * 32)
static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
-int nfsrtton = 0;
-struct nfsrtt nfsrtt;
struct callout_handle nfs_timer_handle;
-static int nfs_msg __P((struct thread *,char *,char *));
-static int nfs_rcvlock __P((struct nfsreq *));
-static void nfs_rcvunlock __P((struct nfsreq *));
-static void nfs_realign __P((struct mbuf **pm, int hsiz));
-static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
- struct mbuf **mp));
-static void nfs_softterm __P((struct nfsreq *rep));
-static int nfs_reconnect __P((struct nfsreq *rep));
-#ifndef NFS_NOSERVER
-static int nfsrv_getstream __P((struct nfssvc_sock *,int));
-
-int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp)) = {
- nfsrv_null,
- nfsrv_getattr,
- nfsrv_setattr,
- nfsrv_lookup,
- nfsrv3_access,
- nfsrv_readlink,
- nfsrv_read,
- nfsrv_write,
- nfsrv_create,
- nfsrv_mkdir,
- nfsrv_symlink,
- nfsrv_mknod,
- nfsrv_remove,
- nfsrv_rmdir,
- nfsrv_rename,
- nfsrv_link,
- nfsrv_readdir,
- nfsrv_readdirplus,
- nfsrv_statfs,
- nfsrv_fsinfo,
- nfsrv_pathconf,
- nfsrv_commit,
- nqnfsrv_getlease,
- nqnfsrv_vacated,
- nfsrv_noop,
- nfsrv_noop
-};
-#endif /* NFS_NOSERVER */
+static int nfs_msg(struct thread *, char *, char *);
+static int nfs_rcvlock(struct nfsreq *);
+static void nfs_rcvunlock(struct nfsreq *);
+static void nfs_realign(struct mbuf **pm, int hsiz);
+static int nfs_receive(struct nfsreq *rep, struct sockaddr **aname,
+ struct mbuf **mp);
+static int nfs_reply(struct nfsreq *);
+static void nfs_softterm(struct nfsreq *rep);
+static int nfs_reconnect(struct nfsreq *rep);
/*
* Initialize sockets and congestion for a new NFS connection.
* We do not free the sockaddr if error.
*/
int
-nfs_connect(nmp, rep)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
+nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
{
- register struct socket *so;
+ struct socket *so;
int s, error, rcvreserve, sndreserve;
int pktscale;
struct sockaddr *saddr;
@@ -364,7 +314,7 @@ nfs_connect(nmp, rep)
so->so_snd.sb_flags |= SB_NOINTR;
/* Initialize other non-zero congestion variables */
- nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] =
+ nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] =
nmp->nm_srtt[3] = (NFS_TIMEO << 3);
nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] =
nmp->nm_sdrtt[3] = 0;
@@ -388,11 +338,10 @@ bad:
* nb: Must be called with the nfs_sndlock() set on the mount point.
*/
static int
-nfs_reconnect(rep)
- register struct nfsreq *rep;
+nfs_reconnect(struct nfsreq *rep)
{
- register struct nfsreq *rp;
- register struct nfsmount *nmp = rep->r_nmp;
+ struct nfsreq *rp;
+ struct nfsmount *nmp = rep->r_nmp;
int error;
nfs_disconnect(nmp);
@@ -406,7 +355,7 @@ nfs_reconnect(rep)
* Loop through outstanding request list and fix up all requests
* on old socket.
*/
- for (rp = nfs_reqq.tqh_first; rp != 0; rp = rp->r_chain.tqe_next) {
+ TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
if (rp->r_nmp == nmp)
rp->r_flags |= R_MUSTRESEND;
}
@@ -417,10 +366,9 @@ nfs_reconnect(rep)
* NFS disconnect. Clean up and unlink.
*/
void
-nfs_disconnect(nmp)
- register struct nfsmount *nmp;
+nfs_disconnect(struct nfsmount *nmp)
{
- register struct socket *so;
+ struct socket *so;
if (nmp->nm_so) {
so = nmp->nm_so;
@@ -431,8 +379,7 @@ nfs_disconnect(nmp)
}
void
-nfs_safedisconnect(nmp)
- struct nfsmount *nmp;
+nfs_safedisconnect(struct nfsmount *nmp)
{
struct nfsreq dummyreq;
@@ -446,40 +393,31 @@ nfs_safedisconnect(nmp)
/*
* This is the nfs send routine. For connection based socket types, it
* must be called with an nfs_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 (?)
*/
int
-nfs_send(so, nam, top, rep)
- register struct socket *so;
- struct sockaddr *nam;
- register struct mbuf *top;
- struct nfsreq *rep;
+nfs_send(struct socket *so, struct sockaddr *nam, struct mbuf *top,
+ struct nfsreq *rep)
{
struct sockaddr *sendnam;
int error, soflags, flags;
- if (rep) {
- if (rep->r_flags & R_SOFTTERM) {
- m_freem(top);
- return (EINTR);
- }
- if ((so = rep->r_nmp->nm_so) == NULL) {
- rep->r_flags |= R_MUSTRESEND;
- m_freem(top);
- return (0);
- }
- rep->r_flags &= ~R_MUSTRESEND;
- soflags = rep->r_nmp->nm_soflags;
- } else
- soflags = so->so_proto->pr_flags;
+ KASSERT(rep, ("nfs_send: called with rep == NULL"));
+
+ if (rep->r_flags & R_SOFTTERM) {
+ m_freem(top);
+ return (EINTR);
+ }
+ if ((so = rep->r_nmp->nm_so) == NULL) {
+ rep->r_flags |= R_MUSTRESEND;
+ m_freem(top);
+ return (0);
+ }
+ rep->r_flags &= ~R_MUSTRESEND;
+ soflags = rep->r_nmp->nm_soflags;
+
if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
sendnam = (struct sockaddr *)0;
else
@@ -491,29 +429,21 @@ nfs_send(so, nam, top, rep)
error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
flags, curthread /*XXX*/);
- /*
- * ENOBUFS for dgram sockets is transient and non fatal.
- * No need to log, and no need to break a soft mount.
- */
if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
error = 0;
- if (rep) /* do backoff retransmit on client */
- rep->r_flags |= R_MUSTRESEND;
+ rep->r_flags |= R_MUSTRESEND;
}
if (error) {
- if (rep) {
- log(LOG_INFO, "nfs send error %d for server %s\n",error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- /*
- * 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, "nfsd send error %d\n", error);
+ log(LOG_INFO, "nfs send error %d for server %s\n", error,
+ rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
+ /*
+ * Deal with errors for the client side.
+ */
+ if (rep->r_flags & R_SOFTTERM)
+ error = EINTR;
+ else
+ rep->r_flags |= R_MUSTRESEND;
/*
* Handle any recoverable (soft) socket errors here. (?)
@@ -535,15 +465,12 @@ nfs_send(so, nam, top, rep)
* we have read any of it, even if the system call has been interrupted.
*/
static int
-nfs_receive(rep, aname, mp)
- register struct nfsreq *rep;
- struct sockaddr **aname;
- struct mbuf **mp;
+nfs_receive(struct nfsreq *rep, struct sockaddr **aname, struct mbuf **mp)
{
- register struct socket *so;
+ struct socket *so;
struct uio auio;
struct iovec aio;
- register struct mbuf *m;
+ struct mbuf *m;
struct mbuf *control;
u_int32_t len;
struct sockaddr **getnam;
@@ -760,17 +687,16 @@ errout:
* with outstanding requests using the xid, until ours is found.
*/
/* ARGSUSED */
-int
-nfs_reply(myrep)
- struct nfsreq *myrep;
+static int
+nfs_reply(struct nfsreq *myrep)
{
- register struct nfsreq *rep;
- register struct nfsmount *nmp = myrep->r_nmp;
- register int32_t t1;
+ struct nfsreq *rep;
+ struct nfsmount *nmp = myrep->r_nmp;
+ int32_t t1;
struct mbuf *mrep, *md;
struct sockaddr *nam;
u_int32_t rxid, *tl;
- caddr_t dpos, cp2;
+ caddr_t dpos;
int error;
/*
@@ -822,18 +748,8 @@ nfs_reply(myrep)
nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED);
rxid = *tl++;
if (*tl != rpc_reply) {
-#ifndef NFS_NOSERVER
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (nqnfs_callback(nmp, mrep, md, dpos))
- nfsstats.rpcinvalid++;
- } else {
- nfsstats.rpcinvalid++;
- m_freem(mrep);
- }
-#else
nfsstats.rpcinvalid++;
m_freem(mrep);
-#endif
nfsmout:
if (myrep->r_flags & R_GETONEREP)
return (0);
@@ -844,31 +760,12 @@ nfsmout:
* Loop through the request list to match up the reply
* Iff no match, just drop the datagram
*/
- for (rep = nfs_reqq.tqh_first; rep != 0;
- rep = rep->r_chain.tqe_next) {
+ TAILQ_FOREACH(rep, &nfs_reqq, 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;
- if (nfsrtton) {
- struct rttl *rt;
-
- rt = &nfsrtt.rttl[nfsrtt.pos];
- rt->proc = rep->r_procnum;
- rt->rto = NFS_RTO(nmp, proct[rep->r_procnum]);
- rt->sent = nmp->nm_sent;
- rt->cwnd = nmp->nm_cwnd;
- rt->srtt = nmp->nm_srtt[proct[rep->r_procnum] - 1];
- rt->sdrtt = nmp->nm_sdrtt[proct[rep->r_procnum] - 1];
- rt->fsid = nmp->nm_mountp->mnt_stat.f_fsid;
- getmicrotime(&rt->tstamp);
- if (rep->r_flags & R_TIMING)
- rt->rtt = rep->r_rtt;
- else
- rt->rtt = 1000000;
- nfsrtt.pos = (nfsrtt.pos + 1) % NFSRTTLOGSIZ;
- }
/*
* Update congestion window.
* Do the additive increase of
@@ -937,34 +834,25 @@ nfsmout:
* by mrep or error
* nb: always frees up mreq mbuf list
*/
+/* XXX overloaded before */
+#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
+
int
-nfs_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp)
- struct vnode *vp;
- struct mbuf *mrest;
- int procnum;
- struct thread *td;
- struct ucred *cred;
- struct mbuf **mrp;
- struct mbuf **mdp;
- caddr_t *dposp;
+nfs_request(struct vnode *vp, struct mbuf *mrest, int procnum,
+ struct thread *td, struct ucred *cred, struct mbuf **mrp,
+ struct mbuf **mdp, caddr_t *dposp)
{
- register struct mbuf *mrep, *m2;
- register struct nfsreq *rep;
- register u_int32_t *tl;
- register int i;
+ struct mbuf *mrep, *m2;
+ struct nfsreq *rep;
+ u_int32_t *tl;
+ int i;
struct nfsmount *nmp;
struct mbuf *m, *md, *mheadend;
- struct nfsnode *np;
- char nickv[RPCX_NICKVERF];
- time_t reqtime, waituntil;
- caddr_t dpos, cp2;
- int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
- int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
- int verf_len, verf_type;
+ time_t waituntil;
+ caddr_t dpos;
+ int s, error = 0, mrest_len, auth_len, auth_type;
+ int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0;
u_int32_t xid;
- u_quad_t frev;
- char *auth_str, *verf_str;
- NFSKERBKEY_T key; /* save session key */
nmp = VFSTONFS(vp->v_mount);
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
@@ -983,35 +871,14 @@ nfs_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp)
/*
* Get the RPC header with authorization.
*/
-kerbauth:
- verf_str = auth_str = (char *)0;
- if (nmp->nm_flag & NFSMNT_KERB) {
- verf_str = nickv;
- verf_len = sizeof (nickv);
- auth_type = RPCAUTH_KERB4;
- bzero((caddr_t)key, sizeof (key));
- if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
- &auth_len, verf_str, verf_len)) {
- error = nfs_getauth(nmp, rep, cred, &auth_str,
- &auth_len, verf_str, &verf_len, key);
- if (error) {
- free((caddr_t)rep, M_NFSREQ);
- m_freem(mrest);
- return (error);
- }
- }
- } else {
- auth_type = RPCAUTH_UNIX;
- if (cred->cr_ngroups < 1)
- panic("nfsreq nogrps");
- auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
- nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
- 5 * NFSX_UNSIGNED;
- }
+ auth_type = RPCAUTH_UNIX;
+ if (cred->cr_ngroups < 1)
+ panic("nfsreq nogrps");
+ auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
+ nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
+ 5 * NFSX_UNSIGNED;
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
- auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
- if (auth_str)
- free(auth_str, M_TEMP);
+ mrest, mrest_len, &mheadend, &xid);
/*
* For stream protocols, insert a Sun RPC Record Mark.
@@ -1046,9 +913,6 @@ tryagain:
s = splsoftclock();
TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
- /* Get send time for nqnfs */
- reqtime = time_second;
-
/*
* If backing off another request or avoiding congestion, don't
* send this one now but let timer do it. If not timing a request,
@@ -1119,16 +983,7 @@ tryagain:
if (*tl++ == rpc_msgdenied) {
if (*tl == rpc_mismatch)
error = EOPNOTSUPP;
- else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
- if (!failed_auth) {
- failed_auth++;
- mheadend->m_next = (struct mbuf *)0;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- goto kerbauth;
- } else
- error = EAUTH;
- } else
+ else
error = EACCES;
m_freem(mrep);
m_freem(rep->r_mreq);
@@ -1137,15 +992,11 @@ tryagain:
}
/*
- * Grab any Kerberos verifier, otherwise just throw it away.
+ * Just throw away any verifyer (ie: kerberos etc).
*/
- verf_type = fxdr_unsigned(int, *tl++);
- i = fxdr_unsigned(int32_t, *tl);
- if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
- error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
- if (error)
- goto nfsmout;
- } else if (i > 0)
+ i = fxdr_unsigned(int, *tl++); /* verf type */
+ i = fxdr_unsigned(int32_t, *tl); /* len */
+ if (i > 0)
nfsm_adv(nfsm_rndup(i));
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
/* 0 == ok */
@@ -1185,24 +1036,6 @@ tryagain:
return (error);
}
- /*
- * For nqnfs, get any lease in reply
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl) {
- np = VTONFS(vp);
- nqlflag = fxdr_unsigned(int, *tl);
- nfsm_dissect(tl, u_int32_t *, 4*NFSX_UNSIGNED);
- cachable = fxdr_unsigned(int, *tl++);
- reqtime += fxdr_unsigned(int, *tl++);
- if (reqtime > time_second) {
- frev = fxdr_hyper(tl);
- nqnfs_clientlease(nmp, np, nqlflag,
- cachable, reqtime, frev);
- }
- }
- }
*mrp = mrep;
*mdp = md;
*dposp = dpos;
@@ -1218,162 +1051,6 @@ nfsmout:
return (error);
}
-#ifndef NFS_NOSERVER
-/*
- * Generate the rpc reply header
- * siz arg. is used to decide if adding a cluster is worthwhile
- */
-int
-nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
- int siz;
- struct nfsrv_descript *nd;
- struct nfssvc_sock *slp;
- int err;
- int cache;
- u_quad_t *frev;
- struct mbuf **mrq;
- struct mbuf **mbp;
- caddr_t *bposp;
-{
- register u_int32_t *tl;
- register struct mbuf *mreq;
- caddr_t bpos;
- struct mbuf *mb, *mb2;
-
- MGETHDR(mreq, M_TRYWAIT, MT_DATA);
- mb = mreq;
- /*
- * If this is a big reply, use a cluster else
- * try and leave leading space for the lower level headers.
- */
- siz += RPC_REPLYSIZ;
- if ((max_hdr + siz) >= MINCLSIZE) {
- MCLGET(mreq, M_TRYWAIT);
- } else
- mreq->m_data += max_hdr;
- tl = mtod(mreq, u_int32_t *);
- mreq->m_len = 6 * NFSX_UNSIGNED;
- bpos = ((caddr_t)tl) + mreq->m_len;
- *tl++ = txdr_unsigned(nd->nd_retxid);
- *tl++ = rpc_reply;
- if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
- *tl++ = rpc_msgdenied;
- if (err & NFSERR_AUTHERR) {
- *tl++ = rpc_autherr;
- *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
- mreq->m_len -= NFSX_UNSIGNED;
- bpos -= NFSX_UNSIGNED;
- } else {
- *tl++ = rpc_mismatch;
- *tl++ = txdr_unsigned(RPC_VER2);
- *tl = txdr_unsigned(RPC_VER2);
- }
- } else {
- *tl++ = rpc_msgaccepted;
-
- /*
- * For Kerberos authentication, we must send the nickname
- * verifier back, otherwise just RPCAUTH_NULL.
- */
- if (nd->nd_flag & ND_KERBFULL) {
- register struct nfsuid *nuidp;
- struct timeval ktvin, ktvout;
-
- for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
- (!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- ktvin.tv_sec =
- txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
- ktvin.tv_usec =
- txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Encrypt the timestamp in ecb mode using the
- * session key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *tl++ = rpc_auth_kerb;
- *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
- *tl = ktvout.tv_sec;
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- *tl++ = ktvout.tv_usec;
- *tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- switch (err) {
- case EPROGUNAVAIL:
- *tl = txdr_unsigned(RPC_PROGUNAVAIL);
- break;
- case EPROGMISMATCH:
- *tl = txdr_unsigned(RPC_PROGMISMATCH);
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (nd->nd_flag & ND_NQNFS) {
- *tl++ = txdr_unsigned(3);
- *tl = txdr_unsigned(3);
- } else {
- *tl++ = txdr_unsigned(2);
- *tl = txdr_unsigned(3);
- }
- break;
- case EPROCUNAVAIL:
- *tl = txdr_unsigned(RPC_PROCUNAVAIL);
- break;
- case EBADRPC:
- *tl = txdr_unsigned(RPC_GARBAGE);
- break;
- default:
- *tl = 0;
- if (err != NFSERR_RETVOID) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- if (err)
- *tl = txdr_unsigned(nfsrv_errmap(nd, err));
- else
- *tl = 0;
- }
- break;
- };
- }
-
- /*
- * For nqnfs, piggyback lease as requested.
- */
- if ((nd->nd_flag & ND_NQNFS) && err == 0) {
- if (nd->nd_flag & ND_LEASE) {
- nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
- *tl++ = txdr_unsigned(cache);
- *tl++ = txdr_unsigned(nd->nd_duration);
- txdr_hyper(*frev, tl);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- if (mrq != NULL)
- *mrq = mreq;
- *mbp = mb;
- *bposp = bpos;
- if (err != 0 && err != NFSERR_RETVOID)
- nfsstats.srvrpc_errs++;
- return (0);
-}
-
-
-#endif /* NFS_NOSERVER */
/*
* Nfs timer routine
* Scan the nfsreq list and retranmit any requests that have timed out
@@ -1381,24 +1058,18 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
* sure to set the r_retry field to 0 (implies nm_retry == 0).
*/
void
-nfs_timer(arg)
- void *arg; /* never used */
+nfs_timer(void *arg)
{
- register struct nfsreq *rep;
- register struct mbuf *m;
- register struct socket *so;
- register struct nfsmount *nmp;
- register int timeo;
+ struct nfsreq *rep;
+ struct mbuf *m;
+ struct socket *so;
+ struct nfsmount *nmp;
+ int timeo;
int s, error;
-#ifndef NFS_NOSERVER
- static long lasttime = 0;
- register struct nfssvc_sock *slp;
- u_quad_t cur_usec;
-#endif /* NFS_NOSERVER */
struct thread *td = thread0; /* XXX for credentials, will break if sleep */
s = splnet();
- for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
+ TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
nmp = rep->r_nmp;
if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
continue;
@@ -1425,9 +1096,12 @@ nfs_timer(arg)
*/
if ((rep->r_flags & R_TPRINTFMSG) == 0 &&
rep->r_rexmit > nmp->nm_deadthresh) {
+ char buf[40];
+ sprintf(buf, "not responding %d > %d",
+ rep->r_rexmit, nmp->nm_deadthresh);
nfs_msg(rep->r_td,
nmp->nm_mountp->mnt_stat.f_mntfromname,
- "not responding");
+ buf /* "not responding" */);
rep->r_flags |= R_TPRINTFMSG;
}
if (rep->r_rexmit >= rep->r_retry) { /* too many */
@@ -1487,26 +1161,6 @@ nfs_timer(arg)
}
}
}
-#ifndef NFS_NOSERVER
- /*
- * Call the nqnfs server timer once a second to handle leases.
- */
- if (lasttime != time_second) {
- lasttime = time_second;
- nqnfs_serverd();
- }
-
- /*
- * Scan the write gathering queues for writes that need to be
- * completed now.
- */
- cur_usec = nfs_curusec();
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
- if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
- nfsrv_wakenfsd(slp);
- }
-#endif /* NFS_NOSERVER */
splx(s);
nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
}
@@ -1518,11 +1172,10 @@ nfs_timer(arg)
*/
static void
-nfs_softterm(rep)
- struct nfsreq *rep;
+nfs_softterm(struct nfsreq *rep)
{
- rep->r_flags |= R_SOFTTERM;
+ rep->r_flags |= R_SOFTTERM;
if (rep->r_flags & R_SENT) {
rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
rep->r_flags &= ~R_SENT;
@@ -1534,10 +1187,7 @@ nfs_softterm(rep)
* This is used for NFSMNT_INT mounts.
*/
int
-nfs_sigintr(nmp, rep, p)
- struct nfsmount *nmp;
- struct nfsreq *rep;
- register struct proc *p;
+nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct proc *p)
{
sigset_t tmpset;
@@ -1564,10 +1214,9 @@ nfs_sigintr(nmp, rep, p)
* in progress when a reconnect is necessary.
*/
int
-nfs_sndlock(rep)
- struct nfsreq *rep;
+nfs_sndlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
struct thread *td;
int slpflag = 0, slptimeo = 0;
@@ -1596,10 +1245,9 @@ nfs_sndlock(rep)
* Unlock the stream socket for others.
*/
void
-nfs_sndunlock(rep)
- struct nfsreq *rep;
+nfs_sndunlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
if ((*statep & NFSSTA_SNDLOCK) == 0)
panic("nfs sndunlock");
@@ -1611,10 +1259,9 @@ nfs_sndunlock(rep)
}
static int
-nfs_rcvlock(rep)
- register struct nfsreq *rep;
+nfs_rcvlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
int slpflag, slptimeo = 0;
if (rep->r_nmp->nm_flag & NFSMNT_INT)
@@ -1649,10 +1296,9 @@ nfs_rcvlock(rep)
* Unlock the stream socket for others.
*/
static void
-nfs_rcvunlock(rep)
- register struct nfsreq *rep;
+nfs_rcvunlock(struct nfsreq *rep)
{
- register int *statep = &rep->r_nmp->nm_state;
+ int *statep = &rep->r_nmp->nm_state;
if ((*statep & NFSSTA_RCVLOCK) == 0)
panic("nfs rcvunlock");
@@ -1679,16 +1325,13 @@ nfs_rcvunlock(rep)
* with TCP. Use vfs.nfs.realign_count and realign_test to check this.
*/
static void
-nfs_realign(pm, hsiz)
- register struct mbuf **pm;
- int hsiz;
+nfs_realign(struct mbuf **pm, int hsiz)
{
struct mbuf *m;
struct mbuf *n = NULL;
int off = 0;
++nfs_realign_test;
-
while ((m = *pm) != NULL) {
if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
MGET(n, M_TRYWAIT, MT_DATA);
@@ -1700,7 +1343,6 @@ nfs_realign(pm, hsiz)
}
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.
@@ -1717,580 +1359,11 @@ nfs_realign(pm, hsiz)
}
}
-#ifndef NFS_NOSERVER
-
-/*
- * Parse an RPC request
- * - verify it
- * - fill in the cred struct.
- */
-int
-nfs_getreq(nd, nfsd, has_header)
- register struct nfsrv_descript *nd;
- struct nfsd *nfsd;
- int has_header;
-{
- register int len, i;
- register u_int32_t *tl;
- register int32_t t1;
- struct uio uio;
- struct iovec iov;
- caddr_t dpos, cp2, cp;
- u_int32_t nfsvers, auth_type;
- uid_t nickuid;
- int error = 0, nqnfs = 0, ticklen;
- struct mbuf *mrep, *md;
- register struct nfsuid *nuidp;
- struct timeval tvin, tvout;
-#if 0 /* until encrypted keys are implemented */
- NFSKERBKEYSCHED_T keys; /* stores key schedule */
-#endif
-
- mrep = nd->nd_mrep;
- md = nd->nd_md;
- dpos = nd->nd_dpos;
- if (has_header) {
- nfsm_dissect(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
- nd->nd_retxid = fxdr_unsigned(u_int32_t, *tl++);
- if (*tl++ != rpc_call) {
- m_freem(mrep);
- return (EBADRPC);
- }
- } else
- nfsm_dissect(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
- nd->nd_repstat = 0;
- nd->nd_flag = 0;
- if (*tl++ != rpc_vers) {
- nd->nd_repstat = ERPCMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (*tl != nfs_prog) {
- if (*tl == nqnfs_prog)
- nqnfs++;
- else {
- nd->nd_repstat = EPROGUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- }
- tl++;
- nfsvers = fxdr_unsigned(u_int32_t, *tl++);
- if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
- (nfsvers != NQNFS_VER3 && nqnfs)) {
- nd->nd_repstat = EPROGMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (nqnfs)
- nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
- else if (nfsvers == NFS_VER3)
- nd->nd_flag = ND_NFSV3;
- nd->nd_procnum = fxdr_unsigned(u_int32_t, *tl++);
- if (nd->nd_procnum == NFSPROC_NULL)
- return (0);
- if (nd->nd_procnum >= NFS_NPROCS ||
- (!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
- (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
- nd->nd_repstat = EPROCUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if ((nd->nd_flag & ND_NFSV3) == 0)
- nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
- auth_type = *tl++;
- len = fxdr_unsigned(int, *tl++);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
-
- nd->nd_flag &= ~ND_KERBAUTH;
- /*
- * Handle auth_unix or auth_kerb.
- */
- if (auth_type == rpc_auth_unix) {
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > NFS_MAXNAMLEN) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_adv(nfsm_rndup(len));
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
- nd->nd_cr.cr_ref = 1;
- nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
- nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
- len = fxdr_unsigned(int, *tl);
- if (len < 0 || len > RPCAUTH_UNIXGIDS) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_dissect(tl, u_int32_t *, (len + 2) * NFSX_UNSIGNED);
- for (i = 1; i <= len; i++)
- if (i < NGROUPS)
- nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
- else
- tl++;
- nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
- if (nd->nd_cr.cr_ngroups > 1)
- nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
- if (len > 0)
- nfsm_adv(nfsm_rndup(len));
- } else if (auth_type == rpc_auth_kerb) {
- switch (fxdr_unsigned(int, *tl++)) {
- case RPCAKN_FULLNAME:
- ticklen = fxdr_unsigned(int, *tl);
- *((u_int32_t *)nfsd->nfsd_authstr) = *tl;
- uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
- nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
- if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
- m_freem(mrep);
- return (EBADRPC);
- }
- uio.uio_offset = 0;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_segflg = UIO_SYSSPACE;
- iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
- iov.iov_len = RPCAUTH_MAXSIZ - 4;
- nfsm_mtouio(&uio, uio.uio_resid);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
- printf("Bad kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
- tl = (u_int32_t *)cp;
- if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
- printf("Not fullname kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- cp += NFSX_UNSIGNED;
- bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
- nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
- nd->nd_flag |= ND_KERBFULL;
- nfsd->nfsd_flag |= NFSD_NEEDAUTH;
- break;
- case RPCAKN_NICKNAME:
- if (len != 2 * NFSX_UNSIGNED) {
- printf("Kerb nickname short\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nickuid = fxdr_unsigned(uid_t, *tl);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
- printf("Kerb nick verifier bad\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- tvin.tv_sec = *tl++;
- tvin.tv_usec = *tl;
-
- for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nickuid &&
- (!nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (!nuidp) {
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * Now, decrypt the timestamp using the session key
- * and validate it.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
- tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
- if (nuidp->nu_expire < time_second ||
- nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
- (nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
- nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
- nuidp->nu_expire = 0;
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
- nd->nd_flag |= ND_KERBNICK;
- };
- } else {
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * For nqnfs, get piggybacked lease request.
- */
- if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_flag |= fxdr_unsigned(int, *tl);
- if (nd->nd_flag & ND_LEASE) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_duration = fxdr_unsigned(int32_t, *tl);
- } else
- nd->nd_duration = NQ_MINLEASE;
- } else
- nd->nd_duration = NQ_MINLEASE;
- nd->nd_md = md;
- nd->nd_dpos = dpos;
- return (0);
-nfsmout:
- return (error);
-}
-
-#endif
static int
-nfs_msg(td, server, msg)
- struct thread *td;
- char *server, *msg;
+nfs_msg(struct thread *td, char *server, char *msg)
{
tprintf(td->td_proc, LOG_INFO, "nfs server %s: %s\n", server, msg);
return (0);
}
-
-#ifndef NFS_NOSERVER
-/*
- * Socket upcall routine for the nfsd sockets.
- * The caddr_t arg is a pointer to the "struct nfssvc_sock".
- * Essentially do as much as possible non-blocking, else punt and it will
- * be called with M_TRYWAIT from an nfsd.
- */
-void
-nfsrv_rcv(so, arg, waitflag)
- struct socket *so;
- void *arg;
- int waitflag;
-{
- register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
- register struct mbuf *m;
- struct mbuf *mp;
- struct sockaddr *nam;
- struct uio auio;
- int flags, error;
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
-#ifdef notdef
- /*
- * Define this to test for nfsds handling this under heavy load.
- */
- if (waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ; goto dorecs;
- }
-#endif
- auio.uio_td = NULL;
- if (so->so_type == SOCK_STREAM) {
- /*
- * If there are already records on the queue, defer soreceive()
- * to an nfsd so that there is feedback to the TCP layer that
- * the nfs servers are heavily loaded.
- */
- if (STAILQ_FIRST(&slp->ns_rec) && waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ;
- goto dorecs;
- }
-
- /*
- * Do soreceive().
- */
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, &nam, &auio, &mp, (struct mbuf **)0, &flags);
- if (error || mp == (struct mbuf *)0) {
- if (error == EWOULDBLOCK)
- slp->ns_flag |= SLP_NEEDQ;
- else
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- m = mp;
- if (slp->ns_rawend) {
- slp->ns_rawend->m_next = m;
- slp->ns_cc += 1000000000 - auio.uio_resid;
- } else {
- slp->ns_raw = m;
- slp->ns_cc = 1000000000 - auio.uio_resid;
- }
- while (m->m_next)
- m = m->m_next;
- slp->ns_rawend = m;
-
- /*
- * Now try and parse record(s) out of the raw stream data.
- */
- error = nfsrv_getstream(slp, waitflag);
- if (error) {
- if (error == EPERM)
- slp->ns_flag |= SLP_DISCONN;
- else
- slp->ns_flag |= SLP_NEEDQ;
- }
- } else {
- do {
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, &nam, &auio, &mp,
- (struct mbuf **)0, &flags);
- if (mp) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec),
- M_NFSRVDESC, waitflag);
- if (!rec) {
- if (nam)
- FREE(nam, M_SONAME);
- m_freem(mp);
- continue;
- }
- nfs_realign(&mp, 10 * NFSX_UNSIGNED);
- rec->nr_address = nam;
- rec->nr_packet = mp;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- }
- if (error) {
- if ((so->so_proto->pr_flags & PR_CONNREQUIRED)
- && error != EWOULDBLOCK) {
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- }
- } while (mp);
- }
-
- /*
- * Now try and process the request records, non-blocking.
- */
-dorecs:
- if (waitflag == M_DONTWAIT &&
- (STAILQ_FIRST(&slp->ns_rec)
- || (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))))
- nfsrv_wakenfsd(slp);
-}
-
-/*
- * Try and extract an RPC request from the mbuf data list received on a
- * stream socket. The "waitflag" argument indicates whether or not it
- * can sleep.
- */
-static int
-nfsrv_getstream(slp, waitflag)
- register struct nfssvc_sock *slp;
- int waitflag;
-{
- register struct mbuf *m, **mpp;
- register char *cp1, *cp2;
- register int len;
- struct mbuf *om, *m2, *recm = NULL;
- u_int32_t recmark;
-
- if (slp->ns_flag & SLP_GETSTREAM)
- panic("nfs getstream");
- slp->ns_flag |= SLP_GETSTREAM;
- for (;;) {
- if (slp->ns_reclen == 0) {
- if (slp->ns_cc < NFSX_UNSIGNED) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
- m = slp->ns_raw;
- if (m->m_len >= NFSX_UNSIGNED) {
- bcopy(mtod(m, caddr_t), (caddr_t)&recmark, NFSX_UNSIGNED);
- m->m_data += NFSX_UNSIGNED;
- m->m_len -= NFSX_UNSIGNED;
- } else {
- cp1 = (caddr_t)&recmark;
- cp2 = mtod(m, caddr_t);
- while (cp1 < ((caddr_t)&recmark) + NFSX_UNSIGNED) {
- while (m->m_len == 0) {
- m = m->m_next;
- cp2 = mtod(m, caddr_t);
- }
- *cp1++ = *cp2++;
- m->m_data++;
- m->m_len--;
- }
- }
- slp->ns_cc -= NFSX_UNSIGNED;
- recmark = ntohl(recmark);
- slp->ns_reclen = recmark & ~0x80000000;
- if (recmark & 0x80000000)
- slp->ns_flag |= SLP_LASTFRAG;
- else
- slp->ns_flag &= ~SLP_LASTFRAG;
- if (slp->ns_reclen > NFS_MAXPACKET) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EPERM);
- }
- }
-
- /*
- * Now get the record part.
- */
- if (slp->ns_cc == slp->ns_reclen) {
- recm = slp->ns_raw;
- slp->ns_raw = slp->ns_rawend = (struct mbuf *)0;
- slp->ns_cc = slp->ns_reclen = 0;
- } else if (slp->ns_cc > slp->ns_reclen) {
- len = 0;
- m = slp->ns_raw;
- om = (struct mbuf *)0;
- while (len < slp->ns_reclen) {
- if ((len + m->m_len) > slp->ns_reclen) {
- m2 = m_copym(m, 0, slp->ns_reclen - len,
- waitflag);
- if (m2) {
- if (om) {
- om->m_next = m2;
- recm = slp->ns_raw;
- } else
- recm = m2;
- m->m_data += slp->ns_reclen - len;
- m->m_len -= slp->ns_reclen - len;
- len = slp->ns_reclen;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EWOULDBLOCK);
- }
- } else if ((len + m->m_len) == slp->ns_reclen) {
- om = m;
- len += m->m_len;
- m = m->m_next;
- recm = slp->ns_raw;
- om->m_next = (struct mbuf *)0;
- } else {
- om = m;
- len += m->m_len;
- m = m->m_next;
- }
- }
- slp->ns_raw = m;
- slp->ns_cc -= len;
- slp->ns_reclen = 0;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
-
- /*
- * Accumulate the fragments into a record.
- */
- mpp = &slp->ns_frag;
- while (*mpp)
- mpp = &((*mpp)->m_next);
- *mpp = recm;
- if (slp->ns_flag & SLP_LASTFRAG) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec), M_NFSRVDESC, waitflag);
- if (!rec) {
- m_freem(slp->ns_frag);
- } else {
- nfs_realign(&slp->ns_frag, 10 * NFSX_UNSIGNED);
- rec->nr_address = (struct sockaddr *)0;
- rec->nr_packet = slp->ns_frag;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- }
- slp->ns_frag = (struct mbuf *)0;
- }
- }
-}
-
-/*
- * Parse an RPC header.
- */
-int
-nfsrv_dorec(slp, nfsd, ndp)
- register struct nfssvc_sock *slp;
- struct nfsd *nfsd;
- struct nfsrv_descript **ndp;
-{
- struct nfsrv_rec *rec;
- register struct mbuf *m;
- struct sockaddr *nam;
- register struct nfsrv_descript *nd;
- int error;
-
- *ndp = NULL;
- if ((slp->ns_flag & SLP_VALID) == 0 || !STAILQ_FIRST(&slp->ns_rec))
- return (ENOBUFS);
- rec = STAILQ_FIRST(&slp->ns_rec);
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- nam = rec->nr_address;
- m = rec->nr_packet;
- free(rec, M_NFSRVDESC);
- MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
- M_NFSRVDESC, M_WAITOK);
- nd->nd_md = nd->nd_mrep = m;
- nd->nd_nam2 = nam;
- nd->nd_dpos = mtod(m, caddr_t);
- error = nfs_getreq(nd, nfsd, TRUE);
- if (error) {
- if (nam) {
- FREE(nam, M_SONAME);
- }
- free((caddr_t)nd, M_NFSRVDESC);
- return (error);
- }
- *ndp = nd;
- nfsd->nfsd_nd = nd;
- return (0);
-}
-
-/*
- * Search for a sleeping nfsd and wake it up.
- * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the
- * running nfsds will go look for the work in the nfssvc_sock list.
- */
-void
-nfsrv_wakenfsd(slp)
- struct nfssvc_sock *slp;
-{
- register struct nfsd *nd;
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
- for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
- if (nd->nfsd_flag & NFSD_WAITING) {
- nd->nfsd_flag &= ~NFSD_WAITING;
- if (nd->nfsd_slp)
- panic("nfsd wakeup");
- slp->ns_sref++;
- nd->nfsd_slp = slp;
- wakeup((caddr_t)nd);
- return;
- }
- }
- slp->ns_flag |= SLP_DOREC;
- nfsd_head_flag |= NFSD_CHECKSLP;
-}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 4425129..c951115 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -34,14 +34,17 @@
* SUCH DAMAGE.
*
* @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* These functions support the macros and help fiddle mbuf chains for
* the nfs op functions. They do things like create the rpc header and
* copy data between mbuf chains and uio lists.
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -57,6 +60,7 @@
#include <sys/malloc.h>
#include <sys/sysent.h>
#include <sys/syscall.h>
+#include <sys/sysproto.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
@@ -65,13 +69,11 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsnode.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
+#include <nfsclient/nfsm_subs.h>
+#include <nfsclient/nfsmount.h>
#include <netinet/in.h>
@@ -79,75 +81,26 @@
* Data items converted to xdr at startup, since they are constant
* This is kinda hokey, but may save a little time doing byte swaps
*/
-u_int32_t nfs_xdrneg1;
-u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
- rpc_auth_kerb;
-u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false;
+u_int32_t nfs_xdrneg1;
+u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
+ rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
+u_int32_t nfs_true, nfs_false;
/* And other global data */
static u_int32_t nfs_xid = 0;
static enum vtype nv2tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON
-};
-enum vtype nv3tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
+ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON
};
-int nfs_ticks;
-int nfs_pbuf_freecnt = -1; /* start out unlimited */
-
-struct nfs_reqq nfs_reqq;
-struct nfssvc_sockhead nfssvc_sockhead;
-int nfssvc_sockhead_flag;
-struct nfsd_head nfsd_head;
-int nfsd_head_flag;
-struct nfs_bufq nfs_bufq;
-struct nqtimerhead nqtimerhead;
-struct nqfhhashhead *nqfhhashtbl;
-u_long nqfhhash;
-
-static void (*nfs_prev_lease_updatetime) __P((int));
-static int nfs_prev_nfssvc_sy_narg;
-static sy_call_t *nfs_prev_nfssvc_sy_call;
-
-#ifndef NFS_NOSERVER
+int nfs_ticks;
+int nfs_pbuf_freecnt = -1; /* start out unlimited */
-static vop_t *nfs_prev_vop_lease_check;
+struct nfs_reqq nfs_reqq;
+struct nfs_bufq nfs_bufq;
-/*
- * Mapping of old NFS Version 2 RPC numbers to generic numbers.
- */
-int nfsv3_procid[NFS_NPROCS] = {
- NFSPROC_NULL,
- NFSPROC_GETATTR,
- NFSPROC_SETATTR,
- NFSPROC_NOOP,
- NFSPROC_LOOKUP,
- NFSPROC_READLINK,
- NFSPROC_READ,
- NFSPROC_NOOP,
- NFSPROC_WRITE,
- NFSPROC_CREATE,
- NFSPROC_REMOVE,
- NFSPROC_RENAME,
- NFSPROC_LINK,
- NFSPROC_SYMLINK,
- NFSPROC_MKDIR,
- NFSPROC_RMDIR,
- NFSPROC_READDIR,
- NFSPROC_FSSTAT,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP
-};
+static int nfs_prev_nfsclnt_sy_narg;
+static sy_call_t *nfs_prev_nfsclnt_sy_call;
-#endif /* NFS_NOSERVER */
/*
* and the reverse mapping from generic to Version 2 procedure numbers
*/
@@ -175,444 +128,24 @@ int nfsv2_procid[NFS_NPROCS] = {
NFSV2PROC_NOOP,
NFSV2PROC_NOOP,
NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
-};
-
-#ifndef NFS_NOSERVER
-/*
- * Maps errno values to nfs error numbers.
- * Use NFSERR_IO as the catch all for ones not specifically defined in
- * RFC 1094.
- */
-static u_char nfsrv_v2errmap[ELAST] = {
- NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
- NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
- NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO /* << Last is 86 */
-};
-
-/*
- * Maps errno values to nfs error numbers.
- * Although it is not obvious whether or not NFS clients really care if
- * a returned error value is in the specified list for the procedure, the
- * safest thing to do is filter them appropriately. For Version 2, the
- * X/Open XNFS document is the only specification that defines error values
- * for each RPC (The RFC simply lists all possible error values for all RPCs),
- * so I have decided to not do this for Version 2.
- * The first entry is the default error return and the rest are the valid
- * errors for that RPC in increasing numeric order.
- */
-static short nfsv3err_null[] = {
- 0,
- 0,
-};
-
-static short nfsv3err_getattr[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_setattr[] = {
- NFSERR_IO,
- NFSERR_PERM,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOT_SYNC,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_lookup[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_access[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_read[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_NXIO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_write[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_FBIG,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_create[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_mkdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_symlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_mknod[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- NFSERR_BADTYPE,
- 0,
-};
-
-static short nfsv3err_remove[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_rmdir[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_rename[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_ISDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
};
-static short nfsv3err_link[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_readdirplus[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_NOTSUPP,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_fsstat[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_fsinfo[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_pathconf[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short nfsv3err_commit[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static short *nfsrv_v3errmap[] = {
- nfsv3err_null,
- nfsv3err_getattr,
- nfsv3err_setattr,
- nfsv3err_lookup,
- nfsv3err_access,
- nfsv3err_readlink,
- nfsv3err_read,
- nfsv3err_write,
- nfsv3err_create,
- nfsv3err_mkdir,
- nfsv3err_symlink,
- nfsv3err_mknod,
- nfsv3err_remove,
- nfsv3err_rmdir,
- nfsv3err_rename,
- nfsv3err_link,
- nfsv3err_readdir,
- nfsv3err_readdirplus,
- nfsv3err_fsstat,
- nfsv3err_fsinfo,
- nfsv3err_pathconf,
- nfsv3err_commit,
-};
-
-#endif /* NFS_NOSERVER */
-
-extern struct nfsrtt nfsrtt;
-extern time_t nqnfsstarttime;
-extern int nqsrv_clockskew;
-extern int nqsrv_writeslack;
-extern int nqsrv_maxlease;
-extern struct nfsstats nfsstats;
-extern int nqnfs_piggy[NFS_NPROCS];
-extern nfstype nfsv2_type[9];
-extern nfstype nfsv3_type[9];
-extern struct nfsnodehashhead *nfsnodehashtbl;
-extern u_long nfsnodehash;
-
-struct nfssvc_args;
-extern int nfssvc(struct thread *, struct nfssvc_args *, int *);
-
LIST_HEAD(nfsnodehashhead, nfsnode);
-int nfs_webnamei __P((struct nameidata *, struct vnode *, struct thread *));
-
-u_quad_t
-nfs_curusec()
-{
- struct timeval tv;
-
- getmicrotime(&tv);
- return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
-}
-
/*
* Create the header for an rpc request packet
* The hsiz is the size of the rest of the nfs request header.
* (just used to decide if a cluster is a good idea)
*/
struct mbuf *
-nfsm_reqh(vp, procid, hsiz, bposp)
- struct vnode *vp;
- u_long procid;
- int hsiz;
- caddr_t *bposp;
+nfsm_reqhead(struct vnode *vp, u_long procid, int hsiz)
{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- struct mbuf *mb2;
- struct nfsmount *nmp;
- int nqflag;
+ struct mbuf *mb;
MGET(mb, M_TRYWAIT, MT_DATA);
if (hsiz >= MINCLSIZE)
MCLGET(mb, M_TRYWAIT);
mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
-
- /*
- * For NQNFS, add lease request.
- */
- if (vp) {
- nmp = VFSTONFS(vp->v_mount);
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nqflag = NQNFS_NEEDLEASE(vp, procid);
- if (nqflag) {
- nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nqflag);
- *tl = txdr_unsigned(nmp->nm_leaseterm);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- }
- /* Finally, return values */
- *bposp = bpos;
return (mb);
}
@@ -623,27 +156,16 @@ nfsm_reqh(vp, procid, hsiz, bposp)
* Returns the head of the mbuf list.
*/
struct mbuf *
-nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
- verf_str, mrest, mrest_len, mbp, xidp)
- register struct ucred *cr;
- int nmflag;
- int procid;
- int auth_type;
- int auth_len;
- char *auth_str;
- int verf_len;
- char *verf_str;
- struct mbuf *mrest;
- int mrest_len;
- struct mbuf **mbp;
- u_int32_t *xidp;
+nfsm_rpchead(struct ucred *cr, int nmflag, int procid, int auth_type,
+ int auth_len, struct mbuf *mrest, int mrest_len, struct mbuf **mbp,
+ u_int32_t *xidp)
{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- register int i;
- struct mbuf *mreq, *mb2;
- int siz, grpsiz, authsiz;
+ struct mbuf *mb;
+ u_int32_t *tl;
+ caddr_t bpos;
+ int i;
+ struct mbuf *mreq;
+ int grpsiz, authsiz;
authsiz = nfsm_rndup(auth_len);
MGETHDR(mb, M_TRYWAIT, MT_DATA);
@@ -664,7 +186,7 @@ nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
/* Get a pretty random xid to start with */
- if (!nfs_xid)
+ if (!nfs_xid)
nfs_xid = random();
/*
* Skip zero xid if it should ever happen.
@@ -675,20 +197,14 @@ nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
*tl++ = *xidp = txdr_unsigned(nfs_xid);
*tl++ = rpc_call;
*tl++ = rpc_vers;
- if (nmflag & NFSMNT_NQNFS) {
- *tl++ = txdr_unsigned(NQNFS_PROG);
- *tl++ = txdr_unsigned(NQNFS_VER3);
- } else {
- *tl++ = txdr_unsigned(NFS_PROG);
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(NFS_VER3);
- else
- *tl++ = txdr_unsigned(NFS_VER2);
- }
- if (nmflag & NFSMNT_NFSV3)
+ *tl++ = txdr_unsigned(NFS_PROG);
+ if (nmflag & NFSMNT_NFSV3) {
+ *tl++ = txdr_unsigned(NFS_VER3);
*tl++ = txdr_unsigned(procid);
- else
+ } else {
+ *tl++ = txdr_unsigned(NFS_VER2);
*tl++ = txdr_unsigned(nfsv2_procid[procid]);
+ }
/*
* And then the authorization cred.
@@ -707,67 +223,14 @@ nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
for (i = 1; i <= grpsiz; i++)
*tl++ = txdr_unsigned(cr->cr_groups[i]);
break;
- case RPCAUTH_KERB4:
- siz = auth_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(auth_str, bpos, i);
- mb->m_len += i;
- auth_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- break;
- };
+ }
/*
* And the verifier...
*/
nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (verf_str) {
- *tl++ = txdr_unsigned(RPCAUTH_KERB4);
- *tl = txdr_unsigned(verf_len);
- siz = verf_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(verf_str, bpos, i);
- mb->m_len += i;
- verf_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- } else {
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
- }
+ *tl++ = txdr_unsigned(RPCAUTH_NULL);
+ *tl = 0;
mb->m_next = mrest;
mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
mreq->m_pkthdr.rcvif = (struct ifnet *)0;
@@ -776,94 +239,15 @@ nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
}
/*
- * copies mbuf chain to the uio scatter/gather list
- */
-int
-nfsm_mbuftouio(mrep, uiop, siz, dpos)
- struct mbuf **mrep;
- register struct uio *uiop;
- int siz;
- caddr_t *dpos;
-{
- register char *mbufcp, *uiocp;
- register int xfer, left, len;
- register struct mbuf *mp;
- long uiosiz, rem;
- int error = 0;
-
- mp = *mrep;
- mbufcp = *dpos;
- len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
- rem = nfsm_rndup(siz)-siz;
- while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EFBIG);
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- while (len == 0) {
- mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- mbufcp = mtod(mp, caddr_t);
- len = mp->m_len;
- }
- xfer = (left > len) ? len : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (mbufcp, uiocp, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(mbufcp, uiocp, xfer);
- else
- copyout(mbufcp, uiocp, xfer);
- left -= xfer;
- len -= xfer;
- mbufcp += xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- if (uiop->uio_iov->iov_len <= siz) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- }
- siz -= uiosiz;
- }
- *dpos = mbufcp;
- *mrep = mp;
- if (rem > 0) {
- if (len < rem)
- error = nfs_adv(mrep, dpos, rem, len);
- else
- *dpos += rem;
- }
- return (error);
-}
-
-/*
* copies a uio scatter/gather list to an mbuf chain.
* NOTE: can ony handle iovcnt == 1
*/
int
-nfsm_uiotombuf(uiop, mq, siz, bpos)
- register struct uio *uiop;
- struct mbuf **mq;
- int siz;
- caddr_t *bpos;
+nfsm_uiotombuf(struct uio *uiop, struct mbuf **mq, int siz, caddr_t *bpos)
{
- register char *uiocp;
- register struct mbuf *mp, *mp2;
- register int xfer, left, mlen;
+ char *uiocp;
+ struct mbuf *mp, *mp2;
+ int xfer, left, mlen;
int uiosiz, clflg, rem;
char *cp;
@@ -935,109 +319,12 @@ nfsm_uiotombuf(uiop, mq, siz, bpos)
}
/*
- * Help break down an mbuf chain by setting the first siz bytes contiguous
- * pointed to by returned val.
- * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
- * cases. (The macros use the vars. dpos and dpos2)
- */
-int
-nfsm_disct(mdp, dposp, siz, left, cp2)
- struct mbuf **mdp;
- caddr_t *dposp;
- int siz;
- int left;
- caddr_t *cp2;
-{
- register struct mbuf *mp, *mp2;
- register int siz2, xfer;
- register caddr_t ptr;
-
- mp = *mdp;
- while (left == 0) {
- *mdp = mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- left = mp->m_len;
- *dposp = mtod(mp, caddr_t);
- }
- if (left >= siz) {
- *cp2 = *dposp;
- *dposp += siz;
- } else if (mp->m_next == NULL) {
- return (EBADRPC);
- } else if (siz > MHLEN) {
- panic("nfs S too big");
- } else {
- MGET(mp2, M_TRYWAIT, MT_DATA);
- mp2->m_next = mp->m_next;
- mp->m_next = mp2;
- mp->m_len -= left;
- mp = mp2;
- *cp2 = ptr = mtod(mp, caddr_t);
- bcopy(*dposp, ptr, left); /* Copy what was left */
- siz2 = siz-left;
- ptr += left;
- mp2 = mp->m_next;
- /* Loop around copying up the siz2 bytes */
- while (siz2 > 0) {
- if (mp2 == NULL)
- return (EBADRPC);
- xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
- if (xfer > 0) {
- bcopy(mtod(mp2, caddr_t), ptr, xfer);
- NFSMADV(mp2, xfer);
- mp2->m_len -= xfer;
- ptr += xfer;
- siz2 -= xfer;
- }
- if (siz2 > 0)
- mp2 = mp2->m_next;
- }
- mp->m_len = siz;
- *mdp = mp2;
- *dposp = mtod(mp2, caddr_t);
- }
- return (0);
-}
-
-/*
- * Advance the position in the mbuf chain.
- */
-int
-nfs_adv(mdp, dposp, offs, left)
- struct mbuf **mdp;
- caddr_t *dposp;
- int offs;
- int left;
-{
- register struct mbuf *m;
- register int s;
-
- m = *mdp;
- s = left;
- while (s < offs) {
- offs -= s;
- m = m->m_next;
- if (m == NULL)
- return (EBADRPC);
- s = m->m_len;
- }
- *mdp = m;
- *dposp = mtod(m, caddr_t)+offs;
- return (0);
-}
-
-/*
* Copy a string into mbufs for the hard cases...
*/
int
-nfsm_strtmbuf(mb, bpos, cp, siz)
- struct mbuf **mb;
- char **bpos;
- const char *cp;
- long siz;
+nfsm_strtmbuf(struct mbuf **mb, char **bpos, const char *cp, long siz)
{
- register struct mbuf *m1 = NULL, *m2;
+ struct mbuf *m1 = NULL, *m2;
long left, xfer, len, tlen;
u_int32_t *tl;
int putsize;
@@ -1097,15 +384,11 @@ nfsm_strtmbuf(mb, bpos, cp, siz)
* Called once to initialize data structures...
*/
int
-nfs_init(vfsp)
- struct vfsconf *vfsp;
+nfs_init(struct vfsconf *vfsp)
{
- register int i;
+ int i;
nfsmount_zone = zinit("NFSMOUNT", sizeof(struct nfsmount), 0, 0, 1);
-
- nfs_mount_type = vfsp->vfc_typenum;
- nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
rpc_reply = txdr_unsigned(RPC_REPLY);
@@ -1114,9 +397,6 @@ nfs_init(vfsp)
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);
- nfs_prog = txdr_unsigned(NFS_PROG);
- nqnfs_prog = txdr_unsigned(NQNFS_PROG);
nfs_true = txdr_unsigned(TRUE);
nfs_false = txdr_unsigned(FALSE);
nfs_xdrneg1 = txdr_unsigned(-1);
@@ -1129,21 +409,6 @@ nfs_init(vfsp)
nfs_iodmount[i] = (struct nfsmount *)0;
}
nfs_nhinit(); /* Init the nfsnode table */
-#ifndef NFS_NOSERVER
- nfsrv_init(0); /* Init server data structures */
- nfsrv_initcache(); /* Init the server request cache */
-#endif
-
- /*
- * Initialize the nqnfs server stuff.
- */
- if (nqnfsstarttime == 0) {
- nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
- + nqsrv_clockskew + nqsrv_writeslack;
- NQLOADNOVRAM(nqnfsstarttime);
- TAILQ_INIT(&nqtimerhead);
- nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
- }
/*
* Initialize reply list and start timer
@@ -1152,20 +417,10 @@ nfs_init(vfsp)
nfs_timer(0);
- /*
- * Set up lease_check and lease_updatetime so that other parts
- * of the system can call us, if we are loadable.
- */
-#ifndef NFS_NOSERVER
- nfs_prev_vop_lease_check = default_vnodeop_p[VOFFSET(vop_lease)];
- default_vnodeop_p[VOFFSET(vop_lease)] = (vop_t *)nqnfs_vop_lease_check;
-#endif
- nfs_prev_lease_updatetime = lease_updatetime;
- lease_updatetime = nfs_lease_updatetime;
- nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
- sysent[SYS_nfssvc].sy_narg = 2;
- nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call;
- sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc;
+ nfs_prev_nfsclnt_sy_narg = sysent[SYS_nfsclnt].sy_narg;
+ sysent[SYS_nfsclnt].sy_narg = 2;
+ nfs_prev_nfsclnt_sy_call = sysent[SYS_nfsclnt].sy_call;
+ sysent[SYS_nfsclnt].sy_call = (sy_call_t *)nfsclnt;
nfs_pbuf_freecnt = nswbuf / 2 + 1;
@@ -1173,18 +428,12 @@ nfs_init(vfsp)
}
int
-nfs_uninit(vfsp)
- struct vfsconf *vfsp;
+nfs_uninit(struct vfsconf *vfsp)
{
untimeout(nfs_timer, (void *)NULL, nfs_timer_handle);
- nfs_mount_type = -1;
-#ifndef NFS_NOSERVER
- default_vnodeop_p[VOFFSET(vop_lease)] = nfs_prev_vop_lease_check;
-#endif
- lease_updatetime = nfs_prev_lease_updatetime;
- sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
- sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
+ sysent[SYS_nfsclnt].sy_narg = nfs_prev_nfsclnt_sy_narg;
+ sysent[SYS_nfsclnt].sy_call = nfs_prev_nfsclnt_sy_call;
return (0);
}
@@ -1203,18 +452,14 @@ nfs_uninit(vfsp)
* copy the attributes to *vaper
*/
int
-nfs_loadattrcache(vpp, mdp, dposp, vaper, dontshrink)
- struct vnode **vpp;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vattr *vaper;
- int dontshrink;
+nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
+ struct vattr *vaper, int dontshrink)
{
- register struct vnode *vp = *vpp;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
- register struct nfsnode *np;
- register int32_t t1;
+ struct vnode *vp = *vpp;
+ struct vattr *vap;
+ struct nfs_fattr *fp;
+ struct nfsnode *np;
+ int32_t t1;
caddr_t cp2;
int error = 0, rdev;
struct mbuf *md;
@@ -1321,7 +566,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper, dontshrink)
vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
fp->fa2_ctime.nfsv2_sec);
vap->va_ctime.tv_nsec = 0;
- vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
+ vap->va_gen = fxdr_unsigned(u_int32_t, fp->fa2_ctime.nfsv2_usec);
vap->va_filerev = 0;
}
np->n_attrstamp = time_second;
@@ -1373,12 +618,10 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, acdebug, CTLFLAG_RW, &nfs_acdebug, 0, "");
* otherwise return an error
*/
int
-nfs_getattrcache(vp, vaper)
- register struct vnode *vp;
- struct vattr *vaper;
+nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
{
- register struct nfsnode *np;
- register struct vattr *vap;
+ struct nfsnode *np;
+ struct vattr *vap;
struct nfsmount *nmp;
int timeo;
@@ -1446,613 +689,16 @@ nfs_getattrcache(vp, vaper)
return (0);
}
-#ifndef NFS_NOSERVER
-/*
- * Set up nameidata for a lookup() call and do it.
- *
- * If pubflag is set, this call is done for a lookup operation on the
- * public filehandle. In that case we allow crossing mountpoints and
- * absolute pathnames. However, the caller is expected to check that
- * the lookup result is within the public fs, and deny access if
- * it is not.
- *
- * nfs_namei() clears out garbage fields that namei() might leave garbage.
- * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
- * error occurs but the parent was not requested.
- *
- * dirp may be set whether an error is returned or not, and must be
- * released by the caller.
- */
-int
-nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
- register struct nameidata *ndp;
- fhandle_t *fhp;
- int len;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vnode **retdirp;
- struct thread *td;
- int kerbflag, pubflag;
-{
- register int i, rem;
- register struct mbuf *md;
- register char *fromcp, *tocp, *cp;
- struct iovec aiov;
- struct uio auio;
- struct vnode *dp;
- int error, rdonly, linklen;
- struct componentname *cnp = &ndp->ni_cnd;
-
- *retdirp = (struct vnode *)0;
- cnp->cn_pnbuf = zalloc(namei_zone);
-
- /*
- * Copy the name from the mbuf list to ndp->ni_pnbuf
- * and set the various ndp fields appropriately.
- */
- fromcp = *dposp;
- tocp = cnp->cn_pnbuf;
- md = *mdp;
- rem = mtod(md, caddr_t) + md->m_len - fromcp;
- for (i = 0; i < len; i++) {
- while (rem == 0) {
- md = md->m_next;
- if (md == NULL) {
- error = EBADRPC;
- goto out;
- }
- fromcp = mtod(md, caddr_t);
- rem = md->m_len;
- }
- if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
- error = EACCES;
- goto out;
- }
- *tocp++ = *fromcp++;
- rem--;
- }
- *tocp = '\0';
- *mdp = md;
- *dposp = fromcp;
- len = nfsm_rndup(len)-len;
- if (len > 0) {
- if (rem >= len)
- *dposp += len;
- else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
- goto out;
- }
-
- /*
- * Extract and set starting directory.
- */
- error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly, kerbflag, pubflag);
- if (error)
- goto out;
- if (dp->v_type != VDIR) {
- vrele(dp);
- error = ENOTDIR;
- goto out;
- }
-
- if (rdonly)
- cnp->cn_flags |= RDONLY;
-
- /*
- * Set return directory. Reference to dp is implicitly transfered
- * to the returned pointer
- */
- *retdirp = dp;
-
- if (pubflag) {
- /*
- * Oh joy. For WebNFS, handle those pesky '%' escapes,
- * and the 'native path' indicator.
- */
- cp = zalloc(namei_zone);
- fromcp = cnp->cn_pnbuf;
- tocp = cp;
- if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
- switch ((unsigned char)*fromcp) {
- case WEBNFS_NATIVE_CHAR:
- /*
- * 'Native' path for us is the same
- * as a path according to the NFS spec,
- * just skip the escape char.
- */
- fromcp++;
- break;
- /*
- * More may be added in the future, range 0x80-0xff
- */
- default:
- error = EIO;
- zfree(namei_zone, cp);
- goto out;
- }
- }
- /*
- * Translate the '%' escapes, URL-style.
- */
- while (*fromcp != '\0') {
- if (*fromcp == WEBNFS_ESC_CHAR) {
- if (fromcp[1] != '\0' && fromcp[2] != '\0') {
- fromcp++;
- *tocp++ = HEXSTRTOI(fromcp);
- fromcp += 2;
- continue;
- } else {
- error = ENOENT;
- zfree(namei_zone, cp);
- goto out;
- }
- } else
- *tocp++ = *fromcp++;
- }
- *tocp = '\0';
- zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- }
-
- ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
- ndp->ni_segflg = UIO_SYSSPACE;
-
- if (pubflag) {
- ndp->ni_rootdir = rootvnode;
- ndp->ni_loopcnt = 0;
- if (cnp->cn_pnbuf[0] == '/')
- dp = rootvnode;
- } else {
- cnp->cn_flags |= NOCROSSMOUNT;
- }
-
- /*
- * Initialize for scan, set ni_startdir and bump ref on dp again
- * becuase lookup() will dereference ni_startdir.
- */
-
- cnp->cn_thread = td;
- VREF(dp);
- ndp->ni_startdir = dp;
-
- for (;;) {
- cnp->cn_nameptr = cnp->cn_pnbuf;
- /*
- * Call lookup() to do the real work. If an error occurs,
- * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
- * we do not have to dereference anything before returning.
- * In either case ni_startdir will be dereferenced and NULLed
- * out.
- */
- error = lookup(ndp);
- if (error)
- break;
-
- /*
- * Check for encountering a symbolic link. Trivial
- * termination occurs if no symlink encountered.
- * Note: zfree is safe because error is 0, so we will
- * not zfree it again when we break.
- */
- if ((cnp->cn_flags & ISSYMLINK) == 0) {
- nfsrv_object_create(ndp->ni_vp);
- if (cnp->cn_flags & (SAVENAME | SAVESTART))
- cnp->cn_flags |= HASBUF;
- else
- zfree(namei_zone, cnp->cn_pnbuf);
- break;
- }
-
- /*
- * Validate symlink
- */
- if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- VOP_UNLOCK(ndp->ni_dvp, 0, td);
- if (!pubflag) {
- error = EINVAL;
- goto badlink2;
- }
-
- if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
- error = ELOOP;
- goto badlink2;
- }
- if (ndp->ni_pathlen > 1)
- cp = zalloc(namei_zone);
- else
- cp = cnp->cn_pnbuf;
- aiov.iov_base = cp;
- aiov.iov_len = MAXPATHLEN;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_td = (struct thread *)0;
- auio.uio_resid = MAXPATHLEN;
- error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
- if (error) {
- badlink1:
- if (ndp->ni_pathlen > 1)
- zfree(namei_zone, cp);
- badlink2:
- vrele(ndp->ni_dvp);
- vput(ndp->ni_vp);
- break;
- }
- linklen = MAXPATHLEN - auio.uio_resid;
- if (linklen == 0) {
- error = ENOENT;
- goto badlink1;
- }
- if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
- error = ENAMETOOLONG;
- goto badlink1;
- }
-
- /*
- * Adjust or replace path
- */
- if (ndp->ni_pathlen > 1) {
- bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
- zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- } else
- cnp->cn_pnbuf[linklen] = '\0';
- ndp->ni_pathlen += linklen;
-
- /*
- * Cleanup refs for next loop and check if root directory
- * should replace current directory. Normally ni_dvp
- * becomes the new base directory and is cleaned up when
- * we loop. Explicitly null pointers after invalidation
- * to clarify operation.
- */
- vput(ndp->ni_vp);
- ndp->ni_vp = NULL;
-
- if (cnp->cn_pnbuf[0] == '/') {
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = ndp->ni_rootdir;
- VREF(ndp->ni_dvp);
- }
- ndp->ni_startdir = ndp->ni_dvp;
- ndp->ni_dvp = NULL;
- }
-
- /*
- * nfs_namei() guarentees that fields will not contain garbage
- * whether an error occurs or not. This allows the caller to track
- * cleanup state trivially.
- */
-out:
- if (error) {
- zfree(namei_zone, cnp->cn_pnbuf);
- ndp->ni_vp = NULL;
- ndp->ni_dvp = NULL;
- ndp->ni_startdir = NULL;
- cnp->cn_flags &= ~HASBUF;
- } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
- ndp->ni_dvp = NULL;
- }
- return (error);
-}
-
-/*
- * A fiddled version of m_adj() that ensures null fill to a long
- * boundary and only trims off the back end
- */
-void
-nfsm_adj(mp, len, nul)
- struct mbuf *mp;
- register int len;
- int nul;
-{
- register struct mbuf *m;
- register int count, i;
- register char *cp;
-
- /*
- * Trim from tail. Scan the mbuf chain,
- * calculating its length and finding the last mbuf.
- * If the adjustment only affects this mbuf, then just
- * adjust and return. Otherwise, rescan and truncate
- * after the remaining size.
- */
- count = 0;
- m = mp;
- for (;;) {
- count += m->m_len;
- if (m->m_next == (struct mbuf *)0)
- break;
- m = m->m_next;
- }
- if (m->m_len > len) {
- m->m_len -= len;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- return;
- }
- count -= len;
- if (count < 0)
- count = 0;
- /*
- * Correct length for chain is "count".
- * Find the mbuf with last data, adjust its length,
- * and toss data from remaining mbufs on chain.
- */
- for (m = mp; m; m = m->m_next) {
- if (m->m_len >= count) {
- m->m_len = count;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- break;
- }
- count -= m->m_len;
- }
- for (m = m->m_next;m;m = m->m_next)
- m->m_len = 0;
-}
-
-/*
- * Make these functions instead of macros, so that the kernel text size
- * doesn't get too big...
- */
-void
-nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int before_ret;
- register struct vattr *before_vap;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
-{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
-
- if (before_ret) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- txdr_hyper(before_vap->va_size, tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_mtime), tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_ctime), tl);
- }
- *bposp = bpos;
- *mbp = mb;
- nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
-}
-
-void
-nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
-{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
- register struct nfs_fattr *fp;
-
- if (after_ret) {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
- *tl++ = nfs_true;
- fp = (struct nfs_fattr *)tl;
- nfsm_srvfattr(nfsd, after_vap, fp);
- }
- *mbp = mb;
- *bposp = bpos;
-}
-
-void
-nfsm_srvfattr(nfsd, vap, fp)
- register struct nfsrv_descript *nfsd;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
-{
-
- fp->fa_nlink = txdr_unsigned(vap->va_nlink);
- fp->fa_uid = txdr_unsigned(vap->va_uid);
- fp->fa_gid = txdr_unsigned(vap->va_gid);
- if (nfsd->nd_flag & ND_NFSV3) {
- fp->fa_type = vtonfsv3_type(vap->va_type);
- fp->fa_mode = vtonfsv3_mode(vap->va_mode);
- txdr_hyper(vap->va_size, &fp->fa3_size);
- txdr_hyper(vap->va_bytes, &fp->fa3_used);
- fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev));
- fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev));
- fp->fa3_fsid.nfsuquad[0] = 0;
- fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
- fp->fa3_fileid.nfsuquad[0] = 0;
- fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
- txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
- txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
- txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
- } else {
- fp->fa_type = vtonfsv2_type(vap->va_type);
- fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- fp->fa2_size = txdr_unsigned(vap->va_size);
- fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
- if (vap->va_type == VFIFO)
- fp->fa2_rdev = 0xffffffff;
- else
- fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
- fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
- fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
- fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
- txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
- txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
- txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
- }
-}
-
-/*
- * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
- * - look up fsid in mount list (if not found ret error)
- * - get vp and export rights by calling VFS_FHTOVP()
- * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
- * - if not lockflag unlock it with VOP_UNLOCK()
- */
-int
-nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
- fhandle_t *fhp;
- int lockflag;
- struct vnode **vpp;
- struct ucred *cred;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- int *rdonlyp;
- int kerbflag;
- int pubflag;
-{
- struct thread *td = curthread; /* XXX */
- register struct mount *mp;
- register int i;
- struct ucred *credanon;
- int error, exflags;
-#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
- struct sockaddr_int *saddr;
-#endif
-
- *vpp = (struct vnode *)0;
-
- if (nfs_ispublicfh(fhp)) {
- if (!pubflag || !nfs_pub.np_valid)
- return (ESTALE);
- fhp = &nfs_pub.np_handle;
- }
-
- mp = vfs_getvfs(&fhp->fh_fsid);
- if (!mp)
- return (ESTALE);
- error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
- if (error)
- return (error);
- error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
- if (error)
- return (error);
-#ifdef MNT_EXNORESPORT
- if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
- saddr = (struct sockaddr_in *)nam;
- if (saddr->sin_family == AF_INET &&
- ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- }
-#endif
- /*
- * Check/setup credentials.
- */
- if (exflags & MNT_EXKERB) {
- if (!kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- } else if (kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
- cred->cr_uid = credanon->cr_uid;
- for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
- cred->cr_groups[i] = credanon->cr_groups[i];
- cred->cr_ngroups = i;
- }
- if (exflags & MNT_EXRDONLY)
- *rdonlyp = 1;
- else
- *rdonlyp = 0;
-
- nfsrv_object_create(*vpp);
-
- if (!lockflag)
- VOP_UNLOCK(*vpp, 0, td);
- return (0);
-}
-
-
-/*
- * WebNFS: check if a filehandle is a public filehandle. For v3, this
- * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
- * transformed this to all zeroes in both cases, so check for it.
- */
-int
-nfs_ispublicfh(fhp)
- fhandle_t *fhp;
-{
- char *cp = (char *)fhp;
- int i;
-
- for (i = 0; i < NFSX_V3FH; i++)
- if (*cp++ != 0)
- return (FALSE);
- return (TRUE);
-}
-
-#endif /* NFS_NOSERVER */
-/*
- * This function compares two net addresses by family and returns TRUE
- * if they are the same host.
- * If there is any doubt, return FALSE.
- * The AF_INET family is handled as a special case so that address mbufs
- * don't need to be saved to store "struct in_addr", which is only 4 bytes.
- */
-int
-netaddr_match(family, haddr, nam)
- int family;
- union nethostaddr *haddr;
- struct sockaddr *nam;
-{
- register struct sockaddr_in *inetaddr;
-
- switch (family) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *)nam;
- if (inetaddr->sin_family == AF_INET &&
- inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
- return (1);
- break;
- default:
- break;
- };
- return (0);
-}
-
static nfsuint64 nfs_nullcookie = { { 0, 0 } };
/*
* This function finds the directory cookie that corresponds to the
* logical byte offset given.
*/
nfsuint64 *
-nfs_getcookie(np, off, add)
- register struct nfsnode *np;
- off_t off;
- int add;
+nfs_getcookie(struct nfsnode *np, off_t off, int add)
{
- register struct nfsdmap *dp, *dp2;
- register int pos;
+ struct nfsdmap *dp, *dp2;
+ int pos;
pos = (uoff_t)off / NFS_DIRBLKSIZ;
if (pos == 0 || off < 0) {
@@ -2063,7 +709,7 @@ nfs_getcookie(np, off, add)
return (&nfs_nullcookie);
}
pos--;
- dp = np->n_cookies.lh_first;
+ dp = LIST_FIRST(&np->n_cookies);
if (!dp) {
if (add) {
MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
@@ -2075,11 +721,11 @@ nfs_getcookie(np, off, add)
}
while (pos >= NFSNUMCOOKIES) {
pos -= NFSNUMCOOKIES;
- if (dp->ndm_list.le_next) {
+ if (LIST_NEXT(dp, ndm_list)) {
if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
pos >= dp->ndm_eocookie)
return ((nfsuint64 *)0);
- dp = dp->ndm_list.le_next;
+ dp = LIST_NEXT(dp, ndm_list);
} else if (add) {
MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
M_NFSDIROFF, M_WAITOK);
@@ -2104,10 +750,9 @@ nfs_getcookie(np, off, add)
* Done mainly to avoid the use of stale offset cookies.
*/
void
-nfs_invaldir(vp)
- register struct vnode *vp;
+nfs_invaldir(struct vnode *vp)
{
- register struct nfsnode *np = VTONFS(vp);
+ struct nfsnode *np = VTONFS(vp);
#ifdef DIAGNOSTIC
if (vp->v_type != VDIR)
@@ -2116,8 +761,8 @@ nfs_invaldir(vp)
np->n_direofoffset = 0;
np->n_cookieverf.nfsuquad[0] = 0;
np->n_cookieverf.nfsuquad[1] = 0;
- if (np->n_cookies.lh_first)
- np->n_cookies.lh_first->ndm_eocookie = 0;
+ if (LIST_FIRST(&np->n_cookies))
+ LIST_FIRST(&np->n_cookies)->ndm_eocookie = 0;
}
/*
@@ -2127,15 +772,14 @@ nfs_invaldir(vp)
* and B_CLUSTEROK flags. Once done the new write verifier can be set for the
* mount point.
*
- * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data
+ * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data
* writes are not clusterable.
*/
void
-nfs_clearcommit(mp)
- struct mount *mp;
+nfs_clearcommit(struct mount *mp)
{
- register struct vnode *vp, *nvp;
- register struct buf *bp, *nbp;
+ struct vnode *vp, *nvp;
+ struct buf *bp, *nbp;
int s;
GIANT_REQUIRED;
@@ -2159,85 +803,252 @@ loop:
splx(s);
}
-#ifndef NFS_NOSERVER
/*
- * Map errnos to NFS error numbers. For Version 3 also filter out error
- * numbers not specified for the associated procedure.
+ * Helper functions for former macros. Some of these should be
+ * moved to their callers.
*/
+
int
-nfsrv_errmap(nd, err)
- struct nfsrv_descript *nd;
- register int err;
+nfsm_mtofh_xx(struct vnode *d, struct vnode **v, int v3, int *f,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
{
- register short *defaulterrp, *errp;
-
- if (nd->nd_flag & ND_NFSV3) {
- if (nd->nd_procnum <= NFSPROC_COMMIT) {
- errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
- while (*++errp) {
- if (*errp == err)
- return (err);
- else if (*errp > err)
- break;
+ struct nfsnode *ttnp;
+ struct vnode *ttvp;
+ nfsfh_t *ttfhp;
+ int ttfhsize;
+ int t1;
+
+ if (v3) {
+ t1 = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (t1)
+ return (t1);
+ *f = fxdr_unsigned(int, **tl);
+ } else
+ *f = 1;
+ if (*f) {
+ t1 = nfsm_getfh_xx(&ttfhp, &ttfhsize, (v3), tl, md, dpos);
+ if (t1 != 0)
+ return t1;
+ t1 = nfs_nget(d->v_mount, ttfhp, ttfhsize, &ttnp);
+ if (t1 != 0)
+ return t1;
+ *v = NFSTOV(ttnp);
+ }
+ if (v3) {
+ t1 = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (t1)
+ return t1;
+ if (*f)
+ *f = fxdr_unsigned(int, **tl);
+ else if (fxdr_unsigned(int, **tl))
+ nfsm_adv_xx(NFSX_V3FATTR, tl, md, dpos);
+ }
+ if (*f) {
+ ttvp = *v;
+ t1 = nfs_loadattrcache(&ttvp, md, dpos, (struct vattr *)0, 0);
+ if (t1)
+ return t1;
+ *v = ttvp;
+ }
+ return 0;
+}
+
+int
+nfsm_getfh_xx(nfsfh_t **f, int *s, int v3,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int t1;
+
+ if (v3) {
+ t1 = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (t1)
+ return t1;
+ *s = fxdr_unsigned(int, **tl);
+ if (*s <= 0 || *s > NFSX_V3FHMAX) {
+ return EBADRPC;
+ }
+ } else
+ *s = NFSX_V2FH;
+ t1 = nfsm_dissect_xx((void **)f, nfsm_rndup(*s), md, dpos);
+ return t1;
+}
+
+
+int
+nfsm_loadattr_xx(struct vnode **v, struct vattr *va,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int t1;
+
+ struct vnode *ttvp = *v;
+ t1 = nfs_loadattrcache(&ttvp, md, dpos, va, 0);
+ if (t1 != 0)
+ return t1;
+ *v = ttvp;
+ return 0;
+}
+
+int
+nfsm_postop_attr_xx(struct vnode **v, int *f,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int t1;
+
+ struct vnode *ttvp = *v;
+ t1 = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (t1 != 0)
+ return t1;
+ *f = fxdr_unsigned(int, *tl);
+ if (f != 0) {
+ t1 = nfs_loadattrcache(&ttvp, md, dpos, (struct vattr *)0, 1);
+ if (t1 != 0) {
+ *f = 0;
+ return t1;
}
- return ((int)*defaulterrp);
- } else
- return (err & 0xffff);
+ *v = ttvp;
}
- if (err <= ELAST)
- return ((int)nfsrv_v2errmap[err - 1]);
- return (NFSERR_IO);
+ return 0;
}
int
-nfsrv_object_create(vp)
- struct vnode *vp;
+nfsm_wcc_data_xx(struct vnode **v, int *f,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
{
+ int ttattrf, ttretf = 0;
+ int t1;
+
+ t1 = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (t1 != 0)
+ return t1;
+ if (**tl == nfs_true) {
+ t1 = nfsm_dissect_xx((void **)tl, 6 * NFSX_UNSIGNED, md, dpos);
+ if (t1 != 0)
+ return t1;
+ if (*f)
+ ttretf = (VTONFS(*v)->n_mtime ==
+ fxdr_unsigned(u_int32_t, *((*tl) + 2)));
+ }
+ t1 = nfsm_postop_attr_xx(v, &ttattrf, tl, md, dpos);
+ if (t1)
+ return t1;
+ if (*f)
+ *f = ttretf;
+ else
+ *f = ttattrf;
+ return 0;
+}
- if (vp == NULL || vp->v_type != VREG)
- return (1);
- return (vfs_object_create(vp, curthread,
- curthread ? curthread->td_proc->p_ucred : NULL));
+int
+nfsm_strtom_xx(const char *a, int s, int m,
+ u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
+{
+ int t1;
+
+ if (s > m)
+ return ENAMETOOLONG;
+ t1 = nfsm_rndup(s) + NFSX_UNSIGNED;
+ if (t1 <= M_TRAILINGSPACE(*mb)) {
+ nfsm_build_xx((void **)tl, t1, mb, bpos);
+ *(*tl)++ = txdr_unsigned(s);
+ *((*tl) + ((t1 >> 2) - 2)) = 0;
+ bcopy(a, *tl, s);
+ } else {
+ t1 = nfsm_strtmbuf(mb, bpos, a, s);
+ if (t1 != 0)
+ return t1;
+ }
+ return 0;
}
-/*
- * Sort the group list in increasing numerical order.
- * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
- * that used to be here.)
- */
-void
-nfsrvw_sort(list, num)
- register gid_t *list;
- register int num;
+int
+nfsm_fhtom_xx(struct vnode *v, int v3,
+ u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
{
- register int i, j;
- gid_t v;
-
- /* Insertion sort. */
- for (i = 1; i < num; i++) {
- v = list[i];
- /* find correct slot for value v, moving others up */
- for (j = i; --j >= 0 && v < list[j];)
- list[j + 1] = list[j];
- list[j + 1] = v;
+ int t1;
+ caddr_t cp;
+
+ if (v3) {
+ t1 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED;
+ if (t1 < M_TRAILINGSPACE(*mb)) {
+ nfsm_build_xx((void **)tl, t1, mb, bpos);
+ *(*tl)++ = txdr_unsigned(VTONFS(v)->n_fhsize);
+ *((*tl) + ((t1 >> 2) - 2)) = 0;
+ bcopy(VTONFS(v)->n_fhp, *tl, VTONFS(v)->n_fhsize);
+ } else {
+ t1 = nfsm_strtmbuf(mb, bpos,
+ (const char *)VTONFS(v)->n_fhp,
+ VTONFS(v)->n_fhsize);
+ if (t1 != 0)
+ return t1;
+ }
+ } else {
+ nfsm_build_xx((void **)&cp, NFSX_V2FH, mb, bpos);
+ bcopy(VTONFS(v)->n_fhp, cp, NFSX_V2FH);
}
+ return 0;
}
-/*
- * copy credentials making sure that the result can be compared with bcmp().
- */
void
-nfsrv_setcred(incred, outcred)
- register struct ucred *incred, *outcred;
+nfsm_v3attrbuild_xx(struct vattr *va, int full,
+ u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
{
- register int i;
-
- bzero((caddr_t)outcred, sizeof (struct ucred));
- outcred->cr_ref = 1;
- outcred->cr_uid = incred->cr_uid;
- outcred->cr_ngroups = incred->cr_ngroups;
- for (i = 0; i < incred->cr_ngroups; i++)
- outcred->cr_groups[i] = incred->cr_groups[i];
- nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
+
+ if (va->va_mode != (mode_t)VNOVAL) {
+ nfsm_build_xx((void **)tl, 2 * NFSX_UNSIGNED, mb, bpos);
+ *(*tl)++ = nfs_true;
+ **tl = txdr_unsigned(va->va_mode);
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = nfs_false;
+ }
+ if (full && va->va_uid != (uid_t)VNOVAL) {
+ nfsm_build_xx((void **)tl, 2 * NFSX_UNSIGNED, mb, bpos);
+ *(*tl)++ = nfs_true;
+ **tl = txdr_unsigned(va->va_uid);
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = nfs_false;
+ }
+ if (full && va->va_gid != (gid_t)VNOVAL) {
+ nfsm_build_xx((void **)tl, 2 * NFSX_UNSIGNED, mb, bpos);
+ *(*tl)++ = nfs_true;
+ **tl = txdr_unsigned(va->va_gid);
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = nfs_false;
+ }
+ if (full && va->va_size != VNOVAL) {
+ nfsm_build_xx((void **)tl, 3 * NFSX_UNSIGNED, mb, bpos);
+ *(*tl)++ = nfs_true;
+ txdr_hyper(va->va_size, *tl);
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = nfs_false;
+ }
+ if (va->va_atime.tv_sec != VNOVAL) {
+ if (va->va_atime.tv_sec != time_second) {
+ nfsm_build_xx((void **)tl, 3 * NFSX_UNSIGNED, mb, bpos);
+ *(*tl)++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
+ txdr_nfsv3time(&va->va_atime, *tl);
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
+ }
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
+ }
+ if (va->va_mtime.tv_sec != VNOVAL) {
+ if (va->va_mtime.tv_sec != time_second) {
+ nfsm_build_xx((void **)tl, 3 * NFSX_UNSIGNED, mb, bpos);
+ *(*tl)++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
+ txdr_nfsv3time(&va->va_mtime, *tl);
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
+ }
+ } else {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED, mb, bpos);
+ **tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
+ }
}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index c70600f..68d0b93 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -34,9 +34,11 @@
* SUCH DAMAGE.
*
* @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include "opt_bootp.h"
#include <sys/param.h>
@@ -63,25 +65,16 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfsmount.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsdiskless.h>
-#include <nfs/nqnfs.h>
-
-extern int nfs_mountroot __P((struct mount *mp));
-
-extern int nfs_ticks;
+#include <nfsclient/nfsm_subs.h>
+#include <nfsclient/nfsdiskless.h>
MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle");
-MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data");
-MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
-MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure");
-MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease");
MALLOC_DEFINE(M_NFSHASH, "NFS hash", "NFS hash tables");
vm_zone_t nfsmount_zone;
@@ -89,26 +82,24 @@ vm_zone_t nfsmount_zone;
struct nfsstats nfsstats;
SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
- &nfsstats, nfsstats, "");
+ &nfsstats, nfsstats, "S,nfsstats");
#ifdef NFS_DEBUG
int nfs_debug;
SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
#endif
-static int nfs_iosize __P((struct nfsmount *nmp));
-static void nfs_decode_args __P((struct nfsmount *nmp,
- struct nfs_args *argp));
-static int mountnfs __P((struct nfs_args *,struct mount *,
- struct sockaddr *,char *,char *,struct vnode **));
-static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct thread *p));
-static int nfs_unmount __P(( struct mount *mp, int mntflags,
- struct thread *p));
-static int nfs_root __P(( struct mount *mp, struct vnode **vpp));
-static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp,
- struct thread *p));
-static int nfs_sync __P(( struct mount *mp, int waitfor,
- struct ucred *cred, struct thread *p));
+static int nfs_iosize(struct nfsmount *nmp);
+static void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp);
+static int mountnfs(struct nfs_args *, struct mount *,
+ struct sockaddr *, char *, char *, struct vnode **);
+static int nfs_mount(struct mount *mp, char *path, caddr_t data,
+ struct nameidata *ndp, struct thread *td);
+static int nfs_unmount(struct mount *mp, int mntflags, struct thread *td);
+static int nfs_root(struct mount *mp, struct vnode **vpp);
+static int nfs_statfs(struct mount *mp, struct statfs *sbp,
+ struct thread *td);
+static int nfs_sync(struct mount *mp, int waitfor, struct ucred *cred,
+ struct thread *td);
/*
* nfs vfs operations.
@@ -140,7 +131,7 @@ struct nfs_diskless nfs_diskless = { { { 0 } } };
struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
int nfs_diskless_valid = 0;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
+SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
&nfs_diskless_valid, 0, "");
SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
@@ -154,22 +145,20 @@ SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD,
nfsv3_diskless.swap_hostnam, 0, "");
SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
- &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr,
+ &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr,
"%Ssockaddr_in","");
-void nfsargs_ntoh __P((struct nfs_args *));
-static int nfs_mountdiskless __P((char *, char *, int,
- struct sockaddr_in *, struct nfs_args *,
- struct thread *, struct vnode **,
- struct mount **));
-static void nfs_convert_diskless __P((void));
-static void nfs_convert_oargs __P((struct nfs_args *args,
- struct onfs_args *oargs));
+void nfsargs_ntoh(struct nfs_args *);
+static int nfs_mountdiskless(char *, char *, int,
+ struct sockaddr_in *, struct nfs_args *,
+ struct thread *, struct vnode **, struct mount **);
+static void nfs_convert_diskless(void);
+static void nfs_convert_oargs(struct nfs_args *args,
+ struct onfs_args *oargs);
static int
-nfs_iosize(nmp)
- struct nfsmount* nmp;
+nfs_iosize(struct nfsmount *nmp)
{
int iosize;
@@ -185,10 +174,9 @@ nfs_iosize(nmp)
}
static void
-nfs_convert_oargs(args, oargs)
- struct nfs_args *args;
- struct onfs_args *oargs;
+nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
{
+
args->version = NFS_ARGSVERSION;
args->addr = oargs->addr;
args->addrlen = oargs->addrlen;
@@ -204,35 +192,35 @@ nfs_convert_oargs(args, oargs)
args->retrans = oargs->retrans;
args->maxgrouplist = oargs->maxgrouplist;
args->readahead = oargs->readahead;
- args->leaseterm = oargs->leaseterm;
args->deadthresh = oargs->deadthresh;
args->hostname = oargs->hostname;
}
static void
-nfs_convert_diskless()
+nfs_convert_diskless(void)
{
+
bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
sizeof(struct ifaliasreq));
bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
sizeof(struct sockaddr_in));
nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
nfsv3_diskless.swap_fhsize = NFSX_V2FH;
- bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
+ bcopy(nfs_diskless.swap_fh, nfsv3_diskless.swap_fh, NFSX_V2FH);
bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
sizeof(struct sockaddr_in));
- bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, MNAMELEN);
+ bcopy(nfs_diskless.swap_hostnam, nfsv3_diskless.swap_hostnam, MNAMELEN);
nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
sizeof(struct ucred));
nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
nfsv3_diskless.root_fhsize = NFSX_V2FH;
- bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
+ bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
sizeof(struct sockaddr_in));
- bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, MNAMELEN);
+ bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
nfsv3_diskless.root_time = nfs_diskless.root_time;
- bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam,
+ bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
MAXHOSTNAMELEN);
nfs_diskless_valid = 3;
}
@@ -241,20 +229,15 @@ nfs_convert_diskless()
* nfs statfs call
*/
int
-nfs_statfs(mp, sbp, td)
- struct mount *mp;
- register struct statfs *sbp;
- struct thread *td;
+nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
{
- register struct vnode *vp;
- register struct nfs_statfs *sfp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ struct vnode *vp;
+ struct nfs_statfs *sfp;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
struct nfsmount *nmp = VFSTONFS(mp);
int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
struct nfsnode *np;
u_quad_t tquad;
@@ -268,7 +251,9 @@ nfs_statfs(mp, sbp, td)
if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
(void)nfs_fsinfo(nmp, vp, td->td_proc->p_ucred, td);
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
- nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
+ mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_proc->p_ucred);
if (v3)
@@ -306,7 +291,8 @@ nfs_statfs(mp, sbp, td)
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
vput(vp);
return (error);
}
@@ -315,23 +301,20 @@ nfs_statfs(mp, sbp, td)
* nfs version 3 fsinfo rpc call
*/
int
-nfs_fsinfo(nmp, vp, cred, td)
- register struct nfsmount *nmp;
- register struct vnode *vp;
- struct ucred *cred;
- struct thread *td;
+nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
+ struct thread *td)
{
- register struct nfsv3_fsinfo *fsp;
- register caddr_t cp;
- register int32_t t1, t2;
- register u_int32_t *tl, pref, max;
- caddr_t bpos, dpos, cp2;
+ struct nfsv3_fsinfo *fsp;
+ u_int32_t *tl, pref, max;
+ caddr_t bpos, dpos;
int error = 0, retattr;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
u_int64_t maxfsize;
nfsstats.rpccnt[NFSPROC_FSINFO]++;
- nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
+ mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, 1);
nfsm_request(vp, NFSPROC_FSINFO, td, cred);
nfsm_postop_attr(vp, retattr);
@@ -371,7 +354,8 @@ nfs_fsinfo(nmp, vp, cred, td)
nmp->nm_maxfilesize = maxfsize;
nmp->nm_state |= NFSSTA_GOTFSINFO;
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
return (error);
}
@@ -387,8 +371,7 @@ nfs_fsinfo(nmp, vp, cred, td)
* - build the rootfs mount point and call mountnfs() to do the rest.
*/
int
-nfs_mountroot(mp)
- struct mount *mp;
+nfs_mountroot(struct mount *mp)
{
struct mount *swap_mp;
struct nfsv3_diskless *nd = &nfsv3_diskless;
@@ -410,8 +393,8 @@ nfs_mountroot(mp)
while (time_second == 0)
tsleep(&time_second, PZERO+8, "arpkludge", 10);
- if (nfs_diskless_valid==1)
- nfs_convert_diskless();
+ if (nfs_diskless_valid==1)
+ nfs_convert_diskless();
/*
* XXX splnet, so networks will receive...
@@ -485,8 +468,8 @@ nfs_mountroot(mp)
l = ntohl(nd->root_saddr.sin_addr.s_addr);
snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
(l >> 24) & 0xff, (l >> 16) & 0xff,
- (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
- printf("NFS ROOT: %s\n",buf);
+ (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
+ printf("NFS ROOT: %s\n", buf);
if ((error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
&nd->root_saddr, &nd->root_args, td, &vp, &mp)) != 0) {
if (swap_mp) {
@@ -511,16 +494,15 @@ nfs_mountroot(mp)
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
(l >> 24) & 0xff, (l >> 16) & 0xff,
- (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam);
- printf("NFS SWAP: %s\n",buf);
+ (l >> 8) & 0xff, (l >> 0) & 0xff, nd->swap_hostnam);
+ printf("NFS SWAP: %s\n", buf);
if ((error = nfs_mountdiskless(buf, "/swap", 0,
&nd->swap_saddr, &nd->swap_args, td, &vp, &swap_mp)) != 0)
return (error);
vfs_unbusy(swap_mp, td);
- VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
+ VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
nd->swap_nblks * DEV_BSIZE ;
-
/*
* Since the swap file is not the root dir of a file system,
* hack it to a regular file.
@@ -554,15 +536,9 @@ nfs_mountroot(mp)
* Internal version of mount system call for diskless setup.
*/
static int
-nfs_mountdiskless(path, which, mountflag, sin, args, td, vpp, mpp)
- char *path;
- char *which;
- int mountflag;
- struct sockaddr_in *sin;
- struct nfs_args *args;
- struct thread *td;
- struct vnode **vpp;
- struct mount **mpp;
+nfs_mountdiskless(char *path, char *which, int mountflag,
+ struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
+ struct vnode **vpp, struct mount **mpp)
{
struct mount *mp;
struct sockaddr *nam;
@@ -592,9 +568,7 @@ nfs_mountdiskless(path, which, mountflag, sin, args, td, vpp, mpp)
}
static void
-nfs_decode_args(nmp, argp)
- struct nfsmount *nmp;
- struct nfs_args *argp;
+nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp)
{
int s;
int adjsock;
@@ -710,17 +684,11 @@ nfs_decode_args(nmp, argp)
else
nmp->nm_readahead = NFS_MAXRAHEAD;
}
- if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2) {
- if (argp->leaseterm <= NQ_MAXLEASE)
- nmp->nm_leaseterm = argp->leaseterm;
- else
- nmp->nm_leaseterm = NQ_MAXLEASE;
- }
- if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1) {
- if (argp->deadthresh <= NQ_NEVERDEAD)
+ if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
+ if (argp->deadthresh <= NFS_MAXDEADTHRESH)
nmp->nm_deadthresh = argp->deadthresh;
else
- nmp->nm_deadthresh = NQ_NEVERDEAD;
+ nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
}
adjsock |= ((nmp->nm_sotype != argp->sotype) ||
@@ -750,12 +718,8 @@ nfs_decode_args(nmp, argp)
*/
/* ARGSUSED */
static int
-nfs_mount(mp, path, data, ndp, td)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct thread *td;
+nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
+ struct thread *td)
{
int error;
struct nfs_args args;
@@ -789,18 +753,18 @@ nfs_mount(mp, path, data, ndp, td)
#endif /* COMPAT_PRELITE2 */
}
if (mp->mnt_flag & MNT_UPDATE) {
- register struct nfsmount *nmp = VFSTONFS(mp);
+ struct nfsmount *nmp = VFSTONFS(mp);
if (nmp == NULL)
return (EIO);
/*
* When doing an update, we can't change from or to
- * v3 and/or nqnfs, or change cookie translation
+ * v3, or change cookie translation
*/
args.flags = (args.flags &
- ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
+ ~(NFSMNT_NFSV3 /*|NFSMNT_XLATECOOKIE*/)) |
(nmp->nm_flag &
- (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
+ (NFSMNT_NFSV3 /*|NFSMNT_XLATECOOKIE*/));
nfs_decode_args(nmp, &args);
return (0);
}
@@ -826,14 +790,10 @@ nfs_mount(mp, path, data, ndp, td)
* Common code for mount and mountroot
*/
static int
-mountnfs(argp, mp, nam, pth, hst, vpp)
- register struct nfs_args *argp;
- register struct mount *mp;
- struct sockaddr *nam;
- char *pth, *hst;
- struct vnode **vpp;
+mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
+ char *pth, char *hst, struct vnode **vpp)
{
- register struct nfsmount *nmp;
+ struct nfsmount *nmp;
struct nfsnode *np;
int error;
struct vattr attrs;
@@ -846,20 +806,11 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
} else {
nmp = zalloc(nfsmount_zone);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
- TAILQ_INIT(&nmp->nm_uidlruhead);
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
- if (argp->flags & NFSMNT_NQNFS)
- /*
- * We have to set mnt_maxsymlink to a non-zero value so
- * that COMPAT_43 routines will know that we are setting
- * the d_type field in directories (and can zero it for
- * unsuspecting binaries).
- */
- mp->mnt_maxsymlinklen = 1;
/*
* V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
@@ -883,10 +834,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
- nmp->nm_leaseterm = NQ_DEFLEASE;
- nmp->nm_deadthresh = NQ_DEADTHRESH;
- TAILQ_INIT(&nmp->nm_timerhead);
- nmp->nm_inprog = NULLVP;
+ nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
@@ -949,12 +897,9 @@ bad:
* unmount system call
*/
static int
-nfs_unmount(mp, mntflags, td)
- struct mount *mp;
- int mntflags;
- struct thread *td;
+nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
{
- register struct nfsmount *nmp;
+ struct nfsmount *nmp;
int error, flags = 0;
if (mntflags & MNT_FORCE)
@@ -966,32 +911,18 @@ nfs_unmount(mp, mntflags, td)
* - Close the socket
* - Free up the data structures
*/
- /*
- * Must handshake with nqnfs_clientd() if it is active.
- */
- nmp->nm_state |= NFSSTA_DISMINPROG;
- while (nmp->nm_inprog != NULLVP)
- (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
-
/* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
error = vflush(mp, 1, flags);
- if (error) {
- nmp->nm_state &= ~NFSSTA_DISMINPROG;
+ if (error)
return (error);
- }
/*
* We are now committed to the unmount.
- * For NQNFS, let the server daemon free the nfsmount structure.
*/
- if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
- nmp->nm_state |= NFSSTA_DISMNT;
-
nfs_disconnect(nmp);
FREE(nmp->nm_nam, M_SONAME);
- if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
- zfree(nfsmount_zone, nmp);
+ zfree(nfsmount_zone, nmp);
return (0);
}
@@ -999,11 +930,9 @@ nfs_unmount(mp, mntflags, td)
* Return root of a filesystem
*/
static int
-nfs_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
+nfs_root(struct mount *mp, struct vnode **vpp)
{
- register struct vnode *vp;
+ struct vnode *vp;
struct nfsmount *nmp;
struct nfsnode *np;
int error;
@@ -1020,18 +949,12 @@ nfs_root(mp, vpp)
return (0);
}
-extern int syncprt;
-
/*
* Flush out the buffer cache
*/
/* ARGSUSED */
static int
-nfs_sync(mp, waitfor, cred, td)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct thread *td;
+nfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct thread *td)
{
struct vnode *vp, *vnp;
int error, allerror = 0;
@@ -1072,4 +995,3 @@ loop:
mtx_unlock(&mntvnode_mtx);
return (allerror);
}
-
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 8f9ff7d..4fc4521 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -34,9 +34,10 @@
* SUCH DAMAGE.
*
* @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/*
* vnode op calls for Sun NFS version 2 and 3
@@ -70,13 +71,12 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsmount.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfs_lock.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfs_lock.h>
+#include <nfsclient/nfsm_subs.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -95,40 +95,43 @@
#define vfs_busy_pages(bp, f)
#endif
-static int nfsspec_read __P((struct vop_read_args *));
-static int nfsspec_write __P((struct vop_write_args *));
-static int nfsfifo_read __P((struct vop_read_args *));
-static int nfsfifo_write __P((struct vop_write_args *));
-static int nfsspec_close __P((struct vop_close_args *));
-static int nfsfifo_close __P((struct vop_close_args *));
-#define nfs_poll vop_nopoll
-static int nfs_flush __P((struct vnode *,struct ucred *,int,struct thread *,int));
-static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct thread *));
-static int nfs_lookup __P((struct vop_lookup_args *));
-static int nfs_create __P((struct vop_create_args *));
-static int nfs_mknod __P((struct vop_mknod_args *));
-static int nfs_open __P((struct vop_open_args *));
-static int nfs_close __P((struct vop_close_args *));
-static int nfs_access __P((struct vop_access_args *));
-static int nfs_getattr __P((struct vop_getattr_args *));
-static int nfs_setattr __P((struct vop_setattr_args *));
-static int nfs_read __P((struct vop_read_args *));
-static int nfs_fsync __P((struct vop_fsync_args *));
-static int nfs_remove __P((struct vop_remove_args *));
-static int nfs_link __P((struct vop_link_args *));
-static int nfs_rename __P((struct vop_rename_args *));
-static int nfs_mkdir __P((struct vop_mkdir_args *));
-static int nfs_rmdir __P((struct vop_rmdir_args *));
-static int nfs_symlink __P((struct vop_symlink_args *));
-static int nfs_readdir __P((struct vop_readdir_args *));
-static int nfs_strategy __P((struct vop_strategy_args *));
-static int nfs_lookitup __P((struct vnode *, const char *, int,
- struct ucred *, struct thread *, struct nfsnode **));
-static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
-static int nfsspec_access __P((struct vop_access_args *));
-static int nfs_readlink __P((struct vop_readlink_args *));
-static int nfs_print __P((struct vop_print_args *));
-static int nfs_advlock __P((struct vop_advlock_args *));
+static int nfsspec_read(struct vop_read_args *);
+static int nfsspec_write(struct vop_write_args *);
+static int nfsfifo_read(struct vop_read_args *);
+static int nfsfifo_write(struct vop_write_args *);
+static int nfsspec_close(struct vop_close_args *);
+static int nfsfifo_close(struct vop_close_args *);
+static int nfs_flush(struct vnode *, struct ucred *, int, struct thread *,
+ int);
+static int nfs_setattrrpc(struct vnode *, struct vattr *, struct ucred *,
+ struct thread *);
+static int nfs_lookup(struct vop_lookup_args *);
+static int nfs_create(struct vop_create_args *);
+static int nfs_mknod(struct vop_mknod_args *);
+static int nfs_open(struct vop_open_args *);
+static int nfs_close(struct vop_close_args *);
+static int nfs_access(struct vop_access_args *);
+static int nfs_getattr(struct vop_getattr_args *);
+static int nfs_setattr(struct vop_setattr_args *);
+static int nfs_read(struct vop_read_args *);
+static int nfs_fsync(struct vop_fsync_args *);
+static int nfs_remove(struct vop_remove_args *);
+static int nfs_link(struct vop_link_args *);
+static int nfs_rename(struct vop_rename_args *);
+static int nfs_mkdir(struct vop_mkdir_args *);
+static int nfs_rmdir(struct vop_rmdir_args *);
+static int nfs_symlink(struct vop_symlink_args *);
+static int nfs_readdir(struct vop_readdir_args *);
+static int nfs_strategy(struct vop_strategy_args *);
+static int nfs_lookitup(struct vnode *, const char *, int,
+ struct ucred *, struct thread *, struct nfsnode **);
+static int nfs_sillyrename(struct vnode *, struct vnode *,
+ struct componentname *);
+static int nfsspec_access(struct vop_access_args *);
+static int nfs_readlink(struct vop_readlink_args *);
+static int nfs_print(struct vop_print_args *);
+static int nfs_advlock(struct vop_advlock_args *);
+
/*
* Global vfs data structures for nfs
*/
@@ -152,7 +155,6 @@ static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
{ &vop_mkdir_desc, (vop_t *) nfs_mkdir },
{ &vop_mknod_desc, (vop_t *) nfs_mknod },
{ &vop_open_desc, (vop_t *) nfs_open },
- { &vop_poll_desc, (vop_t *) nfs_poll },
{ &vop_print_desc, (vop_t *) nfs_print },
{ &vop_read_desc, (vop_t *) nfs_read },
{ &vop_readdir_desc, (vop_t *) nfs_readdir },
@@ -219,46 +221,39 @@ static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
{ &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries };
VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
-static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap));
-static int nfs_removerpc __P((struct vnode *dvp, const char *name,
- int namelen,
- struct ucred *cred, struct thread *td));
-static int nfs_renamerpc __P((struct vnode *fdvp, const char *fnameptr,
- int fnamelen, struct vnode *tdvp,
- const char *tnameptr, int tnamelen,
- struct ucred *cred, struct thread *td));
-static int nfs_renameit __P((struct vnode *sdvp,
- struct componentname *scnp,
- struct sillyrename *sp));
+static int nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp,
+ struct componentname *cnp, struct vattr *vap);
+static int nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
+ struct ucred *cred, struct thread *td);
+static int nfs_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 nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
+ struct sillyrename *sp);
/*
* Global variables
*/
-extern u_int32_t nfs_true, nfs_false;
-extern u_int32_t nfs_xdrneg1;
-extern struct nfsstats nfsstats;
-extern nfstype nfsv3_type[9];
-struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
+struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
-int nfs_numasync = 0;
+int nfs_numasync = 0;
#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
SYSCTL_DECL(_vfs_nfs);
static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
+SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
&nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
static int nfsv3_commit_on_close = 0;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW,
+SYSCTL_INT(_vfs_nfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW,
&nfsv3_commit_on_close, 0, "write+commit on close, else only write");
#if 0
-SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_hits, CTLFLAG_RD,
+SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_hits, CTLFLAG_RD,
&nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
+SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
&nfsstats.accesscache_misses, 0, "NFS ACCESS cache miss count");
#endif
@@ -266,27 +261,25 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
| NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
| NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
static int
-nfs3_access_otw(struct vnode *vp,
- int wmode,
- struct thread *td,
- struct ucred *cred)
+nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td,
+ struct ucred *cred)
{
const int v3 = 1;
u_int32_t *tl;
int error = 0, attrflag;
-
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
- caddr_t bpos, dpos, cp2;
- register int32_t t1, t2;
- register caddr_t cp;
+
+ struct mbuf *mreq, *mrep, *md, *mb;
+ caddr_t bpos, dpos;
u_int32_t rmode;
struct nfsnode *np = VTONFS(vp);
nfsstats.rpccnt[NFSPROC_ACCESS]++;
- nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
+ mreq = nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(wmode);
+ *tl = txdr_unsigned(wmode);
nfsm_request(vp, NFSPROC_ACCESS, td, cred);
nfsm_postop_attr(vp, attrflag);
if (!error) {
@@ -296,7 +289,8 @@ nfs3_access_otw(struct vnode *vp,
np->n_modeuid = cred->cr_uid;
np->n_modestamp = time_second;
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
return error;
}
@@ -307,15 +301,9 @@ nfs3_access_otw(struct vnode *vp,
* are changed on the server, accesses might still fail later.
*/
static int
-nfs_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfs_access(struct vop_access_args *ap)
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
int error = 0;
u_int32_t mode, wmode;
int v3 = NFS_ISV3(vp);
@@ -363,8 +351,8 @@ nfs_access(ap)
}
/* XXX safety belt, only make blanket request if caching */
if (nfsaccess_cache_timeout > 0) {
- wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY |
- NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE |
+ wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY |
+ NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE |
NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP;
} else {
wmode = mode;
@@ -445,73 +433,47 @@ nfs_access(ap)
*/
/* ARGSUSED */
static int
-nfs_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfs_open(struct vop_open_args *ap)
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
struct nfsnode *np = VTONFS(vp);
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
struct vattr vattr;
int error;
if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
#ifdef DIAGNOSTIC
- printf("open eacces vtyp=%d\n",vp->v_type);
+ printf("open eacces vtyp=%d\n", vp->v_type);
#endif
return (EACCES);
}
/*
* Get a valid lease. If cached data is stale, flush it.
*/
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (NQNFS_CKINVALID(vp, np, ND_READ)) {
- do {
- error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
- ap->a_td);
- } while (error == NQNFS_EXPIRED);
- if (error)
+ if (np->n_flag & NMODIFIED) {
+ if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
+ ap->a_td, 1)) == EINTR)
return (error);
- if (np->n_lrev != np->n_brev ||
- (np->n_flag & NQNFSNONCACHE)) {
- if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
- ap->a_td, 1)) == EINTR)
- return (error);
- np->n_brev = np->n_lrev;
- }
- }
+ np->n_attrstamp = 0;
+ if (vp->v_type == VDIR)
+ np->n_direofoffset = 0;
+ error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
+ np->n_mtime = vattr.va_mtime.tv_sec;
} else {
- if (np->n_flag & NMODIFIED) {
- if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
- ap->a_td, 1)) == EINTR)
- return (error);
- np->n_attrstamp = 0;
+ error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
+ if (np->n_mtime != vattr.va_mtime.tv_sec) {
if (vp->v_type == VDIR)
np->n_direofoffset = 0;
- error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
- if (error)
+ if ((error = nfs_vinvalbuf(vp, V_SAVE,
+ ap->a_cred, ap->a_td, 1)) == EINTR)
return (error);
np->n_mtime = vattr.va_mtime.tv_sec;
- } else {
- error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- if (np->n_mtime != vattr.va_mtime.tv_sec) {
- if (vp->v_type == VDIR)
- np->n_direofoffset = 0;
- if ((error = nfs_vinvalbuf(vp, V_SAVE,
- ap->a_cred, ap->a_td, 1)) == EINTR)
- return (error);
- np->n_mtime = vattr.va_mtime.tv_sec;
- }
}
}
- if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
- np->n_attrstamp = 0; /* For Open/Close consistency */
+ np->n_attrstamp = 0; /* For Open/Close consistency */
return (0);
}
@@ -541,28 +503,17 @@ nfs_open(ap)
* enough". Changing the last argument to nfs_flush() to
* a 1 would force a commit operation, if it is felt a
* commit is necessary now.
- * for NQNFS - do nothing now, since 2 is dealt with via leases and
- * 1 should be dealt with via an fsync() system call for
- * cases where write errors are important.
*/
/* ARGSUSED */
static int
-nfs_close(ap)
- struct vop_close_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfs_close(struct vop_close_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
int error = 0;
if (vp->v_type == VREG) {
- if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
- (np->n_flag & NMODIFIED)) {
+ if (np->n_flag & NMODIFIED) {
if (NFS_ISV3(vp)) {
/*
* Under NFSv3 we have dirty buffers to dispose of. We
@@ -597,24 +548,16 @@ nfs_close(ap)
* nfs getattr call from vfs.
*/
static int
-nfs_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfs_getattr(struct vop_getattr_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1, t2;
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
+ u_int32_t *tl;
caddr_t bpos, dpos;
int error = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(vp);
-
+
/*
* Update local times for special files.
*/
@@ -634,13 +577,16 @@ nfs_getattr(ap)
}
nfsstats.rpccnt[NFSPROC_GETATTR]++;
- nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
+ mreq = nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_GETATTR, ap->a_td, ap->a_cred);
if (!error) {
nfsm_loadattr(vp, ap->a_vap);
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
return (error);
}
@@ -648,18 +594,11 @@ nfs_getattr(ap)
* nfs setattr call.
*/
static int
-nfs_setattr(ap)
- struct vop_setattr_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfs_setattr(struct vop_setattr_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register struct vattr *vap = ap->a_vap;
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
+ struct vattr *vap = ap->a_vap;
int error = 0;
u_quad_t tsize;
@@ -738,23 +677,20 @@ nfs_setattr(ap)
* Do an nfs setattr rpc.
*/
static int
-nfs_setattrrpc(vp, vap, cred, td)
- register struct vnode *vp;
- register struct vattr *vap;
- struct ucred *cred;
- struct thread *td;
+nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred,
+ struct thread *td)
{
- register struct nfsv2_sattr *sp;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ struct nfsv2_sattr *sp;
+ caddr_t bpos, dpos;
u_int32_t *tl;
int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(vp);
nfsstats.rpccnt[NFSPROC_SETATTR]++;
- nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
+ mreq = nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
if (v3) {
nfsm_v3attrbuild(vap, TRUE);
@@ -783,7 +719,8 @@ nfs_setattrrpc(vp, vap, cred, td)
nfsm_wcc_data(vp, wccflag);
} else
nfsm_loadattr(vp, (struct vattr *)0);
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
return (error);
}
@@ -793,13 +730,7 @@ nfs_setattrrpc(vp, vap, cred, td)
* If not found, unlock the directory nfsnode and do the rpc
*/
static int
-nfs_lookup(ap)
- struct vop_lookup_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- } */ *ap;
+nfs_lookup(struct vop_lookup_args *ap)
{
struct componentname *cnp = ap->a_cnp;
struct vnode *dvp = ap->a_dvp;
@@ -807,11 +738,9 @@ nfs_lookup(ap)
int flags = cnp->cn_flags;
struct vnode *newvp;
u_int32_t *tl;
- caddr_t cp;
- int32_t t1, t2;
struct nfsmount *nmp;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ caddr_t bpos, dpos;
+ struct mbuf *mreq, *mrep, *md, *mb;
long len;
nfsfh_t *fhp;
struct nfsnode *np;
@@ -893,8 +822,10 @@ nfs_lookup(ap)
nfsstats.lookupcache_misses++;
nfsstats.rpccnt[NFSPROC_LOOKUP]++;
len = cnp->cn_namelen;
- nfsm_reqhead(dvp, NFSPROC_LOOKUP,
+ mreq = nfsm_reqhead(dvp, NFSPROC_LOOKUP,
NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred);
@@ -979,7 +910,8 @@ nfs_lookup(ap)
cache_enter(dvp, newvp, cnp);
}
*vpp = newvp;
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
if (error) {
if (newvp != NULLVP) {
vrele(newvp);
@@ -1007,15 +939,9 @@ nfs_lookup(ap)
* Just call nfs_bioread() to do the work.
*/
static int
-nfs_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+nfs_read(struct vop_read_args *ap)
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
if (vp->v_type != VREG)
return (EPERM);
@@ -1026,14 +952,9 @@ nfs_read(ap)
* nfs readlink call
*/
static int
-nfs_readlink(ap)
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
+nfs_readlink(struct vop_readlink_args *ap)
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
if (vp->v_type != VLNK)
return (EINVAL);
@@ -1045,21 +966,18 @@ nfs_readlink(ap)
* Called by nfs_doio() from below the buffer cache.
*/
int
-nfs_readlinkrpc(vp, uiop, cred)
- register struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
+nfs_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
int error = 0, len, attrflag;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(vp);
nfsstats.rpccnt[NFSPROC_READLINK]++;
- nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
+ mreq = nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_READLINK, uiop->uio_td, cred);
if (v3)
@@ -1073,7 +991,8 @@ nfs_readlinkrpc(vp, uiop, cred)
}
nfsm_mtouio(uiop, len);
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
return (error);
}
@@ -1082,16 +1001,11 @@ nfs_readlinkrpc(vp, uiop, cred)
* Ditto above
*/
int
-nfs_readrpc(vp, uiop, cred)
- register struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
+nfs_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
+ struct mbuf *mreq, *mrep, *md, *mb;
struct nfsmount *nmp;
int error = 0, len, retlen, tsiz, eof, attrflag;
int v3 = NFS_ISV3(vp);
@@ -1106,7 +1020,9 @@ nfs_readrpc(vp, uiop, cred)
while (tsiz > 0) {
nfsstats.rpccnt[NFSPROC_READ]++;
len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
- nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
+ mreq = nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
if (v3) {
@@ -1146,17 +1062,13 @@ nfsmout:
* nfs write call
*/
int
-nfs_writerpc(vp, uiop, cred, iomode, must_commit)
- register struct vnode *vp;
- register struct uio *uiop;
- struct ucred *cred;
- int *iomode, *must_commit;
+nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
+ int *iomode, int *must_commit)
{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2, backup;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ u_int32_t *tl;
+ int32_t backup;
+ caddr_t bpos, dpos;
+ struct mbuf *mreq, *mrep, *md, *mb;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
@@ -1172,8 +1084,10 @@ nfs_writerpc(vp, uiop, cred, iomode, must_commit)
while (tsiz > 0) {
nfsstats.rpccnt[NFSPROC_WRITE]++;
len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
- nfsm_reqhead(vp, NFSPROC_WRITE,
+ mreq = nfsm_reqhead(vp, NFSPROC_WRITE,
NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
if (v3) {
nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
@@ -1183,7 +1097,7 @@ nfs_writerpc(vp, uiop, cred, iomode, must_commit)
*tl++ = txdr_unsigned(*iomode);
*tl = txdr_unsigned(len);
} else {
- register u_int32_t x;
+ u_int32_t x;
nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
/* Set both "begin" and "current" to non-garbage. */
@@ -1261,23 +1175,17 @@ nfsmout:
* mode set to specify the file type and the size field for rdev.
*/
static int
-nfs_mknodrpc(dvp, vpp, cnp, vap)
- register struct vnode *dvp;
- register struct vnode **vpp;
- register struct componentname *cnp;
- register struct vattr *vap;
+nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
+ struct vattr *vap)
{
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
+ struct nfsv2_sattr *sp;
+ u_int32_t *tl;
struct vnode *newvp = (struct vnode *)0;
struct nfsnode *np = (struct nfsnode *)0;
struct vattr vattr;
- char *cp2;
caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
u_int32_t rdev;
int v3 = NFS_ISV3(dvp);
@@ -1292,8 +1200,10 @@ nfs_mknodrpc(dvp, vpp, cnp, vap)
return (error);
}
nfsstats.rpccnt[NFSPROC_MKNOD]++;
- nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
+ mreq = nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
+ nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
if (v3) {
@@ -1330,7 +1240,8 @@ nfs_mknodrpc(dvp, vpp, cnp, vap)
}
if (v3)
nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
if (error) {
if (newvp)
vput(newvp);
@@ -1351,14 +1262,9 @@ nfs_mknodrpc(dvp, vpp, cnp, vap)
*/
/* ARGSUSED */
static int
-nfs_mknod(ap)
- struct vop_mknod_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
+nfs_mknod(struct vop_mknod_args *ap)
{
+
return nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
}
@@ -1367,26 +1273,18 @@ static u_long create_verf;
* nfs file create call
*/
static int
-nfs_create(ap)
- struct vop_create_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
+nfs_create(struct vop_create_args *ap)
{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
+ struct componentname *cnp = ap->a_cnp;
+ struct nfsv2_sattr *sp;
+ u_int32_t *tl;
struct nfsnode *np = (struct nfsnode *)0;
struct vnode *newvp = (struct vnode *)0;
- caddr_t bpos, dpos, cp2;
+ caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
struct vattr vattr;
int v3 = NFS_ISV3(dvp);
@@ -1403,8 +1301,10 @@ nfs_create(ap)
fmode |= O_EXCL;
again:
nfsstats.rpccnt[NFSPROC_CREATE]++;
- nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
+ mreq = nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
if (v3) {
@@ -1414,7 +1314,7 @@ again:
nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
#ifdef INET
if (!TAILQ_EMPTY(&in_ifaddrhead))
- *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr;
+ *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr.s_addr;
else
#endif
*tl++ = create_verf;
@@ -1448,7 +1348,8 @@ again:
}
if (v3)
nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
if (error) {
if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
fmode &= ~O_EXCL;
@@ -1494,18 +1395,12 @@ again:
* do the remove rpc
*/
static int
-nfs_remove(ap)
- struct vop_remove_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode * a_dvp;
- struct vnode * a_vp;
- struct componentname * a_cnp;
- } */ *ap;
+nfs_remove(struct vop_remove_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsnode *np = VTONFS(vp);
+ 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;
@@ -1555,8 +1450,7 @@ nfs_remove(ap)
* nfs file remove rpc called from nfs_inactive
*/
int
-nfs_removeit(sp)
- register struct sillyrename *sp;
+nfs_removeit(struct sillyrename *sp)
{
return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
@@ -1567,30 +1461,27 @@ nfs_removeit(sp)
* Nfs remove rpc, called from nfs_remove() and nfs_removeit().
*/
static int
-nfs_removerpc(dvp, name, namelen, cred, td)
- register struct vnode *dvp;
- const char *name;
- int namelen;
- struct ucred *cred;
- struct thread *td;
+nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
+ struct ucred *cred, struct thread *td)
{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(dvp);
nfsstats.rpccnt[NFSPROC_REMOVE]++;
- nfsm_reqhead(dvp, NFSPROC_REMOVE,
+ mreq = nfsm_reqhead(dvp, NFSPROC_REMOVE,
NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
nfsm_request(dvp, NFSPROC_REMOVE, td, cred);
if (v3)
nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
VTONFS(dvp)->n_flag |= NMODIFIED;
if (!wccflag)
VTONFS(dvp)->n_attrstamp = 0;
@@ -1601,22 +1492,14 @@ nfs_removerpc(dvp, name, namelen, cred, td)
* nfs file rename call
*/
static int
-nfs_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
+nfs_rename(struct vop_rename_args *ap)
{
- register struct vnode *fvp = ap->a_fvp;
- register struct vnode *tvp = ap->a_tvp;
- register struct vnode *fdvp = ap->a_fdvp;
- register struct vnode *tdvp = ap->a_tdvp;
- register struct componentname *tcnp = ap->a_tcnp;
- register struct componentname *fcnp = ap->a_fcnp;
+ 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
@@ -1686,41 +1569,34 @@ out:
* nfs file rename rpc called from nfs_remove() above
*/
static int
-nfs_renameit(sdvp, scnp, sp)
- struct vnode *sdvp;
- struct componentname *scnp;
- register struct sillyrename *sp;
+nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
+ struct sillyrename *sp)
{
- return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
- sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread));
+
+ return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, sdvp,
+ sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread));
}
/*
* Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
*/
static int
-nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, td)
- register struct vnode *fdvp;
- const char *fnameptr;
- int fnamelen;
- register struct vnode *tdvp;
- const char *tnameptr;
- int tnamelen;
- struct ucred *cred;
- struct thread *td;
+nfs_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
+ struct vnode *tdvp, const char *tnameptr, int tnamelen, struct ucred *cred,
+ struct thread *td)
{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(fdvp);
nfsstats.rpccnt[NFSPROC_RENAME]++;
- nfsm_reqhead(fdvp, NFSPROC_RENAME,
+ mreq = nfsm_reqhead(fdvp, NFSPROC_RENAME,
(NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
nfsm_rndup(tnamelen));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(fdvp, v3);
nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
nfsm_fhtom(tdvp, v3);
@@ -1730,7 +1606,8 @@ nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, td)
nfsm_wcc_data(fdvp, fwccflag);
nfsm_wcc_data(tdvp, twccflag);
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
VTONFS(fdvp)->n_flag |= NMODIFIED;
VTONFS(tdvp)->n_flag |= NMODIFIED;
if (!fwccflag)
@@ -1744,22 +1621,15 @@ nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, td)
* nfs hard link create call
*/
static int
-nfs_link(ap)
- struct vop_link_args /* {
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
+nfs_link(struct vop_link_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct vnode *tdvp = ap->a_tdvp;
- register struct componentname *cnp = ap->a_cnp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *tdvp = ap->a_tdvp;
+ struct componentname *cnp = ap->a_cnp;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3;
if (vp->v_mount != tdvp->v_mount) {
@@ -1775,8 +1645,10 @@ nfs_link(ap)
v3 = NFS_ISV3(vp);
nfsstats.rpccnt[NFSPROC_LINK]++;
- nfsm_reqhead(vp, NFSPROC_LINK,
+ mreq = nfsm_reqhead(vp, NFSPROC_LINK,
NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
nfsm_fhtom(tdvp, v3);
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
@@ -1785,7 +1657,8 @@ nfs_link(ap)
nfsm_postop_attr(vp, attrflag);
nfsm_wcc_data(tdvp, wccflag);
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
VTONFS(tdvp)->n_flag |= NMODIFIED;
if (!attrflag)
VTONFS(vp)->n_attrstamp = 0;
@@ -1803,32 +1676,25 @@ nfs_link(ap)
* nfs symbolic link create call
*/
static int
-nfs_symlink(ap)
- struct vop_symlink_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
- } */ *ap;
+nfs_symlink(struct vop_symlink_args *ap)
{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
+ struct componentname *cnp = ap->a_cnp;
+ struct nfsv2_sattr *sp;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
struct vnode *newvp = (struct vnode *)0;
int v3 = NFS_ISV3(dvp);
nfsstats.rpccnt[NFSPROC_SYMLINK]++;
slen = strlen(ap->a_target);
- nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
+ mreq = nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
if (v3) {
@@ -1863,7 +1729,8 @@ nfs_symlink(ap)
* out code jumps -> here, mrep is also freed.
*/
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
/*
* If we get an EEXIST error, silently convert it to no-error
@@ -1876,7 +1743,7 @@ nfs_symlink(ap)
* If we do not have (or no longer have) an error, and we could
* not extract the newvp from the response due to the request being
* NFSv2 or the error being EEXIST. We have to do a lookup in order
- * to obtain a newvp to return.
+ * to obtain a newvp to return.
*/
if (error == 0 && newvp == NULL) {
struct nfsnode *np = NULL;
@@ -1902,28 +1769,20 @@ nfs_symlink(ap)
* nfs make dir call
*/
static int
-nfs_mkdir(ap)
- struct vop_mkdir_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
+nfs_mkdir(struct vop_mkdir_args *ap)
{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- register struct componentname *cnp = ap->a_cnp;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register int len;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
+ struct componentname *cnp = ap->a_cnp;
+ struct nfsv2_sattr *sp;
+ u_int32_t *tl;
+ int len;
struct nfsnode *np = (struct nfsnode *)0;
struct vnode *newvp = (struct vnode *)0;
- caddr_t bpos, dpos, cp2;
+ caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR;
int gotvp = 0;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
struct vattr vattr;
int v3 = NFS_ISV3(dvp);
@@ -1932,8 +1791,10 @@ nfs_mkdir(ap)
}
len = cnp->cn_namelen;
nfsstats.rpccnt[NFSPROC_MKDIR]++;
- nfsm_reqhead(dvp, NFSPROC_MKDIR,
+ mreq = nfsm_reqhead(dvp, NFSPROC_MKDIR,
NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
if (v3) {
@@ -1952,7 +1813,8 @@ nfs_mkdir(ap)
nfsm_mtofh(dvp, newvp, v3, gotvp);
if (v3)
nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
VTONFS(dvp)->n_flag |= NMODIFIED;
if (!wccflag)
VTONFS(dvp)->n_attrstamp = 0;
@@ -1985,35 +1847,31 @@ nfs_mkdir(ap)
* nfs remove directory call
*/
static int
-nfs_rmdir(ap)
- struct vop_rmdir_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
+nfs_rmdir(struct vop_rmdir_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
- register struct componentname *cnp = ap->a_cnp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- caddr_t bpos, dpos, cp2;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ u_int32_t *tl;
+ caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(dvp);
if (dvp == vp)
return (EINVAL);
nfsstats.rpccnt[NFSPROC_RMDIR]++;
- nfsm_reqhead(dvp, NFSPROC_RMDIR,
+ mreq = nfsm_reqhead(dvp, NFSPROC_RMDIR,
NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_thread, cnp->cn_cred);
if (v3)
nfsm_wcc_data(dvp, wccflag);
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
VTONFS(dvp)->n_flag |= NMODIFIED;
if (!wccflag)
VTONFS(dvp)->n_attrstamp = 0;
@@ -2031,16 +1889,11 @@ nfs_rmdir(ap)
* nfs readdir call
*/
static int
-nfs_readdir(ap)
- struct vop_readdir_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
+nfs_readdir(struct vop_readdir_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
- register struct uio *uio = ap->a_uio;
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
+ struct uio *uio = ap->a_uio;
int tresid, error;
struct vattr vattr;
@@ -2051,12 +1904,7 @@ nfs_readdir(ap)
*/
if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
(np->n_flag & NMODIFIED) == 0) {
- if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
- if (NQNFS_CKCACHABLE(vp, ND_READ)) {
- nfsstats.direofcache_hits++;
- return (0);
- }
- } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
+ if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
np->n_mtime == vattr.va_mtime.tv_sec) {
nfsstats.direofcache_hits++;
return (0);
@@ -2079,20 +1927,15 @@ nfs_readdir(ap)
* Called from below the buffer cache by nfs_doio().
*/
int
-nfs_readdirrpc(vp, uiop, cred)
- struct vnode *vp;
- register struct uio *uiop;
- struct ucred *cred;
-
+nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
{
- register int len, left;
- register struct dirent *dp = NULL;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register nfsuint64 *cookiep;
- caddr_t bpos, dpos, cp2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ int len, left;
+ struct dirent *dp = NULL;
+ u_int32_t *tl;
+ caddr_t cp;
+ nfsuint64 *cookiep;
+ caddr_t bpos, dpos;
+ struct mbuf *mreq, *mrep, *md, *mb;
nfsuint64 cookie;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
struct nfsnode *dnp = VTONFS(vp);
@@ -2122,8 +1965,10 @@ nfs_readdirrpc(vp, uiop, cred)
*/
while (more_dirs && bigenough) {
nfsstats.rpccnt[NFSPROC_READDIR]++;
- nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
+ mreq = nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
NFSX_READDIR(v3));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, v3);
if (v3) {
nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
@@ -2151,7 +1996,7 @@ nfs_readdirrpc(vp, uiop, cred)
}
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
more_dirs = fxdr_unsigned(int, *tl);
-
+
/* loop thru the dir entries, doctoring them to 4bsd form */
while (more_dirs && bigenough) {
if (v3) {
@@ -2266,20 +2111,16 @@ nfsmout:
* NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
*/
int
-nfs_readdirplusrpc(vp, uiop, cred)
- struct vnode *vp;
- register struct uio *uiop;
- struct ucred *cred;
+nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
{
- register int len, left;
- register struct dirent *dp;
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
- register struct vnode *newvp;
- register nfsuint64 *cookiep;
- caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
+ int len, left;
+ struct dirent *dp;
+ u_int32_t *tl;
+ caddr_t cp;
+ struct vnode *newvp;
+ nfsuint64 *cookiep;
+ caddr_t bpos, dpos, dpossav1, dpossav2;
+ struct mbuf *mreq, *mrep, *md, *mb, *mdsav1, *mdsav2;
struct nameidata nami, *ndp = &nami;
struct componentname *cnp = &ndp->ni_cnd;
nfsuint64 cookie;
@@ -2316,8 +2157,10 @@ nfs_readdirplusrpc(vp, uiop, cred)
*/
while (more_dirs && bigenough) {
nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
- nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
+ mreq = nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
NFSX_FH(1) + 6 * NFSX_UNSIGNED);
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, 1);
nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
*tl++ = cookie.nfsuquad[0];
@@ -2503,11 +2346,9 @@ nfsmout:
* nfs_rename() completes, but...
*/
static int
-nfs_sillyrename(dvp, vp, cnp)
- struct vnode *dvp, *vp;
- struct componentname *cnp;
+nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
{
- register struct sillyrename *sp;
+ struct sillyrename *sp;
struct nfsnode *np;
int error;
short pid;
@@ -2560,28 +2401,23 @@ bad:
* *npp != NULL --> update the file handle in the vnode
*/
static int
-nfs_lookitup(dvp, name, len, cred, td, npp)
- register struct vnode *dvp;
- const char *name;
- int len;
- struct ucred *cred;
- struct thread *td;
- struct nfsnode **npp;
+nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
+ struct thread *td, struct nfsnode **npp)
{
- register u_int32_t *tl;
- register caddr_t cp;
- register int32_t t1, t2;
+ u_int32_t *tl;
struct vnode *newvp = (struct vnode *)0;
struct nfsnode *np, *dnp = VTONFS(dvp);
- caddr_t bpos, dpos, cp2;
+ caddr_t bpos, dpos;
int error = 0, fhlen, attrflag;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+ struct mbuf *mreq, *mrep, *md, *mb;
nfsfh_t *nfhp;
int v3 = NFS_ISV3(dvp);
nfsstats.rpccnt[NFSPROC_LOOKUP]++;
- nfsm_reqhead(dvp, NFSPROC_LOOKUP,
+ mreq = nfsm_reqhead(dvp, NFSPROC_LOOKUP,
NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(dvp, v3);
nfsm_strtom(name, len, NFS_MAXNAMLEN);
nfsm_request(dvp, NFSPROC_LOOKUP, td, cred);
@@ -2593,7 +2429,7 @@ nfs_lookitup(dvp, name, len, cred, td, npp)
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);
+ 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);
@@ -2621,7 +2457,8 @@ nfs_lookitup(dvp, name, len, cred, td, npp)
} else
nfsm_loadattr(newvp, (struct vattr *)0);
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
if (npp && *npp == NULL) {
if (error) {
if (newvp) {
@@ -2640,25 +2477,21 @@ nfs_lookitup(dvp, name, len, cred, td, npp)
* Nfs Version 3 commit rpc
*/
int
-nfs_commit(vp, offset, cnt, cred, td)
- struct vnode *vp;
- u_quad_t offset;
- int cnt;
- struct ucred *cred;
- struct thread *td;
+nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
+ struct thread *td)
{
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1, t2;
- register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- caddr_t bpos, dpos, cp2;
+ u_int32_t *tl;
+ struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+ caddr_t bpos, dpos;
int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-
+ struct mbuf *mreq, *mrep, *md, *mb;
+
if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
return (0);
nfsstats.rpccnt[NFSPROC_COMMIT]++;
- nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
+ mreq = nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
+ mb = mreq;
+ bpos = mtod(mb, caddr_t);
nfsm_fhtom(vp, 1);
nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
txdr_hyper(offset, tl);
@@ -2675,7 +2508,8 @@ nfs_commit(vp, offset, cnt, cred, td)
error = NFSERR_STALEWRITEVERF;
}
}
- nfsm_reqdone;
+ m_freem(mrep);
+nfsmout:
return (error);
}
@@ -2686,10 +2520,9 @@ nfs_commit(vp, offset, cnt, cred, td)
* request.
*/
static int
-nfs_strategy(ap)
- struct vop_strategy_args *ap;
+nfs_strategy(struct vop_strategy_args *ap)
{
- register struct buf *bp = ap->a_bp;
+ struct buf *bp = ap->a_bp;
struct ucred *cr;
struct thread *td;
int error = 0;
@@ -2726,14 +2559,7 @@ nfs_strategy(ap)
*/
/* ARGSUSED */
static int
-nfs_fsync(ap)
- struct vop_fsync_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode * a_vp;
- struct ucred * a_cred;
- int a_waitfor;
- struct thread * a_td;
- } */ *ap;
+nfs_fsync(struct vop_fsync_args *ap)
{
return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_td, 1));
@@ -2745,16 +2571,12 @@ nfs_fsync(ap)
* associated with the vnode.
*/
static int
-nfs_flush(vp, cred, waitfor, td, commit)
- register struct vnode *vp;
- struct ucred *cred;
- int waitfor;
- struct thread *td;
- int commit;
+nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td,
+ int commit)
{
- register struct nfsnode *np = VTONFS(vp);
- register struct buf *bp;
- register int i;
+ struct nfsnode *np = VTONFS(vp);
+ struct buf *bp;
+ int i;
struct buf *nbp;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
@@ -2831,7 +2653,7 @@ again:
* 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
+ * 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
@@ -2915,7 +2737,7 @@ again:
/*
* Success, remove B_DELWRI ( bundirty() ).
*
- * b_dirtyoff/b_dirtyend seem to be NFS
+ * b_dirtyoff/b_dirtyend seem to be NFS
* specific. We should probably move that
* into bundirty(). XXX
*/
@@ -3013,14 +2835,7 @@ done:
* NFS advisory byte-level locks.
*/
static int
-nfs_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
+nfs_advlock(struct vop_advlock_args *ap)
{
return (nfs_dolock(ap));
@@ -3030,13 +2845,10 @@ nfs_advlock(ap)
* Print out the contents of an nfsnode.
*/
static int
-nfs_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
+nfs_print(struct vop_print_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
printf("tag VT_NFS, fileid %ld fsid 0x%x",
np->n_vattr.va_fileid, np->n_vattr.va_fsid);
@@ -3048,15 +2860,12 @@ nfs_print(ap)
/*
* This is the "real" nfs::bwrite(struct buf*).
- * B_WRITEINPROG isn't set unless the force flag is one and it
+ * B_WRITEINPROG isn't set unless the force flag is one and it
* handles the B_NEEDCOMMIT flag.
* We set B_CACHE if this is a VMIO buffer.
*/
int
-nfs_writebp(bp, force, td)
- register struct buf *bp;
- int force;
- struct thread *td;
+nfs_writebp(struct buf *bp, int force, struct thread *td)
{
int s;
int oldflags = bp->b_flags;
@@ -3111,7 +2920,7 @@ nfs_writebp(bp, force, td)
brelse(bp);
return (rtval);
- }
+ }
return (0);
}
@@ -3122,21 +2931,15 @@ nfs_writebp(bp, force, td)
* local to the client.
*/
static int
-nfsspec_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfsspec_access(struct vop_access_args *ap)
{
- register struct vattr *vap;
- register gid_t *gp;
- register struct ucred *cred = ap->a_cred;
+ struct vattr *vap;
+ gid_t *gp;
+ struct ucred *cred = ap->a_cred;
struct vnode *vp = ap->a_vp;
mode_t mode = ap->a_mode;
struct vattr vattr;
- register int i;
+ int i;
int error;
/*
@@ -3187,15 +2990,9 @@ found:
* Read wrapper for special devices.
*/
static int
-nfsspec_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+nfsspec_read(struct vop_read_args *ap)
{
- register struct nfsnode *np = VTONFS(ap->a_vp);
+ struct nfsnode *np = VTONFS(ap->a_vp);
/*
* Set access flag.
@@ -3209,15 +3006,9 @@ nfsspec_read(ap)
* Write wrapper for special devices.
*/
static int
-nfsspec_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+nfsspec_write(struct vop_write_args *ap)
{
- register struct nfsnode *np = VTONFS(ap->a_vp);
+ struct nfsnode *np = VTONFS(ap->a_vp);
/*
* Set update flag.
@@ -3233,16 +3024,10 @@ nfsspec_write(ap)
* Update the times on the nfsnode then do device close.
*/
static int
-nfsspec_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfsspec_close(struct vop_close_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
struct vattr vattr;
if (np->n_flag & (NACC | NUPD)) {
@@ -3264,15 +3049,9 @@ nfsspec_close(ap)
* Read wrapper for fifos.
*/
static int
-nfsfifo_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+nfsfifo_read(struct vop_read_args *ap)
{
- register struct nfsnode *np = VTONFS(ap->a_vp);
+ struct nfsnode *np = VTONFS(ap->a_vp);
/*
* Set access flag.
@@ -3286,15 +3065,9 @@ nfsfifo_read(ap)
* Write wrapper for fifos.
*/
static int
-nfsfifo_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+nfsfifo_write(struct vop_write_args *ap)
{
- register struct nfsnode *np = VTONFS(ap->a_vp);
+ struct nfsnode *np = VTONFS(ap->a_vp);
/*
* Set update flag.
@@ -3310,16 +3083,10 @@ nfsfifo_write(ap)
* Update the times on the nfsnode then do fifo close.
*/
static int
-nfsfifo_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+nfsfifo_close(struct vop_close_args *ap)
{
- register struct vnode *vp = ap->a_vp;
- register struct nfsnode *np = VTONFS(vp);
+ struct vnode *vp = ap->a_vp;
+ struct nfsnode *np = VTONFS(vp);
struct vattr vattr;
struct timespec ts;
diff --git a/sys/nfsclient/nfsargs.h b/sys/nfsclient/nfsargs.h
index da808f4..d53e4e0 100644
--- a/sys/nfsclient/nfsargs.h
+++ b/sys/nfsclient/nfsargs.h
@@ -37,81 +37,8 @@
* $FreeBSD$
*/
-#ifndef _NFS_NFS_H_
-#define _NFS_NFS_H_
-
-#ifdef _KERNEL
-#include "opt_nfs.h"
-#endif
-
-/*
- * Tunable constants for nfs
- */
-
-#define NFS_MAXIOVEC 34
-#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
-#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
-#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
-#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
-#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
-#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
-#define NFS_MAXREXMIT 100 /* Stop counting after this many */
-#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
-#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
-#define NFS_MAXGRPS 16 /* Max. size of groups list */
-#ifndef NFS_MINATTRTIMO
-#define NFS_MINATTRTIMO 3 /* VREG attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXATTRTIMO
-#define NFS_MAXATTRTIMO 60
-#endif
-#ifndef NFS_MINDIRATTRTIMO
-#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXDIRATTRTIMO
-#define NFS_MAXDIRATTRTIMO 60
-#endif
-#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
-#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
-#define NFS_READDIRSIZE 8192 /* Def. readdir size */
-#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
-#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
-#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
-#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
-#ifndef NFS_GATHERDELAY
-#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
-#endif
-#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
-#ifdef _KERNEL
-#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
-#endif
-
-/*
- * Oddballs
- */
-#define NMOD(a) ((a) % nfs_asyncdaemons)
-#define NFS_CMPFH(n, f, s) \
- ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
-#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
-#define NFS_SRVMAXDATA(n) \
- (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
- NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
-
-/*
- * XXX
- * The B_INVAFTERWRITE flag should be set to whatever is required by the
- * buffer cache code to say "Invalidate the block after it is written back".
- */
-#define B_INVAFTERWRITE B_NOCACHE
-
-/*
- * The IO_METASYNC flag should be implemented for local file systems.
- * (Until then, it is nothin at all.)
- */
-#ifndef IO_METASYNC
-#define IO_METASYNC 0
-#endif
+#ifndef _NFSCLIENT_NFSARGS_H_
+#define _NFSCLIENT_NFSARGS_H_
/*
* Arguments to mount NFS
@@ -133,7 +60,7 @@ struct nfs_args {
int retrans; /* times to retry send */
int maxgrouplist; /* Max. size of group list */
int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
+ int __pad1; /* was "leaseterm" */
int deadthresh; /* Retrans threshold */
char *hostname; /* server's name */
int acregmin; /* cache attrs for reg files min time */
@@ -153,11 +80,11 @@ struct nfs_args {
#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+/* 0x100 free, was NFSMNT_NQNFS */
#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+/* 0x400 free, was NFSMNT_KERB */
#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+/* 0x1000 free, was NFSMNT_LEASETERM */
#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
@@ -168,560 +95,4 @@ struct nfs_args {
#define NFSMNT_ACDIRMIN 0x00100000
#define NFSMNT_ACDIRMAX 0x00200000
-#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
-#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSSTA_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSSTA_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSSTA_DISMNT 0x00800000 /* Dismounted */
-#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
-#define NFSSTA_WANTSND 0x02000000 /* Want above */
-#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
-#define NFSSTA_WANTRCV 0x08000000 /* Want above */
-#define NFSSTA_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSSTA_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSSTA_AUTHERR 0x80000000 /* Authentication error */
-
-/*
- * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
- * should ever try and use it.
- */
-struct nfsd_args {
- int sock; /* Socket to serve */
- caddr_t name; /* Client addr for connection based sockets */
- int namelen; /* Length of name */
-};
-
-struct nfsd_srvargs {
- struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
- uid_t nsd_uid; /* Effective uid mapped to cred */
- u_int32_t nsd_haddr; /* Ip address of client */
- struct xucred nsd_cr; /* Cred. uid maps to */
- u_int nsd_authlen; /* Length of auth string (ret) */
- u_char *nsd_authstr; /* Auth string (ret) */
- u_int nsd_verflen; /* and the verfier */
- u_char *nsd_verfstr;
- struct timeval nsd_timestamp; /* timestamp from verifier */
- u_int32_t nsd_ttl; /* credential ttl (sec) */
- NFSKERBKEY_T nsd_key; /* Session key */
-};
-
-struct nfsd_cargs {
- char *ncd_dirp; /* Mount dir path */
- uid_t ncd_authuid; /* Effective uid */
- int ncd_authtype; /* Type of authenticator */
- u_int ncd_authlen; /* Length of authenticator string */
- u_char *ncd_authstr; /* Authenticator string */
- u_int ncd_verflen; /* and the verifier */
- u_char *ncd_verfstr;
- NFSKERBKEY_T ncd_key; /* Session key */
-};
-
-/*
- * XXX to allow amd to include nfs.h without nfsproto.h
- */
-#ifdef NFS_NPROCS
-/*
- * Stats structure
- */
-struct nfsstats {
- int attrcache_hits;
- int attrcache_misses;
- int lookupcache_hits;
- int lookupcache_misses;
- int direofcache_hits;
- int direofcache_misses;
- int biocache_reads;
- int read_bios;
- int read_physios;
- int biocache_writes;
- int write_bios;
- int write_physios;
- int biocache_readlinks;
- int readlink_bios;
- int biocache_readdirs;
- int readdir_bios;
- int rpccnt[NFS_NPROCS];
- int rpcretries;
- int srvrpccnt[NFS_NPROCS];
- int srvrpc_errs;
- int srv_errs;
- int rpcrequests;
- int rpctimeouts;
- int rpcunexpected;
- int rpcinvalid;
- int srvcache_inproghits;
- int srvcache_idemdonehits;
- int srvcache_nonidemdonehits;
- int srvcache_misses;
- int srvnqnfs_leases;
- int srvnqnfs_maxleases;
- int srvnqnfs_getleases;
- int srvvop_writes;
- int accesscache_hits;
- int accesscache_misses;
-};
-#endif
-
-/*
- * Flags for nfssvc() system call.
- */
-#define NFSSVC_BIOD 0x002
-#define NFSSVC_NFSD 0x004
-#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_AUTHIN 0x010
-#define NFSSVC_GOTAUTH 0x040
-#define NFSSVC_AUTHINFAIL 0x080
-#define NFSSVC_MNTD 0x100
-#define NFSSVC_LOCKDANS 0x200
-
-/*
- * fs.nfs sysctl(3) identifiers
- */
-#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
-#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
-
-#define FS_NFS_NAMES { \
- { 0, 0 }, \
- { "nfsstats", CTLTYPE_STRUCT }, \
- { "nfsprivport", CTLTYPE_INT }, \
-}
-
-#ifdef _KERNEL
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_NFSREQ);
-MALLOC_DECLARE(M_NFSDIROFF);
-MALLOC_DECLARE(M_NFSRVDESC);
-MALLOC_DECLARE(M_NFSUID);
-MALLOC_DECLARE(M_NQLEASE);
-MALLOC_DECLARE(M_NFSD);
-MALLOC_DECLARE(M_NFSBIGFH);
-MALLOC_DECLARE(M_NFSHASH);
-#endif
-
-#ifdef ZONE_INTERRUPT
-extern vm_zone_t nfsmount_zone;
-#endif
-
-extern struct callout_handle nfs_timer_handle;
-
-struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
-
-/*
- * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
- * What should be in this set is open to debate, but I believe that since
- * I/O system calls on ufs are never interrupted by signals the set should
- * be minimal. My reasoning is that many current programs that use signals
- * such as SIGALRM will not expect file I/O system calls to be interrupted
- * by them and break.
- */
-#define NFSINT_SIGMASK(set) \
- (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
- SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
- SIGISMEMBER(set, SIGQUIT))
-
-/*
- * Socket errors ignored for connectionless sockets??
- * For now, ignore them all
- */
-#define NFSIGNORE_SOERROR(s, e) \
- ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
- ((s) & PR_CONNREQUIRED) == 0)
-
-/*
- * Nfs outstanding request list element
- */
-struct nfsreq {
- TAILQ_ENTRY(nfsreq) r_chain;
- struct mbuf *r_mreq;
- struct mbuf *r_mrep;
- struct mbuf *r_md;
- caddr_t r_dpos;
- struct nfsmount *r_nmp;
- struct vnode *r_vp;
- 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 */
- u_int32_t r_procnum; /* NFS procedure number */
- int r_rtt; /* RTT for rpc */
- struct thread *r_td; /* Proc that did I/O system call */
-};
-
-/*
- * Queue head for nfsreq's
- */
-extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
-
-/* 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 */
-
-/*
- * A list of nfssvc_sock structures is maintained with all the sockets
- * that require service by the nfsd.
- * The nfsuid structs hang off of the nfssvc_sock structs in both lru
- * and uid hash lists.
- */
-#ifndef NFS_UIDHASHSIZ
-#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
-#endif
-#define NUIDHASH(sock, uid) \
- (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
-#ifndef NFS_WDELAYHASHSIZ
-#define NFS_WDELAYHASHSIZ 16 /* and with this */
-#endif
-#define NWDELAYHASH(sock, f) \
- (&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifndef NFS_MUIDHASHSIZ
-#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
-#endif
-#define NMUIDHASH(nmp, uid) \
- (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
-#define NFSNOHASH(fhsum) \
- (&nfsnodehashtbl[(fhsum) & nfsnodehash])
-
-/*
- * Network address hash list element
- */
-union nethostaddr {
- u_int32_t had_inetaddr;
- struct sockaddr *had_nam;
-};
-
-struct nfsuid {
- TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
- LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
- int nu_flag; /* Flags */
- union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
- struct ucred nu_cr; /* Cred uid mapped to */
- int nu_expire; /* Expiry time (sec) */
- struct timeval nu_timestamp; /* Kerb. timestamp */
- u_int32_t nu_nickname; /* Nickname on server */
- NFSKERBKEY_T nu_key; /* and session key */
-};
-
-#define nu_inetaddr nu_haddr.had_inetaddr
-#define nu_nam nu_haddr.had_nam
-/* Bits for nu_flag */
-#define NU_INETADDR 0x1
-#define NU_NAM 0x2
-#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
-
-struct nfsrv_rec {
- STAILQ_ENTRY(nfsrv_rec) nr_link;
- struct sockaddr *nr_address;
- struct mbuf *nr_packet;
-};
-
-struct nfssvc_sock {
- TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- TAILQ_HEAD(, nfsuid) ns_uidlruhead;
- struct file *ns_fp;
- struct socket *ns_so;
- struct sockaddr *ns_nam;
- struct mbuf *ns_raw;
- struct mbuf *ns_rawend;
- STAILQ_HEAD(, nfsrv_rec) ns_rec;
- struct mbuf *ns_frag;
- int ns_flag;
- int ns_solock;
- int ns_cc;
- int ns_reclen;
- int ns_numuids;
- u_int32_t ns_sref;
- LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
- LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
-};
-
-/* Bits for "ns_flag" */
-#define SLP_VALID 0x01
-#define SLP_DOREC 0x02
-#define SLP_NEEDQ 0x04
-#define SLP_DISCONN 0x08
-#define SLP_GETSTREAM 0x10
-#define SLP_LASTFRAG 0x20
-#define SLP_ALLFLAGS 0xff
-
-extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
-extern int nfssvc_sockhead_flag;
-#define SLP_INIT 0x01
-#define SLP_WANTINIT 0x02
-
-/*
- * One of these structures is allocated for each nfsd.
- */
-struct nfsd {
- TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
- int nfsd_flag; /* NFSD_ flags */
- struct nfssvc_sock *nfsd_slp; /* Current socket */
- int nfsd_authlen; /* Authenticator len */
- u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
- int nfsd_verflen; /* and the Verifier */
- u_char nfsd_verfstr[RPCVERF_MAXSIZ];
- struct thread *nfsd_td; /* daemon thread ptr */
- struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
-};
-
-/* Bits for "nfsd_flag" */
-#define NFSD_WAITING 0x01
-#define NFSD_REQINPROG 0x02
-#define NFSD_NEEDAUTH 0x04
-#define NFSD_AUTHFAIL 0x08
-
-/*
- * This structure is used by the server for describing each request.
- * Some fields are used only when write request gathering is performed.
- */
-struct nfsrv_descript {
- u_quad_t nd_time; /* Write deadline (usec) */
- off_t nd_off; /* Start byte offset */
- off_t nd_eoff; /* and end byte offset */
- LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
- LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
- LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
- struct mbuf *nd_mrep; /* Request mbuf list */
- struct mbuf *nd_md; /* Current dissect mbuf */
- struct mbuf *nd_mreq; /* Reply mbuf list */
- struct sockaddr *nd_nam; /* and socket addr */
- struct sockaddr *nd_nam2; /* return socket addr */
- caddr_t nd_dpos; /* Current dissect pos */
- u_int32_t nd_procnum; /* RPC # */
- int nd_stable; /* storage type */
- int nd_flag; /* nd_flag */
- int nd_len; /* Length of this write */
- int nd_repstat; /* Reply status */
- u_int32_t nd_retxid; /* Reply xid */
- u_int32_t nd_duration; /* Lease duration */
- struct timeval nd_starttime; /* Time RPC initiated */
- fhandle_t nd_fh; /* File handle */
- struct ucred nd_cr; /* Credentials */
-};
-
-/* Bits for "nd_flag" */
-#define ND_READ LEASE_READ
-#define ND_WRITE LEASE_WRITE
-#define ND_CHECK 0x04
-#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
-#define ND_NFSV3 0x08
-#define ND_NQNFS 0x10
-#define ND_KERBNICK 0x20
-#define ND_KERBFULL 0x40
-#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
-
-extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
-extern int nfsd_head_flag;
-#define NFSD_CHECKSLP 0x01
-
-/*
- * These macros compare nfsrv_descript structures.
- */
-#define NFSW_CONTIG(o, n) \
- ((o)->nd_eoff >= (n)->nd_off && \
- !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
-
-#define NFSW_SAMECRED(o, n) \
- (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
- !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
- sizeof (struct ucred)))
-
-/*
- * Defines for WebNFS
- */
-
-#define WEBNFS_ESC_CHAR '%'
-#define WEBNFS_SPECCHAR_START 0x80
-
-#define WEBNFS_NATIVE_CHAR 0x80
-/*
- * ..
- * Possibly more here in the future.
- */
-
-/*
- * Macro for converting escape characters in WebNFS pathnames.
- * Should really be in libkern.
- */
-
-#define HEXTOC(c) \
- ((c) >= 'a' ? ((c) - ('a' - 10)) : \
- ((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
-#define HEXSTRTOI(p) \
- ((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
-
-#ifdef NFS_DEBUG
-
-extern int nfs_debug;
-#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
-#define NFS_DEBUG_WG 2 /* server write gathering */
-#define NFS_DEBUG_RC 4 /* server request caching */
-
-#define NFS_DPF(cat, args) \
- do { \
- if (nfs_debug & NFS_DEBUG_##cat) printf args; \
- } while (0)
-
-#else
-
-#define NFS_DPF(cat, args)
-
-#endif
-
-u_quad_t nfs_curusec __P((void));
-int nfs_init __P((struct vfsconf *vfsp));
-int nfs_uninit __P((struct vfsconf *vfsp));
-int nfs_reply __P((struct nfsreq *));
-int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
-int nfs_send __P((struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *));
-int nfs_rephead __P((int, struct nfsrv_descript *, struct nfssvc_sock *,
- int, int, u_quad_t *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_sndlock __P((struct nfsreq *));
-void nfs_sndunlock __P((struct nfsreq *));
-int nfs_slplock __P((struct nfssvc_sock *, int));
-void nfs_slpunlock __P((struct nfssvc_sock *));
-int nfs_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-int nfs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct thread *,
- int));
-int nfs_readrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_writerpc __P((struct vnode *, struct uio *, struct ucred *, int *,
- int *));
-int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
- struct ucred *cred, struct thread *td));
-int nfs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_asyncio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_doio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_readlinkrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_sigintr __P((struct nfsmount *, struct nfsreq *, struct proc *));
-int nfs_readdirplusrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfsm_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-void nfsm_srvfattr __P((struct nfsrv_descript *, struct vattr *,
- struct nfs_fattr *));
-void nfsm_srvwcc __P((struct nfsrv_descript *, int, struct vattr *, int,
- struct vattr *, struct mbuf **, char **));
-void nfsm_srvpostopattr __P((struct nfsrv_descript *, int, struct vattr *,
- struct mbuf **, char **));
-int netaddr_match __P((int, union nethostaddr *, struct sockaddr *));
-int nfs_request __P((struct vnode *, struct mbuf *, int, struct thread *,
- struct ucred *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *, int));
-int nfs_namei __P((struct nameidata *, fhandle_t *, int,
- struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
- caddr_t *, struct vnode **, struct thread *, int, int));
-void nfsm_adj __P((struct mbuf *, int, int));
-int nfsm_mbuftouio __P((struct mbuf **, struct uio *, int, caddr_t *));
-void nfsrv_initcache __P((void));
-int nfs_getauth __P((struct nfsmount *, struct nfsreq *, struct ucred *,
- char **, int *, char *, int *, NFSKERBKEY_T));
-int nfs_getnickauth __P((struct nfsmount *, struct ucred *, char **,
- int *, char *, int));
-int nfs_savenickauth __P((struct nfsmount *, struct ucred *, int,
- NFSKERBKEY_T, struct mbuf **, char **,
- struct mbuf *));
-int nfs_adv __P((struct mbuf **, caddr_t *, int, int));
-void nfs_nhinit __P((void));
-void nfs_timer __P((void*));
-int nfsrv_dorec __P((struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **));
-int nfsrv_getcache __P((struct nfsrv_descript *, struct nfssvc_sock *,
- struct mbuf **));
-void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *));
-void nfsrv_cleancache __P((void));
-int nfs_connect __P((struct nfsmount *, struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *));
-void nfs_safedisconnect __P((struct nfsmount *));
-int nfs_getattrcache __P((struct vnode *, struct vattr *));
-int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long));
-int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *));
-int nfsm_uiotombuf __P((struct uio *, struct mbuf **, int, caddr_t *));
-void nfsrv_init __P((int));
-void nfs_clearcommit __P((struct mount *));
-int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrvw_sort __P((gid_t *, int));
-void nfsrv_setcred __P((struct ucred *, struct ucred *));
-int nfs_writebp __P((struct buf *, int, struct thread *));
-int nfsrv_object_create __P((struct vnode *));
-void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
-int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
- struct thread *, struct mbuf **));
-int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
- struct thread *td));
-
-int nfsrv3_access __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_fhtovp __P((fhandle_t *, int, struct vnode **, struct ucred *,
- struct nfssvc_sock *, struct sockaddr *, int *,
- int, int));
-int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
- struct export_args *));
-int nfs_ispublicfh __P((fhandle_t *));
-int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdir __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_setattr __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_statfs __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_symlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-void nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
-#endif /* _KERNEL */
-
#endif
diff --git a/sys/nfsclient/nfsdiskless.h b/sys/nfsclient/nfsdiskless.h
index 487e0bf..9b74d5c 100644
--- a/sys/nfsclient/nfsdiskless.h
+++ b/sys/nfsclient/nfsdiskless.h
@@ -37,9 +37,8 @@
* $FreeBSD$
*/
-
-#ifndef _NFS_NFSDISKLESS_H_
-#define _NFS_NFSDISKLESS_H_
+#ifndef _NFSCLIENT_NFSDISKLESS_H_
+#define _NFSCLIENT_NFSDISKLESS_H_
/*
* Structure that must be initialized for a diskless nfs client.
@@ -121,4 +120,10 @@ struct nfs_diskless {
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
};
+#ifdef _KERNEL
+extern struct nfsv3_diskless nfsv3_diskless;
+extern struct nfs_diskless nfs_diskless;
+extern int nfs_diskless_valid;
+#endif
+
#endif
diff --git a/sys/nfsclient/nfsm_subs.h b/sys/nfsclient/nfsm_subs.h
index d58ef15..47ca520 100644
--- a/sys/nfsclient/nfsm_subs.h
+++ b/sys/nfsclient/nfsm_subs.h
@@ -37,9 +37,12 @@
* $FreeBSD$
*/
+#ifndef _NFSCLIENT_NFSM_SUBS_H_
+#define _NFSCLIENT_NFSM_SUBS_H_
-#ifndef _NFS_NFSM_SUBS_H_
-#define _NFS_NFSM_SUBS_H_
+#include <nfs/nfs_common.h>
+
+#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_int32_t,(a))&0x7]
struct ucred;
struct vnode;
@@ -53,13 +56,11 @@ struct vnode;
/*
* First define what the actual subs. return
*/
-struct mbuf *nfsm_reqh __P((struct vnode *vp, u_long procid, int hsiz,
- caddr_t *bposp));
-struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
- int auth_type, int auth_len, char *auth_str,
- int verf_len, char *verf_str,
- struct mbuf *mrest, int mrest_len,
- struct mbuf **mbp, u_int32_t *xidp));
+struct mbuf *nfsm_reqhead(struct vnode *vp, u_long procid, int hsiz);
+struct mbuf *nfsm_rpchead(struct ucred *cr, int nmflag, int procid,
+ int auth_type, int auth_len,
+ struct mbuf *mrest, int mrest_len,
+ struct mbuf **mbp, u_int32_t *xidp);
#define M_HASCL(m) ((m)->m_flags & M_EXT)
#define NFSMINOFF(m) \
@@ -71,10 +72,6 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
else \
(m)->m_data = (m)->m_dat; \
} while (0)
-#define NFSMADV(m, s) \
- do { \
- (m)->m_data += (s); \
- } while (0)
#define NFSMSIZ(m) ((M_HASCL(m))?MCLBYTES: \
(((m)->m_flags & M_PKTHDR)?MHLEN:MLEN))
@@ -91,474 +88,130 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
* unions.
*/
-#define nfsm_build(a,c,s) \
- do { \
- if ((s) > M_TRAILINGSPACE(mb)) { \
- MGET(mb2, M_TRYWAIT, MT_DATA); \
- if ((s) > MLEN) \
- panic("build > MLEN"); \
- mb->m_next = mb2; \
- mb = mb2; \
- mb->m_len = 0; \
- bpos = mtod(mb, caddr_t); \
- } \
- (a) = (c)(bpos); \
- mb->m_len += (s); \
- bpos += (s); \
- } while (0)
-
-#define nfsm_dissect(a, c, s) \
- do { \
- t1 = mtod(md, caddr_t)+md->m_len-dpos; \
- if (t1 >= (s)) { \
- (a) = (c)(dpos); \
- dpos += (s); \
- } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } else { \
- (a) = (c)cp2; \
- } \
- } while (0)
+int nfsm_fhtom_xx(struct vnode *v, int v3, u_int32_t **tl,
+ struct mbuf **mb, caddr_t *bpos);
+int nfsm_mtofh_xx(struct vnode *d, struct vnode **v, int v3, int *f,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos);
+int nfsm_getfh_xx(nfsfh_t **f, int *s, int v3, u_int32_t **tl,
+ struct mbuf **md, caddr_t *dpos);
+void nfsm_v3attrbuild_xx(struct vattr *va, int full, u_int32_t **tl,
+ struct mbuf **mb, caddr_t *bpos);
+int nfsm_loadattr_xx(struct vnode **v, struct vattr *va, u_int32_t **tl,
+ struct mbuf **md, caddr_t *dpos);
+int nfsm_postop_attr_xx(struct vnode **v, int *f, u_int32_t **tl,
+ struct mbuf **md, caddr_t *dpos);
+int nfsm_wcc_data_xx(struct vnode **v, int *f, u_int32_t **tl,
+ struct mbuf **md, caddr_t *dpos);
+int nfsm_strtom_xx(const char *a, int s, int m, u_int32_t **tl,
+ struct mbuf **mb, caddr_t *bpos);
#define nfsm_fhtom(v, v3) \
- do { \
- if (v3) { \
- t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
- if (t2 <= M_TRAILINGSPACE(mb)) { \
- nfsm_build(tl, u_int32_t *, t2); \
- *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
- *(tl + ((t2>>2) - 2)) = 0; \
- bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
- VTONFS(v)->n_fhsize); \
- } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \
- (caddr_t)VTONFS(v)->n_fhp, \
- VTONFS(v)->n_fhsize)) != 0) { \
- error = t2; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } else { \
- nfsm_build(cp, caddr_t, NFSX_V2FH); \
- bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
- } \
- } while (0)
-
-#define nfsm_srvfhtom(f, v3) \
- do { \
- if (v3) { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH);\
- *tl++ = txdr_unsigned(NFSX_V3FH); \
- bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
- } else { \
- nfsm_build(cp, caddr_t, NFSX_V2FH); \
- bcopy((caddr_t)(f), cp, NFSX_V2FH); \
- } \
- } while (0)
-
-#define nfsm_srvpostop_fh(f) \
- do { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
- *tl++ = nfs_true; \
- *tl++ = txdr_unsigned(NFSX_V3FH); \
- bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
- } while (0)
+do { \
+ int32_t t1; \
+ t1 = nfsm_fhtom_xx((v), (v3), &tl, &mb, &bpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mreq); \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_mtofh(d, v, v3, f) \
- do { \
- struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (f) = fxdr_unsigned(int, *tl); \
- } else \
- (f) = 1; \
- if (f) { \
- nfsm_getfh(ttfhp, ttfhsize, (v3)); \
- if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
- &ttnp)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = NFSTOV(ttnp); \
- } \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (f) \
- (f) = fxdr_unsigned(int, *tl); \
- else if (fxdr_unsigned(int, *tl)) \
- nfsm_adv(NFSX_V3FATTR); \
- } \
- if (f) \
- nfsm_loadattr((v), (struct vattr *)0); \
- } while (0)
+do { \
+ int32_t t1; \
+ t1 = nfsm_mtofh_xx((d), &(v), (v3), &(f), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mrep); \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_getfh(f, s, v3) \
- do { \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
- (s) > NFSX_V3FHMAX) { \
- m_freem(mrep); \
- error = EBADRPC; \
- goto nfsmout; \
- } \
- } else \
- (s) = NFSX_V2FH; \
- nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); \
- } while (0)
+do { \
+ int32_t t1; \
+ t1 = nfsm_getfh_xx(&(f), &(s), (v3), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mrep); \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_loadattr(v, a) \
- do { \
- struct vnode *ttvp = (v); \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = ttvp; \
- } while (0)
+do { \
+ int32_t t1; \
+ t1 = nfsm_loadattr_xx(&v, a, &tl, &md, &dpos); \
+ if (t1 != 0) { \
+ error = t1; \
+ m_freem(mrep); \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_postop_attr(v, f) \
- do { \
- struct vnode *ttvp = (v); \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (((f) = fxdr_unsigned(int, *tl)) != 0) { \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
- (struct vattr *)0, 1)) != 0) { \
- error = t1; \
- (f) = 0; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = ttvp; \
- } \
- } while (0)
+do { \
+ int32_t t1; \
+ t1 = nfsm_postop_attr_xx(&v, &f, &tl, &md, &dpos); \
+ if (t1 != 0) { \
+ error = t1; \
+ m_freem(mrep); \
+ goto nfsmout; \
+ } \
+} while (0)
/* Used as (f) for nfsm_wcc_data() */
#define NFSV3_WCCRATTR 0
#define NFSV3_WCCCHK 1
#define nfsm_wcc_data(v, f) \
- do { \
- int ttattrf, ttretf = 0; \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \
- if (f) \
- ttretf = (VTONFS(v)->n_mtime == \
- fxdr_unsigned(u_int32_t, *(tl + 2))); \
- } \
- nfsm_postop_attr((v), ttattrf); \
- if (f) { \
- (f) = ttretf; \
- } else { \
- (f) = ttattrf; \
- } \
- } while (0)
+do { \
+ int32_t t1; \
+ t1 = nfsm_wcc_data_xx(&v, &f, &tl, &md, &dpos); \
+ if (t1 != 0) { \
+ error = t1; \
+ m_freem(mrep); \
+ goto nfsmout; \
+ } \
+} while (0)
/* If full is true, set all fields, otherwise just set mode and time fields */
#define nfsm_v3attrbuild(a, full) \
- do { \
- if ((a)->va_mode != (mode_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_mode); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_uid); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_gid); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_size != VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- txdr_hyper((a)->va_size, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((a)->va_atime.tv_sec != VNOVAL) { \
- if ((a)->va_atime.tv_sec != time_second) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
- txdr_nfsv3time(&(a)->va_atime, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
- } \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
- } \
- if ((a)->va_mtime.tv_sec != VNOVAL) { \
- if ((a)->va_mtime.tv_sec != time_second) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
- txdr_nfsv3time(&(a)->va_mtime, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
- } \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
- } \
- } while (0)
-
-
-#define nfsm_strsiz(s,m) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \
- m_freem(mrep); \
- error = EBADRPC; \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvstrsiz(s,m) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \
- error = EBADRPC; \
- nfsm_reply(0); \
- } \
- } while (0)
-
-#define nfsm_srvnamesiz(s) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \
- error = NFSERR_NAMETOL; \
- if ((s) <= 0) \
- error = EBADRPC; \
- if (error) \
- nfsm_reply(0); \
- } while (0)
-
-#define nfsm_mtouio(p,s) \
- do {\
- if ((s) > 0 && \
- (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_uiotom(p,s) \
- do { \
- if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \
- error = t1; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_reqhead(v,a,s) \
- do { \
- mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \
- } while (0)
-
-#define nfsm_reqdone \
- do { \
- m_freem(mrep); \
- nfsmout: \
- } while (0)
-
-#define nfsm_rndup(a) (((a)+3)&(~0x3))
+do { \
+ nfsm_v3attrbuild_xx(a, full, &tl, &mb, &bpos); \
+} while(0)
+
+#define nfsm_uiotom(p, s) \
+do { \
+ int t1; \
+ t1 = nfsm_uiotombuf((p), &mb, (s), &bpos); \
+ if (t1 != 0) { \
+ error = t1; \
+ m_freem(mreq); \
+ goto nfsmout; \
+ } \
+} while (0)
#define nfsm_request(v, t, p, c) \
- do { \
- if ((error = nfs_request((v), mreq, (t), (p), \
- (c), &mrep, &md, &dpos)) != 0) { \
- if (error & NFSERR_RETERR) \
- error &= ~NFSERR_RETERR; \
- else \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_strtom(a,s,m) \
- do {\
- if ((s) > (m)) { \
- m_freem(mreq); \
- error = ENAMETOOLONG; \
- goto nfsmout; \
- } \
- t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
- if (t2 <= M_TRAILINGSPACE(mb)) { \
- nfsm_build(tl,u_int32_t *,t2); \
- *tl++ = txdr_unsigned(s); \
- *(tl+((t2>>2)-2)) = 0; \
- bcopy((const char *)(a), (caddr_t)tl, (s)); \
- } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \
- error = t2; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvdone \
- do { \
- nfsmout: \
- return (error); \
- } while (0)
-
-#define nfsm_reply(s) \
- do { \
- nfsd->nd_repstat = error; \
- if (error && !(nfsd->nd_flag & ND_NFSV3)) \
- (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
- mrq, &mb, &bpos); \
+do { \
+ error = nfs_request((v), mreq, (t), (p), (c), &mrep, &md, &dpos); \
+ if (error != 0) { \
+ if (error & NFSERR_RETERR) \
+ error &= ~NFSERR_RETERR; \
else \
- (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
- mrq, &mb, &bpos); \
- if (mrep != NULL) { \
- m_freem(mrep); \
- mrep = NULL; \
- } \
- mreq = *mrq; \
- if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
- error == EBADRPC)) { \
- error = 0; \
goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_writereply(s, v3) \
- do { \
- nfsd->nd_repstat = error; \
- if (error && !(v3)) \
- (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
- &mreq, &mb, &bpos); \
- else \
- (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
- &mreq, &mb, &bpos); \
- } while (0)
-
-#define nfsm_adv(s) \
- do { \
- t1 = mtod(md, caddr_t)+md->m_len-dpos; \
- if (t1 >= (s)) { \
- dpos += (s); \
- } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvmtofh(f) \
- do { \
- int fhlen; \
- if (nfsd->nd_flag & ND_NFSV3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- fhlen = fxdr_unsigned(int, *tl); \
- if (fhlen != 0 && fhlen != NFSX_V3FH) { \
- error = EBADRPC; \
- nfsm_reply(0); \
- } \
- } else { \
- fhlen = NFSX_V2FH; \
- } \
- if (fhlen != 0) { \
- nfsm_dissect(tl, u_int32_t *, fhlen); \
- bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \
- } else {\
- bzero((caddr_t)(f), NFSX_V3FH); \
- } \
- } while (0)
-
-#define nfsm_clget \
- do { \
- if (bp >= be) { \
- if (mp == mb) \
- mp->m_len += bp-bpos; \
- MGET(mp, M_TRYWAIT, MT_DATA); \
- MCLGET(mp, M_TRYWAIT); \
- mp->m_len = NFSMSIZ(mp); \
- mp2->m_next = mp; \
- mp2 = mp; \
- bp = mtod(mp, caddr_t); \
- be = bp+mp->m_len; \
- } \
- tl = (u_int32_t *)bp; \
- } while (0)
-
-#define nfsm_srvfillattr(a, f) \
- do { \
- nfsm_srvfattr(nfsd, (a), (f)); \
- } while (0)
-
-#define nfsm_srvwcc_data(br, b, ar, a) \
- do { \
- nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
- } while (0)
-
-#define nfsm_srvpostop_attr(r, a) \
- do { \
- nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
- } while (0)
-
-#define nfsm_srvsattr(a) \
- do { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_mode = nfstov_mode(*tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_uid = fxdr_unsigned(uid_t, *tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_gid = fxdr_unsigned(gid_t, *tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- (a)->va_size = fxdr_hyper(tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- switch (fxdr_unsigned(int, *tl)) { \
- case NFSV3SATTRTIME_TOCLIENT: \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- fxdr_nfsv3time(tl, &(a)->va_atime); \
- break; \
- case NFSV3SATTRTIME_TOSERVER: \
- getnanotime(&(a)->va_atime); \
- break; \
- }; \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- switch (fxdr_unsigned(int, *tl)) { \
- case NFSV3SATTRTIME_TOCLIENT: \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- fxdr_nfsv3time(tl, &(a)->va_mtime); \
- break; \
- case NFSV3SATTRTIME_TOSERVER: \
- getnanotime(&(a)->va_mtime); \
- break; \
- } \
- } while (0)
+ } \
+} while (0)
+
+#define nfsm_strtom(a, s, m) \
+do { \
+ int t1; \
+ t1 = nfsm_strtom_xx((a), (s), (m), &tl, &mb, &bpos); \
+ if (t1 != 0) { \
+ error = t1; \
+ m_freem(mreq); \
+ goto nfsmout; \
+ } \
+} while (0)
#endif
diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h
index d6f8a8b..8c531cb 100644
--- a/sys/nfsclient/nfsmount.h
+++ b/sys/nfsclient/nfsmount.h
@@ -37,9 +37,8 @@
* $FreeBSD$
*/
-
-#ifndef _NFS_NFSMOUNT_H_
-#define _NFS_NFSMOUNT_H_
+#ifndef _NFSCLIENT_NFSMOUNT_H_
+#define _NFSCLIENT_NFSMOUNT_H_
/*
* Mount structure.
@@ -70,24 +69,11 @@ struct nfsmount {
int nm_wsize; /* Max size of write rpc */
int nm_readdirsize; /* Size of a readdir rpc */
int nm_readahead; /* Num. of blocks to readahead */
- int nm_leaseterm; /* Term (sec) for NQNFS lease */
int nm_acdirmin; /* Directory attr cache min lifetime */
int nm_acdirmax; /* Directory attr cache max lifetime */
int nm_acregmin; /* Reg file attr cache min lifetime */
int nm_acregmax; /* Reg file attr cache max lifetime */
- TAILQ_HEAD(timhd, nfsnode) nm_timerhead; /* Head of lease timer queue */
- struct vnode *nm_inprog; /* Vnode in prog by nqnfs_clientd() */
- uid_t nm_authuid; /* Uid for authenticator */
- int nm_authtype; /* Authenticator type */
- int nm_authlen; /* and length */
- char *nm_authstr; /* Authenticator string */
- char *nm_verfstr; /* and the verifier */
- int nm_verflen;
u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
- NFSKERBKEY_T nm_key; /* and the session key */
- int nm_numuids; /* Number of nfsuid mappings */
- TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
- LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
TAILQ_HEAD(, buf) nm_bufq; /* async io buffer queue */
short nm_bufqlen; /* number of buffers in queue */
short nm_bufqwant; /* process wants to add to the queue */
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index ba99fea..fcda484 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -37,11 +37,10 @@
* $FreeBSD$
*/
+#ifndef _NFSCLIENT_NFSNODE_H_
+#define _NFSCLIENT_NFSNODE_H_
-#ifndef _NFS_NFSNODE_H_
-#define _NFS_NFSNODE_H_
-
-#if !defined(_NFS_NFS_H_) && !defined(_KERNEL)
+#if !defined(_NFSCLIENT_NFS_H_) && !defined(_KERNEL)
#include <nfs/nfs.h>
#endif
@@ -87,7 +86,6 @@ struct nfsdmap {
*/
struct nfsnode {
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
- TAILQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
u_quad_t n_size; /* Current size of file */
u_quad_t n_brev; /* Modify rev when cached */
u_quad_t n_lrev; /* Modify rev for lease */
@@ -135,9 +133,7 @@ struct nfsnode {
#define NFLUSHINPROG 0x0002 /* Avoid multiple calls to vinvalbuf() */
#define NMODIFIED 0x0004 /* Might have a modified buffer in bio */
#define NWRITEERR 0x0008 /* Flag write errors so close will know */
-#define NQNFSNONCACHE 0x0020 /* Non-cachable lease */
-#define NQNFSWRITE 0x0040 /* Write lease */
-#define NQNFSEVICTED 0x0080 /* Has been evicted */
+/* 0x20, 0x40, 0x80 free */
#define NACC 0x0100 /* Special file accessed */
#define NUPD 0x0200 /* Special file updated */
#define NCHG 0x0400 /* Special file times changed */
@@ -169,17 +165,18 @@ extern struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
* should not be obtained while other locks are being held.
*/
-static __inline
-int
+static __inline int
nfs_rslock(struct nfsnode *np, struct thread *td)
{
- return(lockmgr(&np->n_rslock, LK_EXCLUSIVE | LK_CANRECURSE | LK_SLEEPFAIL, NULL, td));
+
+ return(lockmgr(&np->n_rslock,
+ LK_EXCLUSIVE | LK_CANRECURSE | LK_SLEEPFAIL, NULL, td));
}
-static __inline
-void
+static __inline void
nfs_rsunlock(struct nfsnode *np, struct thread *td)
{
+
(void)lockmgr(&np->n_rslock, LK_RELEASE, NULL, td);
}
@@ -190,20 +187,17 @@ extern vop_t **spec_nfsv2nodeop_p;
/*
* Prototypes for NFS vnode operations
*/
-int nfs_getpages __P((struct vop_getpages_args *));
-int nfs_putpages __P((struct vop_putpages_args *));
-int nfs_write __P((struct vop_write_args *));
-int nqnfs_vop_lease_check __P((struct vop_lease_args *));
-int nfs_inactive __P((struct vop_inactive_args *));
-int nfs_reclaim __P((struct vop_reclaim_args *));
+int nfs_getpages(struct vop_getpages_args *);
+int nfs_putpages(struct vop_putpages_args *);
+int nfs_write(struct vop_write_args *);
+int nfs_inactive(struct vop_inactive_args *);
+int nfs_reclaim(struct vop_reclaim_args *);
/* other stuff */
-int nfs_removeit __P((struct sillyrename *));
-int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
-nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
-void nfs_invaldir __P((struct vnode *));
-
-#define nqnfs_lease_updatetime nfs_lease_updatetime
+int nfs_removeit(struct sillyrename *);
+int nfs_nget(struct mount *, nfsfh_t *, int, struct nfsnode **);
+nfsuint64 *nfs_getcookie(struct nfsnode *, off_t, int);
+void nfs_invaldir(struct vnode *);
#endif /* _KERNEL */
diff --git a/sys/nfsclient/nfsstats.h b/sys/nfsclient/nfsstats.h
index da808f4..03063e6 100644
--- a/sys/nfsclient/nfsstats.h
+++ b/sys/nfsclient/nfsstats.h
@@ -37,192 +37,10 @@
* $FreeBSD$
*/
-#ifndef _NFS_NFS_H_
-#define _NFS_NFS_H_
-
-#ifdef _KERNEL
-#include "opt_nfs.h"
-#endif
+#ifndef _NFSCLIENT_NFSSTATS_H_
+#define _NFSCLIENT_NFSSTATS_H_
/*
- * Tunable constants for nfs
- */
-
-#define NFS_MAXIOVEC 34
-#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
-#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
-#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
-#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
-#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
-#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
-#define NFS_MAXREXMIT 100 /* Stop counting after this many */
-#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
-#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
-#define NFS_MAXGRPS 16 /* Max. size of groups list */
-#ifndef NFS_MINATTRTIMO
-#define NFS_MINATTRTIMO 3 /* VREG attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXATTRTIMO
-#define NFS_MAXATTRTIMO 60
-#endif
-#ifndef NFS_MINDIRATTRTIMO
-#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXDIRATTRTIMO
-#define NFS_MAXDIRATTRTIMO 60
-#endif
-#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
-#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
-#define NFS_READDIRSIZE 8192 /* Def. readdir size */
-#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
-#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
-#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
-#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
-#ifndef NFS_GATHERDELAY
-#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
-#endif
-#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
-#ifdef _KERNEL
-#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
-#endif
-
-/*
- * Oddballs
- */
-#define NMOD(a) ((a) % nfs_asyncdaemons)
-#define NFS_CMPFH(n, f, s) \
- ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
-#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
-#define NFS_SRVMAXDATA(n) \
- (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
- NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
-
-/*
- * XXX
- * The B_INVAFTERWRITE flag should be set to whatever is required by the
- * buffer cache code to say "Invalidate the block after it is written back".
- */
-#define B_INVAFTERWRITE B_NOCACHE
-
-/*
- * The IO_METASYNC flag should be implemented for local file systems.
- * (Until then, it is nothin at all.)
- */
-#ifndef IO_METASYNC
-#define IO_METASYNC 0
-#endif
-
-/*
- * Arguments to mount NFS
- */
-#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
-struct nfs_args {
- int version; /* args structure version number */
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
- int acregmin; /* cache attrs for reg files min time */
- int acregmax; /* cache attrs for reg files max time */
- int acdirmin; /* cache attrs for dirs min time */
- int acdirmax; /* cache attrs for dirs max time */
-};
-
-/*
- * NFS mount option flags
- */
-#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
-#define NFSMNT_WSIZE 0x00000002 /* set write size */
-#define NFSMNT_RSIZE 0x00000004 /* set read size */
-#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
-#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
-#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
-#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
-#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
-#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
-#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
-#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
-#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
-#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
-#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
-#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
-#define NFSMNT_ACREGMIN 0x00040000
-#define NFSMNT_ACREGMAX 0x00080000
-#define NFSMNT_ACDIRMIN 0x00100000
-#define NFSMNT_ACDIRMAX 0x00200000
-
-#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
-#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSSTA_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSSTA_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSSTA_DISMNT 0x00800000 /* Dismounted */
-#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
-#define NFSSTA_WANTSND 0x02000000 /* Want above */
-#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
-#define NFSSTA_WANTRCV 0x08000000 /* Want above */
-#define NFSSTA_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSSTA_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSSTA_AUTHERR 0x80000000 /* Authentication error */
-
-/*
- * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
- * should ever try and use it.
- */
-struct nfsd_args {
- int sock; /* Socket to serve */
- caddr_t name; /* Client addr for connection based sockets */
- int namelen; /* Length of name */
-};
-
-struct nfsd_srvargs {
- struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
- uid_t nsd_uid; /* Effective uid mapped to cred */
- u_int32_t nsd_haddr; /* Ip address of client */
- struct xucred nsd_cr; /* Cred. uid maps to */
- u_int nsd_authlen; /* Length of auth string (ret) */
- u_char *nsd_authstr; /* Auth string (ret) */
- u_int nsd_verflen; /* and the verfier */
- u_char *nsd_verfstr;
- struct timeval nsd_timestamp; /* timestamp from verifier */
- u_int32_t nsd_ttl; /* credential ttl (sec) */
- NFSKERBKEY_T nsd_key; /* Session key */
-};
-
-struct nfsd_cargs {
- char *ncd_dirp; /* Mount dir path */
- uid_t ncd_authuid; /* Effective uid */
- int ncd_authtype; /* Type of authenticator */
- u_int ncd_authlen; /* Length of authenticator string */
- u_char *ncd_authstr; /* Authenticator string */
- u_int ncd_verflen; /* and the verifier */
- u_char *ncd_verfstr;
- NFSKERBKEY_T ncd_key; /* Session key */
-};
-
-/*
- * XXX to allow amd to include nfs.h without nfsproto.h
- */
-#ifdef NFS_NPROCS
-/*
* Stats structure
*/
struct nfsstats {
@@ -232,6 +50,8 @@ struct nfsstats {
int lookupcache_misses;
int direofcache_hits;
int direofcache_misses;
+ int accesscache_hits;
+ int accesscache_misses;
int biocache_reads;
int read_bios;
int read_physios;
@@ -242,486 +62,12 @@ struct nfsstats {
int readlink_bios;
int biocache_readdirs;
int readdir_bios;
- int rpccnt[NFS_NPROCS];
int rpcretries;
- int srvrpccnt[NFS_NPROCS];
- int srvrpc_errs;
- int srv_errs;
int rpcrequests;
int rpctimeouts;
int rpcunexpected;
int rpcinvalid;
- int srvcache_inproghits;
- int srvcache_idemdonehits;
- int srvcache_nonidemdonehits;
- int srvcache_misses;
- int srvnqnfs_leases;
- int srvnqnfs_maxleases;
- int srvnqnfs_getleases;
- int srvvop_writes;
- int accesscache_hits;
- int accesscache_misses;
-};
-#endif
-
-/*
- * Flags for nfssvc() system call.
- */
-#define NFSSVC_BIOD 0x002
-#define NFSSVC_NFSD 0x004
-#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_AUTHIN 0x010
-#define NFSSVC_GOTAUTH 0x040
-#define NFSSVC_AUTHINFAIL 0x080
-#define NFSSVC_MNTD 0x100
-#define NFSSVC_LOCKDANS 0x200
-
-/*
- * fs.nfs sysctl(3) identifiers
- */
-#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
-#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
-
-#define FS_NFS_NAMES { \
- { 0, 0 }, \
- { "nfsstats", CTLTYPE_STRUCT }, \
- { "nfsprivport", CTLTYPE_INT }, \
-}
-
-#ifdef _KERNEL
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_NFSREQ);
-MALLOC_DECLARE(M_NFSDIROFF);
-MALLOC_DECLARE(M_NFSRVDESC);
-MALLOC_DECLARE(M_NFSUID);
-MALLOC_DECLARE(M_NQLEASE);
-MALLOC_DECLARE(M_NFSD);
-MALLOC_DECLARE(M_NFSBIGFH);
-MALLOC_DECLARE(M_NFSHASH);
-#endif
-
-#ifdef ZONE_INTERRUPT
-extern vm_zone_t nfsmount_zone;
-#endif
-
-extern struct callout_handle nfs_timer_handle;
-
-struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
-
-/*
- * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
- * What should be in this set is open to debate, but I believe that since
- * I/O system calls on ufs are never interrupted by signals the set should
- * be minimal. My reasoning is that many current programs that use signals
- * such as SIGALRM will not expect file I/O system calls to be interrupted
- * by them and break.
- */
-#define NFSINT_SIGMASK(set) \
- (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
- SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
- SIGISMEMBER(set, SIGQUIT))
-
-/*
- * Socket errors ignored for connectionless sockets??
- * For now, ignore them all
- */
-#define NFSIGNORE_SOERROR(s, e) \
- ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
- ((s) & PR_CONNREQUIRED) == 0)
-
-/*
- * Nfs outstanding request list element
- */
-struct nfsreq {
- TAILQ_ENTRY(nfsreq) r_chain;
- struct mbuf *r_mreq;
- struct mbuf *r_mrep;
- struct mbuf *r_md;
- caddr_t r_dpos;
- struct nfsmount *r_nmp;
- struct vnode *r_vp;
- 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 */
- u_int32_t r_procnum; /* NFS procedure number */
- int r_rtt; /* RTT for rpc */
- struct thread *r_td; /* Proc that did I/O system call */
-};
-
-/*
- * Queue head for nfsreq's
- */
-extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
-
-/* 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 */
-
-/*
- * A list of nfssvc_sock structures is maintained with all the sockets
- * that require service by the nfsd.
- * The nfsuid structs hang off of the nfssvc_sock structs in both lru
- * and uid hash lists.
- */
-#ifndef NFS_UIDHASHSIZ
-#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
-#endif
-#define NUIDHASH(sock, uid) \
- (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
-#ifndef NFS_WDELAYHASHSIZ
-#define NFS_WDELAYHASHSIZ 16 /* and with this */
-#endif
-#define NWDELAYHASH(sock, f) \
- (&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifndef NFS_MUIDHASHSIZ
-#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
-#endif
-#define NMUIDHASH(nmp, uid) \
- (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
-#define NFSNOHASH(fhsum) \
- (&nfsnodehashtbl[(fhsum) & nfsnodehash])
-
-/*
- * Network address hash list element
- */
-union nethostaddr {
- u_int32_t had_inetaddr;
- struct sockaddr *had_nam;
-};
-
-struct nfsuid {
- TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
- LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
- int nu_flag; /* Flags */
- union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
- struct ucred nu_cr; /* Cred uid mapped to */
- int nu_expire; /* Expiry time (sec) */
- struct timeval nu_timestamp; /* Kerb. timestamp */
- u_int32_t nu_nickname; /* Nickname on server */
- NFSKERBKEY_T nu_key; /* and session key */
-};
-
-#define nu_inetaddr nu_haddr.had_inetaddr
-#define nu_nam nu_haddr.had_nam
-/* Bits for nu_flag */
-#define NU_INETADDR 0x1
-#define NU_NAM 0x2
-#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
-
-struct nfsrv_rec {
- STAILQ_ENTRY(nfsrv_rec) nr_link;
- struct sockaddr *nr_address;
- struct mbuf *nr_packet;
-};
-
-struct nfssvc_sock {
- TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- TAILQ_HEAD(, nfsuid) ns_uidlruhead;
- struct file *ns_fp;
- struct socket *ns_so;
- struct sockaddr *ns_nam;
- struct mbuf *ns_raw;
- struct mbuf *ns_rawend;
- STAILQ_HEAD(, nfsrv_rec) ns_rec;
- struct mbuf *ns_frag;
- int ns_flag;
- int ns_solock;
- int ns_cc;
- int ns_reclen;
- int ns_numuids;
- u_int32_t ns_sref;
- LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
- LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
-};
-
-/* Bits for "ns_flag" */
-#define SLP_VALID 0x01
-#define SLP_DOREC 0x02
-#define SLP_NEEDQ 0x04
-#define SLP_DISCONN 0x08
-#define SLP_GETSTREAM 0x10
-#define SLP_LASTFRAG 0x20
-#define SLP_ALLFLAGS 0xff
-
-extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
-extern int nfssvc_sockhead_flag;
-#define SLP_INIT 0x01
-#define SLP_WANTINIT 0x02
-
-/*
- * One of these structures is allocated for each nfsd.
- */
-struct nfsd {
- TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
- int nfsd_flag; /* NFSD_ flags */
- struct nfssvc_sock *nfsd_slp; /* Current socket */
- int nfsd_authlen; /* Authenticator len */
- u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
- int nfsd_verflen; /* and the Verifier */
- u_char nfsd_verfstr[RPCVERF_MAXSIZ];
- struct thread *nfsd_td; /* daemon thread ptr */
- struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
-};
-
-/* Bits for "nfsd_flag" */
-#define NFSD_WAITING 0x01
-#define NFSD_REQINPROG 0x02
-#define NFSD_NEEDAUTH 0x04
-#define NFSD_AUTHFAIL 0x08
-
-/*
- * This structure is used by the server for describing each request.
- * Some fields are used only when write request gathering is performed.
- */
-struct nfsrv_descript {
- u_quad_t nd_time; /* Write deadline (usec) */
- off_t nd_off; /* Start byte offset */
- off_t nd_eoff; /* and end byte offset */
- LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
- LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
- LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
- struct mbuf *nd_mrep; /* Request mbuf list */
- struct mbuf *nd_md; /* Current dissect mbuf */
- struct mbuf *nd_mreq; /* Reply mbuf list */
- struct sockaddr *nd_nam; /* and socket addr */
- struct sockaddr *nd_nam2; /* return socket addr */
- caddr_t nd_dpos; /* Current dissect pos */
- u_int32_t nd_procnum; /* RPC # */
- int nd_stable; /* storage type */
- int nd_flag; /* nd_flag */
- int nd_len; /* Length of this write */
- int nd_repstat; /* Reply status */
- u_int32_t nd_retxid; /* Reply xid */
- u_int32_t nd_duration; /* Lease duration */
- struct timeval nd_starttime; /* Time RPC initiated */
- fhandle_t nd_fh; /* File handle */
- struct ucred nd_cr; /* Credentials */
+ int rpccnt[NFS_NPROCS];
};
-/* Bits for "nd_flag" */
-#define ND_READ LEASE_READ
-#define ND_WRITE LEASE_WRITE
-#define ND_CHECK 0x04
-#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
-#define ND_NFSV3 0x08
-#define ND_NQNFS 0x10
-#define ND_KERBNICK 0x20
-#define ND_KERBFULL 0x40
-#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
-
-extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
-extern int nfsd_head_flag;
-#define NFSD_CHECKSLP 0x01
-
-/*
- * These macros compare nfsrv_descript structures.
- */
-#define NFSW_CONTIG(o, n) \
- ((o)->nd_eoff >= (n)->nd_off && \
- !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
-
-#define NFSW_SAMECRED(o, n) \
- (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
- !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
- sizeof (struct ucred)))
-
-/*
- * Defines for WebNFS
- */
-
-#define WEBNFS_ESC_CHAR '%'
-#define WEBNFS_SPECCHAR_START 0x80
-
-#define WEBNFS_NATIVE_CHAR 0x80
-/*
- * ..
- * Possibly more here in the future.
- */
-
-/*
- * Macro for converting escape characters in WebNFS pathnames.
- * Should really be in libkern.
- */
-
-#define HEXTOC(c) \
- ((c) >= 'a' ? ((c) - ('a' - 10)) : \
- ((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
-#define HEXSTRTOI(p) \
- ((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
-
-#ifdef NFS_DEBUG
-
-extern int nfs_debug;
-#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
-#define NFS_DEBUG_WG 2 /* server write gathering */
-#define NFS_DEBUG_RC 4 /* server request caching */
-
-#define NFS_DPF(cat, args) \
- do { \
- if (nfs_debug & NFS_DEBUG_##cat) printf args; \
- } while (0)
-
-#else
-
-#define NFS_DPF(cat, args)
-
-#endif
-
-u_quad_t nfs_curusec __P((void));
-int nfs_init __P((struct vfsconf *vfsp));
-int nfs_uninit __P((struct vfsconf *vfsp));
-int nfs_reply __P((struct nfsreq *));
-int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
-int nfs_send __P((struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *));
-int nfs_rephead __P((int, struct nfsrv_descript *, struct nfssvc_sock *,
- int, int, u_quad_t *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_sndlock __P((struct nfsreq *));
-void nfs_sndunlock __P((struct nfsreq *));
-int nfs_slplock __P((struct nfssvc_sock *, int));
-void nfs_slpunlock __P((struct nfssvc_sock *));
-int nfs_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-int nfs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct thread *,
- int));
-int nfs_readrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_writerpc __P((struct vnode *, struct uio *, struct ucred *, int *,
- int *));
-int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
- struct ucred *cred, struct thread *td));
-int nfs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_asyncio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_doio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_readlinkrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_sigintr __P((struct nfsmount *, struct nfsreq *, struct proc *));
-int nfs_readdirplusrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfsm_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-void nfsm_srvfattr __P((struct nfsrv_descript *, struct vattr *,
- struct nfs_fattr *));
-void nfsm_srvwcc __P((struct nfsrv_descript *, int, struct vattr *, int,
- struct vattr *, struct mbuf **, char **));
-void nfsm_srvpostopattr __P((struct nfsrv_descript *, int, struct vattr *,
- struct mbuf **, char **));
-int netaddr_match __P((int, union nethostaddr *, struct sockaddr *));
-int nfs_request __P((struct vnode *, struct mbuf *, int, struct thread *,
- struct ucred *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *, int));
-int nfs_namei __P((struct nameidata *, fhandle_t *, int,
- struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
- caddr_t *, struct vnode **, struct thread *, int, int));
-void nfsm_adj __P((struct mbuf *, int, int));
-int nfsm_mbuftouio __P((struct mbuf **, struct uio *, int, caddr_t *));
-void nfsrv_initcache __P((void));
-int nfs_getauth __P((struct nfsmount *, struct nfsreq *, struct ucred *,
- char **, int *, char *, int *, NFSKERBKEY_T));
-int nfs_getnickauth __P((struct nfsmount *, struct ucred *, char **,
- int *, char *, int));
-int nfs_savenickauth __P((struct nfsmount *, struct ucred *, int,
- NFSKERBKEY_T, struct mbuf **, char **,
- struct mbuf *));
-int nfs_adv __P((struct mbuf **, caddr_t *, int, int));
-void nfs_nhinit __P((void));
-void nfs_timer __P((void*));
-int nfsrv_dorec __P((struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **));
-int nfsrv_getcache __P((struct nfsrv_descript *, struct nfssvc_sock *,
- struct mbuf **));
-void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *));
-void nfsrv_cleancache __P((void));
-int nfs_connect __P((struct nfsmount *, struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *));
-void nfs_safedisconnect __P((struct nfsmount *));
-int nfs_getattrcache __P((struct vnode *, struct vattr *));
-int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long));
-int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *));
-int nfsm_uiotombuf __P((struct uio *, struct mbuf **, int, caddr_t *));
-void nfsrv_init __P((int));
-void nfs_clearcommit __P((struct mount *));
-int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrvw_sort __P((gid_t *, int));
-void nfsrv_setcred __P((struct ucred *, struct ucred *));
-int nfs_writebp __P((struct buf *, int, struct thread *));
-int nfsrv_object_create __P((struct vnode *));
-void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
-int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
- struct thread *, struct mbuf **));
-int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
- struct thread *td));
-
-int nfsrv3_access __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_fhtovp __P((fhandle_t *, int, struct vnode **, struct ucred *,
- struct nfssvc_sock *, struct sockaddr *, int *,
- int, int));
-int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
- struct export_args *));
-int nfs_ispublicfh __P((fhandle_t *));
-int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdir __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_setattr __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_statfs __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_symlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-void nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
-#endif /* _KERNEL */
-
#endif
diff --git a/sys/nfsclient/nlminfo.h b/sys/nfsclient/nlminfo.h
index 79c6e17..3dc55b4 100644
--- a/sys/nfsclient/nlminfo.h
+++ b/sys/nfsclient/nlminfo.h
@@ -41,5 +41,4 @@ struct nlminfo {
struct timeval pid_start; /* process starting time */
};
-extern void nlminfo_release __P((struct proc *p));
-
+extern void nlminfo_release(struct proc *p);
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index da808f4..93e56eb 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -37,8 +37,8 @@
* $FreeBSD$
*/
-#ifndef _NFS_NFS_H_
-#define _NFS_NFS_H_
+#ifndef _NFSSERVER_NFS_H_
+#define _NFSSERVER_NFS_H_
#ifdef _KERNEL
#include "opt_nfs.h"
@@ -48,41 +48,16 @@
* Tunable constants for nfs
*/
-#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
-#define NFS_MAXREXMIT 100 /* Stop counting after this many */
-#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
-#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
-#define NFS_MAXGRPS 16 /* Max. size of groups list */
-#ifndef NFS_MINATTRTIMO
-#define NFS_MINATTRTIMO 3 /* VREG attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXATTRTIMO
-#define NFS_MAXATTRTIMO 60
-#endif
-#ifndef NFS_MINDIRATTRTIMO
-#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXDIRATTRTIMO
-#define NFS_MAXDIRATTRTIMO 60
-#endif
-#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
-#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
-#define NFS_READDIRSIZE 8192 /* Def. readdir size */
-#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
-#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
-#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
-#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
#ifdef _KERNEL
#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
#endif
@@ -90,10 +65,6 @@
/*
* Oddballs
*/
-#define NMOD(a) ((a) % nfs_asyncdaemons)
-#define NFS_CMPFH(n, f, s) \
- ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
-#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
@@ -113,75 +84,10 @@
#define IO_METASYNC 0
#endif
-/*
- * Arguments to mount NFS
- */
-#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
-struct nfs_args {
- int version; /* args structure version number */
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
- int acregmin; /* cache attrs for reg files min time */
- int acregmax; /* cache attrs for reg files max time */
- int acdirmin; /* cache attrs for dirs min time */
- int acdirmax; /* cache attrs for dirs max time */
-};
-/*
- * NFS mount option flags
- */
-#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
-#define NFSMNT_WSIZE 0x00000002 /* set write size */
-#define NFSMNT_RSIZE 0x00000004 /* set read size */
-#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
-#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
-#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
-#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
-#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
-#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
-#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
-#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
-#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
-#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
-#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
-#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
-#define NFSMNT_ACREGMIN 0x00040000
-#define NFSMNT_ACREGMAX 0x00080000
-#define NFSMNT_ACDIRMIN 0x00100000
-#define NFSMNT_ACDIRMAX 0x00200000
-
-#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
-#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSSTA_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSSTA_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSSTA_DISMNT 0x00800000 /* Dismounted */
-#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
-#define NFSSTA_WANTSND 0x02000000 /* Want above */
-#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
-#define NFSSTA_WANTRCV 0x08000000 /* Want above */
-#define NFSSTA_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSSTA_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSSTA_AUTHERR 0x80000000 /* Authentication error */
+/* NFS state flags XXX -Wunused */
+#define NFSRV_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSRV_WANTSND 0x02000000 /* Want above */
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
@@ -204,7 +110,6 @@ struct nfsd_srvargs {
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_int32_t nsd_ttl; /* credential ttl (sec) */
- NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@@ -215,180 +120,69 @@ struct nfsd_cargs {
u_char *ncd_authstr; /* Authenticator string */
u_int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
- NFSKERBKEY_T ncd_key; /* Session key */
};
/*
* XXX to allow amd to include nfs.h without nfsproto.h
*/
#ifdef NFS_NPROCS
-/*
- * Stats structure
- */
-struct nfsstats {
- int attrcache_hits;
- int attrcache_misses;
- int lookupcache_hits;
- int lookupcache_misses;
- int direofcache_hits;
- int direofcache_misses;
- int biocache_reads;
- int read_bios;
- int read_physios;
- int biocache_writes;
- int write_bios;
- int write_physios;
- int biocache_readlinks;
- int readlink_bios;
- int biocache_readdirs;
- int readdir_bios;
- int rpccnt[NFS_NPROCS];
- int rpcretries;
- int srvrpccnt[NFS_NPROCS];
- int srvrpc_errs;
- int srv_errs;
- int rpcrequests;
- int rpctimeouts;
- int rpcunexpected;
- int rpcinvalid;
- int srvcache_inproghits;
- int srvcache_idemdonehits;
- int srvcache_nonidemdonehits;
- int srvcache_misses;
- int srvnqnfs_leases;
- int srvnqnfs_maxleases;
- int srvnqnfs_getleases;
- int srvvop_writes;
- int accesscache_hits;
- int accesscache_misses;
-};
+#include <nfsserver/nfsrvstats.h>
#endif
/*
* Flags for nfssvc() system call.
*/
-#define NFSSVC_BIOD 0x002
#define NFSSVC_NFSD 0x004
#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_AUTHIN 0x010
-#define NFSSVC_GOTAUTH 0x040
-#define NFSSVC_AUTHINFAIL 0x080
-#define NFSSVC_MNTD 0x100
-#define NFSSVC_LOCKDANS 0x200
/*
- * fs.nfs sysctl(3) identifiers
+ * vfs.nfsrv sysctl(3) identifiers
*/
-#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
+#define NFS_NFSRVSTATS 1 /* struct: struct nfsrvstats */
#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
-#define FS_NFS_NAMES { \
- { 0, 0 }, \
- { "nfsstats", CTLTYPE_STRUCT }, \
- { "nfsprivport", CTLTYPE_INT }, \
-}
-
#ifdef _KERNEL
#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_NFSREQ);
-MALLOC_DECLARE(M_NFSDIROFF);
MALLOC_DECLARE(M_NFSRVDESC);
-MALLOC_DECLARE(M_NFSUID);
-MALLOC_DECLARE(M_NQLEASE);
MALLOC_DECLARE(M_NFSD);
-MALLOC_DECLARE(M_NFSBIGFH);
-MALLOC_DECLARE(M_NFSHASH);
#endif
-#ifdef ZONE_INTERRUPT
-extern vm_zone_t nfsmount_zone;
-#endif
+/* Forward declarations */
+struct nfssvc_sock;
+struct nfsrv_descript;
+struct uio;
+struct vattr;
+struct nameidata;
-extern struct callout_handle nfs_timer_handle;
+extern struct callout_handle nfsrv_timer_handle;
+extern struct nfsrvstats nfsrvstats;
-struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
+extern int nfs_ticks;
+extern int nfsrvw_procrastinate;
+extern int nfsrvw_procrastinate_v3;
-/*
- * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
- * What should be in this set is open to debate, but I believe that since
- * I/O system calls on ufs are never interrupted by signals the set should
- * be minimal. My reasoning is that many current programs that use signals
- * such as SIGALRM will not expect file I/O system calls to be interrupted
- * by them and break.
- */
-#define NFSINT_SIGMASK(set) \
- (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
- SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
- SIGISMEMBER(set, SIGQUIT))
-
-/*
- * Socket errors ignored for connectionless sockets??
- * For now, ignore them all
- */
-#define NFSIGNORE_SOERROR(s, e) \
- ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
- ((s) & PR_CONNREQUIRED) == 0)
-
-/*
- * Nfs outstanding request list element
- */
-struct nfsreq {
- TAILQ_ENTRY(nfsreq) r_chain;
- struct mbuf *r_mreq;
- struct mbuf *r_mrep;
- struct mbuf *r_md;
- caddr_t r_dpos;
- struct nfsmount *r_nmp;
- struct vnode *r_vp;
- 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 */
- u_int32_t r_procnum; /* NFS procedure number */
- int r_rtt; /* RTT for rpc */
- struct thread *r_td; /* Proc that did I/O system call */
-};
+/* Various values converted to XDR form. */
+extern u_int32_t nfs_false, nfs_true, nfs_xdrneg1, nfs_prog;
+extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers;
+extern u_int32_t rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr;
-/*
- * Queue head for nfsreq's
- */
-extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
-
-/* 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 */
+/* Procedure table data */
+extern int nfsrvv2_procid[NFS_NPROCS];
+extern int nfsv3_procid[NFS_NPROCS];
+extern int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
+ struct nfssvc_sock *slp, struct thread *td,
+ struct mbuf **mreqp);
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
- * The nfsuid structs hang off of the nfssvc_sock structs in both lru
- * and uid hash lists.
*/
-#ifndef NFS_UIDHASHSIZ
-#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
-#endif
-#define NUIDHASH(sock, uid) \
- (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifndef NFS_MUIDHASHSIZ
-#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
-#endif
-#define NMUIDHASH(nmp, uid) \
- (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
-#define NFSNOHASH(fhsum) \
- (&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@@ -398,18 +192,6 @@ union nethostaddr {
struct sockaddr *had_nam;
};
-struct nfsuid {
- TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
- LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
- int nu_flag; /* Flags */
- union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
- struct ucred nu_cr; /* Cred uid mapped to */
- int nu_expire; /* Expiry time (sec) */
- struct timeval nu_timestamp; /* Kerb. timestamp */
- u_int32_t nu_nickname; /* Nickname on server */
- NFSKERBKEY_T nu_key; /* and session key */
-};
-
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
@@ -425,7 +207,6 @@ struct nfsrv_rec {
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- TAILQ_HEAD(, nfsuid) ns_uidlruhead;
struct file *ns_fp;
struct socket *ns_so;
struct sockaddr *ns_nam;
@@ -437,10 +218,8 @@ struct nfssvc_sock {
int ns_solock;
int ns_cc;
int ns_reclen;
- int ns_numuids;
u_int32_t ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
@@ -476,8 +255,6 @@ struct nfsd {
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
-#define NFSD_NEEDAUTH 0x04
-#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
@@ -488,8 +265,8 @@ struct nfsrv_descript {
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
- LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
- LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
+ LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
+ LIST_HEAD(, nfsrv_descript) nd_coalesce;/* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
@@ -502,22 +279,13 @@ struct nfsrv_descript {
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_int32_t nd_retxid; /* Reply xid */
- u_int32_t nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
-#define ND_READ LEASE_READ
-#define ND_WRITE LEASE_WRITE
-#define ND_CHECK 0x04
-#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
-#define ND_NQNFS 0x10
-#define ND_KERBNICK 0x20
-#define ND_KERBFULL 0x40
-#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
extern int nfsd_head_flag;
@@ -531,8 +299,7 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
- (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
- !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
+ (!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
/*
@@ -577,151 +344,94 @@ extern int nfs_debug;
#endif
-u_quad_t nfs_curusec __P((void));
-int nfs_init __P((struct vfsconf *vfsp));
-int nfs_uninit __P((struct vfsconf *vfsp));
-int nfs_reply __P((struct nfsreq *));
-int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
-int nfs_send __P((struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *));
-int nfs_rephead __P((int, struct nfsrv_descript *, struct nfssvc_sock *,
- int, int, u_quad_t *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_sndlock __P((struct nfsreq *));
-void nfs_sndunlock __P((struct nfsreq *));
-int nfs_slplock __P((struct nfssvc_sock *, int));
-void nfs_slpunlock __P((struct nfssvc_sock *));
-int nfs_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-int nfs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct thread *,
- int));
-int nfs_readrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_writerpc __P((struct vnode *, struct uio *, struct ucred *, int *,
- int *));
-int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
- struct ucred *cred, struct thread *td));
-int nfs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_asyncio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_doio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_readlinkrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_sigintr __P((struct nfsmount *, struct nfsreq *, struct proc *));
-int nfs_readdirplusrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfsm_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-void nfsm_srvfattr __P((struct nfsrv_descript *, struct vattr *,
- struct nfs_fattr *));
-void nfsm_srvwcc __P((struct nfsrv_descript *, int, struct vattr *, int,
- struct vattr *, struct mbuf **, char **));
-void nfsm_srvpostopattr __P((struct nfsrv_descript *, int, struct vattr *,
- struct mbuf **, char **));
-int netaddr_match __P((int, union nethostaddr *, struct sockaddr *));
-int nfs_request __P((struct vnode *, struct mbuf *, int, struct thread *,
- struct ucred *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *, int));
-int nfs_namei __P((struct nameidata *, fhandle_t *, int,
- struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
- caddr_t *, struct vnode **, struct thread *, int, int));
-void nfsm_adj __P((struct mbuf *, int, int));
-int nfsm_mbuftouio __P((struct mbuf **, struct uio *, int, caddr_t *));
-void nfsrv_initcache __P((void));
-int nfs_getauth __P((struct nfsmount *, struct nfsreq *, struct ucred *,
- char **, int *, char *, int *, NFSKERBKEY_T));
-int nfs_getnickauth __P((struct nfsmount *, struct ucred *, char **,
- int *, char *, int));
-int nfs_savenickauth __P((struct nfsmount *, struct ucred *, int,
- NFSKERBKEY_T, struct mbuf **, char **,
- struct mbuf *));
-int nfs_adv __P((struct mbuf **, caddr_t *, int, int));
-void nfs_nhinit __P((void));
-void nfs_timer __P((void*));
-int nfsrv_dorec __P((struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **));
-int nfsrv_getcache __P((struct nfsrv_descript *, struct nfssvc_sock *,
- struct mbuf **));
-void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *));
-void nfsrv_cleancache __P((void));
-int nfs_connect __P((struct nfsmount *, struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *));
-void nfs_safedisconnect __P((struct nfsmount *));
-int nfs_getattrcache __P((struct vnode *, struct vattr *));
-int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long));
-int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *));
-int nfsm_uiotombuf __P((struct uio *, struct mbuf **, int, caddr_t *));
-void nfsrv_init __P((int));
-void nfs_clearcommit __P((struct mount *));
-int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrvw_sort __P((gid_t *, int));
-void nfsrv_setcred __P((struct ucred *, struct ucred *));
-int nfs_writebp __P((struct buf *, int, struct thread *));
-int nfsrv_object_create __P((struct vnode *));
-void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
-int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
- struct thread *, struct mbuf **));
-int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
- struct thread *td));
-
-int nfsrv3_access __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_fhtovp __P((fhandle_t *, int, struct vnode **, struct ucred *,
- struct nfssvc_sock *, struct sockaddr *, int *,
- int, int));
-int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
- struct export_args *));
-int nfs_ispublicfh __P((fhandle_t *));
-int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdir __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_setattr __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_statfs __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_symlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-void nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
+int nfs_getreq(struct nfsrv_descript *, struct nfsd *, int);
+int nfsrv_send(struct socket *, struct sockaddr *, struct mbuf *);
+void nfs_rephead(int, struct nfsrv_descript *, struct nfssvc_sock *,
+ int, struct mbuf **, struct mbuf **, caddr_t *);
+int nfs_slplock(struct nfssvc_sock *, int);
+void nfs_slpunlock(struct nfssvc_sock *);
+void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *,
+ struct nfs_fattr *);
+void nfsm_srvwcc(struct nfsrv_descript *, int, struct vattr *, int,
+ struct vattr *, struct mbuf **, char **);
+void nfsm_srvpostopattr(struct nfsrv_descript *, int, struct vattr *,
+ struct mbuf **, char **);
+int netaddr_match(int, union nethostaddr *, struct sockaddr *);
+int nfs_namei(struct nameidata *, fhandle_t *, int,
+ struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
+ caddr_t *, struct vnode **, struct thread *, int);
+void nfsm_adj(struct mbuf *, int, int);
+int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *);
+void nfsrv_initcache(void);
+void nfsrv_timer(void*);
+int nfsrv_dorec(struct nfssvc_sock *, struct nfsd *,
+ struct nfsrv_descript **);
+int nfsrv_getcache(struct nfsrv_descript *, struct nfssvc_sock *,
+ struct mbuf **);
+void nfsrv_updatecache(struct nfsrv_descript *, int, struct mbuf *);
+void nfsrv_cleancache(void);
+void nfsrv_init(int);
+int nfsrv_errmap(struct nfsrv_descript *, int);
+void nfsrvw_sort(gid_t *, int);
+void nfsrv_setcred(struct ucred *, struct ucred *);
+int nfsrv_object_create(struct vnode *);
+void nfsrv_wakenfsd(struct nfssvc_sock *slp);
+int nfsrv_writegather(struct nfsrv_descript **, struct nfssvc_sock *,
+ struct thread *, struct mbuf **);
+
+int nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, struct ucred *,
+ struct nfssvc_sock *, struct sockaddr *, int *, int);
+int nfsrv_setpublicfs(struct mount *, struct netexport *,
+ struct export_args *);
+int nfs_ispublicfh(fhandle_t *);
+int nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+int nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq);
+void nfsrv_rcv(struct socket *so, void *arg, int waitflag);
+void nfsrv_slpderef(struct nfssvc_sock *slp);
#endif /* _KERNEL */
#endif
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 0469388..901250f 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -34,9 +34,11 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* nfs version 2 and 3 server calls to vnode ops
* - these routines generally have 3 phases
@@ -94,10 +96,9 @@
#include <nfs/nfsproto.h>
#include <nfs/rpcv2.h>
-#include <nfs/nfs.h>
+#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nqnfs.h>
+#include <nfsserver/nfsm_subs.h>
#ifdef NFSRV_DEBUG
#define nfsdbprintf(info) printf info
@@ -113,51 +114,46 @@
#define NHUSE_MAX 2048
static struct nfsheur {
- struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
- off_t nh_nextr; /* next offset for sequential detection */
- int nh_use; /* use count for selection */
- int nh_seqcount; /* heuristic */
+ struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
+ off_t nh_nextr; /* next offset for sequential detection */
+ int nh_use; /* use count for selection */
+ int nh_seqcount; /* heuristic */
} nfsheur[NUM_HEURISTIC];
-nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
- NFFIFO, NFNON };
-#ifndef NFS_NOSERVER
-nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
- NFCHR, NFNON };
/* Global vars */
-extern u_int32_t nfs_xdrneg1;
-extern u_int32_t nfs_false, nfs_true;
-extern enum vtype nv3tov_type[8];
-extern struct nfsstats nfsstats;
int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
int nfsrvw_procrastinate_v3 = 0;
static struct timeval nfsver = { 0 };
-SYSCTL_DECL(_vfs_nfs);
+SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
static int nfs_async;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
static int nfs_commit_blks;
static int nfs_commit_miss;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
+
+struct nfsrvstats nfsrvstats;
+SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RD,
+ &nfsrvstats, nfsrvstats, "S,nfsrvstats");
-static int nfsrv_access __P((struct vnode *,int,struct ucred *,int,
- struct thread *, int));
-static void nfsrvw_coalesce __P((struct nfsrv_descript *,
- struct nfsrv_descript *));
+static int nfsrv_access(struct vnode *, int, struct ucred *, int,
+ struct thread *, int);
+static void nfsrvw_coalesce(struct nfsrv_descript *,
+ struct nfsrv_descript *);
/*
* Clear nameidata fields that are tested in nsfmout cleanup code prior
* to using first nfsm macro (that might jump to the cleanup code).
*/
-static __inline
-void
+static __inline void
ndclear(struct nameidata *nd)
{
+
nd->ni_cnd.cn_flags = 0;
nd->ni_vp = NULL;
nd->ni_dvp = NULL;
@@ -168,11 +164,8 @@ ndclear(struct nameidata *nd)
* nfs v3 access service
*/
int
-nfsrv3_access(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
@@ -181,25 +174,21 @@ nfsrv3_access(nfsd, slp, td, mrq)
struct vnode *vp = NULL;
nfsfh_t nfh;
fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache, getret;
- char *cp2;
- struct mbuf *mb, *mreq, *mb2;
+ int error = 0, rdonly, getret;
+ struct mbuf *mb, *mreq;
struct vattr vattr, *vap = &vattr;
u_long testmode, nfsmode;
- u_quad_t frev;
+ int v3 = (nfsd->nd_flag & ND_NFSV3);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
+ if (!v3)
+ panic("nfsrv3_access: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, (struct vattr *)0);
@@ -242,41 +231,33 @@ nfsmout:
* nfs getattr service
*/
int
-nfsrv_getattr(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
+ struct nfs_fattr *fp;
struct vattr va;
- register struct vattr *vap = &va;
+ struct vattr *vap = &va;
struct vnode *vp = NULL;
nfsfh_t nfh;
fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- u_quad_t frev;
+ int error = 0, rdonly;
+ struct mbuf *mb, *mreq;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(0);
error = 0;
goto nfsmout;
}
- nqsrv_getl(vp, ND_READ);
error = VOP_GETATTR(vp, vap, cred, td);
vput(vp);
vp = NULL;
@@ -299,31 +280,25 @@ nfsmout:
* nfs setattr service
*/
int
-nfsrv_setattr(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
struct vattr va, preat;
- register struct vattr *vap = &va;
- register struct nfsv2_sattr *sp;
- register struct nfs_fattr *fp;
+ struct vattr *vap = &va;
+ struct nfsv2_sattr *sp;
+ struct nfs_fattr *fp;
struct vnode *vp = NULL;
nfsfh_t nfh;
fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
+ int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- u_quad_t frev;
+ struct mbuf *mb, *mreq;
struct timespec guard;
struct mount *mp = NULL;
@@ -384,11 +359,11 @@ nfsrv_setattr(nfsd, slp, td, mrq)
/*
* Now that we have all the fields, lets do it.
*/
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
+ if (v3)
+ nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
error = 0;
goto nfsmout;
}
@@ -396,8 +371,6 @@ nfsrv_setattr(nfsd, slp, td, mrq)
/*
* vp now an active resource, pay careful attention to cleanup
*/
-
- nqsrv_getl(vp, ND_WRITE);
if (v3) {
error = preat_ret = VOP_GETATTR(vp, &preat, cred, td);
if (!error && gcheck &&
@@ -408,7 +381,8 @@ nfsrv_setattr(nfsd, slp, td, mrq)
vput(vp);
vp = NULL;
nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
+ if (v3)
+ nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
error = 0;
goto nfsmout;
}
@@ -462,31 +436,24 @@ nfsmout:
* nfs lookup rpc
*/
int
-nfsrv_lookup(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
+ struct nfs_fattr *fp;
struct nameidata nd, ind, *ndp = &nd;
struct vnode *vp, *dirp = NULL;
nfsfh_t nfh;
fhandle_t *fhp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, cache, len, dirattr_ret = 1;
+ int error = 0, len, dirattr_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vattr va, dirattr, *vap = &va;
- u_quad_t frev;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
@@ -501,7 +468,7 @@ nfsrv_lookup(nfsd, slp, td, mrq)
nd.ni_cnd.cn_nameiop = LOOKUP;
nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
+ &dirp, td, pubflag);
/*
* namei failure, only dirp to cleanup. Clear out garbarge from
@@ -517,7 +484,8 @@ nfsrv_lookup(nfsd, slp, td, mrq)
dirp = NULL;
}
nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+ if (v3)
+ nfsm_srvpostop_attr(dirattr_ret, &dirattr);
error = 0;
goto nfsmout;
}
@@ -559,7 +527,7 @@ nfsrv_lookup(nfsd, slp, td, mrq)
* Found an index file. Get rid of
* the old references. transfer nd.ni_vp'
*/
- if (dirp)
+ if (dirp)
vrele(dirp);
dirp = nd.ni_vp;
nd.ni_vp = NULL;
@@ -599,13 +567,12 @@ nfsrv_lookup(nfsd, slp, td, mrq)
if (error) {
nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+ if (v3)
+ nfsm_srvpostop_attr(dirattr_ret, &dirattr);
error = 0;
goto nfsmout;
}
- nqsrv_getl(ndp->ni_startdir, ND_READ);
-
/*
* Clear out some resources prior to potentially blocking. This
* is not as critical as ni_dvp resources in other routines, but
@@ -630,7 +597,8 @@ nfsrv_lookup(nfsd, slp, td, mrq)
ndp->ni_vp = NULL;
nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
if (error) {
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+ if (v3)
+ nfsm_srvpostop_attr(dirattr_ret, &dirattr);
error = 0;
goto nfsmout;
}
@@ -658,36 +626,30 @@ nfsmout:
* nfs readlink service
*/
int
-nfsrv_readlink(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
- register struct iovec *ivp = iv;
- register struct mbuf *mp;
- register u_int32_t *tl;
- register int32_t t1;
+ struct iovec *ivp = iv;
+ struct mbuf *mp;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache, i, tlen, len, getret;
+ int error = 0, rdonly, i, tlen, len, getret;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
+ struct mbuf *mb, *mp3, *nmp, *mreq;
struct vnode *vp = NULL;
struct vattr attr;
nfsfh_t nfh;
fhandle_t *fhp;
struct uio io, *uiop = &io;
- u_quad_t frev;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
#ifndef nolint
- mp2 = (struct mbuf *)0;
+ mp = (struct mbuf *)0;
#endif
mp3 = NULL;
fhp = &nfh.fh_generic;
@@ -695,17 +657,17 @@ nfsrv_readlink(nfsd, slp, td, mrq)
len = 0;
i = 0;
while (len < NFS_MAXPATHLEN) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- MCLGET(mp, M_TRYWAIT);
- mp->m_len = NFSMSIZ(mp);
+ MGET(nmp, M_TRYWAIT, MT_DATA);
+ MCLGET(nmp, M_TRYWAIT);
+ nmp->m_len = NFSMSIZ(nmp);
if (len == 0)
- mp3 = mp2 = mp;
+ mp3 = mp = nmp;
else {
- mp2->m_next = mp;
- mp2 = mp;
+ mp->m_next = nmp;
+ mp = nmp;
}
- if ((len+mp->m_len) > NFS_MAXPATHLEN) {
- mp->m_len = NFS_MAXPATHLEN-len;
+ if ((len + mp->m_len) > NFS_MAXPATHLEN) {
+ mp->m_len = NFS_MAXPATHLEN - len;
len = NFS_MAXPATHLEN;
} else
len += mp->m_len;
@@ -721,11 +683,11 @@ nfsrv_readlink(nfsd, slp, td, mrq)
uiop->uio_rw = UIO_READ;
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_td = (struct thread *)0;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvpostop_attr(1, (struct vattr *)0);
+ if (v3)
+ nfsm_srvpostop_attr(1, (struct vattr *)0);
error = 0;
goto nfsmout;
}
@@ -736,7 +698,6 @@ nfsrv_readlink(nfsd, slp, td, mrq)
error = ENXIO;
goto out;
}
- nqsrv_getl(vp, ND_READ);
error = VOP_READLINK(vp, uiop, cred);
out:
getret = VOP_GETATTR(vp, &attr, cred, td);
@@ -771,28 +732,23 @@ nfsmout:
* nfs read service
*/
int
-nfsrv_read(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register struct iovec *iv;
+ struct iovec *iv;
struct iovec *iv2;
- register struct mbuf *m;
- register struct nfs_fattr *fp;
- register u_int32_t *tl;
- register int32_t t1;
- register int i;
+ struct mbuf *m;
+ struct nfs_fattr *fp;
+ u_int32_t *tl;
+ int i;
caddr_t bpos;
- int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret;
+ int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct mbuf *m2;
struct vnode *vp = NULL;
nfsfh_t nfh;
@@ -802,7 +758,6 @@ nfsrv_read(nfsd, slp, td, mrq)
struct nfsheur *nh;
off_t off;
int ioflag = 0;
- u_quad_t frev;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
fhp = &nfh.fh_generic;
@@ -822,12 +777,12 @@ nfsrv_read(nfsd, slp, td, mrq)
* as well.
*/
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
vp = NULL;
nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvpostop_attr(1, (struct vattr *)0);
+ if (v3)
+ nfsm_srvpostop_attr(1, (struct vattr *)0);
error = 0;
goto nfsmout;
}
@@ -839,9 +794,8 @@ nfsrv_read(nfsd, slp, td, mrq)
error = (vp->v_type == VDIR) ? EISDIR : EACCES;
}
if (!error) {
- nqsrv_getl(vp, ND_READ);
- if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1);
+ if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0)
+ error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1);
}
getret = VOP_GETATTR(vp, vap, cred, td);
if (!error)
@@ -850,7 +804,8 @@ nfsrv_read(nfsd, slp, td, mrq)
vput(vp);
vp = NULL;
nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, vap);
+ if (v3)
+ nfsm_srvpostop_attr(getret, vap);
error = 0;
goto nfsmout;
}
@@ -989,7 +944,8 @@ nfsrv_read(nfsd, slp, td, mrq)
vput(vp);
vp = NULL;
nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, vap);
+ if (v3)
+ nfsm_srvpostop_attr(getret, vap);
error = 0;
goto nfsmout;
}
@@ -1022,38 +978,32 @@ nfsmout:
* nfs write service
*/
int
-nfsrv_write(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register struct iovec *ivp;
- register int i, cnt;
- register struct mbuf *mp;
- register struct nfs_fattr *fp;
+ struct iovec *ivp;
+ int i, cnt;
+ struct mbuf *mp;
+ struct nfs_fattr *fp;
struct iovec *iv;
struct vattr va, forat;
- register struct vattr *vap = &va;
- register u_int32_t *tl;
- register int32_t t1;
+ struct vattr *vap = &va;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache, len, forat_ret = 1;
+ int error = 0, rdonly, len, forat_ret = 1;
int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
int stable = NFSV3WRITE_FILESYNC;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vnode *vp = NULL;
nfsfh_t nfh;
fhandle_t *fhp;
struct uio io, *uiop = &io;
off_t off;
- u_quad_t frev;
struct mount *mntp = NULL;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
@@ -1123,16 +1073,17 @@ nfsrv_write(nfsd, slp, td, mrq)
if (len > NFS_MAXDATA || len < 0 || i < len) {
error = EIO;
nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+ if (v3)
+ nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
error = 0;
goto nfsmout;
}
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
vp = NULL;
nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+ if (v3)
+ nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
error = 0;
goto nfsmout;
}
@@ -1144,15 +1095,14 @@ nfsrv_write(nfsd, slp, td, mrq)
else
error = (vp->v_type == VDIR) ? EISDIR : EACCES;
}
- if (!error) {
- nqsrv_getl(vp, ND_WRITE);
+ if (!error)
error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
- }
if (error) {
vput(vp);
vp = NULL;
nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+ if (v3)
+ nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
error = 0;
goto nfsmout;
}
@@ -1191,7 +1141,7 @@ nfsrv_write(nfsd, slp, td, mrq)
uiop->uio_td = (struct thread *)0;
uiop->uio_offset = off;
error = VOP_WRITE(vp, uiop, ioflags, cred);
- nfsstats.srvvop_writes++;
+ nfsrvstats.srvvop_writes++;
FREE((caddr_t)iv, M_TEMP);
}
aftat_ret = VOP_GETATTR(vp, vap, cred, td);
@@ -1246,31 +1196,26 @@ nfsmout:
* Jan. 1994.
*/
int
-nfsrv_writegather(ndp, slp, td, mrq)
- struct nfsrv_descript **ndp;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
- register struct iovec *ivp;
- register struct mbuf *mp;
- register struct nfsrv_descript *wp, *nfsd, *owp, *swp;
- register struct nfs_fattr *fp;
- register int i;
+ struct iovec *ivp;
+ struct mbuf *mp;
+ struct nfsrv_descript *wp, *nfsd, *owp, *swp;
+ struct nfs_fattr *fp;
+ int i;
struct iovec *iov;
struct nfsrvw_delayhash *wpp;
struct ucred *cred;
struct vattr va, forat;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos, dpos;
- int error = 0, rdonly, cache, len, forat_ret = 1;
+ int error = 0, rdonly, len, forat_ret = 1;
int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq, *mrep, *md;
+ struct mbuf *mb, *mreq, *mrep, *md;
struct vnode *vp = NULL;
struct uio io, *uiop = &io;
- u_quad_t frev, cur_usec;
+ u_quad_t cur_usec;
struct mount *mntp = NULL;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
@@ -1293,7 +1238,7 @@ nfsrv_writegather(ndp, slp, td, mrq)
cur_usec = nfs_curusec();
nfsd->nd_time = cur_usec +
(v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
-
+
/*
* Now, get the write header..
*/
@@ -1313,7 +1258,7 @@ nfsrv_writegather(ndp, slp, td, mrq)
len = fxdr_unsigned(int32_t, *tl);
nfsd->nd_len = len;
nfsd->nd_eoff = nfsd->nd_off + len;
-
+
/*
* Trim the header out of the mbuf list and trim off any trailing
* junk so that the mbuf list has only the write data.
@@ -1344,23 +1289,23 @@ nfsrv_writegather(ndp, slp, td, mrq)
nfsmout:
m_freem(mrep);
error = EIO;
- nfsm_writereply(2 * NFSX_UNSIGNED, v3);
+ nfsm_writereply(2 * NFSX_UNSIGNED);
if (v3)
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
nfsd->nd_mreq = mreq;
nfsd->nd_mrep = NULL;
nfsd->nd_time = 0;
}
-
+
/*
* Add this entry to the hash and time queues.
*/
s = splsoftclock();
owp = NULL;
- wp = slp->ns_tq.lh_first;
+ wp = LIST_FIRST(&slp->ns_tq);
while (wp && wp->nd_time < nfsd->nd_time) {
owp = wp;
- wp = wp->nd_tq.le_next;
+ wp = LIST_NEXT(wp, nd_tq);
}
NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
if (owp) {
@@ -1371,16 +1316,16 @@ nfsmout:
if (nfsd->nd_mrep) {
wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
owp = NULL;
- wp = wpp->lh_first;
+ wp = LIST_FIRST(wpp);
while (wp &&
- bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
+ bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)){
owp = wp;
- wp = wp->nd_hash.le_next;
+ wp = LIST_NEXT(wp, nd_hash);
}
while (wp && wp->nd_off < nfsd->nd_off &&
- !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
+ !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)) {
owp = wp;
- wp = wp->nd_hash.le_next;
+ wp = LIST_NEXT(wp, nd_hash);
}
if (owp) {
LIST_INSERT_AFTER(owp, nfsd, nd_hash);
@@ -1390,7 +1335,7 @@ nfsmout:
* coalesce.
*/
for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
- wp = nfsd->nd_hash.le_next;
+ wp = LIST_NEXT(nfsd, nd_hash);
if (NFSW_SAMECRED(owp, nfsd))
nfsrvw_coalesce(owp, nfsd);
}
@@ -1400,7 +1345,7 @@ nfsmout:
}
splx(s);
}
-
+
/*
* Now, do VOP_WRITE()s for any one(s) that need to be done now
* and generate the associated reply mbuf list(s).
@@ -1408,8 +1353,8 @@ nfsmout:
loop1:
cur_usec = nfs_curusec();
s = splsoftclock();
- for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) {
- owp = nfsd->nd_tq.le_next;
+ for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
+ owp = LIST_NEXT(nfsd, nd_tq);
if (nfsd->nd_time > cur_usec)
break;
if (nfsd->nd_mreq)
@@ -1423,8 +1368,8 @@ loop1:
cred = &nfsd->nd_cr;
v3 = (nfsd->nd_flag & ND_NFSV3);
forat_ret = aftat_ret = 1;
- error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
- nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
+ nfsd->nd_nam, &rdonly, TRUE);
if (!error) {
if (v3)
forat_ret = VOP_GETATTR(vp, &forat, cred, td);
@@ -1437,11 +1382,8 @@ loop1:
} else {
vp = NULL;
}
- if (!error) {
- nqsrv_getl(vp, ND_WRITE);
+ if (!error)
error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
- }
-
if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
ioflags = IO_NODELOCKED;
else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
@@ -1462,7 +1404,7 @@ loop1:
mp = mp->m_next;
}
uiop->uio_iovcnt = i;
- MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
+ MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
M_TEMP, M_WAITOK);
uiop->uio_iov = ivp = iov;
mp = mrep;
@@ -1483,7 +1425,7 @@ loop1:
}
if (!error) {
error = VOP_WRITE(vp, uiop, ioflags, cred);
- nfsstats.srvvop_writes++;
+ nfsrvstats.srvvop_writes++;
vn_finished_write(mntp);
}
FREE((caddr_t)iov, M_TEMP);
@@ -1503,14 +1445,14 @@ loop1:
do {
NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
if (error) {
- nfsm_writereply(NFSX_WCCDATA(v3), v3);
+ nfsm_writereply(NFSX_WCCDATA(v3));
if (v3) {
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
}
} else {
nfsm_writereply(NFSX_PREOPATTR(v3) +
NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
- NFSX_WRITEVERF(v3), v3);
+ NFSX_WRITEVERF(v3));
if (v3) {
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
@@ -1543,7 +1485,7 @@ loop1:
nfsd->nd_time = 0;
LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
}
- nfsd = swp->nd_coalesce.lh_first;
+ nfsd = LIST_FIRST(&swp->nd_coalesce);
if (nfsd) {
LIST_REMOVE(nfsd, nd_tq);
}
@@ -1561,7 +1503,7 @@ loop1:
* Search for a reply to return.
*/
s = splsoftclock();
- for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next)
+ LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
if (nfsd->nd_mreq) {
NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
LIST_REMOVE(nfsd, nd_tq);
@@ -1582,12 +1524,10 @@ loop1:
* NB: Must be called at splsoftclock().
*/
static void
-nfsrvw_coalesce(owp, nfsd)
- register struct nfsrv_descript *owp;
- register struct nfsrv_descript *nfsd;
+nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
{
- register int overlap;
- register struct mbuf *mp;
+ int overlap;
+ struct mbuf *mp;
struct nfsrv_descript *p;
NFS_DPF(WG, ("C%03x-%03x",
@@ -1619,8 +1559,8 @@ nfsrvw_coalesce(owp, nfsd)
* If nfsd had anything else coalesced into it, transfer them
* to owp, otherwise their replies will never get sent.
*/
- for (p = nfsd->nd_coalesce.lh_first; p;
- p = nfsd->nd_coalesce.lh_first) {
+ for (p = LIST_FIRST(&nfsd->nd_coalesce); p;
+ p = LIST_FIRST(&nfsd->nd_coalesce)) {
LIST_REMOVE(p, nd_tq);
LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
}
@@ -1631,33 +1571,28 @@ nfsrvw_coalesce(owp, nfsd)
* now does a truncate to 0 length via. setattr if it already exists
*/
int
-nfsrv_create(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register struct nfs_fattr *fp;
+ struct nfs_fattr *fp;
struct vattr va, dirfor, diraft;
- register struct vattr *vap = &va;
- register struct nfsv2_sattr *sp;
- register u_int32_t *tl;
+ struct vattr *vap = &va;
+ struct nfsv2_sattr *sp;
+ u_int32_t *tl;
struct nameidata nd;
- register int32_t t1;
caddr_t bpos;
- int error = 0, rdev, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
caddr_t cp;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vnode *dirp = (struct vnode *)0;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev, tempsize;
+ u_quad_t tempsize;
u_char cverf[NFSX_V3CREATEVERF];
struct mount *mp = NULL;
struct vnode *vp;
@@ -1696,7 +1631,7 @@ nfsrv_create(nfsd, slp, td, mrq)
* prior to calling nfsm_reply ( which might goto nfsmout ).
*/
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp) {
if (v3) {
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@@ -1708,7 +1643,8 @@ nfsrv_create(nfsd, slp, td, mrq)
}
if (error) {
nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+ if (v3)
+ nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
error = 0;
goto nfsmout;
}
@@ -1776,12 +1712,11 @@ nfsrv_create(nfsd, slp, td, mrq)
* otherwise just truncate to 0 length
* should I set the mode too ?
*
- * The only possible error we can have at this point is EEXIST.
+ * The only possible error we can have at this point is EEXIST.
* nd.ni_vp will also be non-NULL in that case.
*/
if (nd.ni_vp == NULL) {
if (vap->va_type == VREG || vap->va_type == VSOCK) {
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
if (error)
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1797,7 +1732,7 @@ nfsrv_create(nfsd, slp, td, mrq)
}
}
} else if (
- vap->va_type == VCHR ||
+ vap->va_type == VCHR ||
vap->va_type == VBLK ||
vap->va_type == VFIFO
) {
@@ -1812,8 +1747,6 @@ nfsrv_create(nfsd, slp, td, mrq)
goto nfsmreply0;
}
vap->va_rdev = rdev;
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
-
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
if (error) {
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1829,10 +1762,10 @@ nfsrv_create(nfsd, slp, td, mrq)
nd.ni_dvp = NULL;
/*
- * Setup for lookup.
+ * Setup for lookup.
*
* Even though LOCKPARENT was cleared, ni_dvp may
- * be garbage.
+ * be garbage.
*/
nd.ni_cnd.cn_nameiop = LOOKUP;
nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
@@ -1859,7 +1792,6 @@ nfsrv_create(nfsd, slp, td, mrq)
error = nfsrv_access(nd.ni_vp, VWRITE, cred,
(nd.ni_cnd.cn_flags & RDONLY), td, 0);
if (!error) {
- nqsrv_getl(nd.ni_vp, ND_WRITE);
tempsize = vap->va_size;
VATTR_NULL(vap);
vap->va_size = tempsize;
@@ -1903,9 +1835,6 @@ ereply:
nfsmreply0:
nfsm_reply(0);
- error = 0;
- /* fall through */
-
nfsmout:
if (nd.ni_startdir) {
vrele(nd.ni_startdir);
@@ -1930,34 +1859,31 @@ nfsmout:
* nfs v3 mknod service
*/
int
-nfsrv_mknod(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
struct vattr va, dirfor, diraft;
- register struct vattr *vap = &va;
- register u_int32_t *tl;
+ struct vattr *vap = &va;
+ u_int32_t *tl;
struct nameidata nd;
- register int32_t t1;
caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
u_int32_t major, minor;
enum vtype vtyp;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vnode *vp, *dirp = (struct vnode *)0;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
struct mount *mp = NULL;
+ int v3 = (nfsd->nd_flag & ND_NFSV3);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ if (!v3)
+ panic("nfsrv_mknod: v3 proc called on a v2 connection");
ndclear(&nd);
fhp = &nfh.fh_generic;
@@ -1986,7 +1912,7 @@ nfsrv_mknod(nfsd, slp, td, mrq)
*/
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp)
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, td);
if (error) {
@@ -2021,15 +1947,12 @@ nfsrv_mknod(nfsd, slp, td, mrq)
if (vtyp == VSOCK) {
vrele(nd.ni_startdir);
nd.ni_startdir = NULL;
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
if (error)
NDFREE(&nd, NDF_ONLY_PNBUF);
} else {
if (vtyp != VFIFO && (error = suser_xxx(cred, 0, 0)))
goto out;
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
-
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
if (error) {
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2092,11 +2015,13 @@ out:
}
ereply:
nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
+ if (v3) {
+ if (!error) {
+ nfsm_srvpostop_fh(fhp);
+ nfsm_srvpostop_attr(0, vap);
+ }
+ nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
}
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
vn_finished_write(mp);
return (0);
nfsmout:
@@ -2121,29 +2046,23 @@ nfsmout:
* nfs remove service
*/
int
-nfsrv_remove(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
struct nameidata nd;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
struct mbuf *mb, *mreq;
struct vnode *dirp;
struct vattr dirfor, diraft;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
struct mount *mp = NULL;
struct vnode *vp;
@@ -2169,7 +2088,7 @@ nfsrv_remove(nfsd, slp, td, mrq)
nd.ni_cnd.cn_nameiop = DELETE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp) {
if (v3) {
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@@ -2193,8 +2112,6 @@ nfsrv_remove(nfsd, slp, td, mrq)
}
out:
if (!error) {
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- nqsrv_getl(nd.ni_vp, ND_WRITE);
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
NDFREE(&nd, NDF_ONLY_PNBUF);
}
@@ -2228,23 +2145,18 @@ nfsmout:
* nfs rename service
*/
int
-nfsrv_rename(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, cache, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
+ int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
int tdirfor_ret = 1, tdiraft_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
struct mbuf *mb, *mreq;
struct nameidata fromnd, tond;
struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
@@ -2252,7 +2164,6 @@ nfsrv_rename(nfsd, slp, td, mrq)
struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
nfsfh_t fnfh, tnfh;
fhandle_t *ffhp, *tfhp;
- u_quad_t frev;
uid_t saved_uid;
struct mount *mp = NULL;
struct vnode *vp;
@@ -2293,7 +2204,7 @@ nfsrv_rename(nfsd, slp, td, mrq)
fromnd.ni_cnd.cn_nameiop = DELETE;
fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
- &dpos, &fdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dpos, &fdirp, td, FALSE);
if (fdirp) {
if (v3) {
fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
@@ -2305,8 +2216,10 @@ nfsrv_rename(nfsd, slp, td, mrq)
}
if (error) {
nfsm_reply(2 * NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
- nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
+ if (v3) {
+ nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
+ nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
+ }
error = 0;
goto nfsmout;
}
@@ -2318,7 +2231,7 @@ nfsrv_rename(nfsd, slp, td, mrq)
tond.ni_cnd.cn_nameiop = RENAME;
tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
- &dpos, &tdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dpos, &tdirp, td, FALSE);
if (tdirp) {
if (v3) {
tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
@@ -2392,11 +2305,6 @@ out:
* locks prior to returning so we need to clear the pointers
* to bypass cleanup code later on.
*/
- nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
- nqsrv_getl(tdvp, ND_WRITE);
- if (tvp) {
- nqsrv_getl(tvp, ND_WRITE);
- }
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
fromnd.ni_dvp = NULL;
@@ -2465,29 +2373,23 @@ nfsmout:
* nfs link service
*/
int
-nfsrv_link(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
struct nameidata nd;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
struct mbuf *mb, *mreq;
struct vnode *vp = NULL, *xp, *dirp = (struct vnode *)0;
struct vattr dirfor, diraft, at;
nfsfh_t nfh, dnfh;
fhandle_t *fhp, *dfhp;
- u_quad_t frev;
struct mount *mp = NULL;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
@@ -2510,12 +2412,13 @@ nfsrv_link(nfsd, slp, td, mrq)
nfsm_srvmtofh(dfhp);
nfsm_srvnamesiz(len);
- error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- nfsm_srvpostop_attr(getret, &at);
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+ if (v3) {
+ nfsm_srvpostop_attr(getret, &at);
+ nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+ }
vp = NULL;
error = 0;
goto nfsmout;
@@ -2528,7 +2431,7 @@ nfsrv_link(nfsd, slp, td, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT;
error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp) {
if (v3) {
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@@ -2551,8 +2454,6 @@ nfsrv_link(nfsd, slp, td, mrq)
error = EXDEV;
out:
if (!error) {
- nqsrv_getl(vp, ND_WRITE);
- nqsrv_getl(xp, ND_WRITE);
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
NDFREE(&nd, NDF_ONLY_PNBUF);
}
@@ -2594,11 +2495,8 @@ nfsmout:
* nfs symbolic link service
*/
int
-nfsrv_symlink(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
@@ -2606,20 +2504,18 @@ nfsrv_symlink(nfsd, slp, td, mrq)
struct ucred *cred = &nfsd->nd_cr;
struct vattr va, dirfor, diraft;
struct nameidata nd;
- register struct vattr *vap = &va;
- register u_int32_t *tl;
- register int32_t t1;
+ struct vattr *vap = &va;
+ u_int32_t *tl;
struct nfsv2_sattr *sp;
- char *bpos, *pathcp = (char *)0, *cp2;
+ char *bpos, *pathcp = (char *)0;
struct uio io;
struct iovec iv;
- int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq, *mb2;
+ struct mbuf *mb, *mreq;
struct vnode *dirp = (struct vnode *)0;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
struct mount *mp = NULL;
struct vnode *vp;
@@ -2644,7 +2540,7 @@ nfsrv_symlink(nfsd, slp, td, mrq)
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp) {
if (v3) {
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@@ -2686,7 +2582,6 @@ nfsrv_symlink(nfsd, slp, td, mrq)
* issue symlink op. SAVESTART is set so the underlying path component
* is only freed by the VOP if an error occurs.
*/
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
if (error)
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2784,33 +2679,26 @@ nfsmout:
* nfs mkdir service
*/
int
-nfsrv_mkdir(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
struct vattr va, dirfor, diraft;
- register struct vattr *vap = &va;
- register struct nfs_fattr *fp;
+ struct vattr *vap = &va;
+ struct nfs_fattr *fp;
struct nameidata nd;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vnode *dirp = NULL;
int vpexcl = 0;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
struct mount *mp = NULL;
struct vnode *vp;
@@ -2836,7 +2724,7 @@ nfsrv_mkdir(nfsd, slp, td, mrq)
nd.ni_cnd.cn_flags = LOCKPARENT;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp) {
if (v3) {
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@@ -2848,7 +2736,8 @@ nfsrv_mkdir(nfsd, slp, td, mrq)
}
if (error) {
nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+ if (v3)
+ nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
error = 0;
goto nfsmout;
}
@@ -2873,11 +2762,10 @@ nfsrv_mkdir(nfsd, slp, td, mrq)
}
/*
- * Issue mkdir op. Since SAVESTART is not set, the pathname
+ * Issue mkdir op. Since SAVESTART is not set, the pathname
* component is freed by the VOP call. This will fill-in
* nd.ni_vp, reference, and exclusively lock it.
*/
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
NDFREE(&nd, NDF_ONLY_PNBUF);
vpexcl = 1;
@@ -2935,29 +2823,23 @@ nfsmout:
* nfs rmdir service
*/
int
-nfsrv_rmdir(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
struct mbuf *mb, *mreq;
struct vnode *vp, *dirp = (struct vnode *)0;
struct vattr dirfor, diraft;
nfsfh_t nfh;
fhandle_t *fhp;
struct nameidata nd;
- u_quad_t frev;
struct mount *mp = NULL;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
@@ -2981,7 +2863,7 @@ nfsrv_rmdir(nfsd, slp, td, mrq)
nd.ni_cnd.cn_nameiop = DELETE;
nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
- &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
+ &dirp, td, FALSE);
if (dirp) {
if (v3) {
dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
@@ -2993,7 +2875,8 @@ nfsrv_rmdir(nfsd, slp, td, mrq)
}
if (error) {
nfsm_reply(NFSX_WCCDATA(v3));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+ if (v3)
+ nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
error = 0;
goto nfsmout;
}
@@ -3019,11 +2902,8 @@ out:
* Issue or abort op. Since SAVESTART is not set, path name
* component is freed by the VOP after either.
*/
- if (!error) {
- nqsrv_getl(nd.ni_dvp, ND_WRITE);
- nqsrv_getl(vp, ND_WRITE);
+ if (!error)
error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
- }
NDFREE(&nd, NDF_ONLY_PNBUF);
if (dirp)
@@ -3091,25 +2971,21 @@ struct flrep {
};
int
-nfsrv_readdir(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register char *bp, *be;
- register struct mbuf *mp;
- register struct dirent *dp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
+ char *bp, *be;
+ struct mbuf *mp;
+ struct dirent *dp;
+ caddr_t cp;
+ u_int32_t *tl;
caddr_t bpos;
- struct mbuf *mb, *mb2, *mreq, *mp2;
- char *cpos, *cend, *cp2, *rbuf;
+ struct mbuf *mb, *mreq;
+ char *cpos, *cend, *rbuf;
struct vnode *vp = NULL;
struct vattr at;
nfsfh_t nfh;
@@ -3117,9 +2993,9 @@ nfsrv_readdir(nfsd, slp, td, mrq)
struct uio io;
struct iovec iv;
int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
- int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
+ int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- u_quad_t frev, off, toff, verf;
+ u_quad_t off, toff, verf;
u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
@@ -3143,8 +3019,7 @@ nfsrv_readdir(nfsd, slp, td, mrq)
if (siz > xfer)
siz = xfer;
fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (!error && vp->v_type != VDIR) {
error = ENOTDIR;
vput(vp);
@@ -3152,7 +3027,8 @@ nfsrv_readdir(nfsd, slp, td, mrq)
}
if (error) {
nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
+ if (v3)
+ nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
@@ -3160,8 +3036,6 @@ nfsrv_readdir(nfsd, slp, td, mrq)
/*
* Obtain lock on vnode for this section of the code
*/
-
- nqsrv_getl(vp, ND_READ);
if (v3) {
error = getret = VOP_GETATTR(vp, &at, cred, td);
#if 0
@@ -3178,7 +3052,8 @@ nfsrv_readdir(nfsd, slp, td, mrq)
vput(vp);
vp = NULL;
nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, &at);
+ if (v3)
+ nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
@@ -3221,7 +3096,8 @@ again:
if (cookies)
free((caddr_t)cookies, M_TEMP);
nfsm_reply(NFSX_POSTOPATTR(v3));
- nfsm_srvpostop_attr(getret, &at);
+ if (v3)
+ nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
@@ -3289,7 +3165,7 @@ again:
nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
txdr_hyper(at.va_filerev, tl);
}
- mp = mp2 = mb;
+ mp = mb;
bp = bpos;
be = bp + M_TRAILINGSPACE(mp);
@@ -3384,25 +3260,21 @@ nfsmout:
}
int
-nfsrv_readdirplus(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register char *bp, *be;
- register struct mbuf *mp;
- register struct dirent *dp;
- register caddr_t cp;
- register u_int32_t *tl;
- register int32_t t1;
+ char *bp, *be;
+ struct mbuf *mp;
+ struct dirent *dp;
+ caddr_t cp;
+ u_int32_t *tl;
caddr_t bpos;
- struct mbuf *mb, *mb2, *mreq, *mp2;
- char *cpos, *cend, *cp2, *rbuf;
+ struct mbuf *mb, *mreq;
+ char *cpos, *cend, *rbuf;
struct vnode *vp = NULL, *nvp;
struct flrep fl;
nfsfh_t nfh;
@@ -3412,11 +3284,14 @@ nfsrv_readdirplus(nfsd, slp, td, mrq)
struct vattr va, at, *vap = &va;
struct nfs_fattr *fp;
int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
- int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
- u_quad_t frev, off, toff, verf;
+ int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
+ u_quad_t off, toff, verf;
u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
+ int v3 = (nfsd->nd_flag & ND_NFSV3);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ if (!v3)
+ panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
@@ -3432,8 +3307,7 @@ nfsrv_readdirplus(nfsd, slp, td, mrq)
if (siz > xfer)
siz = xfer;
fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (!error && vp->v_type != VDIR) {
error = ENOTDIR;
vput(vp);
@@ -3453,10 +3327,8 @@ nfsrv_readdirplus(nfsd, slp, td, mrq)
if (!error && toff && verf && verf != at.va_filerev)
error = NFSERR_BAD_COOKIE;
#endif
- if (!error) {
- nqsrv_getl(vp, ND_READ);
+ if (!error)
error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
- }
if (error) {
vput(vp);
vp = NULL;
@@ -3573,13 +3445,13 @@ again:
}
vput(nvp);
nvp = NULL;
-
+
dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
nfsm_reply(cnt);
nfsm_srvpostop_attr(getret, &at);
nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
txdr_hyper(at.va_filerev, tl);
- mp = mp2 = mb;
+ mp = mb;
bp = bpos;
be = bp + M_TRAILINGSPACE(mp);
@@ -3668,7 +3540,7 @@ again:
/* And null pad to a int32_t boundary */
for (i = 0; i < rem; i++)
*bp++ = '\0';
-
+
/*
* Now copy the flrep structure out.
*/
@@ -3721,11 +3593,8 @@ nfsmout:
* nfs commit service
*/
int
-nfsrv_commit(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
@@ -3735,19 +3604,17 @@ nfsrv_commit(nfsd, slp, td, mrq)
struct vnode *vp = NULL;
nfsfh_t nfh;
fhandle_t *fhp;
- register u_int32_t *tl;
- register int32_t t1;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
- u_quad_t frev, off;
+ int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
+ struct mbuf *mb, *mreq;
+ u_quad_t off;
struct mount *mp = NULL;
+ int v3 = (nfsd->nd_flag & ND_NFSV3);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
+ if (!v3)
+ panic("nfsrv_commit: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
@@ -3770,8 +3637,7 @@ nfsrv_commit(nfsd, slp, td, mrq)
off = fxdr_hyper(tl);
tl += 2;
cnt = fxdr_unsigned(int, *tl);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
@@ -3872,43 +3738,35 @@ nfsmout:
* nfs statfs service
*/
int
-nfsrv_statfs(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register struct statfs *sf;
- register struct nfs_statfs *sfp;
- register u_int32_t *tl;
- register int32_t t1;
+ struct statfs *sf;
+ struct nfs_statfs *sfp;
+ u_int32_t *tl;
caddr_t bpos;
- int error = 0, rdonly, cache, getret = 1;
+ int error = 0, rdonly, getret = 1;
int v3 = (nfsd->nd_flag & ND_NFSV3);
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vnode *vp = NULL;
struct vattr at;
nfsfh_t nfh;
fhandle_t *fhp;
struct statfs statfs;
- u_quad_t frev, tval;
+ u_quad_t tval;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
+ if (v3)
+ nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
@@ -3959,38 +3817,32 @@ nfsmout:
* nfs fsinfo service
*/
int
-nfsrv_fsinfo(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register struct nfsv3_fsinfo *sip;
- register int32_t t1;
+ u_int32_t *tl;
+ struct nfsv3_fsinfo *sip;
caddr_t bpos;
- int error = 0, rdonly, cache, getret = 1, pref;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ int error = 0, rdonly, getret = 1, pref;
+ struct mbuf *mb, *mreq;
struct vnode *vp = NULL;
struct vattr at;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev, maxfsize;
+ u_quad_t maxfsize;
struct statfs sb;
+ int v3 = (nfsd->nd_flag & ND_NFSV3);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
+ if (!v3)
+ panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
@@ -4041,38 +3893,31 @@ nfsmout:
* nfs pathconf service
*/
int
-nfsrv_pathconf(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct sockaddr *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- register u_int32_t *tl;
- register struct nfsv3_pathconf *pc;
- register int32_t t1;
+ u_int32_t *tl;
+ struct nfsv3_pathconf *pc;
caddr_t bpos;
- int error = 0, rdonly, cache, getret = 1;
+ int error = 0, rdonly, getret = 1;
register_t linkmax, namemax, chownres, notrunc;
- char *cp2;
- struct mbuf *mb, *mb2, *mreq;
+ struct mbuf *mb, *mreq;
struct vnode *vp = NULL;
struct vattr at;
nfsfh_t nfh;
fhandle_t *fhp;
- u_quad_t frev;
+ int v3 = (nfsd->nd_flag & ND_NFSV3);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
+ if (!v3)
+ panic("nfsrv_pathconf: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
- &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
if (error) {
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
@@ -4110,7 +3955,7 @@ nfsrv_pathconf(nfsd, slp, td, mrq)
pc->pc_caseinsensitive = nfs_false;
pc->pc_casepreserving = nfs_true;
nfsmout:
- if (vp)
+ if (vp)
vput(vp);
return(error);
}
@@ -4120,24 +3965,18 @@ nfsmout:
*/
/* ARGSUSED */
int
-nfsrv_null(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep;
caddr_t bpos;
- int error = NFSERR_RETVOID, cache;
+ int error = NFSERR_RETVOID;
struct mbuf *mb, *mreq;
- u_quad_t frev;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
nfsm_reply(0);
- nfsm_srvdone;
+nfsmout:
+ return (error);
}
/*
@@ -4145,28 +3984,22 @@ nfsrv_null(nfsd, slp, td, mrq)
*/
/* ARGSUSED */
int
-nfsrv_noop(nfsd, slp, td, mrq)
- struct nfsrv_descript *nfsd;
- struct nfssvc_sock *slp;
- struct thread *td;
- struct mbuf **mrq;
+nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct thread *td, struct mbuf **mrq)
{
struct mbuf *mrep = nfsd->nd_mrep;
caddr_t bpos;
- int error, cache;
+ int error;
struct mbuf *mb, *mreq;
- u_quad_t frev;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- cache = 0;
-#endif
if (nfsd->nd_repstat)
error = nfsd->nd_repstat;
else
error = EPROCUNAVAIL;
nfsm_reply(0);
- nfsm_srvdone;
+nfsmout:
+ return (error);
}
/*
@@ -4184,13 +4017,8 @@ nfsrv_noop(nfsd, slp, td, mrq)
* will return EPERM instead of EACCESS. EPERM is always an error.
*/
static int
-nfsrv_access(vp, flags, cred, rdonly, td, override)
- register struct vnode *vp;
- int flags;
- register struct ucred *cred;
- int rdonly;
- struct thread *td;
- int override;
+nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
+ struct thread *td, int override)
{
struct vattr vattr;
int error;
@@ -4232,4 +4060,3 @@ nfsrv_access(vp, flags, cred, rdonly, td, override)
error = 0;
return error;
}
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c
index e7b10dd..4bab5d0 100644
--- a/sys/nfsserver/nfs_srvcache.c
+++ b/sys/nfsserver/nfs_srvcache.c
@@ -34,9 +34,11 @@
* SUCH DAMAGE.
*
* @(#)nfs_srvcache.c 8.3 (Berkeley) 3/30/95
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* Reference: Chet Juszczak, "Improving the Performance and Correctness
* of an NFS Server", in Proc. Winter 1989 USENIX Conference,
@@ -53,12 +55,9 @@
#include <netinet/in.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsrvcache.h>
+#include <nfsserver/nfs.h>
+#include <nfsserver/nfsrvcache.h>
-#ifndef NFS_NOSERVER
-extern struct nfsstats nfsstats;
-extern int nfsv2_procid[NFS_NPROCS];
static long numnfsrvcache;
static long desirednfsrvcache = NFSRVCACHESIZ;
@@ -101,9 +100,6 @@ static int nonidempotent[NFS_NPROCS] = {
FALSE,
FALSE,
FALSE,
- FALSE,
- FALSE,
- FALSE,
};
/* True iff the rpc reply is an nfs status ONLY! */
@@ -132,7 +128,7 @@ static int nfsv2_repstat[NFS_NPROCS] = {
* Initialize the server request cache list
*/
void
-nfsrv_initcache()
+nfsrv_initcache(void)
{
nfsrvhashtbl = hashinit(desirednfsrvcache, M_NFSD, &nfsrvhash);
@@ -154,12 +150,10 @@ nfsrv_initcache()
* Update/add new request at end of lru list
*/
int
-nfsrv_getcache(nd, slp, repp)
- register struct nfsrv_descript *nd;
- struct nfssvc_sock *slp;
- struct mbuf **repp;
+nfsrv_getcache(struct nfsrv_descript *nd, struct nfssvc_sock *slp,
+ struct mbuf **repp)
{
- register struct nfsrvcache *rp;
+ struct nfsrvcache *rp;
struct mbuf *mb;
struct sockaddr_in *saddr;
caddr_t bpos;
@@ -172,8 +166,7 @@ nfsrv_getcache(nd, slp, repp)
if (!nd->nd_nam2)
return (RC_DOIT);
loop:
- for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
- rp = rp->rc_hash.le_next) {
+ LIST_FOREACH(rp, NFSRCHASH(nd->nd_retxid), rc_hash) {
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
NFS_DPF(RC, ("H%03x", rp->rc_xid & 0xfff));
@@ -184,27 +177,27 @@ loop:
}
rp->rc_flag |= RC_LOCKED;
/* If not at end of LRU chain, move it there */
- if (rp->rc_lru.tqe_next) {
+ if (TAILQ_NEXT(rp, rc_lru)) {
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
}
if (rp->rc_state == RC_UNUSED)
panic("nfsrv cache");
if (rp->rc_state == RC_INPROG) {
- nfsstats.srvcache_inproghits++;
+ nfsrvstats.srvcache_inproghits++;
ret = RC_DROPIT;
} else if (rp->rc_flag & RC_REPSTATUS) {
- nfsstats.srvcache_nonidemdonehits++;
+ nfsrvstats.srvcache_nonidemdonehits++;
nfs_rephead(0, nd, slp, rp->rc_status,
- 0, (u_quad_t *)0, repp, &mb, &bpos);
+ repp, &mb, &bpos);
ret = RC_REPLY;
} else if (rp->rc_flag & RC_REPMBUF) {
- nfsstats.srvcache_nonidemdonehits++;
+ nfsrvstats.srvcache_nonidemdonehits++;
*repp = m_copym(rp->rc_reply, 0, M_COPYALL,
M_TRYWAIT);
ret = RC_REPLY;
} else {
- nfsstats.srvcache_idemdonehits++;
+ nfsrvstats.srvcache_idemdonehits++;
rp->rc_state = RC_INPROG;
ret = RC_DOIT;
}
@@ -216,7 +209,7 @@ loop:
return (ret);
}
}
- nfsstats.srvcache_misses++;
+ nfsrvstats.srvcache_misses++;
NFS_DPF(RC, ("M%03x", nd->nd_retxid & 0xfff));
if (numnfsrvcache < desirednfsrvcache) {
rp = (struct nfsrvcache *)malloc((u_long)sizeof *rp,
@@ -224,11 +217,11 @@ loop:
numnfsrvcache++;
rp->rc_flag = RC_LOCKED;
} else {
- rp = nfsrvlruhead.tqh_first;
+ rp = TAILQ_FIRST(&nfsrvlruhead);
while ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED;
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
- rp = nfsrvlruhead.tqh_first;
+ rp = TAILQ_FIRST(&nfsrvlruhead);
}
rp->rc_flag |= RC_LOCKED;
LIST_REMOVE(rp, rc_hash);
@@ -268,18 +261,14 @@ loop:
* Update a request cache entry after the rpc has been done
*/
void
-nfsrv_updatecache(nd, repvalid, repmbuf)
- register struct nfsrv_descript *nd;
- int repvalid;
- struct mbuf *repmbuf;
+nfsrv_updatecache(struct nfsrv_descript *nd, int repvalid, struct mbuf *repmbuf)
{
- register struct nfsrvcache *rp;
+ struct nfsrvcache *rp;
if (!nd->nd_nam2)
return;
loop:
- for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
- rp = rp->rc_hash.le_next) {
+ LIST_FOREACH(rp, NFSRCHASH(nd->nd_retxid), rc_hash) {
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
NFS_DPF(RC, ("U%03x", rp->rc_xid & 0xfff));
@@ -292,8 +281,8 @@ loop:
if (rp->rc_state == RC_DONE) {
/*
* This can occur if the cache is too small.
- * Retransmits of the same request aren't
- * dropped so we may see the operation
+ * Retransmits of the same request aren't
+ * dropped so we may see the operation
* complete more then once.
*/
if (rp->rc_flag & RC_REPMBUF) {
@@ -308,7 +297,8 @@ loop:
*/
if (repvalid && nonidempotent[nd->nd_procnum]) {
if ((nd->nd_flag & ND_NFSV3) == 0 &&
- nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
+ nfsv2_repstat[
+ nfsrvv2_procid[nd->nd_procnum]]) {
rp->rc_status = nd->nd_repstat;
rp->rc_flag |= RC_REPSTATUS;
} else {
@@ -332,12 +322,12 @@ loop:
* Clean out the cache. Called when the last nfsd terminates.
*/
void
-nfsrv_cleancache()
+nfsrv_cleancache(void)
{
- register struct nfsrvcache *rp, *nextrp;
+ struct nfsrvcache *rp, *nextrp;
- for (rp = nfsrvlruhead.tqh_first; rp != 0; rp = nextrp) {
- nextrp = rp->rc_lru.tqe_next;
+ for (rp = TAILQ_FIRST(&nfsrvlruhead); rp != 0; rp = nextrp) {
+ nextrp = TAILQ_NEXT(rp, rc_lru);
LIST_REMOVE(rp, rc_hash);
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
if (rp->rc_flag & RC_REPMBUF)
@@ -348,5 +338,3 @@ nfsrv_cleancache()
}
numnfsrvcache = 0;
}
-
-#endif /* NFS_NOSERVER */
diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c
index 8991672..0c36faa 100644
--- a/sys/nfsserver/nfs_srvsock.c
+++ b/sys/nfsserver/nfs_srvsock.c
@@ -37,6 +37,9 @@
* $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* Socket operations for use by nfs
*/
@@ -63,70 +66,20 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
+#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nqnfs.h>
+#include <nfsserver/nfsm_subs.h>
#define TRUE 1
#define FALSE 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 NFS_RTO(n, t) \
- ((t) == 0 ? (n)->nm_timeo : \
- ((t) < 3 ? \
- (((((n)->nm_srtt[t-1] + 3) >> 2) + (n)->nm_sdrtt[t-1] + 1) >> 1) : \
- ((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
-#define NFS_SRTT(r) (r)->r_nmp->nm_srtt[proct[(r)->r_procnum] - 1]
-#define NFS_SDRTT(r) (r)->r_nmp->nm_sdrtt[proct[(r)->r_procnum] - 1]
-/*
- * External data, mostly RPC constants in XDR form
- */
-extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers,
- rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr,
- rpc_auth_kerb;
-extern u_int32_t nfs_prog, nqnfs_prog;
-extern time_t nqnfsstarttime;
-extern struct nfsstats nfsstats;
-extern int nfsv3_procid[NFS_NPROCS];
-extern int nfs_ticks;
-
-/*
- * Defines which timer to use for the procnum.
- * 0 - default
- * 1 - getattr
- * 2 - lookup
- * 3 - read
- * 4 - write
- */
-static int proct[NFS_NPROCS] = {
- 0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
- 0, 0, 0,
-};
-
static int nfs_realign_test;
static int nfs_realign_count;
-static int nfs_bufpackets = 4;
-SYSCTL_DECL(_vfs_nfs);
+SYSCTL_DECL(_vfs_nfsrv);
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0, "");
/*
@@ -144,26 +97,15 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, "");
*/
#define NFS_CWNDSCALE 256
#define NFS_MAXCWND (NFS_CWNDSCALE * 32)
-static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
-int nfsrtton = 0;
-struct nfsrtt nfsrtt;
-struct callout_handle nfs_timer_handle;
+struct callout_handle nfsrv_timer_handle;
-static int nfs_msg __P((struct thread *,char *,char *));
-static int nfs_rcvlock __P((struct nfsreq *));
-static void nfs_rcvunlock __P((struct nfsreq *));
-static void nfs_realign __P((struct mbuf **pm, int hsiz));
-static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
- struct mbuf **mp));
-static void nfs_softterm __P((struct nfsreq *rep));
-static int nfs_reconnect __P((struct nfsreq *rep));
-#ifndef NFS_NOSERVER
-static int nfsrv_getstream __P((struct nfssvc_sock *,int));
+static void nfs_realign(struct mbuf **pm, int hsiz); /* XXX SHARED */
+static int nfsrv_getstream(struct nfssvc_sock *, int);
-int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp)) = {
+int (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
+ struct nfssvc_sock *slp,
+ struct thread *td,
+ struct mbuf **mreqp) = {
nfsrv_null,
nfsrv_getattr,
nfsrv_setattr,
@@ -186,1059 +128,26 @@ int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
nfsrv_fsinfo,
nfsrv_pathconf,
nfsrv_commit,
- nqnfsrv_getlease,
- nqnfsrv_vacated,
- nfsrv_noop,
nfsrv_noop
};
-#endif /* NFS_NOSERVER */
-
-/*
- * Initialize sockets and congestion for a new NFS connection.
- * We do not free the sockaddr if error.
- */
-int
-nfs_connect(nmp, rep)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
-{
- register struct socket *so;
- int s, error, rcvreserve, sndreserve;
- int pktscale;
- struct sockaddr *saddr;
- struct sockaddr_in *sin;
- struct thread *td = thread0; /* only used for socreate and sobind */
-
- nmp->nm_so = (struct socket *)0;
- saddr = nmp->nm_nam;
- error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype,
- nmp->nm_soproto, td);
- if (error)
- goto bad;
- so = nmp->nm_so;
- nmp->nm_soflags = so->so_proto->pr_flags;
-
- /*
- * Some servers require that the client port be a reserved port number.
- */
- if (saddr->sa_family == AF_INET && (nmp->nm_flag & NFSMNT_RESVPORT)) {
- struct sockopt sopt;
- int ip;
- struct sockaddr_in ssin;
-
- bzero(&sopt, sizeof sopt);
- ip = IP_PORTRANGE_LOW;
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = IPPROTO_IP;
- sopt.sopt_name = IP_PORTRANGE;
- sopt.sopt_val = (void *)&ip;
- sopt.sopt_valsize = sizeof(ip);
- sopt.sopt_td = NULL;
- error = sosetopt(so, &sopt);
- if (error)
- goto bad;
- bzero(&ssin, sizeof ssin);
- sin = &ssin;
- sin->sin_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, (struct sockaddr *)sin, td);
- if (error)
- goto bad;
- bzero(&sopt, sizeof sopt);
- ip = IP_PORTRANGE_DEFAULT;
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = IPPROTO_IP;
- sopt.sopt_name = IP_PORTRANGE;
- sopt.sopt_val = (void *)&ip;
- sopt.sopt_valsize = sizeof(ip);
- sopt.sopt_td = NULL;
- error = sosetopt(so, &sopt);
- 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 (nmp->nm_flag & NFSMNT_NOCONN) {
- if (nmp->nm_soflags & PR_CONNREQUIRED) {
- error = ENOTCONN;
- goto bad;
- }
- } else {
- error = soconnect(so, nmp->nm_nam, 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.
- */
- s = splnet();
- while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
- (void) tsleep((caddr_t)&so->so_timeo, PSOCK,
- "nfscon", 2 * hz);
- if ((so->so_state & SS_ISCONNECTING) &&
- so->so_error == 0 && rep &&
- (error = nfs_sigintr(nmp, rep,
- (rep->r_td ? rep->r_td->td_proc : NULL))) != 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 (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_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;
- }
-
- /*
- * Get buffer reservation size from sysctl, but impose reasonable
- * limits.
- */
- pktscale = nfs_bufpackets;
- if (pktscale < 2)
- pktscale = 2;
- if (pktscale > 64)
- pktscale = 64;
-
- if (nmp->nm_sotype == SOCK_DGRAM) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else if (nmp->nm_sotype == SOCK_SEQPACKET) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else {
- if (nmp->nm_sotype != SOCK_STREAM)
- panic("nfscon sotype");
- if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_KEEPALIVE;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- if (so->so_proto->pr_protocol == IPPROTO_TCP) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_level = IPPROTO_TCP;
- sopt.sopt_name = TCP_NODELAY;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- }
- 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 */
- nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] =
- nmp->nm_srtt[3] = (NFS_TIMEO << 3);
- nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] =
- nmp->nm_sdrtt[3] = 0;
- nmp->nm_cwnd = NFS_MAXCWND / 2; /* Initial send window */
- nmp->nm_sent = 0;
- nmp->nm_timeouts = 0;
- return (0);
-
-bad:
- nfs_disconnect(nmp);
- return (error);
-}
-
-/*
- * Reconnect routine:
- * Called when a connection is broken on a reliable protocol.
- * - clean up the old socket
- * - nfs_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 nfs_sndlock() set on the mount point.
- */
-static int
-nfs_reconnect(rep)
- register struct nfsreq *rep;
-{
- register struct nfsreq *rp;
- register struct nfsmount *nmp = rep->r_nmp;
- int error;
-
- nfs_disconnect(nmp);
- while ((error = nfs_connect(nmp, rep)) != 0) {
- if (error == EINTR || error == ERESTART)
- return (EINTR);
- (void) tsleep((caddr_t)&lbolt, PSOCK, "nfscon", 0);
- }
-
- /*
- * Loop through outstanding request list and fix up all requests
- * on old socket.
- */
- for (rp = nfs_reqq.tqh_first; rp != 0; rp = rp->r_chain.tqe_next) {
- if (rp->r_nmp == nmp)
- rp->r_flags |= R_MUSTRESEND;
- }
- return (0);
-}
-
-/*
- * NFS disconnect. Clean up and unlink.
- */
-void
-nfs_disconnect(nmp)
- register struct nfsmount *nmp;
-{
- register struct socket *so;
-
- if (nmp->nm_so) {
- so = nmp->nm_so;
- nmp->nm_so = (struct socket *)0;
- soshutdown(so, 2);
- soclose(so);
- }
-}
-
-void
-nfs_safedisconnect(nmp)
- struct nfsmount *nmp;
-{
- struct nfsreq dummyreq;
-
- bzero(&dummyreq, sizeof(dummyreq));
- dummyreq.r_nmp = nmp;
- nfs_rcvlock(&dummyreq);
- nfs_disconnect(nmp);
- nfs_rcvunlock(&dummyreq);
-}
-
-/*
- * This is the nfs send routine. For connection based socket types, it
- * must be called with an nfs_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 (?)
- */
-int
-nfs_send(so, nam, top, rep)
- register struct socket *so;
- struct sockaddr *nam;
- register struct mbuf *top;
- struct nfsreq *rep;
-{
- struct sockaddr *sendnam;
- int error, soflags, flags;
-
- if (rep) {
- if (rep->r_flags & R_SOFTTERM) {
- m_freem(top);
- return (EINTR);
- }
- if ((so = rep->r_nmp->nm_so) == NULL) {
- rep->r_flags |= R_MUSTRESEND;
- m_freem(top);
- return (0);
- }
- rep->r_flags &= ~R_MUSTRESEND;
- soflags = rep->r_nmp->nm_soflags;
- } else
- soflags = so->so_proto->pr_flags;
- if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
- sendnam = (struct sockaddr *)0;
- else
- sendnam = nam;
- if (so->so_type == SOCK_SEQPACKET)
- flags = MSG_EOR;
- else
- flags = 0;
-
- error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
- flags, curthread /*XXX*/);
- /*
- * ENOBUFS for dgram sockets is transient and non fatal.
- * No need to log, and no need to break a soft mount.
- */
- if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
- error = 0;
- if (rep) /* do backoff retransmit on client */
- rep->r_flags |= R_MUSTRESEND;
- }
-
- if (error) {
- if (rep) {
- log(LOG_INFO, "nfs send error %d for server %s\n",error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- /*
- * 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, "nfsd send error %d\n", error);
-
- /*
- * Handle any recoverable (soft) socket errors here. (?)
- */
- if (error != EINTR && error != ERESTART &&
- error != EWOULDBLOCK && error != EPIPE)
- error = 0;
- }
- 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
-nfs_receive(rep, aname, mp)
- register struct nfsreq *rep;
- struct sockaddr **aname;
- struct mbuf **mp;
-{
- register struct socket *so;
- struct uio auio;
- struct iovec aio;
- register struct mbuf *m;
- struct mbuf *control;
- u_int32_t len;
- struct sockaddr **getnam;
- int error, sotype, rcvflg;
- struct thread *td = curthread; /* XXX */
-
- /*
- * Set up arguments for soreceive()
- */
- *mp = (struct mbuf *)0;
- *aname = (struct sockaddr *)0;
- sotype = rep->r_nmp->nm_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 = nfs_sndlock(rep);
- if (error)
- return (error);
-tryagain:
- /*
- * Check for fatal errors and resending request.
- */
- /*
- * Ugh: If a reconnect attempt just happened, nm_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)) {
- nfs_sndunlock(rep);
- return (EINTR);
- }
- so = rep->r_nmp->nm_so;
- if (!so) {
- error = nfs_reconnect(rep);
- if (error) {
- nfs_sndunlock(rep);
- return (error);
- }
- goto tryagain;
- }
- while (rep->r_flags & R_MUSTRESEND) {
- m = m_copym(rep->r_mreq, 0, M_COPYALL, M_TRYWAIT);
- nfsstats.rpcretries++;
- error = nfs_send(so, rep->r_nmp->nm_nam, m, rep);
- if (error) {
- if (error == EINTR || error == ERESTART ||
- (error = nfs_reconnect(rep)) != 0) {
- nfs_sndunlock(rep);
- return (error);
- }
- goto tryagain;
- }
- }
- nfs_sndunlock(rep);
- 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);
- auio.uio_td = td;
- do {
- rcvflg = MSG_WAITALL;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, (struct sockaddr **)0, &auio,
- (struct mbuf **)0, (struct mbuf **)0,
- &rcvflg);
- if (error == EWOULDBLOCK && rep) {
- if (rep->r_flags & R_SOFTTERM)
- return (EINTR);
- }
- } while (error == EWOULDBLOCK);
- if (!error && auio.uio_resid > 0) {
- /*
- * Don't log a 0 byte receive; it means
- * that the socket has been closed, and
- * can happen during normal operation
- * (forcible unmount or Solaris server).
- */
- if (auio.uio_resid != sizeof (u_int32_t))
- log(LOG_INFO,
- "short receive (%d/%d) from nfs server %s\n",
- (int)(sizeof(u_int32_t) - auio.uio_resid),
- (int)sizeof(u_int32_t),
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- 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 > NFS_MAXPACKET) {
- log(LOG_ERR, "%s (%d) from nfs server %s\n",
- "impossible packet length",
- len,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- error = EFBIG;
- goto errout;
- }
- auio.uio_resid = len;
- do {
- rcvflg = MSG_WAITALL;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, (struct sockaddr **)0,
- &auio, mp, (struct mbuf **)0, &rcvflg);
- } while (error == EWOULDBLOCK || error == EINTR ||
- error == ERESTART);
- if (!error && auio.uio_resid > 0) {
- if (len != auio.uio_resid)
- log(LOG_INFO,
- "short receive (%d/%d) from nfs server %s\n",
- len - auio.uio_resid, len,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- 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 */
- auio.uio_td = td;
- do {
- rcvflg = 0;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, (struct sockaddr **)0,
- &auio, mp, &control, &rcvflg);
- if (control)
- m_freem(control);
- if (error == EWOULDBLOCK && rep) {
- if (rep->r_flags & R_SOFTTERM)
- 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 nfs server %s\n",
- error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- error = nfs_sndlock(rep);
- if (!error)
- error = nfs_reconnect(rep);
- if (!error)
- goto tryagain;
- else
- nfs_sndunlock(rep);
- }
- } else {
- if ((so = rep->r_nmp->nm_so) == NULL)
- return (EACCES);
- if (so->so_state & SS_ISCONNECTED)
- getnam = (struct sockaddr **)0;
- else
- getnam = aname;
- auio.uio_resid = len = 1000000;
- auio.uio_td = td;
- do {
- rcvflg = 0;
- error = so->so_proto->pr_usrreqs->pru_soreceive
- (so, getnam, &auio, mp,
- (struct mbuf **)0, &rcvflg);
- if (error == EWOULDBLOCK &&
- (rep->r_flags & R_SOFTTERM))
- return (EINTR);
- } while (error == EWOULDBLOCK);
- len -= auio.uio_resid;
- }
- if (error) {
- m_freem(*mp);
- *mp = (struct mbuf *)0;
- }
- /*
- * 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.
- */
- nfs_realign(mp, 5 * NFSX_UNSIGNED);
- 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 */
-int
-nfs_reply(myrep)
- struct nfsreq *myrep;
-{
- register struct nfsreq *rep;
- register struct nfsmount *nmp = myrep->r_nmp;
- register int32_t t1;
- struct mbuf *mrep, *md;
- struct sockaddr *nam;
- 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.
- * If nfs_rcvlock() returns EALREADY, that means that
- * the reply has already been recieved by another
- * process and we can return immediately. In this
- * case, the lock is not taken to avoid races with
- * other processes.
- */
- error = nfs_rcvlock(myrep);
- if (error == EALREADY)
- return (0);
- if (error)
- return (error);
- /*
- * Get the next Rpc reply off the socket
- */
- error = nfs_receive(myrep, &nam, &mrep);
- nfs_rcvunlock(myrep);
- if (error) {
-
- /*
- * Ignore routing errors on connectionless protocols??
- */
- if (NFSIGNORE_SOERROR(nmp->nm_soflags, error)) {
- nmp->nm_so->so_error = 0;
- if (myrep->r_flags & R_GETONEREP)
- return (0);
- continue;
- }
- return (error);
- }
- if (nam)
- FREE(nam, M_SONAME);
-
- /*
- * Get the xid and check that it is an rpc reply
- */
- md = mrep;
- dpos = mtod(md, caddr_t);
- nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- rxid = *tl++;
- if (*tl != rpc_reply) {
-#ifndef NFS_NOSERVER
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- if (nqnfs_callback(nmp, mrep, md, dpos))
- nfsstats.rpcinvalid++;
- } else {
- nfsstats.rpcinvalid++;
- m_freem(mrep);
- }
-#else
- nfsstats.rpcinvalid++;
- m_freem(mrep);
-#endif
-nfsmout:
- if (myrep->r_flags & R_GETONEREP)
- return (0);
- continue;
- }
-
- /*
- * Loop through the request list to match up the reply
- * Iff no match, just drop the datagram
- */
- for (rep = nfs_reqq.tqh_first; rep != 0;
- rep = rep->r_chain.tqe_next) {
- if (rep->r_mrep == NULL && rxid == rep->r_xid) {
- /* Found it.. */
- rep->r_mrep = mrep;
- rep->r_md = md;
- rep->r_dpos = dpos;
- if (nfsrtton) {
- struct rttl *rt;
-
- rt = &nfsrtt.rttl[nfsrtt.pos];
- rt->proc = rep->r_procnum;
- rt->rto = NFS_RTO(nmp, proct[rep->r_procnum]);
- rt->sent = nmp->nm_sent;
- rt->cwnd = nmp->nm_cwnd;
- rt->srtt = nmp->nm_srtt[proct[rep->r_procnum] - 1];
- rt->sdrtt = nmp->nm_sdrtt[proct[rep->r_procnum] - 1];
- rt->fsid = nmp->nm_mountp->mnt_stat.f_fsid;
- getmicrotime(&rt->tstamp);
- if (rep->r_flags & R_TIMING)
- rt->rtt = rep->r_rtt;
- else
- rt->rtt = 1000000;
- nfsrtt.pos = (nfsrtt.pos + 1) % NFSRTTLOGSIZ;
- }
- /*
- * Update congestion window.
- * Do the additive increase of
- * one rpc/rtt.
- */
- if (nmp->nm_cwnd <= nmp->nm_sent) {
- nmp->nm_cwnd +=
- (NFS_CWNDSCALE * NFS_CWNDSCALE +
- (nmp->nm_cwnd >> 1)) / nmp->nm_cwnd;
- if (nmp->nm_cwnd > NFS_MAXCWND)
- nmp->nm_cwnd = NFS_MAXCWND;
- }
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_SENT;
- nmp->nm_sent -= NFS_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 -= (NFS_SRTT(rep) >> 3);
- NFS_SRTT(rep) += t1;
- if (t1 < 0)
- t1 = -t1;
- t1 -= (NFS_SDRTT(rep) >> 2);
- NFS_SDRTT(rep) += t1;
- }
- nmp->nm_timeouts = 0;
- break;
- }
- }
- /*
- * If not matched to a request, drop it.
- * If it's mine, get out.
- */
- if (rep == 0) {
- nfsstats.rpcunexpected++;
- m_freem(mrep);
- } else if (rep == myrep) {
- if (rep->r_mrep == NULL)
- panic("nfsreply nil");
- return (0);
- }
- if (myrep->r_flags & R_GETONEREP)
- return (0);
- }
-}
-
-/*
- * 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
- */
-int
-nfs_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp)
- struct vnode *vp;
- struct mbuf *mrest;
- int procnum;
- struct thread *td;
- struct ucred *cred;
- struct mbuf **mrp;
- struct mbuf **mdp;
- caddr_t *dposp;
-{
- register struct mbuf *mrep, *m2;
- register struct nfsreq *rep;
- register u_int32_t *tl;
- register int i;
- struct nfsmount *nmp;
- struct mbuf *m, *md, *mheadend;
- struct nfsnode *np;
- char nickv[RPCX_NICKVERF];
- time_t reqtime, waituntil;
- caddr_t dpos, cp2;
- int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
- int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
- int verf_len, verf_type;
- u_int32_t xid;
- u_quad_t frev;
- char *auth_str, *verf_str;
- NFSKERBKEY_T key; /* save session key */
-
- nmp = VFSTONFS(vp->v_mount);
- MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
- rep->r_nmp = nmp;
- rep->r_vp = vp;
- rep->r_td = td;
- rep->r_procnum = procnum;
- i = 0;
- m = mrest;
- while (m) {
- i += m->m_len;
- m = m->m_next;
- }
- mrest_len = i;
-
- /*
- * Get the RPC header with authorization.
- */
-kerbauth:
- verf_str = auth_str = (char *)0;
- if (nmp->nm_flag & NFSMNT_KERB) {
- verf_str = nickv;
- verf_len = sizeof (nickv);
- auth_type = RPCAUTH_KERB4;
- bzero((caddr_t)key, sizeof (key));
- if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
- &auth_len, verf_str, verf_len)) {
- error = nfs_getauth(nmp, rep, cred, &auth_str,
- &auth_len, verf_str, &verf_len, key);
- if (error) {
- free((caddr_t)rep, M_NFSREQ);
- m_freem(mrest);
- return (error);
- }
- }
- } else {
- auth_type = RPCAUTH_UNIX;
- if (cred->cr_ngroups < 1)
- panic("nfsreq nogrps");
- auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
- nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
- 5 * NFSX_UNSIGNED;
- }
- m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
- auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
- if (auth_str)
- free(auth_str, M_TEMP);
-
- /*
- * For stream protocols, insert a Sun RPC Record Mark.
- */
- if (nmp->nm_sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 |
- (m->m_pkthdr.len - NFSX_UNSIGNED));
- }
- rep->r_mreq = m;
- rep->r_xid = xid;
-tryagain:
- if (nmp->nm_flag & NFSMNT_SOFT)
- rep->r_retry = nmp->nm_retry;
- else
- rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */
- rep->r_rtt = rep->r_rexmit = 0;
- if (proct[procnum] > 0)
- rep->r_flags = R_TIMING;
- else
- rep->r_flags = 0;
- rep->r_mrep = NULL;
-
- /*
- * Do the client side RPC.
- */
- nfsstats.rpcrequests++;
- /*
- * Chain request into list of outstanding requests. Be sure
- * to put it LAST so timer finds oldest requests first.
- */
- s = splsoftclock();
- TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
-
- /* Get send time for nqnfs */
- reqtime = time_second;
-
- /*
- * 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 (nmp->nm_so && (nmp->nm_sotype != SOCK_DGRAM ||
- (nmp->nm_flag & NFSMNT_DUMBTIMR) ||
- nmp->nm_sent < nmp->nm_cwnd)) {
- splx(s);
- if (nmp->nm_soflags & PR_CONNREQUIRED)
- error = nfs_sndlock(rep);
- if (!error) {
- m2 = m_copym(m, 0, M_COPYALL, M_TRYWAIT);
- error = nfs_send(nmp->nm_so, nmp->nm_nam, m2, rep);
- if (nmp->nm_soflags & PR_CONNREQUIRED)
- nfs_sndunlock(rep);
- }
- if (!error && (rep->r_flags & R_MUSTRESEND) == 0) {
- nmp->nm_sent += NFS_CWNDSCALE;
- rep->r_flags |= R_SENT;
- }
- } else {
- splx(s);
- rep->r_rtt = -1;
- }
-
- /*
- * Wait for the reply from our send or the timer's.
- */
- if (!error || error == EPIPE)
- error = nfs_reply(rep);
-
- /*
- * RPC done, unlink the request.
- */
- s = splsoftclock();
- TAILQ_REMOVE(&nfs_reqq, rep, r_chain);
- splx(s);
-
- /*
- * Decrement the outstanding request count.
- */
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_SENT; /* paranoia */
- nmp->nm_sent -= NFS_CWNDSCALE;
- }
- /*
- * If there was a successful reply and a tprintf msg.
- * tprintf a response.
- */
- if (!error && (rep->r_flags & R_TPRINTFMSG))
- nfs_msg(rep->r_td, nmp->nm_mountp->mnt_stat.f_mntfromname,
- "is alive again");
- mrep = rep->r_mrep;
- md = rep->r_md;
- dpos = rep->r_dpos;
- if (error) {
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * break down the rpc header and check if ok
- */
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- if (*tl++ == rpc_msgdenied) {
- if (*tl == rpc_mismatch)
- error = EOPNOTSUPP;
- else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
- if (!failed_auth) {
- failed_auth++;
- mheadend->m_next = (struct mbuf *)0;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- goto kerbauth;
- } else
- error = EAUTH;
- } else
- error = EACCES;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * Grab any Kerberos verifier, otherwise just throw it away.
- */
- verf_type = fxdr_unsigned(int, *tl++);
- i = fxdr_unsigned(int32_t, *tl);
- if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
- error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
- if (error)
- goto nfsmout;
- } else if (i > 0)
- nfsm_adv(nfsm_rndup(i));
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- /* 0 == ok */
- if (*tl == 0) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl != 0) {
- error = fxdr_unsigned(int, *tl);
- 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((caddr_t)&lbolt,
- PSOCK, "nqnfstry", 0);
- trylater_delay *= nfs_backoff[trylater_cnt];
- if (trylater_cnt < 7)
- trylater_cnt++;
- goto tryagain;
- }
-
- /*
- * If the File Handle was stale, invalidate the
- * lookup cache, just in case.
- */
- if (error == ESTALE)
- cache_purge(vp);
- if (nmp->nm_flag & NFSMNT_NFSV3) {
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- error |= NFSERR_RETERR;
- } else
- m_freem(mrep);
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * For nqnfs, get any lease in reply
- */
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl) {
- np = VTONFS(vp);
- nqlflag = fxdr_unsigned(int, *tl);
- nfsm_dissect(tl, u_int32_t *, 4*NFSX_UNSIGNED);
- cachable = fxdr_unsigned(int, *tl++);
- reqtime += fxdr_unsigned(int, *tl++);
- if (reqtime > time_second) {
- frev = fxdr_hyper(tl);
- nqnfs_clientlease(nmp, np, nqlflag,
- cachable, reqtime, frev);
- }
- }
- }
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- m_freem(rep->r_mreq);
- FREE((caddr_t)rep, M_NFSREQ);
- return (0);
- }
- m_freem(mrep);
- error = EPROTONOSUPPORT;
-nfsmout:
- m_freem(rep->r_mreq);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
-}
-#ifndef NFS_NOSERVER
/*
* Generate the rpc reply header
* siz arg. is used to decide if adding a cluster is worthwhile
*/
-int
-nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
- int siz;
- struct nfsrv_descript *nd;
- struct nfssvc_sock *slp;
- int err;
- int cache;
- u_quad_t *frev;
- struct mbuf **mrq;
- struct mbuf **mbp;
- caddr_t *bposp;
+void
+nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
+ int err, struct mbuf **mrq, struct mbuf **mbp, caddr_t *bposp)
{
- register u_int32_t *tl;
- register struct mbuf *mreq;
+ u_int32_t *tl;
+ struct mbuf *mreq;
caddr_t bpos;
- struct mbuf *mb, *mb2;
+ struct mbuf *mb;
+
+ nd->nd_repstat = err;
+ if (err && (nd->nd_flag & ND_NFSV3) == 0) /* XXX recheck */
+ siz = 0;
MGETHDR(mreq, M_TRYWAIT, MT_DATA);
mb = mreq;
@@ -1272,48 +181,10 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
*tl++ = rpc_msgaccepted;
/*
- * For Kerberos authentication, we must send the nickname
- * verifier back, otherwise just RPCAUTH_NULL.
+ * Send a RPCAUTH_NULL verifier - no Kerberos.
*/
- if (nd->nd_flag & ND_KERBFULL) {
- register struct nfsuid *nuidp;
- struct timeval ktvin, ktvout;
-
- for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
- (!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- ktvin.tv_sec =
- txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
- ktvin.tv_usec =
- txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Encrypt the timestamp in ecb mode using the
- * session key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *tl++ = rpc_auth_kerb;
- *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
- *tl = ktvout.tv_sec;
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- *tl++ = ktvout.tv_usec;
- *tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
- } else {
- *tl++ = 0;
- *tl++ = 0;
- }
+ *tl++ = 0;
+ *tl++ = 0;
switch (err) {
case EPROGUNAVAIL:
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
@@ -1321,13 +192,8 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
case EPROGMISMATCH:
*tl = txdr_unsigned(RPC_PROGMISMATCH);
nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (nd->nd_flag & ND_NQNFS) {
- *tl++ = txdr_unsigned(3);
- *tl = txdr_unsigned(3);
- } else {
- *tl++ = txdr_unsigned(2);
- *tl = txdr_unsigned(3);
- }
+ *tl++ = txdr_unsigned(2);
+ *tl = txdr_unsigned(3);
break;
case EPROCUNAVAIL:
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
@@ -1348,320 +214,14 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
};
}
- /*
- * For nqnfs, piggyback lease as requested.
- */
- if ((nd->nd_flag & ND_NQNFS) && err == 0) {
- if (nd->nd_flag & ND_LEASE) {
- nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
- *tl++ = txdr_unsigned(cache);
- *tl++ = txdr_unsigned(nd->nd_duration);
- txdr_hyper(*frev, tl);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
if (mrq != NULL)
- *mrq = mreq;
+ *mrq = mreq;
*mbp = mb;
*bposp = bpos;
if (err != 0 && err != NFSERR_RETVOID)
- nfsstats.srvrpc_errs++;
- return (0);
-}
-
-
-#endif /* NFS_NOSERVER */
-/*
- * Nfs timer routine
- * Scan the nfsreq 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
-nfs_timer(arg)
- void *arg; /* never used */
-{
- register struct nfsreq *rep;
- register struct mbuf *m;
- register struct socket *so;
- register struct nfsmount *nmp;
- register int timeo;
- int s, error;
-#ifndef NFS_NOSERVER
- static long lasttime = 0;
- register struct nfssvc_sock *slp;
- u_quad_t cur_usec;
-#endif /* NFS_NOSERVER */
- struct thread *td = thread0; /* XXX for credentials, will break if sleep */
-
- s = splnet();
- for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
- nmp = rep->r_nmp;
- if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
- continue;
- if (nfs_sigintr(nmp, rep,
- (rep->r_td ? rep->r_td->td_proc : NULL))) {
- nfs_softterm(rep);
- continue;
- }
- if (rep->r_rtt >= 0) {
- rep->r_rtt++;
- if (nmp->nm_flag & NFSMNT_DUMBTIMR)
- timeo = nmp->nm_timeo;
- else
- timeo = NFS_RTO(nmp, proct[rep->r_procnum]);
- if (nmp->nm_timeouts > 0)
- timeo *= nfs_backoff[nmp->nm_timeouts - 1];
- if (rep->r_rtt <= timeo)
- continue;
- if (nmp->nm_timeouts < 8)
- nmp->nm_timeouts++;
- }
- /*
- * Check for server not responding
- */
- if ((rep->r_flags & R_TPRINTFMSG) == 0 &&
- rep->r_rexmit > nmp->nm_deadthresh) {
- nfs_msg(rep->r_td,
- nmp->nm_mountp->mnt_stat.f_mntfromname,
- "not responding");
- rep->r_flags |= R_TPRINTFMSG;
- }
- if (rep->r_rexmit >= rep->r_retry) { /* too many */
- nfsstats.rpctimeouts++;
- nfs_softterm(rep);
- continue;
- }
- if (nmp->nm_sotype != SOCK_DGRAM) {
- if (++rep->r_rexmit > NFS_MAXREXMIT)
- rep->r_rexmit = NFS_MAXREXMIT;
- continue;
- }
- if ((so = nmp->nm_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 &&
- ((nmp->nm_flag & NFSMNT_DUMBTIMR) ||
- (rep->r_flags & R_SENT) ||
- nmp->nm_sent < nmp->nm_cwnd) &&
- (m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))){
- if ((nmp->nm_flag & NFSMNT_NOCONN) == 0)
- error = (*so->so_proto->pr_usrreqs->pru_send)
- (so, 0, m, (struct sockaddr *)0,
- (struct mbuf *)0, td);
- else
- error = (*so->so_proto->pr_usrreqs->pru_send)
- (so, 0, m, nmp->nm_nam, (struct mbuf *)0,
- td);
- if (error) {
- if (NFSIGNORE_SOERROR(nmp->nm_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 > NFS_MAXREXMIT)
- rep->r_rexmit = NFS_MAXREXMIT;
- nmp->nm_cwnd >>= 1;
- if (nmp->nm_cwnd < NFS_CWNDSCALE)
- nmp->nm_cwnd = NFS_CWNDSCALE;
- nfsstats.rpcretries++;
- } else {
- rep->r_flags |= R_SENT;
- nmp->nm_sent += NFS_CWNDSCALE;
- }
- rep->r_rtt = 0;
- }
- }
- }
-#ifndef NFS_NOSERVER
- /*
- * Call the nqnfs server timer once a second to handle leases.
- */
- if (lasttime != time_second) {
- lasttime = time_second;
- nqnfs_serverd();
- }
-
- /*
- * Scan the write gathering queues for writes that need to be
- * completed now.
- */
- cur_usec = nfs_curusec();
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
- if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
- nfsrv_wakenfsd(slp);
- }
-#endif /* NFS_NOSERVER */
- splx(s);
- nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
-}
-
-/*
- * Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT).
- * The nm_send count is decremented now to avoid deadlocks when the process in
- * soreceive() hasn't yet managed to send its own request.
- */
-
-static void
-nfs_softterm(rep)
- struct nfsreq *rep;
-{
- rep->r_flags |= R_SOFTTERM;
-
- if (rep->r_flags & R_SENT) {
- rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
- rep->r_flags &= ~R_SENT;
- }
-}
-
-/*
- * Test for a termination condition pending on the process.
- * This is used for NFSMNT_INT mounts.
- */
-int
-nfs_sigintr(nmp, rep, p)
- struct nfsmount *nmp;
- struct nfsreq *rep;
- register struct proc *p;
-{
- sigset_t tmpset;
-
- if (rep && (rep->r_flags & R_SOFTTERM))
- return (EINTR);
- if (!(nmp->nm_flag & NFSMNT_INT))
- return (0);
- if (p == NULL)
- return (0);
-
- tmpset = p->p_siglist;
- SIGSETNAND(tmpset, p->p_sigmask);
- SIGSETNAND(tmpset, p->p_sigignore);
- if (SIGNOTEMPTY(p->p_siglist) && NFSINT_SIGMASK(tmpset))
- return (EINTR);
-
- 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.
- */
-int
-nfs_sndlock(rep)
- struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
- struct thread *td;
- int slpflag = 0, slptimeo = 0;
-
- if (rep) {
- td = rep->r_td;
- if (rep->r_nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- } else
- td = (struct thread *)0;
- while (*statep & NFSSTA_SNDLOCK) {
- if (nfs_sigintr(rep->r_nmp, rep, td ? td->td_proc : NULL))
- return (EINTR);
- *statep |= NFSSTA_WANTSND;
- (void) tsleep((caddr_t)statep, slpflag | (PZERO - 1),
- "nfsndlck", slptimeo);
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- *statep |= NFSSTA_SNDLOCK;
- return (0);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-void
-nfs_sndunlock(rep)
- struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
-
- if ((*statep & NFSSTA_SNDLOCK) == 0)
- panic("nfs sndunlock");
- *statep &= ~NFSSTA_SNDLOCK;
- if (*statep & NFSSTA_WANTSND) {
- *statep &= ~NFSSTA_WANTSND;
- wakeup((caddr_t)statep);
- }
-}
-
-static int
-nfs_rcvlock(rep)
- register struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
- int slpflag, slptimeo = 0;
-
- if (rep->r_nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- else
- slpflag = 0;
- while (*statep & NFSSTA_RCVLOCK) {
- if (nfs_sigintr(rep->r_nmp, rep,
- (rep->r_td ? rep->r_td->td_proc : NULL)))
- return (EINTR);
- *statep |= NFSSTA_WANTRCV;
- (void) tsleep((caddr_t)statep, slpflag | (PZERO - 1), "nfsrcvlk",
- slptimeo);
- /*
- * If our reply was recieved while we were sleeping,
- * then just return without taking the lock to avoid a
- * situation where a single iod could 'capture' the
- * recieve lock.
- */
- if (rep->r_mrep != NULL)
- return (EALREADY);
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- *statep |= NFSSTA_RCVLOCK;
- return (0);
+ nfsrvstats.srvrpc_errs++;
}
-/*
- * Unlock the stream socket for others.
- */
-static void
-nfs_rcvunlock(rep)
- register struct nfsreq *rep;
-{
- register int *statep = &rep->r_nmp->nm_state;
-
- if ((*statep & NFSSTA_RCVLOCK) == 0)
- panic("nfs rcvunlock");
- *statep &= ~NFSSTA_RCVLOCK;
- if (*statep & NFSSTA_WANTRCV) {
- *statep &= ~NFSSTA_WANTRCV;
- wakeup((caddr_t)statep);
- }
-}
/*
* nfs_realign:
@@ -1679,16 +239,13 @@ nfs_rcvunlock(rep)
* with TCP. Use vfs.nfs.realign_count and realign_test to check this.
*/
static void
-nfs_realign(pm, hsiz)
- register struct mbuf **pm;
- int hsiz;
+nfs_realign(struct mbuf **pm, int hsiz) /* XXX COMMON */
{
struct mbuf *m;
struct mbuf *n = NULL;
int off = 0;
++nfs_realign_test;
-
while ((m = *pm) != NULL) {
if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
MGET(n, M_TRYWAIT, MT_DATA);
@@ -1717,7 +274,6 @@ nfs_realign(pm, hsiz)
}
}
-#ifndef NFS_NOSERVER
/*
* Parse an RPC request
@@ -1725,26 +281,14 @@ nfs_realign(pm, hsiz)
* - fill in the cred struct.
*/
int
-nfs_getreq(nd, nfsd, has_header)
- register struct nfsrv_descript *nd;
- struct nfsd *nfsd;
- int has_header;
+nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
{
- register int len, i;
- register u_int32_t *tl;
- register int32_t t1;
- struct uio uio;
- struct iovec iov;
- caddr_t dpos, cp2, cp;
+ int len, i;
+ u_int32_t *tl;
+ caddr_t dpos;
u_int32_t nfsvers, auth_type;
- uid_t nickuid;
- int error = 0, nqnfs = 0, ticklen;
+ int error = 0;
struct mbuf *mrep, *md;
- register struct nfsuid *nuidp;
- struct timeval tvin, tvout;
-#if 0 /* until encrypted keys are implemented */
- NFSKERBKEYSCHED_T keys; /* stores key schedule */
-#endif
mrep = nd->nd_mrep;
md = nd->nd_md;
@@ -1766,38 +310,36 @@ nfs_getreq(nd, nfsd, has_header)
return (0);
}
if (*tl != nfs_prog) {
- if (*tl == nqnfs_prog)
- nqnfs++;
- else {
- nd->nd_repstat = EPROGUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
+ nd->nd_repstat = EPROGUNAVAIL;
+ nd->nd_procnum = NFSPROC_NOOP;
+ return (0);
}
tl++;
nfsvers = fxdr_unsigned(u_int32_t, *tl++);
- if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
- (nfsvers != NQNFS_VER3 && nqnfs)) {
+ if (nfsvers < NFS_VER2 || nfsvers > NFS_VER3) {
nd->nd_repstat = EPROGMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
- if (nqnfs)
- nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
- else if (nfsvers == NFS_VER3)
- nd->nd_flag = ND_NFSV3;
nd->nd_procnum = fxdr_unsigned(u_int32_t, *tl++);
if (nd->nd_procnum == NFSPROC_NULL)
return (0);
- if (nd->nd_procnum >= NFS_NPROCS ||
- (!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
- (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
- nd->nd_repstat = EPROCUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if ((nd->nd_flag & ND_NFSV3) == 0)
+ if (nfsvers == NFS_VER3) {
+ nd->nd_flag = ND_NFSV3;
+ if (nd->nd_procnum >= NFS_NPROCS) {
+ nd->nd_repstat = EPROCUNAVAIL;
+ nd->nd_procnum = NFSPROC_NOOP;
+ return (0);
+ }
+ } else {
+ if (nd->nd_procnum > NFSV2PROC_STATFS) {
+ nd->nd_repstat = EPROCUNAVAIL;
+ nd->nd_procnum = NFSPROC_NOOP;
+ return (0);
+ }
+ /* Map the v2 procedure numbers into v3 ones */
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
+ }
auth_type = *tl++;
len = fxdr_unsigned(int, *tl++);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
@@ -1805,9 +347,8 @@ nfs_getreq(nd, nfsd, has_header)
return (EBADRPC);
}
- nd->nd_flag &= ~ND_KERBAUTH;
/*
- * Handle auth_unix or auth_kerb.
+ * Handle auth_unix;
*/
if (auth_type == rpc_auth_unix) {
len = fxdr_unsigned(int, *++tl);
@@ -1842,123 +383,12 @@ nfs_getreq(nd, nfsd, has_header)
}
if (len > 0)
nfsm_adv(nfsm_rndup(len));
- } else if (auth_type == rpc_auth_kerb) {
- switch (fxdr_unsigned(int, *tl++)) {
- case RPCAKN_FULLNAME:
- ticklen = fxdr_unsigned(int, *tl);
- *((u_int32_t *)nfsd->nfsd_authstr) = *tl;
- uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
- nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
- if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
- m_freem(mrep);
- return (EBADRPC);
- }
- uio.uio_offset = 0;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_segflg = UIO_SYSSPACE;
- iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
- iov.iov_len = RPCAUTH_MAXSIZ - 4;
- nfsm_mtouio(&uio, uio.uio_resid);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
- printf("Bad kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
- tl = (u_int32_t *)cp;
- if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
- printf("Not fullname kerb verifier\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- cp += NFSX_UNSIGNED;
- bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
- nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
- nd->nd_flag |= ND_KERBFULL;
- nfsd->nfsd_flag |= NFSD_NEEDAUTH;
- break;
- case RPCAKN_NICKNAME:
- if (len != 2 * NFSX_UNSIGNED) {
- printf("Kerb nickname short\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nickuid = fxdr_unsigned(uid_t, *tl);
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (*tl++ != rpc_auth_kerb ||
- fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
- printf("Kerb nick verifier bad\n");
- nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- tvin.tv_sec = *tl++;
- tvin.tv_usec = *tl;
-
- for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nickuid &&
- (!nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nd->nd_nam2)))
- break;
- }
- if (!nuidp) {
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- /*
- * Now, decrypt the timestamp using the session key
- * and validate it.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
- tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
- if (nuidp->nu_expire < time_second ||
- nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
- (nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
- nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
- nuidp->nu_expire = 0;
- nd->nd_repstat =
- (NFSERR_AUTHERR|AUTH_REJECTVERF);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
- nd->nd_flag |= ND_KERBNICK;
- };
} else {
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
- /*
- * For nqnfs, get piggybacked lease request.
- */
- if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_flag |= fxdr_unsigned(int, *tl);
- if (nd->nd_flag & ND_LEASE) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- nd->nd_duration = fxdr_unsigned(int32_t, *tl);
- } else
- nd->nd_duration = NQ_MINLEASE;
- } else
- nd->nd_duration = NQ_MINLEASE;
nd->nd_md = md;
nd->nd_dpos = dpos;
return (0);
@@ -1966,19 +396,6 @@ nfsmout:
return (error);
}
-#endif
-
-static int
-nfs_msg(td, server, msg)
- struct thread *td;
- char *server, *msg;
-{
-
- tprintf(td->td_proc, LOG_INFO, "nfs server %s: %s\n", server, msg);
- return (0);
-}
-
-#ifndef NFS_NOSERVER
/*
* Socket upcall routine for the nfsd sockets.
* The caddr_t arg is a pointer to the "struct nfssvc_sock".
@@ -1986,13 +403,10 @@ nfs_msg(td, server, msg)
* be called with M_TRYWAIT from an nfsd.
*/
void
-nfsrv_rcv(so, arg, waitflag)
- struct socket *so;
- void *arg;
- int waitflag;
+nfsrv_rcv(struct socket *so, void *arg, int waitflag)
{
- register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
- register struct mbuf *m;
+ struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
+ struct mbuf *m;
struct mbuf *mp;
struct sockaddr *nam;
struct uio auio;
@@ -2005,7 +419,8 @@ nfsrv_rcv(so, arg, waitflag)
* Define this to test for nfsds handling this under heavy load.
*/
if (waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ; goto dorecs;
+ slp->ns_flag |= SLP_NEEDQ;
+ goto dorecs;
}
#endif
auio.uio_td = NULL;
@@ -2104,13 +519,11 @@ dorecs:
* can sleep.
*/
static int
-nfsrv_getstream(slp, waitflag)
- register struct nfssvc_sock *slp;
- int waitflag;
+nfsrv_getstream(struct nfssvc_sock *slp, int waitflag)
{
- register struct mbuf *m, **mpp;
- register char *cp1, *cp2;
- register int len;
+ struct mbuf *m, **mpp;
+ char *cp1, *cp2;
+ int len;
struct mbuf *om, *m2, *recm = NULL;
u_int32_t recmark;
@@ -2229,15 +642,13 @@ nfsrv_getstream(slp, waitflag)
* Parse an RPC header.
*/
int
-nfsrv_dorec(slp, nfsd, ndp)
- register struct nfssvc_sock *slp;
- struct nfsd *nfsd;
- struct nfsrv_descript **ndp;
+nfsrv_dorec(struct nfssvc_sock *slp, struct nfsd *nfsd,
+ struct nfsrv_descript **ndp)
{
struct nfsrv_rec *rec;
- register struct mbuf *m;
+ struct mbuf *m;
struct sockaddr *nam;
- register struct nfsrv_descript *nd;
+ struct nfsrv_descript *nd;
int error;
*ndp = NULL;
@@ -2272,14 +683,13 @@ nfsrv_dorec(slp, nfsd, ndp)
* running nfsds will go look for the work in the nfssvc_sock list.
*/
void
-nfsrv_wakenfsd(slp)
- struct nfssvc_sock *slp;
+nfsrv_wakenfsd(struct nfssvc_sock *slp)
{
- register struct nfsd *nd;
+ struct nfsd *nd;
if ((slp->ns_flag & SLP_VALID) == 0)
return;
- for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
+ TAILQ_FOREACH(nd, &nfsd_head, nfsd_chain) {
if (nd->nfsd_flag & NFSD_WAITING) {
nd->nfsd_flag &= ~NFSD_WAITING;
if (nd->nfsd_slp)
@@ -2293,4 +703,71 @@ nfsrv_wakenfsd(slp)
slp->ns_flag |= SLP_DOREC;
nfsd_head_flag |= NFSD_CHECKSLP;
}
-#endif /* NFS_NOSERVER */
+
+/*
+ * This is the nfs send routine.
+ * 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 (?)
+ */
+int
+nfsrv_send(struct socket *so, struct sockaddr *nam, struct mbuf *top)
+{
+ struct sockaddr *sendnam;
+ int error, soflags, flags;
+
+ soflags = so->so_proto->pr_flags;
+ if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
+ sendnam = (struct sockaddr *)0;
+ else
+ sendnam = nam;
+ if (so->so_type == SOCK_SEQPACKET)
+ flags = MSG_EOR;
+ else
+ flags = 0;
+
+ error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
+ flags, curthread/*XXX*/);
+ if (error == ENOBUFS && so->so_type == SOCK_DGRAM)
+ error = 0;
+
+ if (error) {
+ log(LOG_INFO, "nfsd send error %d\n", error);
+
+ /*
+ * Handle any recoverable (soft) socket errors here. (?)
+ */
+ if (error != EINTR && error != ERESTART &&
+ error != EWOULDBLOCK && error != EPIPE)
+ error = 0;
+ }
+ return (error);
+}
+
+/*
+ * Nfs timer routine
+ * Scan the nfsreq 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
+nfsrv_timer(void *arg)
+{
+ int s;
+ struct nfssvc_sock *slp;
+ u_quad_t cur_usec;
+
+ s = splnet();
+ /*
+ * Scan the write gathering queues for writes that need to be
+ * completed now.
+ */
+ cur_usec = nfs_curusec();
+ TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) {
+ if (LIST_FIRST(&slp->ns_tq) && LIST_FIRST(&slp->ns_tq)->nd_time<=cur_usec)
+ nfsrv_wakenfsd(slp);
+ }
+ splx(s);
+ nfsrv_timer_handle = timeout(nfsrv_timer, (void *)0, nfs_ticks);
+}
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 4425129..31a095f 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -37,11 +37,15 @@
* $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* These functions support the macros and help fiddle mbuf chains for
* the nfs op functions. They do things like create the rpc header and
* copy data between mbuf chains and uio lists.
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -57,6 +61,7 @@
#include <sys/malloc.h>
#include <sys/sysent.h>
#include <sys/syscall.h>
+#include <sys/sysproto.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
@@ -65,13 +70,9 @@
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsnode.h>
+#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
+#include <nfsserver/nfsm_subs.h>
#include <netinet/in.h>
@@ -81,40 +82,25 @@
*/
u_int32_t nfs_xdrneg1;
u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
- rpc_auth_kerb;
-u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false;
+ rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
+u_int32_t nfs_prog, nfs_true, nfs_false;
/* And other global data */
-static u_int32_t nfs_xid = 0;
-static enum vtype nv2tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON
-};
-enum vtype nv3tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
-};
+static nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
+ NFNON, NFCHR, NFNON };
+#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))])
+#define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS)
int nfs_ticks;
-int nfs_pbuf_freecnt = -1; /* start out unlimited */
-struct nfs_reqq nfs_reqq;
struct nfssvc_sockhead nfssvc_sockhead;
int nfssvc_sockhead_flag;
struct nfsd_head nfsd_head;
int nfsd_head_flag;
-struct nfs_bufq nfs_bufq;
-struct nqtimerhead nqtimerhead;
-struct nqfhhashhead *nqfhhashtbl;
-u_long nqfhhash;
-static void (*nfs_prev_lease_updatetime) __P((int));
static int nfs_prev_nfssvc_sy_narg;
static sy_call_t *nfs_prev_nfssvc_sy_call;
-#ifndef NFS_NOSERVER
-
-static vop_t *nfs_prev_vop_lease_check;
-
/*
* Mapping of old NFS Version 2 RPC numbers to generic numbers.
*/
@@ -142,16 +128,12 @@ int nfsv3_procid[NFS_NPROCS] = {
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP
};
-#endif /* NFS_NOSERVER */
/*
* and the reverse mapping from generic to Version 2 procedure numbers
*/
-int nfsv2_procid[NFS_NPROCS] = {
+int nfsrvv2_procid[NFS_NPROCS] = {
NFSV2PROC_NULL,
NFSV2PROC_GETATTR,
NFSV2PROC_SETATTR,
@@ -175,12 +157,8 @@ int nfsv2_procid[NFS_NPROCS] = {
NFSV2PROC_NOOP,
NFSV2PROC_NOOP,
NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
};
-#ifndef NFS_NOSERVER
/*
* Maps errno values to nfs error numbers.
* Use NFSERR_IO as the catch all for ones not specifically defined in
@@ -539,573 +517,13 @@ static short *nfsrv_v3errmap[] = {
nfsv3err_commit,
};
-#endif /* NFS_NOSERVER */
-
-extern struct nfsrtt nfsrtt;
-extern time_t nqnfsstarttime;
-extern int nqsrv_clockskew;
-extern int nqsrv_writeslack;
-extern int nqsrv_maxlease;
-extern struct nfsstats nfsstats;
-extern int nqnfs_piggy[NFS_NPROCS];
-extern nfstype nfsv2_type[9];
-extern nfstype nfsv3_type[9];
-extern struct nfsnodehashhead *nfsnodehashtbl;
-extern u_long nfsnodehash;
-
-struct nfssvc_args;
-extern int nfssvc(struct thread *, struct nfssvc_args *, int *);
-
-LIST_HEAD(nfsnodehashhead, nfsnode);
-
-int nfs_webnamei __P((struct nameidata *, struct vnode *, struct thread *));
-
-u_quad_t
-nfs_curusec()
-{
- struct timeval tv;
-
- getmicrotime(&tv);
- return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
-}
-
-/*
- * Create the header for an rpc request packet
- * The hsiz is the size of the rest of the nfs request header.
- * (just used to decide if a cluster is a good idea)
- */
-struct mbuf *
-nfsm_reqh(vp, procid, hsiz, bposp)
- struct vnode *vp;
- u_long procid;
- int hsiz;
- caddr_t *bposp;
-{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- struct mbuf *mb2;
- struct nfsmount *nmp;
- int nqflag;
-
- MGET(mb, M_TRYWAIT, MT_DATA);
- if (hsiz >= MINCLSIZE)
- MCLGET(mb, M_TRYWAIT);
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
-
- /*
- * For NQNFS, add lease request.
- */
- if (vp) {
- nmp = VFSTONFS(vp->v_mount);
- if (nmp->nm_flag & NFSMNT_NQNFS) {
- nqflag = NQNFS_NEEDLEASE(vp, procid);
- if (nqflag) {
- nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nqflag);
- *tl = txdr_unsigned(nmp->nm_leaseterm);
- } else {
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = 0;
- }
- }
- }
- /* Finally, return values */
- *bposp = bpos;
- return (mb);
-}
-
-/*
- * 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.
- * Returns the head of the mbuf list.
- */
-struct mbuf *
-nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
- verf_str, mrest, mrest_len, mbp, xidp)
- register struct ucred *cr;
- int nmflag;
- int procid;
- int auth_type;
- int auth_len;
- char *auth_str;
- int verf_len;
- char *verf_str;
- struct mbuf *mrest;
- int mrest_len;
- struct mbuf **mbp;
- u_int32_t *xidp;
-{
- register struct mbuf *mb;
- register u_int32_t *tl;
- register caddr_t bpos;
- register int i;
- struct mbuf *mreq, *mb2;
- int siz, grpsiz, authsiz;
-
- authsiz = nfsm_rndup(auth_len);
- MGETHDR(mb, M_TRYWAIT, MT_DATA);
- if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
- MCLGET(mb, M_TRYWAIT);
- } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
- MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
- } else {
- MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
- }
- mb->m_len = 0;
- mreq = mb;
- bpos = mtod(mb, caddr_t);
-
- /*
- * First the RPC header.
- */
- nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
-
- /* Get a pretty random xid to start with */
- if (!nfs_xid)
- nfs_xid = random();
- /*
- * Skip zero xid if it should ever happen.
- */
- if (++nfs_xid == 0)
- nfs_xid++;
-
- *tl++ = *xidp = txdr_unsigned(nfs_xid);
- *tl++ = rpc_call;
- *tl++ = rpc_vers;
- if (nmflag & NFSMNT_NQNFS) {
- *tl++ = txdr_unsigned(NQNFS_PROG);
- *tl++ = txdr_unsigned(NQNFS_VER3);
- } else {
- *tl++ = txdr_unsigned(NFS_PROG);
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(NFS_VER3);
- else
- *tl++ = txdr_unsigned(NFS_VER2);
- }
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(procid);
- else
- *tl++ = txdr_unsigned(nfsv2_procid[procid]);
-
- /*
- * And then the authorization cred.
- */
- *tl++ = txdr_unsigned(auth_type);
- *tl = txdr_unsigned(authsiz);
- switch (auth_type) {
- case RPCAUTH_UNIX:
- nfsm_build(tl, u_int32_t *, auth_len);
- *tl++ = 0; /* stamp ?? */
- *tl++ = 0; /* NULL hostname */
- *tl++ = txdr_unsigned(cr->cr_uid);
- *tl++ = txdr_unsigned(cr->cr_groups[0]);
- grpsiz = (auth_len >> 2) - 5;
- *tl++ = txdr_unsigned(grpsiz);
- for (i = 1; i <= grpsiz; i++)
- *tl++ = txdr_unsigned(cr->cr_groups[i]);
- break;
- case RPCAUTH_KERB4:
- siz = auth_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(auth_str, bpos, i);
- mb->m_len += i;
- auth_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- break;
- };
-
- /*
- * And the verifier...
- */
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (verf_str) {
- *tl++ = txdr_unsigned(RPCAUTH_KERB4);
- *tl = txdr_unsigned(verf_len);
- siz = verf_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_TRYWAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_TRYWAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(verf_str, bpos, i);
- mb->m_len += i;
- verf_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- } else {
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
- }
- mb->m_next = mrest;
- mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
- mreq->m_pkthdr.rcvif = (struct ifnet *)0;
- *mbp = mb;
- return (mreq);
-}
-
-/*
- * copies mbuf chain to the uio scatter/gather list
- */
-int
-nfsm_mbuftouio(mrep, uiop, siz, dpos)
- struct mbuf **mrep;
- register struct uio *uiop;
- int siz;
- caddr_t *dpos;
-{
- register char *mbufcp, *uiocp;
- register int xfer, left, len;
- register struct mbuf *mp;
- long uiosiz, rem;
- int error = 0;
-
- mp = *mrep;
- mbufcp = *dpos;
- len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
- rem = nfsm_rndup(siz)-siz;
- while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EFBIG);
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- while (len == 0) {
- mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- mbufcp = mtod(mp, caddr_t);
- len = mp->m_len;
- }
- xfer = (left > len) ? len : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (mbufcp, uiocp, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(mbufcp, uiocp, xfer);
- else
- copyout(mbufcp, uiocp, xfer);
- left -= xfer;
- len -= xfer;
- mbufcp += xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- if (uiop->uio_iov->iov_len <= siz) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- }
- siz -= uiosiz;
- }
- *dpos = mbufcp;
- *mrep = mp;
- if (rem > 0) {
- if (len < rem)
- error = nfs_adv(mrep, dpos, rem, len);
- else
- *dpos += rem;
- }
- return (error);
-}
-
-/*
- * copies a uio scatter/gather list to an mbuf chain.
- * NOTE: can ony handle iovcnt == 1
- */
-int
-nfsm_uiotombuf(uiop, mq, siz, bpos)
- register struct uio *uiop;
- struct mbuf **mq;
- int siz;
- caddr_t *bpos;
-{
- register char *uiocp;
- register struct mbuf *mp, *mp2;
- register int xfer, left, mlen;
- int uiosiz, clflg, rem;
- char *cp;
-
-#ifdef DIAGNOSTIC
- if (uiop->uio_iovcnt != 1)
- panic("nfsm_uiotombuf: iovcnt != 1");
-#endif
-
- if (siz > MLEN) /* or should it >= MCLBYTES ?? */
- clflg = 1;
- else
- clflg = 0;
- rem = nfsm_rndup(siz)-siz;
- mp = mp2 = *mq;
- while (siz > 0) {
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- mlen = M_TRAILINGSPACE(mp);
- if (mlen == 0) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- if (clflg)
- MCLGET(mp, M_TRYWAIT);
- mp->m_len = 0;
- mp2->m_next = mp;
- mp2 = mp;
- mlen = M_TRAILINGSPACE(mp);
- }
- xfer = (left > mlen) ? mlen : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
- copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- mp->m_len += xfer;
- left -= xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- uiop->uio_iov->iov_base += uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- siz -= uiosiz;
- }
- if (rem > 0) {
- if (rem > M_TRAILINGSPACE(mp)) {
- MGET(mp, M_TRYWAIT, MT_DATA);
- mp->m_len = 0;
- mp2->m_next = mp;
- }
- cp = mtod(mp, caddr_t)+mp->m_len;
- for (left = 0; left < rem; left++)
- *cp++ = '\0';
- mp->m_len += rem;
- *bpos = cp;
- } else
- *bpos = mtod(mp, caddr_t)+mp->m_len;
- *mq = mp;
- return (0);
-}
-
-/*
- * Help break down an mbuf chain by setting the first siz bytes contiguous
- * pointed to by returned val.
- * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
- * cases. (The macros use the vars. dpos and dpos2)
- */
-int
-nfsm_disct(mdp, dposp, siz, left, cp2)
- struct mbuf **mdp;
- caddr_t *dposp;
- int siz;
- int left;
- caddr_t *cp2;
-{
- register struct mbuf *mp, *mp2;
- register int siz2, xfer;
- register caddr_t ptr;
-
- mp = *mdp;
- while (left == 0) {
- *mdp = mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- left = mp->m_len;
- *dposp = mtod(mp, caddr_t);
- }
- if (left >= siz) {
- *cp2 = *dposp;
- *dposp += siz;
- } else if (mp->m_next == NULL) {
- return (EBADRPC);
- } else if (siz > MHLEN) {
- panic("nfs S too big");
- } else {
- MGET(mp2, M_TRYWAIT, MT_DATA);
- mp2->m_next = mp->m_next;
- mp->m_next = mp2;
- mp->m_len -= left;
- mp = mp2;
- *cp2 = ptr = mtod(mp, caddr_t);
- bcopy(*dposp, ptr, left); /* Copy what was left */
- siz2 = siz-left;
- ptr += left;
- mp2 = mp->m_next;
- /* Loop around copying up the siz2 bytes */
- while (siz2 > 0) {
- if (mp2 == NULL)
- return (EBADRPC);
- xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
- if (xfer > 0) {
- bcopy(mtod(mp2, caddr_t), ptr, xfer);
- NFSMADV(mp2, xfer);
- mp2->m_len -= xfer;
- ptr += xfer;
- siz2 -= xfer;
- }
- if (siz2 > 0)
- mp2 = mp2->m_next;
- }
- mp->m_len = siz;
- *mdp = mp2;
- *dposp = mtod(mp2, caddr_t);
- }
- return (0);
-}
-
-/*
- * Advance the position in the mbuf chain.
- */
-int
-nfs_adv(mdp, dposp, offs, left)
- struct mbuf **mdp;
- caddr_t *dposp;
- int offs;
- int left;
-{
- register struct mbuf *m;
- register int s;
-
- m = *mdp;
- s = left;
- while (s < offs) {
- offs -= s;
- m = m->m_next;
- if (m == NULL)
- return (EBADRPC);
- s = m->m_len;
- }
- *mdp = m;
- *dposp = mtod(m, caddr_t)+offs;
- return (0);
-}
-
-/*
- * Copy a string into mbufs for the hard cases...
- */
-int
-nfsm_strtmbuf(mb, bpos, cp, siz)
- struct mbuf **mb;
- char **bpos;
- const char *cp;
- long siz;
-{
- register struct mbuf *m1 = NULL, *m2;
- long left, xfer, len, tlen;
- u_int32_t *tl;
- int putsize;
-
- putsize = 1;
- m2 = *mb;
- left = M_TRAILINGSPACE(m2);
- if (left > 0) {
- tl = ((u_int32_t *)(*bpos));
- *tl++ = txdr_unsigned(siz);
- putsize = 0;
- left -= NFSX_UNSIGNED;
- m2->m_len += NFSX_UNSIGNED;
- if (left > 0) {
- bcopy(cp, (caddr_t) tl, left);
- siz -= left;
- cp += left;
- m2->m_len += left;
- left = 0;
- }
- }
- /* Loop around adding mbufs */
- while (siz > 0) {
- MGET(m1, M_TRYWAIT, MT_DATA);
- if (siz > MLEN)
- MCLGET(m1, M_TRYWAIT);
- m1->m_len = NFSMSIZ(m1);
- m2->m_next = m1;
- m2 = m1;
- tl = mtod(m1, u_int32_t *);
- tlen = 0;
- if (putsize) {
- *tl++ = txdr_unsigned(siz);
- m1->m_len -= NFSX_UNSIGNED;
- tlen = NFSX_UNSIGNED;
- putsize = 0;
- }
- if (siz < m1->m_len) {
- len = nfsm_rndup(siz);
- xfer = siz;
- if (xfer < len)
- *(tl+(xfer>>2)) = 0;
- } else {
- xfer = len = m1->m_len;
- }
- bcopy(cp, (caddr_t) tl, xfer);
- m1->m_len = len+tlen;
- siz -= xfer;
- cp += xfer;
- }
- *mb = m1;
- *bpos = mtod(m1, caddr_t)+m1->m_len;
- return (0);
-}
-
/*
* Called once to initialize data structures...
*/
-int
-nfs_init(vfsp)
- struct vfsconf *vfsp;
+static int
+nfs_init(void *dummy __unused)
{
- register int i;
-
- nfsmount_zone = zinit("NFSMOUNT", sizeof(struct nfsmount), 0, 0, 1);
- nfs_mount_type = vfsp->vfc_typenum;
- nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
rpc_reply = txdr_unsigned(RPC_REPLY);
@@ -1114,340 +532,40 @@ nfs_init(vfsp)
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);
nfs_prog = txdr_unsigned(NFS_PROG);
- nqnfs_prog = txdr_unsigned(NQNFS_PROG);
nfs_true = txdr_unsigned(TRUE);
nfs_false = txdr_unsigned(FALSE);
nfs_xdrneg1 = txdr_unsigned(-1);
nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
if (nfs_ticks < 1)
nfs_ticks = 1;
- /* Ensure async daemons disabled */
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
- nfs_iodwant[i] = (struct proc *)0;
- nfs_iodmount[i] = (struct nfsmount *)0;
- }
- nfs_nhinit(); /* Init the nfsnode table */
-#ifndef NFS_NOSERVER
+
nfsrv_init(0); /* Init server data structures */
nfsrv_initcache(); /* Init the server request cache */
-#endif
-
- /*
- * Initialize the nqnfs server stuff.
- */
- if (nqnfsstarttime == 0) {
- nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
- + nqsrv_clockskew + nqsrv_writeslack;
- NQLOADNOVRAM(nqnfsstarttime);
- TAILQ_INIT(&nqtimerhead);
- nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
- }
- /*
- * Initialize reply list and start timer
- */
- TAILQ_INIT(&nfs_reqq);
-
- nfs_timer(0);
+ nfsrv_timer(0);
- /*
- * Set up lease_check and lease_updatetime so that other parts
- * of the system can call us, if we are loadable.
- */
-#ifndef NFS_NOSERVER
- nfs_prev_vop_lease_check = default_vnodeop_p[VOFFSET(vop_lease)];
- default_vnodeop_p[VOFFSET(vop_lease)] = (vop_t *)nqnfs_vop_lease_check;
-#endif
- nfs_prev_lease_updatetime = lease_updatetime;
- lease_updatetime = nfs_lease_updatetime;
nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
sysent[SYS_nfssvc].sy_narg = 2;
nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call;
sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc;
- nfs_pbuf_freecnt = nswbuf / 2 + 1;
-
return (0);
}
+SYSINIT(nfs, SI_SUB_VFS, SI_ORDER_ANY, nfs_init, NULL);
-int
-nfs_uninit(vfsp)
- struct vfsconf *vfsp;
+static int
+nfs_uninit(void *dummy __unused)
{
- untimeout(nfs_timer, (void *)NULL, nfs_timer_handle);
- nfs_mount_type = -1;
-#ifndef NFS_NOSERVER
- default_vnodeop_p[VOFFSET(vop_lease)] = nfs_prev_vop_lease_check;
-#endif
- lease_updatetime = nfs_prev_lease_updatetime;
+ untimeout(nfsrv_timer, (void *)NULL, nfsrv_timer_handle);
sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
return (0);
}
+SYSUNINIT(nfs, SI_SUB_VFS, SI_ORDER_ANY, nfs_uninit, NULL);
/*
- * Attribute cache routines.
- * nfs_loadattrcache() - loads or updates the cache contents from attributes
- * that are on the mbuf list
- * nfs_getattrcache() - returns valid attributes if found in cache, returns
- * error otherwise
- */
-
-/*
- * Load the attribute cache (that lives in the nfsnode entry) with
- * the values on the mbuf list and
- * Iff vap not NULL
- * copy the attributes to *vaper
- */
-int
-nfs_loadattrcache(vpp, mdp, dposp, vaper, dontshrink)
- struct vnode **vpp;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vattr *vaper;
- int dontshrink;
-{
- register struct vnode *vp = *vpp;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
- register struct nfsnode *np;
- register int32_t t1;
- caddr_t cp2;
- int error = 0, rdev;
- struct mbuf *md;
- enum vtype vtyp;
- u_short vmode;
- struct timespec mtime;
- int v3 = NFS_ISV3(vp);
-
- md = *mdp;
- t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
- if ((error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)) != 0)
- return (error);
- fp = (struct nfs_fattr *)cp2;
- if (v3) {
- vtyp = nfsv3tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- rdev = makeudev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
- fxdr_unsigned(int, fp->fa3_rdev.specdata2));
- fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
- } else {
- vtyp = nfsv2tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- /*
- * XXX
- *
- * The duplicate information returned in fa_type and fa_mode
- * is an ambiguity in the NFS version 2 protocol.
- *
- * VREG should be taken literally as a regular file. If a
- * server intents to return some type information differently
- * in the upper bits of the mode field (e.g. for sockets, or
- * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
- * leave the examination of the mode bits even in the VREG
- * case to avoid breakage for bogus servers, but we make sure
- * that there are actually type bits set in the upper part of
- * fa_mode (and failing that, trust the va_type field).
- *
- * NFSv3 cleared the issue, and requires fa_mode to not
- * contain any type information (while also introduing sockets
- * and FIFOs for fa_type).
- */
- if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
- vtyp = IFTOVT(vmode);
- rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
- fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
-
- /*
- * Really ugly NFSv2 kludge.
- */
- if (vtyp == VCHR && rdev == 0xffffffff)
- vtyp = VFIFO;
- }
-
- /*
- * 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);
- if (vp->v_type != vtyp) {
- vp->v_type = vtyp;
- if (vp->v_type == VFIFO) {
- vp->v_op = fifo_nfsv2nodeop_p;
- }
- if (vp->v_type == VCHR || vp->v_type == VBLK) {
- vp->v_op = spec_nfsv2nodeop_p;
- vp = addaliasu(vp, rdev);
- np->n_vnode = vp;
- }
- np->n_mtime = mtime.tv_sec;
- }
- vap = &np->n_vattr;
- 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 (v3) {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_hyper(&fp->fa3_size);
- vap->va_blocksize = NFS_FABLKSIZE;
- vap->va_bytes = fxdr_hyper(&fp->fa3_used);
- vap->va_fileid = fxdr_unsigned(int32_t,
- fp->fa3_fileid.nfsuquad[1]);
- fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
- fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
- vap->va_flags = 0;
- vap->va_filerev = 0;
- } else {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
- vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
- vap->va_bytes = (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks)
- * NFS_FABLKSIZE;
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
- fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
- vap->va_flags = 0;
- vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
- fp->fa2_ctime.nfsv2_sec);
- vap->va_ctime.tv_nsec = 0;
- vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
- vap->va_filerev = 0;
- }
- np->n_attrstamp = time_second;
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (dontshrink && vap->va_size < np->n_size) {
- /*
- * We've been told not to shrink the file;
- * zero np->n_attrstamp to indicate that
- * the attributes are stale.
- */
- vap->va_size = np->n_size;
- np->n_attrstamp = 0;
- } else 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;
- }
- }
- 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;
- }
- }
- return (0);
-}
-
-#ifdef NFS_ACDEBUG
-#include <sys/sysctl.h>
-SYSCTL_DECL(_vfs_nfs);
-static int nfs_acdebug;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, acdebug, CTLFLAG_RW, &nfs_acdebug, 0, "");
-#endif
-
-/*
- * Check the time stamp
- * If the cache is valid, copy contents to *vap and return 0
- * otherwise return an error
- */
-int
-nfs_getattrcache(vp, vaper)
- register struct vnode *vp;
- struct vattr *vaper;
-{
- register struct nfsnode *np;
- register struct vattr *vap;
- struct nfsmount *nmp;
- int timeo;
-
- np = VTONFS(vp);
- vap = &np->n_vattr;
- nmp = VFSTONFS(vp->v_mount);
- /* XXX n_mtime doesn't seem to be updated on a miss-and-reload */
- timeo = (time_second - np->n_mtime) / 10;
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug>1)
- printf("nfs_getattrcache: initial timeo = %d\n", timeo);
-#endif
-
- if (vap->va_type == VDIR) {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acdirmin)
- timeo = nmp->nm_acdirmin;
- else if (timeo > nmp->nm_acdirmax)
- timeo = nmp->nm_acdirmax;
- } else {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acregmin)
- timeo = nmp->nm_acregmin;
- else if (timeo > nmp->nm_acregmax)
- timeo = nmp->nm_acregmax;
- }
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug > 2)
- printf("acregmin %d; acregmax %d; acdirmin %d; acdirmax %d\n",
- nmp->nm_acregmin, nmp->nm_acregmax,
- nmp->nm_acdirmin, nmp->nm_acdirmax);
-
- if (nfs_acdebug)
- printf("nfs_getattrcache: age = %d; final timeo = %d\n",
- (time_second - np->n_attrstamp), timeo);
-#endif
-
- if ((time_second - np->n_attrstamp) >= timeo) {
- nfsstats.attrcache_misses++;
- return (ENOENT);
- }
- nfsstats.attrcache_hits++;
- 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;
- }
- }
- bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
- 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;
- }
- return (0);
-}
-
-#ifndef NFS_NOSERVER
-/*
* Set up nameidata for a lookup() call and do it.
*
* If pubflag is set, this call is done for a lookup operation on the
@@ -1460,25 +578,17 @@ nfs_getattrcache(vp, vaper)
* This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
* error occurs but the parent was not requested.
*
- * dirp may be set whether an error is returned or not, and must be
+ * dirp may be set whether an error is returned or not, and must be
* released by the caller.
*/
int
-nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
- register struct nameidata *ndp;
- fhandle_t *fhp;
- int len;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- struct mbuf **mdp;
- caddr_t *dposp;
- struct vnode **retdirp;
- struct thread *td;
- int kerbflag, pubflag;
+nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
+ struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp,
+ caddr_t *dposp, struct vnode **retdirp, struct thread *td, int pubflag)
{
- register int i, rem;
- register struct mbuf *md;
- register char *fromcp, *tocp, *cp;
+ int i, rem;
+ struct mbuf *md;
+ char *fromcp, *tocp, *cp;
struct iovec aiov;
struct uio auio;
struct vnode *dp;
@@ -1528,7 +638,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
* Extract and set starting directory.
*/
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly, kerbflag, pubflag);
+ nam, &rdonly, pubflag);
if (error)
goto out;
if (dp->v_type != VDIR) {
@@ -1541,7 +651,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
cnp->cn_flags |= RDONLY;
/*
- * Set return directory. Reference to dp is implicitly transfered
+ * Set return directory. Reference to dp is implicitly transfered
* to the returned pointer
*/
*retdirp = dp;
@@ -1631,7 +741,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
break;
/*
- * Check for encountering a symbolic link. Trivial
+ * Check for encountering a symbolic link. Trivial
* termination occurs if no symlink encountered.
* Note: zfree is safe because error is 0, so we will
* not zfree it again when we break.
@@ -1704,8 +814,8 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, td, kerbflag, pubflag)
ndp->ni_pathlen += linklen;
/*
- * Cleanup refs for next loop and check if root directory
- * should replace current directory. Normally ni_dvp
+ * Cleanup refs for next loop and check if root directory
+ * should replace current directory. Normally ni_dvp
* becomes the new base directory and is cleaned up when
* we loop. Explicitly null pointers after invalidation
* to clarify operation.
@@ -1745,14 +855,11 @@ out:
* boundary and only trims off the back end
*/
void
-nfsm_adj(mp, len, nul)
- struct mbuf *mp;
- register int len;
- int nul;
+nfsm_adj(struct mbuf *mp, int len, int nul)
{
- register struct mbuf *m;
- register int count, i;
- register char *cp;
+ struct mbuf *m;
+ int count, i;
+ char *cp;
/*
* Trim from tail. Scan the mbuf chain,
@@ -1807,18 +914,13 @@ nfsm_adj(mp, len, nul)
* doesn't get too big...
*/
void
-nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int before_ret;
- register struct vattr *before_vap;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
+nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
+ struct vattr *before_vap, int after_ret, struct vattr *after_vap,
+ struct mbuf **mbp, char **bposp)
{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
+ struct mbuf *mb = *mbp;
+ char *bpos = *bposp;
+ u_int32_t *tl;
if (before_ret) {
nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
@@ -1838,17 +940,13 @@ nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
}
void
-nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
- struct nfsrv_descript *nfsd;
- int after_ret;
- struct vattr *after_vap;
- struct mbuf **mbp;
- char **bposp;
+nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
+ struct vattr *after_vap, struct mbuf **mbp, char **bposp)
{
- register struct mbuf *mb = *mbp, *mb2;
- register char *bpos = *bposp;
- register u_int32_t *tl;
- register struct nfs_fattr *fp;
+ struct mbuf *mb = *mbp;
+ char *bpos = *bposp;
+ u_int32_t *tl;
+ struct nfs_fattr *fp;
if (after_ret) {
nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
@@ -1864,10 +962,8 @@ nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
}
void
-nfsm_srvfattr(nfsd, vap, fp)
- register struct nfsrv_descript *nfsd;
- register struct vattr *vap;
- register struct nfs_fattr *fp;
+nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
+ struct nfs_fattr *fp)
{
fp->fa_nlink = txdr_unsigned(vap->va_nlink);
@@ -1913,20 +1009,13 @@ nfsm_srvfattr(nfsd, vap, fp)
* - if not lockflag unlock it with VOP_UNLOCK()
*/
int
-nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
- fhandle_t *fhp;
- int lockflag;
- struct vnode **vpp;
- struct ucred *cred;
- struct nfssvc_sock *slp;
- struct sockaddr *nam;
- int *rdonlyp;
- int kerbflag;
- int pubflag;
+nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
+ struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam,
+ int *rdonlyp, int pubflag)
{
struct thread *td = curthread; /* XXX */
- register struct mount *mp;
- register int i;
+ struct mount *mp;
+ int i;
struct ucred *credanon;
int error, exflags;
#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
@@ -1946,7 +1035,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
return (ESTALE);
error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
if (error)
- return (error);
+ return (error);
error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
if (error)
return (error);
@@ -1964,17 +1053,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
/*
* Check/setup credentials.
*/
- if (exflags & MNT_EXKERB) {
- if (!kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
- } else if (kerbflag) {
- vput(*vpp);
- *vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
+ if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
cred->cr_uid = credanon->cr_uid;
for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
cred->cr_groups[i] = credanon->cr_groups[i];
@@ -1999,8 +1078,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
* transformed this to all zeroes in both cases, so check for it.
*/
int
-nfs_ispublicfh(fhp)
- fhandle_t *fhp;
+nfs_ispublicfh(fhandle_t *fhp)
{
char *cp = (char *)fhp;
int i;
@@ -2010,8 +1088,7 @@ nfs_ispublicfh(fhp)
return (FALSE);
return (TRUE);
}
-
-#endif /* NFS_NOSERVER */
+
/*
* This function compares two net addresses by family and returns TRUE
* if they are the same host.
@@ -2020,12 +1097,9 @@ nfs_ispublicfh(fhp)
* don't need to be saved to store "struct in_addr", which is only 4 bytes.
*/
int
-netaddr_match(family, haddr, nam)
- int family;
- union nethostaddr *haddr;
- struct sockaddr *nam;
+netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
{
- register struct sockaddr_in *inetaddr;
+ struct sockaddr_in *inetaddr;
switch (family) {
case AF_INET:
@@ -2040,136 +1114,14 @@ netaddr_match(family, haddr, nam)
return (0);
}
-static nfsuint64 nfs_nullcookie = { { 0, 0 } };
-/*
- * This function finds the directory cookie that corresponds to the
- * logical byte offset given.
- */
-nfsuint64 *
-nfs_getcookie(np, off, add)
- register struct nfsnode *np;
- off_t off;
- int add;
-{
- register struct nfsdmap *dp, *dp2;
- register 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 = np->n_cookies.lh_first;
- if (!dp) {
- if (add) {
- MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp->ndm_eocookie = 0;
- LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
- } else
- return ((nfsuint64 *)0);
- }
- while (pos >= NFSNUMCOOKIES) {
- pos -= NFSNUMCOOKIES;
- if (dp->ndm_list.le_next) {
- if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
- pos >= dp->ndm_eocookie)
- return ((nfsuint64 *)0);
- dp = dp->ndm_list.le_next;
- } else if (add) {
- MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp2->ndm_eocookie = 0;
- LIST_INSERT_AFTER(dp, dp2, ndm_list);
- dp = dp2;
- } else
- return ((nfsuint64 *)0);
- }
- if (pos >= dp->ndm_eocookie) {
- if (add)
- dp->ndm_eocookie = pos + 1;
- else
- return ((nfsuint64 *)0);
- }
- return (&dp->ndm_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
-nfs_invaldir(vp)
- register struct vnode *vp;
-{
- register struct nfsnode *np = VTONFS(vp);
-
-#ifdef DIAGNOSTIC
- if (vp->v_type != VDIR)
- panic("nfs: invaldir not dir");
-#endif
- np->n_direofoffset = 0;
- np->n_cookieverf.nfsuquad[0] = 0;
- np->n_cookieverf.nfsuquad[1] = 0;
- if (np->n_cookies.lh_first)
- np->n_cookies.lh_first->ndm_eocookie = 0;
-}
-
-/*
- * The write verifier has changed (probably due to a server reboot), so all
- * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
- * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
- * and B_CLUSTEROK flags. Once done the new write verifier can be set for the
- * mount point.
- *
- * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data
- * writes are not clusterable.
- */
-void
-nfs_clearcommit(mp)
- struct mount *mp;
-{
- register struct vnode *vp, *nvp;
- register struct buf *bp, *nbp;
- int s;
-
- GIANT_REQUIRED;
-
- s = splbio();
- mtx_lock(&mntvnode_mtx);
-loop:
- for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
- if (vp->v_mount != mp) /* Paranoia */
- goto loop;
- nvp = LIST_NEXT(vp, v_mntvnodes);
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if (BUF_REFCNT(bp) == 0 &&
- (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
- == (B_DELWRI | B_NEEDCOMMIT))
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- }
- }
- mtx_unlock(&mntvnode_mtx);
- splx(s);
-}
-
-#ifndef NFS_NOSERVER
/*
* Map errnos to NFS error numbers. For Version 3 also filter out error
* numbers not specified for the associated procedure.
*/
int
-nfsrv_errmap(nd, err)
- struct nfsrv_descript *nd;
- register int err;
+nfsrv_errmap(struct nfsrv_descript *nd, int err)
{
- register short *defaulterrp, *errp;
+ short *defaulterrp, *errp;
if (nd->nd_flag & ND_NFSV3) {
if (nd->nd_procnum <= NFSPROC_COMMIT) {
@@ -2190,8 +1142,7 @@ nfsrv_errmap(nd, err)
}
int
-nfsrv_object_create(vp)
- struct vnode *vp;
+nfsrv_object_create(struct vnode *vp)
{
if (vp == NULL || vp->v_type != VREG)
@@ -2206,11 +1157,9 @@ nfsrv_object_create(vp)
* that used to be here.)
*/
void
-nfsrvw_sort(list, num)
- register gid_t *list;
- register int num;
+nfsrvw_sort(gid_t *list, int num)
{
- register int i, j;
+ int i, j;
gid_t v;
/* Insertion sort. */
@@ -2227,10 +1176,9 @@ nfsrvw_sort(list, num)
* copy credentials making sure that the result can be compared with bcmp().
*/
void
-nfsrv_setcred(incred, outcred)
- register struct ucred *incred, *outcred;
+nfsrv_setcred(struct ucred *incred, struct ucred *outcred)
{
- register int i;
+ int i;
bzero((caddr_t)outcred, sizeof (struct ucred));
outcred->cr_ref = 1;
@@ -2240,4 +1188,207 @@ nfsrv_setcred(incred, outcred)
outcred->cr_groups[i] = incred->cr_groups[i];
nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
}
-#endif /* NFS_NOSERVER */
+
+/*
+ * Helper functions for macros.
+ */
+
+void
+nfsm_srvfhtom_xx(fhandle_t *f, int v3,
+ u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
+{
+ u_int32_t *cp;
+
+ if (v3) {
+ nfsm_build_xx((void **)tl, NFSX_UNSIGNED + NFSX_V3FH, mb,
+ bpos);
+ *(*tl)++ = txdr_unsigned(NFSX_V3FH);
+ bcopy(f, (*tl), NFSX_V3FH);
+ } else {
+ nfsm_build_xx((void **)&cp, NFSX_V2FH, mb, bpos);
+ bcopy(f, cp, NFSX_V2FH);
+ }
+}
+
+void
+nfsm_srvpostop_fh_xx(fhandle_t *f,
+ u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
+{
+ nfsm_build_xx((void **)tl, 2 * NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
+ *(*tl)++ = nfs_true;
+ *(*tl)++ = txdr_unsigned(NFSX_V3FH);
+ bcopy(f, (*tl), NFSX_V3FH);
+}
+
+int
+nfsm_srvstrsiz_xx(int *s, int m,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int ret;
+
+ ret = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (ret)
+ return ret;
+ *s = fxdr_unsigned(int32_t, **tl);
+ if (*s > m || *s <= 0)
+ return EBADRPC;
+ return 0;
+}
+
+int
+nfsm_srvnamesiz_xx(int *s,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int ret;
+
+ ret = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (ret)
+ return ret;
+ *s = fxdr_unsigned(int32_t, **tl);
+ if (*s > NFS_MAXNAMLEN)
+ return NFSERR_NAMETOL;
+ if (*s <= 0)
+ return EBADRPC;
+ return 0;
+}
+
+void
+nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
+ char **bp, char **be, caddr_t bpos)
+{
+ struct mbuf *nmp;
+
+ if (*bp >= *be) {
+ if (*mp == mb)
+ (*mp)->m_len += *bp - bpos;
+ MGET(nmp, M_TRYWAIT, MT_DATA);
+ MCLGET(nmp, M_TRYWAIT);
+ nmp->m_len = NFSMSIZ(nmp);
+ (*mp)->m_next = nmp;
+ *mp = nmp;
+ *bp = mtod(*mp, caddr_t);
+ *be = *bp + (*mp)->m_len;
+ }
+ *tl = (u_int32_t *)*bp;
+}
+
+int
+nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int error;
+ int fhlen;
+
+ if (nfsd->nd_flag & ND_NFSV3) {
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ return error;
+ fhlen = fxdr_unsigned(int, **tl);
+ if (fhlen != 0 && fhlen != NFSX_V3FH)
+ return EBADRPC;
+ } else {
+ fhlen = NFSX_V2FH;
+ }
+ if (fhlen != 0) {
+ error = nfsm_dissect_xx((void **)tl, fhlen, md, dpos);
+ if (error)
+ return error;
+ bcopy((caddr_t)*tl, (caddr_t)(f), fhlen);
+ } else {
+ bzero((caddr_t)(f), NFSX_V3FH);
+ }
+ return 0;
+}
+
+int
+nfsm_srvsattr_xx(struct vattr *a,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
+{
+ int error = 0;
+
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ if (**tl == nfs_true) {
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ (a)->va_mode = nfstov_mode(**tl);
+ }
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ if (**tl == nfs_true) {
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ (a)->va_uid = fxdr_unsigned(uid_t, **tl);
+ }
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ if (**tl == nfs_true) {
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ (a)->va_gid = fxdr_unsigned(gid_t, **tl);
+ }
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ if (**tl == nfs_true) {
+ error = nfsm_dissect_xx((void **)tl, 2 * NFSX_UNSIGNED,
+ md, dpos);
+ if (error)
+ goto bugout;
+ (a)->va_size = fxdr_hyper(*tl);
+ }
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ switch (fxdr_unsigned(int, **tl)) {
+ case NFSV3SATTRTIME_TOCLIENT:
+ error = nfsm_dissect_xx((void **)tl, 2 * NFSX_UNSIGNED,
+ md, dpos);
+ if (error)
+ goto bugout;
+ fxdr_nfsv3time(*tl, &(a)->va_atime);
+ break;
+ case NFSV3SATTRTIME_TOSERVER:
+ getnanotime(&(a)->va_atime);
+ break;
+ }
+ error = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, md, dpos);
+ if (error)
+ goto bugout;
+ switch (fxdr_unsigned(int, **tl)) {
+ case NFSV3SATTRTIME_TOCLIENT:
+ error = nfsm_dissect_xx((void **)tl, 2 * NFSX_UNSIGNED,
+ md, dpos);
+ if (error)
+ goto bugout;
+ fxdr_nfsv3time(*tl, &(a)->va_mtime);
+ break;
+ case NFSV3SATTRTIME_TOSERVER:
+ getnanotime(&(a)->va_mtime);
+ break;
+ }
+ return 0;
+
+bugout:
+ return error;
+}
+
+void
+nfs_rephead_xx(int s, struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ int error, struct mbuf **mrq, struct mbuf **mb,
+ struct mbuf **mreq, struct mbuf **mrep, caddr_t *bpos)
+{
+
+ nfs_rephead(s, nfsd, slp, error, mrq, mb, bpos);
+ if (*mrep != NULL) {
+ m_freem(*mrep);
+ *mrep = NULL;
+ }
+ *mreq = *mrq;
+}
diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c
index 657f299..be8fc69 100644
--- a/sys/nfsserver/nfs_syscalls.c
+++ b/sys/nfsserver/nfs_syscalls.c
@@ -37,6 +37,9 @@
* $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
@@ -64,66 +67,45 @@
#include <nfs/xdr_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
-#include <nfs/nfs.h>
-#include <nfs/nfsm_subs.h>
-#include <nfs/nfsrvcache.h>
-#include <nfs/nfsmount.h>
-#include <nfs/nfsnode.h>
-#include <nfs/nqnfs.h>
-#include <nfs/nfsrtt.h>
-#include <nfs/nfs_lock.h>
+#include <nfsserver/nfs.h>
+#include <nfsserver/nfsm_subs.h>
+#include <nfsserver/nfsrvcache.h>
static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure");
-/* Global defs. */
-extern int32_t (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct thread *td,
- struct mbuf **mreqp));
-extern int nfs_numasync;
-extern time_t nqnfsstarttime;
-extern int nqsrv_writeslack;
-extern int nfsrtton;
-extern struct nfsstats nfsstats;
-extern int nfsrvw_procrastinate;
-extern int nfsrvw_procrastinate_v3;
-static int nuidhash_max = NFS_MAXUIDHASH;
+MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
+MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
-#ifndef NFS_NOSERVER
-static void nfsrv_zapsock __P((struct nfssvc_sock *slp));
-#endif
-static int nfssvc_iod __P((struct thread *));
+
+/* Global defs. */
+struct nfsrvstats nfsrvstats;
#define TRUE 1
#define FALSE 0
-static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
+SYSCTL_DECL(_vfs_nfsrv);
-SYSCTL_DECL(_vfs_nfs);
+int nfsd_waiting = 0;
+static int nfs_numnfsd = 0;
+static int notstarted = 1;
-#ifndef NFS_NOSERVER
-int nfsd_waiting = 0;
-static struct nfsdrt nfsdrt;
-static int nfs_numnfsd = 0;
-static int notstarted = 1;
-static int modify_flag = 0;
-static void nfsd_rt __P((int sotype, struct nfsrv_descript *nd,
- int cacherep));
-static int nfssvc_addsock __P((struct file *, struct sockaddr *,
- struct thread *));
-static int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,
- struct thread *));
+static int nfs_privport = 0;
+SYSCTL_INT(_vfs_nfsrv, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW,
+ &nfs_privport, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay, CTLFLAG_RW,
+ &nfsrvw_procrastinate, 0, "");
+SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay_v3, CTLFLAG_RW,
+ &nfsrvw_procrastinate_v3, 0, "");
-static int nfs_privport = 0;
-SYSCTL_INT(_vfs_nfs, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW, &nfs_privport, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay, CTLFLAG_RW, &nfsrvw_procrastinate, 0, "");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay_v3, CTLFLAG_RW, &nfsrvw_procrastinate_v3, 0, "");
+static int nfssvc_addsock(struct file *, struct sockaddr *,
+ struct thread *);
+static void nfsrv_zapsock(struct nfssvc_sock *slp);
+static int nfssvc_nfsd(struct nfsd_srvargs *, caddr_t, struct thread *);
/*
* NFS server system calls
*/
-#endif /* NFS_NOSERVER */
/*
* Nfs server psuedo system call for the nfsd's
* Based on the flag value it either:
@@ -141,37 +123,15 @@ struct nfssvc_args {
* MPSAFE
*/
int
-nfssvc(td, uap)
- struct thread *td;
- register struct nfssvc_args *uap;
+nfssvc(struct thread *td, struct nfssvc_args *uap)
{
-#ifndef NFS_NOSERVER
- struct nameidata nd;
struct file *fp;
struct sockaddr *nam;
struct nfsd_args nfsdarg;
struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;
- struct nfsd_cargs ncd;
- struct nfsd *nfsd;
- struct nfssvc_sock *slp;
- struct nfsuid *nuidp;
- struct nfsmount *nmp;
-#endif /* NFS_NOSERVER */
int error;
mtx_lock(&Giant);
-
- if ((uap->flag & NFSSVC_LOCKDANS) != 0) {
- struct lockd_ans la;
-
- error = copyin(uap->argp, &la, sizeof(la));
- if (error == 0)
- error = nfslockdans(td->td_proc, &la);
- goto done2;
- }
- /*
- * Must be super user
- */
error = suser_td(td);
if (error)
goto done2;
@@ -179,37 +139,7 @@ nfssvc(td, uap)
nfssvc_sockhead_flag |= SLP_WANTINIT;
(void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0);
}
- if (uap->flag & NFSSVC_BIOD)
- error = nfssvc_iod(td);
-#ifdef NFS_NOSERVER
- else
- error = ENXIO;
-#else /* !NFS_NOSERVER */
- else if (uap->flag & NFSSVC_MNTD) {
- error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd));
- if (error)
- goto done2;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
- ncd.ncd_dirp, td);
- error = namei(&nd);
- if (error)
- goto done2;
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if ((nd.ni_vp->v_flag & VROOT) == 0)
- error = EINVAL;
- nmp = VFSTONFS(nd.ni_vp->v_mount);
- vput(nd.ni_vp);
- if (error)
- goto done2;
- if ((nmp->nm_state & NFSSTA_MNTD) &&
- (uap->flag & NFSSVC_GOTAUTH) == 0) {
- error = 0;
- goto done2;
- }
- nmp->nm_state |= NFSSTA_MNTD;
- error = nqnfs_clientd(nmp, td->td_proc->p_ucred, &ncd, uap->flag,
- uap->argp, td);
- } else if (uap->flag & NFSSVC_ADDSOCK) {
+ if (uap->flag & NFSSVC_ADDSOCK) {
error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg));
if (error)
goto done2;
@@ -231,106 +161,14 @@ nfssvc(td, uap)
}
error = nfssvc_addsock(fp, nam, td);
fdrop(fp, td);
- } else {
+ } else if (uap->flag & NFSSVC_NFSD) {
error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd));
if (error)
- goto done2;
- if ((uap->flag & NFSSVC_AUTHIN) &&
- ((nfsd = nsd->nsd_nfsd)) != NULL &&
- (nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
- slp = nfsd->nfsd_slp;
-
- /*
- * First check to see if another nfsd has already
- * added this credential.
- */
- for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
- (!nfsd->nfsd_nd->nd_nam2 ||
- netaddr_match(NU_NETFAM(nuidp),
- &nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
- break;
- }
- if (nuidp) {
- nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
- nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
- } else {
- /*
- * Nope, so we will.
- */
- if (slp->ns_numuids < nuidhash_max) {
- slp->ns_numuids++;
- nuidp = (struct nfsuid *)
- malloc(sizeof (struct nfsuid), M_NFSUID,
- M_WAITOK);
- } else
- nuidp = (struct nfsuid *)0;
- if ((slp->ns_flag & SLP_VALID) == 0) {
- if (nuidp)
- free((caddr_t)nuidp, M_NFSUID);
- } else {
- if (nuidp == (struct nfsuid *)0) {
- nuidp = slp->ns_uidlruhead.tqh_first;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
- nu_lru);
- if (nuidp->nu_flag & NU_NAM)
- FREE(nuidp->nu_nam, M_SONAME);
- }
- nuidp->nu_flag = 0;
- bzero(&nuidp->nu_cr, sizeof(nuidp->nu_cr));
- nuidp->nu_cr.cr_uid = nsd->nsd_cr.cr_uid;
- nuidp->nu_cr.cr_ngroups =
- nsd->nsd_cr.cr_ngroups;
- bcopy(nsd->nsd_cr.cr_groups,
- nuidp->nu_cr.cr_groups,
- sizeof(nuidp->nu_cr.cr_groups));
- if (nuidp->nu_cr.cr_ngroups > NGROUPS)
- nuidp->nu_cr.cr_ngroups = NGROUPS;
- nuidp->nu_cr.cr_ref = 1;
- nuidp->nu_timestamp = nsd->nsd_timestamp;
- nuidp->nu_expire = time_second + nsd->nsd_ttl;
- /*
- * and save the session key in nu_key.
- */
- bcopy(nsd->nsd_key, nuidp->nu_key,
- sizeof (nsd->nsd_key));
- if (nfsd->nfsd_nd->nd_nam2) {
- struct sockaddr_in *saddr;
-
- saddr = (struct sockaddr_in *)
- nfsd->nfsd_nd->nd_nam2;
- switch (saddr->sin_family) {
- case AF_INET:
- nuidp->nu_flag |= NU_INETADDR;
- nuidp->nu_inetaddr =
- saddr->sin_addr.s_addr;
- break;
- case AF_ISO:
- default:
- nuidp->nu_flag |= NU_NAM;
- nuidp->nu_nam =
- dup_sockaddr(nfsd->nfsd_nd->
- nd_nam2, 1);
- break;
- };
- }
- TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
- nu_lru);
- LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
- nuidp, nu_hash);
- nfsrv_setcred(&nuidp->nu_cr,
- &nfsd->nfsd_nd->nd_cr);
- nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
- }
- }
- }
- if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
- nfsd->nfsd_flag |= NFSD_AUTHFAIL;
+ return (error);
error = nfssvc_nfsd(nsd, uap->argp, td);
+ } else {
+ error = ENXIO;
}
-#endif /* NFS_NOSERVER */
if (error == EINTR || error == ERESTART)
error = 0;
done2:
@@ -338,19 +176,15 @@ done2:
return (error);
}
-#ifndef NFS_NOSERVER
/*
* Adds a socket to the list for servicing by nfsds.
*/
static int
-nfssvc_addsock(fp, mynam, td)
- struct file *fp;
- struct sockaddr *mynam;
- struct thread *td;
+nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td)
{
- register int siz;
- register struct nfssvc_sock *slp;
- register struct socket *so;
+ int siz;
+ struct nfssvc_sock *slp;
+ struct socket *so;
int error, s;
so = (struct socket *)fp->f_data;
@@ -418,7 +252,6 @@ nfssvc_addsock(fp, mynam, td)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC,
M_WAITOK | M_ZERO);
STAILQ_INIT(&slp->ns_rec);
- TAILQ_INIT(&slp->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
slp->ns_so = so;
@@ -440,13 +273,10 @@ nfssvc_addsock(fp, mynam, td)
* until it is killed by a signal.
*/
static int
-nfssvc_nfsd(nsd, argp, td)
- struct nfsd_srvargs *nsd;
- caddr_t argp;
- struct thread *td;
+nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td)
{
- register int siz;
- register struct nfssvc_sock *slp;
+ int siz;
+ struct nfssvc_sock *slp;
struct nfsd *nfsd = nsd->nsd_nfsd;
struct nfsrv_descript *nd = NULL;
struct mbuf *m, *mreq;
@@ -485,8 +315,7 @@ nfssvc_nfsd(nsd, argp, td)
}
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
- for (slp = nfssvc_sockhead.tqh_first; slp != 0;
- slp = slp->ns_chain.tqe_next) {
+ TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) {
if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
== (SLP_VALID | SLP_DOREC)) {
slp->ns_flag &= ~SLP_DOREC;
@@ -512,8 +341,8 @@ nfssvc_nfsd(nsd, argp, td)
}
error = nfsrv_dorec(slp, nfsd, &nd);
cur_usec = nfs_curusec();
- if (error && slp->ns_tq.lh_first &&
- slp->ns_tq.lh_first->nd_time <= cur_usec) {
+ if (error && LIST_FIRST(&slp->ns_tq) &&
+ LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) {
error = 0;
cacherep = RC_DOIT;
writes_todo = 1;
@@ -547,49 +376,9 @@ nfssvc_nfsd(nsd, argp, td)
/*
* Check to see if authorization is needed.
*/
- if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
- nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
- nsd->nsd_haddr =
- ((struct sockaddr_in *)
- nd->nd_nam)->sin_addr.s_addr;
- nsd->nsd_authlen = nfsd->nfsd_authlen;
- nsd->nsd_verflen = nfsd->nfsd_verflen;
- if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
- nfsd->nfsd_authlen) &&
- !copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
- nfsd->nfsd_verflen) &&
- !copyout((caddr_t)nsd, argp, sizeof (*nsd)))
- return (ENEEDAUTH);
- cacherep = RC_DROPIT;
- } else
- cacherep = nfsrv_getcache(nd, slp, &mreq);
+ cacherep = nfsrv_getcache(nd, slp, &mreq);
- /*
- * Check for just starting up for NQNFS and send
- * fake "try again later" replies to the NQNFS clients.
- */
- if (notstarted && nqnfsstarttime <= time_second) {
- if (modify_flag) {
- nqnfsstarttime = time_second + nqsrv_writeslack;
- modify_flag = 0;
- } else
- notstarted = 0;
- }
- if (notstarted) {
- if ((nd->nd_flag & ND_NQNFS) == 0)
- cacherep = RC_DROPIT;
- else if (nd->nd_procnum != NFSPROC_WRITE) {
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = NQNFS_TRYLATER;
- cacherep = RC_DOIT;
- } else
- modify_flag = 1;
- } else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
- nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- cacherep = RC_DOIT;
- } else if (nfs_privport) {
+ if (nfs_privport) {
/* Check if source port is privileged */
u_short port;
struct sockaddr *nam = nd->nd_nam;
@@ -597,7 +386,7 @@ nfssvc_nfsd(nsd, argp, td)
sin = (struct sockaddr_in *)nam;
port = ntohs(sin->sin_port);
- if (port >= IPPORT_RESERVED &&
+ if (port >= IPPORT_RESERVED &&
nd->nd_procnum != NFSPROC_NULL) {
nd->nd_procnum = NFSPROC_NOOP;
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
@@ -630,14 +419,13 @@ nfssvc_nfsd(nsd, argp, td)
if (mreq == NULL)
break;
if (error != 0 && error != NFSERR_RETVOID) {
- if (nd->nd_procnum != NQNFSPROC_VACATED)
- nfsstats.srv_errs++;
+ nfsrvstats.srv_errs++;
nfsrv_updatecache(nd, FALSE, mreq);
if (nd->nd_nam2)
FREE(nd->nd_nam2, M_SONAME);
break;
}
- nfsstats.srvrpccnt[nd->nd_procnum]++;
+ nfsrvstats.srvrpccnt[nd->nd_procnum]++;
nfsrv_updatecache(nd, TRUE, mreq);
nd->nd_mrep = (struct mbuf *)0;
case RC_REPLY:
@@ -665,13 +453,11 @@ nfssvc_nfsd(nsd, argp, td)
if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
(void) nfs_slplock(slp, 1);
if (slp->ns_flag & SLP_VALID)
- error = nfs_send(slp->ns_so, nd->nd_nam2, m, NULL);
+ error = nfsrv_send(slp->ns_so, nd->nd_nam2, m);
else {
error = EPIPE;
m_freem(m);
}
- if (nfsrtton)
- nfsd_rt(sotype, nd, cacherep);
if (nd->nd_nam2)
FREE(nd->nd_nam2, M_SONAME);
if (nd->nd_mrep)
@@ -688,8 +474,6 @@ nfssvc_nfsd(nsd, argp, td)
}
break;
case RC_DROPIT:
- if (nfsrtton)
- nfsd_rt(sotype, nd, cacherep);
m_freem(nd->nd_mrep);
if (nd->nd_nam2)
FREE(nd->nd_nam2, M_SONAME);
@@ -706,8 +490,8 @@ nfssvc_nfsd(nsd, argp, td)
*/
cur_usec = nfs_curusec();
s = splsoftclock();
- if (slp->ns_tq.lh_first &&
- slp->ns_tq.lh_first->nd_time <= cur_usec) {
+ if (LIST_FIRST(&slp->ns_tq) &&
+ LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) {
cacherep = RC_DOIT;
writes_todo = 1;
} else
@@ -739,11 +523,9 @@ done:
* reassigned during cleanup.
*/
static void
-nfsrv_zapsock(slp)
- register struct nfssvc_sock *slp;
+nfsrv_zapsock(struct nfssvc_sock *slp)
{
- register struct nfsuid *nuidp, *nnuidp;
- register struct nfsrv_descript *nwp, *nnwp;
+ struct nfsrv_descript *nwp, *nnwp;
struct socket *so;
struct file *fp;
struct nfsrv_rec *rec;
@@ -769,18 +551,9 @@ nfsrv_zapsock(slp)
m_freem(rec->nr_packet);
free(rec, M_NFSRVDESC);
}
- for (nuidp = slp->ns_uidlruhead.tqh_first; nuidp != 0;
- nuidp = nnuidp) {
- nnuidp = nuidp->nu_lru.tqe_next;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
- if (nuidp->nu_flag & NU_NAM)
- FREE(nuidp->nu_nam, M_SONAME);
- free((caddr_t)nuidp, M_NFSUID);
- }
s = splsoftclock();
- for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
- nnwp = nwp->nd_tq.le_next;
+ for (nwp = LIST_FIRST(&slp->ns_tq); nwp; nwp = nnwp) {
+ nnwp = LIST_NEXT(nwp, nd_tq);
LIST_REMOVE(nwp, nd_tq);
free((caddr_t)nwp, M_NFSRVDESC);
}
@@ -794,9 +567,9 @@ nfsrv_zapsock(slp)
* is no longer valid, you can throw it away.
*/
void
-nfsrv_slpderef(slp)
- register struct nfssvc_sock *slp;
+nfsrv_slpderef(struct nfssvc_sock *slp)
{
+
if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
free((caddr_t)slp, M_NFSSVC);
@@ -807,19 +580,17 @@ nfsrv_slpderef(slp)
* Lock a socket against others.
*/
int
-nfs_slplock(slp, wait)
- register struct nfssvc_sock *slp;
- int wait;
+nfs_slplock(struct nfssvc_sock *slp, int wait)
{
int *statep = &slp->ns_solock;
- if (!wait && (*statep & NFSSTA_SNDLOCK))
+ if (!wait && (*statep & NFSRV_SNDLOCK))
return(0); /* already locked, fail */
- while (*statep & NFSSTA_SNDLOCK) {
- *statep |= NFSSTA_WANTSND;
+ while (*statep & NFSRV_SNDLOCK) {
+ *statep |= NFSRV_WANTSND;
(void) tsleep((caddr_t)statep, PZERO - 1, "nfsslplck", 0);
}
- *statep |= NFSSTA_SNDLOCK;
+ *statep |= NFSRV_SNDLOCK;
return (1);
}
@@ -827,16 +598,15 @@ nfs_slplock(slp, wait)
* Unlock the stream socket for others.
*/
void
-nfs_slpunlock(slp)
- register struct nfssvc_sock *slp;
+nfs_slpunlock(struct nfssvc_sock *slp)
{
int *statep = &slp->ns_solock;
- if ((*statep & NFSSTA_SNDLOCK) == 0)
+ if ((*statep & NFSRV_SNDLOCK) == 0)
panic("nfs slpunlock");
- *statep &= ~NFSSTA_SNDLOCK;
- if (*statep & NFSSTA_WANTSND) {
- *statep &= ~NFSSTA_WANTSND;
+ *statep &= ~NFSRV_SNDLOCK;
+ if (*statep & NFSRV_WANTSND) {
+ *statep &= ~NFSRV_WANTSND;
wakeup((caddr_t)statep);
}
}
@@ -847,17 +617,16 @@ nfs_slpunlock(slp)
* corruption.
*/
void
-nfsrv_init(terminating)
- int terminating;
+nfsrv_init(int terminating)
{
- register struct nfssvc_sock *slp, *nslp;
+ struct nfssvc_sock *slp, *nslp;
if (nfssvc_sockhead_flag & SLP_INIT)
panic("nfsd init");
nfssvc_sockhead_flag |= SLP_INIT;
if (terminating) {
- for (slp = nfssvc_sockhead.tqh_first; slp != 0; slp = nslp) {
- nslp = slp->ns_chain.tqe_next;
+ for (slp = TAILQ_FIRST(&nfssvc_sockhead); slp != 0; slp = nslp){
+ nslp = TAILQ_NEXT(slp, ns_chain);
if (slp->ns_flag & SLP_VALID)
nfsrv_zapsock(slp);
TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
@@ -881,334 +650,11 @@ nfsrv_init(terminating)
nfs_udpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
STAILQ_INIT(&nfs_udpsock->ns_rec);
- TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
nfs_cltpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
STAILQ_INIT(&nfs_cltpsock->ns_rec);
- TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
#endif
}
-
-/*
- * Add entries to the server monitor log.
- */
-static void
-nfsd_rt(sotype, nd, cacherep)
- int sotype;
- register struct nfsrv_descript *nd;
- int cacherep;
-{
- register struct drt *rt;
-
- rt = &nfsdrt.drt[nfsdrt.pos];
- if (cacherep == RC_DOIT)
- rt->flag = 0;
- else if (cacherep == RC_REPLY)
- rt->flag = DRT_CACHEREPLY;
- else
- rt->flag = DRT_CACHEDROP;
- if (sotype == SOCK_STREAM)
- rt->flag |= DRT_TCP;
- if (nd->nd_flag & ND_NQNFS)
- rt->flag |= DRT_NQNFS;
- else if (nd->nd_flag & ND_NFSV3)
- rt->flag |= DRT_NFSV3;
- rt->proc = nd->nd_procnum;
- if (nd->nd_nam->sa_family == AF_INET)
- rt->ipadr = ((struct sockaddr_in *)nd->nd_nam)->sin_addr.s_addr;
- else
- rt->ipadr = INADDR_ANY;
- rt->resptime = nfs_curusec() - (nd->nd_starttime.tv_sec * 1000000 + nd->nd_starttime.tv_usec);
- getmicrotime(&rt->tstamp);
- nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
-}
-#endif /* NFS_NOSERVER */
-
-static int nfs_defect = 0;
-SYSCTL_INT(_vfs_nfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0, "");
-
-/*
- * Asynchronous I/O daemons for client nfs.
- * They do read-ahead and write-behind operations on the block I/O cache.
- * Never returns unless it fails or gets killed.
- */
-static int
-nfssvc_iod(td)
- struct thread *td;
-{
- register struct buf *bp;
- register int i, myiod;
- struct nfsmount *nmp;
- int error = 0;
-
- /*
- * Assign my position or return error if too many already running
- */
- myiod = -1;
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
- if (nfs_asyncdaemon[i] == 0) {
- nfs_asyncdaemon[i]++;
- myiod = i;
- break;
- }
- if (myiod == -1)
- return (EBUSY);
- nfs_numasync++;
- /*
- * Just loop around doin our stuff until SIGKILL
- */
- for (;;) {
- while (((nmp = nfs_iodmount[myiod]) == NULL
- || nmp->nm_bufq.tqh_first == NULL)
- && error == 0) {
- if (nmp)
- nmp->nm_bufqiods--;
- nfs_iodwant[myiod] = td->td_proc;
- nfs_iodmount[myiod] = NULL;
- error = tsleep((caddr_t)&nfs_iodwant[myiod],
- PWAIT | PCATCH, "nfsidl", 0);
- }
- if (error) {
- nfs_asyncdaemon[myiod] = 0;
- if (nmp)
- nmp->nm_bufqiods--;
- nfs_iodwant[myiod] = NULL;
- nfs_iodmount[myiod] = NULL;
- nfs_numasync--;
- return (error);
- }
- while ((bp = nmp->nm_bufq.tqh_first) != NULL) {
- /* Take one off the front of the list */
- TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist);
- nmp->nm_bufqlen--;
- if (nmp->nm_bufqwant && nmp->nm_bufqlen <= nfs_numasync) {
- nmp->nm_bufqwant = FALSE;
- wakeup(&nmp->nm_bufq);
- }
- if (bp->b_iocmd == BIO_READ)
- (void) nfs_doio(bp, bp->b_rcred, (struct thread *)0);
- else
- (void) nfs_doio(bp, bp->b_wcred, (struct thread *)0);
- /*
- * If there are more than one iod on this mount, then defect
- * so that the iods can be shared out fairly between the mounts
- */
- if (nfs_defect && nmp->nm_bufqiods > 1) {
- NFS_DPF(ASYNCIO,
- ("nfssvc_iod: iod %d defecting from mount %p\n",
- myiod, nmp));
- nfs_iodmount[myiod] = NULL;
- nmp->nm_bufqiods--;
- break;
- }
- }
- }
-}
-
-
-/*
- * Get an authorization string for the uid by having the mount_nfs sitting
- * on this mount point porpous out of the kernel and do it.
- */
-int
-nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
- register struct nfsmount *nmp;
- struct nfsreq *rep;
- struct ucred *cred;
- char **auth_str;
- int *auth_len;
- char *verf_str;
- int *verf_len;
- NFSKERBKEY_T key; /* return session key */
-{
- int error = 0;
-
- while ((nmp->nm_state & NFSSTA_WAITAUTH) == 0) {
- nmp->nm_state |= NFSSTA_WANTAUTH;
- (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK,
- "nfsauth1", 2 * hz);
- error = nfs_sigintr(nmp, rep, rep->r_td->td_proc);
- if (error) {
- nmp->nm_state &= ~NFSSTA_WANTAUTH;
- return (error);
- }
- }
- nmp->nm_state &= ~(NFSSTA_WAITAUTH | NFSSTA_WANTAUTH);
- nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
- nmp->nm_authlen = RPCAUTH_MAXSIZ;
- nmp->nm_verfstr = verf_str;
- nmp->nm_verflen = *verf_len;
- nmp->nm_authuid = cred->cr_uid;
- wakeup((caddr_t)&nmp->nm_authstr);
-
- /*
- * And wait for mount_nfs to do its stuff.
- */
- while ((nmp->nm_state & NFSSTA_HASAUTH) == 0 && error == 0) {
- (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK,
- "nfsauth2", 2 * hz);
- error = nfs_sigintr(nmp, rep, rep->r_td->td_proc);
- }
- if (nmp->nm_state & NFSSTA_AUTHERR) {
- nmp->nm_state &= ~NFSSTA_AUTHERR;
- error = EAUTH;
- }
- if (error)
- free((caddr_t)*auth_str, M_TEMP);
- else {
- *auth_len = nmp->nm_authlen;
- *verf_len = nmp->nm_verflen;
- bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
- }
- nmp->nm_state &= ~NFSSTA_HASAUTH;
- nmp->nm_state |= NFSSTA_WAITAUTH;
- if (nmp->nm_state & NFSSTA_WANTAUTH) {
- nmp->nm_state &= ~NFSSTA_WANTAUTH;
- wakeup((caddr_t)&nmp->nm_authtype);
- }
- return (error);
-}
-
-/*
- * Get a nickname authenticator and verifier.
- */
-int
-nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
- struct nfsmount *nmp;
- struct ucred *cred;
- char **auth_str;
- int *auth_len;
- char *verf_str;
- int verf_len;
-{
- register struct nfsuid *nuidp;
- register u_int32_t *nickp, *verfp;
- struct timeval ktvin, ktvout;
-
-#ifdef DIAGNOSTIC
- if (verf_len < (4 * NFSX_UNSIGNED))
- panic("nfs_getnickauth verf too small");
-#endif
- for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
- nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
- if (nuidp->nu_cr.cr_uid == cred->cr_uid)
- break;
- }
- if (!nuidp || nuidp->nu_expire < time_second)
- return (EACCES);
-
- /*
- * Move to the end of the lru list (end of lru == most recently used).
- */
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
- TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
-
- nickp = (u_int32_t *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
- *nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
- *nickp = txdr_unsigned(nuidp->nu_nickname);
- *auth_str = (char *)nickp;
- *auth_len = 2 * NFSX_UNSIGNED;
-
- /*
- * Now we must encrypt the verifier and package it up.
- */
- verfp = (u_int32_t *)verf_str;
- *verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
- if (time_second > nuidp->nu_timestamp.tv_sec ||
- (time_second == nuidp->nu_timestamp.tv_sec &&
- time_second > nuidp->nu_timestamp.tv_usec))
- getmicrotime(&nuidp->nu_timestamp);
- else
- nuidp->nu_timestamp.tv_usec++;
- ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
- ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
-
- /*
- * Now encrypt the timestamp verifier in ecb mode using the session
- * key.
- */
-#ifdef NFSKERB
- XXX
-#endif
-
- *verfp++ = ktvout.tv_sec;
- *verfp++ = ktvout.tv_usec;
- *verfp = 0;
- return (0);
-}
-
-/*
- * Save the current nickname in a hash list entry on the mount point.
- */
-int
-nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
- register struct nfsmount *nmp;
- struct ucred *cred;
- int len;
- NFSKERBKEY_T key;
- struct mbuf **mdp;
- char **dposp;
- struct mbuf *mrep;
-{
- register struct nfsuid *nuidp;
- register u_int32_t *tl;
- register int32_t t1;
- struct mbuf *md = *mdp;
- struct timeval ktvin, ktvout;
- u_int32_t nick;
- char *dpos = *dposp, *cp2;
- int deltasec, error = 0;
-
- if (len == (3 * NFSX_UNSIGNED)) {
- nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
- ktvin.tv_sec = *tl++;
- ktvin.tv_usec = *tl++;
- nick = fxdr_unsigned(u_int32_t, *tl);
-
- /*
- * Decrypt the timestamp in ecb mode.
- */
-#ifdef NFSKERB
- XXX
-#endif
- ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
- ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
- deltasec = time_second - ktvout.tv_sec;
- if (deltasec < 0)
- deltasec = -deltasec;
- /*
- * If ok, add it to the hash list for the mount point.
- */
- if (deltasec <= NFS_KERBCLOCKSKEW) {
- if (nmp->nm_numuids < nuidhash_max) {
- nmp->nm_numuids++;
- nuidp = (struct nfsuid *)
- malloc(sizeof (struct nfsuid), M_NFSUID,
- M_WAITOK);
- } else {
- nuidp = nmp->nm_uidlruhead.tqh_first;
- LIST_REMOVE(nuidp, nu_hash);
- TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
- nu_lru);
- }
- nuidp->nu_flag = 0;
- nuidp->nu_cr.cr_uid = cred->cr_uid;
- nuidp->nu_expire = time_second + NFS_KERBTTL;
- nuidp->nu_timestamp = ktvout;
- nuidp->nu_nickname = nick;
- bcopy(key, nuidp->nu_key, sizeof (key));
- TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
- nu_lru);
- LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
- nuidp, nu_hash);
- }
- } else
- nfsm_adv(nfsm_rndup(len));
-nfsmout:
- *mdp = md;
- *dposp = dpos;
- return (error);
-}
diff --git a/sys/nfsserver/nfsm_subs.h b/sys/nfsserver/nfsm_subs.h
index d58ef15..2f60521 100644
--- a/sys/nfsserver/nfsm_subs.h
+++ b/sys/nfsserver/nfsm_subs.h
@@ -37,12 +37,12 @@
* $FreeBSD$
*/
+#ifndef _NFSSERVER_NFSM_SUBS_H_
+#define _NFSSERVER_NFSM_SUBS_H_
-#ifndef _NFS_NFSM_SUBS_H_
-#define _NFS_NFSM_SUBS_H_
+#include <nfs/nfs_common.h>
-struct ucred;
-struct vnode;
+#define nfstov_mode(a) (fxdr_unsigned(u_int32_t, (a)) & ALLPERMS)
/*
* These macros do strange and peculiar things to mbuf chains for
@@ -53,24 +53,8 @@ struct vnode;
/*
* First define what the actual subs. return
*/
-struct mbuf *nfsm_reqh __P((struct vnode *vp, u_long procid, int hsiz,
- caddr_t *bposp));
-struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
- int auth_type, int auth_len, char *auth_str,
- int verf_len, char *verf_str,
- struct mbuf *mrest, int mrest_len,
- struct mbuf **mbp, u_int32_t *xidp));
#define M_HASCL(m) ((m)->m_flags & M_EXT)
-#define NFSMINOFF(m) \
- do { \
- if (M_HASCL(m)) \
- (m)->m_data = (m)->m_ext.ext_buf; \
- else if ((m)->m_flags & M_PKTHDR) \
- (m)->m_data = (m)->m_pktdat; \
- else \
- (m)->m_data = (m)->m_dat; \
- } while (0)
#define NFSMADV(m, s) \
do { \
(m)->m_data += (s); \
@@ -91,474 +75,111 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
* unions.
*/
-#define nfsm_build(a,c,s) \
- do { \
- if ((s) > M_TRAILINGSPACE(mb)) { \
- MGET(mb2, M_TRYWAIT, MT_DATA); \
- if ((s) > MLEN) \
- panic("build > MLEN"); \
- mb->m_next = mb2; \
- mb = mb2; \
- mb->m_len = 0; \
- bpos = mtod(mb, caddr_t); \
- } \
- (a) = (c)(bpos); \
- mb->m_len += (s); \
- bpos += (s); \
- } while (0)
-#define nfsm_dissect(a, c, s) \
- do { \
- t1 = mtod(md, caddr_t)+md->m_len-dpos; \
- if (t1 >= (s)) { \
- (a) = (c)(dpos); \
- dpos += (s); \
- } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } else { \
- (a) = (c)cp2; \
- } \
- } while (0)
-
-#define nfsm_fhtom(v, v3) \
- do { \
- if (v3) { \
- t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
- if (t2 <= M_TRAILINGSPACE(mb)) { \
- nfsm_build(tl, u_int32_t *, t2); \
- *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
- *(tl + ((t2>>2) - 2)) = 0; \
- bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
- VTONFS(v)->n_fhsize); \
- } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \
- (caddr_t)VTONFS(v)->n_fhp, \
- VTONFS(v)->n_fhsize)) != 0) { \
- error = t2; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } else { \
- nfsm_build(cp, caddr_t, NFSX_V2FH); \
- bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
- } \
- } while (0)
+/* Helpers for macros */
+void nfsm_srvfhtom_xx(fhandle_t *f, int v3, u_int32_t **tl, struct mbuf **mb,
+ caddr_t *bpos);
+void nfsm_srvpostop_fh_xx(fhandle_t *f, u_int32_t **tl, struct mbuf **mb,
+ caddr_t *bpos);
+int nfsm_srvstrsiz_xx(int *s, int m, u_int32_t **tl, struct mbuf **md,
+ caddr_t *dpos);
+int nfsm_srvnamesiz_xx(int *s, u_int32_t **tl, struct mbuf **md,
+ caddr_t *dpos);
+void nfs_rephead_xx(int s, struct nfsrv_descript *nfsd,
+ struct nfssvc_sock *slp, int error, struct mbuf **mrq,
+ struct mbuf **mb, struct mbuf **mreq, struct mbuf **mrep,
+ caddr_t *bpos);
+int nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd,
+ u_int32_t **tl, struct mbuf **md, caddr_t *dpos);
+void nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
+ char **bp, char **be, caddr_t bpos);
+int nfsm_srvsattr_xx(struct vattr *a, u_int32_t **tl, struct mbuf **md,
+ caddr_t *dpos);
#define nfsm_srvfhtom(f, v3) \
- do { \
- if (v3) { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH);\
- *tl++ = txdr_unsigned(NFSX_V3FH); \
- bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
- } else { \
- nfsm_build(cp, caddr_t, NFSX_V2FH); \
- bcopy((caddr_t)(f), cp, NFSX_V2FH); \
- } \
- } while (0)
+do { \
+ nfsm_srvfhtom_xx((f), (v3), &tl, &mb, &bpos); \
+} while (0)
#define nfsm_srvpostop_fh(f) \
- do { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
- *tl++ = nfs_true; \
- *tl++ = txdr_unsigned(NFSX_V3FH); \
- bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
- } while (0)
-
-#define nfsm_mtofh(d, v, v3, f) \
- do { \
- struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (f) = fxdr_unsigned(int, *tl); \
- } else \
- (f) = 1; \
- if (f) { \
- nfsm_getfh(ttfhp, ttfhsize, (v3)); \
- if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
- &ttnp)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = NFSTOV(ttnp); \
- } \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (f) \
- (f) = fxdr_unsigned(int, *tl); \
- else if (fxdr_unsigned(int, *tl)) \
- nfsm_adv(NFSX_V3FATTR); \
- } \
- if (f) \
- nfsm_loadattr((v), (struct vattr *)0); \
- } while (0)
-
-#define nfsm_getfh(f, s, v3) \
- do { \
- if (v3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
- (s) > NFSX_V3FHMAX) { \
- m_freem(mrep); \
- error = EBADRPC; \
- goto nfsmout; \
- } \
- } else \
- (s) = NFSX_V2FH; \
- nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); \
- } while (0)
-
-#define nfsm_loadattr(v, a) \
- do { \
- struct vnode *ttvp = (v); \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = ttvp; \
- } while (0)
-
-#define nfsm_postop_attr(v, f) \
- do { \
- struct vnode *ttvp = (v); \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (((f) = fxdr_unsigned(int, *tl)) != 0) { \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
- (struct vattr *)0, 1)) != 0) { \
- error = t1; \
- (f) = 0; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- (v) = ttvp; \
- } \
- } while (0)
-
-/* Used as (f) for nfsm_wcc_data() */
-#define NFSV3_WCCRATTR 0
-#define NFSV3_WCCCHK 1
-
-#define nfsm_wcc_data(v, f) \
- do { \
- int ttattrf, ttretf = 0; \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \
- if (f) \
- ttretf = (VTONFS(v)->n_mtime == \
- fxdr_unsigned(u_int32_t, *(tl + 2))); \
- } \
- nfsm_postop_attr((v), ttattrf); \
- if (f) { \
- (f) = ttretf; \
- } else { \
- (f) = ttattrf; \
- } \
- } while (0)
-
-/* If full is true, set all fields, otherwise just set mode and time fields */
-#define nfsm_v3attrbuild(a, full) \
- do { \
- if ((a)->va_mode != (mode_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_mode); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_uid); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- *tl = txdr_unsigned((a)->va_gid); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((full) && (a)->va_size != VNOVAL) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \
- *tl++ = nfs_true; \
- txdr_hyper((a)->va_size, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = nfs_false; \
- } \
- if ((a)->va_atime.tv_sec != VNOVAL) { \
- if ((a)->va_atime.tv_sec != time_second) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
- txdr_nfsv3time(&(a)->va_atime, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
- } \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
- } \
- if ((a)->va_mtime.tv_sec != VNOVAL) { \
- if ((a)->va_mtime.tv_sec != time_second) { \
- nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
- txdr_nfsv3time(&(a)->va_mtime, tl); \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
- } \
- } else { \
- nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
- } \
- } while (0)
-
-
-#define nfsm_strsiz(s,m) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \
- m_freem(mrep); \
- error = EBADRPC; \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvstrsiz(s,m) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \
- error = EBADRPC; \
- nfsm_reply(0); \
- } \
- } while (0)
+do { \
+ nfsm_srvpostop_fh_xx((f), &tl, &mb, &bpos); \
+} while (0)
+
+#define nfsm_srvstrsiz(s, m) \
+do { \
+ int t1; \
+ t1 = nfsm_srvstrsiz_xx(&(s), (m), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ nfsm_reply(0); \
+ } \
+} while (0)
#define nfsm_srvnamesiz(s) \
- do { \
- nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \
- error = NFSERR_NAMETOL; \
- if ((s) <= 0) \
- error = EBADRPC; \
- if (error) \
- nfsm_reply(0); \
- } while (0)
-
-#define nfsm_mtouio(p,s) \
- do {\
- if ((s) > 0 && \
- (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_uiotom(p,s) \
- do { \
- if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \
- error = t1; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_reqhead(v,a,s) \
- do { \
- mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \
- } while (0)
-
-#define nfsm_reqdone \
- do { \
- m_freem(mrep); \
- nfsmout: \
- } while (0)
-
-#define nfsm_rndup(a) (((a)+3)&(~0x3))
-
-#define nfsm_request(v, t, p, c) \
- do { \
- if ((error = nfs_request((v), mreq, (t), (p), \
- (c), &mrep, &md, &dpos)) != 0) { \
- if (error & NFSERR_RETERR) \
- error &= ~NFSERR_RETERR; \
- else \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_strtom(a,s,m) \
- do {\
- if ((s) > (m)) { \
- m_freem(mreq); \
- error = ENAMETOOLONG; \
- goto nfsmout; \
- } \
- t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
- if (t2 <= M_TRAILINGSPACE(mb)) { \
- nfsm_build(tl,u_int32_t *,t2); \
- *tl++ = txdr_unsigned(s); \
- *(tl+((t2>>2)-2)) = 0; \
- bcopy((const char *)(a), (caddr_t)tl, (s)); \
- } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \
- error = t2; \
- m_freem(mreq); \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_srvdone \
- do { \
- nfsmout: \
- return (error); \
- } while (0)
+do { \
+ int t1; \
+ t1 = nfsm_srvnamesiz_xx(&(s), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ nfsm_reply(0); \
+ } \
+} while (0)
#define nfsm_reply(s) \
- do { \
- nfsd->nd_repstat = error; \
- if (error && !(nfsd->nd_flag & ND_NFSV3)) \
- (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
- mrq, &mb, &bpos); \
- else \
- (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
- mrq, &mb, &bpos); \
- if (mrep != NULL) { \
- m_freem(mrep); \
- mrep = NULL; \
- } \
- mreq = *mrq; \
- if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
- error == EBADRPC)) { \
- error = 0; \
- goto nfsmout; \
- } \
- } while (0)
-
-#define nfsm_writereply(s, v3) \
- do { \
- nfsd->nd_repstat = error; \
- if (error && !(v3)) \
- (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
- &mreq, &mb, &bpos); \
- else \
- (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
- &mreq, &mb, &bpos); \
- } while (0)
-
-#define nfsm_adv(s) \
- do { \
- t1 = mtod(md, caddr_t)+md->m_len-dpos; \
- if (t1 >= (s)) { \
- dpos += (s); \
- } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \
- error = t1; \
- m_freem(mrep); \
- goto nfsmout; \
- } \
- } while (0)
+do { \
+ nfs_rephead_xx((s), nfsd, slp, error, mrq, &mb, &mreq, &mrep, &bpos); \
+ if (error && error == EBADRPC) { \
+ error = 0; \
+ goto nfsmout; \
+ } \
+} while (0)
+
+#define nfsm_writereply(s) \
+do { \
+ nfs_rephead((s), nfsd, slp, error, &mreq, &mb, &bpos); \
+} while (0)
#define nfsm_srvmtofh(f) \
- do { \
- int fhlen; \
- if (nfsd->nd_flag & ND_NFSV3) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- fhlen = fxdr_unsigned(int, *tl); \
- if (fhlen != 0 && fhlen != NFSX_V3FH) { \
- error = EBADRPC; \
- nfsm_reply(0); \
- } \
- } else { \
- fhlen = NFSX_V2FH; \
- } \
- if (fhlen != 0) { \
- nfsm_dissect(tl, u_int32_t *, fhlen); \
- bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \
- } else {\
- bzero((caddr_t)(f), NFSX_V3FH); \
- } \
- } while (0)
-
-#define nfsm_clget \
- do { \
- if (bp >= be) { \
- if (mp == mb) \
- mp->m_len += bp-bpos; \
- MGET(mp, M_TRYWAIT, MT_DATA); \
- MCLGET(mp, M_TRYWAIT); \
- mp->m_len = NFSMSIZ(mp); \
- mp2->m_next = mp; \
- mp2 = mp; \
- bp = mtod(mp, caddr_t); \
- be = bp+mp->m_len; \
- } \
- tl = (u_int32_t *)bp; \
- } while (0)
+do { \
+ int t1; \
+ t1 = nfsm_srvmtofh_xx((f), nfsd, &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ nfsm_reply(0); \
+ } \
+} while (0)
+
+#define nfsm_clget \
+do { \
+ nfsm_clget_xx(&tl, mb, &mp, &bp, &be, bpos); \
+} while (0)
#define nfsm_srvfillattr(a, f) \
- do { \
- nfsm_srvfattr(nfsd, (a), (f)); \
- } while (0)
+do { \
+ nfsm_srvfattr(nfsd, (a), (f)); \
+} while (0)
#define nfsm_srvwcc_data(br, b, ar, a) \
- do { \
- nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
- } while (0)
+do { \
+ nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
+} while (0)
#define nfsm_srvpostop_attr(r, a) \
- do { \
- nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
- } while (0)
+do { \
+ nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
+} while (0)
#define nfsm_srvsattr(a) \
- do { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_mode = nfstov_mode(*tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_uid = fxdr_unsigned(uid_t, *tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- (a)->va_gid = fxdr_unsigned(gid_t, *tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- if (*tl == nfs_true) { \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- (a)->va_size = fxdr_hyper(tl); \
- } \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- switch (fxdr_unsigned(int, *tl)) { \
- case NFSV3SATTRTIME_TOCLIENT: \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- fxdr_nfsv3time(tl, &(a)->va_atime); \
- break; \
- case NFSV3SATTRTIME_TOSERVER: \
- getnanotime(&(a)->va_atime); \
- break; \
- }; \
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
- switch (fxdr_unsigned(int, *tl)) { \
- case NFSV3SATTRTIME_TOCLIENT: \
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
- fxdr_nfsv3time(tl, &(a)->va_mtime); \
- break; \
- case NFSV3SATTRTIME_TOSERVER: \
- getnanotime(&(a)->va_mtime); \
- break; \
- } \
- } while (0)
+do { \
+ int t1; \
+ t1 = nfsm_srvsattr_xx((a), &tl, &md, &dpos); \
+ if (t1) { \
+ error = t1; \
+ m_freem(mrep); \
+ mrep = NULL; \
+ goto nfsmout; \
+ } \
+} while (0)
#endif
diff --git a/sys/nfsserver/nfsrvcache.h b/sys/nfsserver/nfsrvcache.h
index eec5850..96b76d5 100644
--- a/sys/nfsserver/nfsrvcache.h
+++ b/sys/nfsserver/nfsrvcache.h
@@ -37,9 +37,8 @@
* $FreeBSD$
*/
-
-#ifndef _NFS_NFSRVCACHE_H_
-#define _NFS_NFSRVCACHE_H_
+#ifndef _NFSSERVER_NFSRVCACHE_H_
+#define _NFSSERVER_NFSRVCACHE_H_
#include <sys/queue.h>
@@ -77,14 +76,13 @@ struct nfsrvcache {
#define RC_DROPIT 0
#define RC_REPLY 1
#define RC_DOIT 2
-#define RC_CHECKIT 3
/* Flag bits */
#define RC_LOCKED 0x01
#define RC_WANTED 0x02
#define RC_REPSTATUS 0x04
#define RC_REPMBUF 0x08
-#define RC_NQNFS 0x10
+/* free 0x10 */
#define RC_INETADDR 0x20
#define RC_NAM 0x40
diff --git a/sys/nfsserver/nfsrvstats.h b/sys/nfsserver/nfsrvstats.h
index da808f4..d744f95 100644
--- a/sys/nfsserver/nfsrvstats.h
+++ b/sys/nfsserver/nfsrvstats.h
@@ -37,691 +37,21 @@
* $FreeBSD$
*/
-#ifndef _NFS_NFS_H_
-#define _NFS_NFS_H_
-
-#ifdef _KERNEL
-#include "opt_nfs.h"
-#endif
-
-/*
- * Tunable constants for nfs
- */
-
-#define NFS_MAXIOVEC 34
-#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
-#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
-#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
-#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
-#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
-#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
-#define NFS_MAXREXMIT 100 /* Stop counting after this many */
-#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
-#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
-#define NFS_MAXGRPS 16 /* Max. size of groups list */
-#ifndef NFS_MINATTRTIMO
-#define NFS_MINATTRTIMO 3 /* VREG attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXATTRTIMO
-#define NFS_MAXATTRTIMO 60
-#endif
-#ifndef NFS_MINDIRATTRTIMO
-#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */
-#endif
-#ifndef NFS_MAXDIRATTRTIMO
-#define NFS_MAXDIRATTRTIMO 60
-#endif
-#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
-#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
-#define NFS_READDIRSIZE 8192 /* Def. readdir size */
-#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
-#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
-#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
-#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
-#ifndef NFS_GATHERDELAY
-#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
-#endif
-#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
-#ifdef _KERNEL
-#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
-#endif
-
-/*
- * Oddballs
- */
-#define NMOD(a) ((a) % nfs_asyncdaemons)
-#define NFS_CMPFH(n, f, s) \
- ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
-#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
-#define NFS_SRVMAXDATA(n) \
- (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
- NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
-
-/*
- * XXX
- * The B_INVAFTERWRITE flag should be set to whatever is required by the
- * buffer cache code to say "Invalidate the block after it is written back".
- */
-#define B_INVAFTERWRITE B_NOCACHE
-
-/*
- * The IO_METASYNC flag should be implemented for local file systems.
- * (Until then, it is nothin at all.)
- */
-#ifndef IO_METASYNC
-#define IO_METASYNC 0
-#endif
-
-/*
- * Arguments to mount NFS
- */
-#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
-struct nfs_args {
- int version; /* args structure version number */
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
- int acregmin; /* cache attrs for reg files min time */
- int acregmax; /* cache attrs for reg files max time */
- int acdirmin; /* cache attrs for dirs min time */
- int acdirmax; /* cache attrs for dirs max time */
-};
-
-/*
- * NFS mount option flags
- */
-#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
-#define NFSMNT_WSIZE 0x00000002 /* set write size */
-#define NFSMNT_RSIZE 0x00000004 /* set read size */
-#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
-#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
-#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
-#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
-#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
-#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
-#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
-#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
-#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
-#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
-#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
-#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
-#define NFSMNT_ACREGMIN 0x00040000
-#define NFSMNT_ACREGMAX 0x00080000
-#define NFSMNT_ACDIRMIN 0x00100000
-#define NFSMNT_ACDIRMAX 0x00200000
-
-#define NFSSTA_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSSTA_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
-#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSSTA_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSSTA_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSSTA_DISMNT 0x00800000 /* Dismounted */
-#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
-#define NFSSTA_WANTSND 0x02000000 /* Want above */
-#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
-#define NFSSTA_WANTRCV 0x08000000 /* Want above */
-#define NFSSTA_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSSTA_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSSTA_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSSTA_AUTHERR 0x80000000 /* Authentication error */
+#ifndef _NFSSERVER_NFSRVSTATS_H_
+#define _NFSSERVER_NFSRVSTATS_H_
/*
- * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
- * should ever try and use it.
+ * Server stats structure
*/
-struct nfsd_args {
- int sock; /* Socket to serve */
- caddr_t name; /* Client addr for connection based sockets */
- int namelen; /* Length of name */
-};
-
-struct nfsd_srvargs {
- struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
- uid_t nsd_uid; /* Effective uid mapped to cred */
- u_int32_t nsd_haddr; /* Ip address of client */
- struct xucred nsd_cr; /* Cred. uid maps to */
- u_int nsd_authlen; /* Length of auth string (ret) */
- u_char *nsd_authstr; /* Auth string (ret) */
- u_int nsd_verflen; /* and the verfier */
- u_char *nsd_verfstr;
- struct timeval nsd_timestamp; /* timestamp from verifier */
- u_int32_t nsd_ttl; /* credential ttl (sec) */
- NFSKERBKEY_T nsd_key; /* Session key */
-};
-
-struct nfsd_cargs {
- char *ncd_dirp; /* Mount dir path */
- uid_t ncd_authuid; /* Effective uid */
- int ncd_authtype; /* Type of authenticator */
- u_int ncd_authlen; /* Length of authenticator string */
- u_char *ncd_authstr; /* Authenticator string */
- u_int ncd_verflen; /* and the verifier */
- u_char *ncd_verfstr;
- NFSKERBKEY_T ncd_key; /* Session key */
-};
-
-/*
- * XXX to allow amd to include nfs.h without nfsproto.h
- */
-#ifdef NFS_NPROCS
-/*
- * Stats structure
- */
-struct nfsstats {
- int attrcache_hits;
- int attrcache_misses;
- int lookupcache_hits;
- int lookupcache_misses;
- int direofcache_hits;
- int direofcache_misses;
- int biocache_reads;
- int read_bios;
- int read_physios;
- int biocache_writes;
- int write_bios;
- int write_physios;
- int biocache_readlinks;
- int readlink_bios;
- int biocache_readdirs;
- int readdir_bios;
- int rpccnt[NFS_NPROCS];
- int rpcretries;
- int srvrpccnt[NFS_NPROCS];
+struct nfsrvstats {
int srvrpc_errs;
int srv_errs;
- int rpcrequests;
- int rpctimeouts;
- int rpcunexpected;
- int rpcinvalid;
int srvcache_inproghits;
int srvcache_idemdonehits;
int srvcache_nonidemdonehits;
int srvcache_misses;
- int srvnqnfs_leases;
- int srvnqnfs_maxleases;
- int srvnqnfs_getleases;
int srvvop_writes;
- int accesscache_hits;
- int accesscache_misses;
-};
-#endif
-
-/*
- * Flags for nfssvc() system call.
- */
-#define NFSSVC_BIOD 0x002
-#define NFSSVC_NFSD 0x004
-#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_AUTHIN 0x010
-#define NFSSVC_GOTAUTH 0x040
-#define NFSSVC_AUTHINFAIL 0x080
-#define NFSSVC_MNTD 0x100
-#define NFSSVC_LOCKDANS 0x200
-
-/*
- * fs.nfs sysctl(3) identifiers
- */
-#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
-#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
-
-#define FS_NFS_NAMES { \
- { 0, 0 }, \
- { "nfsstats", CTLTYPE_STRUCT }, \
- { "nfsprivport", CTLTYPE_INT }, \
-}
-
-#ifdef _KERNEL
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_NFSREQ);
-MALLOC_DECLARE(M_NFSDIROFF);
-MALLOC_DECLARE(M_NFSRVDESC);
-MALLOC_DECLARE(M_NFSUID);
-MALLOC_DECLARE(M_NQLEASE);
-MALLOC_DECLARE(M_NFSD);
-MALLOC_DECLARE(M_NFSBIGFH);
-MALLOC_DECLARE(M_NFSHASH);
-#endif
-
-#ifdef ZONE_INTERRUPT
-extern vm_zone_t nfsmount_zone;
-#endif
-
-extern struct callout_handle nfs_timer_handle;
-
-struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
-
-/*
- * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
- * What should be in this set is open to debate, but I believe that since
- * I/O system calls on ufs are never interrupted by signals the set should
- * be minimal. My reasoning is that many current programs that use signals
- * such as SIGALRM will not expect file I/O system calls to be interrupted
- * by them and break.
- */
-#define NFSINT_SIGMASK(set) \
- (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
- SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
- SIGISMEMBER(set, SIGQUIT))
-
-/*
- * Socket errors ignored for connectionless sockets??
- * For now, ignore them all
- */
-#define NFSIGNORE_SOERROR(s, e) \
- ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
- ((s) & PR_CONNREQUIRED) == 0)
-
-/*
- * Nfs outstanding request list element
- */
-struct nfsreq {
- TAILQ_ENTRY(nfsreq) r_chain;
- struct mbuf *r_mreq;
- struct mbuf *r_mrep;
- struct mbuf *r_md;
- caddr_t r_dpos;
- struct nfsmount *r_nmp;
- struct vnode *r_vp;
- 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 */
- u_int32_t r_procnum; /* NFS procedure number */
- int r_rtt; /* RTT for rpc */
- struct thread *r_td; /* Proc that did I/O system call */
-};
-
-/*
- * Queue head for nfsreq's
- */
-extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
-
-/* 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 */
-
-/*
- * A list of nfssvc_sock structures is maintained with all the sockets
- * that require service by the nfsd.
- * The nfsuid structs hang off of the nfssvc_sock structs in both lru
- * and uid hash lists.
- */
-#ifndef NFS_UIDHASHSIZ
-#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
-#endif
-#define NUIDHASH(sock, uid) \
- (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
-#ifndef NFS_WDELAYHASHSIZ
-#define NFS_WDELAYHASHSIZ 16 /* and with this */
-#endif
-#define NWDELAYHASH(sock, f) \
- (&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifndef NFS_MUIDHASHSIZ
-#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
-#endif
-#define NMUIDHASH(nmp, uid) \
- (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
-#define NFSNOHASH(fhsum) \
- (&nfsnodehashtbl[(fhsum) & nfsnodehash])
-
-/*
- * Network address hash list element
- */
-union nethostaddr {
- u_int32_t had_inetaddr;
- struct sockaddr *had_nam;
-};
-
-struct nfsuid {
- TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
- LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
- int nu_flag; /* Flags */
- union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
- struct ucred nu_cr; /* Cred uid mapped to */
- int nu_expire; /* Expiry time (sec) */
- struct timeval nu_timestamp; /* Kerb. timestamp */
- u_int32_t nu_nickname; /* Nickname on server */
- NFSKERBKEY_T nu_key; /* and session key */
-};
-
-#define nu_inetaddr nu_haddr.had_inetaddr
-#define nu_nam nu_haddr.had_nam
-/* Bits for nu_flag */
-#define NU_INETADDR 0x1
-#define NU_NAM 0x2
-#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
-
-struct nfsrv_rec {
- STAILQ_ENTRY(nfsrv_rec) nr_link;
- struct sockaddr *nr_address;
- struct mbuf *nr_packet;
-};
-
-struct nfssvc_sock {
- TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- TAILQ_HEAD(, nfsuid) ns_uidlruhead;
- struct file *ns_fp;
- struct socket *ns_so;
- struct sockaddr *ns_nam;
- struct mbuf *ns_raw;
- struct mbuf *ns_rawend;
- STAILQ_HEAD(, nfsrv_rec) ns_rec;
- struct mbuf *ns_frag;
- int ns_flag;
- int ns_solock;
- int ns_cc;
- int ns_reclen;
- int ns_numuids;
- u_int32_t ns_sref;
- LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
- LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
-};
-
-/* Bits for "ns_flag" */
-#define SLP_VALID 0x01
-#define SLP_DOREC 0x02
-#define SLP_NEEDQ 0x04
-#define SLP_DISCONN 0x08
-#define SLP_GETSTREAM 0x10
-#define SLP_LASTFRAG 0x20
-#define SLP_ALLFLAGS 0xff
-
-extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
-extern int nfssvc_sockhead_flag;
-#define SLP_INIT 0x01
-#define SLP_WANTINIT 0x02
-
-/*
- * One of these structures is allocated for each nfsd.
- */
-struct nfsd {
- TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
- int nfsd_flag; /* NFSD_ flags */
- struct nfssvc_sock *nfsd_slp; /* Current socket */
- int nfsd_authlen; /* Authenticator len */
- u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
- int nfsd_verflen; /* and the Verifier */
- u_char nfsd_verfstr[RPCVERF_MAXSIZ];
- struct thread *nfsd_td; /* daemon thread ptr */
- struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
-};
-
-/* Bits for "nfsd_flag" */
-#define NFSD_WAITING 0x01
-#define NFSD_REQINPROG 0x02
-#define NFSD_NEEDAUTH 0x04
-#define NFSD_AUTHFAIL 0x08
-
-/*
- * This structure is used by the server for describing each request.
- * Some fields are used only when write request gathering is performed.
- */
-struct nfsrv_descript {
- u_quad_t nd_time; /* Write deadline (usec) */
- off_t nd_off; /* Start byte offset */
- off_t nd_eoff; /* and end byte offset */
- LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
- LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
- LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
- struct mbuf *nd_mrep; /* Request mbuf list */
- struct mbuf *nd_md; /* Current dissect mbuf */
- struct mbuf *nd_mreq; /* Reply mbuf list */
- struct sockaddr *nd_nam; /* and socket addr */
- struct sockaddr *nd_nam2; /* return socket addr */
- caddr_t nd_dpos; /* Current dissect pos */
- u_int32_t nd_procnum; /* RPC # */
- int nd_stable; /* storage type */
- int nd_flag; /* nd_flag */
- int nd_len; /* Length of this write */
- int nd_repstat; /* Reply status */
- u_int32_t nd_retxid; /* Reply xid */
- u_int32_t nd_duration; /* Lease duration */
- struct timeval nd_starttime; /* Time RPC initiated */
- fhandle_t nd_fh; /* File handle */
- struct ucred nd_cr; /* Credentials */
+ int srvrpccnt[NFS_NPROCS];
};
-/* Bits for "nd_flag" */
-#define ND_READ LEASE_READ
-#define ND_WRITE LEASE_WRITE
-#define ND_CHECK 0x04
-#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
-#define ND_NFSV3 0x08
-#define ND_NQNFS 0x10
-#define ND_KERBNICK 0x20
-#define ND_KERBFULL 0x40
-#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
-
-extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
-extern int nfsd_head_flag;
-#define NFSD_CHECKSLP 0x01
-
-/*
- * These macros compare nfsrv_descript structures.
- */
-#define NFSW_CONTIG(o, n) \
- ((o)->nd_eoff >= (n)->nd_off && \
- !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
-
-#define NFSW_SAMECRED(o, n) \
- (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
- !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
- sizeof (struct ucred)))
-
-/*
- * Defines for WebNFS
- */
-
-#define WEBNFS_ESC_CHAR '%'
-#define WEBNFS_SPECCHAR_START 0x80
-
-#define WEBNFS_NATIVE_CHAR 0x80
-/*
- * ..
- * Possibly more here in the future.
- */
-
-/*
- * Macro for converting escape characters in WebNFS pathnames.
- * Should really be in libkern.
- */
-
-#define HEXTOC(c) \
- ((c) >= 'a' ? ((c) - ('a' - 10)) : \
- ((c) >= 'A' ? ((c) - ('A' - 10)) : ((c) - '0')))
-#define HEXSTRTOI(p) \
- ((HEXTOC(p[0]) << 4) + HEXTOC(p[1]))
-
-#ifdef NFS_DEBUG
-
-extern int nfs_debug;
-#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
-#define NFS_DEBUG_WG 2 /* server write gathering */
-#define NFS_DEBUG_RC 4 /* server request caching */
-
-#define NFS_DPF(cat, args) \
- do { \
- if (nfs_debug & NFS_DEBUG_##cat) printf args; \
- } while (0)
-
-#else
-
-#define NFS_DPF(cat, args)
-
-#endif
-
-u_quad_t nfs_curusec __P((void));
-int nfs_init __P((struct vfsconf *vfsp));
-int nfs_uninit __P((struct vfsconf *vfsp));
-int nfs_reply __P((struct nfsreq *));
-int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
-int nfs_send __P((struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *));
-int nfs_rephead __P((int, struct nfsrv_descript *, struct nfssvc_sock *,
- int, int, u_quad_t *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_sndlock __P((struct nfsreq *));
-void nfs_sndunlock __P((struct nfsreq *));
-int nfs_slplock __P((struct nfssvc_sock *, int));
-void nfs_slpunlock __P((struct nfssvc_sock *));
-int nfs_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-int nfs_vinvalbuf __P((struct vnode *, int, struct ucred *, struct thread *,
- int));
-int nfs_readrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_writerpc __P((struct vnode *, struct uio *, struct ucred *, int *,
- int *));
-int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
- struct ucred *cred, struct thread *td));
-int nfs_readdirrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_asyncio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_doio __P((struct buf *, struct ucred *, struct thread *));
-int nfs_readlinkrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfs_sigintr __P((struct nfsmount *, struct nfsreq *, struct proc *));
-int nfs_readdirplusrpc __P((struct vnode *, struct uio *, struct ucred *));
-int nfsm_disct __P((struct mbuf **, caddr_t *, int, int, caddr_t *));
-void nfsm_srvfattr __P((struct nfsrv_descript *, struct vattr *,
- struct nfs_fattr *));
-void nfsm_srvwcc __P((struct nfsrv_descript *, int, struct vattr *, int,
- struct vattr *, struct mbuf **, char **));
-void nfsm_srvpostopattr __P((struct nfsrv_descript *, int, struct vattr *,
- struct mbuf **, char **));
-int netaddr_match __P((int, union nethostaddr *, struct sockaddr *));
-int nfs_request __P((struct vnode *, struct mbuf *, int, struct thread *,
- struct ucred *, struct mbuf **, struct mbuf **,
- caddr_t *));
-int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *, int));
-int nfs_namei __P((struct nameidata *, fhandle_t *, int,
- struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
- caddr_t *, struct vnode **, struct thread *, int, int));
-void nfsm_adj __P((struct mbuf *, int, int));
-int nfsm_mbuftouio __P((struct mbuf **, struct uio *, int, caddr_t *));
-void nfsrv_initcache __P((void));
-int nfs_getauth __P((struct nfsmount *, struct nfsreq *, struct ucred *,
- char **, int *, char *, int *, NFSKERBKEY_T));
-int nfs_getnickauth __P((struct nfsmount *, struct ucred *, char **,
- int *, char *, int));
-int nfs_savenickauth __P((struct nfsmount *, struct ucred *, int,
- NFSKERBKEY_T, struct mbuf **, char **,
- struct mbuf *));
-int nfs_adv __P((struct mbuf **, caddr_t *, int, int));
-void nfs_nhinit __P((void));
-void nfs_timer __P((void*));
-int nfsrv_dorec __P((struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **));
-int nfsrv_getcache __P((struct nfsrv_descript *, struct nfssvc_sock *,
- struct mbuf **));
-void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *));
-void nfsrv_cleancache __P((void));
-int nfs_connect __P((struct nfsmount *, struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *));
-void nfs_safedisconnect __P((struct nfsmount *));
-int nfs_getattrcache __P((struct vnode *, struct vattr *));
-int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long));
-int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *));
-int nfsm_uiotombuf __P((struct uio *, struct mbuf **, int, caddr_t *));
-void nfsrv_init __P((int));
-void nfs_clearcommit __P((struct mount *));
-int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrvw_sort __P((gid_t *, int));
-void nfsrv_setcred __P((struct ucred *, struct ucred *));
-int nfs_writebp __P((struct buf *, int, struct thread *));
-int nfsrv_object_create __P((struct vnode *));
-void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
-int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
- struct thread *, struct mbuf **));
-int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
- struct thread *td));
-
-int nfsrv3_access __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_fhtovp __P((fhandle_t *, int, struct vnode **, struct ucred *,
- struct nfssvc_sock *, struct sockaddr *, int *,
- int, int));
-int nfsrv_setpublicfs __P((struct mount *, struct netexport *,
- struct export_args *));
-int nfs_ispublicfh __P((fhandle_t *));
-int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdir __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp, struct thread *td,
- struct mbuf **mrq));
-int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_setattr __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_statfs __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_symlink __P((struct nfsrv_descript *nfsd,
- struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct thread *td, struct mbuf **mrq));
-void nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
-#endif /* _KERNEL */
-
#endif
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index 324e882..2354838 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -37,7 +37,8 @@ options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MD_ROOT #MD is a potential root device
-options NFS #Network Filesystem
+options NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
options NFS_ROOT #NFS usable as root device, NFS required
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
diff --git a/sys/powerpc/powerpc/autoconf.c b/sys/powerpc/powerpc/autoconf.c
index b66c68a..400c234 100644
--- a/sys/powerpc/powerpc/autoconf.c
+++ b/sys/powerpc/powerpc/autoconf.c
@@ -61,8 +61,6 @@ static const char rcsid[] =
static void configure __P((void *));
SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL)
-extern int nfs_diskless_valid;
-
dev_t rootdev = NODEV;
dev_t dumpdev = NODEV;
OpenPOWER on IntegriCloud