Whamcloud - gitweb
LU-11518 ldlm: control lru_size for extent lock
[fs/lustre-release.git] / lustre / ldlm / ldlm_resource.c
index 6691acd..e262e7f 100644 (file)
@@ -207,7 +207,7 @@ static const struct file_operations ldlm_granted_fops = {
 
 #endif /* HAVE_SERVER_SUPPORT */
 
-static struct lprocfs_vars ldlm_debugfs_list[] = {
+static struct ldebugfs_vars ldlm_debugfs_list[] = {
        { .name =       "dump_namespaces",
          .fops =       &ldlm_dump_ns_fops,
          .proc_mode =  0222 },
@@ -316,18 +316,8 @@ static ssize_t lru_size_store(struct kobject *kobj, struct attribute *attr,
                CDEBUG(D_DLMTRACE,
                       "dropping all unused locks from namespace %s\n",
                       ldlm_ns_name(ns));
-               if (ns_connect_lru_resize(ns)) {
-                       /* Try to cancel all @ns_nr_unused locks. */
-                       ldlm_cancel_lru(ns, ns->ns_nr_unused, 0,
-                                       LDLM_LRU_FLAG_PASSED |
-                                       LDLM_LRU_FLAG_CLEANUP);
-               } else {
-                       tmp = ns->ns_max_unused;
-                       ns->ns_max_unused = 0;
-                       ldlm_cancel_lru(ns, 0, 0, LDLM_LRU_FLAG_PASSED |
-                                       LDLM_LRU_FLAG_CLEANUP);
-                       ns->ns_max_unused = tmp;
-               }
+               /* Try to cancel all @ns_nr_unused locks. */
+               ldlm_cancel_lru(ns, INT_MAX, 0, LDLM_LRU_FLAG_CLEANUP);
                return count;
        }
 
@@ -350,7 +340,6 @@ static ssize_t lru_size_store(struct kobject *kobj, struct attribute *attr,
                       "changing namespace %s unused locks from %u to %u\n",
                       ldlm_ns_name(ns), ns->ns_nr_unused,
                       (unsigned int)tmp);
-               ldlm_cancel_lru(ns, tmp, LCF_ASYNC, LDLM_LRU_FLAG_PASSED);
 
                if (!lru_resize) {
                        CDEBUG(D_DLMTRACE,
@@ -358,13 +347,12 @@ static ssize_t lru_size_store(struct kobject *kobj, struct attribute *attr,
                               ldlm_ns_name(ns));
                        ns->ns_connect_flags &= ~OBD_CONNECT_LRU_RESIZE;
                }
+               ldlm_cancel_lru(ns, tmp, LCF_ASYNC, 0);
        } else {
                CDEBUG(D_DLMTRACE,
                       "changing namespace %s max_unused from %u to %u\n",
                       ldlm_ns_name(ns), ns->ns_max_unused,
                       (unsigned int)tmp);
-               ns->ns_max_unused = (unsigned int)tmp;
-               ldlm_cancel_lru(ns, 0, LCF_ASYNC, LDLM_LRU_FLAG_PASSED);
 
                /* Make sure that LRU resize was originally supported before
                 * turning it on here.
@@ -376,12 +364,40 @@ static ssize_t lru_size_store(struct kobject *kobj, struct attribute *attr,
                               ldlm_ns_name(ns));
                        ns->ns_connect_flags |= OBD_CONNECT_LRU_RESIZE;
                }
+               ns->ns_max_unused = (unsigned int)tmp;
+               ldlm_cancel_lru(ns, 0, LCF_ASYNC, 0);
        }
 
        return count;
 }
 LUSTRE_RW_ATTR(lru_size);
 
+static ssize_t lru_cancel_batch_show(struct kobject *kobj,
+                                struct attribute *attr, char *buf)
+{
+       struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+                                                ns_kobj);
+
+       return snprintf(buf, sizeof(buf) - 1, "%u\n", ns->ns_cancel_batch);
+}
+
+static ssize_t lru_cancel_batch_store(struct kobject *kobj,
+                                 struct attribute *attr,
+                                 const char *buffer, size_t count)
+{
+       struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+                                                ns_kobj);
+       unsigned long tmp;
+
+       if (kstrtoul(buffer, 10, &tmp))
+               return -EINVAL;
+
+       ns->ns_cancel_batch = (unsigned int)tmp;
+
+       return count;
+}
+LUSTRE_RW_ATTR(lru_cancel_batch);
+
 static ssize_t lru_max_age_show(struct kobject *kobj, struct attribute *attr,
                                char *buf)
 {
@@ -458,7 +474,8 @@ static ssize_t dirty_age_limit_show(struct kobject *kobj,
        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
                                                 ns_kobj);
 
-       return sprintf(buf, "%llu\n", ns->ns_dirty_age_limit);
+       return snprintf(buf, PAGE_SIZE, "%llu\n",
+                       ktime_divns(ns->ns_dirty_age_limit, NSEC_PER_SEC));
 }
 
 static ssize_t dirty_age_limit_store(struct kobject *kobj,
@@ -472,7 +489,7 @@ static ssize_t dirty_age_limit_store(struct kobject *kobj,
        if (kstrtoull(buffer, 10, &tmp))
                return -EINVAL;
 
-       ns->ns_dirty_age_limit = tmp;
+       ns->ns_dirty_age_limit = ktime_set(tmp, 0);
 
        return count;
 }
@@ -485,7 +502,7 @@ static ssize_t ctime_age_limit_show(struct kobject *kobj,
        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
                                                 ns_kobj);
 
-       return sprintf(buf, "%llu\n", ns->ns_ctime_age_limit);
+       return snprintf(buf, PAGE_SIZE, "%u\n", ns->ns_ctime_age_limit);
 }
 
 static ssize_t ctime_age_limit_store(struct kobject *kobj,
@@ -494,9 +511,9 @@ static ssize_t ctime_age_limit_store(struct kobject *kobj,
 {
        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
                                                 ns_kobj);
-       unsigned long long tmp;
+       unsigned long tmp;
 
-       if (kstrtoull(buffer, 10, &tmp))
+       if (kstrtoul(buffer, 10, &tmp))
                return -EINVAL;
 
        ns->ns_ctime_age_limit = tmp;
@@ -549,7 +566,7 @@ static ssize_t contention_seconds_show(struct kobject *kobj,
        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
                                                 ns_kobj);
 
-       return sprintf(buf, "%llu\n", ns->ns_contention_time);
+       return scnprintf(buf, PAGE_SIZE, "%d\n", ns->ns_contention_time);
 }
 
 static ssize_t contention_seconds_store(struct kobject *kobj,
@@ -558,9 +575,9 @@ static ssize_t contention_seconds_store(struct kobject *kobj,
 {
        struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
                                                 ns_kobj);
-       unsigned long long tmp;
+       unsigned int tmp;
 
-       if (kstrtoull(buffer, 10, &tmp))
+       if (kstrtouint(buffer, 10, &tmp))
                return -EINVAL;
 
        ns->ns_contention_time = tmp;
@@ -633,6 +650,7 @@ static struct attribute *ldlm_ns_attrs[] = {
        &lustre_attr_lock_count.attr,
        &lustre_attr_lock_unused_count.attr,
        &lustre_attr_lru_size.attr,
+       &lustre_attr_lru_cancel_batch.attr,
        &lustre_attr_lru_max_age.attr,
        &lustre_attr_early_lock_cancel.attr,
        &lustre_attr_dirty_age_limit.attr,
@@ -880,8 +898,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
        ns->ns_bucket_bits = ldlm_ns_hash_defs[ns_type].nsd_all_bits -
                             ldlm_ns_hash_defs[ns_type].nsd_bkt_bits;
 
-       OBD_ALLOC_LARGE(ns->ns_rs_buckets,
-                       BIT(ns->ns_bucket_bits) * sizeof(ns->ns_rs_buckets[0]));
+       OBD_ALLOC_PTR_ARRAY_LARGE(ns->ns_rs_buckets, 1 << ns->ns_bucket_bits);
        if (!ns->ns_rs_buckets)
                goto out_hash;
 
@@ -914,15 +931,17 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
        ns->ns_max_parallel_ast   = LDLM_DEFAULT_PARALLEL_AST_LIMIT;
        ns->ns_nr_unused          = 0;
        ns->ns_max_unused         = LDLM_DEFAULT_LRU_SIZE;
+       ns->ns_cancel_batch       = LDLM_DEFAULT_LRU_SHRINK_BATCH;
        ns->ns_max_age            = ktime_set(LDLM_DEFAULT_MAX_ALIVE, 0);
        ns->ns_ctime_age_limit    = LDLM_CTIME_AGE_LIMIT;
-       ns->ns_dirty_age_limit    = LDLM_DIRTY_AGE_LIMIT;
+       ns->ns_dirty_age_limit    = ktime_set(LDLM_DIRTY_AGE_LIMIT, 0);
        ns->ns_timeouts           = 0;
        ns->ns_orig_connect_flags = 0;
        ns->ns_connect_flags      = 0;
        ns->ns_stopping           = 0;
        ns->ns_reclaim_start      = 0;
        ns->ns_last_pos           = &ns->ns_unused_list;
+       ns->ns_flags              = 0;
 
        rc = ldlm_namespace_sysfs_register(ns);
        if (rc) {
@@ -951,8 +970,7 @@ out_sysfs:
        ldlm_namespace_sysfs_unregister(ns);
        ldlm_namespace_cleanup(ns, 0);
 out_hash:
-       OBD_FREE_LARGE(ns->ns_rs_buckets,
-                      BIT(ns->ns_bucket_bits) * sizeof(ns->ns_rs_buckets[0]));
+       OBD_FREE_PTR_ARRAY_LARGE(ns->ns_rs_buckets, 1 << ns->ns_bucket_bits);
        kfree(ns->ns_name);
        cfs_hash_putref(ns->ns_rs_hash);
 out_ns:
@@ -1221,8 +1239,7 @@ void ldlm_namespace_free_post(struct ldlm_namespace *ns)
        ldlm_namespace_debugfs_unregister(ns);
        ldlm_namespace_sysfs_unregister(ns);
        cfs_hash_putref(ns->ns_rs_hash);
-       OBD_FREE_LARGE(ns->ns_rs_buckets,
-                      BIT(ns->ns_bucket_bits) * sizeof(ns->ns_rs_buckets[0]));
+       OBD_FREE_PTR_ARRAY_LARGE(ns->ns_rs_buckets, 1 << ns->ns_bucket_bits);
        kfree(ns->ns_name);
        /* Namespace \a ns should be not on list at this time, otherwise
         * this will cause issues related to using freed \a ns in poold
@@ -1343,7 +1360,7 @@ static bool ldlm_resource_extent_new(struct ldlm_resource *res)
        /* Initialize interval trees for each lock mode. */
        for (idx = 0; idx < LCK_MODE_NUM; idx++) {
                res->lr_itree[idx].lit_size = 0;
-               res->lr_itree[idx].lit_mode = 1 << idx;
+               res->lr_itree[idx].lit_mode = BIT(idx);
                res->lr_itree[idx].lit_root = NULL;
        }
        return true;
@@ -1367,7 +1384,7 @@ static struct ldlm_resource *ldlm_resource_new(enum ldlm_type ldlm_type)
        struct ldlm_resource *res;
        bool rc;
 
-       res = kmem_cache_alloc(ldlm_resource_slab, GFP_NOFS);
+       OBD_SLAB_ALLOC_PTR_GFP(res, ldlm_resource_slab, GFP_NOFS);
        if (res == NULL)
                return NULL;
 
@@ -1383,21 +1400,20 @@ static struct ldlm_resource *ldlm_resource_new(enum ldlm_type ldlm_type)
                break;
        }
        if (!rc) {
-               kmem_cache_free(ldlm_resource_slab, res);
+               OBD_SLAB_FREE_PTR(res, ldlm_resource_slab);
                return NULL;
        }
 
        INIT_LIST_HEAD(&res->lr_granted);
        INIT_LIST_HEAD(&res->lr_waiting);
-       res->lr_lvb_data = NULL;
-       res->lr_lvb_inode = NULL;
-       res->lr_lvb_len = 0;
 
        atomic_set(&res->lr_refcount, 1);
+       spin_lock_init(&res->lr_lock);
        lu_ref_init(&res->lr_reference);
 
        /* Since LVB init can be delayed now, there is no longer need to
         * immediatelly acquire mutex here. */
+       mutex_init(&res->lr_lvb_mutex);
        res->lr_lvb_initialized = false;
 
        return res;
@@ -1414,7 +1430,7 @@ static void ldlm_resource_free(struct ldlm_resource *res)
                        OBD_FREE_PTR(res->lr_ibits_queues);
        }
 
-       kmem_cache_free(ldlm_resource_slab, res);
+       OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
 }
 
 /**
@@ -1556,16 +1572,13 @@ int ldlm_resource_putref(struct ldlm_resource *res)
 }
 EXPORT_SYMBOL(ldlm_resource_putref);
 
-/**
- * Add a lock into a given resource into specified lock list.
- */
-void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
-                           struct ldlm_lock *lock)
+static void __ldlm_resource_add_lock(struct ldlm_resource *res,
+                                    struct list_head *head,
+                                    struct ldlm_lock *lock,
+                                    bool tail)
 {
        check_res_locked(res);
 
-       LDLM_DEBUG(lock, "About to add this lock");
-
        if (ldlm_is_destroyed(lock)) {
                CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
                return;
@@ -1573,36 +1586,53 @@ void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
 
        LASSERT(list_empty(&lock->l_res_link));
 
-       list_add_tail(&lock->l_res_link, head);
+       if (tail)
+               list_add_tail(&lock->l_res_link, head);
+       else
+               list_add(&lock->l_res_link, head);
 
        if (res->lr_type == LDLM_IBITS)
                ldlm_inodebits_add_lock(res, head, lock);
+
+       ldlm_resource_dump(D_INFO, res);
+}
+
+/**
+ * Add a lock into a given resource into specified lock list.
+ */
+void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
+                           struct ldlm_lock *lock)
+{
+       LDLM_DEBUG(lock, "About to add this lock");
+
+       __ldlm_resource_add_lock(res, head, lock, true);
 }
 
 /**
  * Insert a lock into resource after specified lock.
- *
- * Obtain resource description from the lock we are inserting after.
  */
 void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
                                     struct ldlm_lock *new)
 {
-       struct ldlm_resource *res = original->l_resource;
+       LASSERT(!list_empty(&original->l_res_link));
 
-       check_res_locked(res);
-
-       ldlm_resource_dump(D_INFO, res);
        LDLM_DEBUG(new, "About to insert this lock after %p: ", original);
+       __ldlm_resource_add_lock(original->l_resource,
+                                &original->l_res_link,
+                                new, false);
+}
 
-       if (ldlm_is_destroyed(new)) {
-               CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
-               goto out;
-       }
-
-       LASSERT(list_empty(&new->l_res_link));
+/**
+ * Insert a lock into resource before the specified lock.
+ */
+void ldlm_resource_insert_lock_before(struct ldlm_lock *original,
+                                      struct ldlm_lock *new)
+{
+       LASSERT(!list_empty(&original->l_res_link));
 
-       list_add(&new->l_res_link, &original->l_res_link);
- out:;
+       LDLM_DEBUG(new, "About to insert this lock before %p: ", original);
+       __ldlm_resource_add_lock(original->l_resource,
+                                original->l_res_link.prev, new, false);
 }
 
 void ldlm_resource_unlink_lock(struct ldlm_lock *lock)