]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
midlayer: Add Volume Server support
authorDavid Howells <dhowells@redhat.com>
Fri, 10 Jul 2020 11:07:42 +0000 (12:07 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 5 May 2023 10:53:26 +0000 (11:53 +0100)
Signed-off-by: David Howells <dhowells@redhat.com>
kafs/Makefile
kafs/kafs.H
kafs/vol_probe.C [new file with mode: 0644]
kafs/vol_query.C [new file with mode: 0644]
kafs/volservice.H [new file with mode: 0644]

index c673349e3a4bd4eeae85c018f3cd7cd6b630768f..c794fbd243b48d80b2ed0e6ff69732c2b36e3f8d 100644 (file)
@@ -13,7 +13,9 @@ CORE_SRCS := \
        misc.C \
        vl_fileservers.C \
        vl_probe.C \
-       vl_volumes.C
+       vl_volumes.C \
+       vol_probe.C \
+       vol_query.C
 
 BOS_SRCS := \
        bos.C \
index 2a12dbfe93b97f94f8cbf84c04bb333d3d81cc88..cb0d63cd2485b4f95dc892ee4bd32b2d4e505501 100644 (file)
@@ -28,6 +28,7 @@ constexpr unsigned int FS_PORT                = 7000; /* AFS file server port */
 constexpr unsigned int FS_SERVICE      = 1;    /* AFS File Service ID */
 constexpr unsigned int VL_PORT         = 7003; /* Volume location service port */
 constexpr unsigned int VL_SERVICE      = 52;   /* Service ID for the AFS Volume Location service */
+constexpr unsigned int YFS_VOL_SERVICE = 2502; /* Service ID for AuriStor upgraded volume service */
 constexpr unsigned int YFS_VL_SERVICE  = 2503; /* Service ID for AuriStor upgraded VL service */
 }
 
