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.gnu.org/licenses/gpl-2.0.html
  19 *
  20 * GPL HEADER END
  21 */
  22/*
  23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24 * Use is subject to license terms.
  25 *
  26 * Copyright (c) 2012, 2015, Intel Corporation.
  27 */
  28/*
  29 * This file is part of Lustre, http://www.lustre.org/
  30 * Lustre is a trademark of Sun Microsystems, Inc.
  31 */
  32
  33#define DEBUG_SUBSYSTEM S_LNET
  34#include "../../include/linux/lnet/lib-lnet.h"
  35#include "../../include/linux/lnet/lib-dlc.h"
  36
  37static int config_on_load;
  38module_param(config_on_load, int, 0444);
  39MODULE_PARM_DESC(config_on_load, "configure network at module load");
  40
  41static struct mutex lnet_config_mutex;
  42
  43static int
  44lnet_configure(void *arg)
  45{
  46        /* 'arg' only there so I can be passed to cfs_create_thread() */
  47        int rc = 0;
  48
  49        mutex_lock(&lnet_config_mutex);
  50
  51        if (!the_lnet.ln_niinit_self) {
  52                rc = try_module_get(THIS_MODULE);
  53
  54                if (rc != 1)
  55                        goto out;
  56
  57                rc = LNetNIInit(LNET_PID_LUSTRE);
  58                if (rc >= 0) {
  59                        the_lnet.ln_niinit_self = 1;
  60                        rc = 0;
  61                } else {
  62                        module_put(THIS_MODULE);
  63                }
  64        }
  65
  66out:
  67        mutex_unlock(&lnet_config_mutex);
  68        return rc;
  69}
  70
  71static int
  72lnet_unconfigure(void)
  73{
  74        int refcount;
  75
  76        mutex_lock(&lnet_config_mutex);
  77
  78        if (the_lnet.ln_niinit_self) {
  79                the_lnet.ln_niinit_self = 0;
  80                LNetNIFini();
  81                module_put(THIS_MODULE);
  82        }
  83
  84        mutex_lock(&the_lnet.ln_api_mutex);
  85        refcount = the_lnet.ln_refcount;
  86        mutex_unlock(&the_lnet.ln_api_mutex);
  87
  88        mutex_unlock(&lnet_config_mutex);
  89        return !refcount ? 0 : -EBUSY;
  90}
  91
  92static int
  93lnet_dyn_configure(struct libcfs_ioctl_hdr *hdr)
  94{
  95        struct lnet_ioctl_config_data *conf =
  96                (struct lnet_ioctl_config_data *)hdr;
  97        int rc;
  98
  99        if (conf->cfg_hdr.ioc_len < sizeof(*conf))
 100                return -EINVAL;
 101
 102        mutex_lock(&lnet_config_mutex);
 103        if (!the_lnet.ln_niinit_self) {
 104                rc = -EINVAL;
 105                goto out_unlock;
 106        }
 107        rc = lnet_dyn_add_ni(LNET_PID_LUSTRE, conf);
 108out_unlock:
 109        mutex_unlock(&lnet_config_mutex);
 110
 111        return rc;
 112}
 113
 114static int
 115lnet_dyn_unconfigure(struct libcfs_ioctl_hdr *hdr)
 116{
 117        struct lnet_ioctl_config_data *conf =
 118                (struct lnet_ioctl_config_data *)hdr;
 119        int rc;
 120
 121        if (conf->cfg_hdr.ioc_len < sizeof(*conf))
 122                return -EINVAL;
 123
 124        mutex_lock(&lnet_config_mutex);
 125        if (!the_lnet.ln_niinit_self) {
 126                rc = -EINVAL;
 127                goto out_unlock;
 128        }
 129        rc = lnet_dyn_del_ni(conf->cfg_net);
 130out_unlock:
 131        mutex_unlock(&lnet_config_mutex);
 132
 133        return rc;
 134}
 135
 136static int
 137lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
 138{
 139        int rc;
 140
 141        switch (cmd) {
 142        case IOC_LIBCFS_CONFIGURE: {
 143                struct libcfs_ioctl_data *data =
 144                        (struct libcfs_ioctl_data *)hdr;
 145
 146                if (data->ioc_hdr.ioc_len < sizeof(*data))
 147                        return -EINVAL;
 148
 149                the_lnet.ln_nis_from_mod_params = data->ioc_flags;
 150                return lnet_configure(NULL);
 151        }
 152
 153        case IOC_LIBCFS_UNCONFIGURE:
 154                return lnet_unconfigure();
 155
 156        case IOC_LIBCFS_ADD_NET:
 157                return lnet_dyn_configure(hdr);
 158
 159        case IOC_LIBCFS_DEL_NET:
 160                return lnet_dyn_unconfigure(hdr);
 161
 162        default:
 163                /*
 164                 * Passing LNET_PID_ANY only gives me a ref if the net is up
 165                 * already; I'll need it to ensure the net can't go down while
 166                 * I'm called into it
 167                 */
 168                rc = LNetNIInit(LNET_PID_ANY);
 169                if (rc >= 0) {
 170                        rc = LNetCtl(cmd, hdr);
 171                        LNetNIFini();
 172                }
 173                return rc;
 174        }
 175}
 176
 177static DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl);
 178
 179static int __init lnet_init(void)
 180{
 181        int rc;
 182
 183        mutex_init(&lnet_config_mutex);
 184
 185        rc = lnet_lib_init();
 186        if (rc) {
 187                CERROR("lnet_lib_init: error %d\n", rc);
 188                return rc;
 189        }
 190
 191        rc = libcfs_register_ioctl(&lnet_ioctl_handler);
 192        LASSERT(!rc);
 193
 194        if (config_on_load) {
 195                /*
 196                 * Have to schedule a separate thread to avoid deadlocking
 197                 * in modload
 198                 */
 199                (void)kthread_run(lnet_configure, NULL, "lnet_initd");
 200        }
 201
 202        return 0;
 203}
 204
 205static void __exit lnet_exit(void)
 206{
 207        int rc;
 208
 209        rc = libcfs_deregister_ioctl(&lnet_ioctl_handler);
 210        LASSERT(!rc);
 211
 212        lnet_lib_exit();
 213}
 214
 215MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
 216MODULE_DESCRIPTION("Lustre Networking layer");
 217MODULE_VERSION(LNET_VERSION);
 218MODULE_LICENSE("GPL");
 219
 220module_init(lnet_init);
 221module_exit(lnet_exit);
 222