Whamcloud - gitweb
b=21147 be tolerant to setting the same type and version of quota
[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 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         mdc_obd = class_find_client_obd(mds_uuid, LUSTRE_MDC_NAME, NULL);
511         if (mdc_obd == NULL) {
512                 CERROR("6: no MDC devices connected to %s found.\n",
513                        mds_uuid->uuid);
514                 GOTO(ctxt_release, rc = -ENOENT);
515         }
516
517         nctxt = llog_get_context(mdc_obd, LLOG_CONFIG_REPL_CTXT);
518         rc = llog_create(nctxt, &llh, NULL, name);
519         if (rc) {
520                 CERROR("6: llog_create failed %d\n", rc);
521                 llog_ctxt_put(nctxt);
522                 GOTO(ctxt_release, rc);
523         }
524
525         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
526         if (rc) {
527                 CERROR("6: llog_init_handle failed %d\n", rc);
528                 GOTO(parse_out, rc);
529         }
530
531         rc = llog_process(llh, plain_print_cb, NULL, NULL);
532         if (rc)
533                 CERROR("6: llog_process failed %d\n", rc);
534
535         rc = llog_reverse_process(llh, plain_print_cb, NULL, NULL);
536         if (rc)
537                 CERROR("6: llog_reverse_process failed %d\n", rc);
538
539 parse_out:
540         rc = llog_close(llh);
541         llog_ctxt_put(nctxt);
542         if (rc) {
543                 CERROR("6: llog_close failed: rc = %d\n", rc);
544         }
545
546 ctxt_release:
547         llog_ctxt_put(ctxt);
548         RETURN(rc);
549 }
550
551 static int llog_test_7(struct obd_device *obd)
552 {
553         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
554         struct llog_handle *llh;
555         struct llog_create_rec lcr;
556         char name[10];
557         int rc;
558         ENTRY;
559
560         sprintf(name, "%x", llog_test_rand+2);
561         CWARN("7: create a log with name: %s\n", name);
562         LASSERT(ctxt);
563
564         rc = llog_create(ctxt, &llh, NULL, name);
565         if (rc) {
566                 CERROR("7: llog_create with name %s failed: %d\n", name, rc);
567                 GOTO(ctxt_release, rc);
568         }
569         llog_init_handle(llh, LLOG_F_IS_PLAIN, &uuid);
570
571         lcr.lcr_hdr.lrh_len = lcr.lcr_tail.lrt_len = sizeof(lcr);
572         lcr.lcr_hdr.lrh_type = OST_SZ_REC;
573         rc = llog_write_rec(llh,  &lcr.lcr_hdr, NULL, 0, NULL, -1);
574         if (rc) {
575                 CERROR("7: write one log record failed: %d\n", rc);
576                 GOTO(ctxt_release, rc);
577         }
578
579         rc = llog_destroy(llh);
580         if (rc) 
581                 CERROR("7: llog_destroy failed: %d\n", rc);
582         else
583                 llog_free_handle(llh); 
584 ctxt_release:
585         llog_ctxt_put(ctxt);
586         RETURN(rc);
587 }
588
589 /* -------------------------------------------------------------------------
590  * Tests above, boring obd functions below
591  * ------------------------------------------------------------------------- */
592 static int llog_run_tests(struct obd_device *obd)
593 {
594         struct llog_handle *llh;
595         struct lvfs_run_ctxt saved;
596         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
597         int rc, err, cleanup_phase = 0;
598         char name[10];
599         ENTRY;
600
601         sprintf(name, "%x", llog_test_rand);
602         push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
603
604         rc = llog_test_1(obd, name);
605         if (rc)
606                 GOTO(cleanup, rc);
607
608         rc = llog_test_2(obd, name, &llh);
609         if (rc)
610                 GOTO(cleanup, rc);
611         cleanup_phase = 1; /* close llh */
612
613         rc = llog_test_3(obd, llh);
614         if (rc)
615                 GOTO(cleanup, rc);
616
617         rc = llog_test_4(obd);
618         if (rc)
619                 GOTO(cleanup, rc);
620
621         rc = llog_test_5(obd);
622         if (rc)
623                 GOTO(cleanup, rc);
624
625         rc = llog_test_6(obd, name);
626         if (rc)
627                 GOTO(cleanup, rc);
628
629         rc = llog_test_7(obd);
630         if (rc)
631                 GOTO(cleanup, rc);
632
633  cleanup:
634         switch (cleanup_phase) {
635         case 1:
636                 err = llog_close(llh);
637                 if (err)
638                         CERROR("cleanup: llog_close failed: %d\n", err);
639                 if (!rc)
640                         rc = err;
641         case 0:
642                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
643         }
644         llog_ctxt_put(ctxt);
645         return rc;
646 }
647
648
649 static int llog_test_llog_init(struct obd_device *obd, struct obd_device *disk_obd,
650                                int *index)
651 {
652         int rc;
653         ENTRY;
654
655         rc = llog_setup(obd, LLOG_TEST_ORIG_CTXT, disk_obd, 0, NULL, &llog_lvfs_ops);
656         RETURN(rc);
657 }
658
659 static int llog_test_llog_finish(struct obd_device *obd, int count)
660 {
661         int rc;
662         ENTRY;
663
664         rc = llog_cleanup(llog_get_context(obd, LLOG_TEST_ORIG_CTXT));
665         RETURN(rc);
666 }
667
668 static int llog_test_cleanup(struct obd_device *obd)
669 {
670         int rc = obd_llog_finish(obd, 0);
671         if (rc)
672                 CERROR("failed to llog_test_llog_finish: %d\n", rc);
673
674         lprocfs_obd_cleanup(obd);
675
676         return rc;
677 }
678
679 #ifdef LPROCFS
680 static struct lprocfs_vars lprocfs_llog_test_obd_vars[] = { {0} };
681 static struct lprocfs_vars lprocfs_llog_test_module_vars[] = { {0} };
682 static void lprocfs_llog_test_init_vars(struct lprocfs_static_vars *lvars)
683 {
684     lvars->module_vars  = lprocfs_llog_test_module_vars;
685     lvars->obd_vars     = lprocfs_llog_test_obd_vars;
686 }
687 #endif
688
689 static int llog_test_setup(struct obd_device *obd, obd_count len, void *buf)
690 {
691         struct lprocfs_static_vars lvars;
692         struct lustre_cfg *lcfg = buf;
693         struct obd_device *tgt;
694         int rc;
695         ENTRY;
696
697         if (lcfg->lcfg_bufcount < 2) {
698                 CERROR("requires a TARGET OBD name\n");
699                 RETURN(-EINVAL);
700         }
701
702         if (lcfg->lcfg_buflens[1] < 1) {
703                 CERROR("requires a TARGET OBD name\n");
704                 RETURN(-EINVAL);
705         }
706
707         tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
708         if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
709                 CERROR("target device not attached or not set up (%s)\n",
710                        lustre_cfg_string(lcfg, 1));
711                 RETURN(-EINVAL);
712         }
713
714         rc = obd_llog_init(obd, tgt, NULL);
715         if (rc)
716                 RETURN(rc);
717
718         llog_test_rand = ll_rand();
719
720         rc = llog_run_tests(obd);
721         if (rc)
722                 llog_test_cleanup(obd);
723
724         lprocfs_llog_test_init_vars(&lvars);
725         lprocfs_obd_setup(obd, lvars.obd_vars);
726
727         RETURN(rc);
728 }
729
730 static struct obd_ops llog_obd_ops = {
731         .o_owner       = THIS_MODULE,
732         .o_setup       = llog_test_setup,
733         .o_cleanup     = llog_test_cleanup,
734         .o_llog_init   = llog_test_llog_init,
735         .o_llog_finish = llog_test_llog_finish,
736 };
737
738 static int __init llog_test_init(void)
739 {
740         struct lprocfs_static_vars lvars;
741
742         lprocfs_llog_test_init_vars(&lvars);
743         return class_register_type(&llog_obd_ops,lvars.module_vars,"llog_test");
744 }
745
746 static void __exit llog_test_exit(void)
747 {
748         class_unregister_type("llog_test");
749 }
750
751 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
752 MODULE_DESCRIPTION("llog test module");
753 MODULE_LICENSE("GPL");
754
755 module_init(llog_test_init);
756 module_exit(llog_test_exit);