Whamcloud - gitweb
LU-12757 utils: avoid newline inside error message
[fs/lustre-release.git] / lustre / utils / llog_reader.c
index 890de00..01e59de 100644 (file)
@@ -23,7 +23,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -40,6 +40,7 @@
 #include <limits.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <linux/magic.h>
 #include <errno.h>
 #include <time.h>
-#include <lnet/nidstr.h>
-#include <lustre/lustre_fid.h>
-#include <lustre/lustre_ostid.h>
+#include <linux/lnet/nidstr.h>
+#include <linux/lustre/lustre_cfg.h>
+#include <linux/lustre/lustre_fid.h>
+#include <linux/lustre/lustre_ostid.h>
+#include <linux/lustre/lustre_log_user.h>
 #include <lustre/lustreapi.h>
-#include <lustre_log_user.h>
-#include <lustre_cfg.h>
 
 static inline int ext2_test_bit(int nr, const void *addr)
 {
@@ -153,9 +154,9 @@ static void print_log_path(struct llog_logid_rec *lid, int is_ext)
                         (uintmax_t)(fid_from_logid.f_seq & (OSD_OI_FID_NR - 1)),
                         PFID(&fid_from_logid));
 
-       printf("ogen=%X id="DOSTID" path=%s\n",
-               lid->lid_id.lgl_ogen, POSTID(&lid->lid_id.lgl_oi),
-               object_path);
+       printf("id="DFID":%x path=%s\n",
+              PFID(&lid->lid_id.lgl_oi.oi_fid), lid->lid_id.lgl_ogen,
+              object_path);
 }
 
 int main(int argc, char **argv)
@@ -184,7 +185,8 @@ int main(int argc, char **argv)
        is_ext = is_fstype_ext(fd);
        if (is_ext < 0) {
                rc = is_ext;
-               printf("Unable to determine type of filesystem containing %s\n",
+               llapi_error(LLAPI_MSG_ERROR, -rc,
+                           "Unable to determine filesystem type for %s",
                       argv[1]);
                goto out_fd;
        }
@@ -195,8 +197,10 @@ int main(int argc, char **argv)
                goto out_fd;
        }
 
-       print_llog_header(llog_buf);
-       print_records(recs_buf, rec_number, is_ext);
+       if (llog_buf != NULL)
+               print_llog_header(llog_buf);
+       if (recs_buf != NULL)
+               print_records(recs_buf, rec_number, is_ext);
        llog_unpack_buffer(fd, llog_buf, recs_buf);
 
 out_fd:
@@ -217,6 +221,7 @@ int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
        char *file_buf = NULL, *recs_buf = NULL;
        struct llog_rec_hdr **recs_pr = NULL;
        char *ptr = NULL;
+       int count;
        int i;
 
        rc = fstat(fd, &st);
@@ -229,8 +234,7 @@ int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
        file_size = st.st_size;
        if (file_size < sizeof(**llog)) {
                llapi_error(LLAPI_MSG_ERROR, rc,
-                           "File too small for llog header: "
-                           "need %zd, size %lld\n",
+                           "File too small for llog header: want=%zd got=%lld",
                            sizeof(**llog), file_size);
                rc = -EIO;
                goto out;
@@ -258,10 +262,23 @@ int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
                goto clear_file_buf;
        }
 
+       count = __le32_to_cpu((*llog)->llh_count);
+       if (count < 0) {
+               rc = -EINVAL;
+               llapi_error(LLAPI_MSG_ERROR, rc,
+                           "corrupted llog: negative record number %d",
+                           count);
+               goto clear_file_buf;
+       } else if (count == 0) {
+               llapi_printf(LLAPI_MSG_NORMAL,
+                            "uninitialized llog: zero record number\n");
+               *recs_number = 0;
+               goto clear_file_buf;
+       }
        /* the llog header not countable here.*/
-       recs_num = __le32_to_cpu((*llog)->llh_count) - 1;
+       recs_num = count - 1;
 
