linux/drivers/staging/lustre/lustre/obdclass/obd_config.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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2011, 2012, 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 * lustre/obdclass/obd_config.c
  37 *
  38 * Config API
  39 */
  40
  41#define DEBUG_SUBSYSTEM S_CLASS
  42#include "../include/obd_class.h"
  43#include <linux/string.h>
  44#include "../include/lustre_log.h"
  45#include "../include/lprocfs_status.h"
  46#include "../include/lustre_param.h"
  47
  48#include "llog_internal.h"
  49
  50static cfs_hash_ops_t uuid_hash_ops;
  51static cfs_hash_ops_t nid_hash_ops;
  52static cfs_hash_ops_t nid_stat_hash_ops;
  53
  54/*********** string parsing utils *********/
  55
  56/* returns 0 if we find this key in the buffer, else 1 */
  57int class_find_param(char *buf, char *key, char **valp)
  58{
  59        char *ptr;
  60
  61        if (!buf)
  62                return 1;
  63
  64        ptr = strstr(buf, key);
  65        if (ptr == NULL)
  66                return 1;
  67
  68        if (valp)
  69                *valp = ptr + strlen(key);
  70
  71        return 0;
  72}
  73EXPORT_SYMBOL(class_find_param);
  74
  75/**
  76 * Check whether the proc parameter \a param is an old parameter or not from
  77 * the array \a ptr which contains the mapping from old parameters to new ones.
  78 * If it's an old one, then return the pointer to the cfg_interop_param struc-
  79 * ture which contains both the old and new parameters.
  80 *
  81 * \param param                 proc parameter
  82 * \param ptr                   an array which contains the mapping from
  83 *                              old parameters to new ones
  84 *
  85 * \retval valid-pointer        pointer to the cfg_interop_param structure
  86 *                              which contains the old and new parameters
  87 * \retval NULL                 \a param or \a ptr is NULL,
  88 *                              or \a param is not an old parameter
  89 */
  90struct cfg_interop_param *class_find_old_param(const char *param,
  91                                               struct cfg_interop_param *ptr)
  92{
  93        char *value = NULL;
  94        int   name_len = 0;
  95
  96        if (param == NULL || ptr == NULL)
  97                return NULL;
  98
  99        value = strchr(param, '=');
 100        if (value == NULL)
 101                name_len = strlen(param);
 102        else
 103                name_len = value - param;
 104
 105        while (ptr->old_param != NULL) {
 106                if (strncmp(param, ptr->old_param, name_len) == 0 &&
 107                    name_len == strlen(ptr->old_param))
 108                        return ptr;
 109                ptr++;
 110        }
 111
 112        return NULL;
 113}
 114EXPORT_SYMBOL(class_find_old_param);
 115
 116/**
 117 * Finds a parameter in \a params and copies it to \a copy.
 118 *
 119 * Leading spaces are skipped. Next space or end of string is the
 120 * parameter terminator with the exception that spaces inside single or double
 121 * quotes get included into a parameter. The parameter is copied into \a copy
 122 * which has to be allocated big enough by a caller, quotes are stripped in
 123 * the copy and the copy is terminated by 0.
 124 *
 125 * On return \a params is set to next parameter or to NULL if last
 126 * parameter is returned.
 127 *
 128 * \retval 0 if parameter is returned in \a copy
 129 * \retval 1 otherwise
 130 * \retval -EINVAL if unbalanced quota is found
 131 */
 132int class_get_next_param(char **params, char *copy)
 133{
 134        char *q1, *q2, *str;
 135        int len;
 136
 137        str = *params;
 138        while (*str == ' ')
 139                str++;
 140
 141        if (*str == '\0') {
 142                *params = NULL;
 143                return 1;
 144        }
 145
 146        while (1) {
 147                q1 = strpbrk(str, " '\"");
 148                if (q1 == NULL) {
 149                        len = strlen(str);
 150                        memcpy(copy, str, len);
 151                        copy[len] = '\0';
 152                        *params = NULL;
 153                        return 0;
 154                }
 155                len = q1 - str;
 156                if (*q1 == ' ') {
 157                        memcpy(copy, str, len);
 158                        copy[len] = '\0';
 159                        *params = str + len;
 160                        return 0;
 161                }
 162
 163                memcpy(copy, str, len);
 164                copy += len;
 165
 166                /* search for the matching closing quote */
 167                str = q1 + 1;
 168                q2 = strchr(str, *q1);
 169                if (q2 == NULL) {
 170                        CERROR("Unbalanced quota in parameters: \"%s\"\n",
 171                               *params);
 172                        return -EINVAL;
 173                }
 174                len = q2 - str;
 175                memcpy(copy, str, len);
 176                copy += len;
 177                str = q2 + 1;
 178        }
 179        return 1;
 180}
 181EXPORT_SYMBOL(class_get_next_param);
 182
 183/* returns 0 if this is the first key in the buffer, else 1.
 184   valp points to first char after key. */
 185int class_match_param(char *buf, char *key, char **valp)
 186{
 187        if (!buf)
 188                return 1;
 189
 190        if (memcmp(buf, key, strlen(key)) != 0)
 191                return 1;
 192
 193        if (valp)
 194                *valp = buf + strlen(key);
 195
 196        return 0;
 197}
 198EXPORT_SYMBOL(class_match_param);
 199
 200static int parse_nid(char *buf, void *value, int quiet)
 201{
 202        lnet_nid_t *nid = (lnet_nid_t *)value;
 203
 204        *nid = libcfs_str2nid(buf);
 205        if (*nid != LNET_NID_ANY)
 206                return 0;
 207
 208        if (!quiet)
 209                LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", buf);
 210        return -EINVAL;
 211}
 212
 213static int parse_net(char *buf, void *value)
 214{
 215        __u32 *net = (__u32 *)value;
 216
 217        *net = libcfs_str2net(buf);
 218        CDEBUG(D_INFO, "Net %s\n", libcfs_net2str(*net));
 219        return 0;
 220}
 221
 222enum {
 223        CLASS_PARSE_NID = 1,
 224        CLASS_PARSE_NET,
 225};
 226
 227/* 0 is good nid,
 228   1 not found
 229   < 0 error
 230   endh is set to next separator */
 231static int class_parse_value(char *buf, int opc, void *value, char **endh,
 232                             int quiet)
 233{
 234        char *endp;
 235        char  tmp;
 236        int   rc = 0;
 237
 238        if (!buf)
 239                return 1;
 240        while (*buf == ',' || *buf == ':')
 241                buf++;
 242        if (*buf == ' ' || *buf == '/' || *buf == '\0')
 243                return 1;
 244
 245        /* nid separators or end of nids */
 246        endp = strpbrk(buf, ",: /");
 247        if (endp == NULL)
 248                endp = buf + strlen(buf);
 249
 250        tmp = *endp;
 251        *endp = '\0';
 252        switch (opc) {
 253        default:
 254                LBUG();
 255        case CLASS_PARSE_NID:
 256                rc = parse_nid(buf, value, quiet);
 257                break;
 258        case CLASS_PARSE_NET:
 259                rc = parse_net(buf, value);
 260                break;
 261        }
 262        *endp = tmp;
 263        if (rc != 0)
 264                return rc;
 265        if (endh)
 266                *endh = endp;
 267        return 0;
 268}
 269
 270int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
 271{
 272        return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh, 0);
 273}
 274EXPORT_SYMBOL(class_parse_nid);
 275
 276int class_parse_nid_quiet(char *buf, lnet_nid_t *nid, char **endh)
 277{
 278        return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh, 1);
 279}
 280EXPORT_SYMBOL(class_parse_nid_quiet);
 281
 282int class_parse_net(char *buf, __u32 *net, char **endh)
 283{
 284        return class_parse_value(buf, CLASS_PARSE_NET, (void *)net, endh, 0);
 285}
 286EXPORT_SYMBOL(class_parse_net);
 287
 288/* 1 param contains key and match
 289 * 0 param contains key and not match
 290 * -1 param does not contain key
 291 */
 292int class_match_nid(char *buf, char *key, lnet_nid_t nid)
 293{
 294        lnet_nid_t tmp;
 295        int   rc = -1;
 296
 297        while (class_find_param(buf, key, &buf) == 0) {
 298                /* please restrict to the nids pertaining to
 299                 * the specified nids */
 300                while (class_parse_nid(buf, &tmp, &buf) == 0) {
 301                        if (tmp == nid)
 302                                return 1;
 303                }
 304                rc = 0;
 305        }
 306        return rc;
 307}
 308EXPORT_SYMBOL(class_match_nid);
 309
 310int class_match_net(char *buf, char *key, __u32 net)
 311{
 312        __u32 tmp;
 313        int   rc = -1;
 314
 315        while (class_find_param(buf, key, &buf) == 0) {
 316                /* please restrict to the nids pertaining to
 317                 * the specified networks */
 318                while (class_parse_net(buf, &tmp, &buf) == 0) {
 319                        if (tmp == net)
 320                                return 1;
 321                }
 322                rc = 0;
 323        }
 324        return rc;
 325}
 326EXPORT_SYMBOL(class_match_net);
 327
 328/********************** class fns **********************/
 329
 330/**
 331 * Create a new obd device and set the type, name and uuid.  If successful,
 332 * the new device can be accessed by either name or uuid.
 333 */
 334int class_attach(struct lustre_cfg *lcfg)
 335{
 336        struct obd_device *obd = NULL;
 337        char *typename, *name, *uuid;
 338        int rc, len;
 339
 340        if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
 341                CERROR("No type passed!\n");
 342                return -EINVAL;
 343        }
 344        typename = lustre_cfg_string(lcfg, 1);
 345
 346        if (!LUSTRE_CFG_BUFLEN(lcfg, 0)) {
 347                CERROR("No name passed!\n");
 348                return -EINVAL;
 349        }
 350        name = lustre_cfg_string(lcfg, 0);
 351
 352        if (!LUSTRE_CFG_BUFLEN(lcfg, 2)) {
 353                CERROR("No UUID passed!\n");
 354                return -EINVAL;
 355        }
 356        uuid = lustre_cfg_string(lcfg, 2);
 357
 358        CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
 359               MKSTR(typename), MKSTR(name), MKSTR(uuid));
 360
 361        obd = class_newdev(typename, name);
 362        if (IS_ERR(obd)) {
 363                /* Already exists or out of obds */
 364                rc = PTR_ERR(obd);
 365                obd = NULL;
 366                CERROR("Cannot create device %s of type %s : %d\n",
 367                       name, typename, rc);
 368                goto out;
 369        }
 370        LASSERTF(obd != NULL, "Cannot get obd device %s of type %s\n",
 371                 name, typename);
 372        LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
 373                 "obd %p obd_magic %08X != %08X\n",
 374                 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
 375        LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0,
 376                 "%p obd_name %s != %s\n", obd, obd->obd_name, name);
 377
 378        rwlock_init(&obd->obd_pool_lock);
 379        obd->obd_pool_limit = 0;
 380        obd->obd_pool_slv = 0;
 381
 382        INIT_LIST_HEAD(&obd->obd_exports);
 383        INIT_LIST_HEAD(&obd->obd_unlinked_exports);
 384        INIT_LIST_HEAD(&obd->obd_delayed_exports);
 385        INIT_LIST_HEAD(&obd->obd_exports_timed);
 386        INIT_LIST_HEAD(&obd->obd_nid_stats);
 387        spin_lock_init(&obd->obd_nid_lock);
 388        spin_lock_init(&obd->obd_dev_lock);
 389        mutex_init(&obd->obd_dev_mutex);
 390        spin_lock_init(&obd->obd_osfs_lock);
 391        /* obd->obd_osfs_age must be set to a value in the distant
 392         * past to guarantee a fresh statfs is fetched on mount. */
 393        obd->obd_osfs_age = cfs_time_shift_64(-1000);
 394
 395        /* XXX belongs in setup not attach  */
 396        init_rwsem(&obd->obd_observer_link_sem);
 397        /* recovery data */
 398        cfs_init_timer(&obd->obd_recovery_timer);
 399        spin_lock_init(&obd->obd_recovery_task_lock);
 400        init_waitqueue_head(&obd->obd_next_transno_waitq);
 401        init_waitqueue_head(&obd->obd_evict_inprogress_waitq);
 402        INIT_LIST_HEAD(&obd->obd_req_replay_queue);
 403        INIT_LIST_HEAD(&obd->obd_lock_replay_queue);
 404        INIT_LIST_HEAD(&obd->obd_final_req_queue);
 405        INIT_LIST_HEAD(&obd->obd_evict_list);
 406
 407        llog_group_init(&obd->obd_olg, FID_SEQ_LLOG);
 408
 409        obd->obd_conn_inprogress = 0;
 410
 411        len = strlen(uuid);
 412        if (len >= sizeof(obd->obd_uuid)) {
 413                CERROR("uuid must be < %d bytes long\n",
 414                       (int)sizeof(obd->obd_uuid));
 415                rc = -EINVAL;
 416                goto out;
 417        }
 418        memcpy(obd->obd_uuid.uuid, uuid, len);
 419
 420        /* do the attach */
 421        if (OBP(obd, attach)) {
 422                rc = OBP(obd, attach)(obd, sizeof(*lcfg), lcfg);
 423                if (rc) {
 424                        rc = -EINVAL;
 425                        goto out;
 426                }
 427        }
 428
 429        /* Detach drops this */
 430        spin_lock(&obd->obd_dev_lock);
 431        atomic_set(&obd->obd_refcount, 1);
 432        spin_unlock(&obd->obd_dev_lock);
 433        lu_ref_init(&obd->obd_reference);
 434        lu_ref_add(&obd->obd_reference, "attach", obd);
 435
 436        obd->obd_attached = 1;
 437        CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
 438               obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
 439        return 0;
 440 out:
 441        if (obd != NULL) {
 442                class_release_dev(obd);
 443        }
 444        return rc;
 445}
 446EXPORT_SYMBOL(class_attach);
 447
 448/** Create hashes, self-export, and call type-specific setup.
 449 * Setup is effectively the "start this obd" call.
 450 */
 451int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 452{
 453        int err = 0;
 454        struct obd_export *exp;
 455
 456        LASSERT(obd != NULL);
 457        LASSERTF(obd == class_num2obd(obd->obd_minor),
 458                 "obd %p != obd_devs[%d] %p\n",
 459                 obd, obd->obd_minor, class_num2obd(obd->obd_minor));
 460        LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
 461                 "obd %p obd_magic %08x != %08x\n",
 462                 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
 463
 464        /* have we attached a type to this device? */
 465        if (!obd->obd_attached) {
 466                CERROR("Device %d not attached\n", obd->obd_minor);
 467                return -ENODEV;
 468        }
 469
 470        if (obd->obd_set_up) {
 471                CERROR("Device %d already setup (type %s)\n",
 472                       obd->obd_minor, obd->obd_type->typ_name);
 473                return -EEXIST;
 474        }
 475
 476        /* is someone else setting us up right now? (attach inits spinlock) */
 477        spin_lock(&obd->obd_dev_lock);
 478        if (obd->obd_starting) {
 479                spin_unlock(&obd->obd_dev_lock);
 480                CERROR("Device %d setup in progress (type %s)\n",
 481                       obd->obd_minor, obd->obd_type->typ_name);
 482                return -EEXIST;
 483        }
 484        /* just leave this on forever.  I can't use obd_set_up here because
 485           other fns check that status, and we're not actually set up yet. */
 486        obd->obd_starting = 1;
 487        obd->obd_uuid_hash = NULL;
 488        obd->obd_nid_hash = NULL;
 489        obd->obd_nid_stats_hash = NULL;
 490        spin_unlock(&obd->obd_dev_lock);
 491
 492        /* create an uuid-export lustre hash */
 493        obd->obd_uuid_hash = cfs_hash_create("UUID_HASH",
 494                                             HASH_UUID_CUR_BITS,
 495                                             HASH_UUID_MAX_BITS,
 496                                             HASH_UUID_BKT_BITS, 0,
 497                                             CFS_HASH_MIN_THETA,
 498                                             CFS_HASH_MAX_THETA,
 499                                             &uuid_hash_ops, CFS_HASH_DEFAULT);
 500        if (!obd->obd_uuid_hash) {
 501                err = -ENOMEM;
 502                goto err_hash;
 503        }
 504
 505        /* create a nid-export lustre hash */
 506        obd->obd_nid_hash = cfs_hash_create("NID_HASH",
 507                                            HASH_NID_CUR_BITS,
 508                                            HASH_NID_MAX_BITS,
 509                                            HASH_NID_BKT_BITS, 0,
 510                                            CFS_HASH_MIN_THETA,
 511                                            CFS_HASH_MAX_THETA,
 512                                            &nid_hash_ops, CFS_HASH_DEFAULT);
 513        if (!obd->obd_nid_hash) {
 514                err = -ENOMEM;
 515                goto err_hash;
 516        }
 517
 518        /* create a nid-stats lustre hash */
 519        obd->obd_nid_stats_hash = cfs_hash_create("NID_STATS",
 520                                                  HASH_NID_STATS_CUR_BITS,
 521                                                  HASH_NID_STATS_MAX_BITS,
 522                                                  HASH_NID_STATS_BKT_BITS, 0,
 523                                                  CFS_HASH_MIN_THETA,
 524                                                  CFS_HASH_MAX_THETA,
 525                                                  &nid_stat_hash_ops, CFS_HASH_DEFAULT);
 526        if (!obd->obd_nid_stats_hash) {
 527                err = -ENOMEM;
 528                goto err_hash;
 529        }
 530
 531        exp = class_new_export(obd, &obd->obd_uuid);
 532        if (IS_ERR(exp)) {
 533                err = PTR_ERR(exp);
 534                goto err_hash;
 535        }
 536
 537        obd->obd_self_export = exp;
 538        list_del_init(&exp->exp_obd_chain_timed);
 539        class_export_put(exp);
 540
 541        err = obd_setup(obd, lcfg);
 542        if (err)
 543                goto err_exp;
 544
 545        obd->obd_set_up = 1;
 546
 547        spin_lock(&obd->obd_dev_lock);
 548        /* cleanup drops this */
 549        class_incref(obd, "setup", obd);
 550        spin_unlock(&obd->obd_dev_lock);
 551
 552        CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
 553               obd->obd_name, obd->obd_uuid.uuid);
 554
 555        return 0;
 556err_exp:
 557        if (obd->obd_self_export) {
 558                class_unlink_export(obd->obd_self_export);
 559                obd->obd_self_export = NULL;
 560        }
 561err_hash:
 562        if (obd->obd_uuid_hash) {
 563                cfs_hash_putref(obd->obd_uuid_hash);
 564                obd->obd_uuid_hash = NULL;
 565        }
 566        if (obd->obd_nid_hash) {
 567                cfs_hash_putref(obd->obd_nid_hash);
 568                obd->obd_nid_hash = NULL;
 569        }
 570        if (obd->obd_nid_stats_hash) {
 571                cfs_hash_putref(obd->obd_nid_stats_hash);
 572                obd->obd_nid_stats_hash = NULL;
 573        }
 574        obd->obd_starting = 0;
 575        CERROR("setup %s failed (%d)\n", obd->obd_name, err);
 576        return err;
 577}
 578EXPORT_SYMBOL(class_setup);
 579
 580/** We have finished using this obd and are ready to destroy it.
 581 * There can be no more references to this obd.
 582 */
 583int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
 584{
 585        if (obd->obd_set_up) {
 586                CERROR("OBD device %d still set up\n", obd->obd_minor);
 587                return -EBUSY;
 588        }
 589
 590        spin_lock(&obd->obd_dev_lock);
 591        if (!obd->obd_attached) {
 592                spin_unlock(&obd->obd_dev_lock);
 593                CERROR("OBD device %d not attached\n", obd->obd_minor);
 594                return -ENODEV;
 595        }
 596        obd->obd_attached = 0;
 597        spin_unlock(&obd->obd_dev_lock);
 598
 599        CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
 600               obd->obd_name, obd->obd_uuid.uuid);
 601
 602        class_decref(obd, "attach", obd);
 603        return 0;
 604}
 605EXPORT_SYMBOL(class_detach);
 606
 607/** Start shutting down the obd.  There may be in-progress ops when
 608 * this is called.  We tell them to start shutting down with a call
 609 * to class_disconnect_exports().
 610 */
 611int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
 612{
 613        int err = 0;
 614        char *flag;
 615
 616        OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
 617
 618        if (!obd->obd_set_up) {
 619                CERROR("Device %d not setup\n", obd->obd_minor);
 620                return -ENODEV;
 621        }
 622
 623        spin_lock(&obd->obd_dev_lock);
 624        if (obd->obd_stopping) {
 625                spin_unlock(&obd->obd_dev_lock);
 626                CERROR("OBD %d already stopping\n", obd->obd_minor);
 627                return -ENODEV;
 628        }
 629        /* Leave this on forever */
 630        obd->obd_stopping = 1;
 631
 632        /* wait for already-arrived-connections to finish. */
 633        while (obd->obd_conn_inprogress > 0) {
 634                spin_unlock(&obd->obd_dev_lock);
 635
 636                cond_resched();
 637
 638                spin_lock(&obd->obd_dev_lock);
 639        }
 640        spin_unlock(&obd->obd_dev_lock);
 641
 642        if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
 643                for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
 644                        switch (*flag) {
 645                        case 'F':
 646                                obd->obd_force = 1;
 647                                break;
 648                        case 'A':
 649                                LCONSOLE_WARN("Failing over %s\n",
 650                                              obd->obd_name);
 651                                obd->obd_fail = 1;
 652                                obd->obd_no_transno = 1;
 653                                obd->obd_no_recov = 1;
 654                                if (OBP(obd, iocontrol)) {
 655                                        obd_iocontrol(OBD_IOC_SYNC,
 656                                                      obd->obd_self_export,
 657                                                      0, NULL, NULL);
 658                                }
 659                                break;
 660                        default:
 661                                CERROR("Unrecognised flag '%c'\n", *flag);
 662                        }
 663        }
 664
 665        LASSERT(obd->obd_self_export);
 666
 667        /* The three references that should be remaining are the
 668         * obd_self_export and the attach and setup references. */
 669        if (atomic_read(&obd->obd_refcount) > 3) {
 670                /* refcount - 3 might be the number of real exports
 671                   (excluding self export). But class_incref is called
 672                   by other things as well, so don't count on it. */
 673                CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
 674                       obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
 675                dump_exports(obd, 0);
 676                class_disconnect_exports(obd);
 677        }
 678
 679        /* Precleanup, we must make sure all exports get destroyed. */
 680        err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
 681        if (err)
 682                CERROR("Precleanup %s returned %d\n",
 683                       obd->obd_name, err);
 684
 685        /* destroy an uuid-export hash body */
 686        if (obd->obd_uuid_hash) {
 687                cfs_hash_putref(obd->obd_uuid_hash);
 688                obd->obd_uuid_hash = NULL;
 689        }
 690
 691        /* destroy a nid-export hash body */
 692        if (obd->obd_nid_hash) {
 693                cfs_hash_putref(obd->obd_nid_hash);
 694                obd->obd_nid_hash = NULL;
 695        }
 696
 697        /* destroy a nid-stats hash body */
 698        if (obd->obd_nid_stats_hash) {
 699                cfs_hash_putref(obd->obd_nid_stats_hash);
 700                obd->obd_nid_stats_hash = NULL;
 701        }
 702
 703        class_decref(obd, "setup", obd);
 704        obd->obd_set_up = 0;
 705
 706        return 0;
 707}
 708EXPORT_SYMBOL(class_cleanup);
 709
 710struct obd_device *class_incref(struct obd_device *obd,
 711                                const char *scope, const void *source)
 712{
 713        lu_ref_add_atomic(&obd->obd_reference, scope, source);
 714        atomic_inc(&obd->obd_refcount);
 715        CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
 716               atomic_read(&obd->obd_refcount));
 717
 718        return obd;
 719}
 720EXPORT_SYMBOL(class_incref);
 721
 722void class_decref(struct obd_device *obd, const char *scope, const void *source)
 723{
 724        int err;
 725        int refs;
 726
 727        spin_lock(&obd->obd_dev_lock);
 728        atomic_dec(&obd->obd_refcount);
 729        refs = atomic_read(&obd->obd_refcount);
 730        spin_unlock(&obd->obd_dev_lock);
 731        lu_ref_del(&obd->obd_reference, scope, source);
 732
 733        CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
 734
 735        if ((refs == 1) && obd->obd_stopping) {
 736                /* All exports have been destroyed; there should
 737                   be no more in-progress ops by this point.*/
 738
 739                spin_lock(&obd->obd_self_export->exp_lock);
 740                obd->obd_self_export->exp_flags |= exp_flags_from_obd(obd);
 741                spin_unlock(&obd->obd_self_export->exp_lock);
 742
 743                /* note that we'll recurse into class_decref again */
 744                class_unlink_export(obd->obd_self_export);
 745                return;
 746        }
 747
 748        if (refs == 0) {
 749                CDEBUG(D_CONFIG, "finishing cleanup of obd %s (%s)\n",
 750                       obd->obd_name, obd->obd_uuid.uuid);
 751                LASSERT(!obd->obd_attached);
 752                if (obd->obd_stopping) {
 753                        /* If we're not stopping, we were never set up */
 754                        err = obd_cleanup(obd);
 755                        if (err)
 756                                CERROR("Cleanup %s returned %d\n",
 757                                       obd->obd_name, err);
 758                }
 759                if (OBP(obd, detach)) {
 760                        err = OBP(obd, detach)(obd);
 761                        if (err)
 762                                CERROR("Detach returned %d\n", err);
 763                }
 764                class_release_dev(obd);
 765        }
 766}
 767EXPORT_SYMBOL(class_decref);
 768
 769/** Add a failover nid location.
 770 * Client obd types contact server obd types using this nid list.
 771 */
 772int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
 773{
 774        struct obd_import *imp;
 775        struct obd_uuid uuid;
 776        int rc;
 777
 778        if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
 779            LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
 780                CERROR("invalid conn_uuid\n");
 781                return -EINVAL;
 782        }
 783        if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
 784            strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
 785            strcmp(obd->obd_type->typ_name, LUSTRE_OSP_NAME) &&
 786            strcmp(obd->obd_type->typ_name, LUSTRE_LWP_NAME) &&
 787            strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
 788                CERROR("can't add connection on non-client dev\n");
 789                return -EINVAL;
 790        }
 791
 792        imp = obd->u.cli.cl_import;
 793        if (!imp) {
 794                CERROR("try to add conn on immature client dev\n");
 795                return -EINVAL;
 796        }
 797
 798        obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
 799        rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
 800
 801        return rc;
 802}
 803EXPORT_SYMBOL(class_add_conn);
 804
 805/** Remove a failover nid location.
 806 */
 807int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
 808{
 809        struct obd_import *imp;
 810        struct obd_uuid uuid;
 811        int rc;
 812
 813        if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
 814            LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
 815                CERROR("invalid conn_uuid\n");
 816                return -EINVAL;
 817        }
 818        if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
 819            strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
 820                CERROR("can't del connection on non-client dev\n");
 821                return -EINVAL;
 822        }
 823
 824        imp = obd->u.cli.cl_import;
 825        if (!imp) {
 826                CERROR("try to del conn on immature client dev\n");
 827                return -EINVAL;
 828        }
 829
 830        obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
 831        rc = obd_del_conn(imp, &uuid);
 832
 833        return rc;
 834}
 835
 836LIST_HEAD(lustre_profile_list);
 837
 838struct lustre_profile *class_get_profile(const char *prof)
 839{
 840        struct lustre_profile *lprof;
 841
 842        list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
 843                if (!strcmp(lprof->lp_profile, prof)) {
 844                        return lprof;
 845                }
 846        }
 847        return NULL;
 848}
 849EXPORT_SYMBOL(class_get_profile);
 850
 851/** Create a named "profile".
 852 * This defines the mdc and osc names to use for a client.
 853 * This also is used to define the lov to be used by a mdt.
 854 */
 855int class_add_profile(int proflen, char *prof, int osclen, char *osc,
 856                      int mdclen, char *mdc)
 857{
 858        struct lustre_profile *lprof;
 859        int err = 0;
 860
 861        CDEBUG(D_CONFIG, "Add profile %s\n", prof);
 862
 863        OBD_ALLOC(lprof, sizeof(*lprof));
 864        if (lprof == NULL)
 865                return -ENOMEM;
 866        INIT_LIST_HEAD(&lprof->lp_list);
 867
 868        LASSERT(proflen == (strlen(prof) + 1));
 869        OBD_ALLOC(lprof->lp_profile, proflen);
 870        if (lprof->lp_profile == NULL) {
 871                err = -ENOMEM;
 872                goto out;
 873        }
 874        memcpy(lprof->lp_profile, prof, proflen);
 875
 876        LASSERT(osclen == (strlen(osc) + 1));
 877        OBD_ALLOC(lprof->lp_dt, osclen);
 878        if (lprof->lp_dt == NULL) {
 879                err = -ENOMEM;
 880                goto out;
 881        }
 882        memcpy(lprof->lp_dt, osc, osclen);
 883
 884        if (mdclen > 0) {
 885                LASSERT(mdclen == (strlen(mdc) + 1));
 886                OBD_ALLOC(lprof->lp_md, mdclen);
 887                if (lprof->lp_md == NULL) {
 888                        err = -ENOMEM;
 889                        goto out;
 890                }
 891                memcpy(lprof->lp_md, mdc, mdclen);
 892        }
 893
 894        list_add(&lprof->lp_list, &lustre_profile_list);
 895        return err;
 896
 897out:
 898        if (lprof->lp_md)
 899                OBD_FREE(lprof->lp_md, mdclen);
 900        if (lprof->lp_dt)
 901                OBD_FREE(lprof->lp_dt, osclen);
 902        if (lprof->lp_profile)
 903                OBD_FREE(lprof->lp_profile, proflen);
 904        OBD_FREE(lprof, sizeof(*lprof));
 905        return err;
 906}
 907
 908void class_del_profile(const char *prof)
 909{
 910        struct lustre_profile *lprof;
 911
 912        CDEBUG(D_CONFIG, "Del profile %s\n", prof);
 913
 914        lprof = class_get_profile(prof);
 915        if (lprof) {
 916                list_del(&lprof->lp_list);
 917                OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
 918                OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
 919                if (lprof->lp_md)
 920                        OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
 921                OBD_FREE(lprof, sizeof(*lprof));
 922        }
 923}
 924EXPORT_SYMBOL(class_del_profile);
 925
 926/* COMPAT_146 */
 927void class_del_profiles(void)
 928{
 929        struct lustre_profile *lprof, *n;
 930
 931        list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
 932                list_del(&lprof->lp_list);
 933                OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
 934                OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
 935                if (lprof->lp_md)
 936                        OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
 937                OBD_FREE(lprof, sizeof(*lprof));
 938        }
 939}
 940EXPORT_SYMBOL(class_del_profiles);
 941
 942static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
 943{
 944        if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
 945                at_min = val;
 946        else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
 947                at_max = val;
 948        else if (class_match_param(ptr, PARAM_AT_EXTRA, NULL) == 0)
 949                at_extra = val;
 950        else if (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, NULL) == 0)
 951                at_early_margin = val;
 952        else if (class_match_param(ptr, PARAM_AT_HISTORY, NULL) == 0)
 953                at_history = val;
 954        else if (class_match_param(ptr, PARAM_JOBID_VAR, NULL) == 0)
 955                strlcpy(obd_jobid_var, lustre_cfg_string(lcfg, 2),
 956                        JOBSTATS_JOBID_VAR_MAX_LEN + 1);
 957        else
 958                return -EINVAL;
 959
 960        CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
 961        return 0;
 962}
 963
 964
 965/* We can't call ll_process_config or lquota_process_config directly because
 966 * it lives in a module that must be loaded after this one. */
 967static int (*client_process_config)(struct lustre_cfg *lcfg) = NULL;
 968static int (*quota_process_config)(struct lustre_cfg *lcfg) = NULL;
 969
 970void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
 971{
 972        client_process_config = cpc;
 973}
 974EXPORT_SYMBOL(lustre_register_client_process_config);
 975
 976/**
 977 * Rename the proc parameter in \a cfg with a new name \a new_name.
 978 *
 979 * \param cfg      config structure which contains the proc parameter
 980 * \param new_name new name of the proc parameter
 981 *
 982 * \retval valid-pointer    pointer to the newly-allocated config structure
 983 *                          which contains the renamed proc parameter
 984 * \retval ERR_PTR(-EINVAL) if \a cfg or \a new_name is NULL, or \a cfg does
 985 *                          not contain a proc parameter
 986 * \retval ERR_PTR(-ENOMEM) if memory allocation failure occurs
 987 */
 988struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
 989                                     const char *new_name)
 990{
 991        struct lustre_cfg_bufs  *bufs = NULL;
 992        struct lustre_cfg       *new_cfg = NULL;
 993        char                    *param = NULL;
 994        char                    *new_param = NULL;
 995        char                    *value = NULL;
 996        int                      name_len = 0;
 997        int                      new_len = 0;
 998
 999        if (cfg == NULL || new_name == NULL)
1000                return ERR_PTR(-EINVAL);
1001
1002        param = lustre_cfg_string(cfg, 1);
1003        if (param == NULL)
1004                return ERR_PTR(-EINVAL);
1005
1006        value = strchr(param, '=');
1007        if (value == NULL)
1008                name_len = strlen(param);
1009        else
1010                name_len = value - param;
1011
1012        new_len = LUSTRE_CFG_BUFLEN(cfg, 1) + strlen(new_name) - name_len;
1013
1014        OBD_ALLOC(new_param, new_len);
1015        if (new_param == NULL)
1016                return ERR_PTR(-ENOMEM);
1017
1018        strcpy(new_param, new_name);
1019        if (value != NULL)
1020                strcat(new_param, value);
1021
1022        OBD_ALLOC_PTR(bufs);
1023        if (bufs == NULL) {
1024                OBD_FREE(new_param, new_len);
1025                return ERR_PTR(-ENOMEM);
1026        }
1027
1028        lustre_cfg_bufs_reset(bufs, NULL);
1029        lustre_cfg_bufs_init(bufs, cfg);
1030        lustre_cfg_bufs_set_string(bufs, 1, new_param);
1031
1032        new_cfg = lustre_cfg_new(cfg->lcfg_command, bufs);
1033
1034        OBD_FREE(new_param, new_len);
1035        OBD_FREE_PTR(bufs);
1036        if (new_cfg == NULL)
1037                return ERR_PTR(-ENOMEM);
1038
1039        new_cfg->lcfg_num = cfg->lcfg_num;
1040        new_cfg->lcfg_flags = cfg->lcfg_flags;
1041        new_cfg->lcfg_nid = cfg->lcfg_nid;
1042        new_cfg->lcfg_nal = cfg->lcfg_nal;
1043
1044        return new_cfg;
1045}
1046EXPORT_SYMBOL(lustre_cfg_rename);
1047
1048static int process_param2_config(struct lustre_cfg *lcfg)
1049{
1050        char *param = lustre_cfg_string(lcfg, 1);
1051        char *upcall = lustre_cfg_string(lcfg, 2);
1052        char *argv[] = {
1053                [0] = "/usr/sbin/lctl",
1054                [1] = "set_param",
1055                [2] = param,
1056                [3] = NULL
1057        };
1058        struct timeval  start;
1059        struct timeval  end;
1060        int             rc;
1061
1062
1063        /* Add upcall processing here. Now only lctl is supported */
1064        if (strcmp(upcall, LCTL_UPCALL) != 0) {
1065                CERROR("Unsupported upcall %s\n", upcall);
1066                return -EINVAL;
1067        }
1068
1069        do_gettimeofday(&start);
1070        rc = call_usermodehelper(argv[0], argv, NULL, 1);
1071        do_gettimeofday(&end);
1072
1073        if (rc < 0) {
1074                CERROR(
1075                       "lctl: error invoking upcall %s %s %s: rc = %d; time %ldus\n",
1076                       argv[0], argv[1], argv[2], rc,
1077                       cfs_timeval_sub(&end, &start, NULL));
1078        } else {
1079                CDEBUG(D_HA, "lctl: invoked upcall %s %s %s, time %ldus\n",
1080                       argv[0], argv[1], argv[2],
1081                       cfs_timeval_sub(&end, &start, NULL));
1082                       rc = 0;
1083        }
1084
1085        return rc;
1086}
1087
1088void lustre_register_quota_process_config(int (*qpc)(struct lustre_cfg *lcfg))
1089{
1090        quota_process_config = qpc;
1091}
1092EXPORT_SYMBOL(lustre_register_quota_process_config);
1093
1094/** Process configuration commands given in lustre_cfg form.
1095 * These may come from direct calls (e.g. class_manual_cleanup)
1096 * or processing the config llog, or ioctl from lctl.
1097 */
1098int class_process_config(struct lustre_cfg *lcfg)
1099{
1100        struct obd_device *obd;
1101        int err;
1102
1103        LASSERT(lcfg && !IS_ERR(lcfg));
1104        CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
1105
1106        /* Commands that don't need a device */
1107        switch (lcfg->lcfg_command) {
1108        case LCFG_ATTACH: {
1109                err = class_attach(lcfg);
1110                goto out;
1111        }
1112        case LCFG_ADD_UUID: {
1113                CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid %#llx (%s)\n",
1114                       lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid,
1115                       libcfs_nid2str(lcfg->lcfg_nid));
1116
1117                err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
1118                goto out;
1119        }
1120        case LCFG_DEL_UUID: {
1121                CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
1122                       (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) == 0)
1123                       ? "<all uuids>" : lustre_cfg_string(lcfg, 1));
1124
1125                err = class_del_uuid(lustre_cfg_string(lcfg, 1));
1126                goto out;
1127        }
1128        case LCFG_MOUNTOPT: {
1129                CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
1130                       lustre_cfg_string(lcfg, 1),
1131                       lustre_cfg_string(lcfg, 2),
1132                       lustre_cfg_string(lcfg, 3));
1133                /* set these mount options somewhere, so ll_fill_super
1134                 * can find them. */
1135                err = class_add_profile(LUSTRE_CFG_BUFLEN(lcfg, 1),
1136                                        lustre_cfg_string(lcfg, 1),
1137                                        LUSTRE_CFG_BUFLEN(lcfg, 2),
1138                                        lustre_cfg_string(lcfg, 2),
1139                                        LUSTRE_CFG_BUFLEN(lcfg, 3),
1140                                        lustre_cfg_string(lcfg, 3));
1141                goto out;
1142        }
1143        case LCFG_DEL_MOUNTOPT: {
1144                CDEBUG(D_IOCTL, "mountopt: profile %s\n",
1145                       lustre_cfg_string(lcfg, 1));
1146                class_del_profile(lustre_cfg_string(lcfg, 1));
1147                err = 0;
1148                goto out;
1149        }
1150        case LCFG_SET_TIMEOUT: {
1151                CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
1152                       obd_timeout, lcfg->lcfg_num);
1153                obd_timeout = max(lcfg->lcfg_num, 1U);
1154                obd_timeout_set = 1;
1155                err = 0;
1156                goto out;
1157        }
1158        case LCFG_SET_LDLM_TIMEOUT: {
1159                CDEBUG(D_IOCTL, "changing lustre ldlm_timeout from %d to %d\n",
1160                       ldlm_timeout, lcfg->lcfg_num);
1161                ldlm_timeout = max(lcfg->lcfg_num, 1U);
1162                if (ldlm_timeout >= obd_timeout)
1163                        ldlm_timeout = max(obd_timeout / 3, 1U);
1164                ldlm_timeout_set = 1;
1165                err = 0;
1166                goto out;
1167        }
1168        case LCFG_SET_UPCALL: {
1169                LCONSOLE_ERROR_MSG(0x15a, "recovery upcall is deprecated\n");
1170                /* COMPAT_146 Don't fail on old configs */
1171                err = 0;
1172                goto out;
1173        }
1174        case LCFG_MARKER: {
1175                struct cfg_marker *marker;
1176                marker = lustre_cfg_buf(lcfg, 1);
1177                CDEBUG(D_IOCTL, "marker %d (%#x) %.16s %s\n", marker->cm_step,
1178                       marker->cm_flags, marker->cm_tgtname, marker->cm_comment);
1179                err = 0;
1180                goto out;
1181        }
1182        case LCFG_PARAM: {
1183                char *tmp;
1184                /* llite has no obd */
1185                if ((class_match_param(lustre_cfg_string(lcfg, 1),
1186                                       PARAM_LLITE, NULL) == 0) &&
1187                    client_process_config) {
1188                        err = (*client_process_config)(lcfg);
1189                        goto out;
1190                } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
1191                                              PARAM_SYS, &tmp) == 0)) {
1192                        /* Global param settings */
1193                        err = class_set_global(tmp, lcfg->lcfg_num, lcfg);
1194                        /*
1195                         * Client or server should not fail to mount if
1196                         * it hits an unknown configuration parameter.
1197                         */
1198                        if (err != 0)
1199                                CWARN("Ignoring unknown param %s\n", tmp);
1200
1201                        err = 0;
1202                        goto out;
1203                } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
1204                                              PARAM_QUOTA, &tmp) == 0) &&
1205                           quota_process_config) {
1206                        err = (*quota_process_config)(lcfg);
1207                        goto out;
1208                }
1209
1210                break;
1211        }
1212        case LCFG_SET_PARAM: {
1213                err = process_param2_config(lcfg);
1214                goto out;
1215        }
1216        }
1217        /* Commands that require a device */
1218        obd = class_name2obd(lustre_cfg_string(lcfg, 0));
1219        if (obd == NULL) {
1220                if (!LUSTRE_CFG_BUFLEN(lcfg, 0))
1221                        CERROR("this lcfg command requires a device name\n");
1222                else
1223                        CERROR("no device for: %s\n",
1224                               lustre_cfg_string(lcfg, 0));
1225
1226                err = -EINVAL;
1227                goto out;
1228        }
1229
1230        switch (lcfg->lcfg_command) {
1231        case LCFG_SETUP: {
1232                err = class_setup(obd, lcfg);
1233                goto out;
1234        }
1235        case LCFG_DETACH: {
1236                err = class_detach(obd, lcfg);
1237                err = 0;
1238                goto out;
1239        }
1240        case LCFG_CLEANUP: {
1241                err = class_cleanup(obd, lcfg);
1242                err = 0;
1243                goto out;
1244        }
1245        case LCFG_ADD_CONN: {
1246                err = class_add_conn(obd, lcfg);
1247                err = 0;
1248                goto out;
1249        }
1250        case LCFG_DEL_CONN: {
1251                err = class_del_conn(obd, lcfg);
1252                err = 0;
1253                goto out;
1254        }
1255        case LCFG_POOL_NEW: {
1256                err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
1257                err = 0;
1258                goto out;
1259        }
1260        case LCFG_POOL_ADD: {
1261                err = obd_pool_add(obd, lustre_cfg_string(lcfg, 2),
1262                                   lustre_cfg_string(lcfg, 3));
1263                err = 0;
1264                goto out;
1265        }
1266        case LCFG_POOL_REM: {
1267                err = obd_pool_rem(obd, lustre_cfg_string(lcfg, 2),
1268                                   lustre_cfg_string(lcfg, 3));
1269                err = 0;
1270                goto out;
1271        }
1272        case LCFG_POOL_DEL: {
1273                err = obd_pool_del(obd, lustre_cfg_string(lcfg, 2));
1274                err = 0;
1275                goto out;
1276        }
1277        default: {
1278                err = obd_process_config(obd, sizeof(*lcfg), lcfg);
1279                goto out;
1280
1281        }
1282        }
1283out:
1284        if ((err < 0) && !(lcfg->lcfg_command & LCFG_REQUIRED)) {
1285                CWARN("Ignoring error %d on optional command %#x\n", err,
1286                      lcfg->lcfg_command);
1287                err = 0;
1288        }
1289        return err;
1290}
1291EXPORT_SYMBOL(class_process_config);
1292
1293int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
1294                             struct lustre_cfg *lcfg, void *data)
1295{
1296        struct lprocfs_vars *var;
1297        struct file fakefile;
1298        struct seq_file fake_seqfile;
1299        char *key, *sval;
1300        int i, keylen, vallen;
1301        int matched = 0, j = 0;
1302        int rc = 0;
1303        int skip = 0;
1304
1305        if (lcfg->lcfg_command != LCFG_PARAM) {
1306                CERROR("Unknown command: %d\n", lcfg->lcfg_command);
1307                return -EINVAL;
1308        }
1309
1310        /* fake a seq file so that var->fops->write can work... */
1311        fakefile.private_data = &fake_seqfile;
1312        fake_seqfile.private = data;
1313        /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
1314           or   lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
1315           or   lctl conf_param lustre-OST0000.osc.max_dirty_mb=36 */
1316        for (i = 1; i < lcfg->lcfg_bufcount; i++) {
1317                key = lustre_cfg_buf(lcfg, i);
1318                /* Strip off prefix */
1319                class_match_param(key, prefix, &key);
1320                sval = strchr(key, '=');
1321                if (!sval || (*(sval + 1) == 0)) {
1322                        CERROR("Can't parse param %s (missing '=')\n", key);
1323                        /* rc = -EINVAL;        continue parsing other params */
1324                        continue;
1325                }
1326                keylen = sval - key;
1327                sval++;
1328                vallen = strlen(sval);
1329                matched = 0;
1330                j = 0;
1331                /* Search proc entries */
1332                while (lvars[j].name) {
1333                        var = &lvars[j];
1334                        if (class_match_param(key, (char *)var->name, NULL) == 0
1335                            && keylen == strlen(var->name)) {
1336                                matched++;
1337                                rc = -EROFS;
1338                                if (var->fops && var->fops->write) {
1339                                        mm_segment_t oldfs;
1340                                        oldfs = get_fs();
1341                                        set_fs(KERNEL_DS);
1342                                        rc = (var->fops->write)(&fakefile, sval,
1343                                                                vallen, NULL);
1344                                        set_fs(oldfs);
1345                                }
1346                                break;
1347                        }
1348                        j++;
1349                }
1350                if (!matched) {
1351                        /* If the prefix doesn't match, return error so we
1352                           can pass it down the stack */
1353                        if (strnchr(key, keylen, '.'))
1354                            return -ENOSYS;
1355                        CERROR("%s: unknown param %s\n",
1356                               (char *)lustre_cfg_string(lcfg, 0), key);
1357                        /* rc = -EINVAL;        continue parsing other params */
1358                        skip++;
1359                } else if (rc < 0) {
1360                        CERROR("writing proc entry %s err %d\n",
1361                               var->name, rc);
1362                        rc = 0;
1363                } else {
1364                        CDEBUG(D_CONFIG, "%s.%.*s: Set parameter %.*s=%s\n",
1365                                         lustre_cfg_string(lcfg, 0),
1366                                         (int)strlen(prefix) - 1, prefix,
1367                                         (int)(sval - key - 1), key, sval);
1368                }
1369        }
1370
1371        if (rc > 0)
1372                rc = 0;
1373        if (!rc && skip)
1374                rc = skip;
1375        return rc;
1376}
1377EXPORT_SYMBOL(class_process_proc_param);
1378
1379extern int lustre_check_exclusion(struct super_block *sb, char *svname);
1380
1381/** Parse a configuration llog, doing various manipulations on them
1382 * for various reasons, (modifications for compatibility, skip obsolete
1383 * records, change uuids, etc), then class_process_config() resulting
1384 * net records.
1385 */
1386int class_config_llog_handler(const struct lu_env *env,
1387                              struct llog_handle *handle,
1388                              struct llog_rec_hdr *rec, void *data)
1389{
1390        struct config_llog_instance *clli = data;
1391        int cfg_len = rec->lrh_len;
1392        char *cfg_buf = (char *) (rec + 1);
1393        int rc = 0;
1394
1395        //class_config_dump_handler(handle, rec, data);
1396
1397        switch (rec->lrh_type) {
1398        case OBD_CFG_REC: {
1399                struct lustre_cfg *lcfg, *lcfg_new;
1400                struct lustre_cfg_bufs bufs;
1401                char *inst_name = NULL;
1402                int inst_len = 0;
1403                int inst = 0, swab = 0;
1404
1405                lcfg = (struct lustre_cfg *)cfg_buf;
1406                if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
1407                        lustre_swab_lustre_cfg(lcfg);
1408                        swab = 1;
1409                }
1410
1411                rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1412                if (rc)
1413                        goto out;
1414
1415                /* Figure out config state info */
1416                if (lcfg->lcfg_command == LCFG_MARKER) {
1417                        struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1418                        lustre_swab_cfg_marker(marker, swab,
1419                                               LUSTRE_CFG_BUFLEN(lcfg, 1));
1420                        CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
1421                               clli->cfg_flags, marker->cm_flags);
1422                        if (marker->cm_flags & CM_START) {
1423                                /* all previous flags off */
1424                                clli->cfg_flags = CFG_F_MARKER;
1425                                if (marker->cm_flags & CM_SKIP) {
1426                                        clli->cfg_flags |= CFG_F_SKIP;
1427                                        CDEBUG(D_CONFIG, "SKIP #%d\n",
1428                                               marker->cm_step);
1429                                } else if ((marker->cm_flags & CM_EXCLUDE) ||
1430                                           (clli->cfg_sb &&
1431                                            lustre_check_exclusion(clli->cfg_sb,
1432                                                         marker->cm_tgtname))) {
1433                                        clli->cfg_flags |= CFG_F_EXCLUDE;
1434                                        CDEBUG(D_CONFIG, "EXCLUDE %d\n",
1435                                               marker->cm_step);
1436                                }
1437                        } else if (marker->cm_flags & CM_END) {
1438                                clli->cfg_flags = 0;
1439                        }
1440                }
1441                /* A config command without a start marker before it is
1442                   illegal (post 146) */
1443                if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
1444                    !(clli->cfg_flags & CFG_F_MARKER) &&
1445                    (lcfg->lcfg_command != LCFG_MARKER)) {
1446                        CWARN("Config not inside markers, ignoring! (inst: %p, uuid: %s, flags: %#x)\n",
1447                              clli->cfg_instance,
1448                              clli->cfg_uuid.uuid, clli->cfg_flags);
1449                        clli->cfg_flags |= CFG_F_SKIP;
1450                }
1451                if (clli->cfg_flags & CFG_F_SKIP) {
1452                        CDEBUG(D_CONFIG, "skipping %#x\n",
1453                               clli->cfg_flags);
1454                        rc = 0;
1455                        /* No processing! */
1456                        break;
1457                }
1458
1459                /*
1460                 * For interoperability between 1.8 and 2.0,
1461                 * rename "mds" obd device type to "mdt".
1462                 */
1463                {
1464                        char *typename = lustre_cfg_string(lcfg, 1);
1465                        char *index = lustre_cfg_string(lcfg, 2);
1466
1467                        if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
1468                             strcmp(typename, "mds") == 0)) {
1469                                CWARN("For 1.8 interoperability, rename obd type from mds to mdt\n");
1470                                typename[2] = 't';
1471                        }
1472                        if ((lcfg->lcfg_command == LCFG_SETUP && index &&
1473                             strcmp(index, "type") == 0)) {
1474                                CDEBUG(D_INFO, "For 1.8 interoperability, set this index to '0'\n");
1475                                index[0] = '0';
1476                                index[1] = 0;
1477                        }
1478                }
1479
1480
1481                if (clli->cfg_flags & CFG_F_EXCLUDE) {
1482                        CDEBUG(D_CONFIG, "cmd: %x marked EXCLUDED\n",
1483                               lcfg->lcfg_command);
1484                        if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD)
1485                                /* Add inactive instead */
1486                                lcfg->lcfg_command = LCFG_LOV_ADD_INA;
1487                }
1488
1489                lustre_cfg_bufs_init(&bufs, lcfg);
1490
1491                if (clli && clli->cfg_instance &&
1492                    LUSTRE_CFG_BUFLEN(lcfg, 0) > 0){
1493                        inst = 1;
1494                        inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
1495                                   sizeof(clli->cfg_instance) * 2 + 4;
1496                        OBD_ALLOC(inst_name, inst_len);
1497                        if (inst_name == NULL) {
1498                                rc = -ENOMEM;
1499                                goto out;
1500                        }
1501                        sprintf(inst_name, "%s-%p",
1502                                lustre_cfg_string(lcfg, 0),
1503                                clli->cfg_instance);
1504                        lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
1505                        CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n",
1506                               lcfg->lcfg_command, inst_name);
1507                }
1508
1509                /* we override the llog's uuid for clients, to insure they
1510                are unique */
1511                if (clli && clli->cfg_instance != NULL &&
1512                    lcfg->lcfg_command == LCFG_ATTACH) {
1513                        lustre_cfg_bufs_set_string(&bufs, 2,
1514                                                   clli->cfg_uuid.uuid);
1515                }
1516                /*
1517                 * sptlrpc config record, we expect 2 data segments:
1518                 *  [0]: fs_name/target_name,
1519                 *  [1]: rule string
1520                 * moving them to index [1] and [2], and insert MGC's
1521                 * obdname at index [0].
1522                 */
1523                if (clli && clli->cfg_instance == NULL &&
1524                    lcfg->lcfg_command == LCFG_SPTLRPC_CONF) {
1525                        lustre_cfg_bufs_set(&bufs, 2, bufs.lcfg_buf[1],
1526                                            bufs.lcfg_buflen[1]);
1527                        lustre_cfg_bufs_set(&bufs, 1, bufs.lcfg_buf[0],
1528                                            bufs.lcfg_buflen[0]);
1529                        lustre_cfg_bufs_set_string(&bufs, 0,
1530                                                   clli->cfg_obdname);
1531                }
1532
1533                lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
1534
1535                lcfg_new->lcfg_num   = lcfg->lcfg_num;
1536                lcfg_new->lcfg_flags = lcfg->lcfg_flags;
1537
1538                /* XXX Hack to try to remain binary compatible with
1539                 * pre-newconfig logs */
1540                if (lcfg->lcfg_nal != 0 &&      /* pre-newconfig log? */
1541                    (lcfg->lcfg_nid >> 32) == 0) {
1542                        __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
1543
1544                        lcfg_new->lcfg_nid =
1545                                LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
1546                        CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
1547                              lcfg->lcfg_nal, addr,
1548                              libcfs_nid2str(lcfg_new->lcfg_nid));
1549                } else {
1550                        lcfg_new->lcfg_nid = lcfg->lcfg_nid;
1551                }
1552
1553                lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
1554
1555                rc = class_process_config(lcfg_new);
1556                lustre_cfg_free(lcfg_new);
1557
1558                if (inst)
1559                        OBD_FREE(inst_name, inst_len);
1560                break;
1561        }
1562        default:
1563                CERROR("Unknown llog record type %#x encountered\n",
1564                       rec->lrh_type);
1565                break;
1566        }
1567out:
1568        if (rc) {
1569                CERROR("%s: cfg command failed: rc = %d\n",
1570                       handle->lgh_ctxt->loc_obd->obd_name, rc);
1571                class_config_dump_handler(NULL, handle, rec, data);
1572        }
1573        return rc;
1574}
1575EXPORT_SYMBOL(class_config_llog_handler);
1576
1577int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
1578                            char *name, struct config_llog_instance *cfg)
1579{
1580        struct llog_process_cat_data     cd = {0, 0};
1581        struct llog_handle              *llh;
1582        llog_cb_t                        callback;
1583        int                              rc;
1584
1585        CDEBUG(D_INFO, "looking up llog %s\n", name);
1586        rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
1587        if (rc)
1588                return rc;
1589
1590        rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
1591        if (rc)
1592                goto parse_out;
1593
1594        /* continue processing from where we last stopped to end-of-log */
1595        if (cfg) {
1596                cd.lpcd_first_idx = cfg->cfg_last_idx;
1597                callback = cfg->cfg_callback;
1598                LASSERT(callback != NULL);
1599        } else {
1600                callback = class_config_llog_handler;
1601        }
1602
1603        cd.lpcd_last_idx = 0;
1604
1605        rc = llog_process(env, llh, callback, cfg, &cd);
1606
1607        CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name,
1608               cd.lpcd_first_idx + 1, cd.lpcd_last_idx, rc);
1609        if (cfg)
1610                cfg->cfg_last_idx = cd.lpcd_last_idx;
1611
1612parse_out:
1613        llog_close(env, llh);
1614        return rc;
1615}
1616EXPORT_SYMBOL(class_config_parse_llog);
1617
1618/**
1619 * parse config record and output dump in supplied buffer.
1620 * This is separated from class_config_dump_handler() to use
1621 * for ioctl needs as well
1622 */
1623int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, int size)
1624{
1625        struct lustre_cfg       *lcfg = (struct lustre_cfg *)(rec + 1);
1626        char                    *ptr = buf;
1627        char                    *end = buf + size;
1628        int                      rc = 0;
1629
1630        LASSERT(rec->lrh_type == OBD_CFG_REC);
1631        rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len);
1632        if (rc < 0)
1633                return rc;
1634
1635        ptr += snprintf(ptr, end-ptr, "cmd=%05x ", lcfg->lcfg_command);
1636        if (lcfg->lcfg_flags)
1637                ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
1638                                lcfg->lcfg_flags);
1639
1640        if (lcfg->lcfg_num)
1641                ptr += snprintf(ptr, end-ptr, "num=%#08x ", lcfg->lcfg_num);
1642
1643        if (lcfg->lcfg_nid)
1644                ptr += snprintf(ptr, end-ptr, "nid=%s(%#llx)\n     ",
1645                                libcfs_nid2str(lcfg->lcfg_nid),
1646                                lcfg->lcfg_nid);
1647
1648        if (lcfg->lcfg_command == LCFG_MARKER) {
1649                struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1650
1651                ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'",
1652                                marker->cm_step, marker->cm_flags,
1653                                marker->cm_tgtname, marker->cm_comment);
1654        } else {
1655                int i;
1656
1657                for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
1658                        ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
1659                                        lustre_cfg_string(lcfg, i));
1660                }
1661        }
1662        /* return consumed bytes */
1663        rc = ptr - buf;
1664        return rc;
1665}
1666
1667int class_config_dump_handler(const struct lu_env *env,
1668                              struct llog_handle *handle,
1669                              struct llog_rec_hdr *rec, void *data)
1670{
1671        char    *outstr;
1672        int      rc = 0;
1673
1674        OBD_ALLOC(outstr, 256);
1675        if (outstr == NULL)
1676                return -ENOMEM;
1677
1678        if (rec->lrh_type == OBD_CFG_REC) {
1679                class_config_parse_rec(rec, outstr, 256);
1680                LCONSOLE(D_WARNING, "   %s\n", outstr);
1681        } else {
1682                LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
1683                rc = -EINVAL;
1684        }
1685
1686        OBD_FREE(outstr, 256);
1687        return rc;
1688}
1689
1690int class_config_dump_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
1691                           char *name, struct config_llog_instance *cfg)
1692{
1693        struct llog_handle      *llh;
1694        int                      rc;
1695
1696        LCONSOLE_INFO("Dumping config log %s\n", name);
1697
1698        rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
1699        if (rc)
1700                return rc;
1701
1702        rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
1703        if (rc)
1704                goto parse_out;
1705
1706        rc = llog_process(env, llh, class_config_dump_handler, cfg, NULL);
1707parse_out:
1708        llog_close(env, llh);
1709
1710        LCONSOLE_INFO("End config log %s\n", name);
1711        return rc;
1712}
1713EXPORT_SYMBOL(class_config_dump_llog);
1714
1715/** Call class_cleanup and class_detach.
1716 * "Manual" only in the sense that we're faking lcfg commands.
1717 */
1718int class_manual_cleanup(struct obd_device *obd)
1719{
1720        char                flags[3] = "";
1721        struct lustre_cfg      *lcfg;
1722        struct lustre_cfg_bufs  bufs;
1723        int                  rc;
1724
1725        if (!obd) {
1726                CERROR("empty cleanup\n");
1727                return -EALREADY;
1728        }
1729
1730        if (obd->obd_force)
1731                strcat(flags, "F");
1732        if (obd->obd_fail)
1733                strcat(flags, "A");
1734
1735        CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
1736               obd->obd_name, flags);
1737
1738        lustre_cfg_bufs_reset(&bufs, obd->obd_name);
1739        lustre_cfg_bufs_set_string(&bufs, 1, flags);
1740        lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
1741        if (!lcfg)
1742                return -ENOMEM;
1743
1744        rc = class_process_config(lcfg);
1745        if (rc) {
1746                CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
1747                goto out;
1748        }
1749
1750        /* the lcfg is almost the same for both ops */
1751        lcfg->lcfg_command = LCFG_DETACH;
1752        rc = class_process_config(lcfg);
1753        if (rc)
1754                CERROR("detach failed %d: %s\n", rc, obd->obd_name);
1755out:
1756        lustre_cfg_free(lcfg);
1757        return rc;
1758}
1759EXPORT_SYMBOL(class_manual_cleanup);
1760
1761/*
1762 * uuid<->export lustre hash operations
1763 */
1764
1765static unsigned
1766uuid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
1767{
1768        return cfs_hash_djb2_hash(((struct obd_uuid *)key)->uuid,
1769                                  sizeof(((struct obd_uuid *)key)->uuid), mask);
1770}
1771
1772static void *
1773uuid_key(struct hlist_node *hnode)
1774{
1775        struct obd_export *exp;
1776
1777        exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1778
1779        return &exp->exp_client_uuid;
1780}
1781
1782/*
1783 * NOTE: It is impossible to find an export that is in failed
1784 *       state with this function
1785 */
1786static int
1787uuid_keycmp(const void *key, struct hlist_node *hnode)
1788{
1789        struct obd_export *exp;
1790
1791        LASSERT(key);
1792        exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1793
1794        return obd_uuid_equals(key, &exp->exp_client_uuid) &&
1795               !exp->exp_failed;
1796}
1797
1798static void *
1799uuid_export_object(struct hlist_node *hnode)
1800{
1801        return hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1802}
1803
1804static void
1805uuid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
1806{
1807        struct obd_export *exp;
1808
1809        exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1810        class_export_get(exp);
1811}
1812
1813static void
1814uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
1815{
1816        struct obd_export *exp;
1817
1818        exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1819        class_export_put(exp);
1820}
1821
1822static cfs_hash_ops_t uuid_hash_ops = {
1823        .hs_hash        = uuid_hash,
1824        .hs_key  = uuid_key,
1825        .hs_keycmp      = uuid_keycmp,
1826        .hs_object      = uuid_export_object,
1827        .hs_get  = uuid_export_get,
1828        .hs_put_locked  = uuid_export_put_locked,
1829};
1830
1831
1832/*
1833 * nid<->export hash operations
1834 */
1835
1836static unsigned
1837nid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
1838{
1839        return cfs_hash_djb2_hash(key, sizeof(lnet_nid_t), mask);
1840}
1841
1842static void *
1843nid_key(struct hlist_node *hnode)
1844{
1845        struct obd_export *exp;
1846
1847        exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1848
1849        return &exp->exp_connection->c_peer.nid;
1850}
1851
1852/*
1853 * NOTE: It is impossible to find an export that is in failed
1854 *       state with this function
1855 */
1856static int
1857nid_kepcmp(const void *key, struct hlist_node *hnode)
1858{
1859        struct obd_export *exp;
1860
1861        LASSERT(key);
1862        exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1863
1864        return exp->exp_connection->c_peer.nid == *(lnet_nid_t *)key &&
1865               !exp->exp_failed;
1866}
1867
1868static void *
1869nid_export_object(struct hlist_node *hnode)
1870{
1871        return hlist_entry(hnode, struct obd_export, exp_nid_hash);
1872}
1873
1874static void
1875nid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
1876{
1877        struct obd_export *exp;
1878
1879        exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1880        class_export_get(exp);
1881}
1882
1883static void
1884nid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
1885{
1886        struct obd_export *exp;
1887
1888        exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1889        class_export_put(exp);
1890}
1891
1892static cfs_hash_ops_t nid_hash_ops = {
1893        .hs_hash        = nid_hash,
1894        .hs_key  = nid_key,
1895        .hs_keycmp      = nid_kepcmp,
1896        .hs_object      = nid_export_object,
1897        .hs_get  = nid_export_get,
1898        .hs_put_locked  = nid_export_put_locked,
1899};
1900
1901
1902/*
1903 * nid<->nidstats hash operations
1904 */
1905
1906static void *
1907nidstats_key(struct hlist_node *hnode)
1908{
1909        struct nid_stat *ns;
1910
1911        ns = hlist_entry(hnode, struct nid_stat, nid_hash);
1912
1913        return &ns->nid;
1914}
1915
1916static int
1917nidstats_keycmp(const void *key, struct hlist_node *hnode)
1918{
1919        return *(lnet_nid_t *)nidstats_key(hnode) == *(lnet_nid_t *)key;
1920}
1921
1922static void *
1923nidstats_object(struct hlist_node *hnode)
1924{
1925        return hlist_entry(hnode, struct nid_stat, nid_hash);
1926}
1927
1928static void
1929nidstats_get(struct cfs_hash *hs, struct hlist_node *hnode)
1930{
1931        struct nid_stat *ns;
1932
1933        ns = hlist_entry(hnode, struct nid_stat, nid_hash);
1934        nidstat_getref(ns);
1935}
1936
1937static void
1938nidstats_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
1939{
1940        struct nid_stat *ns;
1941
1942        ns = hlist_entry(hnode, struct nid_stat, nid_hash);
1943        nidstat_putref(ns);
1944}
1945
1946static cfs_hash_ops_t nid_stat_hash_ops = {
1947        .hs_hash        = nid_hash,
1948        .hs_key  = nidstats_key,
1949        .hs_keycmp      = nidstats_keycmp,
1950        .hs_object      = nidstats_object,
1951        .hs_get  = nidstats_get,
1952        .hs_put_locked  = nidstats_put_locked,
1953};
1954