#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.
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);
+}
--- /dev/null
+/* 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;
+}