linux/drivers/staging/lustre/lnet/lnet/module.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License version 2 for more details (a copy is included
  14 * in the LICENSE file that accompanied this code).
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * version 2 along with this program; If not, see
  18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
  19 *
  20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  21 * CA 95054 USA or visit www.sun.com if you need additional information or
  22 * have any questions.
  23 *
  24 * GPL HEADER END
  25 */
  26/*
  27 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2012, 2015, Intel Corporation.
  31 */
  32/*
  33 * This file is part of Lustre, http://www.lustre.org/
  34 * Lustre is a trademark of Sun Microsystems, Inc.
  35 */
  36
  37#define DEBUG_SUBSYSTEM S_LNET
  38#include "../../include/linux/lnet/lib-lnet.h"
  39#include "../../include/linux/lnet/lib-dlc.h"
  40
  41static int config_on_load;
  42module_param(config_on_load, int, 0444);
  43MODULE_PARM_DESC(config_on_load, "configure network at module load");
  44
  45static struct mutex lnet_config_mutex;
  46
  47static int
  48lnet_configure(void *arg)
  49{
  50        /* 'arg' only there so I can be passed to cfs_create_thread() */
  51        int rc = 0;
  52
  53        mutex_lock(&lnet_config_mutex);
  54
  55        if (!the_lnet.ln_niinit_self) {
  56                rc = try_module_get(THIS_MODULE);
  57
  58                if (rc != 1)
  59                        goto out;
  60
  61                rc = LNetNIInit(LNET_PID_LUSTRE);
  62                if (rc >= 0) {
  63                        the_lnet.ln_niinit_self = 1;
  64                        rc = 0;
  65                } else {
  66                        module_put(THIS_MODULE);
  67                }
  68        }
  69
  70out:
  71        mutex_unlock(&lnet_config_mutex);
  72        return rc;
  73}
  74
  75static int
  76lnet_unconfigure(void)
  77{
  78        int refcount;
  79
  80        mutex_lock(&lnet_config_mutex);
  81
  82        if (the_lnet.ln_niinit_self) {
  83                the_lnet.ln_niinit_self = 0;
  84                LNetNIFini();
  85                module_put(THIS_MODULE);
  86        }
  87
  88        mutex_lock(&the_lnet.ln_api_mutex);
  89        refcount = the_lnet.ln_refcount;
  90        mutex_unlock(&the_lnet.ln_api_mutex);
  91
  92        mutex_unlock(&lnet_config_mutex);
  93        return !refcount ? 0 : -EBUSY;
  94}
  95
  96static int
  97lnet_dyn_configure(struct libcfs_ioctl_hdr *hdr)
  98{
  99        struct lnet_ioctl_config_data *conf =
 100                (struct lnet_ioctl_config_data *)hdr;
 101        int rc;
 102
 103        if (conf->cfg_hdr.ioc_len < sizeof(*conf))
 104                return -EINVAL;
 105
 106        mutex_lock(&lnet_config_mutex);
 107        if (!the_lnet.ln_niinit_self) {
 108                rc = -EINVAL;
 109                goto out_unlock;
 110        }
 111        rc = lnet_dyn_add_ni(LNET_PID_LUSTRE,
 112                             conf->cfg_config_u.cfg_net.net_intf,
 113                             conf->cfg_config_u.cfg_net.net_peer_timeout,
 114                             conf->cfg_config_u.cfg_net.net_peer_tx_credits,
 115                             conf->cfg_config_u.cfg_net.net_peer_rtr_credits,
 116                             conf->cfg_config_u.cfg_net.net_max_tx_credits);
 117out_unlock:
 118        mutex_unlock(&lnet_config_mutex);
 119
 120        return rc;
 121}
 122
 123static int
 124lnet_dyn_unconfigure(struct libcfs_ioctl_hdr *hdr)
 125{
 126        struct lnet_ioctl_config_data *conf =
 127                (struct lnet_ioctl_config_data *)hdr;
 128        int rc;
 129
 130        if (conf->cfg_hdr.ioc_len < sizeof(*conf))
 131                return -EINVAL;
 132
 133        mutex_lock(&lnet_config_mutex);
 134        if (!the_lnet.ln_niinit_self) {
 135                rc = -EINVAL;
 136                goto out_unlock;
 137        }
 138        rc = lnet_dyn_del_ni(conf->cfg_net);
 139out_unlock:
 140        mutex_unlock(&lnet_config_mutex);
 141
 142        return rc;
 143}
 144
 145static int
 146lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
 147{
 148        int rc;
 149
 150        switch (cmd) {
 151        case IOC_LIBCFS_CONFIGURE: {
 152                struct libcfs_ioctl_data *data =
 153                        (struct libcfs_ioctl_data *)hdr;
 154
 155                if (data->ioc_hdr.ioc_len < sizeof(*data))
 156                        return -EINVAL;
 157
 158                the_lnet.ln_nis_from_mod_params = data->ioc_flags;
 159                return lnet_configure(NULL);
 160        }
 161
 162        case IOC_LIBCFS_UNCONFIGURE:
 163                return lnet_unconfigure();
 164
 165        case IOC_LIBCFS_ADD_NET:
 166                return lnet_dyn_configure(hdr);
 167
 168        case IOC_LIBCFS_DEL_NET:
 169                return lnet_dyn_unconfigure(hdr);
 170
 171        default:
 172                /*
 173                 * Passing LNET_PID_ANY only gives me a ref if the net is up
 174                 * already; I'll need it to ensure the net can't go down while
 175                 * I'm called into it
 176                 */
 177                rc = LNetNIInit(LNET_PID_ANY);
 178                if (rc >= 0) {
 179                        rc = LNetCtl(cmd, hdr);
 180                        LNetNIFini();
 181                }
 182                return rc;
 183        }
 184}
 185
 186static DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl);
 187
 188static int __init lnet_init(void)
 189{
 190        int rc;
 191
 192        mutex_init(&lnet_config_mutex);
 193
 194        rc = lnet_lib_init();
 195        if (rc) {
 196                CERROR("lnet_lib_init: error %d\n", rc);
 197                return rc;
 198        }
 199
 200        rc = libcfs_register_ioctl(&lnet_ioctl_handler);
 201        LASSERT(!rc);
 202
 203        if (config_on_load) {
 204                /*
 205                 * Have to schedule a separate thread to avoid deadlocking
 206                 * in modload
 207                 */
 208                (void) kthread_run(lnet_configure, NULL, "lnet_initd");
 209        }
 210
 211        return 0;
 212}
 213
 214static void __exit lnet_exit(void)
 215{
 216        int rc;
 217
 218        rc = libcfs_deregister_ioctl(&lnet_ioctl_handler);
 219        LASSERT(!rc);
 220
 221        lnet_lib_exit();
 222}
 223
 224MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
 225MODULE_DESCRIPTION("Lustre Networking layer");
 226MODULE_VERSION(LNET_VERSION);
 227MODULE_LICENSE("GPL");
 228
 229module_init(lnet_init);
 230module_exit(lnet_exit);
 231