[rtems-libbsd commit] kern/sys: Add NFSv4 client

Chris Johns chrisj at rtems.org
Thu Sep 2 02:43:01 UTC 2021


Module:    rtems-libbsd
Branch:    6-freebsd-12
Commit:    882425fe547f73a1a77caa4938dec369cfd1063d
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=882425fe547f73a1a77caa4938dec369cfd1063d

Author:    Chris Johns <chrisj at rtems.org>
Date:      Thu Jul 29 15:49:52 2021 +1000

kern/sys: Add NFSv4 client

Update #4475

---

 buildset/default.ini                               |   9 +-
 buildset/nfsv2.ini                                 |  13 +
 config.inc                                         |   1 +
 freebsd/sys/fs/nfs/nfs_commonacl.c                 |   2 +
 freebsd/sys/fs/nfs/nfs_commonkrpc.c                |  37 ++-
 freebsd/sys/fs/nfs/nfs_commonport.c                |   3 +-
 freebsd/sys/fs/nfs/nfs_commonsubs.c                |   9 +-
 freebsd/sys/fs/nfs/nfsport.h                       |  17 +-
 freebsd/sys/fs/nfsclient/nfs.h                     |   3 +-
 freebsd/sys/fs/nfsclient/nfs_clbio.c               |  53 +++-
 freebsd/sys/fs/nfsclient/nfs_clcomsubs.c           |   2 +
 freebsd/sys/fs/nfsclient/nfs_clkdtrace.c           |   4 +
 freebsd/sys/fs/nfsclient/nfs_clkrpc.c              |   5 +-
 freebsd/sys/fs/nfsclient/nfs_clnfsiod.c            |   6 +-
 freebsd/sys/fs/nfsclient/nfs_clnode.c              |  10 +
 freebsd/sys/fs/nfsclient/nfs_clport.c              |  46 ++-
 freebsd/sys/fs/nfsclient/nfs_clrpcops.c            |  67 +++-
 freebsd/sys/fs/nfsclient/nfs_clstate.c             |   3 +-
 freebsd/sys/fs/nfsclient/nfs_clsubs.c              |   7 +-
 freebsd/sys/fs/nfsclient/nfs_clvfsops.c            |  17 +-
 freebsd/sys/fs/nfsclient/nfs_clvnops.c             |  98 ++++--
 freebsd/sys/nfs/bootp_subr.c                       |   8 +-
 freebsd/sys/nfs/krpc_subr.c                        |   2 +
 freebsd/sys/nfs/nfs_fha.c                          |   2 +
 freebsd/sys/nfs/nfs_lock.c                         |  14 +-
 freebsd/sys/nfs/nfs_nfssvc.c                       |  13 +-
 freebsd/sys/nfsclient/nfs.h                        |   2 +-
 freebsd/sys/nfsclient/nfsnode.h                    |   4 +
 libbsd.py                                          | 138 ++++++++-
 rtemsbsd/fs/nfsclient/nfs.c                        | 223 ++++++++++++++
 rtemsbsd/include/rtems/bsd/local/opt_kgssapi.h     |   0
 rtemsbsd/include/rtems/bsd/local/opt_nfs.h         |   0
 rtemsbsd/include/rtems/bsd/local/opt_nfsroot.h     |   0
 rtemsbsd/include/rtems/bsd/local/opt_rootdevname.h |   0
 rtemsbsd/include/rtems/bsd/local/opt_ufs.h         |   0
 rtemsbsd/rtems/rtems-bsd-libio.c                   |   2 +-
 .../include/rtems/bsd/test/network-config.h.in     |   3 +
 testsuite/nfs01/test_main.c                        | 340 ++++++++++++++++++++-
 waf_libbsd.py                                      |  32 +-
 39 files changed, 1104 insertions(+), 91 deletions(-)

diff --git a/buildset/default.ini b/buildset/default.ini
index 5848a45..47df5ae 100644
--- a/buildset/default.ini
+++ b/buildset/default.ini
@@ -40,6 +40,8 @@ dhcpcd = on
 dpaa = on
 evdev = on
 fdt = on
+fs_nfs = on
+fs_nfsclient = on
 imx = on
 in_cksum = on
 mdnsresponder = on
@@ -50,14 +52,15 @@ net80211 = off
 netinet = on
 netinet6 = on
 netipsec = off
-nfsv2 = on
-rpc = on
+nfsv2 = off
+nfs = on
 nvme = on
 opencrypto = on
 pci = on
 pf = on
 regulator = on
-rpc_user = on
+rpc = on
+rpc_user = off
 rtems = on
 tests = on
 tty = on
diff --git a/buildset/nfsv2.ini b/buildset/nfsv2.ini
new file mode 100644
index 0000000..45fdcc5
--- /dev/null
+++ b/buildset/nfsv2.ini
@@ -0,0 +1,13 @@
+#
+# The configuration to build legacy NFSv2 client
+#
+
+[general]
+name = nfsv2
+extends = default.ini
+
+[modules]
+nfsv2 = on
+rpc_user = on
+fs_nfs = off
+fs_nfsclient = off
diff --git a/config.inc b/config.inc
index f69983b..27863d5 100644
--- a/config.inc
+++ b/config.inc
@@ -3,3 +3,4 @@ NET_CFG_SELF_IP = 10.0.2.1
 NET_CFG_NETMASK = 255.255.0.0
 NET_CFG_PEER_IP = 192.168.100.11
 NET_CFG_GATEWAY_IP = 192.168.100.11
+NET_CFG_NFS_MOUNT_PATH = 192.168.100.11:/srv/nfs
diff --git a/freebsd/sys/fs/nfs/nfs_commonacl.c b/freebsd/sys/fs/nfs/nfs_commonacl.c
index 3e8cfe2..31b18ea 100644
--- a/freebsd/sys/fs/nfs/nfs_commonacl.c
+++ b/freebsd/sys/fs/nfs/nfs_commonacl.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
diff --git a/freebsd/sys/fs/nfs/nfs_commonkrpc.c b/freebsd/sys/fs/nfs/nfs_commonkrpc.c
index f85121f..8ddcc6b 100644
--- a/freebsd/sys/fs/nfs/nfs_commonkrpc.c
+++ b/freebsd/sys/fs/nfs/nfs_commonkrpc.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -40,8 +42,8 @@ __FBSDID("$FreeBSD$");
  * Socket operations for use by nfs
  */
 
-#include "opt_kgssapi.h"
-#include "opt_nfs.h"
+#include <rtems/bsd/local/opt_kgssapi.h>
+#include <rtems/bsd/local/opt_nfs.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -62,7 +64,9 @@ __FBSDID("$FreeBSD$");
 #include <rpc/rpc.h>
 #include <rpc/krpc.h>
 
+#ifndef __rtems__
 #include <kgssapi/krb5/kcrypto.h>
+#endif /* __rtems__ */
 
 #include <fs/nfs/nfsport.h>
 
@@ -215,7 +219,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
 			nconf = getnetconfigent("udp6");
 		else
 			nconf = getnetconfigent("tcp6");
-			
+
 	pktscale = nfs_bufpackets;
 	if (pktscale < 2)
 		pktscale = 2;
@@ -233,7 +237,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
 	 */
 	so = NULL;
 	saddr = NFSSOCKADDR(nrp->nr_nam, struct sockaddr *);
-	error = socreate(saddr->sa_family, &so, nrp->nr_sotype, 
+	error = socreate(saddr->sa_family, &so, nrp->nr_sotype,
 	    nrp->nr_soproto, td->td_ucred, td);
 	if (error) {
 		td->td_ucred = origcred;
@@ -387,7 +391,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
 		/*
 		 * For UDP, there are 2 timeouts:
 		 * - CLSET_RETRY_TIMEOUT sets the initial timeout for the timer
-		 *   that does a retransmit of an RPC request using the same 
+		 *   that does a retransmit of an RPC request using the same
 		 *   socket and xid. This is what you normally want to do,
 		 *   since NFS servers depend on "same xid" for their
 		 *   Duplicate Request Cache.
@@ -737,7 +741,7 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
 		if (dtrace_nfscl_nfs234_start_probe != NULL) {
 			uint32_t probe_id;
 			int probe_procnum;
-	
+
 			if (nd->nd_flag & ND_NFSV4) {
 				probe_id =
 				    nfscl_nfs4_start_probes[nd->nd_procnum];
@@ -1139,9 +1143,9 @@ tryagain:
 				      j != NFSERR_STALESTATEID &&
 				      j != NFSERR_BADSTATEID &&
 				      j != NFSERR_BADSEQID &&
-				      j != NFSERR_BADXDR &&	 
+				      j != NFSERR_BADXDR &&
 				      j != NFSERR_RESOURCE &&
-				      j != NFSERR_NOFILEHANDLE)))		 
+				      j != NFSERR_NOFILEHANDLE)))
 					nd->nd_flag |= ND_INCRSEQID;
 			}
 			/*
@@ -1260,13 +1264,13 @@ static int
 nfs_sig_pending(sigset_t set)
 {
 	int i;
-	
+
 	for (i = 0 ; i < nitems(newnfs_sig_set); i++)
 		if (SIGISMEMBER(set, newnfs_sig_set[i]))
 			return (1);
 	return (0);
 }
- 
+
 /*
  * The set/restore sigmask functions are used to (temporarily) overwrite
  * the thread td_sigmask during an RPC call (for example). These are also
@@ -1275,10 +1279,11 @@ nfs_sig_pending(sigset_t set)
 void
 newnfs_set_sigmask(struct thread *td, sigset_t *oldset)
 {
+#ifndef __rtems__
 	sigset_t newset;
 	int i;
 	struct proc *p;
-	
+
 	SIGFILLSET(newset);
 	if (td == NULL)
 		td = curthread; /* XXX */
@@ -1301,14 +1306,17 @@ newnfs_set_sigmask(struct thread *td, sigset_t *oldset)
 	kern_sigprocmask(td, SIG_SETMASK, &newset, oldset,
 	    SIGPROCMASK_PROC_LOCKED);
 	PROC_UNLOCK(p);
+#endif /* __rtems__ */
 }
 
 void
 newnfs_restore_sigmask(struct thread *td, sigset_t *set)
 {
+#ifndef __rtems__
 	if (td == NULL)
 		td = curthread; /* XXX */
 	kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0);
+#endif /* __rtems__ */
 }
 
 /*
@@ -1338,9 +1346,10 @@ newnfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority, cha
 int
 newnfs_sigintr(struct nfsmount *nmp, struct thread *td)
 {
+#ifndef __rtems__
 	struct proc *p;
 	sigset_t tmpset;
-	
+
 	/* Terminate all requests while attempting a forced unmount. */
 	if (NFSCL_FORCEDISM(nmp->nm_mountp))
 		return (EIO);
@@ -1362,6 +1371,7 @@ newnfs_sigintr(struct nfsmount *nmp, struct thread *td)
 		return (EINTR);
 	}
 	PROC_UNLOCK(p);
+#endif /* __rtems__ */
 	return (0);
 }
 
@@ -1423,7 +1433,7 @@ nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg,
 		    VQ_NOTRESP, 1);
 	} else
 		mtx_unlock(&nmp->nm_mtx);
-	
+
 	mtx_lock(&nmp->nm_mtx);
 	if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) {
 		nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
@@ -1433,4 +1443,3 @@ nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg,
 	} else
 		mtx_unlock(&nmp->nm_mtx);
 }
-
diff --git a/freebsd/sys/fs/nfs/nfs_commonport.c b/freebsd/sys/fs/nfs/nfs_commonport.c
index 1a1e64c..80648a1 100644
--- a/freebsd/sys/fs/nfs/nfs_commonport.c
+++ b/freebsd/sys/fs/nfs/nfs_commonport.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -816,4 +818,3 @@ DECLARE_MODULE(nfscommon, nfscommon_mod, SI_SUB_VFS, SI_ORDER_ANY);
 MODULE_VERSION(nfscommon, 1);
 MODULE_DEPEND(nfscommon, nfssvc, 1, 1, 1);
 MODULE_DEPEND(nfscommon, krpc, 1, 1, 1);
-
diff --git a/freebsd/sys/fs/nfs/nfs_commonsubs.c b/freebsd/sys/fs/nfs/nfs_commonsubs.c
index 9214674..f7c93ce 100644
--- a/freebsd/sys/fs/nfs/nfs_commonsubs.c
+++ b/freebsd/sys/fs/nfs/nfs_commonsubs.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -42,8 +44,8 @@ __FBSDID("$FreeBSD$");
  * copy data between mbuf chains and uio lists.
  */
 #ifndef APPLEKEXT
