Whamcloud - gitweb
a2a1d91b5e8f2fc4e7e3bc0f36c416a4b037391a
[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         RETURN(rc);
242 }
243
244 /* Test catalogue additions */
245 static int llog_test_4(struct obd_device *obd)
246 {
247         struct llog_handle *cath;
248         char name[10];
249         int rc, i, buflen;
250         struct llog_mini_rec lmr;
251         struct llog_cookie cookie;
252         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
253         int num_recs = 0;
254         char *buf;
255         struct llog_rec_hdr rec;
256
257         ENTRY;
258
259         lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE;
260         lmr.lmr_hdr.lrh_type = 0xf00f00;
261
262         sprintf(name, "%x", llog_test_rand+1);
263         CWARN("4a: create a catalog log with name: %s\n", name);
264         rc = llog_create(ctxt, &cath, NULL, name);
265         if (rc) {
266                 CERROR("1a: llog_create with name %s failed: %d\n", name, rc);
267                 GOTO(out, rc);
268         }
269         llog_init_handle(cath, LLOG_F_IS_CAT, &uuid);
270         num_recs++;
271         cat_logid = cath->lgh_id;
272
273         CWARN("4b: write 1 record into the catalog\n");
274         rc = llog_cat_add_rec(cath, &lmr.lmr_hdr, &cookie, NULL);
275         if (rc != 1) {
276                 CERROR("4b: write 1 catalog record failed at: %d\n", rc);
277                 GOTO(out, rc);
278         }
279         num_recs++;
280         if ((rc = verify_handle("4b", cath, 2)))
281                 GOTO(ctxt_release, rc);
282
283         if ((rc = verify_handle("4b", cath->u.chd.chd_current_log, num_recs)))
284                 GOTO(ctxt_release, rc);
285
286         CWARN("4c: cancel 1 log record\n");
287         rc = llog_cat_cancel_records(cath, 1, &cookie);
288         if (rc) {
289                 CERROR("4c: cancel 1 catalog based record failed: %d\n", rc);
290                 GOTO(out, rc);
291         }
292         num_recs--;
293
294         if ((rc = verify_handle("4c", cath->u.chd.chd_current_log, num_recs)))
295                 GOTO(ctxt_release, rc);
296
297         CWARN("4d: write 40,000 more log records\n");
298         for (i = 0; i < 40000; i++) {
299                 rc = llog_cat_add_rec(cath, &lmr.lmr_hdr, NULL, NULL);
300                 if (rc) {
301                         CERROR("4d: write 40000 records failed at #%d: %d\n",
302                                i + 1, rc);
303                         GOTO(out, rc);
304                 }
305                 num_recs++;
306         }
307
308         CWARN("4e: add 5 large records, one record per block\n");
309         buflen = LLOG_CHUNK_SIZE - sizeof(struct llog_rec_hdr)
310                         - sizeof(struct llog_rec_tail);
311         OBD_ALLOC(buf, buflen);
312         if (buf == NULL)
313                 GOTO(out, rc = -ENOMEM);
314         for (i = 0; i < 5; i++) {
315                 rec.lrh_len = buflen;
316                 rec.lrh_type = OBD_CFG_REC;
317                 rc = llog_cat_add_rec(cath, &rec, NULL, buf);
318                 if (rc) {
319                         CERROR("4e: write 5 records failed at #%d: %d\n",
320                                i + 1, rc);
321                         OBD_FREE(buf, buflen);
322                         GOTO(out, rc);
323                 }
324                 num_recs++;
325         }
326         OBD_FREE(buf, buflen);
327
328  out:
329         CWARN("4f: put newly-created catalog\n");
330         rc = llog_cat_put(cath);
331 ctxt_release:
332         llog_ctxt_put(ctxt);
333         if (rc)
334                 CERROR("1b: close log %s failed: %d\n", name, rc);
335         RETURN(rc);
336 }
337
338 static int cat_print_cb(struct llog_handle *llh, struct llog_rec_hdr *rec,
339                         void *data)
340 {
341         struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
342
343         if (rec->lrh_type != LLOG_LOGID_MAGIC) {
344                 CERROR("invalid record in catalog\n");
345                 RETURN(-EINVAL);
346         }
347
348         CWARN("seeing record at index %d - "LPX64":%x in log "LPX64"\n",
349                rec->lrh_index, lir->lid_id.lgl_oid,
350                lir->lid_id.lgl_ogen, llh->lgh_id.lgl_oid);
351         RETURN(0);
352 }
353
354 static int plain_print_cb(struct llog_handle *llh, struct llog_rec_hdr *rec,
355                           void *data)
356 {
357         if (!(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)) {
358                 CERROR("log is not plain\n");
359                 RETURN(-EINVAL);
360         }
361
362         CWARN("seeing record at index %d in log "LPX64"\n",
363                rec->lrh_index, llh->lgh_id.lgl_oid);
364         RETURN(0);
365 }
366
367 static int llog_cancel_rec_cb(struct llog_handle *llh, struct llog_rec_hdr *rec,
368                               void *data)
369 {
370         struct llog_cookie cookie;
371         static int i = 0;
372
373         if (!(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)) {
374                 CERROR("log is not plain\n");
375                 RETURN(-EINVAL);
376         }
377
378         cookie.lgc_lgl = llh->lgh_id;
379         cookie.lgc_index = rec->lrh_index;
380
381         llog_cat_cancel_records(llh->u.phd.phd_cat_handle, 1, &cookie);
382         i++;
383         if (i == 40000)
384                 RETURN(-4711);
385         RETURN(0);
386 }
387
388 /* Test log and catalogue processing */
389 static int llog_test_5(struct obd_device *obd)
390 {
391         struct llog_handle *llh = NULL;
392         char name[10];
393         int rc;
394         struct llog_mini_rec lmr;
395         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
396
397         ENTRY;
398
399         lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE;
400         lmr.lmr_hdr.lrh_type = 0xf00f00;
401
402         CWARN("5a: re-open catalog by id\n");
403         rc = llog_create(ctxt, &llh, &cat_logid, NULL);
404         if (rc) {
405                 CERROR("5a: llog_create with logid failed: %d\n", rc);
406                 GOTO(out, rc);
407         }
408         llog_init_handle(llh, LLOG_F_IS_CAT, &uuid);
409
410         CWARN("5b: print the catalog entries.. we expect 2\n");
411         rc = llog_process(llh, cat_print_cb, "test 5", NULL);
412         if (rc) {
413                 CERROR("5b: process with cat_print_cb failed: %d\n", rc);
414                 GOTO(out, rc);
415         }
416
417         CWARN("5c: Cancel 40000 records, see one log zapped\n");
418         rc = llog_cat_process(llh, llog_cancel_rec_cb, "foobar");
419         if (rc != -4711) {
420                 CERROR("5c: process with cat_cancel_cb failed: %d\n", rc);
421                 GOTO(out, rc);
422         }
423
424         CWARN("5d: add 1 record to the log with many canceled empty pages\n");
425         rc = llog_cat_add_rec(llh, &lmr.lmr_hdr, NULL, NULL);
426         if (rc) {
427                 CERROR("5d: add record to the log with many canceled empty\
428                        pages failed\n");
429                 GOTO(out, rc);
430         }
431
432         CWARN("5b: print the catalog entries.. we expect 1\n");
433         rc = llog_process(llh, cat_print_cb, "test 5", NULL);
434         if (rc) {
435                 CERROR("5b: process with cat_print_cb failed: %d\n", rc);
436                 GOTO(out, rc);
437         }
438
439         CWARN("5e: print plain log entries.. expect 6\n");
440         rc = llog_cat_process(llh, plain_print_cb, "foobar");
441         if (rc) {
442                 CERROR("5e: process with plain_print_cb failed: %d\n", rc);
443                 GOTO(out, rc);
444         }
445
446         CWARN("5f: print plain log entries reversely.. expect 6\n");
447         rc = llog_cat_reverse_process(llh, plain_print_cb, "foobar");
448         if (rc) {
449                 CERROR("5f: reversely process with plain_print_cb failed: %d\n", rc);
450                 GOTO(out, rc);
451         }
452
453  out:
454         CWARN("5: close re-opened catalog\n");
455         if (llh)
456                 rc = llog_cat_put(llh);
457         if (rc)
458                 CERROR("1b: close log %s failed: %d\n", name, rc);
459         llog_ctxt_put(ctxt);
460
461         RETURN(rc);
462 }
463
464 /* Test client api; open log by name and process */
465 static int llog_test_6(struct obd_device *obd, char *name)
466 {
467         struct obd_device *mdc_obd;
468         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
469         struct obd_uuid *mds_uuid = &ctxt->loc_exp->exp_obd->obd_uuid;
470         struct lustre_handle exph = {0, };
471         struct obd_export *exp;
472         struct obd_uuid uuid = {"LLOG_TEST6_UUID"};
473         struct llog_handle *llh = NULL;
474         struct llog_ctxt *nctxt;
475         int rc;
476
477         CWARN("6a: re-open log %s using client API\n", name);
478         mdc_obd = class_find_client_obd(mds_uuid, LUSTRE_MDC_NAME, NULL);
479         if (mdc_obd == NULL) {
480                 CERROR("6: no MDC devices connected to %s found.\n",
481                        mds_uuid->uuid);
482                 GOTO(ctxt_release, rc = -ENOENT);
483         }
484
485         rc = obd_connect(NULL, &exph, mdc_obd, &uuid,
486                          NULL /* obd_connect_data */, NULL);
487         if (rc) {
488                 CERROR("6: failed to connect to MDC: %s\n", mdc_obd->obd_name);
489                 GOTO(ctxt_release, rc);
490         }
491         exp = class_conn2export(&exph);
492
493         nctxt = llog_get_context(mdc_obd, LLOG_CONFIG_REPL_CTXT);
494         rc = llog_create(nctxt, &llh, NULL, name);
495         if (rc) {
496                 CERROR("6: llog_create failed %d\n", rc);
497                 llog_ctxt_put(nctxt);
498                 GOTO(ctxt_release, rc);
499         }
500
501         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
502         if (rc) {
503                 CERROR("6: llog_init_handle failed %d\n", rc);
504                 GOTO(parse_out, rc);
505         }
506
507         rc = llog_process(llh, plain_print_cb, NULL, NULL);
508         if (rc)
509                 CERROR("6: llog_process failed %d\n", rc);
510
511         rc = llog_reverse_process(llh, plain_print_cb, NULL, NULL);
512         if (rc)
513                 CERROR("6: llog_reverse_process failed %d\n", rc);
514
515 parse_out:
516         rc = llog_close(llh);
517         llog_ctxt_put(nctxt);
518         if (rc) {
519                 CERROR("6: llog_close failed: rc = %d\n", rc);
520         }
521         rc = obd_disconnect(exp);
522 ctxt_release:
523         llog_ctxt_put(ctxt);
524         RETURN(rc);
525 }
526
527 static int llog_test_7(struct obd_device *obd)
528 {
529         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
530         struct llog_handle *llh;
531         struct llog_create_rec lcr;
532         char name[10];
533         int rc;
534         ENTRY;
535
536         sprintf(name, "%x", llog_test_rand+2);
537         CWARN("7: create a log with name: %s\n", name);
538         LASSERT(ctxt);
539
540         rc = llog_create(ctxt, &llh, NULL, name);
541         if (rc) {
542                 CERROR("7: llog_create with name %s failed: %d\n", name, rc);
543                 GOTO(ctxt_release, rc);
544         }
545         llog_init_handle(llh, LLOG_F_IS_PLAIN, &uuid);
546
547         lcr.lcr_hdr.lrh_len = lcr.lcr_tail.lrt_len = sizeof(lcr);
548         lcr.lcr_hdr.lrh_type = OST_SZ_REC;
549         rc = llog_write_rec(llh,  &lcr.lcr_hdr, NULL, 0, NULL, -1);
550         if (rc) {
551                 CERROR("7: write one log record failed: %d\n", rc);
552                 GOTO(ctxt_release, rc);
553         }
554
555         rc = llog_destroy(llh);
556         if (rc)
557                 CERROR("7: llog_destroy failed: %d\n", rc);
558         else
559                 llog_free_handle(llh);
560 ctxt_release:
561         llog_ctxt_put(ctxt);
562         RETURN(rc);
563 }
564
565 /* -------------------------------------------------------------------------
566  * Tests above, boring obd functions below
567  * ------------------------------------------------------------------------- */
568 static int llog_run_tests(struct obd_device *obd)
569 {
570         struct llog_handle *llh;
571         struct lvfs_run_ctxt saved;
572         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
573         int rc, err, cleanup_phase = 0;
574         char name[10];
575         ENTRY;
576
577         sprintf(name, "%x", llog_test_rand);
578         push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
579
580         rc = llog_test_1(obd, name);
581         if (rc)
582                 GOTO(cleanup, rc);
583
584         rc = llog_test_2(obd, name, &llh);
585         if (rc)
586                 GOTO(cleanup, rc);
587         cleanup_phase = 1; /* close llh */
588
589         rc = llog_test_3(obd, llh);
590         if (rc)
591                 GOTO(cleanup, rc);
592
593         rc = llog_test_4(obd);
594         if (rc)
595                 GOTO(cleanup, rc);
596
597         rc = llog_test_5(obd);
598         if (rc)
599                 GOTO(cleanup, rc);
600
601         rc = llog_test_6(obd, name);
602         if (rc)
603                 GOTO(cleanup, rc);
604
605         rc = llog_test_7(obd);
606         if (rc)
607                 GOTO(cleanup, rc);
608
609  cleanup:
610         switch (cleanup_phase) {
611         case 1:
612                 err = llog_close(llh);
613                 if (err)
614                         CERROR("cleanup: llog_close failed: %d\n", err);
615                 if (!rc)
616                         rc = err;
617         case 0:
618                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
619         }
620         llog_ctxt_put(ctxt);
621         return rc;
622 }
623
624
625 static int llog_test_llog_init(struct obd_device *obd,
626                                struct obd_llog_group *olg,
627                                struct obd_device *tgt, int count,
628                                struct llog_catid *logid, struct obd_uuid *uuid)
629 {
630         int rc;
631         ENTRY;
632
633         rc = llog_setup(obd, &obd->obd_olg, LLOG_TEST_ORIG_CTXT, tgt, 0, NULL,
634                         &llog_lvfs_ops);
635         RETURN(rc);
636 }
637
638 static int llog_test_llog_finish(struct obd_device *obd, int count)
639 {
640         int rc;
641         ENTRY;
642
643         rc = llog_cleanup(llog_get_context(obd, LLOG_TEST_ORIG_CTXT));
644         RETURN(rc);
645 }
646 #ifdef LPROCFS
647 static struct lprocfs_vars lprocfs_llog_test_obd_vars[] = { {0} };
648 static struct lprocfs_vars lprocfs_llog_test_module_vars[] = { {0} };
649 static void lprocfs_llog_test_init_vars(struct lprocfs_static_vars *lvars)
650 {
651     lvars->module_vars  = lprocfs_llog_test_module_vars;
652     lvars->obd_vars     = lprocfs_llog_test_obd_vars;
653 }
654 #endif
655
656 static int llog_test_cleanup(struct obd_device *obd)
657 {
658         int rc = obd_llog_finish(obd, 0);
659         if (rc)
660                 CERROR("failed to llog_test_llog_finish: %d\n", rc);
661
662         lprocfs_obd_cleanup(obd);
663
664         return rc;
665 }
666
667 static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
668 {
669         struct lprocfs_static_vars lvars;
670         struct obd_device *tgt;
671         int rc;
672         ENTRY;
673
674         if (lcfg->lcfg_bufcount < 2) {
675                 CERROR("requires a TARGET OBD name\n");
676                 RETURN(-EINVAL);
677         }
678
679         if (lcfg->lcfg_buflens[1] < 1) {
680                 CERROR("requires a TARGET OBD name\n");
681                 RETURN(-EINVAL);
682         }
683
684         tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
685         if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
686                 CERROR("target device not attached or not set up (%s)\n",
687                        lustre_cfg_string(lcfg, 1));
688                 RETURN(-EINVAL);
689         }
690
691         rc = obd_llog_init(obd, OBD_LLOG_GROUP, tgt, 0, NULL, NULL);
692         if (rc)
693                 RETURN(rc);
694
695         llog_test_rand = ll_rand();
696
697         rc = llog_run_tests(obd);
698         if (rc)
699                 llog_test_cleanup(obd);
700
701         lprocfs_llog_test_init_vars(&lvars);
702         lprocfs_obd_setup(obd, lvars.obd_vars);
703
704         RETURN(rc);
705 }
706
707 static struct obd_ops llog_obd_ops = {
708         .o_owner       = THIS_MODULE,
709         .o_setup       = llog_test_setup,
710         .o_cleanup     = llog_test_cleanup,
711         .o_llog_init   = llog_test_llog_init,
712         .o_llog_finish = llog_test_llog_finish,
713 };
714
715 static int __init llog_test_init(void)
716 {
717         struct lprocfs_static_vars lvars;
718
719         lprocfs_llog_test_init_vars(&lvars);
720         return class_register_type(&llog_obd_ops, NULL,
721                                    lvars.module_vars,"llog_test", NULL);
722 }
723
724 static void __exit llog_test_exit(void)
725 {
726         class_unregister_type("llog_test");
727 }
728
729 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
730 MODULE_DESCRIPTION("llog test module");
731 MODULE_LICENSE("GPL");
732
733 module_init(llog_test_init);
734 module_exit(llog_test_exit);