X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Flr_reader.c;h=a6d94c164292c01e64dccce942bc7f3b662b8032;hb=2f8d7b4679de3fa467040aa61733f262714e39c9;hp=996f4d9b01610db2441d7d92b029b1a58be4839c;hpb=6869932b552ac705f411de3362f01bd50c1f6f7d;p=fs%2Flustre-release.git diff --git a/lustre/utils/lr_reader.c b/lustre/utils/lr_reader.c index 996f4d9..a6d94c1 100644 --- a/lustre/utils/lr_reader.c +++ b/lustre/utils/lr_reader.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -17,17 +15,15 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -39,9 +35,16 @@ */ /* Safely read the last_rcvd file from a device */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include +#include +#include #include #include #include @@ -56,170 +59,334 @@ #include #include -#include -#include +#include +#include +#include -int run_command(char *cmd) +char *progname; +static struct option const long_opts[] = { + { .val = 'c', .name = "client", .has_arg = no_argument }, + { .val = 'h', .name = "help", .has_arg = no_argument }, + { .val = 'r', .name = "reply", .has_arg = no_argument }, + { .name = NULL } }; + +/* Executes the command \a cmd and returns command status. + */ +int run_command(char *cmd, size_t cmdsz) { - char log[] = "/tmp/mkfs_logXXXXXX"; - int fd, rc; - - - if ((fd = mkstemp(log)) >= 0) { - close(fd); - strcat(cmd, " >"); - strcat(cmd, log); - } - strcat(cmd, " 2>&1"); - - /* Can't use popen because we need the rv of the command */ - rc = system(cmd); - if (rc && fd >= 0) { - char buf[128]; - FILE *fp; - fp = fopen(log, "r"); - if (fp) { - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (rc) - printf(" %s", buf); - } - fclose(fp); - } - } - if (fd >= 0) - remove(log); - return rc; -} + char log[] = "/tmp/run_command_logXXXXXX"; + int fd, rc; + + if (strlen(cmd) + strlen(log) + 8 > cmdsz) { + fprintf(stderr, "Command buffer overflow: %.*s...\n", + (int)cmdsz, cmd); + return -ENOMEM; + } + + fd = mkstemp(log); + if (fd >= 0) { + close(fd); + strncat(cmd, " >", 2); + strncat(cmd, log, strlen(log)); + } + strncat(cmd, " 2>&1", 5); + + /* Can't use popen because we need the rv of the command */ + rc = system(cmd); + if (rc && fd >= 0) { + char buf[128]; + FILE *fp; + fp = fopen(log, "r"); + if (fp) { + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (rc) + printf(" %s", buf); + } + fclose(fp); + } + } + if (fd >= 0) + remove(log); + return rc; +} +void display_usage(void) +{ + printf("Usage: %s [OPTIONS] devicename\n", progname); + printf("Read and print the last_rcvd file from a device\n"); + printf("(safe for mounted devices)\n"); + printf("\t-c, --client, display client information\n"); + printf("\t-h, --help, display this help and exit\n"); + printf("\t-r, --reply, display reply data information\n"); +} + int main(int argc, char *const argv[]) { - char tmpdir[] = "/tmp/dirXXXXXX"; - char cmd[128]; - char filepnm[128]; - char *progname, *dev; - struct lr_server_data lsd; - FILE *filep; - int ret; - - if ((argc < 2) || (argv[argc - 1][0] == '-')) { - printf("Usage: %s devicename\n", argv[0]); - printf("Read and print the last_rcvd file from a device\n"); - printf("(safe for mounted devices)\n"); - return EINVAL; - } - - progname = argv[0]; - dev = argv[argc - 1]; - - /* Make a temporary directory to hold Lustre data files. */ - if (!mkdtemp(tmpdir)) { - fprintf(stderr, "%s: Can't create temporary directory %s: %s\n", - progname, tmpdir, strerror(errno)); - return errno; - } - - memset(cmd, 0, sizeof(cmd)); - sprintf(cmd, - "debugfs -c -R 'dump /%s %s/%s' %s", - LAST_RCVD, tmpdir, LAST_RCVD, dev); - - ret = run_command(cmd); - if (ret) { - fprintf(stderr, "%s: Unable to dump %s file\n", - progname, LAST_RCVD); - goto out_rmdir; - } - - sprintf(filepnm, "%s/%s", tmpdir, LAST_RCVD); - filep = fopen(filepnm, "r"); - if (!filep) { - fprintf(stderr, "%s: Unable to read old data\n", - progname); - ret = -errno; - goto out_rmdir; - } - - printf("Reading %s\n", LAST_RCVD); - ret = fread(&lsd, 1, sizeof(lsd), filep); - if (ret < sizeof(lsd)) { - fprintf(stderr, "%s: Short read (%d of %d)\n", - progname, ret, (int)sizeof(lsd)); - ret = -ferror(filep); - if (ret) - goto out_close; - } - - #if 0 - __u8 lsd_uuid[40]; /* server UUID */ - __u64 lsd_last_transno; /* last completed transaction ID */ - __u64 lsd_compat14; /* reserved - compat with old last_rcvd */ - __u64 lsd_mount_count; /* incarnation number */ - __u32 lsd_feature_compat; /* compatible feature flags */ - __u32 lsd_feature_rocompat;/* read-only compatible feature flags */ - __u32 lsd_feature_incompat;/* incompatible feature flags */ - __u32 lsd_server_size; /* size of server data area */ - __u32 lsd_client_start; /* start of per-client data area */ - __u16 lsd_client_size; /* size of per-client data area */ - __u16 lsd_subdir_count; /* number of subdirectories for objects */ - __u64 lsd_catalog_oid; /* recovery catalog object id */ - __u32 lsd_catalog_ogen; /* recovery catalog inode generation */ - __u8 lsd_peeruuid[40]; /* UUID of MDS associated with this OST */ - __u32 lsd_ost_index; /* index number of OST in LOV */ - __u32 lsd_mdt_index; /* index number of MDT in LMV */ - __u8 lsd_padding[LR_SERVER_SIZE - 148]; - #endif - - printf("UUID %s\n", lsd.lsd_uuid); - printf("Feature compat=%#x\n", lsd.lsd_feature_compat); - printf("Feature incompat=%#x\n", lsd.lsd_feature_incompat); - printf("Feature rocompat=%#x\n", lsd.lsd_feature_rocompat); - printf("Last transaction %llu\n", (long long)lsd.lsd_last_transno); - printf("ost index %u\n", lsd.lsd_ost_index); - printf("mdt index %u\n", lsd.lsd_mdt_index); - - if ((lsd.lsd_feature_compat & OBD_COMPAT_OST) || - (lsd.lsd_feature_incompat & OBD_INCOMPAT_OST)) { - printf("OST, index %d\n", lsd.lsd_ost_index); - } else if ((lsd.lsd_feature_compat & OBD_COMPAT_MDT) || - (lsd.lsd_feature_incompat & OBD_INCOMPAT_MDT)) { - /* We must co-locate so mgs can see old logs. - If user doesn't want this, they can copy the old - logs manually and re-tunefs. */ - printf("MDS, index %d\n", lsd.lsd_mdt_index); - } else { - /* If neither is set, we're pre-1.4.6, make a guess. */ - /* Construct debugfs command line. */ - memset(cmd, 0, sizeof(cmd)); - sprintf(cmd, - "debugfs -c -R 'rdump /%s %s' %s", - MDT_LOGS_DIR, tmpdir, dev); - - run_command(cmd); - - sprintf(filepnm, "%s/%s", tmpdir, MDT_LOGS_DIR); - if (lsd.lsd_ost_index > 0) { - printf("non-flagged OST, index %d\n", - lsd.lsd_ost_index); - } else { - /* If there's a LOGS dir, it's an MDT */ - if ((ret = access(filepnm, F_OK)) == 0) { - /* Old MDT's are always index 0 - (pre CMD) */ - printf("non-flagged MDS, index 0\n"); - } else { - printf("non-flagged OST, index unknown\n"); - } - } - } - -out_close: - fclose(filep); + char tmpdir[] = "/tmp/dirXXXXXX"; + char cmd[128]; + char filepnm[128] = ""; + char *dev; + struct lr_server_data lsd; + FILE *filep = NULL; + int ret; + int c; + int opt_client = 0; + int opt_reply = 0; + + progname = argv[0]; + while ((c = getopt_long(argc, argv, "chr", long_opts, NULL)) != -1) { + switch (c) { + case 'c': + opt_client = 1; + break; + case 'r': + opt_reply = 1; + break; + case 'h': + default: + display_usage(); + return -1; + } + } + dev = argv[optind]; + if (!dev) { + display_usage(); + return -1; + } + + /* Make a temporary directory to hold Lustre data files. */ + if (!mkdtemp(tmpdir)) { + fprintf(stderr, "%s: Can't create temporary directory %s: %s\n", + progname, tmpdir, strerror(errno)); + return errno; + } + + memset(cmd, 0, sizeof(cmd)); + snprintf(cmd, sizeof(cmd), + "%s -c -R 'dump /%s %s/%s' %s", + DEBUGFS, LAST_RCVD, tmpdir, LAST_RCVD, dev); + + ret = run_command(cmd, sizeof(cmd)); + if (ret) { + fprintf(stderr, "%s: Unable to dump %s file\n", + progname, LAST_RCVD); + goto out_rmdir; + } + + snprintf(filepnm, 128, "%s/%s", tmpdir, LAST_RCVD); + filep = fopen(filepnm, "r"); + if (!filep) { + fprintf(stderr, "%s: Unable to read old data\n", + progname); + ret = -errno; + goto out_rmdir; + } + unlink(filepnm); + + /* read lr_server_data structure */ + printf("%s:\n", LAST_RCVD); + ret = fread(&lsd, 1, sizeof(lsd), filep); + if (ret < sizeof(lsd)) { + fprintf(stderr, "%s: Short read (%d of %d)\n", + progname, ret, (int)sizeof(lsd)); + ret = -ferror(filep); + if (ret) + goto out_close; + } + + /* swab structure fields of interest */ + lsd.lsd_feature_compat = __le32_to_cpu(lsd.lsd_feature_compat); + lsd.lsd_feature_incompat = __le32_to_cpu(lsd.lsd_feature_incompat); + lsd.lsd_feature_rocompat = __le32_to_cpu(lsd.lsd_feature_rocompat); + lsd.lsd_last_transno = __le64_to_cpu(lsd.lsd_last_transno); + lsd.lsd_osd_index = __le32_to_cpu(lsd.lsd_osd_index); + lsd.lsd_mount_count = __le64_to_cpu(lsd.lsd_mount_count); + + /* display */ + printf(" uuid: %.40s\n", lsd.lsd_uuid); + printf(" feature_compat: %#x\n", lsd.lsd_feature_compat); + printf(" feature_incompat: %#x\n", lsd.lsd_feature_incompat); + printf(" feature_rocompat: %#x\n", lsd.lsd_feature_rocompat); + printf(" last_transaction: %llu\n", lsd.lsd_last_transno); + printf(" target_index: %u\n", lsd.lsd_osd_index); + printf(" mount_count: %llu\n", lsd.lsd_mount_count); + + /* read client information */ + if (opt_client) { + lsd.lsd_client_start = __le32_to_cpu(lsd.lsd_client_start); + lsd.lsd_client_size = __le16_to_cpu(lsd.lsd_client_size); + printf(" client_area_start: %u\n", lsd.lsd_client_start); + printf(" client_area_size: %hu\n", lsd.lsd_client_size); + + /* seek to per-client data area */ + ret = fseek(filep, lsd.lsd_client_start, SEEK_SET); + if (ret) { + fprintf(stderr, "%s: seek failed. %s\n", + progname, strerror(errno)); + ret = errno; + goto out_close; + } + + /* walk throuh the per-client data area */ + while (true) { + struct lsd_client_data lcd; + + /* read a per-client data area */ + ret = fread(&lcd, 1, sizeof(lcd), filep); + if (ret < sizeof(lcd)) { + if (feof(filep)) + break; + fprintf(stderr, "%s: Short read (%d of %d)\n", + progname, ret, (int)sizeof(lcd)); + ret = -ferror(filep); + goto out_close; + } + + if (lcd.lcd_uuid[0] == '\0') + continue; + + /* swab structure fields */ + lcd.lcd_last_transno = + __le64_to_cpu(lcd.lcd_last_transno); + lcd.lcd_last_xid = __le64_to_cpu(lcd.lcd_last_xid); + lcd.lcd_last_result = __le32_to_cpu(lcd.lcd_last_result); + lcd.lcd_last_data = __le32_to_cpu(lcd.lcd_last_data); + lcd.lcd_generation = __le32_to_cpu(lcd.lcd_generation); + + /* display per-client data area */ + printf("\n %.40s:\n", lcd.lcd_uuid); + printf(" generation: %u\n", lcd.lcd_generation); + printf(" last_transaction: %llu\n", + lcd.lcd_last_transno); + printf(" last_xid: %llu\n", lcd.lcd_last_xid); + printf(" last_result: %u\n", lcd.lcd_last_result); + printf(" last_data: %u\n", lcd.lcd_last_data); + + if (lcd.lcd_last_close_transno != 0 && + lcd.lcd_last_close_xid != 0) { + lcd.lcd_last_close_transno = + __le64_to_cpu(lcd.lcd_last_close_transno); + lcd.lcd_last_close_xid = + __le64_to_cpu(lcd.lcd_last_close_xid); + lcd.lcd_last_close_result = + __le32_to_cpu(lcd.lcd_last_close_result); + lcd.lcd_last_close_data = + __le32_to_cpu(lcd.lcd_last_close_data); + printf(" last_close_transation: %llu\n", + lcd.lcd_last_close_transno); + printf(" last_close_xid: %llu\n", + lcd.lcd_last_close_xid); + printf(" last_close_result: %u\n", + lcd.lcd_last_close_result); + printf(" last_close_data: %u\n", + lcd.lcd_last_close_data); + } + } + } + fclose(filep); + filep = NULL; + + /* read reply data information */ + if (opt_reply) { + struct lsd_reply_header lrh; + struct lsd_reply_data lrd; + unsigned long long slot; + + snprintf(cmd, sizeof(cmd), + "%s -c -R 'dump /%s %s/%s' %s", + DEBUGFS, REPLY_DATA, tmpdir, REPLY_DATA, dev); + + ret = run_command(cmd, sizeof(cmd)); + if (ret) { + fprintf(stderr, "%s: Unable to dump %s file\n", + progname, REPLY_DATA); + goto out_rmdir; + } + + snprintf(filepnm, sizeof(filepnm), + "%s/%s", tmpdir, REPLY_DATA); + filep = fopen(filepnm, "r"); + if (!filep) { + fprintf(stderr, "%s: Unable to read reply data\n", + progname); + ret = -errno; + goto out_rmdir; + } + unlink(filepnm); + + /* read reply_data header */ + printf("\n%s:\n", REPLY_DATA); + ret = fread(&lrh, 1, sizeof(lrh), filep); + if (ret < sizeof(lrh)) { + fprintf(stderr, "%s: Short read (%d of %d)\n", + progname, ret, (int)sizeof(lrh)); + ret = -ferror(filep); + if (ret) + goto out_close; + } + + /* check header */ + lrh.lrh_magic = __le32_to_cpu(lrh.lrh_magic); + lrh.lrh_header_size = __le32_to_cpu(lrh.lrh_header_size); + lrh.lrh_reply_size = __le32_to_cpu(lrh.lrh_reply_size); + if (lrh.lrh_magic != LRH_MAGIC) { + fprintf(stderr, "%s: invalid %s header: " + "lrh_magic=%08x expected %08x\n", + progname, REPLY_DATA, lrh.lrh_magic, LRH_MAGIC); + goto out_close; + } + if (lrh.lrh_header_size != sizeof(struct lsd_reply_header)) { + fprintf(stderr, "%s: invalid %s header: " + "lrh_header_size=%08x expected %08x\n", + progname, REPLY_DATA, lrh.lrh_header_size, + (unsigned int)sizeof(struct lsd_reply_header)); + goto out_close; + } + if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data)) { + fprintf(stderr, "%s: invalid %s header: " + "lrh_reply_size=%08x expected %08x\n", + progname, REPLY_DATA, lrh.lrh_reply_size, + (unsigned int)sizeof(struct lsd_reply_data)); + goto out_close; + } + + /* walk throuh the reply data */ + for (slot = 0; ; slot++) { + /* read a reply data */ + ret = fread(&lrd, 1, sizeof(lrd), filep); + if (ret < sizeof(lrd)) { + if (feof(filep)) + break; + fprintf(stderr, "%s: Short read (%d of %d)\n", + progname, ret, (int)sizeof(lrd)); + ret = -ferror(filep); + goto out_close; + } + + /* display reply data */ + lrd.lrd_transno = __le64_to_cpu(lrd.lrd_transno); + lrd.lrd_xid = __le64_to_cpu(lrd.lrd_xid); + lrd.lrd_data = __le64_to_cpu(lrd.lrd_data); + lrd.lrd_result = __le32_to_cpu(lrd.lrd_result); + lrd.lrd_client_gen = __le32_to_cpu(lrd.lrd_client_gen); + + printf(" %lld:\n", slot); + printf(" client_generation: %u\n", + lrd.lrd_client_gen); + printf(" last_transaction: %llu\n", lrd.lrd_transno); + printf(" last_xid: %llu\n", lrd.lrd_xid); + printf(" last_result: %u\n", lrd.lrd_result); + printf(" last_data: %llu\n\n", lrd.lrd_data); + } + } + +out_close: + if (filep != NULL) + fclose(filep); out_rmdir: - memset(cmd, 0, sizeof(cmd)); - sprintf(cmd, "rm -rf %s", tmpdir); - run_command(cmd); - return ret; + rmdir(tmpdir); + return ret; }