-#include "opt_inet.h"
-#include "opt_inet6.h"
+#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
 
 #include <fs/nfs/nfsport.h>
 
@@ -3814,8 +3816,10 @@ nfssvc_idname(struct nfsd_idargs *nidp)
 			cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid;
 			crsetgroups(cr, nidp->nid_ngroup, grps);
 			cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
+#ifndef __rtems__
 			cr->cr_prison = &prison0;
 			prison_hold(cr->cr_prison);
+#endif /* __rtems__ */
 #ifdef MAC
 			mac_cred_associate_nfsd(cr);
 #endif
@@ -4766,4 +4770,3 @@ nfsv4_findmirror(struct nfsmount *nmp)
 	}
 	return (ds);
 }
-
diff --git a/freebsd/sys/fs/nfs/nfsport.h b/freebsd/sys/fs/nfs/nfsport.h
index 8abb6a5..6eb530a 100644
--- a/freebsd/sys/fs/nfs/nfsport.h
+++ b/freebsd/sys/fs/nfs/nfsport.h
@@ -42,7 +42,7 @@
  * to be the cleanest way to handle #include files for the ports.
  */
 #ifdef _KERNEL
-#include <sys/unistd.h>
+#include <rtems/bsd/sys/unistd.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
@@ -53,7 +53,9 @@
 #include <sys/filedesc.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
+#ifndef __rtems__
 #include <sys/lockf.h>
+#endif /* __rtems__ */
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mount.h>
@@ -77,7 +79,9 @@
 #include <sys/acl.h>
 #include <sys/module.h>
 #include <sys/sysent.h>
+#ifndef __rtems__
 #include <sys/syscall.h>
+#endif /* __rtems__ */
 #include <sys/priv.h>
 #include <sys/kthread.h>
 #include <sys/syscallsubr.h>
@@ -108,6 +112,7 @@
  * (This is always defined as nil otherwise.)
  */
 #define	APPLESTATIC
+#ifndef __rtems__
 #include <ufs/ufs/dir.h>
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>
@@ -117,9 +122,10 @@
 #include <vm/vm.h>
 #include <vm/vm_object.h>
 #include <vm/vm_extern.h>
+#endif /* __rtems__ */
 #include <nfs/nfssvc.h>
-#include "opt_nfs.h"
-#include "opt_ufs.h"
+#include <rtems/bsd/local/opt_nfs.h>
+#include <rtems/bsd/local/opt_ufs.h>
 
 /*
  * These types must be defined before the nfs includes.
@@ -697,8 +703,13 @@ void nfsrvd_rcv(struct socket *, void *, int);
 #define	NFSASSERTIOD()		mtx_assert(&ncl_iod_mutex, MA_OWNED)
 #define	NFSLOCKREQUEST(r)	mtx_lock(&((r)->r_mtx))
 #define	NFSUNLOCKREQUEST(r)	mtx_unlock(&((r)->r_mtx))
+#ifndef __rtems__
 #define	NFSPROCLISTLOCK()	sx_slock(&allproc_lock)
 #define	NFSPROCLISTUNLOCK()	sx_sunlock(&allproc_lock)
+#else /* __rtems__ */
+#define	NFSPROCLISTLOCK()
+#define	NFSPROCLISTUNLOCK()
+#endif /* __rtems__ */
 #define	NFSLOCKSOCKREQ(r)	mtx_lock(&((r)->nr_mtx))
 #define	NFSUNLOCKSOCKREQ(r)	mtx_unlock(&((r)->nr_mtx))
 #define	NFSLOCKDS(d)		mtx_lock(&((d)->nfsclds_mtx))
diff --git a/freebsd/sys/fs/nfsclient/nfs.h b/freebsd/sys/fs/nfsclient/nfs.h
index ce1747a..f76a60a 100644
--- a/freebsd/sys/fs/nfsclient/nfs.h
+++ b/freebsd/sys/fs/nfsclient/nfs.h
@@ -96,7 +96,8 @@ void ncl_doio_directwrite(struct buf *);
 int ncl_bioread(struct vnode *, struct uio *, int, struct ucred *);
 int ncl_biowrite(struct vnode *, struct uio *, int, struct ucred *);
 int ncl_vinvalbuf(struct vnode *, int, struct thread *, int);
-int ncl_asyncio(struct nfsmount *, struct buf *, struct ucred *,
+int ncl_asyncio(struct
+		nfsmount *, struct buf *, struct ucred *,
     struct thread *);
 int ncl_doio(struct vnode *, struct buf *, struct ucred *, struct thread *,
     int);
diff --git a/freebsd/sys/fs/nfsclient/nfs_clbio.c b/freebsd/sys/fs/nfsclient/nfs_clbio.c
index 105ab25..cd157db 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clbio.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clbio.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -53,7 +55,9 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 #include <vm/vm_object.h>
 #include <vm/vm_pager.h>
+#ifndef __rtems__
 #include <vm/vnode_pager.h>
+#endif /* __rtems__ */
 
 #include <fs/nfs/nfsport.h>
 #include <fs/nfsclient/nfsmount.h>
@@ -173,10 +177,12 @@ ncl_getpages(struct vop_getpages_args *ap)
 	 *
 	 * XXXGL: is that true for NFS, where short read can occur???
 	 */
+#ifndef __rtems__
 	VM_OBJECT_WLOCK(object);
 	if (pages[npages - 1]->valid != 0 && --npages == 0)
 		goto out;
 	VM_OBJECT_WUNLOCK(object);
+#endif /* __rtems__*/
 
 	/*
 	 * We use only the kva address for the buffer, but this is extremely
@@ -185,7 +191,9 @@ ncl_getpages(struct vop_getpages_args *ap)
 	bp = getpbuf(&ncl_pbuf_freecnt);
 
 	kva = (vm_offset_t) bp->b_data;
+#ifndef __rtems__
 	pmap_qenter(kva, pages, npages);
+#endif /* __rtems__*/
 	VM_CNT_INC(v_vnodein);
 	VM_CNT_ADD(v_vnodepgsin, npages);
 
@@ -194,14 +202,20 @@ ncl_getpages(struct vop_getpages_args *ap)
 	iov.iov_len = count;
 	uio.uio_iov = &iov;
 	uio.uio_iovcnt = 1;
+#ifndef __rtems__
 	uio.uio_offset = IDX_TO_OFF(pages[0]->pindex);
+#else /* __rtems__*/
+	uio.uio_offset = 0;
+#endif /* __rtems__*/
 	uio.uio_resid = count;
 	uio.uio_segflg = UIO_SYSSPACE;
 	uio.uio_rw = UIO_READ;
 	uio.uio_td = td;
 
 	error = ncl_readrpc(vp, &uio, cred);
+#ifndef __rtems__
 	pmap_qremove(kva, npages);
+#endif /* __rtems__*/
 
 	relpbuf(bp, &ncl_pbuf_freecnt);
 
@@ -221,6 +235,7 @@ ncl_getpages(struct vop_getpages_args *ap)
 	for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
 		vm_page_t m;
 		nextoff = toff + PAGE_SIZE;
+#ifndef __rtems__
 		m = pages[i];
 
 		if (nextoff <= size) {
@@ -250,8 +265,11 @@ ncl_getpages(struct vop_getpages_args *ap)
 			 */
 			;
 		}
+#endif /* __rtems__*/
 	}
+#ifndef __rtems__
 out:
+#endif /* __rtems__ */
 	VM_OBJECT_WUNLOCK(object);
 	if (ap->a_rbehind)
 		*ap->a_rbehind = 0;
@@ -291,7 +309,11 @@ ncl_putpages(struct vop_putpages_args *ap)
 	count = ap->a_count;
 	rtvals = ap->a_rtvals;
 	npages = btoc(count);
+#ifndef __rtems__
 	offset = IDX_TO_OFF(pages[0]->pindex);
+#else /* __rtems__*/
+	offset = 0;
+#endif /* __rtems__*/
 
 	mtx_lock(&nmp->nm_mtx);
 	if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
@@ -334,14 +356,20 @@ ncl_putpages(struct vop_putpages_args *ap)
 	uio.uio_rw = UIO_WRITE;
 	uio.uio_td = td;
 
+#ifndef __rtems__
 	error = VOP_WRITE(vp, &uio, vnode_pager_putpages_ioflags(ap->a_sync),
 	    cred);
+#else /* __rtems__*/
+	error = VOP_WRITE(vp, &uio, 0, cred);
+#endif /* __rtems__*/
 	crfree(cred);
 
+#ifndef __rtems__
 	if (error == 0 || !nfs_keep_dirty_on_error) {
 		vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid,
 		    np->n_size - offset, npages * PAGE_SIZE);
 	}
+#endif /* __rtems__*/
 	return (rtvals[0]);
 }
 
@@ -709,6 +737,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
 	return (error);
 }
 
+#ifdef __rtems__
 /*
  * The NFS write path cannot handle iovecs with len > 1. So we need to
  * break up iovecs accordingly (restricting them to wsize).
@@ -855,6 +884,7 @@ err_free:
 	}
 	return (0);
 }
+#endif /* __rtems__ */
 
 /*
  * Vnode op for write using bio
@@ -1044,7 +1074,9 @@ again:
 				NFSLOCKNODE(np);
 				np->n_size = uio->uio_offset + n;
 				np->n_flag |= NMODIFIED;
+#ifndef __rtems__
 				vnode_pager_setsize(vp, np->n_size);
+#endif /* __rems__ */
 				NFSUNLOCKNODE(np);
 
 				save = bp->b_flags & B_CACHE;
@@ -1073,7 +1105,9 @@ again:
 			if (uio->uio_offset + n > np->n_size) {
 				np->n_size = uio->uio_offset + n;
 				np->n_flag |= NMODIFIED;
+#ifndef __rtems__
 				vnode_pager_setsize(vp, np->n_size);
+#endif /* __rems__ */
 			}
 			NFSUNLOCKNODE(np);
 		}
@@ -1265,6 +1299,7 @@ again:
 	return (error);
 }
 
+#ifdef __rtems__
 /*
  * Get an nfs cache block.
  *
@@ -1309,6 +1344,7 @@ nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, struct thread *td)
 		bp->b_blkno = bn * (vp->v_bufobj.bo_bsize / DEV_BSIZE);
 	return (bp);
 }
+#endif /* __rtems__ */
 
 /*
  * Flush and invalidate all dirty buffers. If another process is already
@@ -1345,9 +1381,11 @@ ncl_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg)
 	 */
 	if ((flags & (V_SAVE | V_VMIO)) == V_SAVE &&
 	     vp->v_bufobj.bo_object != NULL) {
+#ifndef __rtems__
 		VM_OBJECT_WLOCK(vp->v_bufobj.bo_object);
 		vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
 		VM_OBJECT_WUNLOCK(vp->v_bufobj.bo_object);
+#endif /* __rtems__*/
 		/*
 		 * If the page clean was interrupted, fail the invalidation.
 		 * Not doing so, we run the risk of losing dirty pages in the
@@ -1392,6 +1430,9 @@ out:
 int
 ncl_asyncio(struct nfsmount *nmp, struct buf *bp, struct ucred *cred, struct thread *td)
 {
+#ifdef __rtems__
+	return (EOPNOTSUPP);
+#else /* __rtems__ */
 	int iod;
 	int gotiod;
 	int slpflag = 0;
@@ -1533,12 +1574,16 @@ again:
 	 * force the caller to process the i/o synchronously.
 	 */
 	NFS_DPF(ASYNCIO, ("ncl_asyncio: no iods available, i/o is synchronous\n"));
+#endif /* __rtems__ */
 	return (EIO);
 }
 
 void
 ncl_doio_directwrite(struct buf *bp)
 {
+#ifdef __rtems__
+	panic("not supported in RTEMS");
+#else /* __rtems__ */
 	int iomode, must_commit;
 	struct uio *uiop = (struct uio *)bp->b_caller1;
 	char *iov_base = uiop->uio_iov->iov_base;
@@ -1572,6 +1617,7 @@ ncl_doio_directwrite(struct buf *bp)
 	}
 	bp->b_vp = NULL;
 	relpbuf(bp, &ncl_pbuf_freecnt);
+#endif /* __rtems__ */
 }
 
 /*
@@ -1643,9 +1689,13 @@ ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td,
 			NFSLOCKNODE(np);
 			if (NFS_TIMESPEC_COMPARE(&np->n_mtime, &np->n_vattr.na_mtime)) {
 				NFSUNLOCKNODE(np);
+#ifndef __rtems__
 				PROC_LOCK(p);
 				killproc(p, "text file modification");
 				PROC_UNLOCK(p);
+#else /* __rtems__ */
+				panic("nfsclient: text file modification: want to killproc");
+#endif /* _-rtems__ */
 			} else
 				NFSUNLOCKNODE(np);
 		}
