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