-       recs_buf = malloc(recs_num * sizeof(**recs_pr));
+       recs_buf = calloc(recs_num, sizeof(**recs_pr));
        if (recs_buf == NULL) {
                rc = -ENOMEM;
                llapi_error(LLAPI_MSG_ERROR, rc,
@@ -333,11 +350,12 @@ clear_file_buf:
 }
 
 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
-                        struct llog_rec_hdr **recs_buf)
+                       struct llog_rec_hdr **recs_buf)
 {
-        free(llog_buf);
-        free(recs_buf);
-        return;
+       if (llog_buf != NULL)
+               free(llog_buf);
+       if (recs_buf != NULL)
+               free(recs_buf);
 }
 
 void print_llog_header(struct llog_log_hdr *llog_buf)
@@ -359,7 +377,6 @@ void print_llog_header(struct llog_log_hdr *llog_buf)
        /* Add the other info you want to view here */
 
        printf("-----------------------\n");
-       return;
 }
 
 static void print_1_cfg(struct lustre_cfg *lcfg)
@@ -374,9 +391,40 @@ static void print_1_cfg(struct lustre_cfg *lcfg)
         for (i = 0; i <  lcfg->lcfg_bufcount; i++)
                 printf("%d:%.*s  ", i, lcfg->lcfg_buflens[i],
                        (char*)lustre_cfg_buf(lcfg, i));
-        return;
 }
 
+static char *lustre_cfg_string(struct lustre_cfg *lcfg, __u32 index)
+{
+       char *s;
+
+       if (lcfg->lcfg_buflens[index] == 0)
+               return NULL;
+
+       s = lustre_cfg_buf(lcfg, index);
+       if (s == NULL)
+               return NULL;
+
+       /*
+        * make sure it's NULL terminated, even if this kills a char
+        * of data. Try to use the padding first though.
+        */
+       if (s[lcfg->lcfg_buflens[index] - 1] != '\0') {
+               size_t last = __ALIGN_KERNEL(lcfg->lcfg_buflens[index], 8) - 1;
+               char lost;
+
+               /* Use the smaller value */
+               if (last > lcfg->lcfg_buflens[index])
+                       last = lcfg->lcfg_buflens[index];
+
+               lost = s[last];
+               s[last] = '\0';
+               if (lost != '\0') {
+                       fprintf(stderr, "Truncated buf %d to '%s' (lost '%c'...)\n",
+                               index, s, lost);
+               }
+       }
+       return s;
+}
 
 static void print_setup_cfg(struct lustre_cfg *lcfg)
 {
@@ -398,8 +446,6 @@ static void print_setup_cfg(struct lustre_cfg *lcfg)
                 printf("setup     ");
                 print_1_cfg(lcfg);
         }
-
-        return;
 }
 
 void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
@@ -587,7 +633,6 @@ void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
                 printf("unsupported cmd_code = %x\n",cmd);
         }
         printf("\n");
-        return;
 }
 
 static void print_hsm_action(struct llog_agent_req_rec *larr)