@@ -1867,8 +1917,9 @@ ncl_meta_setsize(struct vnode *vp, struct thread *td, u_quad_t nsize)
 		bp->b_flags |= B_RELBUF;  /* don't leave garbage around */
 		brelse(bp);
 	} else {
+#ifndef __rtems__
 		vnode_pager_setsize(vp, nsize);
+#endif /* __rtems__ */
 	}
 	return(error);
 }
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clcomsubs.c b/freebsd/sys/fs/nfsclient/nfs_clcomsubs.c
index 479a453..47388dd 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clcomsubs.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clcomsubs.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/freebsd/sys/fs/nfsclient/nfs_clkdtrace.c b/freebsd/sys/fs/nfsclient/nfs_clkdtrace.c
index 9e51c2f..f4e27ba 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clkdtrace.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clkdtrace.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
@@ -29,6 +31,7 @@
  * SUCH DAMAGE.
  */
 
+#ifndef __rtems__
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -585,3 +588,4 @@ MODULE_DEPEND(dtnfscl, dtrace, 1, 1, 1);
 MODULE_DEPEND(dtnfscl, opensolaris, 1, 1, 1);
 MODULE_DEPEND(dtnfscl, nfscl, 1, 1, 1);
 MODULE_DEPEND(dtnfscl, nfscommon, 1, 1, 1);
+#endif /* __rtems__ */
diff --git a/freebsd/sys/fs/nfsclient/nfs_clkrpc.c b/freebsd/sys/fs/nfsclient/nfs_clkrpc.c
index 6bdeaa7..c3260cc 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clkrpc.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clkrpc.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -36,7 +38,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include "opt_kgssapi.h"
+#include <rtems/bsd/local/opt_kgssapi.h>
 
 #include <fs/nfs/nfsport.h>
 
@@ -296,4 +298,3 @@ nfsrvd_cbinit(int terminating)
 		NFSD_LOCK();
 	}
 }
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clnfsiod.c b/freebsd/sys/fs/nfsclient/nfs_clnfsiod.c
index 3f0fb77..b24b905 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clnfsiod.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clnfsiod.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -55,10 +57,12 @@ __FBSDID("$FreeBSD$");
 #include <sys/domain.h>
 #include <sys/protosw.h>
 #include <sys/namei.h>
-#include <sys/unistd.h>
+#include <rtems/bsd/sys/unistd.h>
 #include <sys/kthread.h>
 #include <sys/fcntl.h>
+#ifndef __rtems__
 #include <sys/lockf.h>
+#endif /* __rtems__ */
 #include <sys/mutex.h>
 #include <sys/taskqueue.h>
 
diff --git a/freebsd/sys/fs/nfsclient/nfs_clnode.c b/freebsd/sys/fs/nfsclient/nfs_clnode.c
index f41cb87..3f7a68a 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clnode.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clnode.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -142,7 +144,11 @@ ncl_nget(struct mount *mntp, u_int8_t *fhp, int fhsize, struct nfsnode **npp,
 	 * destroy the mutex (in the case of the loser, or if hash_insert
 	 * happened to return an error no special casing is needed).
 	 */
+#ifndef __rtems__
 	mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK);
+#else /* __rtems__ */
+	mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK | MTX_RECURSE);
+#endif /* __rtems__ */
 	lockinit(&np->n_excl, PVFS, "nfsupg", VLKTIMEOUT, LK_NOSHARE |
 	    LK_CANRECURSE);
 
@@ -250,8 +256,10 @@ ncl_inactive(struct vop_inactive_args *ap)
 		 */
 		if (vp->v_object != NULL) {
 			VM_OBJECT_WLOCK(vp->v_object);
+#ifndef __rtems__
 			retv = vm_object_page_clean(vp->v_object, 0, 0,
 			    OBJPC_SYNC);
+#endif /* __rtems__ */
 			VM_OBJECT_WUNLOCK(vp->v_object);
 		} else
 			retv = TRUE;
@@ -301,7 +309,9 @@ ncl_reclaim(struct vop_reclaim_args *ap)
 	/*
 	 * Destroy the vm object and flush associated pages.
 	 */
+#ifndef __rtems__
 	vnode_destroy_vobject(vp);
+#endif /* __rtems__ */
 
 	if (NFS_ISV4(vp) && vp->v_type == VREG)
 		/*
diff --git a/freebsd/sys/fs/nfsclient/nfs_clport.c b/freebsd/sys/fs/nfsclient/nfs_clport.c
index 74320c9..ed30770 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clport.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clport.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -36,8 +38,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include "opt_inet.h"
-#include "opt_inet6.h"
+#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
 
 #include <sys/capsicum.h>
 
@@ -232,7 +234,11 @@ nfscl_nget(struct mount *mntp, struct vnode *dvp, struct nfsfh *nfhp,
 	 * destroy the mutex (in the case of the loser, or if hash_insert
 	 * happened to return an error no special casing is needed).
 	 */
+#ifndef __rtems__
 	mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK);
+#else /* __rtems__ */
+	mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK | MTX_RECURSE);
+#endif /* __rtems__ */
 	lockinit(&np->n_excl, PVFS, "nfsupg", VLKTIMEOUT, LK_NOSHARE |
 	    LK_CANRECURSE);
 
@@ -432,7 +438,11 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
 	if (vp->v_type != nvap->va_type) {
 		vp->v_type = nvap->va_type;
 		if (vp->v_type == VFIFO)
+#ifndef __rtems__
 			vp->v_op = &newnfs_fifoops;
+#else /* __rtems__ */
+			panic("no newnfs_fifoops");
+#endif /* __rtems__ */
 		np->n_mtime = nvap->va_mtime;
 	}
 	nmp = VFSTONFS(vp->v_mount);
@@ -596,16 +606,20 @@ ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep)
 	object = vp->v_object;
 	setnsize = false;
 
+#ifndef __rtems__
 	if (object != NULL && nsize != object->un_pager.vnp.vnp_size) {
 		if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
 			setnsize = true;
 		else
 			np->n_flag |= NVNSETSZSKIP;
 	}
+#endif /* __rtems__ */
 	if (nsizep == NULL) {
 		NFSUNLOCKNODE(np);
+#ifndef __rtems__
 		if (setnsize)
 			vnode_pager_setsize(vp, nsize);
+#endif /* __rtems__ */
 		setnsize = false;
 	} else {
 		*nsizep = nsize;
@@ -678,12 +692,20 @@ nfscl_filllockowner(void *id, u_int8_t *cp, int flags)
 		*cp++ = tl.cval[1];
 		*cp++ = tl.cval[2];
 		*cp++ = tl.cval[3];
+#ifndef __rtems__
 		tl.lval = p->p_stats->p_start.tv_sec;
+#else /* __rtems__ */
+		tl.lval = 0;
+#endif /* __rtems__ */
 		*cp++ = tl.cval[0];
 		*cp++ = tl.cval[1];
 		*cp++ = tl.cval[2];
 		*cp++ = tl.cval[3];
+#ifndef __rtems__
 		tl.lval = p->p_stats->p_start.tv_usec;
+#else /* __rtems__ */
+		tl.lval = 0;
+#endif /* __rtems__ */
 		*cp++ = tl.cval[0];
 		*cp++ = tl.cval[1];
 		*cp++ = tl.cval[2];
@@ -705,6 +727,7 @@ nfscl_filllockowner(void *id, u_int8_t *cp, int flags)
 NFSPROC_T *
 nfscl_getparent(struct thread *td)
 {
+#ifndef __rtems__
 	struct proc *p;
 	struct thread *ptd;
 
@@ -718,6 +741,9 @@ nfscl_getparent(struct thread *td)
 		return (NULL);
 	ptd = TAILQ_FIRST(&p->p_threads);
 	return (ptd);
+#else /* __rtems__ */
+	return (NULL);
+#endif /* __rtems__ */
 }
 
 /*
@@ -730,7 +756,11 @@ start_nfscl(void *arg)
 	struct thread *td;
 
 	clp = (struct nfsclclient *)arg;
+#ifndef __rtems__
 	td = TAILQ_FIRST(&clp->nfsc_renewthread->p_threads);
+#else /* __rtems__ */
+	td = rtems_bsd_get_curthread_or_wait_forever();
+#endif /* __rtems__ */
 	nfscl_renewthread(clp, td);
 	kproc_exit(0);
 }
@@ -971,7 +1001,11 @@ nfscl_getmyip(struct nfsmount *nmp, struct in6_addr *paddr, int *isinet6p)
 #if defined(INET6) || defined(INET)
 	int error, fibnum;
 
+#ifndef __rtems__
 	fibnum = curthread->td_proc->p_fibnum;
+#else /* __rtems__ */
+	fibnum = 0;
+#endif /* __rtems__ */
 #endif
 #ifdef INET
 	if (nmp->nm_nam->sa_family == AF_INET) {
@@ -1052,6 +1086,9 @@ nfscl_init(void)
 	inited = 1;
 	nfscl_inited = 1;
 	ncl_pbuf_freecnt = nswbuf / 2 + 1;
+#ifdef __rtems__
+	ncl_pbuf_zone = pbuf_zsecond_create("nfspbuf", ncl_pbuf_freecnt);
+#endif /* __rtems__ */
 }
 
 /*
@@ -1173,6 +1210,7 @@ nfscl_procdoesntexist(u_int8_t *own)
 	pid_t pid;
 	int i, ret = 0;
 
+#ifndef __rtems__
 	/* For the single open_owner of all 0 bytes, just return 0. */
 	for (i = 0; i < NFSV4CL_LOCKNAMELEN; i++)
 		if (own[i] != 0)
@@ -1207,6 +1245,7 @@ nfscl_procdoesntexist(u_int8_t *own)
 			ret = 1;
 	}
 	PROC_UNLOCK(p);
+#endif /* __rtems__ */
 	return (ret);
 }
 
@@ -1243,10 +1282,12 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap)
 		    cap_rights_init(&rights, CAP_SOCK_CLIENT), &fp);
 		if (error)
 			return (error);
+#ifndef __rtems__
 		if (fp->f_type != DTYPE_SOCKET) {
 			fdrop(fp, td);
 			return (EPERM);
 		}
