Whamcloud - gitweb
LU-17705 ptlrpc: replace synchronize_rcu() with rcu_barrier()
[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, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  */
31 /** \defgroup llog_reader Lustre Log Reader
32  *
33  * Interpret llogs used for storing configuration and changelog data
34  *
35  * @{
36  */
37
38 #include <errno.h>
39 #include <limits.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/param.h>
47 #ifdef HAVE_ENDIAN_H
48 # include <endian.h>
49 #endif
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <sys/vfs.h>
53 #include <linux/magic.h>
54 #include <errno.h>
55 #include <time.h>
56 #include <linux/lnet/nidstr.h>
57 #include <linux/lustre/lustre_cfg.h>
58 #include <linux/lustre/lustre_fid.h>
59 #include <linux/lustre/lustre_ostid.h>
60 #include <linux/lustre/lustre_log_user.h>
61 #include <lustre/lustreapi.h>
62
63 static inline int ext2_test_bit(int nr, const void *addr)
64 {
65 #if __BYTE_ORDER == __BIG_ENDIAN
66         const unsigned char *tmp = addr;
67
68         return (tmp[nr >> 3] >> (nr & 7)) & 1;
69 #else
70         const unsigned long *tmp = addr;
71
72         return ((1UL << (nr & (__WORDSIZE - 1))) &
73                 ((tmp)[nr / __WORDSIZE])) != 0;
74 #endif
75 }
76
77 int llog_pack_buffer(int fd, struct llog_log_hdr **llog_buf,
78                      struct llog_rec_hdr ***recs, int *recs_number);
79
80 void print_llog_header(struct llog_log_hdr *llog_buf);
81 static void print_records(struct llog_rec_hdr **recs_buf,
82                           int rec_number, int is_ext);
83 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
84                         struct llog_rec_hdr **recs_buf);
85
86 #define CANCELLED 0x678
87
88 #define PTL_CMD_BASE 100
89 char *portals_command[17] = {
90         "REGISTER_PEER_FD",
91         "CLOSE_CONNECTION",
92         "REGISTER_MYNID",
93         "PUSH_CONNECTION",
94         "GET_CONN",
95         "DEL_PEER",
96         "ADD_PEER",
97         "GET_PEER",
98         "GET_TXDESC",
99         "ADD_ROUTE",
100         "DEL_ROUTE",
101         "GET_ROUTE",
102         "NOTIFY_ROUTER",
103         "ADD_INTERFACE",
104         "DEL_INTERFACE",
105         "GET_INTERFACE",
106         ""
107 };
108
109 static int is_fstype_ext(int fd)
110 {
111         struct statfs st;
112         int rc;
113
114         rc = fstatfs(fd, &st);
115         if (rc < 0) {
116                 llapi_error(LLAPI_MSG_ERROR, rc, "Got statfs error.");
117                 return -errno;
118         }
119
120         return (st.f_type == EXT4_SUPER_MAGIC);
121 }
122
123 /**
124  * Attempt to display a path to the object (file) containing changelog entries,
125  * referred to by this changelog_catalog record.
126  *
127  * This path depends on the implementation of the OSD device; zfs-osd and
128  * ldiskfs-osd are different.
129  *
130  * Assumes that if the file system containing the changelog_catalog is
131  * ext{2,3,4}, the backend is ldiskfs-osd; otherwise it is either zfs-osd or at
132  * least names objects based on FID and the zfs-osd path (which includes the
133  * FID) will be sufficient.
134  *
135  * The Object ID stored in the record is also displayed untranslated.
136  */
137 #define OSD_OI_FID_NR         (1UL << 7)
138 static void print_log_path(struct llog_logid_rec *lid, int is_ext)
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         /**
146          * Llogs with regular llog SEQ such as FID_SEQ_LLOG and
147          * FID_SEQ_LLOG_NAME are stored under O/ directory but
148          * update llogs are using normal FIDs and stored under
149          * 'update_log_dir' directory with FID format name
150          * Distinguish them by FID sequence
151          */
152         if (fid_from_logid.f_seq != FID_SEQ_LLOG &&
153             fid_from_logid.f_seq != FID_SEQ_LLOG_NAME)
154                 snprintf(object_path, sizeof(object_path),
155                          "update_log_dir/"DFID, PFID(&fid_from_logid));
156         else if (is_ext)
157                 snprintf(object_path, sizeof(object_path),
158                          "O/%ju/d%u/%u", (uintmax_t)fid_from_logid.f_seq,
159                          fid_from_logid.f_oid % 32,
160                          fid_from_logid.f_oid);
161         else
162                 snprintf(object_path, sizeof(object_path),
163                          "oi.%ju/"DFID_NOBRACE,
164                          (uintmax_t)(fid_from_logid.f_seq &
165                                      (OSD_OI_FID_NR - 1)),
166                          PFID(&fid_from_logid));
167
168         printf("fid="DFID" path=%s\n", PFID(&fid_from_logid),
169                object_path);
170 }
171
172 int main(int argc, char **argv)
173 {
174         int rc = 0;
175         int is_ext;
176         int fd, rec_number;
177         struct llog_log_hdr *llog_buf = NULL;
178         struct llog_rec_hdr **recs_buf = NULL;
179
180         setlinebuf(stdout);
181
182         if (argc != 2) {
183                 printf("Usage: llog_reader filename\n");
184                 return -1;
185         }
186
187         fd = open(argv[1], O_RDONLY);
188         if (fd < 0) {
189                 rc = -errno;
190                 llapi_error(LLAPI_MSG_ERROR, rc, "Could not open the file %s.",
191                             argv[1]);
192                 goto out;
193         }
194
195         is_ext = is_fstype_ext(fd);
196         if (is_ext < 0) {
197                 rc = is_ext;
198                 llapi_error(LLAPI_MSG_ERROR, -rc,
199                             "Unable to determine filesystem type for %s",
200                        argv[1]);
201                 goto out_fd;
202         }
203
204         rc = llog_pack_buffer(fd, &llog_buf, &recs_buf, &rec_number);
205         if (rc < 0) {
206                 llapi_error(LLAPI_MSG_ERROR, rc, "Could not pack buffer.");
207                 goto out_fd;
208         }
209
210         if (llog_buf)
211                 print_llog_header(llog_buf);
212         if (recs_buf)
213                 print_records(recs_buf, rec_number, is_ext);
214         llog_unpack_buffer(fd, llog_buf, recs_buf);
215
216 out_fd:
217         close(fd);
218 out:
219         return rc;
220 }
221
222 int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
223                      struct llog_rec_hdr ***recs,
224                      int *recs_number)
225 {
226         int rc = 0, recs_num, rd = 0;
227         long long file_size;
228         struct stat st;
229         char *file_buf = NULL, *recs_buf = NULL;
230         struct llog_rec_hdr **recs_pr = NULL;
231         char *ptr = NULL;
232         int count, errors = 0;
233         int i, last_idx;
234
235         *recs = NULL;
236         *recs_number = 0;
237
238         rc = fstat(fd, &st);
239         if (rc < 0) {
240                 rc = -errno;
241                 llapi_error(LLAPI_MSG_ERROR, rc, "Got file stat error.");
242                 return rc;
243         }
244
245         file_size = st.st_size;
246         if (file_size < sizeof(**llog)) {
247                 llapi_error(LLAPI_MSG_ERROR, rc,
248                             "File too small for llog header: want=%zd got=%lld",
249                             sizeof(**llog), file_size);
250                 rc = -EIO;
251                 return rc;
252         }
253
254         file_buf = malloc(file_size);
255         if (!file_buf) {
256                 rc = -ENOMEM;
257                 llapi_error(LLAPI_MSG_ERROR, rc, "Memory Alloc for file_buf.");
258                 return rc;
259         }
260         *llog = (struct llog_log_hdr *)file_buf;
261
262         do {
263                 rc = read(fd, file_buf + rd, file_size - rd);
264                 if (rc > 0)
265                         rd += rc;
266         } while (rc > 0 && rd < file_size);
267
268         if (rd < file_size) {
269                 rc = rc < 0 ? -errno : -EIO;
270                 llapi_error(LLAPI_MSG_ERROR, rc,
271                             "Error reading llog header: need %zd, got %d",
272                             sizeof(**llog), rd);
273                 goto clear_file_buf;
274         }
275
276         count = __le32_to_cpu((*llog)->llh_count);
277         if (count < 0) {
278                 rc = -EINVAL;
279                 llapi_error(LLAPI_MSG_ERROR, rc,
280                             "corrupted llog: negative record number %d",
281                             count);
282                 goto clear_file_buf;
283         } else if (count == 0) {
284                 llapi_printf(LLAPI_MSG_NORMAL,
285                              "uninitialized llog: zero record number\n");
286                 goto clear_file_buf;
287         }
288
289         /* the llog header not countable here.*/
290         recs_num = count - 1;
291         if (recs_num == 0)
292                 return 0;
293
294         recs_buf = calloc(recs_num, sizeof(**recs_pr));
295         if (!recs_buf) {
296                 rc = -ENOMEM;
297                 llapi_error(LLAPI_MSG_ERROR, rc,
298                             "Error allocating %zd bytes for recs_buf",
299                             recs_num * sizeof(**recs_pr));
300                 goto clear_file_buf;
301         }
302         recs_pr = (struct llog_rec_hdr **)recs_buf;
303
304         ptr = file_buf + __le32_to_cpu((*llog)->llh_hdr.lrh_len);
305         i = 0;
306
307         last_idx = 0;
308         while (ptr < (file_buf + file_size)) {
309                 struct llog_rec_hdr *cur_rec;
310                 struct llog_rec_tail *cur_tail;
311                 unsigned int idx, len, tail_idx, tail_len;
312                 unsigned long offset;
313
314                 offset = (unsigned long)ptr - (unsigned long)file_buf;
315                 if (offset + sizeof(**recs_pr) > file_size) {
316                         printf("error: rec header is trimmed by EOF, last idx #%d offset %lu\n",
317                                last_idx, offset);
318                         errors++;
319                         break;
320                 }
321                 cur_rec = (struct llog_rec_hdr *)ptr;
322                 idx = __le32_to_cpu(cur_rec->lrh_index);
323                 len = __le32_to_cpu(cur_rec->lrh_len);
324
325                 if (len == 0 || len + offset % (*llog)->llh_hdr.lrh_len >
326                                 (*llog)->llh_hdr.lrh_len) {
327                         printf("error: rec #%d type=%x has wrong len=%u @%lu\n",
328                                idx, cur_rec->lrh_type, len, offset);
329                         errors++;
330                         len = (*llog)->llh_hdr.lrh_len -
331                               offset % (*llog)->llh_hdr.lrh_len;
332                         printf("skip %u bytes to the next chunk at off %lu.\n",
333                                len, offset + len);
334                         ptr += len;
335                         continue;
336                 }
337
338                 if (ext2_test_bit(idx, LLOG_HDR_BITMAP(*llog))) {
339                         printf("rec #%d type=%x len=%u offset %lu\n", idx,
340                                cur_rec->lrh_type, len, offset);
341                         recs_pr[i] = cur_rec;
342                         i++;
343                 } else {
344                         cur_rec->lrh_id = CANCELLED;
345                         if (cur_rec->lrh_type == LLOG_PAD_MAGIC &&
346                            ((offset + len) & 0x7) != 0) {
347                                 printf("error: rec #%d wrong padding len=%u offset %lu to 0x%lx\n",
348                                        idx, len, offset, offset + len);
349                                 errors++;
350                         }
351                         /* The header counts only set records */
352                 }
353
354                 cur_tail = (struct llog_rec_tail *)(ptr + len - sizeof(*cur_tail));
355                 tail_idx = __le32_to_cpu(cur_tail->lrt_index);
356                 tail_len = __le32_to_cpu(cur_tail->lrt_len);
357                 if (idx != tail_idx || len != tail_len) {
358                         printf("error: rec #%d len=%u has tail #%d len=%u%s\n",
359                                idx, len, tail_idx, tail_len,
360                                cur_rec->lrh_id == CANCELLED ? " (unset)" : "");
361                         errors++;
362                 }
363
364                 if (idx > last_idx + 1)
365                         printf("error: rec #%d len=%u has gap in %d recs\n",
366                                idx, len, idx - last_idx);
367
368                 while (++last_idx < idx) {
369                         printf("error: -> rec #%d is lost%s set in bitmap\n",
370                                last_idx,
371                                ext2_test_bit(last_idx, LLOG_HDR_BITMAP(*llog)) ?
372                                " but" : ", not");
373                         errors++;
374                 }
375                 /* index may decrease only when crosses index zero in catalog */
376                 if (last_idx > idx && idx != 1) {
377                         printf("error: rec #%d index is less than last #%d\n",
378                                idx, last_idx);
379                         errors++;
380                         last_idx = idx;
381                 }
382
383                 ptr += len;
384                 if ((ptr - file_buf) > file_size) {
385                         printf("error: rec #%d is trimmed by EOF, offset %lu\n",
386                                idx, offset);
387                         errors++;
388                         break;
389                 }
390         }
391
392         while (++last_idx < LLOG_HDR_BITMAP_SIZE((*llog))) {
393                 if (ext2_test_bit(last_idx, LLOG_HDR_BITMAP(*llog))) {
394                         printf("error: rec #%d is set in bitmap only\n",
395                                last_idx);
396                         errors++;
397                 }
398         }
399         if (i != recs_num)
400                 printf("error: header reports %d records but %d were found\n",
401                        recs_num, i);
402
403         /* don't set rc to output what was found */
404         if (errors)
405                 llapi_error(LLAPI_MSG_NO_ERRNO, 0,
406                             "The llog is corrupted, %d errors found", errors);
407
408         *recs = recs_pr;
409         /* don't try to output more recs than was found or allocated */
410         *recs_number = i > recs_num ? recs_num : i;
411
412         return 0;
413
414 clear_file_buf:
415         free(file_buf);
416         *llog = NULL;
417
418         return rc;
419 }
420
421 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
422                         struct llog_rec_hdr **recs_buf)
423 {
424         if (llog_buf)
425                 free(llog_buf);
426         if (recs_buf)
427                 free(recs_buf);
428 }
429
430 void print_llog_header(struct llog_log_hdr *llog_buf)
431 {
432         time_t t;
433         unsigned int lrh_len = __le32_to_cpu(llog_buf->llh_hdr.lrh_len);
434         struct llog_rec_tail *tail = ((struct llog_rec_tail *)((char *)llog_buf+
435                                  lrh_len - sizeof(llog_buf->llh_tail)));
436
437         printf("Header size : %u\t llh_size : %u\n", lrh_len,
438                __le32_to_cpu(llog_buf->llh_size));
439
440         t = __le64_to_cpu(llog_buf->llh_timestamp);
441         printf("Time : %s", ctime(&t));
442
443         printf("Number of records: %u\tcat_idx: %u\tlast_idx: %u\n",
444                __le32_to_cpu(llog_buf->llh_count)-1,
445                __le32_to_cpu(llog_buf->llh_cat_idx),
446                __le32_to_cpu(tail->lrt_index));
447         printf("Flags: %#x\n", __le32_to_cpu(llog_buf->llh_flags));
448         printf("Target uuid : %s\n",
449                (char *)(&llog_buf->llh_tgtuuid));
450
451         /* Add the other info you want to view here */
452
453         printf("-----------------------\n");
454 }
455
456 static void print_1_cfg(struct lustre_cfg *lcfg)
457 {
458         int i;
459
460         if (lcfg->lcfg_nid)
461                 printf("nid=%s(%#jx)  ", libcfs_nid2str(lcfg->lcfg_nid),
462                        (uintmax_t)lcfg->lcfg_nid);
463         if (lcfg->lcfg_nal)
464                 printf("nal=%d ", lcfg->lcfg_nal);
465         for (i = 0; i <  lcfg->lcfg_bufcount; i++)
466                 printf("%d:%.*s  ", i, lcfg->lcfg_buflens[i],
467                        (char *)lustre_cfg_buf(lcfg, i));
468 }
469
470 static char *lustre_cfg_string(struct lustre_cfg *lcfg, __u32 index)
471 {
472         char *s;
473
474         if (lcfg->lcfg_buflens[index] == 0)
475                 return NULL;
476
477         s = lustre_cfg_buf(lcfg, index);
478         if (!s)
479                 return NULL;
480
481         /*
482          * make sure it's NULL terminated, even if this kills a char
483          * of data. Try to use the padding first though.
484          */
485         if (s[lcfg->lcfg_buflens[index] - 1] != '\0') {
486                 size_t last = __ALIGN_KERNEL(lcfg->lcfg_buflens[index], 8) - 1;
487                 char lost;
488
489                 /* Use the smaller value */
490                 if (last > lcfg->lcfg_buflens[index])
491                         last = lcfg->lcfg_buflens[index];
492
493                 lost = s[last];
494                 s[last] = '\0';
495                 if (lost != '\0') {
496                         fprintf(stderr,
497                                 "Truncated buf %d to '%s' (lost '%c'...)\n",
498                                 index, s, lost);
499                 }
500         }
501         return s;
502 }
503
504 static void print_setup_cfg(struct lustre_cfg *lcfg)
505 {
506         struct lov_desc *desc;
507
508         if ((lcfg->lcfg_bufcount == 2) &&
509             (lcfg->lcfg_buflens[1] == sizeof(*desc))) {
510                 printf("lov_setup ");
511                 printf("0:%s  ", lustre_cfg_string(lcfg, 0));
512                 printf("1:(struct lov_desc)\n");
513                 desc = (struct lov_desc *)(lustre_cfg_string(lcfg, 1));
514                 printf("\t\tuuid=%s  ", (char *)desc->ld_uuid.uuid);
515                 printf("stripe:cnt=%u ", desc->ld_default_stripe_count);
516                 printf("size=%ju ", (uintmax_t)desc->ld_default_stripe_size);
517                 printf("offset=%ju ",
518                        (uintmax_t)desc->ld_default_stripe_offset);
519                 printf("pattern=%#x", desc->ld_pattern);
520         } else {
521                 printf("setup     ");
522                 print_1_cfg(lcfg);
523         }
524 }
525
526 static void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
527 {
528         enum lcfg_command_type cmd = __le32_to_cpu(lcfg->lcfg_command);
529
530         if (*skip > 0)
531                 printf("SKIP ");
532
533         switch (cmd) {
534         case(LCFG_ATTACH):{
535                 printf("attach    ");
536                 print_1_cfg(lcfg);
537                 break;
538         }
539         case(LCFG_SETUP):{
540                 print_setup_cfg(lcfg);
541                 break;
542         }
543         case(LCFG_DETACH):{
544                 printf("detach    ");
545                 print_1_cfg(lcfg);
546                 break;
547         }
548         case(LCFG_CLEANUP):{
549                 printf("cleanup   ");
550                 print_1_cfg(lcfg);
551                 break;
552         }
553         case(LCFG_ADD_UUID):{
554                 printf("add_uuid  ");
555                 print_1_cfg(lcfg);
556                 break;
557         }
558         case(LCFG_DEL_UUID):{
559                 printf("del_uuid  ");
560                 print_1_cfg(lcfg);
561                 break;
562         }
563         case(LCFG_ADD_CONN):{
564                 printf("add_conn  ");
565                 print_1_cfg(lcfg);
566                 break;
567         }
568         case(LCFG_DEL_CONN):{
569                 printf("del_conn  ");
570                 print_1_cfg(lcfg);
571                 break;
572         }
573         case(LCFG_LOV_ADD_OBD):{
574                 printf("lov_modify_tgts add ");
575                 print_1_cfg(lcfg);
576                 break;
577         }
578         case(LCFG_LOV_DEL_OBD):{
579                 printf("lov_modify_tgts del ");
580                 print_1_cfg(lcfg);
581                 break;
582         }
583         case(LCFG_ADD_MDC):{
584                 printf("modify_mdc_tgts add ");
585                 print_1_cfg(lcfg);
586                 break;
587         }
588         case(LCFG_DEL_MDC):{
589                 printf("modify_mdc_tgts del ");
590                 print_1_cfg(lcfg);
591                 break;
592         }
593         case(LCFG_MOUNTOPT):{
594                 printf("mount_option ");
595                 print_1_cfg(lcfg);
596                 break;
597         }
598         case(LCFG_DEL_MOUNTOPT):{
599                 printf("del_mount_option ");
600                 print_1_cfg(lcfg);
601                 break;
602         }
603         case(LCFG_SET_TIMEOUT):{
604                 printf("set_timeout=%d ", lcfg->lcfg_num);
605                 break;
606         }
607         case(LCFG_SET_LDLM_TIMEOUT):{
608                 printf("set_ldlm_timeout=%d ", lcfg->lcfg_num);
609                 break;
610         }
611         case(LCFG_SET_UPCALL):{
612                 printf("set_lustre_upcall ");
613                 print_1_cfg(lcfg);
614                 break;
615         }
616         case(LCFG_PARAM):{
617                 printf("param ");
618                 print_1_cfg(lcfg);
619                 break;
620         }
621         case(LCFG_SET_PARAM):{
622                 printf("set_param ");
623                 print_1_cfg(lcfg);
624                 break;
625         }
626         case(LCFG_SPTLRPC_CONF):{
627                 printf("sptlrpc_conf ");
628                 print_1_cfg(lcfg);
629                 break;
630         }
631         case(LCFG_MARKER):{
632                 struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
633                 char createtime[26], canceltime[26] = "";
634                 time_t time_tmp;
635
636                 if (marker->cm_flags & CM_START &&
637                     marker->cm_flags & CM_SKIP) {
638                         printf("SKIP START ");
639                         (*skip)++;
640                 } else if (marker->cm_flags & CM_END) {
641                         printf("END   ");
642                         *skip = 0;
643                 }
644
645                 if (marker->cm_flags & CM_EXCLUDE) {
646                         if (marker->cm_flags & CM_START)
647                                 printf("EXCLUDE START ");
648                         else
649                                 printf("EXCLUDE END   ");
650                 }
651
652                 /*
653                  * Handle overflow of 32-bit time_t gracefully.
654                  * The copy to time_tmp is needed in any case to
655                  * keep the pointer happy, even on 64-bit systems.
656                  */
657                 time_tmp = marker->cm_createtime;
658                 if (time_tmp == marker->cm_createtime) {
659                         ctime_r(&time_tmp, createtime);
660                         createtime[strlen(createtime) - 1] = 0;
661                 } else {
662                         strcpy(createtime, "in the distant future");
663                 }
664
665                 if (marker->cm_canceltime) {
666                         /*
667                          * Like cm_createtime, we try to handle overflow of
668                          * 32-bit time_t gracefully. The copy to time_tmp
669                          * is also needed on 64-bit systems to keep the
670                          * pointer happy, see bug 16771
671                          */
672                         time_tmp = marker->cm_canceltime;
673                         if (time_tmp == marker->cm_canceltime) {
674                                 ctime_r(&time_tmp, canceltime);
675                                 canceltime[strlen(canceltime) - 1] = 0;
676                         } else {
677                                 strcpy(canceltime, "in the distant future");
678                         }
679                 }
680
681                 printf("marker %3d (flags=%#04x, v%d.%d.%d.%d) %-15s '%s' %s-%s",
682                        marker->cm_step, marker->cm_flags,
683                        OBD_OCD_VERSION_MAJOR(marker->cm_vers),
684                        OBD_OCD_VERSION_MINOR(marker->cm_vers),
685                        OBD_OCD_VERSION_PATCH(marker->cm_vers),
686                        OBD_OCD_VERSION_FIX(marker->cm_vers),
687                        marker->cm_tgtname, marker->cm_comment,
688                        createtime, canceltime);
689                 break;
690         }
691         case(LCFG_POOL_NEW):{
692                 printf("pool new ");
693                 print_1_cfg(lcfg);
694                 break;
695         }
696         case(LCFG_POOL_ADD):{
697                 printf("pool add ");
698                 print_1_cfg(lcfg);
699                 break;
700         }
701         case(LCFG_POOL_REM):{
702                 printf("pool remove ");
703                 print_1_cfg(lcfg);
704                 break;
705         }
706         case(LCFG_POOL_DEL):{
707                 printf("pool destroy ");
708                 print_1_cfg(lcfg);
709                 break;
710         }
711         default:
712                 printf("unsupported cmd_code = %x\n", cmd);
713         }
714         printf("\n");
715 }
716
717 static void print_hsm_action(struct llog_agent_req_rec *larr)
718 {
719         char buf[12];
720         int sz;
721
722         sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
723         printf("lrh=[type=%X len=%d idx=%d] fid="DFID" compound/cookie=%#llx/%#llx status=%s action=%s archive#=%d flags=%#llx create=%llu change=%llu extent=%#llx-%#llx gid=%#llx datalen=%d data=[%s]\n",
724                larr->arr_hdr.lrh_type,
725                larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index,
726                PFID(&larr->arr_hai.hai_fid),
727                (unsigned long long)larr->arr_compound_id,
728                (unsigned long long)larr->arr_hai.hai_cookie,
729                agent_req_status2name(larr->arr_status),
730                hsm_copytool_action2name(larr->arr_hai.hai_action),
731                larr->arr_archive_id,
732                (unsigned long long)larr->arr_flags,
733                (unsigned long long)larr->arr_req_create,
734                (unsigned long long)larr->arr_req_change,
735                (unsigned long long)larr->arr_hai.hai_extent.offset,
736                (unsigned long long)larr->arr_hai.hai_extent.length,
737                (unsigned long long)larr->arr_hai.hai_gid, sz,
738                hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
739 }
740
741 static void print_changelog_rec(struct llog_changelog_rec *rec)
742 {
743         time_t secs;
744         struct tm ts;
745
746         secs = __le64_to_cpu(rec->cr.cr_time) >> 30;
747         gmtime_r(&secs, &ts);
748         printf("changelog record id:0x%x index:%llu cr_flags:0x%x cr_type:%s(0x%x) date:'%02d:%02d:%02d.%09d %04d.%02d.%02d' target:"DFID,
749                __le32_to_cpu(rec->cr_hdr.lrh_id),
750                (unsigned long long)__le64_to_cpu(rec->cr.cr_index),
751                __le32_to_cpu(rec->cr.cr_flags),
752                changelog_type2str(__le32_to_cpu(rec->cr.cr_type)),
753                __le32_to_cpu(rec->cr.cr_type),
754                ts.tm_hour, ts.tm_min, ts.tm_sec,
755                (int)(__le64_to_cpu(rec->cr.cr_time) & ((1 << 30) - 1)),
756                ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday,
757                PFID(&rec->cr.cr_tfid));
758
759         if (rec->cr.cr_flags & CLF_JOBID) {
760                 struct changelog_ext_jobid *jid =
761                         changelog_rec_jobid(&rec->cr);
762
763                 if (jid->cr_jobid[0] != '\0')
764                         printf(" jobid:%s", jid->cr_jobid);
765         }
766
767         if (rec->cr.cr_flags & CLF_EXTRA_FLAGS) {
768                 struct changelog_ext_extra_flags *ef =
769                         changelog_rec_extra_flags(&rec->cr);
770
771                 printf(" cr_extra_flags:0x%llx",
772                        (unsigned long long)__le64_to_cpu(ef->cr_extra_flags));
773
774                 if (ef->cr_extra_flags & CLFE_UIDGID) {
775                         struct changelog_ext_uidgid *uidgid =
776                                 changelog_rec_uidgid(&rec->cr);
777
778                         printf(" user:%u:%u",
779                                __le32_to_cpu(uidgid->cr_uid),
780                                __le32_to_cpu(uidgid->cr_gid));
781                 }
782                 if (ef->cr_extra_flags & CLFE_NID) {
783                         struct changelog_ext_nid *nid =
784                                 changelog_rec_nid(&rec->cr);
785
786                         printf(" nid:%s",
787                                libcfs_nid2str(nid->cr_nid));
788                 }
789
790                 if (ef->cr_extra_flags & CLFE_OPEN) {
791                         struct changelog_ext_openmode *omd =
792                                 changelog_rec_openmode(&rec->cr);
793                         char mode[] = "---";
794
795                         /* exec mode must be exclusive */
796                         if (__le32_to_cpu(omd->cr_openflags) & MDS_FMODE_EXEC) {
797                                 mode[2] = 'x';
798                         } else {
799                                 if (__le32_to_cpu(omd->cr_openflags) &
800                                     MDS_FMODE_READ)
801                                         mode[0] = 'r';
802                                 if (__le32_to_cpu(omd->cr_openflags) &
803                            (MDS_FMODE_WRITE | MDS_OPEN_TRUNC | MDS_OPEN_APPEND))
804                                         mode[1] = 'w';
805                         }
806
807                         if (strcmp(mode, "---") != 0)
808                                 printf(" mode:%s", mode);
809                 }
810
811                 if (ef->cr_extra_flags & CLFE_XATTR) {
812                         struct changelog_ext_xattr *xattr =
813                                 changelog_rec_xattr(&rec->cr);
814
815                         if (xattr->cr_xattr[0] != '\0')
816                                 printf(" xattr:%s", xattr->cr_xattr);
817                 }
818         }
819
820         if (rec->cr.cr_namelen)
821                 printf(" parent:"DFID" name:%.*s", PFID(&rec->cr.cr_pfid),
822                        __le32_to_cpu(rec->cr.cr_namelen),
823                        changelog_rec_name(&rec->cr));
824
825         if (rec->cr.cr_flags & CLF_RENAME) {
826                 struct changelog_ext_rename *rnm =
827                         changelog_rec_rename(&rec->cr);
828
829                 if (!fid_is_zero(&rnm->cr_sfid))
830                         printf(" source_fid:"DFID" source_parent_fid:"DFID
831                                " %.*s",
832                                PFID(&rnm->cr_sfid),
833                                PFID(&rnm->cr_spfid),
834                                (int)__le32_to_cpu(
835                                        changelog_rec_snamelen(&rec->cr)),
836                                changelog_rec_sname(&rec->cr));
837         }
838         printf("\n");
839 }
840
841 static void lustre_swab_lu_fid(struct lu_fid *fid)
842 {
843         fid->f_seq = __swab64(fid->f_seq);
844         fid->f_oid = __swab32(fid->f_oid);
845         fid->f_ver = __swab32(fid->f_ver);
846 }
847
848 static inline size_t
849 update_op_size(unsigned int param_count)
850 {
851         return offsetof(struct update_op, uop_params_off[param_count]);
852 }
853
854
855 static inline struct update_op *
856 update_op_next_op(const struct update_op *uop)
857 {
858         return (struct update_op *)((char *)uop +
859                                 update_op_size(uop->uop_param_count));
860 }
861
862 static void lustre_swab_update_ops(struct update_ops *uops,
863                                    unsigned int op_count)
864 {
865         unsigned int i;
866         unsigned int j;
867
868         struct update_op *op =
869                (struct update_op *)((char *)&uops->uops_op[0]);
870
871         for (i = 0; i < op_count; i++, op = update_op_next_op(op)) {
872                 lustre_swab_lu_fid(&op->uop_fid);
873                 op->uop_type = __swab16(op->uop_type);
874                 op->uop_param_count = __swab16(op->uop_param_count);
875                 for (j = 0; j < op->uop_param_count; j++)
876                         op->uop_params_off[j] = __swab16(op->uop_params_off[j]);
877         }
878 }
879 static const char *update_op_str(__u16 opc)
880 {
881         static const char *opc_str[] = {
882                 [OUT_START] = "start",
883                 [OUT_CREATE] = "create",
884                 [OUT_DESTROY] = "destroy",
885                 [OUT_REF_ADD] = "ref_add",
886                 [OUT_REF_DEL] = "ref_del",
887                 [OUT_ATTR_SET] = "attr_set",
888                 [OUT_ATTR_GET] = "attr_get",
889                 [OUT_XATTR_SET] = "xattr_set",
890                 [OUT_XATTR_GET] = "xattr_get",
891                 [OUT_XATTR_LIST] = "xattr_list",
892                 [OUT_INDEX_LOOKUP] = "lookup",
893                 [OUT_INDEX_INSERT] = "insert",
894                 [OUT_INDEX_DELETE] = "delete",
895                 [OUT_WRITE] = "write",
896                 [OUT_XATTR_DEL] = "xattr_del",
897                 [OUT_PUNCH] = "punch",
898                 [OUT_READ] = "read",
899                 [OUT_NOOP] = "noop",
900         };
901
902         if (opc < (sizeof(opc_str) / sizeof((opc_str)[0])) &&
903             opc_str[opc] != NULL)
904                 return opc_str[opc];
905         else
906                 return "unknown";
907 }
908
909 static char *buf2str(void *buf, unsigned int size)
910 {
911         const char *hex = "0123456789ABCDEF";
912         char *buf_c = buf;
913         static char string[128];
914         int i, j = 0;
915         bool format_hex = false;
916
917         if (size > 0 && buf_c[size - 1] == 0)
918                 size--;
919         for (i = 0; i < size; i++) {
920                 if (buf_c[i] >= 0x20 && buf_c[i] <= 0x7E) {
921                         string[j++] = buf_c[i];
922                         format_hex = false;
923                 } else if (j < sizeof(string) - 6) {
924                         if (!format_hex) {
925                                 string[j++] = '\\';
926                                 string[j++] = 'x';
927                                 format_hex = true;
928                         }
929                         string[j++] = hex[(buf_c[i] >> 4) & 0xF];
930                         string[j++] = hex[buf_c[i] & 0xF];
931                 } else {
932                         break;
933                 }
934                 if (j == sizeof(string) - 2)
935                         break;
936         }
937         string[j] = 0;
938         return string;
939 }
940
941 static inline size_t
942 object_update_param_size(const struct object_update_param *param)
943 {
944         return roundup(sizeof(*param) + param->oup_len, sizeof(__u64));
945 }
946
947 static void print_update_rec(struct llog_update_record *lur)
948 {
949         struct update_records *rec = &lur->lur_update_rec;
950         unsigned int i, j, up_count, pm_count;
951         struct update_op *op;
952         struct object_update_param *pm;
953
954         up_count = __le32_to_cpu(rec->ur_update_count);
955         pm_count = __le32_to_cpu(rec->ur_param_count);
956         printf("updatelog record master_transno:%llu batchid:%llu flags:0x%x u_index:%d u_count:%d p_count:%d\n",
957                (unsigned long long)__le64_to_cpu(rec->ur_master_transno),
958                (unsigned long long)__le64_to_cpu(rec->ur_batchid),
959                __le32_to_cpu(rec->ur_flags),
960                __le32_to_cpu(rec->ur_index),
961                up_count,
962                pm_count);
963
964         op = (struct update_op *)((char *)&rec->ur_ops.uops_op[0] + 0);
965         if (op->uop_type != __le16_to_cpu(op->uop_type))
966                 lustre_swab_update_ops(&rec->ur_ops, up_count);
967
968         for (i = 0; i < up_count; i++, op = update_op_next_op(op)) {
969                 printf("\t"DFID" type:%s/%d params:%d ",
970                        PFID(&op->uop_fid), update_op_str(op->uop_type),
971                        op->uop_type, op->uop_param_count);
972                 for (j = 0; j < op->uop_param_count; j++)
973                         printf("p_%d:%d ", j, op->uop_params_off[j]);
974                 printf("\n");
975         }
976         pm = (struct object_update_param *) op;
977         for (i = 0; i < pm_count; i++) {
978                 printf("\tp_%d - %d/%s\n", i, pm->oup_len,
979                        buf2str(pm->oup_buf, pm->oup_len));
980                 pm = (struct object_update_param *)((char *)pm +
981                      object_update_param_size(pm));
982         }
983         printf("\n");
984
985 }
986
987 static void print_unlink_rec(struct llog_unlink_rec *lur)
988 {
989         printf("unlink record id:0x%x target %llx:%x:%x\n",
990                 __le32_to_cpu(lur->lur_hdr.lrh_id),
991                 (unsigned long long)__le64_to_cpu(lur->lur_oid),
992                 __le32_to_cpu(lur->lur_oseq),
993                 __le32_to_cpu(lur->lur_count));
994 }
995
996 static void print_unlink64_rec(struct llog_unlink64_rec *lur)
997 {
998         printf("unlink64 record id:0x%x target "DFID"\n",
999                 __le32_to_cpu(lur->lur_hdr.lrh_id),
1000                 PFID(&lur->lur_fid));
1001 }
1002
1003 static void print_setattr64_rec(struct llog_setattr64_rec *lsr)
1004 {
1005         printf("setattr64 record id:0x%x target "DFID" valid %llx uid %u:%u gid %u:%u\n",
1006                 __le32_to_cpu(lsr->lsr_hdr.lrh_id),
1007                 PFID(&lsr->lsr_oi.oi_fid),
1008                 (unsigned long long)__le64_to_cpu(lsr->lsr_valid),
1009                 __le32_to_cpu(lsr->lsr_uid_h),
1010                 __le32_to_cpu(lsr->lsr_uid),
1011                 __le32_to_cpu(lsr->lsr_gid_h),
1012                 __le32_to_cpu(lsr->lsr_gid));
1013 }
1014
1015 static void print_setattr64_rec_v2(struct llog_setattr64_rec_v2 *lsr)
1016 {
1017         printf("setattr64 v2 record id:0x%x target "DFID" valid %llx uid %u:%u gid %u:%u prj %u\n",
1018                 __le32_to_cpu(lsr->lsr_hdr.lrh_id),
1019                 PFID(&lsr->lsr_oi.oi_fid),
1020                 (unsigned long long)__le64_to_cpu(lsr->lsr_valid),
1021                 __le32_to_cpu(lsr->lsr_uid_h),
1022                 __le32_to_cpu(lsr->lsr_uid),
1023                 __le32_to_cpu(lsr->lsr_gid_h),
1024                 __le32_to_cpu(lsr->lsr_gid),
1025                 __le32_to_cpu(lsr->lsr_projid));
1026 }
1027
1028 static void print_changelog_user_rec(struct llog_changelog_user_rec *rec)
1029 {
1030         struct llog_rec_hdr *lrh = &rec->cur_hdr;
1031         bool is_rec_v2 = (__le32_to_cpu(lrh->lrh_type) == CHANGELOG_USER_REC2);
1032
1033         printf("changelog user record (%s) id:0x%x cur_id:%u cur_endrec:%llu cur_time:%u%s",
1034                is_rec_v2 ? "v2" : "v1",
1035                __le32_to_cpu(lrh->lrh_id),
1036                __le32_to_cpu(rec->cur_id),
1037                __le64_to_cpu(rec->cur_endrec),
1038                __le32_to_cpu(rec->cur_time),
1039                is_rec_v2 ? " " : "\n");
1040
1041         if (is_rec_v2) {
1042                 struct llog_changelog_user_rec2 *rec2 = (typeof(rec2)) rec;
1043
1044                 printf("cur_mask:0x%08x cur_name:\"%.*s\"\n",
1045                         __le32_to_cpu(rec2->cur_mask),
1046                         (int) sizeof(rec2->cur_name), rec2->cur_name);
1047         }
1048
1049 }
1050
1051 static void print_records(struct llog_rec_hdr **recs,
1052                           int rec_number, int is_ext)
1053 {
1054         __u32 lopt;
1055         int i, skip = 0;
1056
1057         for (i = 0; i < rec_number; i++) {
1058                 if (!recs[i]) {
1059                         llapi_printf(LLAPI_MSG_NORMAL,
1060                                      "uninitialized llog record at index %d\n",
1061                                      i);
1062                         break;
1063                 }
1064                 printf("#%.2d (%.3d)", __le32_to_cpu(recs[i]->lrh_index),
1065                        __le32_to_cpu(recs[i]->lrh_len));
1066
1067                 lopt = __le32_to_cpu(recs[i]->lrh_type);
1068
1069                 if (recs[i]->lrh_id == CANCELLED)
1070                         printf("NOT SET ");
1071
1072                 switch (lopt) {
1073                 case OBD_CFG_REC:
1074                         print_lustre_cfg(
1075                                 (struct lustre_cfg *)((char *)(recs[i]) +
1076                                 sizeof(struct llog_rec_hdr)), &skip);
1077                         break;
1078                 case LLOG_PAD_MAGIC:
1079                         printf("padding\n");
1080                         break;
1081                 case LLOG_LOGID_MAGIC:
1082                         print_log_path((struct llog_logid_rec *)recs[i],
1083                                        is_ext);
1084                         break;
1085                 case HSM_AGENT_REC:
1086                         print_hsm_action((struct llog_agent_req_rec *)recs[i]);
1087                         break;
1088                 case CHANGELOG_REC:
1089                         print_changelog_rec((struct llog_changelog_rec *)
1090                                             recs[i]);
1091                         break;
1092                 case CHANGELOG_USER_REC:
1093                 case CHANGELOG_USER_REC2:
1094                         print_changelog_user_rec((struct
1095                                                   llog_changelog_user_rec *)
1096                                                  recs[i]);
1097                         break;
1098                 case UPDATE_REC:
1099                         print_update_rec((struct llog_update_record *)recs[i]);
1100                         break;
1101                 case MDS_UNLINK_REC:
1102                         print_unlink_rec((struct llog_unlink_rec *)recs[i]);
1103                         break;
1104                 case MDS_UNLINK64_REC:
1105                         print_unlink64_rec((struct llog_unlink64_rec *)recs[i]);
1106                         break;
1107                 case MDS_SETATTR64_REC:
1108                         if (__le32_to_cpu(recs[i]->lrh_len) >
1109                                 sizeof(struct llog_setattr64_rec)) {
1110                                 print_setattr64_rec_v2(
1111                                   (struct llog_setattr64_rec_v2 *)recs[i]);
1112                         } else {
1113                                 print_setattr64_rec(
1114                                         (struct llog_setattr64_rec *)recs[i]);
1115                         }
1116                         break;
1117                 default:
1118                         printf("unknown type %x\n", lopt);
1119                         break;
1120                 }
1121         }
1122 }
1123
1124 /** @} llog_reader */