linux/drivers/staging/lustre/lustre/ldlm/ldlm_resource.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) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2010, 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 * lustre/ldlm/ldlm_resource.c
  37 *
  38 * Author: Phil Schwan <phil@clusterfs.com>
  39 * Author: Peter Braam <braam@clusterfs.com>
  40 */
  41
  42#define DEBUG_SUBSYSTEM S_LDLM
  43#include "../include/lustre_dlm.h"
  44#include "../include/lustre_fid.h"
  45#include "../include/obd_class.h"
  46#include "ldlm_internal.h"
  47
  48struct kmem_cache *ldlm_resource_slab, *ldlm_lock_slab;
  49
  50int ldlm_srv_namespace_nr;
  51int ldlm_cli_namespace_nr;
  52
  53struct mutex ldlm_srv_namespace_lock;
  54LIST_HEAD(ldlm_srv_namespace_list);
  55
  56struct mutex ldlm_cli_namespace_lock;
  57/* Client Namespaces that have active resources in them.
  58 * Once all resources go away, ldlm_poold moves such namespaces to the
  59 * inactive list
  60 */
  61LIST_HEAD(ldlm_cli_active_namespace_list);
  62/* Client namespaces that don't have any locks in them */
  63static LIST_HEAD(ldlm_cli_inactive_namespace_list);
  64
  65static struct dentry *ldlm_debugfs_dir;
  66static struct dentry *ldlm_ns_debugfs_dir;
  67struct dentry *ldlm_svc_debugfs_dir;
  68
  69/* during debug dump certain amount of granted locks for one resource to avoid
  70 * DDOS.
  71 */
  72static unsigned int ldlm_dump_granted_max = 256;
  73
  74static ssize_t
  75lprocfs_wr_dump_ns(struct file *file, const char __user *buffer,
  76                   size_t count, loff_t *off)
  77{
  78        ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE);
  79        ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE);
  80        return count;
  81}
  82
  83LPROC_SEQ_FOPS_WR_ONLY(ldlm, dump_ns);
  84
  85LPROC_SEQ_FOPS_RW_TYPE(ldlm_rw, uint);
  86
  87static struct lprocfs_vars ldlm_debugfs_list[] = {
  88        { "dump_namespaces", &ldlm_dump_ns_fops, NULL, 0222 },
  89        { "dump_granted_max", &ldlm_rw_uint_fops, &ldlm_dump_granted_max },
  90        { NULL }
  91};
  92
  93int ldlm_debugfs_setup(void)
  94{
  95        int rc;
  96
  97        ldlm_debugfs_dir = ldebugfs_register(OBD_LDLM_DEVICENAME,
  98                                             debugfs_lustre_root,
  99                                             NULL, NULL);
 100        if (IS_ERR_OR_NULL(ldlm_debugfs_dir)) {
 101                CERROR("LProcFS failed in ldlm-init\n");
 102                rc = ldlm_debugfs_dir ? PTR_ERR(ldlm_debugfs_dir) : -ENOMEM;
 103                goto err;
 104        }
 105
 106        ldlm_ns_debugfs_dir = ldebugfs_register("namespaces",
 107                                                ldlm_debugfs_dir,
 108                                                NULL, NULL);
 109        if (IS_ERR_OR_NULL(ldlm_ns_debugfs_dir)) {
 110                CERROR("LProcFS failed in ldlm-init\n");
 111                rc = ldlm_ns_debugfs_dir ? PTR_ERR(ldlm_ns_debugfs_dir)
 112                                         : -ENOMEM;
 113                goto err_type;
 114        }
 115
 116        ldlm_svc_debugfs_dir = ldebugfs_register("services",
 117                                                 ldlm_debugfs_dir,
 118                                                 NULL, NULL);
 119        if (IS_ERR_OR_NULL(ldlm_svc_debugfs_dir)) {
 120                CERROR("LProcFS failed in ldlm-init\n");
 121                rc = ldlm_svc_debugfs_dir ? PTR_ERR(ldlm_svc_debugfs_dir)
 122                                          : -ENOMEM;
 123                goto err_ns;
 124        }
 125
 126        rc = ldebugfs_add_vars(ldlm_debugfs_dir, ldlm_debugfs_list, NULL);
 127
 128        return 0;
 129
 130err_ns:
 131        ldebugfs_remove(&ldlm_ns_debugfs_dir);
 132err_type:
 133        ldebugfs_remove(&ldlm_debugfs_dir);
 134err:
 135        ldlm_svc_debugfs_dir = NULL;
 136        ldlm_ns_debugfs_dir = NULL;
 137        ldlm_debugfs_dir = NULL;
 138        return rc;
 139}
 140
 141void ldlm_debugfs_cleanup(void)
 142{
 143        if (!IS_ERR_OR_NULL(ldlm_svc_debugfs_dir))
 144                ldebugfs_remove(&ldlm_svc_debugfs_dir);
 145
 146        if (!IS_ERR_OR_NULL(ldlm_ns_debugfs_dir))
 147                ldebugfs_remove(&ldlm_ns_debugfs_dir);
 148
 149        if (!IS_ERR_OR_NULL(ldlm_debugfs_dir))
 150                ldebugfs_remove(&ldlm_debugfs_dir);
 151
 152        ldlm_svc_debugfs_dir = NULL;
 153        ldlm_ns_debugfs_dir = NULL;
 154        ldlm_debugfs_dir = NULL;
 155}
 156
 157static ssize_t resource_count_show(struct kobject *kobj, struct attribute *attr,
 158                                   char *buf)
 159{
 160        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 161                                                 ns_kobj);
 162        __u64             res = 0;
 163        struct cfs_hash_bd        bd;
 164        int                 i;
 165
 166        /* result is not strictly consistent */
 167        cfs_hash_for_each_bucket(ns->ns_rs_hash, &bd, i)
 168                res += cfs_hash_bd_count_get(&bd);
 169        return sprintf(buf, "%lld\n", res);
 170}
 171LUSTRE_RO_ATTR(resource_count);
 172
 173static ssize_t lock_count_show(struct kobject *kobj, struct attribute *attr,
 174                               char *buf)
 175{
 176        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 177                                                 ns_kobj);
 178        __u64             locks;
 179
 180        locks = lprocfs_stats_collector(ns->ns_stats, LDLM_NSS_LOCKS,
 181                                        LPROCFS_FIELDS_FLAGS_SUM);
 182        return sprintf(buf, "%lld\n", locks);
 183}
 184LUSTRE_RO_ATTR(lock_count);
 185
 186static ssize_t lock_unused_count_show(struct kobject *kobj,
 187                                      struct attribute *attr,
 188                                      char *buf)
 189{
 190        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 191                                                 ns_kobj);
 192
 193        return sprintf(buf, "%d\n", ns->ns_nr_unused);
 194}
 195LUSTRE_RO_ATTR(lock_unused_count);
 196
 197static ssize_t lru_size_show(struct kobject *kobj, struct attribute *attr,
 198                             char *buf)
 199{
 200        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 201                                                 ns_kobj);
 202        __u32 *nr = &ns->ns_max_unused;
 203
 204        if (ns_connect_lru_resize(ns))
 205                nr = &ns->ns_nr_unused;
 206        return sprintf(buf, "%u", *nr);
 207}
 208
 209static ssize_t lru_size_store(struct kobject *kobj, struct attribute *attr,
 210                              const char *buffer, size_t count)
 211{
 212        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 213                                                 ns_kobj);
 214        unsigned long tmp;
 215        int lru_resize;
 216        int err;
 217
 218        if (strncmp(buffer, "clear", 5) == 0) {
 219                CDEBUG(D_DLMTRACE,
 220                       "dropping all unused locks from namespace %s\n",
 221                       ldlm_ns_name(ns));
 222                if (ns_connect_lru_resize(ns)) {
 223                        int canceled, unused  = ns->ns_nr_unused;
 224
 225                        /* Try to cancel all @ns_nr_unused locks. */
 226                        canceled = ldlm_cancel_lru(ns, unused, 0,
 227                                                   LDLM_CANCEL_PASSED);
 228                        if (canceled < unused) {
 229                                CDEBUG(D_DLMTRACE,
 230                                       "not all requested locks are canceled, requested: %d, canceled: %d\n",
 231                                       unused,
 232                                       canceled);
 233                                return -EINVAL;
 234                        }
 235                } else {
 236                        tmp = ns->ns_max_unused;
 237                        ns->ns_max_unused = 0;
 238                        ldlm_cancel_lru(ns, 0, 0, LDLM_CANCEL_PASSED);
 239                        ns->ns_max_unused = tmp;
 240                }
 241                return count;
 242        }
 243
 244        err = kstrtoul(buffer, 10, &tmp);
 245        if (err != 0) {
 246                CERROR("lru_size: invalid value written\n");
 247                return -EINVAL;
 248        }
 249        lru_resize = (tmp == 0);
 250
 251        if (ns_connect_lru_resize(ns)) {
 252                if (!lru_resize)
 253                        ns->ns_max_unused = (unsigned int)tmp;
 254
 255                if (tmp > ns->ns_nr_unused)
 256                        tmp = ns->ns_nr_unused;
 257                tmp = ns->ns_nr_unused - tmp;
 258
 259                CDEBUG(D_DLMTRACE,
 260                       "changing namespace %s unused locks from %u to %u\n",
 261                       ldlm_ns_name(ns), ns->ns_nr_unused,
 262                       (unsigned int)tmp);
 263                ldlm_cancel_lru(ns, tmp, LCF_ASYNC, LDLM_CANCEL_PASSED);
 264
 265                if (!lru_resize) {
 266                        CDEBUG(D_DLMTRACE,
 267                               "disable lru_resize for namespace %s\n",
 268                               ldlm_ns_name(ns));
 269                        ns->ns_connect_flags &= ~OBD_CONNECT_LRU_RESIZE;
 270                }
 271        } else {
 272                CDEBUG(D_DLMTRACE,
 273                       "changing namespace %s max_unused from %u to %u\n",
 274                       ldlm_ns_name(ns), ns->ns_max_unused,
 275                       (unsigned int)tmp);
 276                ns->ns_max_unused = (unsigned int)tmp;
 277                ldlm_cancel_lru(ns, 0, LCF_ASYNC, LDLM_CANCEL_PASSED);
 278
 279                /* Make sure that LRU resize was originally supported before
 280                 * turning it on here.
 281                 */
 282                if (lru_resize &&
 283                    (ns->ns_orig_connect_flags & OBD_CONNECT_LRU_RESIZE)) {
 284                        CDEBUG(D_DLMTRACE,
 285                               "enable lru_resize for namespace %s\n",
 286                               ldlm_ns_name(ns));
 287                        ns->ns_connect_flags |= OBD_CONNECT_LRU_RESIZE;
 288                }
 289        }
 290
 291        return count;
 292}
 293LUSTRE_RW_ATTR(lru_size);
 294
 295static ssize_t lru_max_age_show(struct kobject *kobj, struct attribute *attr,
 296                                char *buf)
 297{
 298        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 299                                                 ns_kobj);
 300
 301        return sprintf(buf, "%u", ns->ns_max_age);
 302}
 303
 304static ssize_t lru_max_age_store(struct kobject *kobj, struct attribute *attr,
 305                                 const char *buffer, size_t count)
 306{
 307        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 308                                                 ns_kobj);
 309        unsigned long tmp;
 310        int err;
 311
 312        err = kstrtoul(buffer, 10, &tmp);
 313        if (err != 0)
 314                return -EINVAL;
 315
 316        ns->ns_max_age = tmp;
 317
 318        return count;
 319}
 320LUSTRE_RW_ATTR(lru_max_age);
 321
 322static ssize_t early_lock_cancel_show(struct kobject *kobj,
 323                                      struct attribute *attr,
 324                                      char *buf)
 325{
 326        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 327                                                 ns_kobj);
 328
 329        return sprintf(buf, "%d\n", ns_connect_cancelset(ns));
 330}
 331
 332static ssize_t early_lock_cancel_store(struct kobject *kobj,
 333                                       struct attribute *attr,
 334                                       const char *buffer,
 335                                       size_t count)
 336{
 337        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 338                                                 ns_kobj);
 339        unsigned long supp = -1;
 340        int rc;
 341
 342        rc = kstrtoul(buffer, 10, &supp);
 343        if (rc < 0)
 344                return rc;
 345
 346        if (supp == 0)
 347                ns->ns_connect_flags &= ~OBD_CONNECT_CANCELSET;
 348        else if (ns->ns_orig_connect_flags & OBD_CONNECT_CANCELSET)
 349                ns->ns_connect_flags |= OBD_CONNECT_CANCELSET;
 350        return count;
 351}
 352LUSTRE_RW_ATTR(early_lock_cancel);
 353
 354/* These are for namespaces in /sys/fs/lustre/ldlm/namespaces/ */
 355static struct attribute *ldlm_ns_attrs[] = {
 356        &lustre_attr_resource_count.attr,
 357        &lustre_attr_lock_count.attr,
 358        &lustre_attr_lock_unused_count.attr,
 359        &lustre_attr_lru_size.attr,
 360        &lustre_attr_lru_max_age.attr,
 361        &lustre_attr_early_lock_cancel.attr,
 362        NULL,
 363};
 364
 365static void ldlm_ns_release(struct kobject *kobj)
 366{
 367        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
 368                                                 ns_kobj);
 369        complete(&ns->ns_kobj_unregister);
 370}
 371
 372static struct kobj_type ldlm_ns_ktype = {
 373        .default_attrs  = ldlm_ns_attrs,
 374        .sysfs_ops      = &lustre_sysfs_ops,
 375        .release        = ldlm_ns_release,
 376};
 377
 378static void ldlm_namespace_debugfs_unregister(struct ldlm_namespace *ns)
 379{
 380        if (IS_ERR_OR_NULL(ns->ns_debugfs_entry))
 381                CERROR("dlm namespace %s has no procfs dir?\n",
 382                       ldlm_ns_name(ns));
 383        else
 384                ldebugfs_remove(&ns->ns_debugfs_entry);
 385
 386        if (ns->ns_stats)
 387                lprocfs_free_stats(&ns->ns_stats);
 388}
 389
 390static void ldlm_namespace_sysfs_unregister(struct ldlm_namespace *ns)
 391{
 392        kobject_put(&ns->ns_kobj);
 393        wait_for_completion(&ns->ns_kobj_unregister);
 394}
 395
 396static int ldlm_namespace_sysfs_register(struct ldlm_namespace *ns)
 397{
 398        int err;
 399
 400        ns->ns_kobj.kset = ldlm_ns_kset;
 401        init_completion(&ns->ns_kobj_unregister);
 402        err = kobject_init_and_add(&ns->ns_kobj, &ldlm_ns_ktype, NULL,
 403                                   "%s", ldlm_ns_name(ns));
 404
 405        ns->ns_stats = lprocfs_alloc_stats(LDLM_NSS_LAST, 0);
 406        if (!ns->ns_stats) {
 407                kobject_put(&ns->ns_kobj);
 408                return -ENOMEM;
 409        }
 410
 411        lprocfs_counter_init(ns->ns_stats, LDLM_NSS_LOCKS,
 412                             LPROCFS_CNTR_AVGMINMAX, "locks", "locks");
 413
 414        return err;
 415}
 416
 417static int ldlm_namespace_debugfs_register(struct ldlm_namespace *ns)
 418{
 419        struct dentry *ns_entry;
 420
 421        if (!IS_ERR_OR_NULL(ns->ns_debugfs_entry)) {
 422                ns_entry = ns->ns_debugfs_entry;
 423        } else {
 424                ns_entry = debugfs_create_dir(ldlm_ns_name(ns),
 425                                              ldlm_ns_debugfs_dir);
 426                if (!ns_entry)
 427                        return -ENOMEM;
 428                ns->ns_debugfs_entry = ns_entry;
 429        }
 430
 431        return 0;
 432}
 433
 434#undef MAX_STRING_SIZE
 435
 436static struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res)
 437{
 438        LASSERT(res);
 439        LASSERT(res != LP_POISON);
 440        atomic_inc(&res->lr_refcount);
 441        CDEBUG(D_INFO, "getref res: %p count: %d\n", res,
 442               atomic_read(&res->lr_refcount));
 443        return res;
 444}
 445
 446static unsigned ldlm_res_hop_hash(struct cfs_hash *hs,
 447                                  const void *key, unsigned mask)
 448{
 449        const struct ldlm_res_id     *id  = key;
 450        unsigned                val = 0;
 451        unsigned                i;
 452
 453        for (i = 0; i < RES_NAME_SIZE; i++)
 454                val += id->name[i];
 455        return val & mask;
 456}
 457
 458static unsigned ldlm_res_hop_fid_hash(struct cfs_hash *hs,
 459                                      const void *key, unsigned mask)
 460{
 461        const struct ldlm_res_id *id = key;
 462        struct lu_fid       fid;
 463        __u32          hash;
 464        __u32          val;
 465
 466        fid.f_seq = id->name[LUSTRE_RES_ID_SEQ_OFF];
 467        fid.f_oid = (__u32)id->name[LUSTRE_RES_ID_VER_OID_OFF];
 468        fid.f_ver = (__u32)(id->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32);
 469
 470        hash = fid_flatten32(&fid);
 471        hash += (hash >> 4) + (hash << 12); /* mixing oid and seq */
 472        if (id->name[LUSTRE_RES_ID_HSH_OFF] != 0) {
 473                val = id->name[LUSTRE_RES_ID_HSH_OFF];
 474                hash += (val >> 5) + (val << 11);
 475        } else {
 476                val = fid_oid(&fid);
 477        }
 478        hash = hash_long(hash, hs->hs_bkt_bits);
 479        /* give me another random factor */
 480        hash -= hash_long((unsigned long)hs, val % 11 + 3);
 481
 482        hash <<= hs->hs_cur_bits - hs->hs_bkt_bits;
 483        hash |= ldlm_res_hop_hash(hs, key, CFS_HASH_NBKT(hs) - 1);
 484
 485        return hash & mask;
 486}
 487
 488static void *ldlm_res_hop_key(struct hlist_node *hnode)
 489{
 490        struct ldlm_resource   *res;
 491
 492        res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
 493        return &res->lr_name;
 494}
 495
 496static int ldlm_res_hop_keycmp(const void *key, struct hlist_node *hnode)
 497{
 498        struct ldlm_resource   *res;
 499
 500        res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
 501        return ldlm_res_eq((const struct ldlm_res_id *)key,
 502                           (const struct ldlm_res_id *)&res->lr_name);
 503}
 504
 505static void *ldlm_res_hop_object(struct hlist_node *hnode)
 506{
 507        return hlist_entry(hnode, struct ldlm_resource, lr_hash);
 508}
 509
 510static void ldlm_res_hop_get_locked(struct cfs_hash *hs,
 511                                    struct hlist_node *hnode)
 512{
 513        struct ldlm_resource *res;
 514
 515        res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
 516        ldlm_resource_getref(res);
 517}
 518
 519static void ldlm_res_hop_put_locked(struct cfs_hash *hs,
 520                                    struct hlist_node *hnode)
 521{
 522        struct ldlm_resource *res;
 523
 524        res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
 525        /* cfs_hash_for_each_nolock is the only chance we call it */
 526        ldlm_resource_putref_locked(res);
 527}
 528
 529static void ldlm_res_hop_put(struct cfs_hash *hs, struct hlist_node *hnode)
 530{
 531        struct ldlm_resource *res;
 532
 533        res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
 534        ldlm_resource_putref(res);
 535}
 536
 537static struct cfs_hash_ops ldlm_ns_hash_ops = {
 538        .hs_hash        = ldlm_res_hop_hash,
 539        .hs_key         = ldlm_res_hop_key,
 540        .hs_keycmp      = ldlm_res_hop_keycmp,
 541        .hs_keycpy      = NULL,
 542        .hs_object      = ldlm_res_hop_object,
 543        .hs_get         = ldlm_res_hop_get_locked,
 544        .hs_put_locked  = ldlm_res_hop_put_locked,
 545        .hs_put         = ldlm_res_hop_put
 546};
 547
 548static struct cfs_hash_ops ldlm_ns_fid_hash_ops = {
 549        .hs_hash        = ldlm_res_hop_fid_hash,
 550        .hs_key         = ldlm_res_hop_key,
 551        .hs_keycmp      = ldlm_res_hop_keycmp,
 552        .hs_keycpy      = NULL,
 553        .hs_object      = ldlm_res_hop_object,
 554        .hs_get         = ldlm_res_hop_get_locked,
 555        .hs_put_locked  = ldlm_res_hop_put_locked,
 556        .hs_put         = ldlm_res_hop_put
 557};
 558
 559struct ldlm_ns_hash_def {
 560        enum ldlm_ns_type nsd_type;
 561        /** hash bucket bits */
 562        unsigned        nsd_bkt_bits;
 563        /** hash bits */
 564        unsigned        nsd_all_bits;
 565        /** hash operations */
 566        struct cfs_hash_ops *nsd_hops;
 567};
 568
 569static struct ldlm_ns_hash_def ldlm_ns_hash_defs[] = {
 570        {
 571                .nsd_type       = LDLM_NS_TYPE_MDC,
 572                .nsd_bkt_bits   = 11,
 573                .nsd_all_bits   = 16,
 574                .nsd_hops       = &ldlm_ns_fid_hash_ops,
 575        },
 576        {
 577                .nsd_type       = LDLM_NS_TYPE_MDT,
 578                .nsd_bkt_bits   = 14,
 579                .nsd_all_bits   = 21,
 580                .nsd_hops       = &ldlm_ns_fid_hash_ops,
 581        },
 582        {
 583                .nsd_type       = LDLM_NS_TYPE_OSC,
 584                .nsd_bkt_bits   = 8,
 585                .nsd_all_bits   = 12,
 586                .nsd_hops       = &ldlm_ns_hash_ops,
 587        },
 588        {
 589                .nsd_type       = LDLM_NS_TYPE_OST,
 590                .nsd_bkt_bits   = 11,
 591                .nsd_all_bits   = 17,
 592                .nsd_hops       = &ldlm_ns_hash_ops,
 593        },
 594        {
 595                .nsd_type       = LDLM_NS_TYPE_MGC,
 596                .nsd_bkt_bits   = 4,
 597                .nsd_all_bits   = 4,
 598                .nsd_hops       = &ldlm_ns_hash_ops,
 599        },
 600        {
 601                .nsd_type       = LDLM_NS_TYPE_MGT,
 602                .nsd_bkt_bits   = 4,
 603                .nsd_all_bits   = 4,
 604                .nsd_hops       = &ldlm_ns_hash_ops,
 605        },
 606        {
 607                .nsd_type       = LDLM_NS_TYPE_UNKNOWN,
 608        },
 609};
 610
 611/** Register \a ns in the list of namespaces */
 612static void ldlm_namespace_register(struct ldlm_namespace *ns,
 613                                    ldlm_side_t client)
 614{
 615        mutex_lock(ldlm_namespace_lock(client));
 616        LASSERT(list_empty(&ns->ns_list_chain));
 617        list_add(&ns->ns_list_chain, &ldlm_cli_inactive_namespace_list);
 618        ldlm_namespace_nr_inc(client);
 619        mutex_unlock(ldlm_namespace_lock(client));
 620}
 621
 622/**
 623 * Create and initialize new empty namespace.
 624 */
 625struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
 626                                          ldlm_side_t client,
 627                                          enum ldlm_appetite apt,
 628                                          enum ldlm_ns_type ns_type)
 629{
 630        struct ldlm_namespace *ns = NULL;
 631        struct ldlm_ns_bucket *nsb;
 632        struct ldlm_ns_hash_def    *nsd;
 633        struct cfs_hash_bd        bd;
 634        int                 idx;
 635        int                 rc;
 636
 637        LASSERT(obd);
 638
 639        rc = ldlm_get_ref();
 640        if (rc) {
 641                CERROR("ldlm_get_ref failed: %d\n", rc);
 642                return NULL;
 643        }
 644
 645        for (idx = 0;; idx++) {
 646                nsd = &ldlm_ns_hash_defs[idx];
 647                if (nsd->nsd_type == LDLM_NS_TYPE_UNKNOWN) {
 648                        CERROR("Unknown type %d for ns %s\n", ns_type, name);
 649                        goto out_ref;
 650                }
 651
 652                if (nsd->nsd_type == ns_type)
 653                        break;
 654        }
 655
 656        ns = kzalloc(sizeof(*ns), GFP_NOFS);
 657        if (!ns)
 658                goto out_ref;
 659
 660        ns->ns_rs_hash = cfs_hash_create(name,
 661                                         nsd->nsd_all_bits, nsd->nsd_all_bits,
 662                                         nsd->nsd_bkt_bits, sizeof(*nsb),
 663                                         CFS_HASH_MIN_THETA,
 664                                         CFS_HASH_MAX_THETA,
 665                                         nsd->nsd_hops,
 666                                         CFS_HASH_DEPTH |
 667                                         CFS_HASH_BIGNAME |
 668                                         CFS_HASH_SPIN_BKTLOCK |
 669                                         CFS_HASH_NO_ITEMREF);
 670        if (!ns->ns_rs_hash)
 671                goto out_ns;
 672
 673        cfs_hash_for_each_bucket(ns->ns_rs_hash, &bd, idx) {
 674                nsb = cfs_hash_bd_extra_get(ns->ns_rs_hash, &bd);
 675                at_init(&nsb->nsb_at_estimate, ldlm_enqueue_min, 0);
 676                nsb->nsb_namespace = ns;
 677        }
 678
 679        ns->ns_obd      = obd;
 680        ns->ns_appetite = apt;
 681        ns->ns_client   = client;
 682
 683        INIT_LIST_HEAD(&ns->ns_list_chain);
 684        INIT_LIST_HEAD(&ns->ns_unused_list);
 685        spin_lock_init(&ns->ns_lock);
 686        atomic_set(&ns->ns_bref, 0);
 687        init_waitqueue_head(&ns->ns_waitq);
 688
 689        ns->ns_max_parallel_ast   = LDLM_DEFAULT_PARALLEL_AST_LIMIT;
 690        ns->ns_nr_unused          = 0;
 691        ns->ns_max_unused        = LDLM_DEFAULT_LRU_SIZE;
 692        ns->ns_max_age      = LDLM_DEFAULT_MAX_ALIVE;
 693        ns->ns_orig_connect_flags = 0;
 694        ns->ns_connect_flags      = 0;
 695        ns->ns_stopping    = 0;
 696
 697        rc = ldlm_namespace_sysfs_register(ns);
 698        if (rc != 0) {
 699                CERROR("Can't initialize ns sysfs, rc %d\n", rc);
 700                goto out_hash;
 701        }
 702
 703        rc = ldlm_namespace_debugfs_register(ns);
 704        if (rc != 0) {
 705                CERROR("Can't initialize ns proc, rc %d\n", rc);
 706                goto out_sysfs;
 707        }
 708
 709        idx = ldlm_namespace_nr_read(client);
 710        rc = ldlm_pool_init(&ns->ns_pool, ns, idx, client);
 711        if (rc) {
 712                CERROR("Can't initialize lock pool, rc %d\n", rc);
 713                goto out_proc;
 714        }
 715
 716        ldlm_namespace_register(ns, client);
 717        return ns;
 718out_proc:
 719        ldlm_namespace_debugfs_unregister(ns);
 720out_sysfs:
 721        ldlm_namespace_sysfs_unregister(ns);
 722        ldlm_namespace_cleanup(ns, 0);
 723out_hash:
 724        cfs_hash_putref(ns->ns_rs_hash);
 725out_ns:
 726        kfree(ns);
 727out_ref:
 728        ldlm_put_ref();
 729        return NULL;
 730}
 731EXPORT_SYMBOL(ldlm_namespace_new);
 732
 733extern struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
 734
 735/**
 736 * Cancel and destroy all locks on a resource.
 737 *
 738 * If flags contains FL_LOCAL_ONLY, don't try to tell the server, just
 739 * clean up.  This is currently only used for recovery, and we make
 740 * certain assumptions as a result--notably, that we shouldn't cancel
 741 * locks with refs.
 742 */
 743static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
 744                             __u64 flags)
 745{
 746        struct list_head *tmp;
 747        int rc = 0;
 748        bool local_only = !!(flags & LDLM_FL_LOCAL_ONLY);
 749
 750        do {
 751                struct ldlm_lock *lock = NULL;
 752                struct lustre_handle lockh;
 753
 754                /* First, we look for non-cleaned-yet lock
 755                 * all cleaned locks are marked by CLEANED flag.
 756                 */
 757                lock_res(res);
 758                list_for_each(tmp, q) {
 759                        lock = list_entry(tmp, struct ldlm_lock,
 760                                              l_res_link);
 761                        if (lock->l_flags & LDLM_FL_CLEANED) {
 762                                lock = NULL;
 763                                continue;
 764                        }
 765                        LDLM_LOCK_GET(lock);
 766                        lock->l_flags |= LDLM_FL_CLEANED;
 767                        break;
 768                }
 769
 770                if (!lock) {
 771                        unlock_res(res);
 772                        break;
 773                }
 774
 775                /* Set CBPENDING so nothing in the cancellation path
 776                 * can match this lock.
 777                 */
 778                lock->l_flags |= LDLM_FL_CBPENDING;
 779                lock->l_flags |= LDLM_FL_FAILED;
 780                lock->l_flags |= flags;
 781
 782                /* ... without sending a CANCEL message for local_only. */
 783                if (local_only)
 784                        lock->l_flags |= LDLM_FL_LOCAL_ONLY;
 785
 786                if (local_only && (lock->l_readers || lock->l_writers)) {
 787                        /* This is a little bit gross, but much better than the
 788                         * alternative: pretend that we got a blocking AST from
 789                         * the server, so that when the lock is decref'd, it
 790                         * will go away ...
 791                         */
 792                        unlock_res(res);
 793                        LDLM_DEBUG(lock, "setting FL_LOCAL_ONLY");
 794                        if (lock->l_completion_ast)
 795                                lock->l_completion_ast(lock, 0, NULL);
 796                        LDLM_LOCK_RELEASE(lock);
 797                        continue;
 798                }
 799
 800                unlock_res(res);
 801                ldlm_lock2handle(lock, &lockh);
 802                rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
 803                if (rc)
 804                        CERROR("ldlm_cli_cancel: %d\n", rc);
 805                LDLM_LOCK_RELEASE(lock);
 806        } while (1);
 807}
 808
 809static int ldlm_resource_clean(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 810                               struct hlist_node *hnode, void *arg)
 811{
 812        struct ldlm_resource *res = cfs_hash_object(hs, hnode);
 813        __u64 flags = *(__u64 *)arg;
 814
 815        cleanup_resource(res, &res->lr_granted, flags);
 816        cleanup_resource(res, &res->lr_waiting, flags);
 817
 818        return 0;
 819}
 820
 821static int ldlm_resource_complain(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 822                                  struct hlist_node *hnode, void *arg)
 823{
 824        struct ldlm_resource  *res = cfs_hash_object(hs, hnode);
 825
 826        lock_res(res);
 827        CERROR("%s: namespace resource "DLDLMRES
 828               " (%p) refcount nonzero (%d) after lock cleanup; forcing cleanup.\n",
 829               ldlm_ns_name(ldlm_res_to_ns(res)), PLDLMRES(res), res,
 830               atomic_read(&res->lr_refcount) - 1);
 831
 832        ldlm_resource_dump(D_ERROR, res);
 833        unlock_res(res);
 834        return 0;
 835}
 836
 837/**
 838 * Cancel and destroy all locks in the namespace.
 839 *
 840 * Typically used during evictions when server notified client that it was
 841 * evicted and all of its state needs to be destroyed.
 842 * Also used during shutdown.
 843 */
 844int ldlm_namespace_cleanup(struct ldlm_namespace *ns, __u64 flags)
 845{
 846        if (!ns) {
 847                CDEBUG(D_INFO, "NULL ns, skipping cleanup\n");
 848                return ELDLM_OK;
 849        }
 850
 851        cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_resource_clean, &flags);
 852        cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_resource_complain, NULL);
 853        return ELDLM_OK;
 854}
 855EXPORT_SYMBOL(ldlm_namespace_cleanup);
 856
 857/**
 858 * Attempts to free namespace.
 859 *
 860 * Only used when namespace goes away, like during an unmount.
 861 */
 862static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force)
 863{
 864        /* At shutdown time, don't call the cancellation callback */
 865        ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0);
 866
 867        if (atomic_read(&ns->ns_bref) > 0) {
 868                struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
 869                int rc;
 870
 871                CDEBUG(D_DLMTRACE,
 872                       "dlm namespace %s free waiting on refcount %d\n",
 873                       ldlm_ns_name(ns), atomic_read(&ns->ns_bref));
 874force_wait:
 875                if (force)
 876                        lwi = LWI_TIMEOUT(obd_timeout * HZ / 4, NULL, NULL);
 877
 878                rc = l_wait_event(ns->ns_waitq,
 879                                  atomic_read(&ns->ns_bref) == 0, &lwi);
 880
 881                /* Forced cleanups should be able to reclaim all references,
 882                 * so it's safe to wait forever... we can't leak locks...
 883                 */
 884                if (force && rc == -ETIMEDOUT) {
 885                        LCONSOLE_ERROR("Forced cleanup waiting for %s namespace with %d resources in use, (rc=%d)\n",
 886                                       ldlm_ns_name(ns),
 887                                       atomic_read(&ns->ns_bref), rc);
 888                        goto force_wait;
 889                }
 890
 891                if (atomic_read(&ns->ns_bref)) {
 892                        LCONSOLE_ERROR("Cleanup waiting for %s namespace with %d resources in use, (rc=%d)\n",
 893                                       ldlm_ns_name(ns),
 894                                       atomic_read(&ns->ns_bref), rc);
 895                        return ELDLM_NAMESPACE_EXISTS;
 896                }
 897                CDEBUG(D_DLMTRACE, "dlm namespace %s free done waiting\n",
 898                       ldlm_ns_name(ns));
 899        }
 900
 901        return ELDLM_OK;
 902}
 903
 904/**
 905 * Performs various cleanups for passed \a ns to make it drop refc and be
 906 * ready for freeing. Waits for refc == 0.
 907 *
 908 * The following is done:
 909 * (0) Unregister \a ns from its list to make inaccessible for potential
 910 * users like pools thread and others;
 911 * (1) Clear all locks in \a ns.
 912 */
 913void ldlm_namespace_free_prior(struct ldlm_namespace *ns,
 914                               struct obd_import *imp,
 915                               int force)
 916{
 917        int rc;
 918
 919        if (!ns)
 920                return;
 921
 922        spin_lock(&ns->ns_lock);
 923        ns->ns_stopping = 1;
 924        spin_unlock(&ns->ns_lock);
 925
 926        /*
 927         * Can fail with -EINTR when force == 0 in which case try harder.
 928         */
 929        rc = __ldlm_namespace_free(ns, force);
 930        if (rc != ELDLM_OK) {
 931                if (imp) {
 932                        ptlrpc_disconnect_import(imp, 0);
 933                        ptlrpc_invalidate_import(imp);
 934                }
 935
 936                /*
 937                 * With all requests dropped and the import inactive
 938                 * we are guaranteed all reference will be dropped.
 939                 */
 940                rc = __ldlm_namespace_free(ns, 1);
 941                LASSERT(rc == 0);
 942        }
 943}
 944
 945/** Unregister \a ns from the list of namespaces. */
 946static void ldlm_namespace_unregister(struct ldlm_namespace *ns,
 947                                      ldlm_side_t client)
 948{
 949        mutex_lock(ldlm_namespace_lock(client));
 950        LASSERT(!list_empty(&ns->ns_list_chain));
 951        /* Some asserts and possibly other parts of the code are still
 952         * using list_empty(&ns->ns_list_chain). This is why it is
 953         * important to use list_del_init() here.
 954         */
 955        list_del_init(&ns->ns_list_chain);
 956        ldlm_namespace_nr_dec(client);
 957        mutex_unlock(ldlm_namespace_lock(client));
 958}
 959
 960/**
 961 * Performs freeing memory structures related to \a ns. This is only done
 962 * when ldlm_namespce_free_prior() successfully removed all resources
 963 * referencing \a ns and its refc == 0.
 964 */
 965void ldlm_namespace_free_post(struct ldlm_namespace *ns)
 966{
 967        if (!ns)
 968                return;
 969
 970        /* Make sure that nobody can find this ns in its list. */
 971        ldlm_namespace_unregister(ns, ns->ns_client);
 972        /* Fini pool _before_ parent proc dir is removed. This is important as
 973         * ldlm_pool_fini() removes own proc dir which is child to @dir.
 974         * Removing it after @dir may cause oops.
 975         */
 976        ldlm_pool_fini(&ns->ns_pool);
 977
 978        ldlm_namespace_debugfs_unregister(ns);
 979        ldlm_namespace_sysfs_unregister(ns);
 980        cfs_hash_putref(ns->ns_rs_hash);
 981        /* Namespace \a ns should be not on list at this time, otherwise
 982         * this will cause issues related to using freed \a ns in poold
 983         * thread.
 984         */
 985        LASSERT(list_empty(&ns->ns_list_chain));
 986        kfree(ns);
 987        ldlm_put_ref();
 988}
 989
 990void ldlm_namespace_get(struct ldlm_namespace *ns)
 991{
 992        atomic_inc(&ns->ns_bref);
 993}
 994EXPORT_SYMBOL(ldlm_namespace_get);
 995
 996/* This is only for callers that care about refcount */
 997static int ldlm_namespace_get_return(struct ldlm_namespace *ns)
 998{
 999        return atomic_inc_return(&ns->ns_bref);
1000}
1001
1002void ldlm_namespace_put(struct ldlm_namespace *ns)
1003{
1004        if (atomic_dec_and_lock(&ns->ns_bref, &ns->ns_lock)) {
1005                wake_up(&ns->ns_waitq);
1006                spin_unlock(&ns->ns_lock);
1007        }
1008}
1009EXPORT_SYMBOL(ldlm_namespace_put);
1010
1011/** Should be called with ldlm_namespace_lock(client) taken. */
1012void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns,
1013                                          ldlm_side_t client)
1014{
1015        LASSERT(!list_empty(&ns->ns_list_chain));
1016        LASSERT(mutex_is_locked(ldlm_namespace_lock(client)));
1017        list_move_tail(&ns->ns_list_chain, ldlm_namespace_list(client));
1018}
1019
1020/** Should be called with ldlm_namespace_lock(client) taken. */
1021void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *ns,
1022                                            ldlm_side_t client)
1023{
1024        LASSERT(!list_empty(&ns->ns_list_chain));
1025        LASSERT(mutex_is_locked(ldlm_namespace_lock(client)));
1026        list_move_tail(&ns->ns_list_chain, &ldlm_cli_inactive_namespace_list);
1027}
1028
1029/** Should be called with ldlm_namespace_lock(client) taken. */
1030struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t client)
1031{
1032        LASSERT(mutex_is_locked(ldlm_namespace_lock(client)));
1033        LASSERT(!list_empty(ldlm_namespace_list(client)));
1034        return container_of(ldlm_namespace_list(client)->next,
1035                struct ldlm_namespace, ns_list_chain);
1036}
1037
1038/** Create and initialize new resource. */
1039static struct ldlm_resource *ldlm_resource_new(void)
1040{
1041        struct ldlm_resource *res;
1042        int idx;
1043
1044        res = kmem_cache_zalloc(ldlm_resource_slab, GFP_NOFS);
1045        if (!res)
1046                return NULL;
1047
1048        INIT_LIST_HEAD(&res->lr_granted);
1049        INIT_LIST_HEAD(&res->lr_waiting);
1050
1051        /* Initialize interval trees for each lock mode. */
1052        for (idx = 0; idx < LCK_MODE_NUM; idx++) {
1053                res->lr_itree[idx].lit_size = 0;
1054                res->lr_itree[idx].lit_mode = 1 << idx;
1055                res->lr_itree[idx].lit_root = NULL;
1056        }
1057
1058        atomic_set(&res->lr_refcount, 1);
1059        spin_lock_init(&res->lr_lock);
1060        lu_ref_init(&res->lr_reference);
1061
1062        /* The creator of the resource must unlock the mutex after LVB
1063         * initialization.
1064         */
1065        mutex_init(&res->lr_lvb_mutex);
1066        mutex_lock(&res->lr_lvb_mutex);
1067
1068        return res;
1069}
1070
1071/**
1072 * Return a reference to resource with given name, creating it if necessary.
1073 * Args: namespace with ns_lock unlocked
1074 * Locks: takes and releases NS hash-lock and res->lr_lock
1075 * Returns: referenced, unlocked ldlm_resource or NULL
1076 */
1077struct ldlm_resource *
1078ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
1079                  const struct ldlm_res_id *name, enum ldlm_type type,
1080                  int create)
1081{
1082        struct hlist_node     *hnode;
1083        struct ldlm_resource *res;
1084        struct cfs_hash_bd       bd;
1085        __u64            version;
1086        int                   ns_refcount = 0;
1087
1088        LASSERT(!parent);
1089        LASSERT(ns->ns_rs_hash);
1090        LASSERT(name->name[0] != 0);
1091
1092        cfs_hash_bd_get_and_lock(ns->ns_rs_hash, (void *)name, &bd, 0);
1093        hnode = cfs_hash_bd_lookup_locked(ns->ns_rs_hash, &bd, (void *)name);
1094        if (hnode) {
1095                cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 0);
1096                res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
1097                /* Synchronize with regard to resource creation. */
1098                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
1099                        mutex_lock(&res->lr_lvb_mutex);
1100                        mutex_unlock(&res->lr_lvb_mutex);
1101                }
1102
1103                if (unlikely(res->lr_lvb_len < 0)) {
1104                        ldlm_resource_putref(res);
1105                        res = NULL;
1106                }
1107                return res;
1108        }
1109
1110        version = cfs_hash_bd_version_get(&bd);
1111        cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 0);
1112
1113        if (create == 0)
1114                return NULL;
1115
1116        LASSERTF(type >= LDLM_MIN_TYPE && type < LDLM_MAX_TYPE,
1117                 "type: %d\n", type);
1118        res = ldlm_resource_new();
1119        if (!res)
1120                return NULL;
1121
1122        res->lr_ns_bucket  = cfs_hash_bd_extra_get(ns->ns_rs_hash, &bd);
1123        res->lr_name       = *name;
1124        res->lr_type       = type;
1125
1126        cfs_hash_bd_lock(ns->ns_rs_hash, &bd, 1);
1127        hnode = (version == cfs_hash_bd_version_get(&bd)) ?  NULL :
1128                cfs_hash_bd_lookup_locked(ns->ns_rs_hash, &bd, (void *)name);
1129
1130        if (hnode) {
1131                /* Someone won the race and already added the resource. */
1132                cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
1133                /* Clean lu_ref for failed resource. */
1134                lu_ref_fini(&res->lr_reference);
1135                /* We have taken lr_lvb_mutex. Drop it. */
1136                mutex_unlock(&res->lr_lvb_mutex);
1137                kmem_cache_free(ldlm_resource_slab, res);
1138
1139                res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
1140                /* Synchronize with regard to resource creation. */
1141                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
1142                        mutex_lock(&res->lr_lvb_mutex);
1143                        mutex_unlock(&res->lr_lvb_mutex);
1144                }
1145
1146                if (unlikely(res->lr_lvb_len < 0)) {
1147                        ldlm_resource_putref(res);
1148                        res = NULL;
1149                }
1150                return res;
1151        }
1152        /* We won! Let's add the resource. */
1153        cfs_hash_bd_add_locked(ns->ns_rs_hash, &bd, &res->lr_hash);
1154        if (cfs_hash_bd_count_get(&bd) == 1)
1155                ns_refcount = ldlm_namespace_get_return(ns);
1156
1157        cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
1158        if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
1159                int rc;
1160
1161                OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2);
1162                rc = ns->ns_lvbo->lvbo_init(res);
1163                if (rc < 0) {
1164                        CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n",
1165                               ns->ns_obd->obd_name, name->name[0],
1166                               name->name[1], rc);
1167                        res->lr_lvb_len = rc;
1168                        mutex_unlock(&res->lr_lvb_mutex);
1169                        ldlm_resource_putref(res);
1170                        return NULL;
1171                }
1172        }
1173
1174        /* We create resource with locked lr_lvb_mutex. */
1175        mutex_unlock(&res->lr_lvb_mutex);
1176
1177        /* Let's see if we happened to be the very first resource in this
1178         * namespace. If so, and this is a client namespace, we need to move
1179         * the namespace into the active namespaces list to be patrolled by
1180         * the ldlm_poold.
1181         */
1182        if (ns_refcount == 1) {
1183                mutex_lock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
1184                ldlm_namespace_move_to_active_locked(ns, LDLM_NAMESPACE_CLIENT);
1185                mutex_unlock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
1186        }
1187
1188        return res;
1189}
1190EXPORT_SYMBOL(ldlm_resource_get);
1191
1192static void __ldlm_resource_putref_final(struct cfs_hash_bd *bd,
1193                                         struct ldlm_resource *res)
1194{
1195        struct ldlm_ns_bucket *nsb = res->lr_ns_bucket;
1196
1197        if (!list_empty(&res->lr_granted)) {
1198                ldlm_resource_dump(D_ERROR, res);
1199                LBUG();
1200        }
1201
1202        if (!list_empty(&res->lr_waiting)) {
1203                ldlm_resource_dump(D_ERROR, res);
1204                LBUG();
1205        }
1206
1207        cfs_hash_bd_del_locked(nsb->nsb_namespace->ns_rs_hash,
1208                               bd, &res->lr_hash);
1209        lu_ref_fini(&res->lr_reference);
1210        if (cfs_hash_bd_count_get(bd) == 0)
1211                ldlm_namespace_put(nsb->nsb_namespace);
1212}
1213
1214/* Returns 1 if the resource was freed, 0 if it remains. */
1215int ldlm_resource_putref(struct ldlm_resource *res)
1216{
1217        struct ldlm_namespace *ns = ldlm_res_to_ns(res);
1218        struct cfs_hash_bd   bd;
1219
1220        LASSERT_ATOMIC_GT_LT(&res->lr_refcount, 0, LI_POISON);
1221        CDEBUG(D_INFO, "putref res: %p count: %d\n",
1222               res, atomic_read(&res->lr_refcount) - 1);
1223
1224        cfs_hash_bd_get(ns->ns_rs_hash, &res->lr_name, &bd);
1225        if (cfs_hash_bd_dec_and_lock(ns->ns_rs_hash, &bd, &res->lr_refcount)) {
1226                __ldlm_resource_putref_final(&bd, res);
1227                cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
1228                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
1229                        ns->ns_lvbo->lvbo_free(res);
1230                kmem_cache_free(ldlm_resource_slab, res);
1231                return 1;
1232        }
1233        return 0;
1234}
1235EXPORT_SYMBOL(ldlm_resource_putref);
1236
1237/* Returns 1 if the resource was freed, 0 if it remains. */
1238int ldlm_resource_putref_locked(struct ldlm_resource *res)
1239{
1240        struct ldlm_namespace *ns = ldlm_res_to_ns(res);
1241
1242        LASSERT_ATOMIC_GT_LT(&res->lr_refcount, 0, LI_POISON);
1243        CDEBUG(D_INFO, "putref res: %p count: %d\n",
1244               res, atomic_read(&res->lr_refcount) - 1);
1245
1246        if (atomic_dec_and_test(&res->lr_refcount)) {
1247                struct cfs_hash_bd bd;
1248
1249                cfs_hash_bd_get(ldlm_res_to_ns(res)->ns_rs_hash,
1250                                &res->lr_name, &bd);
1251                __ldlm_resource_putref_final(&bd, res);
1252                cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
1253                /* NB: ns_rs_hash is created with CFS_HASH_NO_ITEMREF,
1254                 * so we should never be here while calling cfs_hash_del,
1255                 * cfs_hash_for_each_nolock is the only case we can get
1256                 * here, which is safe to release cfs_hash_bd_lock.
1257                 */
1258                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
1259                        ns->ns_lvbo->lvbo_free(res);
1260                kmem_cache_free(ldlm_resource_slab, res);
1261
1262                cfs_hash_bd_lock(ns->ns_rs_hash, &bd, 1);
1263                return 1;
1264        }
1265        return 0;
1266}
1267
1268/**
1269 * Add a lock into a given resource into specified lock list.
1270 */
1271void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
1272                            struct ldlm_lock *lock)
1273{
1274        check_res_locked(res);
1275
1276        LDLM_DEBUG(lock, "About to add this lock:\n");
1277
1278        if (lock->l_flags & LDLM_FL_DESTROYED) {
1279                CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
1280                return;
1281        }
1282
1283        LASSERT(list_empty(&lock->l_res_link));
1284
1285        list_add_tail(&lock->l_res_link, head);
1286}
1287
1288void ldlm_resource_unlink_lock(struct ldlm_lock *lock)
1289{
1290        int type = lock->l_resource->lr_type;
1291
1292        check_res_locked(lock->l_resource);
1293        if (type == LDLM_IBITS || type == LDLM_PLAIN)
1294                ldlm_unlink_lock_skiplist(lock);
1295        else if (type == LDLM_EXTENT)
1296                ldlm_extent_unlink_lock(lock);
1297        list_del_init(&lock->l_res_link);
1298}
1299EXPORT_SYMBOL(ldlm_resource_unlink_lock);
1300
1301void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc)
1302{
1303        desc->lr_type = res->lr_type;
1304        desc->lr_name = res->lr_name;
1305}
1306
1307/**
1308 * Print information about all locks in all namespaces on this node to debug
1309 * log.
1310 */
1311void ldlm_dump_all_namespaces(ldlm_side_t client, int level)
1312{
1313        struct list_head *tmp;
1314
1315        if (!((libcfs_debug | D_ERROR) & level))
1316                return;
1317
1318        mutex_lock(ldlm_namespace_lock(client));
1319
1320        list_for_each(tmp, ldlm_namespace_list(client)) {
1321                struct ldlm_namespace *ns;
1322
1323                ns = list_entry(tmp, struct ldlm_namespace, ns_list_chain);
1324                ldlm_namespace_dump(level, ns);
1325        }
1326
1327        mutex_unlock(ldlm_namespace_lock(client));
1328}
1329EXPORT_SYMBOL(ldlm_dump_all_namespaces);
1330
1331static int ldlm_res_hash_dump(struct cfs_hash *hs, struct cfs_hash_bd *bd,
1332                              struct hlist_node *hnode, void *arg)
1333{
1334        struct ldlm_resource *res = cfs_hash_object(hs, hnode);
1335        int    level = (int)(unsigned long)arg;
1336
1337        lock_res(res);
1338        ldlm_resource_dump(level, res);
1339        unlock_res(res);
1340
1341        return 0;
1342}
1343
1344/**
1345 * Print information about all locks in this namespace on this node to debug
1346 * log.
1347 */
1348void ldlm_namespace_dump(int level, struct ldlm_namespace *ns)
1349{
1350        if (!((libcfs_debug | D_ERROR) & level))
1351                return;
1352
1353        CDEBUG(level, "--- Namespace: %s (rc: %d, side: client)\n",
1354               ldlm_ns_name(ns), atomic_read(&ns->ns_bref));
1355
1356        if (time_before(cfs_time_current(), ns->ns_next_dump))
1357                return;
1358
1359        cfs_hash_for_each_nolock(ns->ns_rs_hash,
1360                                 ldlm_res_hash_dump,
1361                                 (void *)(unsigned long)level);
1362        spin_lock(&ns->ns_lock);
1363        ns->ns_next_dump = cfs_time_shift(10);
1364        spin_unlock(&ns->ns_lock);
1365}
1366EXPORT_SYMBOL(ldlm_namespace_dump);
1367
1368/**
1369 * Print information about all locks in this resource to debug log.
1370 */
1371void ldlm_resource_dump(int level, struct ldlm_resource *res)
1372{
1373        struct ldlm_lock *lock;
1374        unsigned int granted = 0;
1375
1376        CLASSERT(RES_NAME_SIZE == 4);
1377
1378        if (!((libcfs_debug | D_ERROR) & level))
1379                return;
1380
1381        CDEBUG(level, "--- Resource: "DLDLMRES" (%p) refcount = %d\n",
1382               PLDLMRES(res), res, atomic_read(&res->lr_refcount));
1383
1384        if (!list_empty(&res->lr_granted)) {
1385                CDEBUG(level, "Granted locks (in reverse order):\n");
1386                list_for_each_entry_reverse(lock, &res->lr_granted,
1387                                                l_res_link) {
1388                        LDLM_DEBUG_LIMIT(level, lock, "###");
1389                        if (!(level & D_CANTMASK) &&
1390                            ++granted > ldlm_dump_granted_max) {
1391                                CDEBUG(level, "only dump %d granted locks to avoid DDOS.\n",
1392                                       granted);
1393                                break;
1394                        }
1395                }
1396        }
1397        if (!list_empty(&res->lr_waiting)) {
1398                CDEBUG(level, "Waiting locks:\n");
1399                list_for_each_entry(lock, &res->lr_waiting, l_res_link)
1400                        LDLM_DEBUG_LIMIT(level, lock, "###");
1401        }
1402}
1403