+#endif /* __rtems__ */
 		error = nfscbd_addsock(fp);
 		fdrop(fp, td);
 		if (!error && nfscl_enablecallb == 0) {
@@ -1411,4 +1452,3 @@ MODULE_DEPEND(nfscl, nfscommon, 1, 1, 1);
 MODULE_DEPEND(nfscl, krpc, 1, 1, 1);
 MODULE_DEPEND(nfscl, nfssvc, 1, 1, 1);
 MODULE_DEPEND(nfscl, nfslock, 1, 1, 1);
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clrpcops.c b/freebsd/sys/fs/nfsclient/nfs_clrpcops.c
index 8feb2a8..e3101f7 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -45,7 +47,7 @@ __FBSDID("$FreeBSD$");
  */
 
 #ifndef APPLEKEXT
-#include "opt_inet6.h"
+#include <rtems/bsd/local/opt_inet6.h>
 
 #include <fs/nfs/nfsport.h>
 #include <sys/sysctl.h>
@@ -2959,41 +2961,57 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 			    return (error);
 			nd->nd_mrep = NULL;
 			dp = (struct dirent *)uio_iov_base(uiop);
+#ifndef __rtems__
 			dp->d_pad0 = dp->d_pad1 = 0;
+#endif /* __rtems__ */
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotfileid;
 			dp->d_namlen = 1;
+#ifndef __rtems__
 			*((uint64_t *)dp->d_name) = 0;	/* Zero pad it. */
+#else /* __rtems__ */
+			dp->d_name[1] = '\0';
+#endif /* __rtems__ */
 			dp->d_name[0] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
+#ifndef __rtems__
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
+#endif /* __rtems__ */
 			blksiz += dp->d_reclen;
 			uio_uio_resid_add(uiop, -(dp->d_reclen));
 			uiop->uio_offset += dp->d_reclen;
 			uio_iov_base_add(uiop, dp->d_reclen);
 			uio_iov_len_add(uiop, -(dp->d_reclen));
 			dp = (struct dirent *)uio_iov_base(uiop);
+#ifndef __rtems__
 			dp->d_pad0 = dp->d_pad1 = 0;
+#endif /* __rtems__ */
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotdotfileid;
 			dp->d_namlen = 2;
+#ifndef __rtems__
 			*((uint64_t *)dp->d_name) = 0;
+#else __rtems__
+			dp->d_name[2] = '\0';
+#endif /* __rtems__ */
 			dp->d_name[0] = '.';
 			dp->d_name[1] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
+#ifndef __rtems__
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
+#endif /* __rtems__ */
 			blksiz += dp->d_reclen;
 			uio_uio_resid_add(uiop, -(dp->d_reclen));
 			uiop->uio_offset += dp->d_reclen;
@@ -3106,7 +3124,9 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 				bigenough = 0;
 			if (bigenough) {
 				dp = (struct dirent *)uio_iov_base(uiop);
+#ifndef __rtems__
 				dp->d_pad0 = dp->d_pad1 = 0;
+#endif /* __rtems__ */
 				dp->d_off = 0;
 				dp->d_namlen = len;
 				dp->d_reclen = _GENERIC_DIRLEN(len) +
@@ -3127,6 +3147,10 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 				NFSBZERO(cp, tlen);
 				cp += tlen;	/* points to cookie storage */
 				tl2 = (u_int32_t *)cp;
+#ifdef __rtems__
+				tlen = dp->d_reclen -
+					(((char*) uio_iov_base(uiop) - (char*) dp) + NFSX_HYPER);
+#endif /* __rtems__ */
 				uio_iov_base_add(uiop, (tlen + NFSX_HYPER));
 				uio_iov_len_add(uiop, -(tlen + NFSX_HYPER));
 				uio_uio_resid_add(uiop, -(tlen + NFSX_HYPER));
@@ -3242,9 +3266,14 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 		dp = (struct dirent *)uio_iov_base(uiop);
 		NFSBZERO(dp, DIRBLKSIZ);
 		dp->d_type = DT_UNKNOWN;
+#ifndef __rtems__
 		tl = (u_int32_t *)&dp->d_name[4];
 		*tl++ = cookie.lval[0];
 		*tl = cookie.lval[1];
+#else /* __rtems__ */
+		memcpy(&dp->d_name[8], &cookie.lval[0], sizeof(u_int32_t));
+		memcpy(&dp->d_name[8 + sizeof(u_int32_t)], &cookie.lval[1], sizeof(u_int32_t));
+#endif /* __rtems__ */
 		dp->d_reclen = DIRBLKSIZ;
 		uio_iov_base_add(uiop, DIRBLKSIZ);
 		uio_iov_len_add(uiop, -(DIRBLKSIZ));
@@ -3396,41 +3425,61 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 			    return (error);
 			nd->nd_mrep = NULL;
 			dp = (struct dirent *)uio_iov_base(uiop);
+#ifndef __rtems__
 			dp->d_pad0 = dp->d_pad1 = 0;
+#endif /* __rtems__ */
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotfileid;
 			dp->d_namlen = 1;
+#ifndef __rtems__
 			*((uint64_t *)dp->d_name) = 0;	/* Zero pad it. */
+#else /* __rtems__ */
+			dp->d_name[0] = dp->d_name[1] = dp->d_name[2] = dp->d_name[3] = '\0';
+#endif /* __rtems__ */
 			dp->d_name[0] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
+#ifndef __rtems__
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
+#else /* __rtems__ */
+			memset(&dp->d_name[8], 0, 2 * sizeof(u_int32_t));
+#endif /* __rtems__ */
 			blksiz += dp->d_reclen;
 			uio_uio_resid_add(uiop, -(dp->d_reclen));
 			uiop->uio_offset += dp->d_reclen;
 			uio_iov_base_add(uiop, dp->d_reclen);
 			uio_iov_len_add(uiop, -(dp->d_reclen));
 			dp = (struct dirent *)uio_iov_base(uiop);
+#ifndef __rtems__
 			dp->d_pad0 = dp->d_pad1 = 0;
+#endif /* __rtems__ */
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotdotfileid;
 			dp->d_namlen = 2;
+#ifndef __rtems__
 			*((uint64_t *)dp->d_name) = 0;
+#else /* __rtems__ */
+			dp->d_name[0] = dp->d_name[1] = dp->d_name[2] = dp->d_name[3] = '\0';
+#endif /* __rtems__ */
 			dp->d_name[0] = '.';
 			dp->d_name[1] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
+#ifndef __rtems__
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
+#else /* __rtems__ */
+			memset(&dp->d_name[8], 0, 2 * sizeof(u_int32_t));
+#endif /* __rtems__ */
 			blksiz += dp->d_reclen;
 			uio_uio_resid_add(uiop, -(dp->d_reclen));
 			uiop->uio_offset += dp->d_reclen;
@@ -3524,7 +3573,9 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 				bigenough = 0;
 			if (bigenough) {
 				dp = (struct dirent *)uio_iov_base(uiop);
+#ifndef __rtems__
 				dp->d_pad0 = dp->d_pad1 = 0;
+#endif /* __rtems__ */
 				dp->d_off = 0;
 				dp->d_namlen = len;
 				dp->d_reclen = _GENERIC_DIRLEN(len) +
@@ -3745,9 +3796,14 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 		dp = (struct dirent *)uio_iov_base(uiop);
 		NFSBZERO(dp, DIRBLKSIZ);
 		dp->d_type = DT_UNKNOWN;
+#ifndef __rtems__
 		tl = (u_int32_t *)&dp->d_name[4];
 		*tl++ = cookie.lval[0];
 		*tl = cookie.lval[1];
+#else /* __rtems__ */
+		memcpy(&dp->d_name[8], &cookie.lval[0], sizeof(u_int32_t));
+		memcpy(&dp->d_name[8 + sizeof(u_int32_t)], &cookie.lval[1], sizeof(u_int32_t));
+#endif /* __rtems__ */
 		dp->d_reclen = DIRBLKSIZ;
 		uio_iov_base_add(uiop, DIRBLKSIZ);
 		uio_iov_len_add(uiop, -(DIRBLKSIZ));
@@ -4670,8 +4726,16 @@ nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclclient *clp,
 
 	/* Set the implementation id4 */
 	*tl = txdr_unsigned(1);
+#ifndef __rtems__
 	(void) nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
 	(void) nfsm_strtom(nd, version, strlen(version));
+#else /* __rtems__ */
+	{
+	  const char* rv = rtems_version();
+	  (void) nfsm_strtom(nd, "rtems.org", strlen("rtems.org"));
+	  (void) nfsm_strtom(nd, rv, strlen(rv));
+	}
+#endif /* __rtems__ */
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
 	verstime.tv_sec = 1293840000;		/* Jan 1, 2011 */
 	verstime.tv_nsec = 0;
@@ -7663,4 +7727,3 @@ out:
 	}
 	return (laystat);
 }
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clstate.c b/freebsd/sys/fs/nfsclient/nfs_clstate.c
index 0a2e4bc..6a93b18 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clstate.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clstate.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
@@ -5455,4 +5457,3 @@ tryagain:
 	NFSUNLOCKCLSTATE();
 	return (0);
 }
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clsubs.c b/freebsd/sys/fs/nfsclient/nfs_clsubs.c
index 1c69d93..af0f3c6 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clsubs.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clsubs.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -57,7 +59,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/stat.h>
 #include <sys/malloc.h>
 #include <sys/sysent.h>
+#ifndef __rtems__
 #include <sys/syscall.h>
+#endif /* __rtems__ */
 #include <sys/sysproto.h>
 #include <sys/taskqueue.h>
 
@@ -256,8 +260,10 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper)
 			vaper->va_mtime = np->n_mtim;
 	}
 	NFSUNLOCKNODE(np);
+#ifndef __rtems__
 	if (setnsize)
 		vnode_pager_setsize(vp, nsize);
+#endif /* __rtems__ */
 	KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
 	return (0);
 }
@@ -388,4 +394,3 @@ ncl_init(struct vfsconf *vfsp)
 
 	return (0);
 }
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clvfsops.c b/freebsd/sys/fs/nfsclient/nfs_clvfsops.c
index 348a64a..70a897f 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clvfsops.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -38,8 +40,8 @@
 __FBSDID("$FreeBSD$");
 
 
-#include "opt_bootp.h"
-#include "opt_nfsroot.h"
+#include <rtems/bsd/local/opt_bootp.h>
+#include <rtems/bsd/local/opt_nfsroot.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -49,7 +51,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/clock.h>
 #include <sys/jail.h>
 #include <sys/limits.h>
+#ifndef __rtems__
 #include <sys/lock.h>
+#endif /* __rtems__ */
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/module.h>
@@ -446,6 +450,7 @@ nfs_mountroot(struct mount *mp)
 	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
 	if (error)
 		panic("nfs_mountroot: SIOCAIFADDR: %d", error);
+#ifndef __rtems__
 	if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
 		ir.ifr_mtu = strtol(cp, NULL, 10);
 		bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
@@ -454,6 +459,7 @@ nfs_mountroot(struct mount *mp)
 		if (error)
 			printf("nfs_mountroot: SIOCSIFMTU: %d", error);
 	}
+#endif /* __rtems__ */
 	soclose(so);
 
 	/*
@@ -506,7 +512,9 @@ nfs_mountroot(struct mount *mp)
 	strlcpy(prison0.pr_hostname, nd->my_hostnam,
 	    sizeof(prison0.pr_hostname));
 	mtx_unlock(&prison0.pr_mtx);
+#ifndef __rtems__
 	inittodr(ntohl(nd->root_time));
+#endif /* __rtems__ */
 	return (0);
 }
 
@@ -1178,7 +1186,11 @@ nfs_mount(struct mount *mp)
 		 * "nfsreq".
 		 */
 		if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
