From 58c4e1c59278acd4e87f5f4372ac6eb3ad0bafb5 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 10 Jun 2016 14:11:40 +0200 Subject: nfsclient: Port to LibBSD --- libbsd.py | 5 ++ libbsd_waf.py | 14 ++++ rtemsbsd/nfsclient/nfs.c | 6 +- rtemsbsd/nfsclient/rpcio.c | 161 +++++++++++++++++++++++--------------------- testsuite/nfs01/test_main.c | 69 +++++++++++++++++++ 5 files changed, 177 insertions(+), 78 deletions(-) create mode 100644 testsuite/nfs01/test_main.c diff --git a/libbsd.py b/libbsd.py index e7c7d066..d2659c4f 100755 --- a/libbsd.py +++ b/libbsd.py @@ -110,6 +110,10 @@ def rtems(mm): 'ftpfs/ftpfs.c', 'mdns/mdns.c', 'mdns/mdns-hostname-default.c', + 'nfsclient/mount_prot_xdr.c', + 'nfsclient/nfs.c', + 'nfsclient/nfs_prot_xdr.c', + 'nfsclient/rpcio.c', 'pppd/auth.c', 'pppd/ccp.c', 'pppd/chap.c', @@ -2496,6 +2500,7 @@ def in_cksum(mm): # def tests(mm): mod = builder.Module('tests') + mod.addTest(mm.generator['test']('nfs01', ['test_main'], netTest = True)) mod.addTest(mm.generator['test']('foobarclient', ['test_main'], runTest = False, netTest = True)) mod.addTest(mm.generator['test']('foobarserver', ['test_main'], diff --git a/libbsd_waf.py b/libbsd_waf.py index b751c9f5..25a979c1 100644 --- a/libbsd_waf.py +++ b/libbsd_waf.py @@ -1018,6 +1018,10 @@ def build(bld): 'rtemsbsd/local/usb_if.c', 'rtemsbsd/mdns/mdns-hostname-default.c', 'rtemsbsd/mdns/mdns.c', + 'rtemsbsd/nfsclient/mount_prot_xdr.c', + 'rtemsbsd/nfsclient/nfs.c', + 'rtemsbsd/nfsclient/nfs_prot_xdr.c', + 'rtemsbsd/nfsclient/rpcio.c', 'rtemsbsd/pppd/auth.c', 'rtemsbsd/pppd/ccp.c', 'rtemsbsd/pppd/chap.c', @@ -1337,6 +1341,16 @@ def build(bld): lib = ["m", "z"], install_path = None) + test_nfs01 = ['testsuite/nfs01/test_main.c'] + bld.program(target = "nfs01.exe", + features = "cprogram", + cflags = cflags, + includes = includes, + source = test_nfs01, + use = ["bsd"], + lib = ["m", "z"], + install_path = None) + test_ping01 = ['testsuite/ping01/test_main.c'] bld.program(target = "ping01.exe", features = "cprogram", diff --git a/rtemsbsd/nfsclient/nfs.c b/rtemsbsd/nfsclient/nfs.c index 17a726df..fae79b86 100644 --- a/rtemsbsd/nfsclient/nfs.c +++ b/rtemsbsd/nfsclient/nfs.c @@ -79,11 +79,11 @@ #include #include -#include -#include +#include "nfs_prot.h" +#include "mount_prot.h" #include "rpcio.h" -#include "librtemsNfs.h" +#include /* Configurable parameters */ diff --git a/rtemsbsd/nfsclient/rpcio.c b/rtemsbsd/nfsclient/rpcio.c index 28482251..6bc1aada 100644 --- a/rtemsbsd/nfsclient/rpcio.c +++ b/rtemsbsd/nfsclient/rpcio.c @@ -71,7 +71,7 @@ #include #include -#include +#include #include #include #include @@ -85,6 +85,7 @@ #include #include #include +#include #include "rpcio.h" #include "nfsclient-private.h" @@ -93,14 +94,14 @@ /* CONFIGURABLE PARAMETERS */ /****************************************************************/ -#define MBUF_RX /* If defined: use mbuf XDR stream for +#undef MBUF_RX /* If defined: use mbuf XDR stream for * decoding directly out of mbufs * Otherwise, the regular 'recvfrom()' * interface will be used involving an * extra buffer allocation + copy step. */ -#define MBUF_TX /* If defined: avoid copying data when +#undef MBUF_TX /* If defined: avoid copying data when * sending. Instead, use a wrapper to * 'sosend()' which will point an MBUF * directly to our buffer space. @@ -121,8 +122,7 @@ */ /* daemon task parameters */ -#define RPCIOD_STACK 10000 -#define RPCIOD_PRIO 100 /* *fallback* priority */ +#define RPCIOD_NAME "RPCD" /* depth of the message queue for sending * RPC requests to the daemon @@ -149,9 +149,10 @@ static struct timeval _rpc_default_timeout = { 10 /* secs */, 0 /* usecs */ }; * RPC IO will receive this - hence it is * RESERVED */ -#define RPCIOD_RX_EVENT RTEMS_EVENT_1 /* Events the RPCIOD is using/waiting for */ -#define RPCIOD_TX_EVENT RTEMS_EVENT_2 -#define RPCIOD_KILL_EVENT RTEMS_EVENT_3 /* send to the daemon to kill it */ +#define RPCIOD_KQ_IDENT 0xeb +#define RPCIOD_RX_EVENT 0x1 /* Events the RPCIOD is using/waiting for */ +#define RPCIOD_TX_EVENT 0x2 +#define RPCIOD_KILL_EVENT 0x4 /* send to the daemon to kill it */ #define LD_XACT_HASH 8 /* ld of the size of the transaction hash table */ @@ -393,6 +394,7 @@ static RpcUdpServer rpcUdpServers = 0; /* linked list of all servers; protected static int ourSock = -1; /* the socket we are using for communication */ static rtems_id rpciod = 0; /* task id of the RPC daemon */ +static int rpcKq = -1; /* the kqueue of the RPC daemon */ static rtems_id msgQ = 0; /* message queue where the daemon picks up * requests */ @@ -407,12 +409,6 @@ static rtems_interval ticksPerSec; /* cached system clock rate (WHO IS ASSUMED * TO CHANGE) */ -rtems_task_priority rpciodPriority = 0; -#ifdef RTEMS_SMP -const cpu_set_t *rpciodCpuset = 0; -size_t rpciodCpusetSize = 0; -#endif - #if (DEBUG) & DEBUG_MALLOC /* malloc wrappers for debugging */ static int nibufs = 0; @@ -481,15 +477,34 @@ bool_t rval; } static inline bool_t -locked_refresh(RpcUdpServer s) +locked_refresh(RpcUdpServer s, struct rpc_msg *msg) { bool_t rval; MU_LOCK(s->authlock); - rval = AUTH_REFRESH(s->auth); + rval = AUTH_REFRESH(s->auth, msg); MU_UNLOCK(s->authlock); return rval; } +static void +sendEventToRpcServer(u_int events) +{ +struct kevent trigger; +int s; + + EV_SET( + &trigger, + RPCIOD_KQ_IDENT, + EVFILT_USER, + 0, + NOTE_TRIGGER | NOTE_FFOR | events, + 0, + 0); + + s = kevent(rpcKq, &trigger, 1, NULL, 0, NULL); + assert(s == 0); +} + /* Create a server object * */ @@ -507,7 +522,7 @@ RpcUdpServer rval; u_short port; char hname[MAX_MACHINE_NAME + 1]; int theuid, thegid; -int thegids[NGRPS]; +u_int thegids[NGRPS]; gid_t gids[NGROUPS]; int len,i; AUTH *auth; @@ -828,7 +843,7 @@ va_list ap; return RPC_CANTSEND; } /* wakeup the rpciod */ - ASSERT( RTEMS_SUCCESSFUL==rtems_event_send(rpciod, RPCIOD_TX_EVENT) ); + sendEventToRpcServer(RPCIOD_TX_EVENT); return RPC_SUCCESS; } @@ -911,14 +926,14 @@ rtems_event_set gotEvents; xact->ibufsize = 0; #endif - if (refresh && locked_refresh(xact->server)) { + if (refresh && locked_refresh(xact->server, &reply_msg)) { rtems_task_ident(RTEMS_SELF, RTEMS_WHO_AM_I, &xact->requestor); if ( rtems_message_queue_send(msgQ, &xact, sizeof(xact)) ) { return RPC_CANTSEND; } /* wakeup the rpciod */ fprintf(stderr,"RPCIO INFO: refreshing my AUTH\n"); - ASSERT( RTEMS_SUCCESSFUL==rtems_event_send(rpciod, RPCIOD_TX_EVENT) ); + sendEventToRpcServer(RPCIOD_TX_EVENT); } } while ( 0 && refresh-- > 0 ); @@ -926,17 +941,6 @@ rtems_event_set gotEvents; return xact->status.re_status; } - -/* On RTEMS, I'm told to avoid select(); this seems to - * be more efficient - */ -static void -rxWakeupCB(struct socket *sock, void *arg) -{ - rtems_id *rpciod = (rtems_id*) arg; - rtems_event_send(*rpciod, RPCIOD_RX_EVENT); -} - void rpcSetXIDs(uint32_t xid) { @@ -955,7 +959,7 @@ rpcUdpInit(void) int s; rtems_status_code status; int noblock = 1; -struct sockwakeup wkup; +struct kevent change; if (ourSock < 0) { fprintf(stderr,"RTEMS-RPCIOD $Release$, " \ @@ -972,34 +976,41 @@ struct sockwakeup wkup; MU_CREAT( &hlock ); MU_CREAT( &llock ); - if ( !rpciodPriority ) { - /* use configured networking priority */ - if ( ! (rpciodPriority = rtems_bsdnet_config.network_task_priority) ) - rpciodPriority = RPCIOD_PRIO; /* fallback value */ - } + rpcKq = kqueue(); + assert( rpcKq >= 0 ); + + EV_SET( + &change, + RPCIOD_KQ_IDENT, + EVFILT_USER, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_FFNOP, + 0, + 0); + + s = kevent( rpcKq, &change, 1, NULL, 0, NULL ); + assert( s == 0 ); + + EV_SET( + &change, + ourSock, + EVFILT_READ, EV_ADD | EV_ENABLE, + 0, + 0, + 0); + + s = kevent( rpcKq, &change, 1, NULL, 0, NULL ); + assert( s == 0 ); status = rtems_task_create( rtems_build_name('R','P','C','d'), - rpciodPriority, - RPCIOD_STACK, + rtems_bsd_get_task_priority(RPCIOD_NAME), + rtems_bsd_get_task_stack_size(RPCIOD_NAME), RTEMS_DEFAULT_MODES, /* fprintf saves/restores FP registers on PPC :-( */ RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &rpciod); assert( status == RTEMS_SUCCESSFUL ); -#ifdef RTEMS_SMP - if ( rpciodCpuset == 0 ) { - rpciodCpuset = rtems_bsdnet_config.network_task_cpuset; - rpciodCpusetSize = rtems_bsdnet_config.network_task_cpuset_size; - } - if ( rpciodCpuset != 0 ) - rtems_task_set_affinity( rpciod, rpciodCpusetSize, rpciodCpuset ); -#endif - - wkup.sw_pfn = rxWakeupCB; - wkup.sw_arg = &rpciod; - assert( 0==setsockopt(ourSock, SOL_SOCKET, SO_RCVWAKEUP, &wkup, sizeof(wkup)) ); status = rtems_message_queue_create( rtems_build_name('R','P','C','q'), RPCIOD_QDEPTH, @@ -1026,7 +1037,7 @@ rpcUdpCleanup(void) RTEMS_DEFAULT_ATTRIBUTES, 0, &fini); - rtems_event_send(rpciod, RPCIOD_KILL_EVENT); + sendEventToRpcServer(RPCIOD_KILL_EVENT); /* synchronize with daemon */ rtems_semaphore_obtain(fini, RTEMS_WAIT, 5*ticksPerSec); /* if the message queue is still there, something went wrong */ @@ -1175,12 +1186,11 @@ nodeAppend(ListNode l, ListNode n) static void rpcio_daemon(rtems_task_argument arg) { -rtems_status_code stat; RpcUdpXact xact; RpcUdpServer srv; rtems_interval next_retrans, then, unow; long now; /* need to do signed comparison with age! */ -rtems_event_set events; +u_int events; ListNode newList; size_t size; rtems_id q = 0; @@ -1193,15 +1203,27 @@ rtems_status_code status; then = rtems_clock_get_ticks_since_boot(); for (next_retrans = epoch;;) { + { + struct timespec timeout = { + .tv_sec = (next_retrans + ticksPerSec - 1) / ticksPerSec, + .tv_nsec = 0 + }; + struct kevent event[2]; + int i; + int n; + + n = kevent(rpcKq, NULL, 0, &event[0], 2, &timeout); + assert(n >= 0); - if ( RTEMS_SUCCESSFUL != - (stat = rtems_event_receive( - RPCIOD_RX_EVENT | RPCIOD_TX_EVENT | RPCIOD_KILL_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - next_retrans, - &events)) ) { - ASSERT( RTEMS_TIMEOUT == stat ); events = 0; + + for (i = 0; i < n; ++i) { + if (event[i].filter == EVFILT_USER) { + events |= event[i].fflags; + } else { + events |= RPCIOD_RX_EVENT; + } + } } if (events & RPCIOD_KILL_EVENT) { @@ -1498,6 +1520,7 @@ rtems_status_code status; } /* close our socket; shut down the receiver */ close(ourSock); + close(rpcKq); #if 0 /* if we get here, no transactions exist, hence there can be none * in the queue whatsoever @@ -1625,7 +1648,7 @@ RpcUdpXactPool pool; * the RTEMS/BSDNET headers redefine those :-( */ -#define _KERNEL +#include #include static void @@ -1687,7 +1710,7 @@ union { struct sockaddr_in sin; struct sockaddr sa; } fromAddr; -int fromLen = sizeof(fromAddr.sin); +socklen_t fromLen = sizeof(fromAddr.sin); RxBuf ibuf = 0; RpcUdpXact xact = 0; @@ -1800,15 +1823,3 @@ cleanup: return 0; } - - -#include -/* double check the event configuration; should probably globally - * manage system events!! - * We do this at the end of the file for the same reason we had - * included mbuf.h only a couple of lines above - see comment up - * there... - */ -#if RTEMS_RPC_EVENT & SOSLEEP_EVENT & SBWAIT_EVENT & NETISR_EVENTS -#error ILLEGAL EVENT CONFIGURATION -#endif diff --git a/testsuite/nfs01/test_main.c b/testsuite/nfs01/test_main.c new file mode 100644 index 00000000..37d48ac4 --- /dev/null +++ b/testsuite/nfs01/test_main.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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 AUTHOR 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 AUTHOR 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 +#include + +#include +#include + +#include + +#include + +#define TEST_NAME "LIBBSD NFS 1" + +static void +test_main(void) +{ + static const char remote_target[] = + "1000.100@" NET_CFG_PEER_IP " :/srv/nfs"; + int rv; + + do { + sleep(1); + + rv = mount_and_make_target_path(&remote_target[0], "/nfs", + RTEMS_FILESYSTEM_TYPE_NFS, RTEMS_FILESYSTEM_READ_WRITE, + NULL); + } while (rv != 0); + + rtems_task_delete(RTEMS_SELF); + assert(0); +} + +#define DEFAULT_NETWORK_SHELL + +#define CONFIGURE_FILESYSTEM_NFS + +#define CONFIGURE_MAXIMUM_DRIVERS 32 + +#include -- cgit v1.2.3