Whamcloud - gitweb
efe314ef2c8c647eff1519f0f062991a33d03056
[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/lustre_dlm.h>
15
16 struct ldlm_test_thread {
17         struct ldlm_namespace *t_ns;
18         struct list_head t_link;
19         __u32 t_flags; 
20         wait_queue_head_t t_ctl_waitq;
21 };
22
23 static spinlock_t ctl_lock = SPIN_LOCK_UNLOCKED;
24 static struct list_head ctl_threads;
25 static int regression_running = 0;
26
27 static int ldlm_test_callback(struct lustre_handle *lockh,
28                               struct ldlm_lock_desc *new,
29                               void *data, __u32 data_len)
30 {
31         printk("ldlm_test_callback: lock=%Lu, new=%p\n", lockh->addr, new);
32         return 0;
33 }
34
35 int ldlm_test_basics(struct obd_device *obddev)
36 {
37         struct ldlm_namespace *ns;
38         struct ldlm_resource *res;
39         __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
40         ldlm_error_t err;
41         struct ldlm_lock *lock1, *lock;
42         int flags;
43
44         ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
45         if (ns == NULL)
46                 LBUG();
47
48         lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_CR, NULL, 0);
49         if (lock1 == NULL)
50                 LBUG();
51         err = ldlm_lock_enqueue(lock1, NULL, 0, &flags,
52                                 ldlm_test_callback, ldlm_test_callback);
53         if (err != ELDLM_OK)
54                 LBUG();
55
56         lock = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_EX, NULL, 0);
57         if (lock == NULL)
58                 LBUG();
59         err = ldlm_lock_enqueue(lock, NULL, 0, &flags,
60                                 ldlm_test_callback, ldlm_test_callback);
61         if (err != ELDLM_OK)
62                 LBUG();
63         if (!(flags & LDLM_FL_BLOCK_GRANTED))
64                 LBUG();
65
66         res = ldlm_resource_get(ns, NULL, res_id, LDLM_PLAIN, 1);
67         if (res == NULL)
68                 LBUG();
69         ldlm_resource_dump(res);
70
71         res = ldlm_convert(lock1, LCK_NL, &flags);
72         if (res != NULL)
73                 ldlm_reprocess_all(res);
74
75         ldlm_resource_dump(res);
76         ldlm_namespace_free(ns);
77
78         return 0;
79 }
80
81 int ldlm_test_extents(struct obd_device *obddev)
82 {
83         struct ldlm_namespace *ns;
84         struct ldlm_resource *res;
85         struct ldlm_lock *lock, *lock1, *lock2;
86         __u64 res_id[RES_NAME_SIZE] = {0, 0, 0};
87         struct ldlm_extent ext1 = {4, 6}, ext2 = {6, 9}, ext3 = {10, 11};
88         ldlm_error_t err;
89         int flags;
90
91         ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
92         if (ns == NULL)
93                 LBUG();
94
95         flags = 0;
96         lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR, NULL,
97                                  0);
98         if (lock1 == NULL)
99                 LBUG();
100         err = ldlm_lock_enqueue(lock1, &ext1, sizeof(ext1), &flags, NULL, NULL);
101         if (err != ELDLM_OK)
102                 LBUG();
103         if (!(flags & LDLM_FL_LOCK_CHANGED))
104                 LBUG();
105
106         flags = 0;
107         lock2 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR,
108                                 NULL, 0);
109         err = ldlm_lock_enqueue(lock2, &ext2, sizeof(ext2), &flags, NULL, NULL);
110         if (err != ELDLM_OK)
111                 LBUG();
112         if (!(flags & LDLM_FL_LOCK_CHANGED))
113                 LBUG();
114
115         flags = 0;
116         lock = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_EX, NULL, 0);
117         if (lock == NULL)
118                 LBUG();
119         err = ldlm_lock_enqueue(lock, &ext3, sizeof(ext3), &flags,
120                                 NULL, NULL);
121         if (err != ELDLM_OK)
122                 LBUG();
123         if (!(flags & LDLM_FL_BLOCK_GRANTED))
124                 LBUG();
125         if (flags & LDLM_FL_LOCK_CHANGED)
126                 LBUG();
127
128         /* Convert/cancel blocking locks */
129         flags = 0;
130         res = ldlm_convert(lock1, LCK_NL, &flags);
131         if (res != NULL)
132                 ldlm_reprocess_all(res);
133
134         ldlm_lock_cancel(lock2);
135         if (res != NULL)
136                 ldlm_reprocess_all(res);
137
138         /* Dump the results */
139         res = ldlm_resource_get(ns, NULL, res_id, LDLM_EXTENT, 0);
140         if (res == NULL)
141                 LBUG();
142         ldlm_resource_dump(res);
143         ldlm_namespace_free(ns);
144
145         return 0;
146 }
147
148 static int ldlm_test_network(struct obd_device *obddev,
149                              struct ptlrpc_connection *conn)
150 {
151         struct ldlm_obd *ldlm = &obddev->u.ldlm;
152
153         __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
154         struct ldlm_extent ext = {4, 6};
155         struct lustre_handle lockh1;
156         int flags = 0;
157         ldlm_error_t err;
158
159         err = ldlm_cli_enqueue(ldlm->ldlm_client, conn, NULL,
160                                obddev->obd_namespace, NULL, res_id, LDLM_EXTENT,
161                                &ext, sizeof(ext), LCK_PR, &flags, NULL, NULL, 0,
162                                &lockh1);
163         CERROR("ldlm_cli_enqueue: %d\n", err);
164
165         RETURN(err);
166 }
167
168 static int ldlm_test_main(void *data)
169 {
170         return 0;
171 }
172
173 static int ldlm_start_thread(void)
174 {
175         struct ldlm_test_thread *test;
176         int rc;
177         ENTRY;
178
179         OBD_ALLOC(test, sizeof(*test));
180         if (test == NULL) {
181                 LBUG();
182                 RETURN(-ENOMEM);
183         }
184         init_waitqueue_head(&test->t_ctl_waitq);
185
186         spin_lock(&ctl_lock);
187         list_add(&test->t_link, &ctl_threads);
188         spin_unlock(&ctl_lock);
189
190         rc = kernel_thread(ldlm_test_main, (void *)test,
191                            CLONE_VM | CLONE_FS | CLONE_FILES);
192         if (rc < 0) {
193                 CERROR("cannot start thread\n");
194                 RETURN(-EINVAL);
195         }
196         wait_event(test->t_ctl_waitq, test->t_flags & SVC_RUNNING);
197
198         RETURN(0);
199 }
200
201 static int ldlm_stop_all_threads(void)
202 {
203         spin_lock(&ctl_lock);
204         while (!list_empty(&ctl_threads)) {
205                 struct ldlm_test_thread *thread;
206                 thread = list_entry(ctl_threads.next, struct ldlm_test_thread,
207                                     t_link);
208                 spin_unlock(&ctl_lock);
209
210                 thread->t_flags = SVC_STOPPING;
211
212                 wake_up(&thread->t_ctl_waitq);
213                 wait_event_interruptible(thread->t_ctl_waitq,
214                                          (thread->t_flags & SVC_STOPPED));
215
216                 spin_lock(&ctl_lock);
217                 list_del(&thread->t_link);
218                 OBD_FREE(thread, sizeof(*thread));
219         }
220         spin_unlock(&ctl_lock);
221
222         return 0;
223 }
224
225 int ldlm_regression_start(struct obd_device *obddev,
226                           struct ptlrpc_connection *conn, int count)
227 {
228         int i, rc;
229         ENTRY;
230
231         spin_lock(&ctl_lock);
232         if (regression_running) {
233                 CERROR("You can't start the ldlm regression twice.\n");
234                 spin_unlock(&ctl_lock);
235                 RETURN(-EINVAL);
236         }
237         regression_running = 1;
238         spin_unlock(&ctl_lock);
239
240         for (i = 0; i < count; i++) {
241                 rc = ldlm_start_thread();
242                 if (rc < 0)
243                         GOTO(cleanup, rc);
244         }
245
246  cleanup:
247         RETURN(rc);
248 }
249
250 int ldlm_regression_stop(void)
251 {
252         ENTRY;
253
254         spin_lock(&ctl_lock);
255         if (!regression_running) {
256                 CERROR("The ldlm regression isn't started.\n");
257                 spin_unlock(&ctl_lock);
258                 RETURN(-EINVAL);
259         }
260         spin_unlock(&ctl_lock);
261
262         /* Do stuff */
263
264         spin_lock(&ctl_lock);
265         regression_running = 0;
266         spin_unlock(&ctl_lock);
267
268         RETURN(0);
269 }
270
271 int ldlm_test(struct obd_device *obddev, struct ptlrpc_connection *conn)
272 {
273         int rc;
274         rc = ldlm_test_basics(obddev);
275         if (rc)
276                 RETURN(rc);
277
278         rc = ldlm_test_extents(obddev);
279         if (rc)
280                 RETURN(rc);
281
282         rc = ldlm_test_network(obddev, conn);
283         RETURN(rc);
284 }