+#ifndef __rtems__
 			tprintf(td->td_proc, LOG_WARNING,
+#else /* __rtems__ */
+			printf(
+#endif /* __rtems__ */
 	"Warning: mount -u that changes TCP->UDP can result in hung threads\n");
 
 		/*
@@ -2048,4 +2060,3 @@ void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
 	nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
 	nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
 }
-
diff --git a/freebsd/sys/fs/nfsclient/nfs_clvnops.c b/freebsd/sys/fs/nfsclient/nfs_clvnops.c
index 478ee05..d52d1b2 100644
--- a/freebsd/sys/fs/nfsclient/nfs_clvnops.c
+++ b/freebsd/sys/fs/nfsclient/nfs_clvnops.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -41,7 +43,7 @@ __FBSDID("$FreeBSD$");
  * vnode op calls for Sun NFS version 2, 3 and 4
  */
 
-#include "opt_inet.h"
+#include <rtems/bsd/local/opt_inet.h>
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -59,7 +61,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/vnode.h>
 #include <sys/dirent.h>
 #include <sys/fcntl.h>
+#ifndef __rtems__
 #include <sys/lockf.h>
+#endif /* __rtems__ */
 #include <sys/stat.h>
 #include <sys/sysctl.h>
 #include <sys/signalvar.h>
@@ -334,7 +338,9 @@ nfs_lock(struct vop_lock1_args *ap)
 	np->n_flag &= ~NVNSETSZSKIP;
 	nsize = np->n_size;
 	NFSUNLOCKNODE(np);
+#ifndef __rtems__
 	vnode_pager_setsize(vp, nsize);
+#endif /* __rtems__ */
 downgrade:
 	if (lktype == LK_SHARED) {
 		ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
@@ -683,7 +689,9 @@ nfs_open(struct vop_open_args *ap)
 
 	if (cred != NULL)
 		crfree(cred);
+#ifndef __rtems__
 	vnode_create_vobject(vp, vattr.va_size, ap->a_td);
+#endif /* __rtems__ */
 
 	/*
 	 * If the text file has been mmap'd, flush any dirty pages to the
@@ -694,12 +702,14 @@ nfs_open(struct vop_open_args *ap)
 	 * executing the text file to be terminated.
 	 */
 	if (vp->v_writecount <= -1) {
+#ifndef __rtems__
 		if ((obj = vp->v_object) != NULL &&
 		    (obj->flags & OBJ_MIGHTBEDIRTY) != 0) {
 			VM_OBJECT_WLOCK(obj);
 			vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
 			VM_OBJECT_WUNLOCK(obj);
 		}
+#endif /* __rtems__ */
 
 		/* Now, flush the buffer cache. */
 		ncl_flush(vp, MNT_WAIT, curthread, 0, 0);
@@ -778,11 +788,13 @@ nfs_close(struct vop_close_args *ap)
 	     * close, regardless of whether they were dirtied by
 	     * mmap'ed writes or via write().
 	     */
+#ifndef __rtems__
 	    if (nfs_clean_pages_on_close && vp->v_object) {
 		VM_OBJECT_WLOCK(vp->v_object);
 		vm_object_page_clean(vp->v_object, 0, 0, 0);
 		VM_OBJECT_WUNLOCK(vp->v_object);
 	    }
+#endif /* __rtems__ */
 	    NFSLOCKNODE(np);
 	    if (np->n_flag & NMODIFIED) {
 		NFSUNLOCKNODE(np);
@@ -805,7 +817,7 @@ nfs_close(struct vop_close_args *ap)
 		    int cm = newnfs_commit_on_close ? 1 : 0;
 		    error = ncl_flush(vp, MNT_WAIT, ap->a_td, cm, 0);
 		    /* np->n_flag &= ~NMODIFIED; */
-		} else if (NFS_ISV4(vp)) { 
+		} else if (NFS_ISV4(vp)) {
 			if (nfscl_mustflush(vp) != 0) {
 				int cm = newnfs_commit_on_close ? 1 : 0;
 				error = ncl_flush(vp, MNT_WAIT, ap->a_td,
@@ -821,10 +833,10 @@ nfs_close(struct vop_close_args *ap)
 		}
 		NFSLOCKNODE(np);
 	    }
- 	    /* 
+ 	    /*
  	     * Invalidate the attribute cache in all cases.
  	     * An open is going to fetch fresh attrs any way, other procs
- 	     * on this node that have file open will be forced to do an 
+ 	     * on this node that have file open will be forced to do an
  	     * otw attr fetch, but this is safe.
 	     * --> A user found that their RPC count dropped by 20% when
 	     *     this was commented out and I can't see any requirement
@@ -879,7 +891,7 @@ nfs_close(struct vop_close_args *ap)
 			 np->n_directio_asyncwr));
 	if (newnfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
 		NFSLOCKNODE(np);
-		KASSERT((np->n_directio_opens > 0), 
+		KASSERT((np->n_directio_opens > 0),
 			("nfs_close: unexpectedly value (0) of n_directio_opens\n"));
 		np->n_directio_opens--;
 		if (np->n_directio_opens == 0)
@@ -1009,7 +1021,7 @@ nfs_setattr(struct vop_setattr_args *ap)
 			    vap->va_mode == (mode_t)VNOVAL &&
 			    vap->va_uid == (uid_t)VNOVAL &&
 			    vap->va_gid == (gid_t)VNOVAL)
-				return (0);		
+				return (0);
  			vap->va_size = VNOVAL;
  			break;
  		default:
@@ -1036,7 +1048,9 @@ nfs_setattr(struct vop_setattr_args *ap)
 			    error = ncl_vinvalbuf(vp, vap->va_size == 0 ?
 			        0 : V_SAVE, td, 1);
 			    if (error != 0) {
+#ifndef __rtems__
 				    vnode_pager_setsize(vp, tsize);
+#endif /* __rtems__ */
 				    return (error);
 			    }
 			    /*
@@ -1058,7 +1072,7 @@ nfs_setattr(struct vop_setattr_args *ap)
   		}
   	} else {
 		NFSLOCKNODE(np);
-		if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) && 
+		if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) &&
 		    (np->n_flag & NMODIFIED) && vp->v_type == VREG) {
 			NFSUNLOCKNODE(np);
 			error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
@@ -1071,7 +1085,9 @@ nfs_setattr(struct vop_setattr_args *ap)
 	if (error && vap->va_size != VNOVAL) {
 		NFSLOCKNODE(np);
 		np->n_size = np->n_vattr.na_size = tsize;
+#ifndef __rtems__
 		vnode_pager_setsize(vp, tsize);
+#endif /* __rtems__ */
 		NFSUNLOCKNODE(np);
 	}
 	return (error);
@@ -1130,7 +1146,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	struct nfsvattr dnfsva, nfsva;
 	struct vattr vattr;
 	struct timespec nctime;
-	
+
 	*vpp = NULLVP;
 	if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) &&
 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
@@ -1207,7 +1223,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 		cache_purge(newvp);
 		if (dvp != newvp)
 			vput(newvp);
-		else 
+		else
 			vrele(newvp);
 		*vpp = NULLVP;
 	} else if (error == ENOENT) {
@@ -1363,7 +1379,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 			(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
 			    0, 1);
 		else if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
-		    !(np->n_flag & NMODIFIED)) {			
+		    !(np->n_flag & NMODIFIED)) {
 			/*
 			 * Flush the attribute cache when opening a
 			 * leaf node to ensure that fresh attributes
@@ -1695,7 +1711,7 @@ again:
 				/* try again without setting uid/gid */
 				vap->va_uid = (uid_t)VNOVAL;
 				vap->va_gid = (uid_t)VNOVAL;
-				error = nfsrpc_setattr(newvp, vap, NULL, 
+				error = nfsrpc_setattr(newvp, vap, NULL,
 				    cnp->cn_cred, cnp->cn_thread, &nfsva,
 				    &attrflag, NULL);
 			}
@@ -1883,7 +1899,7 @@ nfs_rename(struct vop_rename_args *ap)
 	 * under NFSV3.  NFSV2 does not have this problem because
 	 * ( as far as I can tell ) it flushes dirty buffers more
 	 * often.
-	 * 
+	 *
 	 * Skip the rename operation if the fsync fails, this can happen
 	 * due to the server's volume being full, when we pushed out data
 	 * that was written back to our cache earlier. Not checking for
@@ -2295,10 +2311,10 @@ nfs_readdir(struct vop_readdir_args *ap)
 	ssize_t tresid, left;
 	int error = 0;
 	struct vattr vattr;
-	
+
 	if (ap->a_eofflag != NULL)
 		*ap->a_eofflag = 0;
-	if (vp->v_type != VDIR) 
+	if (vp->v_type != VDIR)
 		return(EPERM);
 
 	/*
@@ -2342,7 +2358,7 @@ nfs_readdir(struct vop_readdir_args *ap)
 		if (ap->a_eofflag != NULL)
 			*ap->a_eofflag = 1;
 	}
-	
+
 	/* Add the partial DIRBLKSIZ (left) back in. */
 	uio->uio_resid += left;
 	return (error);
@@ -2376,7 +2392,7 @@ ncl_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
 		cookie = *cookiep;
 		ncl_dircookie_unlock(dnp);
 	} else {
-		ncl_dircookie_unlock(dnp);		
+		ncl_dircookie_unlock(dnp);
 		return (NFSERR_BAD_COOKIE);
 	}
 
@@ -2494,18 +2510,22 @@ nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
 	sp->s_dvp = dvp;
 	VREF(dvp);
 
-	/* 
+	/*
 	 * Fudge together a funny name.
-	 * Changing the format of the funny name to accommodate more 
+	 * Changing the format of the funny name to accommodate more
 	 * sillynames per directory.
-	 * The name is now changed to .nfs.<ticks>.<pid>.4, where ticks is 
+	 * The name is now changed to .nfs.<ticks>.<pid>.4, where ticks is
 	 * CPU ticks since boot.
 	 */
+#ifndef __rtems__
 	pid = cnp->cn_thread->td_proc->p_pid;
+#else /* __rtems__ */
+	pid = 1;
+#endif /* __rtems__ */
 	lticks = (unsigned int)ticks;
 	for ( ; ; ) {
-		sp->s_namlen = sprintf(sp->s_name, 
-				       ".nfs.%08x.%04x4.4", lticks, 
+		sp->s_namlen = sprintf(sp->s_name,
+				       ".nfs.%08x.%04x4.4", lticks,
 				       pid);
 		if (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 				 cnp->cn_thread, NULL))
@@ -3041,12 +3061,12 @@ loop:
 		while (np->n_directio_asyncwr > 0) {
 			np->n_flag |= NFSYNCWAIT;
 			error = newnfs_msleep(td, &np->n_directio_asyncwr,
-			    &np->n_mtx, slpflag | (PRIBIO + 1), 
+			    &np->n_mtx, slpflag | (PRIBIO + 1),
 			    "nfsfsync", 0);
 			if (error) {
 				if (newnfs_sigintr(nmp, td)) {
 					NFSUNLOCKNODE(np);
-					error = EINTR;	
+					error = EINTR;
 					goto done;
 				}
 			}
@@ -3106,7 +3126,7 @@ nfs_advlock(struct vop_advlock_args *ap)
 	struct vattr va;
 	int ret, error = EOPNOTSUPP;
 	u_quad_t size;
-	
+
 	ret = NFSVOPLOCK(vp, LK_SHARED);
 	if (ret != 0)
 		return (EBADF);
@@ -3115,9 +3135,11 @@ nfs_advlock(struct vop_advlock_args *ap)
 			NFSVOPUNLOCK(vp, 0);
 			return (EINVAL);
 		}
+#ifndef __rtems__
 		if ((ap->a_flags & F_POSIX) != 0)
 			cred = p->p_ucred;
 		else
+#endif /* __rtems__ */
 			cred = td->td_ucred;
 		NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY);
 		if (vp->v_iflag & VI_DOOMED) {
@@ -3198,6 +3220,7 @@ nfs_advlock(struct vop_advlock_args *ap)
 		NFSVOPUNLOCK(vp, 0);
 		return (0);
 	} else if (!NFS_ISV4(vp)) {
+#ifndef __rtems__
 		if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
 			size = VTONFS(vp)->n_size;
 			NFSVOPUNLOCK(vp, 0);
@@ -3220,6 +3243,10 @@ nfs_advlock(struct vop_advlock_args *ap)
 				NFSVOPUNLOCK(vp, 0);
 			}
 		}
+#else /* __rtems__ */
+		NFSVOPUNLOCK(vp, 0);
+		return (0);
+#endif /* __rtems__ */
 	} else
 		NFSVOPUNLOCK(vp, 0);
 	return (error);
@@ -3234,7 +3261,7 @@ nfs_advlockasync(struct vop_advlockasync_args *ap)
 	struct vnode *vp = ap->a_vp;
 	u_quad_t size;
 	int error;
-	
+
 	if (NFS_ISV4(vp))
 		return (EOPNOTSUPP);
 	error = NFSVOPLOCK(vp, LK_SHARED);
@@ -3243,7 +3270,9 @@ nfs_advlockasync(struct vop_advlockasync_args *ap)
 	if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
 		size = VTONFS(vp)->n_size;
 		NFSVOPUNLOCK(vp, 0);
+#ifndef __rtems__
 		error = lf_advlockasync(ap, &(vp->v_lockf), size);
+#endif /* __rtems__ */
 	} else {
 		NFSVOPUNLOCK(vp, 0);
 		error = EOPNOTSUPP;
@@ -3262,8 +3291,10 @@ nfs_print(struct vop_print_args *ap)
 
 	printf("\tfileid %jd fsid 0x%jx", (uintmax_t)np->n_vattr.na_fileid,
 	    (uintmax_t)np->n_vattr.na_fsid);
+#ifndef __rtems__
 	if (vp->v_type == VFIFO)
 		fifo_printinfo(vp);
+#endif /* __rtems__ */
 	printf("\n");
 	return (0);
 }
@@ -3296,7 +3327,9 @@ ncl_writebp(struct buf *bp, int force __unused, struct thread *td)
 	bp->b_iocmd = BIO_WRITE;
 
 	bufobj_wref(bp->b_bufobj);
+#ifndef __rtems__
 	curthread->td_ru.ru_oublock++;
