X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lnet%2Fklnds%2Fqswlnd%2Fqswlnd.c;h=c595450684aadb55fb7bb7baf11f7cc1dc7319ac;hb=23de47e82bd999ec651f927097922413527cca71;hp=a386eef85e10a531e21ce339827d9c5036fcc911;hpb=090c677210ee2946d99c71412e4ff762bb300f4f;p=fs%2Flustre-release.git diff --git a/lnet/klnds/qswlnd/qswlnd.c b/lnet/klnds/qswlnd/qswlnd.c index a386eef..c595450 100644 --- a/lnet/klnds/qswlnd/qswlnd.c +++ b/lnet/klnds/qswlnd/qswlnd.c @@ -24,9 +24,10 @@ #include "qswnal.h" -ptl_handle_ni_t kqswnal_ni; nal_t kqswnal_api; kqswnal_data_t kqswnal_data; +ptl_handle_ni_t kqswnal_ni; +kqswnal_tunables_t kqswnal_tunables; kpr_nal_interface_t kqswnal_router_interface = { kprni_nalid: QSWNAL, @@ -42,11 +43,11 @@ kpr_nal_interface_t kqswnal_router_interface = { #define QSWNAL_SYSCTL_COPY_SMALL_FWD 2 static ctl_table kqswnal_ctl_table[] = { - {QSWNAL_SYSCTL_OPTIMIZED_GETS, "optimized_gets", - &kqswnal_data.kqn_optimized_gets, sizeof (int), + {QSWNAL_SYSCTL_OPTIMIZED_GETS, "optimized_puts", + &kqswnal_tunables.kqn_optimized_puts, sizeof (int), 0644, NULL, &proc_dointvec}, - {QSWNAL_SYSCTL_COPY_SMALL_FWD, "copy_small_fwd", - &kqswnal_data.kqn_copy_small_fwd, sizeof (int), + {QSWNAL_SYSCTL_OPTIMIZED_GETS, "optimized_gets", + &kqswnal_tunables.kqn_optimized_gets, sizeof (int), 0644, NULL, &proc_dointvec}, {0} }; @@ -57,111 +58,6 @@ static ctl_table kqswnal_top_ctl_table[] = { }; #endif -static int -kqswnal_forward(nal_t *nal, - int id, - void *args, size_t args_len, - void *ret, size_t ret_len) -{ - kqswnal_data_t *k = nal->nal_data; - nal_cb_t *nal_cb = k->kqn_cb; - - LASSERT (nal == &kqswnal_api); - LASSERT (k == &kqswnal_data); - LASSERT (nal_cb == &kqswnal_lib); - - lib_dispatch(nal_cb, k, id, args, ret); /* nal needs k */ - return (PTL_OK); -} - -static void -kqswnal_lock (nal_t *nal, unsigned long *flags) -{ - kqswnal_data_t *k = nal->nal_data; - nal_cb_t *nal_cb = k->kqn_cb; - - LASSERT (nal == &kqswnal_api); - LASSERT (k == &kqswnal_data); - LASSERT (nal_cb == &kqswnal_lib); - - nal_cb->cb_cli(nal_cb,flags); -} - -static void -kqswnal_unlock(nal_t *nal, unsigned long *flags) -{ - kqswnal_data_t *k = nal->nal_data; - nal_cb_t *nal_cb = k->kqn_cb; - - LASSERT (nal == &kqswnal_api); - LASSERT (k == &kqswnal_data); - LASSERT (nal_cb == &kqswnal_lib); - - nal_cb->cb_sti(nal_cb,flags); -} - -static int -kqswnal_shutdown(nal_t *nal, int ni) -{ - CDEBUG (D_NET, "shutdown\n"); - - LASSERT (nal == &kqswnal_api); - return (0); -} - -static int -kqswnal_yield(nal_t *nal, unsigned long *flags, int milliseconds) -{ - /* NB called holding statelock */ - wait_queue_t wait; - unsigned long now = jiffies; - - CDEBUG (D_NET, "yield\n"); - - if (milliseconds == 0) { - if (current->need_resched) - schedule(); - return 0; - } - - init_waitqueue_entry(&wait, current); - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&kqswnal_data.kqn_yield_waitq, &wait); - - kqswnal_unlock(nal, flags); - - if (milliseconds < 0) - schedule (); - else - schedule_timeout((milliseconds * HZ) / 1000); - - kqswnal_lock(nal, flags); - - remove_wait_queue(&kqswnal_data.kqn_yield_waitq, &wait); - - if (milliseconds > 0) { - milliseconds -= ((jiffies - now) * 1000) / HZ; - if (milliseconds < 0) - milliseconds = 0; - } - - return (milliseconds); -} - -static nal_t * -kqswnal_init(int interface, ptl_pt_index_t ptl_size, ptl_ac_index_t ac_size, - ptl_pid_t requested_pid) -{ - ptl_nid_t mynid = kqswnal_elanid2nid (kqswnal_data.kqn_elanid); - int nnids = kqswnal_data.kqn_nnodes; - - CDEBUG(D_NET, "calling lib_init with nid "LPX64" of %d\n", mynid, nnids); - - lib_init(&kqswnal_lib, mynid, 0, nnids, ptl_size, ac_size); - - return (&kqswnal_api); -} - int kqswnal_get_tx_desc (struct portals_cfg *pcfg) { @@ -211,7 +107,7 @@ kqswnal_cmd (struct portals_cfg *pcfg, void *private) kqswnal_data.kqn_nid_offset); kqswnal_data.kqn_nid_offset = pcfg->pcfg_nid - kqswnal_data.kqn_elanid; - kqswnal_lib.ni.nid = pcfg->pcfg_nid; + kqswnal_lib.libnal_ni.ni_pid.nid = pcfg->pcfg_nid; return (0); default: @@ -219,26 +115,32 @@ kqswnal_cmd (struct portals_cfg *pcfg, void *private) } } -void __exit -kqswnal_finalise (void) +static void +kqswnal_shutdown(nal_t *nal) { + unsigned long flags; + int do_lib_fini = 0; + + /* NB The first ref was this module! */ + if (nal->nal_refct != 0) { + PORTAL_MODULE_UNUSE; + return; + } + + CDEBUG (D_NET, "shutdown\n"); + LASSERT (nal == &kqswnal_api); + switch (kqswnal_data.kqn_init) { default: LASSERT (0); case KQN_INIT_ALL: -#if CONFIG_SYSCTL - if (kqswnal_data.kqn_sysctl != NULL) - unregister_sysctl_table (kqswnal_data.kqn_sysctl); -#endif - PORTAL_SYMBOL_UNREGISTER (kqswnal_ni); - kportal_nal_unregister(QSWNAL); + libcfs_nal_cmd_unregister(QSWNAL); /* fall through */ - case KQN_INIT_PTL: - PtlNIFini (kqswnal_ni); - lib_fini (&kqswnal_lib); + case KQN_INIT_LIB: + do_lib_fini = 1; /* fall through */ case KQN_INIT_DATA: @@ -249,18 +151,24 @@ kqswnal_finalise (void) } /**********************************************************************/ - /* Make router stop her calling me and fail any more call-ins */ + /* Tell router we're shutting down. Any router calls my threads + * make will now fail immediately and the router will stop calling + * into me. */ kpr_shutdown (&kqswnal_data.kqn_router); - + /**********************************************************************/ - /* flag threads we've started to terminate and wait for all to ack */ - + /* Signal the start of shutdown... */ + spin_lock_irqsave(&kqswnal_data.kqn_idletxd_lock, flags); kqswnal_data.kqn_shuttingdown = 1; - wake_up_all (&kqswnal_data.kqn_sched_waitq); + spin_unlock_irqrestore(&kqswnal_data.kqn_idletxd_lock, flags); + + wake_up_all(&kqswnal_data.kqn_idletxd_waitq); - while (atomic_read (&kqswnal_data.kqn_nthreads_running) != 0) { - CDEBUG(D_NET, "waiting for %d threads to start shutting down\n", - atomic_read (&kqswnal_data.kqn_nthreads_running)); + /**********************************************************************/ + /* wait for sends that have allocated a tx desc to launch or give up */ + while (atomic_read (&kqswnal_data.kqn_pending_txs) != 0) { + CDEBUG(D_NET, "waiting for %d pending sends\n", + atomic_read (&kqswnal_data.kqn_pending_txs)); set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (HZ); } @@ -268,18 +176,27 @@ kqswnal_finalise (void) /**********************************************************************/ /* close elan comms */ #if MULTIRAIL_EKC + /* Shut down receivers first; rx callbacks might try sending... */ if (kqswnal_data.kqn_eprx_small != NULL) ep_free_rcvr (kqswnal_data.kqn_eprx_small); if (kqswnal_data.kqn_eprx_large != NULL) ep_free_rcvr (kqswnal_data.kqn_eprx_large); + /* NB ep_free_rcvr() returns only after we've freed off all receive + * buffers (see shutdown handling in kqswnal_requeue_rx()). This + * means we must have completed any messages we passed to + * lib_parse() or kpr_fwd_start(). */ + if (kqswnal_data.kqn_eptx != NULL) ep_free_xmtr (kqswnal_data.kqn_eptx); - /* freeing the xmtr completes all txs pdq */ + /* NB ep_free_xmtr() returns only after all outstanding transmits + * have called their callback... */ LASSERT(list_empty(&kqswnal_data.kqn_activetxds)); #else + /* "Old" EKC just pretends to shutdown cleanly but actually + * provides no guarantees */ if (kqswnal_data.kqn_eprx_small != NULL) ep_remove_large_rcvr (kqswnal_data.kqn_eprx_small); @@ -298,7 +215,6 @@ kqswnal_finalise (void) #endif /**********************************************************************/ /* flag threads to terminate, wake them and wait for them to die */ - kqswnal_data.kqn_shuttingdown = 2; wake_up_all (&kqswnal_data.kqn_sched_waitq); @@ -316,10 +232,12 @@ kqswnal_finalise (void) #if MULTIRAIL_EKC LASSERT (list_empty (&kqswnal_data.kqn_readyrxds)); + LASSERT (list_empty (&kqswnal_data.kqn_delayedtxds)); + LASSERT (list_empty (&kqswnal_data.kqn_delayedfwds)); #endif /**********************************************************************/ - /* Complete any blocked forwarding packets with error + /* Complete any blocked forwarding packets, with error */ while (!list_empty (&kqswnal_data.kqn_idletxd_fwdq)) @@ -327,23 +245,16 @@ kqswnal_finalise (void) kpr_fwd_desc_t *fwd = list_entry (kqswnal_data.kqn_idletxd_fwdq.next, kpr_fwd_desc_t, kprfd_list); list_del (&fwd->kprfd_list); - kpr_fwd_done (&kqswnal_data.kqn_router, fwd, -EHOSTUNREACH); - } - - while (!list_empty (&kqswnal_data.kqn_delayedfwds)) - { - kpr_fwd_desc_t *fwd = list_entry (kqswnal_data.kqn_delayedfwds.next, - kpr_fwd_desc_t, kprfd_list); - list_del (&fwd->kprfd_list); - kpr_fwd_done (&kqswnal_data.kqn_router, fwd, -EHOSTUNREACH); + kpr_fwd_done (&kqswnal_data.kqn_router, fwd, -ESHUTDOWN); } /**********************************************************************/ - /* Wait for router to complete any packets I sent her - */ + /* finalise router and portals lib */ kpr_deregister (&kqswnal_data.kqn_router); + if (do_lib_fini) + lib_fini (&kqswnal_lib); /**********************************************************************/ /* Unmap message buffers and free all descriptors and buffers @@ -464,7 +375,9 @@ kqswnal_finalise (void) } static int __init -kqswnal_initialise (void) +kqswnal_startup (nal_t *nal, ptl_pid_t requested_pid, + ptl_ni_limits_t *requested_limits, + ptl_ni_limits_t *actual_limits) { #if MULTIRAIL_EKC EP_RAILMASK all_rails = EP_RAILMASK_ALL; @@ -474,37 +387,26 @@ kqswnal_initialise (void) int rc; int i; int elan_page_idx; + ptl_process_id_t my_process_id; int pkmem = atomic_read(&portal_kmemory); - LASSERT (kqswnal_data.kqn_init == KQN_INIT_NOTHING); + LASSERT (nal == &kqswnal_api); - CDEBUG (D_MALLOC, "start kmem %d\n", atomic_read(&portal_kmemory)); + if (nal->nal_refct != 0) { + if (actual_limits != NULL) + *actual_limits = kqswnal_lib.libnal_ni.ni_actual_limits; + /* This module got the first ref */ + PORTAL_MODULE_USE; + return (PTL_OK); + } - kqswnal_api.forward = kqswnal_forward; - kqswnal_api.shutdown = kqswnal_shutdown; - kqswnal_api.yield = kqswnal_yield; - kqswnal_api.validate = NULL; /* our api validate is a NOOP */ - kqswnal_api.lock = kqswnal_lock; - kqswnal_api.unlock = kqswnal_unlock; - kqswnal_api.nal_data = &kqswnal_data; + LASSERT (kqswnal_data.kqn_init == KQN_INIT_NOTHING); - kqswnal_lib.nal_data = &kqswnal_data; + CDEBUG (D_MALLOC, "start kmem %d\n", atomic_read(&portal_kmemory)); - memset(&kqswnal_rpc_success, 0, sizeof(kqswnal_rpc_success)); - memset(&kqswnal_rpc_failed, 0, sizeof(kqswnal_rpc_failed)); -#if MULTIRAIL_EKC - kqswnal_rpc_failed.Data[0] = -ECONNREFUSED; -#else - kqswnal_rpc_failed.Status = -ECONNREFUSED; -#endif /* ensure all pointers NULL etc */ memset (&kqswnal_data, 0, sizeof (kqswnal_data)); - kqswnal_data.kqn_optimized_gets = KQSW_OPTIMIZED_GETS; - kqswnal_data.kqn_copy_small_fwd = KQSW_COPY_SMALL_FWD; - - kqswnal_data.kqn_cb = &kqswnal_lib; - INIT_LIST_HEAD (&kqswnal_data.kqn_idletxds); INIT_LIST_HEAD (&kqswnal_data.kqn_nblk_idletxds); INIT_LIST_HEAD (&kqswnal_data.kqn_activetxds); @@ -519,23 +421,28 @@ kqswnal_initialise (void) spin_lock_init (&kqswnal_data.kqn_sched_lock); init_waitqueue_head (&kqswnal_data.kqn_sched_waitq); - spin_lock_init (&kqswnal_data.kqn_statelock); - init_waitqueue_head (&kqswnal_data.kqn_yield_waitq); + /* Leave kqn_rpc_success zeroed */ +#if MULTIRAIL_EKC + kqswnal_data.kqn_rpc_failed.Data[0] = -ECONNREFUSED; +#else + kqswnal_data.kqn_rpc_failed.Status = -ECONNREFUSED; +#endif /* pointers/lists/locks initialised */ kqswnal_data.kqn_init = KQN_INIT_DATA; - + #if MULTIRAIL_EKC kqswnal_data.kqn_ep = ep_system(); if (kqswnal_data.kqn_ep == NULL) { CERROR("Can't initialise EKC\n"); - return (-ENODEV); + kqswnal_shutdown(nal); + return (PTL_IFACE_INVALID); } if (ep_waitfor_nodeid(kqswnal_data.kqn_ep) == ELAN_INVALID_NODE) { CERROR("Can't get elan ID\n"); - kqswnal_finalise(); - return (-ENODEV); + kqswnal_shutdown(nal); + return (PTL_IFACE_INVALID); } #else /**********************************************************************/ @@ -545,7 +452,8 @@ kqswnal_initialise (void) if (kqswnal_data.kqn_ep == NULL) { CERROR ("Can't get elan device 0\n"); - return (-ENODEV); + kqswnal_shutdown(nal); + return (PTL_IFACE_INVALID); } #endif @@ -560,8 +468,8 @@ kqswnal_initialise (void) if (kqswnal_data.kqn_eptx == NULL) { CERROR ("Can't allocate transmitter\n"); - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } /**********************************************************************/ @@ -573,8 +481,8 @@ kqswnal_initialise (void) if (kqswnal_data.kqn_eprx_small == NULL) { CERROR ("Can't install small msg receiver\n"); - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } kqswnal_data.kqn_eprx_large = ep_alloc_rcvr (kqswnal_data.kqn_ep, @@ -583,8 +491,8 @@ kqswnal_initialise (void) if (kqswnal_data.kqn_eprx_large == NULL) { CERROR ("Can't install large msg receiver\n"); - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } /**********************************************************************/ @@ -598,8 +506,8 @@ kqswnal_initialise (void) EP_PERM_WRITE); if (kqswnal_data.kqn_ep_tx_nmh == NULL) { CERROR("Can't reserve tx dma space\n"); - kqswnal_finalise(); - return (-ENOMEM); + kqswnal_shutdown(nal); + return (PTL_NO_SPACE); } #else dmareq.Waitfn = DDI_DMA_SLEEP; @@ -613,8 +521,8 @@ kqswnal_initialise (void) if (rc != DDI_SUCCESS) { CERROR ("Can't reserve rx dma space\n"); - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } #endif /**********************************************************************/ @@ -627,8 +535,8 @@ kqswnal_initialise (void) EP_PERM_WRITE); if (kqswnal_data.kqn_ep_tx_nmh == NULL) { CERROR("Can't reserve rx dma space\n"); - kqswnal_finalise(); - return (-ENOMEM); + kqswnal_shutdown(nal); + return (PTL_NO_SPACE); } #else dmareq.Waitfn = DDI_DMA_SLEEP; @@ -643,8 +551,8 @@ kqswnal_initialise (void) if (rc != DDI_SUCCESS) { CERROR ("Can't reserve rx dma space\n"); - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } #endif /**********************************************************************/ @@ -654,8 +562,8 @@ kqswnal_initialise (void) sizeof(kqswnal_tx_t) * (KQSW_NTXMSGS + KQSW_NNBLK_TXMSGS)); if (kqswnal_data.kqn_txds == NULL) { - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } /* clear flags, null pointers etc */ @@ -670,8 +578,8 @@ kqswnal_initialise (void) PORTAL_ALLOC (ktx->ktx_buffer, KQSW_TX_BUFFER_SIZE); if (ktx->ktx_buffer == NULL) { - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } /* Map pre-allocated buffer NOW, to save latency on transmit */ @@ -707,8 +615,8 @@ kqswnal_initialise (void) sizeof (kqswnal_rx_t) * (KQSW_NRXMSGS_SMALL + KQSW_NRXMSGS_LARGE)); if (kqswnal_data.kqn_rxds == NULL) { - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } memset(kqswnal_data.kqn_rxds, 0, /* clear flags, null pointers etc */ @@ -742,8 +650,8 @@ kqswnal_initialise (void) struct page *page = alloc_page(GFP_KERNEL); if (page == NULL) { - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_NO_SPACE); } krx->krx_kiov[j].kiov_page = page; @@ -787,15 +695,19 @@ kqswnal_initialise (void) /**********************************************************************/ /* Network interface ready to initialise */ - rc = PtlNIInit(kqswnal_init, 32, 4, 0, &kqswnal_ni); - if (rc != 0) + my_process_id.nid = kqswnal_elanid2nid(kqswnal_data.kqn_elanid); + my_process_id.pid = 0; + + rc = lib_init(&kqswnal_lib, nal, my_process_id, + requested_limits, actual_limits); + if (rc != PTL_OK) { - CERROR ("PtlNIInit failed %d\n", rc); - kqswnal_finalise (); - return (-ENOMEM); + CERROR ("lib_init failed %d\n", rc); + kqswnal_shutdown (nal); + return (rc); } - kqswnal_data.kqn_init = KQN_INIT_PTL; + kqswnal_data.kqn_init = KQN_INIT_LIB; /**********************************************************************/ /* Queue receives, now that it's OK to run their completion callbacks */ @@ -805,6 +717,7 @@ kqswnal_initialise (void) kqswnal_rx_t *krx = &kqswnal_data.kqn_rxds[i]; /* NB this enqueue can allocate/sleep (attr == 0) */ + krx->krx_state = KRX_POSTED; #if MULTIRAIL_EKC rc = ep_queue_receive(krx->krx_eprx, kqswnal_rxhandler, krx, &krx->krx_elanbuffer, 0); @@ -816,21 +729,20 @@ kqswnal_initialise (void) if (rc != EP_SUCCESS) { CERROR ("failed ep_queue_receive %d\n", rc); - kqswnal_finalise (); - return (-ENOMEM); + kqswnal_shutdown (nal); + return (PTL_FAIL); } } /**********************************************************************/ /* Spawn scheduling threads */ - for (i = 0; i < smp_num_cpus; i++) - { + for (i = 0; i < num_online_cpus(); i++) { rc = kqswnal_thread_start (kqswnal_scheduler, NULL); if (rc != 0) { CERROR ("failed to spawn scheduling thread: %d\n", rc); - kqswnal_finalise (); - return (rc); + kqswnal_shutdown (nal); + return (PTL_FAIL); } } @@ -839,19 +751,13 @@ kqswnal_initialise (void) rc = kpr_register (&kqswnal_data.kqn_router, &kqswnal_router_interface); CDEBUG(D_NET, "Can't initialise routing interface (rc = %d): not routing\n",rc); - rc = kportal_nal_register (QSWNAL, &kqswnal_cmd, NULL); + rc = libcfs_nal_cmd_register (QSWNAL, &kqswnal_cmd, NULL); if (rc != 0) { CERROR ("Can't initialise command interface (rc = %d)\n", rc); - kqswnal_finalise (); - return (rc); + kqswnal_shutdown (nal); + return (PTL_FAIL); } -#if CONFIG_SYSCTL - /* Press on regardless even if registering sysctl doesn't work */ - kqswnal_data.kqn_sysctl = register_sysctl_table (kqswnal_top_ctl_table, 0); -#endif - - PORTAL_SYMBOL_REGISTER(kqswnal_ni); kqswnal_data.kqn_init = KQN_INIT_ALL; printk(KERN_INFO "Lustre: Routing QSW NAL loaded on node %d of %d " @@ -860,9 +766,55 @@ kqswnal_initialise (void) kpr_routing (&kqswnal_data.kqn_router) ? "enabled" : "disabled", pkmem); - return (0); + return (PTL_OK); +} + +void __exit +kqswnal_finalise (void) +{ +#if CONFIG_SYSCTL + if (kqswnal_tunables.kqn_sysctl != NULL) + unregister_sysctl_table (kqswnal_tunables.kqn_sysctl); +#endif + PtlNIFini(kqswnal_ni); + + ptl_unregister_nal(QSWNAL); } +static int __init +kqswnal_initialise (void) +{ + int rc; + + kqswnal_api.nal_ni_init = kqswnal_startup; + kqswnal_api.nal_ni_fini = kqswnal_shutdown; + + /* Initialise dynamic tunables to defaults once only */ + kqswnal_tunables.kqn_optimized_puts = KQSW_OPTIMIZED_PUTS; + kqswnal_tunables.kqn_optimized_gets = KQSW_OPTIMIZED_GETS; + + rc = ptl_register_nal(QSWNAL, &kqswnal_api); + if (rc != PTL_OK) { + CERROR("Can't register QSWNAL: %d\n", rc); + return (-ENOMEM); /* or something... */ + } + + /* Pure gateways, and the workaround for 'EKC blocks forever until + * the service is active' want the NAL started up at module load + * time... */ + rc = PtlNIInit(QSWNAL, 0, NULL, NULL, &kqswnal_ni); + if (rc != PTL_OK && rc != PTL_IFACE_DUP) { + ptl_unregister_nal(QSWNAL); + return (-ENODEV); + } + +#if CONFIG_SYSCTL + /* Press on regardless even if registering sysctl doesn't work */ + kqswnal_tunables.kqn_sysctl = + register_sysctl_table (kqswnal_top_ctl_table, 0); +#endif + return (0); +} MODULE_AUTHOR("Cluster File Systems, Inc. "); MODULE_DESCRIPTION("Kernel Quadrics/Elan NAL v1.01"); @@ -870,5 +822,3 @@ MODULE_LICENSE("GPL"); module_init (kqswnal_initialise); module_exit (kqswnal_finalise); - -EXPORT_SYMBOL (kqswnal_ni);