Whamcloud - gitweb
- Grammatical, LDLM updates to network.lyx
[fs/lustre-release.git] / lustre / ldlm / ldlm_test.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002 Cluster File Systems, Inc.
5  *
6  * This code is issued under the GNU General Public License.
7  * See the file COPYING in this distribution
8  *
9  * by Cluster File Systems, Inc.
10  */
11
12 #define DEBUG_SUBSYSTEM S_LDLM
13
14 #include <linux/types.h>
15 #include <linux/random.h>
16
17 #include <linux/lustre_dlm.h>
18
19 struct ldlm_test_thread {
20         struct ldlm_namespace *t_ns;
21         struct list_head t_link;
22         __u32 t_flags; 
23         wait_queue_head_t t_ctl_waitq;
24 };
25
26 static spinlock_t ctl_lock = SPIN_LOCK_UNLOCKED;
27 static struct list_head ctl_threads;
28 static int regression_running = 0;
29
30 static int ldlm_blocking_ast(struct ldlm_lock *lock,
31                              struct ldlm_lock_desc *new,
32                              void *data, __u32 data_len)
33 {
34         ENTRY;
35         CERROR("ldlm_blocking_ast: lock=%p, new=%p\n", lock, new);
36         RETURN(0);
37 }
38
39 int ldlm_test_basics(struct obd_device *obddev)
40 {
41         struct ldlm_namespace *ns;
42         struct ldlm_resource *res;
43         __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
44         ldlm_error_t err;
45         struct ldlm_lock *lock1, *lock;
46         int flags;
47
48         ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
49         if (ns == NULL)
50                 LBUG();
51
52         lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_CR, NULL, 0);
53         if (lock1 == NULL)
54                 LBUG();
55         err = ldlm_lock_enqueue(lock1, NULL, 0, &flags,
56                                 ldlm_completion_ast, ldlm_blocking_ast);
57         if (err != ELDLM_OK)
58                 LBUG();
59
60         lock = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_EX, NULL, 0);
61         if (lock == NULL)
62                 LBUG();
63         err = ldlm_lock_enqueue(lock, NULL, 0, &flags,
64                                 ldlm_completion_ast, ldlm_blocking_ast);
65         if (err != ELDLM_OK)
66                 LBUG();
67         if (!(flags & LDLM_FL_BLOCK_GRANTED))
68                 LBUG();
69
70         res = ldlm_resource_get(ns, NULL, res_id, LDLM_PLAIN, 1);
71         if (res == NULL)
72                 LBUG();
73         ldlm_resource_dump(res);
74
75         res = ldlm_lock_convert(lock1, LCK_NL, &flags);
76         if (res != NULL)
77                 ldlm_reprocess_all(res);
78
79         ldlm_resource_dump(res);
80         ldlm_namespace_free(ns);
81
82         return 0;
83 }
84
85 int ldlm_test_extents(struct obd_device *obddev)
86 {
87         struct ldlm_namespace *ns;
88         struct ldlm_resource *res;
89         struct ldlm_lock *lock, *lock1, *lock2;
90         __u64 res_id[RES_NAME_SIZE] = {0, 0, 0};
91         struct ldlm_extent ext1 = {4, 6}, ext2 = {6, 9}, ext3 = {10, 11};
92         ldlm_error_t err;
93         int flags;
94
95         ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
96         if (ns == NULL)
97                 LBUG();
98
99         flags = 0;
100         lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR, NULL,
101                                  0);
102         if (lock1 == NULL)
103                 LBUG();
104         err = ldlm_lock_enqueue(lock1, &ext1, sizeof(ext1), &flags, NULL, NULL);
105         if (err != ELDLM_OK)
106                 LBUG();
107         if (!(flags & LDLM_FL_LOCK_CHANGED))
108                 LBUG();
109
110         flags = 0;
111         lock2 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR,
112                                 NULL, 0);
113         err = ldlm_lock_enqueue(lock2, &ext2, sizeof(ext2), &flags, NULL, NULL);
114         if (err != ELDLM_OK)
115                 LBUG();
116         if (!(flags & LDLM_FL_LOCK_CHANGED))
117                 LBUG();
118
119         flags = 0;
120         lock = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_EX, NULL, 0);
121         if (lock == NULL)
122                 LBUG();
123         err = ldlm_lock_enqueue(lock, &ext3, sizeof(ext3), &flags,
124                                 NULL, NULL);
125         if (err != ELDLM_OK)
126                 LBUG();
127         if (!(flags & LDLM_FL_BLOCK_GRANTED))
128                 LBUG();
129         if (flags & LDLM_FL_LOCK_CHANGED)
130                 LBUG();
131
132         /* Convert/cancel blocking locks */
133         flags = 0;
134         res = ldlm_lock_convert(lock1, LCK_NL, &flags);
135         if (res != NULL)
136                 ldlm_reprocess_all(res);
137
138         ldlm_lock_cancel(lock2);
139         if (res != NULL)
140                 ldlm_reprocess_all(res);
141
142         /* Dump the results */
143         res = ldlm_resource_get(ns, NULL, res_id, LDLM_EXTENT, 0);
144         if (res == NULL)
145                 LBUG();
146         ldlm_resource_dump(res);
147         ldlm_namespace_free(ns);
148
149         return 0;
150 }
151
152 static int ldlm_test_network(struct obd_device *obddev,
153                              struct ptlrpc_connection *conn)
154 {
155
156         __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
157         struct ldlm_extent ext = {4, 6};
158         struct lustre_handle lockh1;
159         int flags = 0;
160         ldlm_error_t err;
161
162         /* FIXME: this needs a connh as 3rd paramter, before it will work */
163
164         err = ldlm_cli_enqueue(NULL, NULL, obddev->obd_namespace, NULL, res_id,
165                                LDLM_EXTENT, &ext, sizeof(ext), LCK_PR, &flags,
166                                NULL, NULL, NULL, 0, &lockh1);
167         CERROR("ldlm_cli_enqueue: %d\n", err);
168         if (err == ELDLM_OK)
169                 ldlm_lock_decref(&lockh1, LCK_PR);
170
171         RETURN(err);
172 }
173
174 static int ldlm_test_main(void *data)
175 {
176         struct ldlm_test_thread *thread = data;
177         struct ldlm_namespace *ns;
178         ENTRY;
179
180         lock_kernel();
181         daemonize();
182         spin_lock_irq(&current->sigmask_lock);
183         sigfillset(&current->blocked);
184         recalc_sigpending(current);
185         spin_unlock_irq(&current->sigmask_lock);
186
187         sprintf(current->comm, "ldlm_test");
188
189         ns = ldlm_namespace_new("ldlm_test", LDLM_NAMESPACE_CLIENT);
190         if (ns == NULL) {
191                 LBUG();
192                 GOTO(out, -ENOMEM);
193         }
194
195         /* Record that the thread is running */
196         thread->t_flags |= SVC_RUNNING;
197         wake_up(&thread->t_ctl_waitq);
198
199         while (1) {
200                 struct lustre_handle lockh;
201                 __u64 res_id[3] = {0};
202                 __u32 lock_mode;
203                 char random;
204                 int flags = 0, rc;
205
206                 /* Pick a random resource from 1 to 10 */
207                 get_random_bytes(&random, sizeof(random));
208                 res_id[0] = random % 10 + 1;
209
210                 /* Pick a random lock mode */
211                 get_random_bytes(&random, sizeof(random));
212                 lock_mode = random % LCK_NL + 1;
213
214                 rc = ldlm_cli_enqueue(NULL, NULL, ns, NULL,
215                                       res_id, LDLM_PLAIN, NULL, 0, lock_mode,
216                                       &flags, ldlm_completion_ast,
217                                       ldlm_blocking_ast, NULL, 0, &lockh);
218                 if (rc < 0) {
219                         CERROR("ldlm_cli_enqueue: %d\n", rc);
220                         LBUG();
221                 }
222         }
223
224  out:
225         thread->t_flags |= SVC_STOPPED;
226         wake_up(&thread->t_ctl_waitq);
227
228         RETURN(0);
229 }
230
231 static int ldlm_start_thread(void)
232 {
233         struct ldlm_test_thread *test;
234         int rc;
235         ENTRY;
236
237         OBD_ALLOC(test, sizeof(*test));
238         if (test == NULL) {
239                 LBUG();
240                 RETURN(-ENOMEM);
241         }
242         init_waitqueue_head(&test->t_ctl_waitq);
243
244         spin_lock(&ctl_lock);
245         list_add(&test->t_link, &ctl_threads);
246         spin_unlock(&ctl_lock);
247
248         rc = kernel_thread(ldlm_test_main, (void *)test,
249                            CLONE_VM | CLONE_FS | CLONE_FILES);
250         if (rc < 0) {
251                 CERROR("cannot start thread\n");
252                 RETURN(-EINVAL);
253         }
254         wait_event(test->t_ctl_waitq, test->t_flags & SVC_RUNNING);
255
256         RETURN(0);
257 }
258
259 int ldlm_regression_start(struct obd_device *obddev,
260                           struct ptlrpc_connection *conn, int count)
261 {
262         int i, rc = 0;
263         ENTRY;
264
265         spin_lock(&ctl_lock);
266         if (regression_running) {
267                 CERROR("You can't start the ldlm regression twice.\n");
268                 spin_unlock(&ctl_lock);
269                 RETURN(-EINVAL);
270         }
271         regression_running = 1;
272         spin_unlock(&ctl_lock);
273
274         for (i = 0; i < count; i++) {
275                 rc = ldlm_start_thread();
276                 if (rc < 0)
277                         GOTO(cleanup, rc);
278         }
279
280  cleanup:
281         RETURN(rc);
282 }
283
284 int ldlm_regression_stop(void)
285 {
286         ENTRY;
287
288         spin_lock(&ctl_lock);
289         if (!regression_running) {
290                 CERROR("The ldlm regression isn't started.\n");
291                 spin_unlock(&ctl_lock);
292                 RETURN(-EINVAL);
293         }
294
295         while (!list_empty(&ctl_threads)) {
296                 struct ldlm_test_thread *thread;
297                 thread = list_entry(ctl_threads.next, struct ldlm_test_thread,
298                                     t_link);
299
300                 thread->t_flags |= SVC_STOPPING;
301                 spin_unlock(&ctl_lock);
302
303                 wake_up(&thread->t_ctl_waitq);
304                 wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPED);
305
306                 spin_lock(&ctl_lock);
307                 list_del(&thread->t_link);
308                 OBD_FREE(thread, sizeof(*thread));
309         }
310
311         regression_running = 0;
312         spin_unlock(&ctl_lock);
313
314         RETURN(0);
315 }
316
317 int ldlm_test(struct obd_device *obddev, struct ptlrpc_connection *conn)
318 {
319         int rc;
320         rc = ldlm_test_basics(obddev);
321         if (rc)
322                 RETURN(rc);
323
324         rc = ldlm_test_extents(obddev);
325         if (rc)
326                 RETURN(rc);
327
328         rc = ldlm_test_network(obddev, conn);
329         RETURN(rc);
330 }