+#endif /* __rtems__ */
 
 	/*
 	 * Note: to avoid loopback deadlocks, we do not
@@ -3364,6 +3397,7 @@ out:
 static int
 nfsfifo_read(struct vop_read_args *ap)
 {
+#ifndef __rtems__
 	struct nfsnode *np = VTONFS(ap->a_vp);
 	int error;
 
@@ -3375,7 +3409,10 @@ nfsfifo_read(struct vop_read_args *ap)
 	vfs_timestamp(&np->n_atim);
 	NFSUNLOCKNODE(np);
 	error = fifo_specops.vop_read(ap);
-	return error;	
+	return error;
+#else /* __rtems__ */
+	return (EINVAL);
+#endif /* __rtems__ */
 }
 
 /*
@@ -3384,6 +3421,7 @@ nfsfifo_read(struct vop_read_args *ap)
 static int
 nfsfifo_write(struct vop_write_args *ap)
 {
+#ifndef __rtems__
 	struct nfsnode *np = VTONFS(ap->a_vp);
 
 	/*
@@ -3394,6 +3432,9 @@ nfsfifo_write(struct vop_write_args *ap)
 	vfs_timestamp(&np->n_mtim);
 	NFSUNLOCKNODE(np);
 	return(fifo_specops.vop_write(ap));
+#else /* __rtems__ */
+	return (EINVAL);
+#endif /* __rtems__ */
 }
 
 /*
@@ -3404,6 +3445,7 @@ nfsfifo_write(struct vop_write_args *ap)
 static int
 nfsfifo_close(struct vop_close_args *ap)
 {
+#ifndef __rtems__
 	struct vnode *vp = ap->a_vp;
 	struct nfsnode *np = VTONFS(vp);
 	struct vattr vattr;
@@ -3432,6 +3474,9 @@ nfsfifo_close(struct vop_close_args *ap)
 	NFSUNLOCKNODE(np);
 out:
 	return (fifo_specops.vop_close(ap));
+#else /* __rtems__ */
+	return (EINVAL);
+#endif /* __rtems__ */
 }
 
 /*
@@ -3601,4 +3646,3 @@ nfs_pathconf(struct vop_pathconf_args *ap)
 	}
 	return (error);
 }
-
diff --git a/freebsd/sys/nfs/bootp_subr.c b/freebsd/sys/nfs/bootp_subr.c
index 07418af..d5c44ba 100644
--- a/freebsd/sys/nfs/bootp_subr.c
+++ b/freebsd/sys/nfs/bootp_subr.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
@@ -45,9 +47,9 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include "opt_bootp.h"
-#include "opt_nfs.h"
-#include "opt_rootdevname.h"
+#include <rtems/bsd/local/opt_bootp.h>
+#include <rtems/bsd/local/opt_nfs.h>
+#include <rtems/bsd/local/opt_rootdevname.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
diff --git a/freebsd/sys/nfs/krpc_subr.c b/freebsd/sys/nfs/krpc_subr.c
index 21e8e3a..16fb6ac 100644
--- a/freebsd/sys/nfs/krpc_subr.c
+++ b/freebsd/sys/nfs/krpc_subr.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*	$NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $	*/
 
 /*-
diff --git a/freebsd/sys/nfs/nfs_fha.c b/freebsd/sys/nfs/nfs_fha.c
index 8c5c144..ac4d7f1 100644
--- a/freebsd/sys/nfs/nfs_fha.c
+++ b/freebsd/sys/nfs/nfs_fha.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
diff --git a/freebsd/sys/nfs/nfs_lock.c b/freebsd/sys/nfs/nfs_lock.c
index efa1e80..e1d0433 100644
--- a/freebsd/sys/nfs/nfs_lock.c
+++ b/freebsd/sys/nfs/nfs_lock.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -41,7 +43,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
+#ifndef __rtems__
 #include <sys/lockf.h>		/* for hz */ /* Must come after sys/malloc.h */
+#endif /* __rtems__ */
 #include <sys/mbuf.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
@@ -50,7 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/resourcevar.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
-#include <sys/unistd.h>
+#include <rtems/bsd/sys/unistd.h>
 #include <sys/vnode.h>
 
 #include <net/if.h>
@@ -286,7 +290,9 @@ nfs_dolock(struct vop_advlock_args *ap)
 	if (p->p_nlminfo == NULL) {
 		p->p_nlminfo = malloc(sizeof(struct nlminfo),
 		    M_NLMINFO, M_WAITOK | M_ZERO);
+#ifndef __rtems__
 		p->p_nlminfo->pid_start = p->p_stats->p_start;
+#endif /* __rtems__ */
 		getboottime(&boottime);
 		timevaladd(&p->p_nlminfo->pid_start, &boottime);
 	}
