]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
cmd: Implement "vos examine"
authorDavid Howells <dhowells@redhat.com>
Mon, 6 Jul 2020 22:13:50 +0000 (23:13 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 5 May 2023 09:05:31 +0000 (10:05 +0100)
Signed-off-by: David Howells <dhowells@redhat.com>
kafs/Makefile
kafs/display.h
kafs/display_vol.c
kafs/vos_examine.c [new file with mode: 0644]

index ad08be58ccdb0d6439b59350058280654a8aa32e..cf2174dd36672d95715cbe0a10576bb12c392034 100644 (file)
@@ -31,6 +31,7 @@ PTS_SRCS := \
 
 VOS_SRCS := \
        vos.c \
+       vos_examine.c \
        vos_help.c \
        vos_listvldb.c \
        vos_status.c
index 20e5c350e0f39cec9e004b901e97387c2ce1a016..08c505c7e30f831242c440be00fe27c3633140db 100644 (file)
@@ -16,6 +16,7 @@
 
 struct kafs_vldb_entry;
 struct kafs_vldb_site;
+struct kafs_volume_info;
 
 /*
  * display.c
@@ -36,5 +37,12 @@ extern bool kafs_display_error(struct kafs_context *);
 extern void kafs_sprint_site(struct kafs_context *, struct kafs_vldb_site *, char *, size_t);
 extern void kafs_display_vldb_site_list(struct kafs_context *, struct kafs_vldb_entry *,
                                        const char *);
+extern void display_vol_information(struct kafs_context *, struct kafs_fileserver *,
+                                   struct kafs_partition *, struct kafs_volume_info *);
+extern void display_vol_statistics(struct kafs_context *, struct kafs_volume_info *);
+extern void display_vol_mp_basic_information(struct kafs_context *, struct kafs_fileserver *,
+                                            struct kafs_partition *, struct kafs_volume_info *);
+extern void display_vol_mp_information(struct kafs_context *, struct kafs_fileserver *,
+                                      struct kafs_partition *, struct kafs_volume_info *);
 
 #endif /* DISPLAY_H */
index 73e3de2893faaeb2debad8b1303c9f096cd8f9ab..0cda8d5ee758039c0f946cc93d034de6512e4d64 100644 (file)
 #include "display.h"
 
 
+static const char *const statistics_time_ranges[] = {
+    "0-60 sec ",
+    "1-10 min ",
+    "10min-1hr",
+    "1hr-1day ",
+    "1day-1wk ",
+    "> 1wk    "
+};
+
+static const char *vol_type(struct kafs_volume_info *vi, char *tbuf)
+{
+       switch (vi->type) {
+       case 0:  return "RW";
+       case 1:  return "RO";
+       case 2:  return "BK";
+       default:
+               sprintf(tbuf, "0x%02x", vi->type);
+               return tbuf;
+       }
+}
+
+static const char *vol_state(const struct kafs_volume_info *vi)
+{
+        if (!vi->needs_salvage) {
+               if (vi->in_use)
+                       return "On-line";
+               else
+                       return "Off-line";
+       } else {
+               if (vi->in_use)
+                       return "On-line**needs salvage**";
+               else
+                       return "Off-line**needs salvage**";
+       }
+}
+
+static const char *vol_status(const struct kafs_volume_info *vi)
+{
+       switch (vi->status) {
+       case VOK:       return "OK";
+       case VBUSY:     return "BUSY";
+       default:        return "UNATTACHABLE";
+       }
+}
+
+static const char *yes_or_no(bool x)
+{
+       return x ? "Y" : "N";
+}
+
 /*
  * Convert a volume site into a textual representation, possibly resolving it
  * to a DNS hostname.
@@ -101,3 +151,289 @@ void kafs_display_vldb_site_list(struct kafs_context *ctx,
                        printf("%sVolume is locked for a dump/restore operation", indent);
        }
 }
+
+/*
+ * Display a one-line volume summary
+ *
+ *       proj.foo                          536870957 RW   40475760 K On-line
+ *
+ */
+void display_vol_oneline_summary(struct kafs_context *ctx,
+                                struct kafs_volume_info *vi)
+{
+       char tbuf[32];
+
+       printf("%-32s %10llu %-2s %10u K %s\n",
+              vi->name,
+              vi->volid,
+              vol_type(vi, tbuf),
+              vi->size,
+              vol_state(vi));
+}
+
+/*
+ * Display a volume information timestamp.
+ */
+static void display_vol_timestamp(const char *key, time_t t)
+{
+       printf("%s", key);
+       kafs_print_time_or_never(t);
+       printf("\n");
+}
+
+/*
+ * Display volume information
+ *
+ *       proj.foo                          536870957 RW   40475760 K On-line
+ *           204.29.154.47 /vicepa
+ *           RWrite  536870957 ROnly  536870958 Backup          0
+ *           MaxQuota          0 K
+ *           Creation    Sat Aug 22 06:22:27 2009
+ *           Copy        Tue Oct 26 00:40:32 2010
+ *           Backup      Never
+ *           Last Access Tue Jan 28 23:20:37 2014
+ *           Last Update Mon Aug 05 21:15:32 2013
+ *           0 accesses in the past day (i.e., vnode references)
+ *       <blank>
+ *
+ */
+void display_vol_information(struct kafs_context *ctx,
+                            struct kafs_fileserver *server,
+                            struct kafs_partition *part,
+                            struct kafs_volume_info *vi)
+{
+       char abuf[1024], pbuf[64];
+
+       kafs_sprint_address(ctx, &server->vs_addrs[0], abuf, sizeof(abuf));
+       kafs_sprint_partition(ctx, part, pbuf, sizeof(pbuf));
+
+       display_vol_oneline_summary(ctx, vi);
+       printf("    %s %s\n", abuf, pbuf);
+       printf("    RWrite %10llu ROnly %10llu Backup %10llu\n",
+              vi->parent_id, vi->clone_id, vi->backup_id);
+       printf("    MaxQuota %10u K\n", vi->max_quota);
+
+       display_vol_timestamp("    Creation    ", vi->creation_date);
+       display_vol_timestamp("    Copy        ", vi->copy_date);
+       display_vol_timestamp("    Backup      ", vi->backup_date);
+       display_vol_timestamp("    Last Access ", vi->access_date);
+       display_vol_timestamp("    Last Update ", vi->update_date);
+       printf("    %u accesses in the past day (i.e., vnode references)\n",
+              vi->day_use);
+       printf("\n");
+}
+
+/*
+ * Display volume access statistics
+ *
+ *                             Raw Read/Write Stats
+ *                 |-------------------------------------------|
+ *                 |    Same Network     |    Diff Network     |
+ *                 |----------|----------|----------|----------|
+ *                 |  Total   |   Auth   |   Total  |   Auth   |
+ *                 |----------|----------|----------|----------|
+ *       Reads     |        0 |        0 |        0 |        0 |
+ *       Writes    |        0 |        0 |        0 |        0 |
+ *                 |-------------------------------------------|
+ *       <blank>
+ *                          Writes Affecting Authorship
+ *                 |-------------------------------------------|
+ *                 |   File Authorship   | Directory Authorship|
+ *                 |----------|----------|----------|----------|
+ *                 |   Same   |   Diff   |    Same  |   Diff   |
+ *                 |----------|----------|----------|----------|
+ *       0-60 sec  |        0 |        0 |        0 |        0 |
+ *       1-10 min  |        0 |        0 |        0 |        0 |
+ *       10min-1hr |        0 |        0 |        0 |        0 |
+ *       1hr-1day  |        0 |        0 |        0 |        0 |
+ *       1day-1wk  |        0 |        0 |        0 |        0 |
+ *       > 1wk     |        0 |        0 |        0 |        0 |
+ *                 |-------------------------------------------|
+ *
+ */
+void display_vol_statistics(struct kafs_context *ctx,
+                           struct kafs_volume_info *vi)
+{
+       int i;
+
+       printf("                      Raw Read/Write Stats\n");
+       printf("          |-------------------------------------------|\n");
+       printf("          |    Same Network     |    Diff Network     |\n");
+       printf("          |----------|----------|----------|----------|\n");
+       printf("          |  Total   |   Auth   |   Total  |   Auth   |\n");
+       printf("          |----------|----------|----------|----------|\n");
+       printf("Reads     |%9u |%9u |%9u |%9u |\n",
+              vi->stat_reads[0],
+              vi->stat_reads[1],
+              vi->stat_reads[2],
+              vi->stat_reads[3]);
+       printf("Writes    |%9u |%9u |%9u |%9u |\n",
+              vi->stat_writes[0],
+              vi->stat_writes[1],
+              vi->stat_writes[2],
+              vi->stat_writes[3]);
+       printf("          |-------------------------------------------|\n");
+
+       printf("\n");
+       printf("                   Writes Affecting Authorship\n");
+       printf("          |-------------------------------------------|\n");
+       printf("          |   File Authorship   | Directory Authorship|\n");
+       printf("          |----------|----------|----------|----------|\n");
+       printf("          |   Same   |   Diff   |    Same  |   Diff   |\n");
+       printf("          |----------|----------|----------|----------|\n");
+
+       for (i = 0; i < 5; i++) {
+               printf("%s |%9u |%9u |%9u |%9u |\n",
+                      statistics_time_ranges[i],
+                      vi->stat_fileSameAuthor[i],
+                      vi->stat_fileDiffAuthor[i],
+                      vi->stat_dirSameAuthor[i],
+                      vi->stat_dirDiffAuthor[i]);
+               printf("          |-------------------------------------------|\n");
+               printf("\n");
+       }
+}
+
+/*
+ * Display a volume information timestamp in machine-parseable format
+ */
+static void display_vol_mp_timestamp(const char *key, time_t t)
+{
+       printf("%s\t%-10lu\t", key, t);
+       kafs_print_time(t);
+       printf("\n");
+}
+
+/*
+ *
+ * Display machine-parseable form of volume record, but excluding certain info
+ *
+ *       name            proj.foo
+ *       id              536870957
+ *       serv            111.22.33.44   foo.abc.com
+ *       part            /vicepa
+ *       status          OK
+ *       backupID        0
+ *       parentID        536870957
+ *       cloneID         536870958
+ *       inUse           Y
+ *       needsSalvaged   N
+ *       destroyMe       N
+ *       type            RW
+ *       creationDate    1250918547      Sat Aug 22 06:22:27 2009
+ *       accessDate      1390951237      Tue Jan 28 23:20:37 2014
+ *       updateDate      1375733732      Mon Aug  5 21:15:32 2013
+ *       backupDate      0               Thu Jan  1 01:00:00 1970
+ *       copyDate        1288050032      Tue Oct 26 00:40:32 2010
+ *       flags           0       (Optional)
+ *       diskused        40475760
+ *       maxquota        0
+ *       minquota        0       (Optional)
+ *       filecount       327
+ *       dayUse          0
+ *
+ */
+void display_vol_mp_basic_information(struct kafs_context *ctx,
+                                     struct kafs_fileserver *server,
+                                     struct kafs_partition *partition,
+                                     struct kafs_volume_info *vi)
+{
+       char abuf[20], sbuf[1024], pbuf[64], tbuf[16];
+       int i;
+
+       abuf[0] = 0;
+       for (i = 0; i < server->vs_nr_addrs; i++) {
+               if (server->vs_addrs[i].transport.family != AF_INET)
+                       continue;
+               if (inet_ntop(AF_INET, &server->vs_addrs[i].transport.sin.sin_addr,
+                             abuf, sizeof(abuf)))
+                       break;
+       }
+
+       if (!abuf[0])
+               strcpy(abuf, "0.0.0.0");
+
+       kafs_sprint_address(ctx, &server->vs_addrs[0], sbuf, sizeof(sbuf));
+       kafs_sprint_partition(ctx, partition, pbuf, sizeof(pbuf));
+
+       printf("BEGIN_OF_ENTRY\n");
+       printf("name\t\t%s\n",          vi->name);
+       printf("id\t\t%llu\n",          vi->volid);
+       printf("serv\t\t%-15s\t%s\n",   abuf, sbuf);
+       printf("part\t\t%s\n",          pbuf);
+       printf("status\t\t%s\n",        vol_status(vi));
+       printf("backupID\t%llu\n",      vi->backup_id);
+       printf("parentID\t%llu\n",      vi->parent_id);
+       printf("cloneID\t\t%llu\n",     vi->clone_id);
+       printf("inUse\t\t%s\n",         yes_or_no(vi->in_use));
+       if (vi->has_need_salvage) {
+               printf("needsSalvaged\t%s\n",   yes_or_no(vi->needs_salvage));
+               printf("destroyMe\t%s\n",       yes_or_no(vi->destroy_me));
+       }
+       printf("type\t\t%s\n",          vol_type(vi, tbuf));
+
+       display_vol_mp_timestamp("creationDate", vi->creation_date);
+       display_vol_mp_timestamp("accessDate", vi->access_date);
+       display_vol_mp_timestamp("updateDate", vi->update_date);
+       display_vol_mp_timestamp("backupData", vi->backup_date);
+       display_vol_mp_timestamp("copyDate", vi->copy_date);
+
+       if (vi->has_flags)
+               printf("flags\t\t%-7u\t(Optional)\n", vi->flags);
+
+       printf("diskused\t%u\n", vi->size);
+       printf("maxquota\t%u\n", vi->max_quota);
+
+       if (vi->has_min_quota)
+               printf("minquota\t%-7u\t(Optional)\n", vi->min_quota);
+
+       printf("filecount\t%u\n", vi->file_count);
+       printf("dayUse\t\t%u\n", vi->day_use);
+}
+
+/*
+ *
+ * Display machine parseable form of volume record
+ *
+ *       name            proj.foo
+ *       id              536870957
+ *       serv            111.22.33.44   foo.abc.com
+ *       part            /vicepa
+ *       status          OK
+ *       backupID        0
+ *       parentID        536870957
+ *       cloneID         536870958
+ *       inUse           Y
+ *       needsSalvaged   N
+ *       destroyMe       N
+ *       type            RW
+ *       creationDate    1250918547      Sat Aug 22 06:22:27 2009
+ *       accessDate      1390951237      Tue Jan 28 23:20:37 2014
+ *       updateDate      1375733732      Mon Aug  5 21:15:32 2013
+ *       backupDate      0               Thu Jan  1 01:00:00 1970
+ *       copyDate        1288050032      Tue Oct 26 00:40:32 2010
+ *       flags           0       (Optional)
+ *       diskused        40475760
+ *       maxquota        0
+ *       minquota        0       (Optional)
+ *       filecount       327
+ *       dayUse          0
+ *       weekUse         0       (Optional)
+ *       spare2          21775   (Optional)
+ *       spare3          0       (Optional)
+ *
+ */
+void display_vol_mp_information(struct kafs_context *ctx,
+                               struct kafs_fileserver *server,
+                               struct kafs_partition *partition,
+                               struct kafs_volume_info *vi)
+{
+       display_vol_mp_basic_information(ctx, server, partition, vi);
+
+       if (vi->has_week_use)
+               printf("weekUse\t\t%-7u\t(Optional)\n", vi->week_use);
+       if (vi->has_spare2)
+               printf("spare2\t\t%-7u\t(Optional)\n", vi->spare2);
+       if (vi->has_spare3)
+               printf("spare3\t\t%-7u\t(Optional)\n", vi->spare3);
+}
diff --git a/kafs/vos_examine.c b/kafs/vos_examine.c
new file mode 100644 (file)
index 0000000..9ebea32
--- /dev/null
@@ -0,0 +1,162 @@
+/* The "vos examine" command
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "kafs.h"
+#include "vlservice.h"
+#include "volservice.h"
+#include "afs_xg.h"
+#include "display.h"
+
+static void display_vldb(struct kafs_context *ctx, struct kafs_vldb_entry *vldb)
+{
+       if (vldb->volume_id[RWVOL] != 0)
+               printf("    RWrite: %10llu", vldb->volume_id[RWVOL]);
+       if (vldb->volume_id[ROVOL] != 0)
+               printf("    ROnly: %10llu", vldb->volume_id[ROVOL]);
+       if (vldb->volume_id[BACKVOL] != 0)
+               printf("    Backup: %10llu", vldb->volume_id[BACKVOL]);
+       printf("\n");
+
+       kafs_display_vldb_site_list(ctx, vldb, "    ");
+}
+
+static void display_normal(struct kafs_context *ctx,
+                          struct kafs_vldb_entry *vldb,
+                          struct kafs_vldb_site *site,
+                          struct kafs_volume_info *vi,
+                          bool extended)
+{
+       if (site && vi) {
+               display_vol_information(ctx, site->server, &site->partition, vi);
+               if (extended)
+                       display_vol_statistics(ctx, vi);
+       }
+       display_vldb(ctx, vldb);
+}
+
+static void display_format(struct kafs_context *ctx,
+                          struct kafs_vldb_entry *vldb,
+                          struct kafs_vldb_site *site,
+                          struct kafs_volume_info *vi)
+{
+       if (site) {
+               display_vol_mp_information(ctx, site->server, &site->partition, vi);
+               printf("\n");
+       }
+       display_vldb(ctx, vldb);
+}
+
+/***
+ * COMMAND: vos examine - Show volume header and VLDB entry information for a volume
+ * ARG: "-id <volume name or ID>"
+ * ARG: "[-extended]"
+ * ARG: "[-format]"
+ * ARG: "[-cell <cell name>]"
+ * ARG: "[-noauth]"                            - Auth
+ * ARG: "[-localauth]"                         - Auth
+ * ARG: "[-verbose]"
+ * ARG: "[-encrypt]"                           - Auth
+ * ARG: "[-noresolve]"
+ *
+ * Show volume header and VLDB entry information for a volume
+ */
+bool COMMAND_vos_examine(
+       struct kafs_context             *ctx,
+       struct kafs_volume_spec         *a_id,
+       bool                            a_extended,
+       bool                            a_format,
+       bool                            a_verbose,
+       bool                            a_noresolve)
+{
+       struct kafs_vldb_entry_list vlist = {};
+       struct kafs_volume_info *vi = NULL;
+       struct kafs_vldb_entry *vldb;
+       struct kafs_vldb_site *site = NULL;
+       kafs_volume_id_t volid;
+       unsigned int servflag = 0;
+       bool ret;
+       int i;
+
+       _enter("");
+
+       ctx->no_resolve = a_noresolve;
+
+       if (!kafs_open_vl_service(ctx))
+               return false;
+
+       if (!kafs_look_up_volume_by_name(ctx, a_id, &vlist))
+               return false;
+
+       vldb = vlist.entries[0];
+       if (a_id->is_numeric) {
+               volid = a_id->number;
+               if (volid == vldb->volume_id[RWVOL]) {
+                       servflag = VLSF_RWVOL;
+               } else if (volid == vldb->volume_id[ROVOL]) {
+                       servflag = VLSF_ROVOL;
+               } else if (volid == vldb->volume_id[BACKVOL]) {
+                       servflag = VLSF_BACKVOL;
+               } else {
+                       kafs_error(ctx, "Requested volume ID not in record for volume ID");
+                       goto error;
+               }
+       } else {
+               for (i = 0; i < vldb->nr_sites; i++)
+                       servflag |= vldb->sites[i].flags;
+               if (servflag & VLSF_RWVOL) {
+                       servflag = VLSF_RWVOL;
+                       volid = vldb->volume_id[RWVOL];
+               } else if (servflag & VLSF_ROVOL) {
+                       servflag = VLSF_ROVOL;
+                       volid = vldb->volume_id[ROVOL];
+               } else if (servflag & VLSF_BACKVOL) {
+                       servflag = VLSF_BACKVOL;
+                       volid = vldb->volume_id[BACKVOL];
+               } else {
+                       kafs_error(ctx, "Requested volume does not exist on any server");
+                       goto error;
+               }
+       }
+
+       if (vldb->nr_sites == 0)
+               return kafs_error(ctx, "Couldn't examine requested volume");
+
+       ret = false;
+       for (i = 0; i < vldb->nr_sites; site = NULL, i++) {
+               site = &vldb->sites[i];
+
+               if (!(site->flags & servflag))
+                       continue;
+
+               if (!kafs_open_volserver(ctx, site->server))
+                       continue;
+
+               if (!kafs_query_volume_state(ctx, site->server, &site->partition,
+                                            volid, a_extended, &vi))
+                       continue;
+               break;
+       }
+
+       if (a_format && !a_extended)
+               display_format(ctx, vldb, site, vi);
+       else
+               display_normal(ctx, vldb, site, vi, a_extended);
+       ret = true;
+
+error:
+       clear_kafs_vldb_entry_list(&vlist);
+       _leave(" = %u", ret);
+       return ret;
+}