Viewing: ldlm_extent.c
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#include <linux/kernel.h>
#ifdef HAVE_PRANDOM_H
#include <linux/prandom.h>
#endif
#include <lustre_dlm.h>
#include <obd_support.h>
#include <obd.h>
#include <obd_class.h>
#include <lustre_lib.h>
//#include "../../ldlm/ldlm_internal.h"
#define LUSTRE_TEST_LDLM_DEVICE "ldlm_test"
/*
* Performance tests for ldlm_extent access
*/
static const struct lu_device_type_operations ldlm_test_type_ops;
static struct lu_device_type ldlm_test_device_type = {
.ldt_tags = LU_DEVICE_MISC,
.ldt_name = LUSTRE_TEST_LDLM_DEVICE,
.ldt_ops = &ldlm_test_type_ops,
.ldt_ctx_tags = LCT_LOCAL
};
static const struct obd_ops extent_ops = {
.o_owner = THIS_MODULE,
};
static struct ldlm_res_id RES_ID = {
.name = {1, 2, 3, 4},
};
static void test_one(struct ldlm_resource *res,
u64 pos, u64 len, enum ldlm_mode mode,
int *cnt, int max, struct list_head *list)
{
__u64 flags = 0;
enum ldlm_error err;
ldlm_processing_policy pol;
struct ldlm_lock *lock = ldlm_lock_new_testing(res);
//struct ldlm_lock *lock = ldlm_lock_create(ns, &RES_ID,
// LDLM_EXTENT, LCK_EX,
// NULL, NULL, 0, LVB_T_NONE);
refcount_inc(&res->lr_refcount);
lock->l_req_mode = mode;
pol = ldlm_get_processing_policy(res);
lock->l_policy_data.l_extent.start = pos;
lock->l_policy_data.l_extent.end = pos + len;
lock->l_policy_data.l_extent.gid = 0;
lock->l_req_extent = lock->l_policy_data.l_extent;
lock_res(res);
if (pol(lock, &flags, LDLM_PROCESS_ENQUEUE, &err, NULL)
== LDLM_ITER_CONTINUE) {
list_add_tail(&lock->l_lru, list);
unlock_res(res);
*cnt += 1;
} else {
unlock_res(res);
ldlm_lock_cancel(lock);
ldlm_lock_put(lock);
}
if (*cnt > max) {
lock = list_first_entry_or_null(list,
struct ldlm_lock, l_lru);
if (lock) {
list_del_init(&lock->l_lru);
ldlm_lock_cancel(lock);
ldlm_lock_put(lock);
*cnt -= 1;
}
}
}
enum tests {
TEST_NO_OVERLAP,
TEST_WHOLE_FILE,
TEST_SAME_RANGE,
NUM_TESTS,
};
static int ldlm_extent_init(void)
{
char *name, *uuid;
struct ldlm_resource *res;
struct obd_device *obd;
struct ldlm_namespace *ns;
enum tests tnum;
struct rnd_state rstate;
prandom_seed_state(&rstate, 42);
class_register_type(&extent_ops, NULL, false,
LUSTRE_TEST_LDLM_DEVICE,
&ldlm_test_device_type);
OBD_ALLOC(name, MAX_OBD_NAME);
OBD_ALLOC(uuid, MAX_OBD_NAME);
strscpy(name, "test", MAX_OBD_NAME);
snprintf(uuid, MAX_OBD_NAME, "%s_UUID", name);
obd = class_attach_name(LUSTRE_TEST_LDLM_DEVICE, name, uuid);
ns = ldlm_namespace_new(obd, "extent-test", LDLM_NAMESPACE_CLIENT,
LDLM_NAMESPACE_MODEST,
LDLM_NS_TYPE_MDT);
res = ldlm_resource_get(ns, &RES_ID, LDLM_EXTENT, 1);
pr_info("ldlm_extent: sizeof(struct ldlm_lock)=%lu\n",
sizeof(struct ldlm_lock));
for (tnum = 0; tnum < NUM_TESTS; tnum++) {
long sum = 0, sumsq = 0, nsec;
int min_iters = 10, lk_num, it_num;
int loops;
pr_info("ldlm_extent: start test %d\n", tnum);
for (loops = 0; loops < 10 ; loops++) {
struct ldlm_lock *lock;
ktime_t start, now;
LIST_HEAD(list);
int cnt = 0;
int max = 1;
int i;
start = now = ktime_get();
for (i = 0; i < 10000000; i++) {
switch (tnum) {
case TEST_NO_OVERLAP:
max = min(8000, min_iters);
if (i < max * 16 / 15)
max = i * 15 / 16;
test_one(res,
prandom_u32_state(&rstate), 1,
LCK_EX, &cnt, max, &list);
break;
case TEST_WHOLE_FILE:
max = min(1000000, min_iters);
if (i < max * 16 / 15)
max = i * 15 / 16;
test_one(res, 0, OBD_OBJECT_EOF, LCK_PR,
&cnt, max, &list);
test_one(res,
prandom_u32_state(&rstate), 1,
LCK_PR, &cnt, max, &list);
break;
case TEST_SAME_RANGE:
max = min(1000000, min_iters);
if (i < max * 16 / 15)
max = i * 15 / 16;
test_one(res, 400, 300, LCK_PR,
&cnt, max, &list);
lock = list_first_entry_or_null(&list,
struct ldlm_lock, l_lru);
if (lock)
ldlm_extent_shift_kms(lock, 1000);
break;
case NUM_TESTS:
break;
}
now = ktime_get();
if (ktime_to_ms(ktime_sub(now, start)) > 10000)
break;
cond_resched();
}
i++;
if (i < min_iters / 3)
min_iters = i;
else if (i > min_iters * 3)
min_iters *= 10;
nsec = ktime_to_ns(ktime_sub(now, start)) / i;
sum += nsec;
sumsq += nsec * nsec;
lk_num = it_num = 0;
while ((lock = list_first_entry_or_null(&list,
struct ldlm_lock, l_lru))
!= NULL) {
#ifdef to_ldlm_interval
struct ldlm_interval *n = lock->l_tree_node;
if (n && interval_is_intree(&n->li_node) &&
lock->l_sl_policy.next == &n->li_group &&
lock->l_sl_policy.prev == &n->li_group)
it_num++;
#else
if (!RB_EMPTY_NODE(&lock->l_rb) &&
list_empty(&lock->l_same_extent))
it_num++;
#endif
list_del_init(&lock->l_lru);
ldlm_lock_cancel(lock);
ldlm_lock_put(lock);
lk_num++;
}
pr_info("ldlm_extent: test %d loop=%d min_iters=%d iters=%d ns/iter=%lu (%d/%d)\n",
tnum, loops, min_iters, i, nsec, lk_num, it_num);
}
pr_info("ldlm_extent: test %d ended - loops=%d min_iters=%d mean=%ld stddev=%ld\n",
tnum, loops, min_iters, sum / loops,
int_sqrt((sumsq - sum*sum/loops) / loops-1));
}
class_detach(obd);
OBD_FREE(name, MAX_OBD_NAME);
OBD_FREE(uuid, MAX_OBD_NAME);
ldlm_resource_putref(res);
ldlm_namespace_free_post(ns);
class_unregister_type(LUSTRE_TEST_LDLM_DEVICE);
return 0;
}
static void ldlm_extent_exit(void)
{
}
MODULE_DESCRIPTION("Lustre ldlm_extent performance test");
MODULE_LICENSE("GPL");
module_init(ldlm_extent_init);
module_exit(ldlm_extent_exit);