@@ -337,7 +343,9 @@ nfs_dolock(struct vop_advlock_args *ap)
 
 		if (msg.lm_getlk && p->p_nlminfo->retcode == 0) {
 			if (p->p_nlminfo->set_getlk_pid) {
+#ifndef __rtems__
 				fl->l_sysid = 0; /* XXX */
+#endif /* __rtems__ */
 				fl->l_pid = p->p_nlminfo->getlk_pid;
 			} else {
 				fl->l_type = F_UNLCK;
@@ -364,9 +372,13 @@ nfslockdans(struct thread *td, struct lockd_ans *ansp)
 	if (ansp->la_vers != LOCKD_ANS_VERSION)
 		return (EINVAL);
 
+#ifndef __rtems__
 	/* Find the process, set its return errno and wake it up. */
 	if ((targetp = pfind(ansp->la_msg_ident.pid)) == NULL)
 		return (ESRCH);
+#else /* __rtems__ */
+	targetp = td->td_proc;
+#endif /* __rtems__ */
 
 	/* 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
diff --git a/freebsd/sys/nfs/nfs_nfssvc.c b/freebsd/sys/nfs/nfs_nfssvc.c
index 19ac16a..ce03773 100644
--- a/freebsd/sys/nfs/nfs_nfssvc.c
+++ b/freebsd/sys/nfs/nfs_nfssvc.c
@@ -1,3 +1,5 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -36,7 +38,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include "opt_nfs.h"
+#include <rtems/bsd/local/opt_nfs.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -49,17 +51,21 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/module.h>
 #include <sys/sysent.h>
+#ifndef __rtems__
 #include <sys/syscall.h>
+#endif /* __rtems__ */
 #include <sys/sysproto.h>
 
 #include <security/audit/audit.h>
 
 #include <nfs/nfssvc.h>
 
+#ifndef __rtems__
 static struct syscall_helper_data nfssvc_syscalls[] = {
 	SYSCALL_INIT_HELPER(nfssvc),
 	SYSCALL_INIT_LAST
 };
+#endif /* __rtems__ */
 
 /*
  * This tiny module simply handles the nfssvc() system call. The other
@@ -124,8 +130,10 @@ nfssvc_modevent(module_t mod, int type, void *data)
 
 	switch (type) {
 	case MOD_LOAD:
+#ifndef __rtems__
 		error = syscall_helper_register(nfssvc_syscalls,
 		    SY_THR_STATIC_KLD);
+#endif /* __rtems__ */
 		break;
 
 	case MOD_UNLOAD:
@@ -134,7 +142,9 @@ nfssvc_modevent(module_t mod, int type, void *data)
 			error = EBUSY;
 			break;
 		}
+#ifndef __rtems__
 		syscall_helper_unregister(nfssvc_syscalls);
+#endif /* __rtems__ */
 		break;
 	default:
 		error = EOPNOTSUPP;
@@ -151,4 +161,3 @@ DECLARE_MODULE(nfssvc, nfssvc_mod, SI_SUB_VFS, SI_ORDER_ANY);
 
 /* So that loader and kldload(2) can find us, wherever we are.. */
 MODULE_VERSION(nfssvc, 1);
-
diff --git a/freebsd/sys/nfsclient/nfs.h b/freebsd/sys/nfsclient/nfs.h
index ab50d89..0662c3c 100644
--- a/freebsd/sys/nfsclient/nfs.h
+++ b/freebsd/sys/nfsclient/nfs.h
@@ -39,7 +39,7 @@
 #define _NFSCLIENT_NFS_H_
 
 #ifdef _KERNEL
-#include "opt_nfs.h"
+#include <rtems/bsd/local/opt_nfs.h>
 #endif
 
 #include <nfsclient/nfsargs.h>
diff --git a/freebsd/sys/nfsclient/nfsnode.h b/freebsd/sys/nfsclient/nfsnode.h
index 3c6856d..2ceeeda 100644
--- a/freebsd/sys/nfsclient/nfsnode.h
+++ b/freebsd/sys/nfsclient/nfsnode.h
@@ -102,13 +102,17 @@ struct nfsnode {
 	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 */
+#ifndef __rtems__
 	struct vattr		n_vattr;	/* Vnode attribute cache */
+#endif /* __rtems__ */
 	time_t			n_attrstamp;	/* Attr. cache timestamp */
 	struct nfs_accesscache	n_accesscache[NFS_ACCESSCACHESIZE];
 	struct timespec		n_mtime;	/* Prev modify time. */
 	nfsfh_t			*n_fhp;		/* NFS File Handle */
+#ifndef __rtems__
 	struct vnode		*n_vnode;	/* associated vnode */
 	struct vnode		*n_dvp;		/* parent vnode */
+#endif /* __rtems__ */
 	int			n_error;	/* Save write error value */
 	union {
 		struct timespec	nf_atim;	/* Special file times */
diff --git a/libbsd.py b/libbsd.py
index 262b979..b27b95d 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -2885,6 +2885,138 @@ class rpc(builder.Module):
         )
 
 #
+# NFS
+#
+class nfs(builder.Module):
+
+    def __init__(self, manager):
+        super(nfs, self).__init__(manager, type(self).__name__)
+
+    def generate(self):
+        mm = self.manager
+        self.addDependency('rpc')
+        self.addKernelSpaceHeaderFiles(
+            [
+                'sys/nfs/krpc.h',
+                'sys/nfs/nfs_common.h',
+                'sys/nfs/nfs_fha.h',
+                'sys/nfs/nfs_kdtrace.h',
+                'sys/nfs/nfs_lock.h',
+                'sys/nfs/nfs_mountcommon.h',
+                'sys/nfs/nfsdiskless.h',
+                'sys/nfs/nfsproto.h',
+                'sys/nfs/nfssvc.h',
+                'sys/nfs/xdr_subs.h',
+                'sys/nfsclient/nfs.h',
+                'sys/nfsclient/nfsargs.h',
+                'sys/nfsclient/nfsm_subs.h',
+                'sys/nfsclient/nfsmount.h',
+                'sys/nfsclient/nfsnode.h',
+                'sys/nfsclient/nfsstats.h',
+                'sys/nfsclient/nlminfo.h',
+            ]
+        )
+        self.addKernelSpaceSourceFiles(
+            [
+                'sys/nfs/bootp_subr.c',
+                'sys/nfs/krpc_subr.c',
+                'sys/nfs/nfs_fha.c',
+                'sys/nfs/nfs_lock.c',
+                'sys/nfs/nfs_nfssvc.c',
+            ],
+            mm.generator['source']()
+        )
+
+#
+# File System NFS
+#
+class fs_nfs(builder.Module):
+
+    def __init__(self, manager):
+        super(fs_nfs, self).__init__(manager, type(self).__name__)
+
+    def generate(self):
+        mm = self.manager
+        self.addDependency('rpc')
+        self.addDependency('nfs')
+        self.addKernelSpaceHeaderFiles(
+            [
+                'sys/fs/nfs/nfs.h',
+                'sys/fs/nfs/nfs_var.h',
+                'sys/fs/nfs/nfscl.h',
+                'sys/fs/nfs/nfsclstate.h',
+                'sys/fs/nfs/nfsdport.h',
+                'sys/fs/nfs/nfskpiport.h',
+                'sys/fs/nfs/nfsm_subs.h',
+                'sys/fs/nfs/nfsport.h',
+                'sys/fs/nfs/nfsproto.h',
+                'sys/fs/nfs/nfsrvcache.h',
+                'sys/fs/nfs/nfsrvstate.h',
+                'sys/fs/nfs/nfsv4_errstr.h',
+                'sys/fs/nfs/rpcv2.h',
+                'sys/fs/nfs/xdr_subs.h',
+            ]
+        )
+        fs_nfs_cflags = ['-DEBADRPC=72',
+                         '-DPVFS=10']
+        self.addKernelSpaceSourceFiles(
+            [
+                'sys/fs/nfs/nfs_commonacl.c',
+                'sys/fs/nfs/nfs_commonkrpc.c',
+                'sys/fs/nfs/nfs_commonport.c',
+                'sys/fs/nfs/nfs_commonsubs.c',
+            ],
+            mm.generator['source']()
+        )
+
+
+#
+# File System NFS Client
+#
+class fs_nfsclient(builder.Module):
+
+    def __init__(self, manager):
+        super(fs_nfsclient, self).__init__(manager, type(self).__name__)
+
+    def generate(self):
+        mm = self.manager
+        self.addDependency('rpc')
+        self.addDependency('nfs')
+        self.addDependency('fs_nfs')
+        self.addKernelSpaceHeaderFiles(
+            [
+                'sys/fs/nfsclient/nfs.h',
+                'sys/fs/nfsclient/nfsmount.h',
+                'sys/fs/nfsclient/nfsnode.h',
+                'sys/fs/nfsclient/nlminfo.h',
+                'sys/fs/nfsclient/nfs_kdtrace.h',
+            ]
+        )
+        self.addKernelSpaceSourceFiles(
+            [
+                'sys/fs/nfsclient/nfs_clbio.c',
+                'sys/fs/nfsclient/nfs_clcomsubs.c',
+                'sys/fs/nfsclient/nfs_clkdtrace.c',
+                'sys/fs/nfsclient/nfs_clkrpc.c',
+                'sys/fs/nfsclient/nfs_clnfsiod.c',
+                'sys/fs/nfsclient/nfs_clnode.c',
+                'sys/fs/nfsclient/nfs_clport.c',
+                'sys/fs/nfsclient/nfs_clrpcops.c',
+                'sys/fs/nfsclient/nfs_clstate.c',
+                'sys/fs/nfsclient/nfs_clsubs.c',
+                'sys/fs/nfsclient/nfs_clvfsops.c',
+                'sys/fs/nfsclient/nfs_clvnops.c',
+            ],
+            mm.generator['source'](['-DDIRBLKSIZ=512'])
+        )
+        self.addRTEMSUserSourceFiles(
+            [
+                'fs/nfsclient/nfs.c'
+            ],
+            mm.generator['source']()
+        )
+
+#
 # PCI
 #
 class pci(builder.Module):
@@ -5312,7 +5444,8 @@ class tests(builder.Module):
         self.addTest(mm.generator['test']('ttcpshell01', ['test_main'], netTest = True, runTest = False))
         self.addTest(mm.generator['test']('epoch01', ['test_main'], extraLibs = ['rtemstest']))
         self.addTest(mm.generator['test']('nfs01', ['test_main'],
-                                          netTest = True, modules = ['nfsv2']))
+                                          netTest = True, modules = ['nfsv2', 'fs_nfsclient'],
+                                          extraLibs = ['telnetd']))
         self.addTest(mm.generator['test']('foobarclient', ['test_main'],
                                           runTest = False, netTest = True))
         self.addTest(mm.generator['test']('foobarserver', ['test_main'],
@@ -5447,6 +5580,9 @@ def load(mm):
     mm.addModule(nfsv2(mm))
 
     mm.addModule(rpc(mm))
+    mm.addModule(nfs(mm))
+    mm.addModule(fs_nfs(mm))
+    mm.addModule(fs_nfsclient(mm))
 
     # Add PCI
     mm.addModule(pci(mm))
diff --git a/rtemsbsd/fs/nfsclient/nfs.c b/rtemsbsd/fs/nfsclient/nfs.c
new file mode 100644
index 0000000..b252619
--- /dev/null
+++ b/rtemsbsd/fs/nfsclient/nfs.c
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup NFSClient
+ *
+ * @brief RTEMS bindings to the NFS client
+ *
+ */
+
+/*
+ * Copyright (C) 2021 Chris Johns <chris at contemporary.software>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <machine/rtems-bsd-kernel-space.h>
+#include <machine/rtems-bsd-libio.h>
+#include <machine/rtems-bsd-vfs.h>
+
+#include <sys/buf.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/time.h>
+#include <sys/vnode.h>
+
+#include <fs/nfsclient/nfs.h>
+#include <nfs/nfsproto.h>
+#include <nfsclient/nfs.h>
+#include <rtems/bsd/rootfs.h>
+#include <stdio.h>
+
+SYSINIT_MODULE_REFERENCE(rootfs);
+SYSINIT_MODULE_REFERENCE(nfs);
+
+#ifndef RTEMS_DEBUG
+#define RTEMS_DEBUG 0
+#endif
+
+#if RTEMS_DEBUG
+extern int nfscl_debuglevel;
+#endif
+
+int
+rtems_nfs_initialize(
+    rtems_filesystem_mount_table_entry_t *mt_entry, const void *data)
+{
+	struct thread *td = curthread;
+	const char *fspath = NULL;
+	char options[64];
+	char *at;
+	int error;
+
+	if (RTEMS_DEBUG) {
+		printf("nfsv4: mount: %s -> %s", mt_entry->type, mt_entry->dev,
+		    mt_entry->target);
+		if (data != NULL) {
+			printf(" (%s)", (const char *)data);
+		}
+		printf("\n");
+#ifdef RTEMS_NFSCL_DEBUGLEVEL
+		nfscl_debuglevel = RTEMS_NFSCL_DEBUGLEVEL;
+#endif
+	}
+
+	if (td == NULL) {
+		if (RTEMS_DEBUG)
+			printf("nfsv4: mount: no current thread\n");
+		error = ENOMEM;
+		goto out;
+	}
+
+	at = strchr(mt_entry->dev, '@');
+	if (at != NULL) {
+		if (RTEMS_DEBUG)
+			printf(
+			    "nfsv4: mount: user/group name in path not supported\n");
+		error = EINVAL;
+		goto out;
+	}
+
+	if (data != NULL) {
+		size_t opts_len = strnlen((const char *)data, sizeof(options));
+		if (opts_len >= sizeof(options)) {
+			if (RTEMS_DEBUG)
+				printf(
+				    "nfsv4: mount: options string too long\n");
+			error = EINVAL;
+			goto out;
+		}
+	}
+
+	rtems_bsd_vfs_mount_init(mt_entry);
+
+	fspath = mt_entry->target;
+	if (*fspath == '/') {
+		++fspath;
+	}
+	if (strchr(fspath, '/') != 0) {
+		error = EINVAL;
+		goto out;
+	}
+
+	rtems_bsd_libio_loc_set_vnode(&mt_entry->mt_fs_root->location, NULL);
+	rtems_bsd_libio_loc_set_vnode_dir(
+	    &mt_entry->mt_fs_root->location, NULL);
+
+	/*
+	 * Make the mount point in the BSD root file system, mount the NFS
+	 * export then find the vnode and hold it. Make sure we find the root
+	 * node of the NFS share and the not the root file system's mount node.
+	 */
+	error = rtems_bsd_rootfs_mkdir(fspath);
+	if (error == 0) {
+		struct mntarg *ma = NULL;
+		char errmsg[255];
+		ma = mount_arg(
+		    ma, "fstype", RTEMS_DECONST(char *, mt_entry->type), -1);
+		ma = mount_arg(ma, "fspath", RTEMS_DECONST(char *, fspath), -1);
+		ma = mount_arg(
+		    ma, "from", RTEMS_DECONST(char *, mt_entry->dev), -1);
+		if (mt_entry->writeable) {
+			ma = mount_arg(ma, "rw", NULL, 0);
+		} else {
+			ma = mount_arg(ma, "ro", NULL, 0);
+		}
+		if (data != NULL) {
+			char *opts;
+			/*
+			 * See `man mount_nfs` and the list of options.
+			 */
+			strlcpy(options, (const char *)data, sizeof(options));
+			opts = &options[0];
+			while (opts != NULL) {
+				char *delimiter = strchr(opts, ',');
+				char *opt = opts;
+				if (delimiter != NULL) {
+					*delimiter = '\0';
+					opts = delimiter + 1;
+				} else {
+					opts = NULL;
+				}
+				delimiter = strchr(opt, '=');
+				if (delimiter != NULL) {
+					*delimiter = '\0';
+					ma = mount_arg(
+					    ma, opt, delimiter + 1, -1);
+				} else {
+					ma = mount_arg(ma, opt, NULL, 0);
+				}
+			}
+		}
+		memset(errmsg, 0, sizeof(errmsg));
+		ma = mount_arg(ma, "errmsg", errmsg, sizeof(errmsg) - 1);
+		error = kernel_mount(ma, MNT_VERIFIED);
+		if (error == 0) {
+			struct nameidata nd;
+			vhold(rootvnode);
+			NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE,
+			    fspath, rootvnode, td);
+			error = namei(&nd);
+			if (error == 0) {
+				rtems_bsd_libio_loc_set_vnode(
+				    &mt_entry->mt_fs_root->location, nd.ni_vp);
+				rtems_bsd_vfs_clonenode(
+				    &mt_entry->mt_fs_root->location);
+				NDFREE(&nd, NDF_NO_VP_RELE);
+			} else {
+				NDFREE(&nd, 0);
+				rtems_bsd_libio_loc_set_vnode(
+				    &mt_entry->mt_fs_root->location, NULL);
+				rtems_bsd_vfs_freenode(
+				    &mt_entry->mt_fs_root->location);
+				rtems_bsd_rootfs_rmdir(fspath);
+			}
+		} else {
+			if (RTEMS_DEBUG)
+				printf("nfsv4: mount: error: %s\n", errmsg);
+		}
+	}
+
+	rtems_bsd_libio_loc_set_vnode_dir(
+	    &mt_entry->mt_fs_root->location, NULL);
+
+out:
+	if (RTEMS_DEBUG)
+		printf("nfsv4: mount: (%d) %s\n", error, strerror(error));
+	if (error != 0) {
+		if (fspath != NULL) {
+			rtems_bsd_rootfs_rmdir(fspath);
+		}
+	}
+	return error;
+}
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_kgssapi.h b/rtemsbsd/include/rtems/bsd/local/opt_kgssapi.h
new file mode 100644
index 0000000..e69de29
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_nfs.h b/rtemsbsd/include/rtems/bsd/local/opt_nfs.h
new file mode 100644
index 0000000..e69de29
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_nfsroot.h b/rtemsbsd/include/rtems/bsd/local/opt_nfsroot.h
new file mode 100644
index 0000000..e69de29
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_rootdevname.h b/rtemsbsd/include/rtems/bsd/local/opt_rootdevname.h
new file mode 100644
index 0000000..e69de29
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_ufs.h b/rtemsbsd/include/rtems/bsd/local/opt_ufs.h
new file mode 100644
index 0000000..e69de29
diff --git a/rtemsbsd/rtems/rtems-bsd-libio.c b/rtemsbsd/rtems/rtems-bsd-libio.c
index bb38594..fba8283 100644
--- a/rtemsbsd/rtems/rtems-bsd-libio.c
+++ b/rtemsbsd/rtems/rtems-bsd-libio.c
@@ -142,7 +142,7 @@ rtems_bsd_libio_loc_set_vnode(
 		old_new_hc = old->v_holdcnt;
 		old_new_rc = vrefcnt(old);
 	}