@@ -621,11 +666,104 @@ static void print_hsm_action(struct llog_agent_req_rec *larr)
 
 void print_changelog_rec(struct llog_changelog_rec *rec)
 {
-       printf("changelog record id:0x%x cr_flags:0x%x cr_type:%s(0x%x)\n",
-              __le32_to_cpu(rec->cr_hdr.lrh_id),
+       time_t secs;
+       struct tm ts;
+
+       secs = __le64_to_cpu(rec->cr.cr_time) >> 30;
+       gmtime_r(&secs, &ts);
+       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, __le32_to_cpu(rec->cr_hdr.lrh_id),
+              __le64_to_cpu(rec->cr.cr_index),
               __le32_to_cpu(rec->cr.cr_flags),
               changelog_type2str(__le32_to_cpu(rec->cr.cr_type)),
-              __le32_to_cpu(rec->cr.cr_type));
+              __le32_to_cpu(rec->cr.cr_type),
+              ts.tm_hour, ts.tm_min, ts.tm_sec,
+              (int)(__le64_to_cpu(rec->cr.cr_time) & ((1 << 30) - 1)),
+              ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday,
+              PFID(&rec->cr.cr_tfid));
+
+       if (rec->cr.cr_flags & CLF_JOBID) {
+               struct changelog_ext_jobid *jid =
+                       changelog_rec_jobid(&rec->cr);
+
+               if (jid->cr_jobid[0] != '\0')
+                       printf(" jobid:%s", jid->cr_jobid);
+       }
+
+       if (rec->cr.cr_flags & CLF_EXTRA_FLAGS) {
+               struct changelog_ext_extra_flags *ef =
+                       changelog_rec_extra_flags(&rec->cr);
+
+               printf(" cr_extra_flags:0x%llx",
+                      __le64_to_cpu(ef->cr_extra_flags));
+
+               if (ef->cr_extra_flags & CLFE_UIDGID) {
+                       struct changelog_ext_uidgid *uidgid =
+                               changelog_rec_uidgid(&rec->cr);
+
+                       printf(" user:%u:%u",
+                              __le32_to_cpu(uidgid->cr_uid),
+                              __le32_to_cpu(uidgid->cr_gid));
+               }
+               if (ef->cr_extra_flags & CLFE_NID) {
+                       struct changelog_ext_nid *nid =
+                               changelog_rec_nid(&rec->cr);
+
+                       printf(" nid:%s",
+                              libcfs_nid2str(nid->cr_nid));
+               }
+
+               if (ef->cr_extra_flags & CLFE_OPEN) {
+                       struct changelog_ext_openmode *omd =
+                               changelog_rec_openmode(&rec->cr);
+                       char mode[] = "---";
+
+                       /* exec mode must be exclusive */
+                       if (__le32_to_cpu(omd->cr_openflags) & MDS_FMODE_EXEC) {
+                               mode[2] = 'x';
+                       } else {
+                               if (__le32_to_cpu(omd->cr_openflags) &
+                                   MDS_FMODE_READ)
+                                       mode[0] = 'r';
+                               if (__le32_to_cpu(omd->cr_openflags) &
+                          (MDS_FMODE_WRITE | MDS_OPEN_TRUNC | MDS_OPEN_APPEND))
+                                       mode[1] = 'w';
+                       }
+
+                       if (strcmp(mode, "---") != 0)
+                               printf(" mode:%s", mode);
+
+               }
+
+               if (ef->cr_extra_flags & CLFE_XATTR) {
+                       struct changelog_ext_xattr *xattr =
+                               changelog_rec_xattr(&rec->cr);
+
+                       if (xattr->cr_xattr[0] != '\0')
+                               printf(" xattr:%s", xattr->cr_xattr);
+               }
+       }
+
+       if (rec->cr.cr_namelen)
+               printf(" parent:"DFID" name:%.*s", PFID(&rec->cr.cr_pfid),
+                      __le32_to_cpu(rec->cr.cr_namelen),
+                      changelog_rec_name(&rec->cr));
+
+       if (rec->cr.cr_flags & CLF_RENAME) {
+               struct changelog_ext_rename *rnm =
+                       changelog_rec_rename(&rec->cr);
+
+               if (!fid_is_zero(&rnm->cr_sfid))
+                       printf(" source_fid:"DFID" source_parent_fid:"DFID
+                              " %.*s",
+                              PFID(&rnm->cr_sfid),
+                              PFID(&rnm->cr_spfid),
+                              (int)__le32_to_cpu(
+                                      changelog_rec_snamelen(&rec->cr)),
+                              changelog_rec_sname(&rec->cr));
+       }
+       printf("\n");
 }
 
 static void print_records(struct llog_rec_hdr **recs,
@@ -635,6 +773,12 @@ static void print_records(struct llog_rec_hdr **recs,
        int i, skip = 0;
 
        for (i = 0; i < rec_number; i++) {
+               if (recs[i] == NULL) {
+                       llapi_printf(LLAPI_MSG_NORMAL,
+                                    "uninitialized llog record at index %d\n",
+                                    i);
+                       break;
+               }
                printf("#%.2d (%.3d)", __le32_to_cpu(recs[i]->lrh_index),
                       __le32_to_cpu(recs[i]->lrh_len));