Whamcloud - gitweb
c72d2e1e55ca73d85382de53bc242703758c9627
[fs/lustre-release.git] / lustre / ptlrpc / llog_server.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  * Copyright (c) 2011, Whamcloud, Inc.
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/ptlrpc/llog_server.c
37  *
38  * remote api for llog - server side
39  *
40  * Author: Andreas Dilger <adilger@clusterfs.com>
41  */
42
43 #define DEBUG_SUBSYSTEM S_LOG
44
45 #ifndef __KERNEL__
46 #include <liblustre.h>
47 #endif
48
49 #include <obd_class.h>
50 #include <lustre_log.h>
51 #include <lustre_net.h>
52 #include <libcfs/list.h>
53 #include <lustre_fsfilt.h>
54
55 #if defined(__KERNEL__) && defined(LUSTRE_LOG_SERVER)
56
57 int llog_origin_handle_create(struct ptlrpc_request *req)
58 {
59         struct obd_export    *exp = req->rq_export;
60         struct obd_device    *obd = exp->exp_obd;
61         struct obd_device    *disk_obd;
62         struct llog_handle   *loghandle;
63         struct llogd_body    *body;
64         struct lvfs_run_ctxt  saved;
65         struct llog_logid    *logid = NULL;
66         struct llog_ctxt     *ctxt;
67         char                 *name = NULL;
68         int                   rc, rc2;
69         ENTRY;
70
71         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
72         if (body == NULL)
73                 RETURN(-EFAULT);
74
75         if (body->lgd_logid.lgl_oid > 0)
76                 logid = &body->lgd_logid;
77
78         if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) {
79                 name = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
80                 if (name == NULL)
81                         RETURN(-EFAULT);
82                 CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name);
83         }
84
85         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
86         if (ctxt == NULL) {
87                 CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n",
88                        obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name);
89                 RETURN(-ENODEV);
90         }
91         disk_obd = ctxt->loc_exp->exp_obd;
92         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
93
94         rc = llog_create(ctxt, &loghandle, logid, name);
95         if (rc)
96                 GOTO(out_pop, rc);
97
98         rc = req_capsule_server_pack(&req->rq_pill);
99         if (rc)
100                 GOTO(out_close, rc = -ENOMEM);
101
102         body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
103         body->lgd_logid = loghandle->lgh_id;
104
105         GOTO(out_close, rc);
106 out_close:
107         rc2 = llog_close(loghandle);
108         if (!rc)
109                 rc = rc2;
110 out_pop:
111         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
112         llog_ctxt_put(ctxt);
113         return rc;
114 }
115
116 int llog_origin_handle_destroy(struct ptlrpc_request *req)
117 {
118         struct obd_export    *exp = req->rq_export;
119         struct obd_device    *obd = exp->exp_obd;
120         struct obd_device    *disk_obd;
121         struct llog_handle   *loghandle;
122         struct llogd_body    *body;
123         struct lvfs_run_ctxt  saved;
124         struct llog_logid    *logid = NULL;
125         struct llog_ctxt     *ctxt;
126         int                   rc;
127         ENTRY;
128
129         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
130         if (body == NULL)
131                 RETURN(-EFAULT);
132
133         if (body->lgd_logid.lgl_oid > 0)
134                 logid = &body->lgd_logid;
135
136         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
137         if (ctxt == NULL)
138                 RETURN(-ENODEV);
139
140         disk_obd = ctxt->loc_exp->exp_obd;
141         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
142
143         rc = llog_create(ctxt, &loghandle, logid, NULL);
144         if (rc)
145                 GOTO(out_pop, rc);
146
147         rc = req_capsule_server_pack(&req->rq_pill);
148         if (rc)
149                 GOTO(out_close, rc = -ENOMEM);
150
151         body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
152         body->lgd_logid = loghandle->lgh_id;
153         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
154         if (rc)
155                 GOTO(out_close, rc);
156         rc = llog_destroy(loghandle);
157         if (rc)
158                 GOTO(out_close, rc);
159         llog_free_handle(loghandle);
160         GOTO(out_close, rc);
161 out_close:
162         if (rc)
163                 llog_close(loghandle);
164 out_pop:
165         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
166         llog_ctxt_put(ctxt);
167         return rc;
168 }
169
170 int llog_origin_handle_next_block(struct ptlrpc_request *req)
171 {
172         struct obd_export   *exp = req->rq_export;
173         struct obd_device   *obd = exp->exp_obd;
174         struct obd_device   *disk_obd;
175         struct llog_handle  *loghandle;
176         struct llogd_body   *body;
177         struct llogd_body   *repbody;
178         struct lvfs_run_ctxt saved;
179         struct llog_ctxt    *ctxt;
180         __u32                flags;
181         __u8                *buf;
182         void                *ptr;
183         int                  rc, rc2;
184         ENTRY;
185
186         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
187         if (body == NULL)
188                 RETURN(-EFAULT);
189
190         OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
191         if (!buf)
192                 RETURN(-ENOMEM);
193
194         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
195         if (ctxt == NULL)
196                 GOTO(out_free, rc = -ENODEV);
197         disk_obd = ctxt->loc_exp->exp_obd;
198         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
199
200         rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
201         if (rc)
202                 GOTO(out_pop, rc);
203
204         flags = body->lgd_llh_flags;
205         rc = llog_init_handle(loghandle, flags, NULL);
206         if (rc)
207                 GOTO(out_close, rc);
208
209         memset(buf, 0, LLOG_CHUNK_SIZE);
210         rc = llog_next_block(loghandle, &body->lgd_saved_index,
211                              body->lgd_index,
212                              &body->lgd_cur_offset, buf, LLOG_CHUNK_SIZE);
213         if (rc)
214                 GOTO(out_close, rc);
215
216         req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER,
217                              LLOG_CHUNK_SIZE);
218         rc = req_capsule_server_pack(&req->rq_pill);
219         if (rc)
220                 GOTO(out_close, rc = -ENOMEM);
221
222         repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
223         *repbody = *body;
224
225         ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
226         memcpy(ptr, buf, LLOG_CHUNK_SIZE);
227         GOTO(out_close, rc);
228 out_close:
229         rc2 = llog_close(loghandle);
230         if (!rc)
231                 rc = rc2;
232 out_pop:
233         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
234         llog_ctxt_put(ctxt);
235 out_free:
236         OBD_FREE(buf, LLOG_CHUNK_SIZE);
237         return rc;
238 }
239
240 int llog_origin_handle_prev_block(struct ptlrpc_request *req)
241 {
242         struct obd_export    *exp = req->rq_export;
243         struct obd_device    *obd = exp->exp_obd;
244         struct llog_handle   *loghandle;
245         struct llogd_body    *body;
246         struct llogd_body    *repbody;
247         struct obd_device    *disk_obd;
248         struct lvfs_run_ctxt  saved;
249         struct llog_ctxt     *ctxt;
250         __u32                 flags;
251         __u8                 *buf;
252         void                 *ptr;
253         int                   rc, rc2;
254         ENTRY;
255
256         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
257         if (body == NULL)
258                 RETURN(-EFAULT);
259
260         OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
261         if (!buf)
262                 RETURN(-ENOMEM);
263
264         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
265         if (ctxt == NULL)
266                 GOTO(out_free, rc = -ENODEV);
267
268         disk_obd = ctxt->loc_exp->exp_obd;
269         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
270
271         rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
272         if (rc)
273                 GOTO(out_pop, rc);
274
275         flags = body->lgd_llh_flags;
276         rc = llog_init_handle(loghandle, flags, NULL);
277         if (rc)
278                 GOTO(out_close, rc);
279
280         memset(buf, 0, LLOG_CHUNK_SIZE);
281         rc = llog_prev_block(loghandle, body->lgd_index,
282                              buf, LLOG_CHUNK_SIZE);
283         if (rc)
284                 GOTO(out_close, rc);
285
286         req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER,
287                              LLOG_CHUNK_SIZE);
288         rc = req_capsule_server_pack(&req->rq_pill);
289         if (rc)
290                 GOTO(out_close, rc = -ENOMEM);
291
292         repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
293         *repbody = *body;
294
295         ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
296         memcpy(ptr, buf, LLOG_CHUNK_SIZE);
297         GOTO(out_close, rc);
298 out_close:
299         rc2 = llog_close(loghandle);
300         if (!rc)
301                 rc = rc2;
302
303 out_pop:
304         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
305         llog_ctxt_put(ctxt);
306 out_free:
307         OBD_FREE(buf, LLOG_CHUNK_SIZE);
308         return rc;
309 }
310
311 int llog_origin_handle_read_header(struct ptlrpc_request *req)
312 {
313         struct obd_export    *exp = req->rq_export;
314         struct obd_device    *obd = exp->exp_obd;
315         struct obd_device    *disk_obd;
316         struct llog_handle   *loghandle;
317         struct llogd_body    *body;
318         struct llog_log_hdr  *hdr;
319         struct lvfs_run_ctxt  saved;
320         struct llog_ctxt     *ctxt;
321         __u32                 flags;
322         int                   rc, rc2;
323         ENTRY;
324
325         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
326         if (body == NULL)
327                 RETURN(-EFAULT);
328
329         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
330         if (ctxt == NULL)
331                 RETURN(-ENODEV);
332
333         disk_obd = ctxt->loc_exp->exp_obd;
334         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
335
336         rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
337         if (rc)
338                 GOTO(out_pop, rc);
339
340         /*
341          * llog_init_handle() reads the llog header
342          */
343         flags = body->lgd_llh_flags;
344         rc = llog_init_handle(loghandle, flags, NULL);
345         if (rc)
346                 GOTO(out_close, rc);
347
348         rc = req_capsule_server_pack(&req->rq_pill);
349         if (rc)
350                 GOTO(out_close, rc = -ENOMEM);
351
352         hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
353         *hdr = *loghandle->lgh_hdr;
354         GOTO(out_close, rc);
355 out_close:
356         rc2 = llog_close(loghandle);
357         if (!rc)
358                 rc = rc2;
359 out_pop:
360         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
361         llog_ctxt_put(ctxt);
362         return rc;
363 }
364
365 int llog_origin_handle_close(struct ptlrpc_request *req)
366 {
367         ENTRY;
368         /* Nothing to do */
369         RETURN(0);
370 }
371
372 int llog_origin_handle_cancel(struct ptlrpc_request *req)
373 {
374         struct obd_device *obd = req->rq_export->exp_obd;
375         int num_cookies, rc = 0, err, i, failed = 0;
376         struct obd_device *disk_obd;
377         struct llog_cookie *logcookies;
378         struct llog_ctxt *ctxt = NULL;
379         struct lvfs_run_ctxt saved;
380         struct llog_handle *cathandle;
381         struct inode *inode;
382         void *handle;
383         ENTRY;
384
385         logcookies = req_capsule_client_get(&req->rq_pill, &RMF_LOGCOOKIES);
386         num_cookies = req_capsule_get_size(&req->rq_pill, &RMF_LOGCOOKIES,
387                                            RCL_CLIENT) / sizeof(*logcookies);
388         if (logcookies == NULL || num_cookies == 0) {
389                 DEBUG_REQ(D_HA, req, "No llog cookies sent");
390                 RETURN(-EFAULT);
391         }
392
393         ctxt = llog_get_context(obd, logcookies->lgc_subsys);
394         if (ctxt == NULL)
395                 RETURN(-ENODEV);
396
397         disk_obd = ctxt->loc_exp->exp_obd;
398         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
399         for (i = 0; i < num_cookies; i++, logcookies++) {
400                 cathandle = ctxt->loc_handle;
401                 LASSERT(cathandle != NULL);
402                 inode = cathandle->lgh_file->f_dentry->d_inode;
403
404                 handle = fsfilt_start_log(disk_obd, inode,
405                                           FSFILT_OP_CANCEL_UNLINK, NULL, 1);
406                 if (IS_ERR(handle)) {
407                         CERROR("fsfilt_start_log() failed: %ld\n",
408                                PTR_ERR(handle));
409                         GOTO(pop_ctxt, rc = PTR_ERR(handle));
410                 }
411
412                 rc = llog_cat_cancel_records(cathandle, 1, logcookies);
413
414                 /*
415                  * Do not raise -ENOENT errors for resent rpcs. This rec already
416                  * might be killed.
417                  */
418                 if (rc == -ENOENT &&
419                     (lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT)) {
420                         /*
421                          * Do not change this message, reply-single.sh test_59b
422                          * expects to find this in log.
423                          */
424                         CDEBUG(D_RPCTRACE, "RESENT cancel req %p - ignored\n",
425                                req);
426                         rc = 0;
427                 } else if (rc == 0) {
428                         CDEBUG(D_RPCTRACE, "Canceled %d llog-records\n",
429                                num_cookies);
430                 }
431
432                 err = fsfilt_commit(disk_obd, inode, handle, 0);
433                 if (err) {
434                         CERROR("Error committing transaction: %d\n", err);
435                         if (!rc)
436                                 rc = err;
437                         failed++;
438                         GOTO(pop_ctxt, rc);
439                 } else if (rc)
440                         failed++;
441         }
442         GOTO(pop_ctxt, rc);
443 pop_ctxt:
444         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
445         if (rc)
446                 CERROR("Cancel %d of %d llog-records failed: %d\n",
447                        failed, num_cookies, rc);
448
449         llog_ctxt_put(ctxt);
450         return rc;
451 }
452 EXPORT_SYMBOL(llog_origin_handle_cancel);
453
454 static int llog_catinfo_config(struct obd_device *obd, char *buf, int buf_len,
455                                char *client)
456 {
457         struct mds_obd       *mds = &obd->u.mds;
458         struct llog_ctxt     *ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
459         struct lvfs_run_ctxt  saved;
460         struct llog_handle   *handle = NULL;
461         char                  name[4][64];
462         int                   rc, i, l, remains = buf_len;
463         char                 *out = buf;
464         ENTRY;
465
466         if (ctxt == NULL || mds == NULL)
467                 GOTO(release_ctxt, rc = -ENODEV);
468
469         push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
470
471         sprintf(name[0], "%s", mds->mds_profile);
472         sprintf(name[1], "%s-clean", mds->mds_profile);
473         sprintf(name[2], "%s", client);
474         sprintf(name[3], "%s-clean", client);
475
476         for (i = 0; i < 4; i++) {
477                 int index, uncanceled = 0;
478                 rc = llog_create(ctxt, &handle, NULL, name[i]);
479                 if (rc)
480                         GOTO(out_pop, rc);
481                 rc = llog_init_handle(handle, 0, NULL);
482                 if (rc) {
483                         llog_close(handle);
484                         GOTO(out_pop, rc = -ENOENT);
485                 }
486
487                 for (index = 1; index < (LLOG_BITMAP_BYTES * 8); index ++) {
488                         if (ext2_test_bit(index, handle->lgh_hdr->llh_bitmap))
489                                 uncanceled++;
490                 }
491
492                 l = snprintf(out, remains, "[Log Name]: %s\nLog Size: %llu\n"
493                              "Last Index: %d\nUncanceled Records: %d\n\n",
494                              name[i],
495                              i_size_read(handle->lgh_file->f_dentry->d_inode),
496                              handle->lgh_last_idx, uncanceled);
497                 out += l;
498                 remains -= l;
499
500                 llog_close(handle);
501                 if (remains <= 0)
502                         break;
503         }
504         GOTO(out_pop, rc);
505 out_pop:
506         pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
507 release_ctxt:
508         llog_ctxt_put(ctxt);
509         return rc;
510 }
511
512 struct cb_data {
513         struct llog_ctxt *ctxt;
514         char *out;
515         int  remains;
516         int  init;
517 };
518
519 static int llog_catinfo_cb(struct llog_handle *cat,
520                            struct llog_rec_hdr *rec, void *data)
521 {
522         static char *out = NULL;
523         static int remains = 0;
524         struct llog_ctxt *ctxt = NULL;
525         struct llog_handle *handle = NULL;
526         struct llog_logid *logid;
527         struct llog_logid_rec *lir;
528         int l, rc, index, count = 0;
529         struct cb_data *cbd = (struct cb_data*)data;
530         ENTRY;
531
532         if (cbd->init) {
533                 out = cbd->out;
534                 remains = cbd->remains;
535                 cbd->init = 0;
536         }
537
538         if (!(cat->lgh_hdr->llh_flags & LLOG_F_IS_CAT))
539                 RETURN(-EINVAL);
540
541         if (!cbd->ctxt)
542                 RETURN(-ENODEV);
543
544         lir = (struct llog_logid_rec *)rec;
545         logid = &lir->lid_id;
546         rc = llog_create(ctxt, &handle, logid, NULL);
547         if (rc)
548                 RETURN(-EINVAL);
549         rc = llog_init_handle(handle, 0, NULL);
550         if (rc)
551                 GOTO(out_close, rc);
552
553         for (index = 1; index < (LLOG_BITMAP_BYTES * 8); index++) {
554                 if (ext2_test_bit(index, handle->lgh_hdr->llh_bitmap))
555                         count++;
556         }
557
558         l = snprintf(out, remains, "\t[Log ID]: #"LPX64"#"LPX64"#%08x\n"
559                      "\tLog Size: %llu\n\tLast Index: %d\n"
560                      "\tUncanceled Records: %d\n",
561                      logid->lgl_oid, logid->lgl_oseq, logid->lgl_ogen,
562                      i_size_read(handle->lgh_file->f_dentry->d_inode),
563                      handle->lgh_last_idx, count);
564         out += l;
565         remains -= l;
566         cbd->out = out;
567         cbd->remains = remains;
568         if (remains <= 0) {
569                 CWARN("Not enough memory\n");
570                 rc = -ENOMEM;
571         }
572         EXIT;
573 out_close:
574         llog_close(handle);
575         return rc;
576 }
577
578 static int llog_catinfo_deletions(struct obd_device *obd, char *buf,
579                                   int buf_len)
580 {
581         struct mds_obd *mds = &obd->u.mds;
582         struct llog_handle *handle;
583         struct lvfs_run_ctxt saved;
584         int size, i, count;
585         struct llog_catid *idarray;
586         char name[32] = CATLIST;
587         struct cb_data data;
588         struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
589         int rc;
590         ENTRY;
591
592         if (ctxt == NULL || mds == NULL)
593                 GOTO(release_ctxt, rc = -ENODEV);
594
595         count = mds->mds_lov_desc.ld_tgt_count;
596         size = sizeof(*idarray) * count;
597
598         OBD_ALLOC_LARGE(idarray, size);
599         if (!idarray)
600                 GOTO(release_ctxt, rc = -ENOMEM);
601
602         cfs_mutex_lock(&obd->obd_olg.olg_cat_processing);
603         rc = llog_get_cat_list(obd, name, 0, count, idarray);
604         if (rc)
605                 GOTO(out_free, rc);
606
607         push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
608
609         data.ctxt = ctxt;
610         data.out = buf;
611         data.remains = buf_len;
612         for (i = 0; i < count; i++) {
613                 int l, index, uncanceled = 0;
614
615                 rc = llog_create(ctxt, &handle, &idarray[i].lci_logid, NULL);
616                 if (rc)
617                         GOTO(out_pop, rc);
618                 rc = llog_init_handle(handle, 0, NULL);
619                 if (rc) {
620                         llog_close(handle);
621                         GOTO(out_pop, rc = -ENOENT);
622                 }
623                 for (index = 1; index < (LLOG_BITMAP_BYTES * 8); index++) {
624                         if (ext2_test_bit(index, handle->lgh_hdr->llh_bitmap))
625                                 uncanceled++;
626                 }
627                 l = snprintf(data.out, data.remains,
628                              "\n[Catlog ID]: #"LPX64"#"LPX64"#%08x  "
629                              "[Log Count]: %d\n",
630                              idarray[i].lci_logid.lgl_oid,
631                              idarray[i].lci_logid.lgl_oseq,
632                              idarray[i].lci_logid.lgl_ogen, uncanceled);
633
634                 data.out += l;
635                 data.remains -= l;
636                 data.init = 1;
637
638                 llog_process(handle, llog_catinfo_cb, &data, NULL);
639                 llog_close(handle);
640
641                 if (data.remains <= 0)
642                         break;
643         }
644         EXIT;
645 out_pop:
646         pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
647 out_free:
648         cfs_mutex_unlock(&obd->obd_olg.olg_cat_processing);
649         OBD_FREE_LARGE(idarray, size);
650 release_ctxt:
651         llog_ctxt_put(ctxt);
652         return rc;
653 }
654
655 int llog_catinfo(struct ptlrpc_request *req)
656 {
657         struct obd_export *exp = req->rq_export;
658         struct obd_device *obd = exp->exp_obd;
659         char              *keyword;
660         char              *buf, *reply;
661         int                rc;
662         ENTRY;
663
664         OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
665         if (buf == NULL)
666                 RETURN(-ENOMEM);
667
668         memset(buf, 0, LLOG_CHUNK_SIZE);
669
670         keyword = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
671         LASSERT(keyword);
672
673         if (strcmp(keyword, "config") == 0) {
674                 char *client = req_capsule_client_get(&req->rq_pill,
675                                                       &RMF_STRING);
676
677                 LASSERT(client);
678                 rc = llog_catinfo_config(obd, buf, LLOG_CHUNK_SIZE, client);
679         } else if (strcmp(keyword, "deletions") == 0) {
680                 rc = llog_catinfo_deletions(obd, buf, LLOG_CHUNK_SIZE);
681         } else {
682                 rc = -EOPNOTSUPP;
683         }
684
685         req_capsule_set_size(&req->rq_pill, &RMF_STRING, RCL_SERVER,
686                              LLOG_CHUNK_SIZE);
687         rc = req_capsule_server_pack(&req->rq_pill);
688         if (rc)
689                 GOTO(out_free, rc = -ENOMEM);
690
691         reply = req_capsule_server_get(&req->rq_pill, &RMF_STRING);
692         if (strlen(buf) == 0)
693                 sprintf(buf, "%s", "No log informations\n");
694         memcpy(reply, buf, LLOG_CHUNK_SIZE);
695         EXIT;
696 out_free:
697         OBD_FREE(buf, LLOG_CHUNK_SIZE);
698         return rc;
699 }
700
701 #else /* !__KERNEL__ */
702 int llog_origin_handle_create(struct ptlrpc_request *req)
703 {
704         LBUG();
705         return 0;
706 }
707
708 int llog_origin_handle_destroy(struct ptlrpc_request *req)
709 {
710         LBUG();
711         return 0;
712 }
713
714 int llog_origin_handle_next_block(struct ptlrpc_request *req)
715 {
716         LBUG();
717         return 0;
718 }
719 int llog_origin_handle_prev_block(struct ptlrpc_request *req)
720 {
721         LBUG();
722         return 0;
723 }
724 int llog_origin_handle_read_header(struct ptlrpc_request *req)
725 {
726         LBUG();
727         return 0;
728 }
729 int llog_origin_handle_close(struct ptlrpc_request *req)
730 {
731         LBUG();
732         return 0;
733 }
734 int llog_origin_handle_cancel(struct ptlrpc_request *req)
735 {
736         LBUG();
737         return 0;
738 }
739 #endif