Whamcloud - gitweb
037e0a7af9772ea316394b59c58bc6c0d007d58c
[fs/lustre-release.git] / lustre / obdclass / llog_test.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lustre/obdclass/llog_test.c
35  *
36  * Author: Phil Schwan <phil@clusterfs.com>
37  */
38
39 #define DEBUG_SUBSYSTEM S_CLASS
40
41 #include <linux/module.h>
42 #include <linux/init.h>
43
44 #include <obd_class.h>
45 #include <lustre_log.h>
46
47 static int llog_test_rand;
48 static struct obd_uuid uuid = { .uuid = "test_uuid" };
49 static struct llog_logid cat_logid;
50
51 struct llog_mini_rec {
52         struct llog_rec_hdr     lmr_hdr;
53         struct llog_rec_tail    lmr_tail;
54 } __attribute__((packed));
55
56 static int verify_handle(char *test, struct llog_handle *llh, int num_recs)
57 {
58         int i;
59         int last_idx = 0;
60         int active_recs = 0;
61
62         for (i = 0; i < LLOG_BITMAP_BYTES * 8; i++) {
63                 if (ext2_test_bit(i, llh->lgh_hdr->llh_bitmap)) {
64                         last_idx = i;
65                         active_recs++;
66                 }
67         }
68
69         if (active_recs != num_recs) {
70                 CERROR("%s: expected %d active recs after write, found %d\n",
71                        test, num_recs, active_recs);
72                 RETURN(-ERANGE);
73         }
74
75         if (llh->lgh_hdr->llh_count != num_recs) {
76                 CERROR("%s: handle->count is %d, expected %d after write\n",
77                        test, llh->lgh_hdr->llh_count, num_recs);
78                 RETURN(-ERANGE);
79         }
80
81         if (llh->lgh_last_idx < last_idx) {
82                 CERROR("%s: handle->last_idx is %d, expected %d after write\n",
83                        test, llh->lgh_last_idx, last_idx);
84                 RETURN(-ERANGE);
85         }
86
87         RETURN(0);
88 }
89
90 /* Test named-log create/open, close */
91 static int llog_test_1(struct obd_device *obd, char *name)
92 {
93         struct llog_handle *llh;
94         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
95         int rc;
96         int rc2;
97         ENTRY;
98
99         CWARN("1a: create a log with name: %s\n", name);
100         LASSERT(ctxt);
101
102         rc = llog_open_create(NULL, ctxt, &llh, NULL, name);
103         if (rc) {
104                 CERROR("1a: llog_create with name %s failed: %d\n", name, rc);
105                 llog_ctxt_put(ctxt);
106                 RETURN(rc);
107         }
108         llog_init_handle(NULL, llh, LLOG_F_IS_PLAIN, &uuid);
109
110         if ((rc = verify_handle("1", llh, 1)))
111                 GOTO(out, rc);
112
113  out:
114         CWARN("1b: close newly-created log\n");
115         rc2 = llog_close(NULL, llh);
116         llog_ctxt_put(ctxt);
117         if (rc2) {
118                 CERROR("1b: close log %s failed: %d\n", name, rc2);
119                 if (rc == 0)
120                         rc = rc2;
121         }
122         RETURN(rc);
123 }
124
125 /* Test named-log reopen; returns opened log on success */
126 static int llog_test_2(struct obd_device *obd, char *name,
127                        struct llog_handle **llh)
128 {
129         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
130         int rc;
131         ENTRY;
132
133         CWARN("2a: re-open a log with name: %s\n", name);
134         rc = llog_open(NULL, ctxt, llh, NULL, name, LLOG_OPEN_EXISTS);
135         if (rc) {
136                 CERROR("2a: re-open log with name %s failed: %d\n", name, rc);
137                 GOTO(out, rc);
138         }
139         llog_init_handle(NULL, *llh, LLOG_F_IS_PLAIN, &uuid);
140
141         if ((rc = verify_handle("2", *llh, 1)))
142                 GOTO(out, rc);
143 #if 0
144         CWARN("2b: create a log without specified NAME & LOGID\n");
145         rc = llog_create(ctxt, &loghandle, NULL, NULL);
146         if (rc) {
147                 CERROR("2b: create log failed\n");
148                 GOTO(out, rc);
149         }
150         llog_init_handle(loghandle, LLOG_F_IS_PLAIN, &uuid);
151         logid = loghandle->lgh_id;
152         llog_close(loghandle);
153
154         CWARN("2b: re-open the log by LOGID\n");
155         rc = llog_create(ctxt, &loghandle, &logid, NULL);
156         if (rc) {
157                 CERROR("2b: re-open log by LOGID failed\n");
158                 GOTO(out, rc);
159         }
160         llog_init_handle(loghandle, LLOG_F_IS_PLAIN, &uuid);
161
162         CWARN("2b: destroy this log\n");
163         rc = llog_destroy(loghandle);
164         if (rc) {
165                 CERROR("2b: destroy log failed\n");
166                 GOTO(out, rc);
167         }
168         llog_free_handle(loghandle);
169 #endif
170 out:
171         llog_ctxt_put(ctxt);
172
173         RETURN(rc);
174 }
175
176 /* Test record writing, single and in bulk */
177 static int llog_test_3(struct obd_device *obd, struct llog_handle *llh)
178 {
179         struct llog_create_rec lcr;
180         int rc, i;
181         int num_recs = 1;       /* 1 for the header */
182         ENTRY;
183
184         lcr.lcr_hdr.lrh_len = lcr.lcr_tail.lrt_len = sizeof(lcr);
185         lcr.lcr_hdr.lrh_type = OST_SZ_REC;
186
187         CWARN("3a: write one create_rec\n");
188         rc = llog_write_rec(NULL, llh,  &lcr.lcr_hdr, NULL, 0, NULL, -1);
189         num_recs++;
190         if (rc) {
191                 CERROR("3a: write one log record failed: %d\n", rc);
192                 RETURN(rc);
193         }
194
195         if ((rc = verify_handle("3a", llh, num_recs)))
196                 RETURN(rc);
197
198         CWARN("3b: write 10 cfg log records with 8 bytes bufs\n");
199         for (i = 0; i < 10; i++) {
200                 struct llog_rec_hdr hdr;
201                 char buf[8];
202                 hdr.lrh_len = 8;
203                 hdr.lrh_type = OBD_CFG_REC;
204                 memset(buf, 0, sizeof buf);
205                 rc = llog_write_rec(NULL, llh, &hdr, NULL, 0, buf, -1);
206                 if (rc) {
207                         CERROR("3b: write 10 records failed at #%d: %d\n",
208                                i + 1, rc);
209                         RETURN(rc);
210                 }
211                 num_recs++;
212                 if ((rc = verify_handle("3c", llh, num_recs)))
213                         RETURN(rc);
214         }
215
216         if ((rc = verify_handle("3b", llh, num_recs)))
217                 RETURN(rc);
218
219         CWARN("3c: write 1000 more log records\n");
220         for (i = 0; i < 1000; i++) {
221                 rc = llog_write_rec(NULL, llh, &lcr.lcr_hdr, NULL, 0, NULL,
222                                     -1);
223                 if (rc) {
224                         CERROR("3c: write 1000 records failed at #%d: %d\n",
225                                i + 1, rc);
226                         RETURN(rc);
227                 }
228                 num_recs++;
229                 if ((rc = verify_handle("3b", llh, num_recs)))
230                         RETURN(rc);
231         }
232
233         if ((rc = verify_handle("3c", llh, num_recs)))
234                 RETURN(rc);
235
236         CWARN("3d: write log more than BITMAP_SIZE, return -ENOSPC\n");
237         for (i = 0; i < LLOG_BITMAP_SIZE(llh->lgh_hdr) + 1; i++) {
238                 struct llog_rec_hdr hdr;
239                 char buf_even[24];
240                 char buf_odd[32];
241
242                 memset(buf_odd, 0, sizeof buf_odd);
243                 memset(buf_even, 0, sizeof buf_even);
244                 if ((i % 2) == 0) {
245                         hdr.lrh_len = 24;
246                         hdr.lrh_type = OBD_CFG_REC;
247                         rc = llog_write_rec(NULL, llh, &hdr, NULL, 0, buf_even,
248                                             -1);
249                 } else {
250                         hdr.lrh_len = 32;
251                         hdr.lrh_type = OBD_CFG_REC;
252                         rc = llog_write_rec(NULL, llh, &hdr, NULL, 0, buf_odd,
253                                             -1);
254                 }
255                 if (rc) {
256                         if (rc == -ENOSPC) {
257                                 break;
258                         } else {
259                                 CERROR("3c: write recs failed at #%d: %d\n",
260                                         i + 1, rc);
261                                 RETURN(rc);
262                         }
263                 }
264                 num_recs++;
265         }
266         if (rc != -ENOSPC) {
267                 CWARN("3d: write record more than BITMAP size!\n");
268                 RETURN(-EINVAL);
269         }
270         if ((rc = verify_handle("3d", llh, num_recs)))
271                 RETURN(rc);
272
273         RETURN(rc);
274 }
275
276 /* Test catalogue additions */
277 static int llog_test_4(struct obd_device *obd)
278 {
279         struct llog_handle *cath;
280         char name[10];
281         int rc, i, buflen;
282         struct llog_mini_rec lmr;
283         struct llog_cookie cookie;
284         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
285         int num_recs = 0;
286         char *buf;
287         struct llog_rec_hdr rec;
288
289         ENTRY;
290
291         lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE;
292         lmr.lmr_hdr.lrh_type = 0xf00f00;
293
294         sprintf(name, "%x", llog_test_rand+1);
295         CWARN("4a: create a catalog log with name: %s\n", name);
296         rc = llog_open_create(NULL, ctxt, &cath, NULL, name);
297         if (rc) {
298                 CERROR("1a: llog_create with name %s failed: %d\n", name, rc);
299                 GOTO(out, rc);
300         }
301         llog_init_handle(NULL, cath, LLOG_F_IS_CAT, &uuid);
302         num_recs++;
303         cat_logid = cath->lgh_id;
304
305         CWARN("4b: write 1 record into the catalog\n");
306         rc = llog_cat_add_rec(NULL, cath, &lmr.lmr_hdr, &cookie, NULL);
307         if (rc != 1) {
308                 CERROR("4b: write 1 catalog record failed at: %d\n", rc);
309                 GOTO(out, rc);
310         }
311         num_recs++;
312         if ((rc = verify_handle("4b", cath, 2)))
313                 GOTO(ctxt_release, rc);
314
315         if ((rc = verify_handle("4b", cath->u.chd.chd_current_log, num_recs)))
316                 GOTO(ctxt_release, rc);
317
318         CWARN("4c: cancel 1 log record\n");
319         rc = llog_cat_cancel_records(NULL, cath, 1, &cookie);
320         if (rc) {
321                 CERROR("4c: cancel 1 catalog based record failed: %d\n", rc);
322                 GOTO(out, rc);
323         }
324         num_recs--;
325
326         if ((rc = verify_handle("4c", cath->u.chd.chd_current_log, num_recs)))
327                 GOTO(ctxt_release, rc);
328
329         CWARN("4d: write 40,000 more log records\n");
330         for (i = 0; i < 40000; i++) {
331                 rc = llog_cat_add_rec(NULL, cath, &lmr.lmr_hdr, NULL, NULL);
332                 if (rc) {
333                         CERROR("4d: write 40000 records failed at #%d: %d\n",
334                                i + 1, rc);
335                         GOTO(out, rc);
336                 }
337                 num_recs++;
338         }
339
340         CWARN("4e: add 5 large records, one record per block\n");
341         buflen = LLOG_CHUNK_SIZE - sizeof(struct llog_rec_hdr)
342                         - sizeof(struct llog_rec_tail);
343         OBD_ALLOC(buf, buflen);
344         if (buf == NULL)
345                 GOTO(out, rc = -ENOMEM);
346         for (i = 0; i < 5; i++) {
347                 rec.lrh_len = buflen;
348                 rec.lrh_type = OBD_CFG_REC;
349                 rc = llog_cat_add_rec(NULL, cath, &rec, NULL, buf);
350                 if (rc) {
351                         CERROR("4e: write 5 records failed at #%d: %d\n",
352                                i + 1, rc);
353                         OBD_FREE(buf, buflen);
354                         GOTO(out, rc);
355                 }
356                 num_recs++;
357         }
358         OBD_FREE(buf, buflen);
359
360  out:
361         CWARN("4f: put newly-created catalog\n");
362         rc = llog_cat_close(NULL, cath);
363 ctxt_release:
364         llog_ctxt_put(ctxt);
365         if (rc)
366                 CERROR("1b: close log %s failed: %d\n", name, rc);
367         RETURN(rc);
368 }
369
370 static int cat_print_cb(const struct lu_env *env, struct llog_handle *llh,
371                         struct llog_rec_hdr *rec, void *data)
372 {
373         struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
374
375         if (rec->lrh_type != LLOG_LOGID_MAGIC) {
376                 CERROR("invalid record in catalog\n");
377                 RETURN(-EINVAL);
378         }
379
380         CWARN("seeing record at index %d - "LPX64":%x in log "LPX64"\n",
381                rec->lrh_index, lir->lid_id.lgl_oid,
382                lir->lid_id.lgl_ogen, llh->lgh_id.lgl_oid);
383         RETURN(0);
384 }
385
386 static int plain_print_cb(const struct lu_env *env, struct llog_handle *llh,
387                           struct llog_rec_hdr *rec, void *data)
388 {
389         if (!(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)) {
390                 CERROR("log is not plain\n");
391                 RETURN(-EINVAL);
392         }
393
394         CWARN("seeing record at index %d in log "LPX64"\n",
395                rec->lrh_index, llh->lgh_id.lgl_oid);
396         RETURN(0);
397 }
398
399 static int llog_cancel_rec_cb(const struct lu_env *env,
400                               struct llog_handle *llh,
401                               struct llog_rec_hdr *rec, void *data)
402 {
403         struct llog_cookie cookie;
404         static int i = 0;
405
406         if (!(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)) {
407                 CERROR("log is not plain\n");
408                 RETURN(-EINVAL);
409         }
410
411         cookie.lgc_lgl = llh->lgh_id;
412         cookie.lgc_index = rec->lrh_index;
413
414         llog_cat_cancel_records(NULL, llh->u.phd.phd_cat_handle, 1, &cookie);
415         i++;
416         if (i == 40000)
417                 RETURN(-4711);
418         RETURN(0);
419 }
420
421 /* Test log and catalogue processing */
422 static int llog_test_5(struct obd_device *obd)
423 {
424         struct llog_handle *llh = NULL;
425         char name[10];
426         int rc;
427         struct llog_mini_rec lmr;
428         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
429
430         ENTRY;
431
432         lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE;
433         lmr.lmr_hdr.lrh_type = 0xf00f00;
434
435         CWARN("5a: re-open catalog by id\n");
436         rc = llog_open(NULL, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS);
437         if (rc) {
438                 CERROR("5a: llog_create with logid failed: %d\n", rc);
439                 GOTO(out, rc);
440         }
441         llog_init_handle(NULL, llh, LLOG_F_IS_CAT, &uuid);
442
443         CWARN("5b: print the catalog entries.. we expect 2\n");
444         rc = llog_process(NULL, llh, cat_print_cb, "test 5", NULL);
445         if (rc) {
446                 CERROR("5b: process with cat_print_cb failed: %d\n", rc);
447                 GOTO(out, rc);
448         }
449
450         CWARN("5c: Cancel 40000 records, see one log zapped\n");
451         rc = llog_cat_process(NULL, llh, llog_cancel_rec_cb, "foobar", 0, 0);
452         if (rc != -4711) {
453                 CERROR("5c: process with cat_cancel_cb failed: %d\n", rc);
454                 GOTO(out, rc);
455         }
456
457         CWARN("5d: add 1 record to the log with many canceled empty pages\n");
458         rc = llog_cat_add_rec(NULL, llh, &lmr.lmr_hdr, NULL, NULL);
459         if (rc) {
460                 CERROR("5d: add record to the log with many canceled empty\
461                        pages failed\n");
462                 GOTO(out, rc);
463         }
464
465         CWARN("5b: print the catalog entries.. we expect 1\n");
466         rc = llog_process(NULL, llh, cat_print_cb, "test 5", NULL);
467         if (rc) {
468                 CERROR("5b: process with cat_print_cb failed: %d\n", rc);
469                 GOTO(out, rc);
470         }
471
472         CWARN("5e: print plain log entries.. expect 6\n");
473         rc = llog_cat_process(NULL, llh, plain_print_cb, "foobar", 0, 0);
474         if (rc) {
475                 CERROR("5e: process with plain_print_cb failed: %d\n", rc);
476                 GOTO(out, rc);
477         }
478
479         CWARN("5f: print plain log entries reversely.. expect 6\n");
480         rc = llog_cat_reverse_process(NULL, llh, plain_print_cb, "foobar");
481         if (rc) {
482                 CERROR("5f: reversely process with plain_print_cb failed: %d\n", rc);
483                 GOTO(out, rc);
484         }
485
486  out:
487         CWARN("5: close re-opened catalog\n");
488         if (llh)
489                 rc = llog_cat_close(NULL, llh);
490         if (rc)
491                 CERROR("1b: close log %s failed: %d\n", name, rc);
492         llog_ctxt_put(ctxt);
493
494         RETURN(rc);
495 }
496
497 /* Test client api; open log by name and process */
498 static int llog_test_6(struct obd_device *obd, char *name)
499 {
500         struct obd_device *mgc_obd;
501         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
502         struct obd_uuid *mgs_uuid = &ctxt->loc_exp->exp_obd->obd_uuid;
503         struct obd_export *exp;
504         struct obd_uuid uuid = {"LLOG_TEST6_UUID"};
505         struct llog_handle *llh = NULL;
506         struct llog_ctxt *nctxt;
507         int rc;
508
509         CWARN("6a: re-open log %s using client API\n", name);
510         mgc_obd = class_find_client_obd(mgs_uuid, LUSTRE_MGC_NAME, NULL);
511         if (mgc_obd == NULL) {
512                 CERROR("6: no MGC devices connected to %s found.\n",
513                        mgs_uuid->uuid);
514                 GOTO(ctxt_release, rc = -ENOENT);
515         }
516
517         rc = obd_connect(NULL, &exp, mgc_obd, &uuid,
518                          NULL /* obd_connect_data */, NULL);
519         if (rc != -EALREADY) {
520                 CERROR("6: connect on connected MDC (%s) failed to return"
521                        " -EALREADY", mgc_obd->obd_name);
522                 if (rc == 0)
523                         obd_disconnect(exp);
524                 GOTO(ctxt_release, rc = -EINVAL);
525         }
526
527         nctxt = llog_get_context(mgc_obd, LLOG_CONFIG_REPL_CTXT);
528         rc = llog_open(NULL, nctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
529         if (rc) {
530                 CERROR("6: llog_create failed %d\n", rc);
531                 llog_ctxt_put(nctxt);
532                 GOTO(ctxt_release, rc);
533         }
534
535         rc = llog_init_handle(NULL, llh, LLOG_F_IS_PLAIN, NULL);
536         if (rc) {
537                 CERROR("6: llog_init_handle failed %d\n", rc);
538                 GOTO(parse_out, rc);
539         }
540
541         rc = llog_process(NULL, llh, plain_print_cb, NULL, NULL);
542         if (rc)
543                 CERROR("6: llog_process failed %d\n", rc);
544
545         rc = llog_reverse_process(NULL, llh, plain_print_cb, NULL, NULL);
546         if (rc)
547                 CERROR("6: llog_reverse_process failed %d\n", rc);
548
549 parse_out:
550         rc = llog_close(NULL, llh);
551         llog_ctxt_put(nctxt);
552         if (rc) {
553                 CERROR("6: llog_close failed: rc = %d\n", rc);
554         }
555 ctxt_release:
556         llog_ctxt_put(ctxt);
557         RETURN(rc);
558 }
559
560 static int llog_test_7(struct obd_device *obd)
561 {
562         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
563         struct llog_handle *llh;
564         struct llog_create_rec lcr;
565         char name[10];
566         int rc;
567         ENTRY;
568
569         sprintf(name, "%x", llog_test_rand+2);
570         CWARN("7: create a log with name: %s\n", name);
571         LASSERT(ctxt);
572
573         rc = llog_open_create(NULL, ctxt, &llh, NULL, name);
574         if (rc) {
575                 CERROR("7: llog_create with name %s failed: %d\n", name, rc);
576                 GOTO(ctxt_release, rc);
577         }
578         llog_init_handle(NULL, llh, LLOG_F_IS_PLAIN, &uuid);
579
580         lcr.lcr_hdr.lrh_len = lcr.lcr_tail.lrt_len = sizeof(lcr);
581         lcr.lcr_hdr.lrh_type = OST_SZ_REC;
582         rc = llog_write_rec(NULL, llh,  &lcr.lcr_hdr, NULL, 0, NULL, -1);
583         if (rc) {
584                 CERROR("7: write one log record failed: %d\n", rc);
585                 GOTO(ctxt_release, rc);
586         }
587
588         rc = llog_destroy(NULL, llh);
589         if (rc)
590                 CERROR("7: llog_destroy failed: %d\n", rc);
591         llog_close(NULL, llh);
592 ctxt_release:
593         llog_ctxt_put(ctxt);
594         RETURN(rc);
595 }
596
597 /* -------------------------------------------------------------------------
598  * Tests above, boring obd functions below
599  * ------------------------------------------------------------------------- */
600 static int llog_run_tests(struct obd_device *obd)
601 {
602         struct llog_handle *llh;
603         struct lvfs_run_ctxt saved;
604         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
605         int rc, err, cleanup_phase = 0;
606         char name[10];
607         ENTRY;
608
609         sprintf(name, "%x", llog_test_rand);
610         push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
611
612         rc = llog_test_1(obd, name);
613         if (rc)
614                 GOTO(cleanup, rc);
615
616         rc = llog_test_2(obd, name, &llh);
617         if (rc)
618                 GOTO(cleanup, rc);
619         cleanup_phase = 1; /* close llh */
620
621         rc = llog_test_3(obd, llh);
622         if (rc)
623                 GOTO(cleanup, rc);
624
625         rc = llog_test_4(obd);
626         if (rc)
627                 GOTO(cleanup, rc);
628
629         rc = llog_test_5(obd);
630         if (rc)
631                 GOTO(cleanup, rc);
632
633         rc = llog_test_6(obd, name);
634         if (rc)
635                 GOTO(cleanup, rc);
636
637         rc = llog_test_7(obd);
638         if (rc)
639                 GOTO(cleanup, rc);
640
641  cleanup:
642         switch (cleanup_phase) {
643         case 1:
644                 err = llog_close(NULL, llh);
645                 if (err)
646                         CERROR("cleanup: llog_close failed: %d\n", err);
647                 if (!rc)
648                         rc = err;
649         case 0:
650                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
651         }
652         llog_ctxt_put(ctxt);
653         return rc;
654 }
655
656 static int llog_test_llog_init(struct obd_device *obd,
657                                struct obd_llog_group *olg,
658                                struct obd_device *tgt, int *index)
659 {
660         int rc;
661         ENTRY;
662
663         rc = llog_setup(obd, &obd->obd_olg, LLOG_TEST_ORIG_CTXT, tgt, 0, NULL,
664                         &llog_lvfs_ops);
665         RETURN(rc);
666 }
667
668 static int llog_test_llog_finish(struct obd_device *obd, int count)
669 {
670         int rc;
671         ENTRY;
672
673         rc = llog_cleanup(llog_get_context(obd, LLOG_TEST_ORIG_CTXT));
674         RETURN(rc);
675 }
676 #ifdef LPROCFS
677 static struct lprocfs_vars lprocfs_llog_test_obd_vars[] = { {0} };
678 static struct lprocfs_vars lprocfs_llog_test_module_vars[] = { {0} };
679 static void lprocfs_llog_test_init_vars(struct lprocfs_static_vars *lvars)
680 {
681     lvars->module_vars  = lprocfs_llog_test_module_vars;
682     lvars->obd_vars     = lprocfs_llog_test_obd_vars;
683 }
684 #endif
685
686 static int llog_test_cleanup(struct obd_device *obd)
687 {
688         int rc = obd_llog_finish(obd, 0);
689         if (rc)
690                 CERROR("failed to llog_test_llog_finish: %d\n", rc);
691
692         lprocfs_obd_cleanup(obd);
693
694         return rc;
695 }
696
697 static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
698 {
699         struct lprocfs_static_vars lvars;
700         struct obd_device *tgt;
701         int rc;
702         ENTRY;
703
704         if (lcfg->lcfg_bufcount < 2) {
705                 CERROR("requires a TARGET OBD name\n");
706                 RETURN(-EINVAL);
707         }
708
709         if (lcfg->lcfg_buflens[1] < 1) {
710                 CERROR("requires a TARGET OBD name\n");
711                 RETURN(-EINVAL);
712         }
713
714         /* disk obd */
715         tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
716         if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
717                 CERROR("target device not attached or not set up (%s)\n",
718                        lustre_cfg_string(lcfg, 1));
719                 RETURN(-EINVAL);
720         }
721
722         rc = obd_llog_init(obd, NULL, tgt, NULL);
723         if (rc)
724                 RETURN(rc);
725
726         llog_test_rand = cfs_rand();
727
728         rc = llog_run_tests(obd);
729         if (rc)
730                 llog_test_cleanup(obd);
731
732         lprocfs_llog_test_init_vars(&lvars);
733         lprocfs_obd_setup(obd, lvars.obd_vars);
734
735         RETURN(rc);
736 }
737
738 static struct obd_ops llog_obd_ops = {
739         .o_owner       = THIS_MODULE,
740         .o_setup       = llog_test_setup,
741         .o_cleanup     = llog_test_cleanup,
742         .o_llog_init   = llog_test_llog_init,
743         .o_llog_finish = llog_test_llog_finish,
744 };
745
746 static int __init llog_test_init(void)
747 {
748         struct lprocfs_static_vars lvars;
749
750         lprocfs_llog_test_init_vars(&lvars);
751         return class_register_type(&llog_obd_ops, NULL,
752                                    lvars.module_vars,"llog_test", NULL);
753 }
754
755 static void __exit llog_test_exit(void)
756 {
757         class_unregister_type("llog_test");
758 }
759
760 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
761 MODULE_DESCRIPTION("llog test module");
762 MODULE_LICENSE("GPL");
763
764 module_init(llog_test_init);
765 module_exit(llog_test_exit);