From 5d8f1802e4c7284a3cdad6ff8f0f8bb6d54e19fb Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 6 Jul 2020 23:13:50 +0100 Subject: [PATCH] cmd: Implement "vos examine" Signed-off-by: David Howells --- kafs/Makefile | 1 + kafs/display.h | 8 ++ kafs/display_vol.c | 336 +++++++++++++++++++++++++++++++++++++++++++++ kafs/vos_examine.c | 162 ++++++++++++++++++++++ 4 files changed, 507 insertions(+) create mode 100644 kafs/vos_examine.c diff --git a/kafs/Makefile b/kafs/Makefile index ad08be5..cf2174d 100644 --- a/kafs/Makefile +++ b/kafs/Makefile @@ -31,6 +31,7 @@ PTS_SRCS := \ VOS_SRCS := \ vos.c \ + vos_examine.c \ vos_help.c \ vos_listvldb.c \ vos_status.c diff --git a/kafs/display.h b/kafs/display.h index 20e5c35..08c505c 100644 --- a/kafs/display.h +++ b/kafs/display.h @@ -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 */ diff --git a/kafs/display_vol.c b/kafs/display_vol.c index 73e3de2..0cda8d5 100644 --- a/kafs/display_vol.c +++ b/kafs/display_vol.c @@ -21,6 +21,56 @@ #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) + * + * + */ +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 | + * |-------------------------------------------| + * + * 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 index 0000000..9ebea32 --- /dev/null +++ b/kafs/vos_examine.c @@ -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 +#include +#include +#include +#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 " + * ARG: "[-extended]" + * ARG: "[-format]" + * ARG: "[-cell ]" + * 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; +} -- 2.50.1