Whamcloud - gitweb
949fed0e0a0030ac07267a026b3ff100e172a714
[fs/lustre-release.git] / lustre / utils / llog_reader.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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2016, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 /** \defgroup llog_reader Lustre Log Reader
33  *
34  * Interpret llogs used for storing configuration and changelog data
35  *
36  * @{
37  */
38
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdbool.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #ifdef HAVE_ENDIAN_H
47 # include <endian.h>
48 #endif
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <sys/vfs.h>
52 #include <linux/magic.h>
53 #include <errno.h>
54 #include <time.h>
55 #include <lnet/nidstr.h>
56 #include <linux/lustre_fid.h>
57 #include <linux/lustre_ostid.h>
58 #include <lustre/lustreapi.h>
59 #include <lustre_log_user.h>
60 #include <lustre_cfg.h>
61
62 static inline int ext2_test_bit(int nr, const void *addr)
63 {
64 #if __BYTE_ORDER == __BIG_ENDIAN
65         const unsigned char *tmp = addr;
66         return (tmp[nr >> 3] >> (nr & 7)) & 1;
67 #else
68         const unsigned long *tmp = addr;
69         return ((1UL << (nr & (__WORDSIZE - 1))) &
70                 ((tmp)[nr / __WORDSIZE])) != 0;
71 #endif
72 }
73
74 int llog_pack_buffer(int fd, struct llog_log_hdr **llog_buf,
75                      struct llog_rec_hdr ***recs, int *recs_number);
76
77 void print_llog_header(struct llog_log_hdr *llog_buf);
78 static void print_records(struct llog_rec_hdr **recs_buf,
79                           int rec_number, int is_ext);
80 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
81                         struct llog_rec_hdr **recs_buf);
82
83 #define CANCELLED 0x678
84
85 #define PTL_CMD_BASE 100
86 char* portals_command[17]=
87 {
88         "REGISTER_PEER_FD",
89         "CLOSE_CONNECTION",
90         "REGISTER_MYNID",
91         "PUSH_CONNECTION",
92         "GET_CONN",
93         "DEL_PEER",
94         "ADD_PEER",
95         "GET_PEER",
96         "GET_TXDESC",
97         "ADD_ROUTE",
98         "DEL_ROUTE",
99         "GET_ROUTE",
100         "NOTIFY_ROUTER",
101         "ADD_INTERFACE",
102         "DEL_INTERFACE",
103         "GET_INTERFACE",
104         ""
105 };
106
107 int is_fstype_ext(int fd)
108 {
109         struct statfs           st;
110         int                     rc;
111
112         rc = fstatfs(fd, &st);
113         if (rc < 0) {
114                 llapi_error(LLAPI_MSG_ERROR, rc, "Got statfs error.");
115                 return -errno;
116         }
117
118         return (st.f_type == EXT4_SUPER_MAGIC);
119 }
120
121
122 /**
123  * Attempt to display a path to the object (file) containing changelog entries,
124  * referred to by this changelog_catalog record.
125  *
126  * This path depends on the implementation of the OSD device; zfs-osd and
127  * ldiskfs-osd are different.
128  *
129  * Assumes that if the file system containing the changelog_catalog is
130  * ext{2,3,4}, the backend is ldiskfs-osd; otherwise it is either zfs-osd or at
131  * least names objects based on FID and the zfs-osd path (which includes the
132  * FID) will be sufficient.
133  *
134  * The Object ID stored in the record is also displayed untranslated.
135  */
136 #define OSD_OI_FID_NR         (1UL << 7)
137 static void print_log_path(struct llog_logid_rec *lid, int is_ext)
138 {
139
140         char                    object_path[255];
141         struct lu_fid           fid_from_logid;
142
143         logid_to_fid(&lid->lid_id, &fid_from_logid);
144
145         if (is_ext)
146                 snprintf(object_path, sizeof(object_path),
147                          "O/%ju/d%u/%u", (uintmax_t)fid_from_logid.f_seq,
148                          fid_from_logid.f_oid % 32,
149                          fid_from_logid.f_oid);
150         else
151                 snprintf(object_path, sizeof(object_path),
152                          "oi.%ju/"DFID_NOBRACE,
153                          (uintmax_t)(fid_from_logid.f_seq & (OSD_OI_FID_NR - 1)),
154                          PFID(&fid_from_logid));
155
156         printf("id="DFID":%x path=%s\n",
157                PFID(&lid->lid_id.lgl_oi.oi_fid), lid->lid_id.lgl_ogen,
158                object_path);
159 }
160
161 int main(int argc, char **argv)
162 {
163         int rc = 0;
164         int is_ext;
165         int fd, rec_number;
166         struct llog_log_hdr *llog_buf = NULL;
167         struct llog_rec_hdr **recs_buf = NULL;
168
169         setlinebuf(stdout);
170
171         if (argc != 2) {
172                 printf("Usage: llog_reader filename\n");
173                 return -1;
174         }
175
176         fd = open(argv[1], O_RDONLY);
177         if (fd < 0) {
178                 rc = -errno;
179                 llapi_error(LLAPI_MSG_ERROR, rc, "Could not open the file %s.",
180                             argv[1]);
181                 goto out;
182         }
183
184         is_ext = is_fstype_ext(fd);
185         if (is_ext < 0) {
186                 rc = is_ext;
187                 printf("Unable to determine type of filesystem containing %s\n",
188                        argv[1]);
189                 goto out_fd;
190         }
191
192         rc = llog_pack_buffer(fd, &llog_buf, &recs_buf, &rec_number);
193         if (rc < 0) {
194                 llapi_error(LLAPI_MSG_ERROR, rc, "Could not pack buffer.");
195                 goto out_fd;
196         }
197
198         print_llog_header(llog_buf);
199         print_records(recs_buf, rec_number, is_ext);
200         llog_unpack_buffer(fd, llog_buf, recs_buf);
201
202 out_fd:
203         close(fd);
204 out:
205         return rc;
206 }
207
208
209
210 int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
211                      struct llog_rec_hdr ***recs,
212                      int *recs_number)
213 {
214         int rc = 0, recs_num, rd = 0;
215         long long file_size;
216         struct stat st;
217         char *file_buf = NULL, *recs_buf = NULL;
218         struct llog_rec_hdr **recs_pr = NULL;
219         char *ptr = NULL;
220         int i;
221
222         rc = fstat(fd, &st);
223         if (rc < 0) {
224                 rc = -errno;
225                 llapi_error(LLAPI_MSG_ERROR, rc, "Got file stat error.");
226                 goto out;
227         }
228
229         file_size = st.st_size;
230         if (file_size < sizeof(**llog)) {
231                 llapi_error(LLAPI_MSG_ERROR, rc,
232                             "File too small for llog header: "
233                             "need %zd, size %lld\n",
234                             sizeof(**llog), file_size);
235                 rc = -EIO;
236                 goto out;
237         }
238
239         file_buf = malloc(file_size);
240         if (file_buf == NULL) {
241                 rc = -ENOMEM;
242                 llapi_error(LLAPI_MSG_ERROR, rc, "Memory Alloc for file_buf.");
243                 goto out;
244         }
245         *llog = (struct llog_log_hdr *)file_buf;
246
247         do {
248                 rc = read(fd, file_buf + rd, file_size - rd);
249                 if (rc > 0)
250                         rd += rc;
251         } while (rc > 0 && rd < file_size);
252
253         if (rd < file_size) {
254                 rc = rc < 0 ? -errno : -EIO;
255                 llapi_error(LLAPI_MSG_ERROR, rc,
256                             "Error reading llog header: need %zd, got %d",
257                             sizeof(**llog), rd);
258                 goto clear_file_buf;
259         }
260
261         /* the llog header not countable here.*/
262         recs_num = __le32_to_cpu((*llog)->llh_count) - 1;
263
264         recs_buf = malloc(recs_num * sizeof(**recs_pr));
265         if (recs_buf == NULL) {
266                 rc = -ENOMEM;
267                 llapi_error(LLAPI_MSG_ERROR, rc,
268                             "Error allocating %zd bytes for recs_buf",
269                             recs_num * sizeof(**recs_pr));
270                 goto clear_file_buf;
271         }
272         recs_pr = (struct llog_rec_hdr **)recs_buf;
273
274         ptr = file_buf + __le32_to_cpu((*llog)->llh_hdr.lrh_len);
275         i = 0;
276
277         while (ptr < (file_buf + file_size)) {
278                 struct llog_rec_hdr *cur_rec;
279                 int idx;
280                 unsigned long offset;
281
282                 if (ptr + sizeof(**recs_pr) > file_buf + file_size) {
283                         rc = -EINVAL;
284                         llapi_error(LLAPI_MSG_ERROR, rc,
285                                     "The log is corrupt (too big at %d)", i);
286                         goto clear_recs_buf;
287                 }
288
289                 cur_rec = (struct llog_rec_hdr *)ptr;
290                 idx = __le32_to_cpu(cur_rec->lrh_index);
291                 recs_pr[i] = cur_rec;
292                 offset = (unsigned long)ptr - (unsigned long)file_buf;
293                 if (cur_rec->lrh_len == 0 ||
294                     cur_rec->lrh_len > (*llog)->llh_hdr.lrh_len) {
295                         cur_rec->lrh_len = (*llog)->llh_hdr.lrh_len -
296                                 offset % (*llog)->llh_hdr.lrh_len;
297                         printf("off %lu skip %u to next chunk.\n", offset,
298                                cur_rec->lrh_len);
299                         i--;
300                 } else if (ext2_test_bit(idx, LLOG_HDR_BITMAP(*llog))) {
301                         printf("rec #%d type=%x len=%u offset %lu\n", idx,
302                                cur_rec->lrh_type, cur_rec->lrh_len, offset);
303                 } else {
304                         printf("Bit %d of %d not set\n", idx, recs_num);
305                         cur_rec->lrh_id = CANCELLED;
306                         /* The header counts only set records */
307                         i--;
308                 }
309
310                 ptr += __le32_to_cpu(cur_rec->lrh_len);
311                 if ((ptr - file_buf) > file_size) {
312                         printf("The log is corrupt (too big at %d)\n", i);
313                         rc = -EINVAL;
314                         goto clear_recs_buf;
315                 }
316                 i++;
317         }
318
319         *recs = recs_pr;
320         *recs_number = recs_num;
321
322 out:
323         return rc;
324
325 clear_recs_buf:
326         free(recs_buf);
327
328 clear_file_buf:
329         free(file_buf);
330
331         *llog = NULL;
332         goto out;
333 }
334
335 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
336                         struct llog_rec_hdr **recs_buf)
337 {
338         free(llog_buf);
339         free(recs_buf);
340         return;
341 }
342
343 void print_llog_header(struct llog_log_hdr *llog_buf)
344 {
345         time_t t;
346
347         printf("Header size : %u\n",
348                __le32_to_cpu(llog_buf->llh_hdr.lrh_len));
349
350         t = __le64_to_cpu(llog_buf->llh_timestamp);
351         printf("Time : %s", ctime(&t));
352
353         printf("Number of records: %u\n",
354                __le32_to_cpu(llog_buf->llh_count)-1);
355
356         printf("Target uuid : %s\n",
357                (char *)(&llog_buf->llh_tgtuuid));
358
359         /* Add the other info you want to view here */
360
361         printf("-----------------------\n");
362         return;
363 }
364
365 static void print_1_cfg(struct lustre_cfg *lcfg)
366 {
367         int i;
368
369         if (lcfg->lcfg_nid)
370                 printf("nid=%s(%#jx)  ", libcfs_nid2str(lcfg->lcfg_nid),
371                        (uintmax_t)lcfg->lcfg_nid);
372         if (lcfg->lcfg_nal)
373                 printf("nal=%d ", lcfg->lcfg_nal);
374         for (i = 0; i <  lcfg->lcfg_bufcount; i++)
375                 printf("%d:%.*s  ", i, lcfg->lcfg_buflens[i],
376                        (char*)lustre_cfg_buf(lcfg, i));
377         return;
378 }
379
380
381 static void print_setup_cfg(struct lustre_cfg *lcfg)
382 {
383         struct lov_desc *desc;
384
385         if ((lcfg->lcfg_bufcount == 2) &&
386             (lcfg->lcfg_buflens[1] == sizeof(*desc))) {
387                 printf("lov_setup ");
388                 printf("0:%s  ", lustre_cfg_string(lcfg, 0));
389                 printf("1:(struct lov_desc)\n");
390                 desc = (struct lov_desc*)(lustre_cfg_string(lcfg, 1));
391                 printf("\t\tuuid=%s  ", (char*)desc->ld_uuid.uuid);
392                 printf("stripe:cnt=%u ", desc->ld_default_stripe_count);
393                 printf("size=%ju ", (uintmax_t)desc->ld_default_stripe_size);
394                 printf("offset=%ju ",
395                        (uintmax_t)desc->ld_default_stripe_offset);
396                 printf("pattern=%#x", desc->ld_pattern);
397         } else {
398                 printf("setup     ");
399                 print_1_cfg(lcfg);
400         }
401
402         return;
403 }
404
405 void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
406 {
407         enum lcfg_command_type cmd = __le32_to_cpu(lcfg->lcfg_command);
408
409         if (*skip > 0)
410                 printf("SKIP ");
411
412         switch(cmd){
413         case(LCFG_ATTACH):{
414                 printf("attach    ");
415                 print_1_cfg(lcfg);
416                 break;
417         }
418         case(LCFG_SETUP):{
419                 print_setup_cfg(lcfg);
420                 break;
421         }
422         case(LCFG_DETACH):{
423                 printf("detach    ");
424                 print_1_cfg(lcfg);
425                 break;
426         }
427         case(LCFG_CLEANUP):{
428                 printf("cleanup   ");
429                 print_1_cfg(lcfg);
430                 break;
431         }
432         case(LCFG_ADD_UUID):{
433                 printf("add_uuid  ");
434                 print_1_cfg(lcfg);
435                 break;
436         }
437         case(LCFG_DEL_UUID):{
438                 printf("del_uuid  ");
439                 print_1_cfg(lcfg);
440                 break;
441         }
442         case(LCFG_ADD_CONN):{
443                 printf("add_conn  ");
444                 print_1_cfg(lcfg);
445                 break;
446         }
447         case(LCFG_DEL_CONN):{
448                 printf("del_conn  ");
449                 print_1_cfg(lcfg);
450                 break;
451         }
452         case(LCFG_LOV_ADD_OBD):{
453                 printf("lov_modify_tgts add ");
454                 print_1_cfg(lcfg);
455                 break;
456         }
457         case(LCFG_LOV_DEL_OBD):{
458                 printf("lov_modify_tgts del ");
459                 print_1_cfg(lcfg);
460                 break;
461         }
462         case(LCFG_ADD_MDC):{
463                 printf("modify_mdc_tgts add ");
464                 print_1_cfg(lcfg);
465                 break;
466         }
467         case(LCFG_DEL_MDC):{
468                 printf("modify_mdc_tgts del ");
469                 print_1_cfg(lcfg);
470                 break;
471         }
472         case(LCFG_MOUNTOPT):{
473                 printf("mount_option ");
474                 print_1_cfg(lcfg);
475                 break;
476         }
477         case(LCFG_DEL_MOUNTOPT):{
478                 printf("del_mount_option ");
479                 print_1_cfg(lcfg);
480                 break;
481         }
482         case(LCFG_SET_TIMEOUT):{
483                 printf("set_timeout=%d ", lcfg->lcfg_num);
484                 break;
485         }
486         case(LCFG_SET_LDLM_TIMEOUT):{
487                 printf("set_ldlm_timeout=%d ", lcfg->lcfg_num);
488                 break;
489         }
490         case(LCFG_SET_UPCALL):{
491                 printf("set_lustre_upcall ");
492                 print_1_cfg(lcfg);
493                 break;
494         }
495         case(LCFG_PARAM):{
496                 printf("param ");
497                 print_1_cfg(lcfg);
498                 break;
499         }
500         case(LCFG_SET_PARAM):{
501                 printf("set_param ");
502                 print_1_cfg(lcfg);
503                 break;
504         }
505         case(LCFG_SPTLRPC_CONF):{
506                 printf("sptlrpc_conf ");
507                 print_1_cfg(lcfg);
508                 break;
509         }
510         case(LCFG_MARKER):{
511                 struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
512                 char createtime[26], canceltime[26] = "";
513                 time_t time_tmp;
514
515                 if (marker->cm_flags & CM_START &&
516                     marker->cm_flags & CM_SKIP) {
517                         printf("SKIP START ");
518                         (*skip)++;
519                 } else if (marker->cm_flags & CM_END) {
520                         printf(     "END   ");
521                         *skip = 0;
522                 }
523
524                 if (marker->cm_flags & CM_EXCLUDE) {
525                         if (marker->cm_flags & CM_START)
526                                 printf("EXCLUDE START ");
527                         else
528                                 printf("EXCLUDE END   ");
529                 }
530
531                 /* Handle overflow of 32-bit time_t gracefully.
532                  * The copy to time_tmp is needed in any case to
533                  * keep the pointer happy, even on 64-bit systems. */
534                 time_tmp = marker->cm_createtime;
535                 if (time_tmp == marker->cm_createtime) {
536                         ctime_r(&time_tmp, createtime);
537                         createtime[strlen(createtime) - 1] = 0;
538                 } else {
539                         strcpy(createtime, "in the distant future");
540                 }
541
542                 if (marker->cm_canceltime) {
543                         /* Like cm_createtime, we try to handle overflow of
544                          * 32-bit time_t gracefully. The copy to time_tmp
545                          * is also needed on 64-bit systems to keep the
546                          * pointer happy, see bug 16771 */
547                         time_tmp = marker->cm_canceltime;
548                         if (time_tmp == marker->cm_canceltime) {
549                                 ctime_r(&time_tmp, canceltime);
550                                 canceltime[strlen(canceltime) - 1] = 0;
551                         } else {
552                                 strcpy(canceltime, "in the distant future");
553                         }
554                 }
555
556                 printf("marker %3d (flags=%#04x, v%d.%d.%d.%d) %-15s '%s' %s-%s",
557                        marker->cm_step, marker->cm_flags,
558                        OBD_OCD_VERSION_MAJOR(marker->cm_vers),
559                        OBD_OCD_VERSION_MINOR(marker->cm_vers),
560                        OBD_OCD_VERSION_PATCH(marker->cm_vers),
561                        OBD_OCD_VERSION_FIX(marker->cm_vers),
562                        marker->cm_tgtname, marker->cm_comment,
563                        createtime, canceltime);
564                 break;
565         }
566         case(LCFG_POOL_NEW):{
567                 printf("pool new ");
568                 print_1_cfg(lcfg);
569                 break;
570         }
571         case(LCFG_POOL_ADD):{
572                 printf("pool add ");
573                 print_1_cfg(lcfg);
574                 break;
575         }
576         case(LCFG_POOL_REM):{
577                 printf("pool remove ");
578                 print_1_cfg(lcfg);
579                 break;
580         }
581         case(LCFG_POOL_DEL):{
582                 printf("pool destroy ");
583                 print_1_cfg(lcfg);
584                 break;
585         }
586         default:
587                 printf("unsupported cmd_code = %x\n",cmd);
588         }
589         printf("\n");
590         return;
591 }
592
593 static void print_hsm_action(struct llog_agent_req_rec *larr)
594 {
595         char    buf[12];
596         int     sz;
597
598         sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
599         printf("lrh=[type=%X len=%d idx=%d] fid="DFID
600                " compound/cookie=%#jx/%#jx"
601                " status=%s action=%s archive#=%d flags=%#jx"
602                " create=%ju change=%ju"
603                " extent=%#jx-%#jx gid=%#jx datalen=%d"
604                " data=[%s]\n",
605                larr->arr_hdr.lrh_type,
606                larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index,
607                PFID(&larr->arr_hai.hai_fid),
608                (uintmax_t)larr->arr_compound_id,
609                (uintmax_t)larr->arr_hai.hai_cookie,
610                agent_req_status2name(larr->arr_status),
611                hsm_copytool_action2name(larr->arr_hai.hai_action),
612                larr->arr_archive_id,
613                (uintmax_t)larr->arr_flags,
614                (uintmax_t)larr->arr_req_create,
615                (uintmax_t)larr->arr_req_change,
616                (uintmax_t)larr->arr_hai.hai_extent.offset,
617                (uintmax_t)larr->arr_hai.hai_extent.length,
618                (uintmax_t)larr->arr_hai.hai_gid, sz,
619                hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
620 }
621
622 void print_changelog_rec(struct llog_changelog_rec *rec)
623 {
624         printf("changelog record id:0x%x cr_flags:0x%x cr_type:%s(0x%x)\n",
625                __le32_to_cpu(rec->cr_hdr.lrh_id),
626                __le32_to_cpu(rec->cr.cr_flags),
627                changelog_type2str(__le32_to_cpu(rec->cr.cr_type)),
628                __le32_to_cpu(rec->cr.cr_type));
629 }
630
631 static void print_records(struct llog_rec_hdr **recs,
632                           int rec_number, int is_ext)
633 {
634         __u32 lopt;
635         int i, skip = 0;
636
637         for (i = 0; i < rec_number; i++) {
638                 printf("#%.2d (%.3d)", __le32_to_cpu(recs[i]->lrh_index),
639                        __le32_to_cpu(recs[i]->lrh_len));
640
641                 lopt = __le32_to_cpu(recs[i]->lrh_type);
642
643                 if (recs[i]->lrh_id == CANCELLED)
644                         printf("NOT SET ");
645
646                 switch (lopt) {
647                 case OBD_CFG_REC:
648                         print_lustre_cfg(
649                                 (struct lustre_cfg *)((char *)(recs[i]) +
650                                 sizeof(struct llog_rec_hdr)), &skip);
651                         break;
652                 case LLOG_PAD_MAGIC:
653                         printf("padding\n");
654                         break;
655                 case LLOG_LOGID_MAGIC:
656                         print_log_path((struct llog_logid_rec *)recs[i],
657                                        is_ext);
658                         break;
659                 case HSM_AGENT_REC:
660                         print_hsm_action((struct llog_agent_req_rec *)recs[i]);
661                         break;
662                 case CHANGELOG_REC:
663                         print_changelog_rec((struct llog_changelog_rec *)
664                                             recs[i]);
665                         break;
666                 case CHANGELOG_USER_REC:
667                         printf("changelog_user record id:0x%x\n",
668                                __le32_to_cpu(recs[i]->lrh_id));
669                         break;
670                 default:
671                         printf("unknown type %x\n", lopt);
672                         break;
673                 }
674         }
675 }
676
677 /** @} llog_reader */