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