diff --git a/kafs/vol_probe.C b/kafs/vol_probe.C
new file mode 100644 (file)
index 0000000..df5f714
--- /dev/null
@@ -0,0 +1,149 @@
+/* Volume server probe.
+ *
+ * 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 <fmt/core.h>
+#include "volservice.H"
+#include "afs_xg.H"
+#include "display.H"
+
+using rxrpc::ref;
+using kafs::Volserver;
+
+/**
+ * Volserver::Volserver - Open a Volume Server for access.
+ * @ctx: The cell and authentication context
+ * @site: The volume server details
+ *
+ * Open a Volume Server.  The server is probed to determine what it's capable
+ * of and what type it is.
+ */
+Volserver::Volserver(Context *ctx, FS_site *site)
+{
+       vs_context = ctx;
+       vs_site = site;
+       vs_probed = false;
+
+       open_endpoint(ctx);
+       if (!vs_probed)
+               probe_volserver();
+}
+
+/*
+ * Volserver::~Volserver - Close a Volume Server.
+ *
+ * Close a volume server, potentially releasing any resources held.
+ */
+Volserver::~Volserver()
+{
+}
+
+/**
+ * Volserver::probe_volserver - Probe a Volume Server
+ *
+ * Probe a volume server to find what it supports.
+ */
+void Volserver::probe_volserver()
+{
+       std::vector<sockaddr_rxrpc> &vs_addrs = vs_site->vs_addrs;
+       rxrpc::Call_params &params = vs_params;
+       struct sockaddr_rxrpc *srx;
+       std::vector<unsigned int> caps;
+       std::error_code saved_error;
+       std::string abuf;
+       unsigned int addr = 0, i, nr_caps;
+
+       _enter("");
+
+try_next_address:
+       if (addr >= vs_addrs.size()) {
+               if (saved_error)
+                       throw std::system_error(saved_error, "Volume server not responding");
+               throw std::runtime_error("No volume servers available");
+       }
+
+       srx = &vs_addrs[addr];
+       params.endpoint         = vs_context->endpoint;
+       params.security         = vs_context->security;
+       params.peer             = *srx;
+       params.peer_len         = sizeof(*srx);
+       params.upgrade_service  = true;
+
+       abuf = sprint_address(vs_context, params.peer);
+       _debug("addr %u %s", addr, abuf.c_str());
+
+       try {
+               afs::VOLSER::GetCapabilities(&params, caps);
+       } catch (const rxrpc::AbortRXGEN_OPCODE &a) {
+               vs_service = service_afs;
+               params.upgrade_service = false;
+               memset(&vs_caps, 0, sizeof(vs_caps));
+               goto out;
+       } catch (const rxrpc::AbortRX_INVALID_OPERATION &a) {
+               vs_service = service_afs;
+               params.upgrade_service = false;
+               memset(&vs_caps, 0, sizeof(vs_caps));
+               goto out;
+       } catch (const std::system_error &e) {
+               switch (e.code().value()) {
+               case -ENONET:
+               case -ECONNRESET: /* Responded, but call expired. */
+               case -ERFKILL:
+               case -EADDRNOTAVAIL:
+               case -ENETUNREACH:
+               case -EHOSTUNREACH:
+               case -EHOSTDOWN:
+               case -ECONNREFUSED:
+               case -ETIMEDOUT:
+               case -ETIME:
+                       saved_error.assign(e.code().value(), e.code().category());
+                       addr++;
+                       goto try_next_address;
+               default:
+                       throw;
+               }
+       }
+
+       params.upgrade_service = false;
+       vs_pref = addr;
+       switch (params.service_id_used) {
+       case afs::VOLSERVICE_ID:
+               vs_service = service_afs;
+               break;
+       case afs::YFS_VOL_SERVICE:
+               vs_service = service_yfs;
+               params.peer.srx_service = params.service_id_used;
+               for (i = 0; i < vs_addrs.size(); i++)
+                       vs_addrs[i].srx_service = params.service_id_used;
+               break;
+       default:
+               throw std::runtime_error(
+                       fmt::format("Upgraded to unsupported volume service {:d}",
+                                   vs_params.service_id_used));
+       }
+
+       memset(&vs_caps, 0, sizeof(vs_caps));
+       nr_caps = caps.size();
+       if (nr_caps > sizeof(vs_caps) / sizeof(vs_caps))
+               nr_caps = sizeof(vs_caps) / sizeof(vs_caps);
+       for (i = 0; i < nr_caps; i++)
+               vs_caps[i] = caps[i];
+
+out:
+       if (debug_caps) {
+               printf("volser-caps:");
+               for (i = 0; i < sizeof(vs_caps) / sizeof(unsigned int); i++)
+                       printf(" %08x", vs_caps[i]);
+               if (vs_service == service_yfs)
+                       printf(" yfs\n");
+               else
+                       printf(" afs\n");
+       }
+}
diff --git a/kafs/vol_query.C b/kafs/vol_query.C
new file mode 100644 (file)
index 0000000..21d6277
--- /dev/null
@@ -0,0 +1,236 @@
+/* Volume information query
+ *
+ * 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 "volservice.H"
+#include "afs_xg.H"
+
+using rxrpc::ref;
+using kafs::Volserver;
+
+namespace kafs {
+static void volintinfo_to_volume_info(afs::volintInfo &info, Volume_info_list &vilist);
+static void xvolintinfo_to_volume_info(afs::xvolintInfo &xinfo, Volume_info_list &vilist);
+}
+
+/**
+ * Volserver::vol_monitor_transaction - Get the state of ongoing transactions on a volume server
+ * @info_list: The list to which the records will be added
+ *
+ * Retrieve the list of ongoing transactions from a volume server and details
+ * of those transactions.  The transaction records are added to the list.
+ */
+void Volserver::vol_monitor_transaction(Vol_transaction_info_list &info_list)
+{
+       std::vector<afs::transDebugInfo> results;
+       unsigned int i;
+
+       afs::VOLSER::Monitor(&vs_params, results);
+       if (!results.size())
+               return;
+
+       info_list.resize(results.size());
+
+       for (i = 0; i < results.size(); i++) {
+               Vol_transaction_info &info = info_list[i];
+               afs::transDebugInfo &r = results[i];
+
+               info.tid                = r.tid;
+               info.time               = r.time;
+               info.creation_time      = r.creationTime;
+               info.return_code        = r.returnCode;
+               info.volid              = r.volid;
+               info.partition.id       = r.partition;
+               info.iflags             = r.iflags;
+               info.vflags             = r.vflags;
+               info.tflags             = r.tflags;
+               info.call_valid         = r.callValid;
+               info.read_next          = r.readNext;
+               info.transmit_next      = r.transmitNext;
+               info.last_send_time     = r.lastSendTime;
+               info.last_receive_time  = r.lastReceiveTime;
+               info.last_proc_name     = r.lastProcName;
+       }
+}
+
+/*
+ * Convert a volintInfo struct to a Volserver::volume_info record.
+ */
+static void kafs::volintinfo_to_volume_info(afs::volintInfo &info,
+                                           Volume_info_list &vilist)
+{
+       unsigned int index = vilist.size();
+       vilist.resize(index + 1);
+       Volume_info &vi = vilist[index];
+
+       vi.name                 = info.name;
+       vi.volid                = info.volid;
+       vi.type                 = info.type;
+       vi.backup_id            = info.backupID;
+       vi.parent_id            = info.parentID;
+       vi.clone_id             = info.cloneID;
+       vi.status               = info.status;
+       vi.copy_date            = info.copyDate;
+       vi.in_use               = info.inUse;
+       vi.needs_salvage        = info.needsSalvaged;
+       vi.destroy_me           = info.destroyMe;
+       vi.creation_date        = info.creationDate;
+       vi.access_date          = info.accessDate;
+       vi.update_date          = info.updateDate;
+       vi.backup_date          = info.backupDate;
+       vi.day_use              = info.dayUse;
+       vi.file_count           = info.filecount;
+       vi.max_quota            = info.maxquota;
+       vi.size                 = info.size;
+       vi.flags                = info.flags;
+       vi.min_quota            = info.spare0;
+       vi.week_use[0]          = info.spare1;
+       vi.spare2               = info.spare2;
+       vi.spare3               = info.spare3;
+
+       vi.has_flags            = true;
+       vi.has_in_use           = true;
+       vi.has_min_quota        = true;
+       vi.has_need_salvage     = true;
+       vi.has_size             = true;
+       vi.has_spare2           = true;
+       vi.has_spare3           = true;
+       vi.nr_week_use          = 1;
+}
+
+/*
+ * Convert an xvolintInfo struct to a Volserver::volume_info record.
+ */
+static void kafs::xvolintinfo_to_volume_info(afs::xvolintInfo &xinfo,
+                                            Volume_info_list &vilist)
+{
+       unsigned int index = vilist.size();
+       vilist.resize(index + 1);
+       Volume_info &vi = vilist[index];
+       int i;
+
+       vi.name                 = xinfo.name;
+       vi.volid                = xinfo.volid;
+       vi.type                 = xinfo.type;
+       vi.backup_id            = xinfo.backupID;
+       vi.parent_id            = xinfo.parentID;
+       vi.clone_id             = xinfo.cloneID;
+       vi.status               = xinfo.status;
+       vi.copy_date            = xinfo.copyDate;
+       vi.in_use               = xinfo.inUse;
+       vi.creation_date        = xinfo.creationDate;
+       vi.access_date          = xinfo.accessDate;
+       vi.update_date          = xinfo.updateDate;
+       vi.backup_date          = xinfo.backupDate;
+       vi.day_use              = xinfo.dayUse;
+       vi.file_count           = xinfo.filecount;
+       vi.max_quota            = xinfo.maxquota;
+       vi.size                 = xinfo.size;
+
+       for (i = 0; i < 4; i++) {
+               vi.stat_reads[i]  = xinfo.stat_reads[i];
+               vi.stat_writes[i] = xinfo.stat_writes[i];
+       }
+
+       for (i = 0; i < 6; i++) {
+               vi.stat_fileSameAuthor[i] = vi.stat_fileSameAuthor[i];
+               vi.stat_fileDiffAuthor[i] = vi.stat_fileDiffAuthor[i];
+               vi.stat_dirSameAuthor[i]  = vi.stat_dirSameAuthor[i];
+               vi.stat_dirDiffAuthor[i]  = vi.stat_dirDiffAuthor[i];
+       }
+
+       vi.has_in_use           = true;
+       vi.has_size             = true;
+       vi.has_stats            = true;
+       vi.nr_week_use          = 0;
+}
+
+/**
+ * Volserver::VOLSER_ListOneVolume - Get the ordinary state of an instance of a volume
+ * @partition: The partition on which the volume resides
+ * @volid: The ID of the volume to query
+ * @vi: The record to load with the information retrieved
+ *
+ * Query the ordinary state of a volume on a volume server.  The information is
+ * stored into the supplied record.
+ */
+void Volserver::VOLSER_ListOneVolume(Partition_spec &partition,
+                                    Volume_id volid,
+                                    Volume_info_list &vi)
+{
+       std::vector<afs::volintInfo> infos;
+
+       afs::VOLSER::ListOneVolume(&vs_params, partition.id, volid, infos);
+       if (!infos.size())
+               throw std::runtime_error("No volume information results returned");
+
+       volintinfo_to_volume_info(infos[0], vi);
+}
+
+/**
+ * Volserver::VOLSER_XListOneVolume - Get the extended state of an instance of a volume
+ * @partition: The partition on which the volume resides
+ * @volid: The ID of the volume to query
+ * @vi: The record to load with the information retrieved
+ *
+ * Query the extended state of a volume on a volume server.  The information is
+ * stored into the supplied record.
+ */
+void Volserver::VOLSER_XListOneVolume(Partition_spec &partition,
+                                     Volume_id volid,
+                                     Volume_info_list &vi)
+{
+       std::vector<afs::xvolintInfo> xinfos;
+
+       afs::VOLSER::XListOneVolume(&vs_params, partition.id, volid, xinfos);
+       if (!xinfos.size())
+               throw std::runtime_error("No volume information results returned");
+
+       xvolintinfo_to_volume_info(xinfos[0], vi);
+}
+
+/**
+ * Volserver::query_volume_state - Query the state of an instance of a volume
+ * @partition: The partition on which the volume resides
+ * @volid: The ID of the volume to query
+ * @extended: True if the extended state is desired; false otherwise.
+ * @_vi: Where to place the result record.
+ *
+ * Query the ordinary or extended state of a volume on a volume server and
+ * transcribe to a record which is placed at *@_vi.
+ */
+void Volserver::query_volume_state(Partition_spec &partition,
+                                  Volume_id volid,
+                                  bool extended,
+                                  Volume_info_list &vi)
+{
+       if (extended)
+               VOLSER_XListOneVolume(partition, volid, vi);
+       else
+               VOLSER_ListOneVolume(partition, volid, vi);
+}
+
+/**
+ * Volserver::list_partitions - Get a list of partitions on a server.
+ * @partitions: Where to store the list of partitions.
+ *
+ * Query a volume server and retrieve the list of volumes attached to it.
+ */
+void Volserver::list_partitions(Partition_list &partitions)
+{
+       std::vector<int32_t> ents;
+       unsigned int i;
+
+       afs::VOLSER::XListPartitions(&vs_params, ents);
+
+       partitions.resize(ents.size());
+       for (i = 0; i < ents.size(); i++)
+               partitions[i].id = ents[i];
+}
diff --git a/kafs/volservice.H b/kafs/volservice.H
new file mode 100644 (file)
index 0000000..4eaf7dc
--- /dev/null
@@ -0,0 +1,155 @@
+/* KAFS Volume service mid-level client library.
+ *
+ * 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.
+ */
+
+#ifndef VOLSERVICE_H
+#define VOLSERVICE_H
+
+#include "rxrpc.H"
+#include "kafs.H"
+#include "afs_xg.H"
+
+namespace kafs {
+
+/*
+ * Volume transaction information.
+ *
+ * Source transDebugInfo.
+ */
+struct Vol_transaction_info {
+       uint32_t        tid;
+       Time            time;
+       Time            creation_time;
+       uint32_t        return_code;
+       uint32_t        volid;
+       Partition_spec  partition;
+       uint16_t        iflags;
+       uint8_t         vflags;
+       uint8_t         tflags;
+       uint32_t        call_valid;
+       uint32_t        read_next;
+       uint32_t        transmit_next;
+       Time            last_send_time;
+       Time            last_receive_time;
+       std::string     last_proc_name;
+};
+
+typedef std::vector<Vol_transaction_info> Vol_transaction_info_list;
+
+/*
+ * Volume information.
+ *
+ * Source: volintInfo, xvolintInfo.
+ */
+struct Volume_info {
+       Volume_id               volid;
+       Volume_id               backup_id;
+       Volume_id               parent_id;
+       Volume_id               clone_id;
+       unsigned int            type;
+       unsigned int            status;
+       unsigned long long      owner;
+
+       Time                    creation_date;
+       Time                    access_date;
+       Time                    update_date;
+       Time                    expiration_date;
+       Time                    backup_date;
+       Time                    copy_date;
+       Time                    day_use_date;
+       unsigned long long      vol_update_counter;
+
+       unsigned long long      day_use;
+       unsigned long long      week_use[7];            /* spare1 */
+       unsigned long long      file_count;
+       unsigned long long      disk_used;
+       unsigned long long      max_quota;
+       unsigned long long      min_quota;              /* spare0 */
+       unsigned long long      max_files;
+       unsigned int            size;
+       unsigned int            flags;
+
+       int                     stat_reads[4];
+       int                     stat_writes[4];
+       int                     stat_fileSameAuthor[6];
+       int                     stat_fileDiffAuthor[6];
+       int                     stat_dirSameAuthor[6];
+       int                     stat_dirDiffAuthor[6];
+
+       unsigned int            spare2;
+       unsigned int            spare3;
+
+       bool                    in_use;
+       bool                    needs_salvage;
+       bool                    destroy_me;
+
+       bool                    has_day_use_date:1;
+       bool                    has_disk_used:1;
+       bool                    has_expiration_date:1;
+       bool                    has_flags:1;
+       bool                    has_in_use:1;
+       bool                    has_max_files:1;
+       bool                    has_min_quota:1;
+       bool                    has_need_salvage:1;
+       bool                    has_owner:1;
+       bool                    has_size:1;
+       bool                    has_spare2:1;
+       bool                    has_spare3:1;
+       bool                    has_stats:1;
+       bool                    has_vol_update_counter:1;
+       unsigned char           nr_week_use;
+
+       std::string             offline_msg;
+       std::string             name;
+};
+
+typedef std::vector<Volume_info> Volume_info_list;
+
+/*
+ * List of partitions.
+ */
+typedef std::vector<Partition_spec> Partition_list;
+
+/*
+ * Volumeserver access handle.
+ */
+class Volserver : public rxrpc::refcount {
+public:
+       rxrpc::ref<Context>             vs_context;
+       rxrpc::ref<FS_site>             vs_site;
+       Service                         vs_service;     /* Service provided by the volserver */
+       unsigned int                    vs_caps[1];     /* Volserver capabilities */
+       rxrpc::Call_params              vs_params;      /* Volserver parameters */
+       unsigned int                    vs_pref;        /* Volserver address to use */
+       bool                            vs_probed:1;    /* T if volserver has been probed */
+
+       const std::string &name() const { return vs_site->name; }
+
+       /* vol_probe.C */
+       Volserver(Context *ctx, FS_site *site);
+       ~Volserver();
+       void probe_volserver();
+
+       /* vol_query.C */
+       void VOLSER_ListOneVolume(Partition_spec &partition,
+                                 Volume_id volid,
+                                 Volume_info_list &vi);
+       void VOLSER_XListOneVolume(Partition_spec &partition,
+                                  Volume_id volid,
+                                  Volume_info_list &vi);
+       void vol_monitor_transaction(Vol_transaction_info_list &);
+       void list_partitions(Partition_list &);
+       void query_volume_state(Partition_spec &, Volume_id, bool,
+                               Volume_info_list &);
+};
+
+} /* end namespace kafs */
+
+#endif /* VLSERVICE_H */