1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This code is issued under the GNU General Public License.
7 * See the file COPYING in this distribution
9 * by Cluster File Systems, Inc.
12 #define DEBUG_SUBSYSTEM S_LDLM
14 #include <linux/types.h>
15 #include <linux/random.h>
17 #include <linux/lustre_dlm.h>
19 struct ldlm_test_thread {
20 struct ldlm_namespace *t_ns;
21 struct list_head t_link;
23 wait_queue_head_t t_ctl_waitq;
26 static spinlock_t ctl_lock = SPIN_LOCK_UNLOCKED;
27 static struct list_head ctl_threads;
28 static int regression_running = 0;
29 static struct ptlrpc_client ctl_client;
30 static struct ptlrpc_connection *ctl_conn;
32 static int ldlm_test_callback(struct lustre_handle *lockh,
33 struct ldlm_lock_desc *new,
34 void *data, __u32 data_len)
36 struct ldlm_lock *lock;
39 lock = ldlm_handle2lock(lockh);
41 CERROR("invalid handle in callback\n");
45 printk("ldlm_test_callback: lock=%Lu, new=%p\n", lockh->addr, new);
49 int ldlm_test_basics(struct obd_device *obddev)
51 struct ldlm_namespace *ns;
52 struct ldlm_resource *res;
53 __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
55 struct ldlm_lock *lock1, *lock;
58 ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
62 lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_CR, NULL, 0);
65 err = ldlm_lock_enqueue(lock1, NULL, 0, &flags,
66 ldlm_test_callback, ldlm_test_callback);
70 lock = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_EX, NULL, 0);
73 err = ldlm_lock_enqueue(lock, NULL, 0, &flags,
74 ldlm_test_callback, ldlm_test_callback);
77 if (!(flags & LDLM_FL_BLOCK_GRANTED))
80 res = ldlm_resource_get(ns, NULL, res_id, LDLM_PLAIN, 1);
83 ldlm_resource_dump(res);
85 res = ldlm_lock_convert(lock1, LCK_NL, &flags);
87 ldlm_reprocess_all(res);
89 ldlm_resource_dump(res);
90 ldlm_namespace_free(ns);
95 int ldlm_test_extents(struct obd_device *obddev)
97 struct ldlm_namespace *ns;
98 struct ldlm_resource *res;
99 struct ldlm_lock *lock, *lock1, *lock2;
100 __u64 res_id[RES_NAME_SIZE] = {0, 0, 0};
101 struct ldlm_extent ext1 = {4, 6}, ext2 = {6, 9}, ext3 = {10, 11};
105 ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
110 lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR, NULL,
114 err = ldlm_lock_enqueue(lock1, &ext1, sizeof(ext1), &flags, NULL, NULL);
117 if (!(flags & LDLM_FL_LOCK_CHANGED))
121 lock2 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR,
123 err = ldlm_lock_enqueue(lock2, &ext2, sizeof(ext2), &flags, NULL, NULL);
126 if (!(flags & LDLM_FL_LOCK_CHANGED))
130 lock = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_EX, NULL, 0);
133 err = ldlm_lock_enqueue(lock, &ext3, sizeof(ext3), &flags,
137 if (!(flags & LDLM_FL_BLOCK_GRANTED))
139 if (flags & LDLM_FL_LOCK_CHANGED)
142 /* Convert/cancel blocking locks */
144 res = ldlm_lock_convert(lock1, LCK_NL, &flags);
146 ldlm_reprocess_all(res);
148 ldlm_lock_cancel(lock2);
150 ldlm_reprocess_all(res);
152 /* Dump the results */
153 res = ldlm_resource_get(ns, NULL, res_id, LDLM_EXTENT, 0);
156 ldlm_resource_dump(res);
157 ldlm_namespace_free(ns);
162 static int ldlm_test_network(struct obd_device *obddev,
163 struct ptlrpc_connection *conn)
165 struct ldlm_obd *ldlm = &obddev->u.ldlm;
167 __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
168 struct ldlm_extent ext = {4, 6};
169 struct lustre_handle lockh1;
173 /* FIXME: this needs a connh as 3rd paramter, before it will work */
175 err = ldlm_cli_enqueue(ldlm->ldlm_client, conn, NULL, NULL,
176 obddev->obd_namespace, NULL, res_id, LDLM_EXTENT,
177 &ext, sizeof(ext), LCK_PR, &flags, NULL, NULL, 0,
179 CERROR("ldlm_cli_enqueue: %d\n", err);
181 ldlm_lock_decref(&lockh1, LCK_PR);
186 static int ldlm_test_main(void *data)
188 struct ldlm_test_thread *thread = data;
189 struct ldlm_namespace *ns;
194 spin_lock_irq(¤t->sigmask_lock);
195 sigfillset(¤t->blocked);
196 recalc_sigpending(current);
197 spin_unlock_irq(¤t->sigmask_lock);
199 sprintf(current->comm, "ldlm_test");
201 ns = ldlm_namespace_new("ldlm_test", LDLM_NAMESPACE_CLIENT);
207 /* Record that the thread is running */
208 thread->t_flags |= SVC_RUNNING;
209 wake_up(&thread->t_ctl_waitq);
212 struct lustre_handle lockh;
213 __u64 res_id[3] = {0};
218 /* Pick a random resource from 1 to 10 */
219 get_random_bytes(&random, sizeof(random));
220 res_id[0] = random % 10 + 1;
222 /* Pick a random lock mode */
223 get_random_bytes(&random, sizeof(random));
224 lock_mode = random % LCK_NL + 1;
226 rc = ldlm_cli_enqueue(&ctl_client, ctl_conn, NULL, NULL, ns, NULL,
227 res_id, LDLM_PLAIN, NULL, 0, lock_mode,
228 &flags, ldlm_test_callback, NULL, 0,
231 CERROR("ldlm_cli_enqueue: %d\n", rc);
237 thread->t_flags |= SVC_STOPPED;
238 wake_up(&thread->t_ctl_waitq);
243 static int ldlm_start_thread(void)
245 struct ldlm_test_thread *test;
249 OBD_ALLOC(test, sizeof(*test));
254 init_waitqueue_head(&test->t_ctl_waitq);
256 spin_lock(&ctl_lock);
257 list_add(&test->t_link, &ctl_threads);
258 spin_unlock(&ctl_lock);
260 rc = kernel_thread(ldlm_test_main, (void *)test,
261 CLONE_VM | CLONE_FS | CLONE_FILES);
263 CERROR("cannot start thread\n");
266 wait_event(test->t_ctl_waitq, test->t_flags & SVC_RUNNING);
271 int ldlm_regression_start(struct obd_device *obddev,
272 struct ptlrpc_connection *conn, int count)
277 spin_lock(&ctl_lock);
278 if (regression_running) {
279 CERROR("You can't start the ldlm regression twice.\n");
280 spin_unlock(&ctl_lock);
283 regression_running = 1;
284 spin_unlock(&ctl_lock);
286 for (i = 0; i < count; i++) {
287 rc = ldlm_start_thread();
296 int ldlm_regression_stop(void)
300 spin_lock(&ctl_lock);
301 if (!regression_running) {
302 CERROR("The ldlm regression isn't started.\n");
303 spin_unlock(&ctl_lock);
307 while (!list_empty(&ctl_threads)) {
308 struct ldlm_test_thread *thread;
309 thread = list_entry(ctl_threads.next, struct ldlm_test_thread,
312 thread->t_flags |= SVC_STOPPING;
313 spin_unlock(&ctl_lock);
315 wake_up(&thread->t_ctl_waitq);
316 wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPED);
318 spin_lock(&ctl_lock);
319 list_del(&thread->t_link);
320 OBD_FREE(thread, sizeof(*thread));
323 regression_running = 0;
324 spin_unlock(&ctl_lock);
329 int ldlm_test(struct obd_device *obddev, struct ptlrpc_connection *conn)
332 rc = ldlm_test_basics(obddev);
336 rc = ldlm_test_extents(obddev);
340 rc = ldlm_test_network(obddev, conn);