-	if (RTEMS_BSD_DESCRIP_TRACE || true)
+	if (RTEMS_BSD_DESCRIP_TRACE)
 		printf(
 		    "bsd: lio: set-vode loc=%p vn=%p (%d/%d)->(%d/%d) old=%p (%d/%d)->(%d/%d)\n",
 		    loc, vp, hc, rc, new_hc, new_rc, old, old_hc, old_rc,
diff --git a/testsuite/include/rtems/bsd/test/network-config.h.in b/testsuite/include/rtems/bsd/test/network-config.h.in
index 39bb538..fd63ede 100755
--- a/testsuite/include/rtems/bsd/test/network-config.h.in
+++ b/testsuite/include/rtems/bsd/test/network-config.h.in
@@ -64,4 +64,7 @@
 
 #define NET_CFG_GATEWAY_IP "@NET_CFG_GATEWAY_IP@"
 
+#define NET_CFG_NFS_MOUNT_PATH "@NET_CFG_NFS_MOUNT_PATH@"
+#define NET_CFG_NFS_MOUNT_OPTIONS "@NET_CFG_NFS_MOUNT_OPTIONS@"
+
 #endif /* _RTEMS_BSD_TEST_NETWORK_CONFIG_H_ */
diff --git a/testsuite/nfs01/test_main.c b/testsuite/nfs01/test_main.c
index 170cd48..21f64d1 100644
--- a/testsuite/nfs01/test_main.c
+++ b/testsuite/nfs01/test_main.c
@@ -5,6 +5,7 @@
  */
 
 /*
+ * Copyright (c) 2021 Chris Johns <chrisj at rtems.org>  All rights reserved.
  * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
@@ -36,38 +37,363 @@
  */
 
 #include <assert.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <rtems.h>
 #include <rtems/libio.h>
 
+#include <rtems/console.h>
+#include <rtems/shell.h>
+#include <rtems/telnetd.h>
+
 #include <librtemsNfs.h>
 
 #include <rtems/bsd/test/network-config.h>
 
 #define TEST_NAME "LIBBSD NFS 1"
-#define TEST_WAIT_FOR_LINK NET_CFG_INTERFACE_0
 #define TEST_STATE_USER_INPUT 1
 
+static const char *test_top = "test-nfs01";
+
+#define rtems_test_errno_assert(__exp) \
+  do { \
+    if (!(__exp)) { \
+      printf( "%s: %d errno:%d:%s %s\n", __FILE__, __LINE__, errno, strerror(errno), #__exp ); \
+      assert(1 == 0); \
+    } \
+  } while (0)
+
+typedef struct test_dir_entry
+{
+	struct test_dir_entry *next;
+	char name[4];
+} test_dir_entry;
+
+typedef struct test_dir
+{
+	struct test_dir *parent;
+	struct test_dir_entry *dirs;
+	struct test_dir_entry *indir;
+	const char *name;
+	int depth;
+	int num;
+} test_dir;
+
+/*
+ * Non-recursive directory tree walk
+ */
+typedef enum {
+	walk_tree_dir_start,
+	walk_tree_dir_end,
+	walk_tree_dir_entry
+} walk_tree_dir;
+
+typedef bool (*walk_tree_callout)(walk_tree_dir state,
+				  test_dir *dir,
+				  struct dirent *entry,
+				  struct stat* stat,
+				  void *data);
+
+static char
+test_stat_label(struct stat *s)
+{
+	if (S_ISBLK(s->st_mode)) {
+		return 'b';
+	}
+	if (S_ISCHR(s->st_mode)) {
+		return 'c';
+	}
+	if (S_ISDIR(s->st_mode)) {
+		return 'd';
+	}
+	if (S_ISFIFO(s->st_mode)) {
+		return 'F';
+	}
+	if (S_ISLNK(s->st_mode)) {
+		return 'l';
+	}
+	if (S_ISREG(s->st_mode)) {
+		return 'f';
+	}
+	if (S_ISSOCK(s->st_mode)) {
+		return 's';
+	}
+	return 'X';
+}
+
+static void
+test_walk_tree(const char *start, walk_tree_callout callout, void *data)
+{
+	test_dir top = {
+		.parent = NULL,
+		.dirs = NULL,
+		.indir = NULL,
+		.name = start,
+		.depth = 0,
+		.num = 0
+	};
+	test_dir *dir = ⊤
+	bool active = true;
+
+	rtems_test_errno_assert(chdir(start) == 0);
+
+	active = callout(walk_tree_dir_start, dir, NULL, NULL, data);
+
+	while (dir != NULL && active) {
+		test_dir *tmp_dir;
+		if (active && dir->dirs == NULL && dir->indir == NULL) {
+			struct DIR *ddir;
+			rtems_test_errno_assert((ddir = opendir(".")) != NULL);
+			while (active) {
+				struct dirent *dp;
+				struct stat s;
+				char t;
+				bool current_or_parent;
+				++dir->num;
+				dp = readdir(ddir);
+				if (dp == NULL) {
+					rtems_test_errno_assert(closedir(ddir) == 0);
+					break;
+				}
+				rtems_test_errno_assert(stat(dp->d_name, &s) == 0);
+				if ((dp->d_namlen == 1 && dp->d_name[0] == '.') ||
+				    (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')) {
+					current_or_parent = true;
+				} else {
+					current_or_parent = false;
+				}
+				t = test_stat_label(&s);
+				active = callout(walk_tree_dir_entry, dir, dp, &s, data);
+				if (active && !current_or_parent && t == 'd') {
+					test_dir_entry *dent;
+					assert((dent = malloc(sizeof(test_dir_entry) + dp->d_namlen)) != NULL);
+					dent->next = dir->dirs;
+					dir->dirs = dent;
+					strlcpy(&dent->name[0], dp->d_name, dp->d_namlen + sizeof(dent->name));
+				}
+			}
+		}
+		if (dir->dirs != NULL) {
+			free(dir->indir);
+			dir->indir = dir->dirs;
+			dir->dirs = dir->indir->next;
+			if (active && dir->indir != NULL) {
+				assert((tmp_dir = malloc(sizeof(test_dir))) != NULL);
+				tmp_dir->parent = dir;
+				tmp_dir->dirs = NULL;
+				tmp_dir->indir = NULL;
+				tmp_dir->name = dir->indir->name;
+				tmp_dir->depth = dir->depth + 1;
+				tmp_dir->num = 0;
+				dir = tmp_dir;
+				active = callout(walk_tree_dir_start, dir, NULL, NULL, data);
+				if (active) {
+					rtems_test_errno_assert(chdir(dir->name) == 0);
+				}
+			}
+		} else  {
+			rtems_test_errno_assert(chdir("..") == 0);
+			if (active) {
+				active = callout(walk_tree_dir_end, dir, NULL, NULL, data);
+			}
+			free(dir->indir);
+			tmp_dir = dir;
+			dir = dir->parent;
+			if (tmp_dir != &top) {
+				free(tmp_dir);
+			}
+		}
+	}
+}
+
+typedef struct test_printer_data {
+	char path[MAXPATHLEN];
+	int count;
+} test_printer_data;
+
+static bool
+test_walk_tree_printer(walk_tree_dir state,
+		       test_dir *dir,
+		       struct dirent *entry,
+		       struct stat* stat,
+		       void *data)
+{
+	test_printer_data *pd = (test_printer_data*) data;
+	int len;
+	switch (state) {
+	case walk_tree_dir_start:
+		strlcat(pd->path, dir->name, MAXPATHLEN);
+		strlcat(pd->path, "/", MAXPATHLEN);
+		break;
+	case walk_tree_dir_entry:
+		++pd->count;
+		printf("%8d %3d %6d %c 0%o %10lld %s%s\n",
+		       pd->count, dir->depth, dir->num, test_stat_label(stat),
+		       stat->st_mode & 0777, stat->st_size,
+		       pd->path, &entry->d_name[0]);
+		break;
+	case walk_tree_dir_end:
+		len = strlen(pd->path) - 1;
+		while (len > 0) {
+			len--;
+			if (pd->path[len] == '/') {
+				if (len < 1) {
+					break;
+				}
+				if (pd->path[len - 1] != '\\') {
+					break;
+				}
+				len -= 2;
+			}
+		}
+		pd->path[len + 1] = '\0';
+		break;
+	default:
+		break;
+	}
+	return true;
+}
+
+static bool
+test_walk_tree_unlink(walk_tree_dir state,
+		      test_dir *dir,
+		      struct dirent *entry,
+		      struct stat* stat,
+		      void *data)
+{
+	if (state == walk_tree_dir_entry) {
+		char type = test_stat_label(stat);
+		if (type != 'd') {
+			printf("unlink: %s\n", entry->d_name);
+			rtems_test_errno_assert(unlink(entry->d_name) == 0);
+		}
+	} else if (state == walk_tree_dir_end) {
+		 printf("rmdir: %s\n", dir->name);
+		 rtems_test_errno_assert(unlink(dir->name) == 0);
+	}
+	return true;
+}
+
+static void
+test_setup(const char *base)
+{
+	printf("test: nfs: setup\n");
+	printf("test: nfs: chdir: %s\n", base);
+	rtems_test_errno_assert(chdir(base) == 0);
+	printf("test: nfs: mkdir: %s\n", test_top);
+	rtems_test_errno_assert(mkdir(test_top, 0777) == 0);
+	printf("test: nfs: chdir: %s\n", test_top);
+	rtems_test_errno_assert(chdir(test_top) == 0);
+}
+
+static void
+test_cleanup(const char *base)
+{
+	printf("test: nfs: cleanup\n");
+	printf("test: nfs: chdir: %s\n", base);
+	rtems_test_errno_assert(chdir(base) == 0);
+	test_walk_tree(test_top, test_walk_tree_unlink, NULL);
+}
+
+static void
+test_path_eval(const char *base, int depth)
+{
+	char path[MAXPATHLEN];
+	int l;
+
+	printf("test path eval\n");
+
+	test_setup(base);
+
+	for (l = 1; l <= depth; ++l) {
+		snprintf(path, sizeof(path), "%d", l);
+		printf("test: nfs: mkdir: %s\n", path);
+		rtems_test_errno_assert(mkdir(path, 0777) == 0);
+		printf("test: nfs: chdir: %s\n", path);
+		rtems_test_errno_assert(chdir(path) == 0);
+		printf("test: nfs: getcwd: %s\n", path);
+		assert(getcwd(path, sizeof(path)) != NULL);
+		printf("test: nfs: getcwd: %s\n", path);
+	}
+
+	test_cleanup(base);
+}
+
+static void
+test_nfs(const char *base)
+{
+	test_printer_data pd;
+	test_path_eval(base, 5);
+	memset(&pd, 0, sizeof(pd));
+	test_walk_tree(base, test_walk_tree_printer, &pd);
+}
+
+static void
+telnet_shell(char *name, void *arg)
+{
+	rtems_shell_env_t env;
+
+	rtems_shell_dup_current_env(&env);
+
+	env.devname = name;
+	env.taskname = "TLNT";
+	env.login_check = NULL;
+	env.forever = false;
+
+	rtems_shell_main_loop(&env);
+}
+
+rtems_telnetd_config_table rtems_telnetd_config = {
+	.command = telnet_shell,
+	.arg = NULL,
+	.priority = 0,
+	.stack_size = 0,
+	.login_check = NULL,
+	.keep_stdio = false
+};
+
 static void
 test_main(void)
 {
-	static const char remote_target[] =
-	    "1000.100@" NET_CFG_PEER_IP " :/srv/nfs";
+	const char remote_target[] = NET_CFG_NFS_MOUNT_PATH;
+	const char *options = NET_CFG_NFS_MOUNT_OPTIONS;
+	const char *mount_options = NULL;
+	const char* mount_point = "/nfs";
+	int retries = 0;
 	int rv;
 
+	assert(rtems_telnetd_initialize() == RTEMS_SUCCESSFUL);
+
+	if (strlen(options) != 0) {
+		mount_options = options;
+	}
+
+	printf("mount: %s -> %s options:%s\n",
+	       remote_target, mount_point, mount_options);
+
 	do {
 		sleep(1);
-
-		rv = mount_and_make_target_path(&remote_target[0], "/nfs",
+		rv = mount_and_make_target_path(&remote_target[0], mount_point,
 		    RTEMS_FILESYSTEM_TYPE_NFS, RTEMS_FILESYSTEM_READ_WRITE,
-		    NULL);
-	} while (rv != 0);
+		    mount_options);
+		if (rv < 0) {
+			printf("mount: %d: %s\n", errno, strerror(errno));
+		}
+	} while (rv != 0 && retries++ < 5);
+
+	if (rv != 0) {
+		printf("error: NFS mount failed\n");
+		exit(rv);
+	}
+
+	test_nfs(mount_point);
 
 	rtems_task_delete(RTEMS_SELF);
 	assert(0);
 }
 
+#define CONFIGURE_SHELL_COMMANDS_ALL
 #define DEFAULT_NETWORK_SHELL
 
 #define CONFIGURE_FILESYSTEM_NFS
diff --git a/waf_libbsd.py b/waf_libbsd.py
index e7222a0..b18077c 100644
--- a/waf_libbsd.py
+++ b/waf_libbsd.py
@@ -289,7 +289,8 @@ class Builder(builder.ModuleManager):
                       (bld.env.NET_CONFIG))
         tags = [
             'NET_CFG_INTERFACE_0', 'NET_CFG_SELF_IP', 'NET_CFG_NETMASK',
-            'NET_CFG_PEER_IP', 'NET_CFG_GATEWAY_IP'
+            'NET_CFG_PEER_IP', 'NET_CFG_GATEWAY_IP', 'NET_CFG_NFS_MOUNT_PATH',
+            'NET_CFG_NFS_MOUNT_OPTIONS'
         ]
         try:
             net_cfg_lines = open(bld.env.NET_CONFIG).readlines()
@@ -307,9 +308,19 @@ class Builder(builder.ModuleManager):
                               'parse error: %d: %s' % (bld.env.NET_CONFIG, lc, l))
                 lhs = ls[0].strip()
                 rhs = ls[1].strip()
-                for t in tags:
-                    if lhs == t:
-                        sed += "-e 's/@%s@/%s/' " % (t, rhs)
+                for tag in tags:
+                    if lhs == tag:
+                        transpose = [(':', '\:'), ('/', '\/')]
+                        trhs = ''
+                        for c in rhs:
+                            for t in transpose:
+                                if c == t[0]:
+                                    trhs += t[1]
+                                    c = None
+                                    break
+                            if c is not None:
+                                trhs += c
+                        sed += "-e 's/@%s@/%s/' " % (tag, trhs)
         bld(target="testsuite/include/rtems/bsd/test/network-config.h",
             source="testsuite/include/rtems/bsd/test/network-config.h.in",
             rule=sed + " < ${SRC} > ${TGT}",
@@ -585,11 +596,14 @@ class Builder(builder.ModuleManager):
             test_source = []
             libs = ['bsd', 'm', 'z', 'rtemstest']
             for cfg in test:
-                build_test = True
-                for mod in test[cfg]['modules']:
-                    if mod not in enabled_modules:
-                        build_test = False
-                        break
+                if len(test[cfg]['modules']) == 0:
+                    build_test = True
+                else:
+                    build_test = False
+                    for mod in test[cfg]['modules']:
+                        if mod in enabled_modules:
+                            build_test = True
+                            break
                 if build_test and cfg != 'default':
                     for c in cfg.split(' '):
                         if not bld.env['HAVE_%s' % (c)]:



More information about the vc mailing list