}
 
 /**
- * kafs_look_up_volume_by_name - Look up a volume by attributes and/or name pattern.
+ * kafs_look_up_volumes_by_attributes - Look up a volume by attributes and/or name pattern.
  * @ctx: The cell and authentication context
  * @fsspec: A fileserver address filter (or NULL)
  * @partition: A partition filter (or NULL)
  * If successful, the resulting records are appended to the list.  These
  * records may be cached locally.
  */
-bool kafs_look_up_vlist_by_attributes(struct kafs_context *ctx,
-                                     struct kafs_fileserver_spec *fsspec,
-                                     struct kafs_partition *partition,
-                                     bool locked,
-                                     const char *volume_name_pattern,
-                                     struct kafs_vldb_entry_list *vlist)
+bool kafs_look_up_volumes_by_attributes(struct kafs_context *ctx,
+                                       struct kafs_fileserver_spec *fsspec,
+                                       struct kafs_partition *partition,
+                                       bool locked,
+                                       const char *volume_name_pattern,
+                                       struct kafs_vldb_entry_list *vlist)
 {
        struct VldbListByAttributes attr = { .Mask = 0 };
        struct sockaddr_in *sin;
 
--- /dev/null
+/* The "vos listvldb" 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 "afs_xg.h"
+#include "display.h"
+
+static void kafs_print_vl_record(struct kafs_context *ctx,
+                                struct kafs_vldb_entry *vldb)
+{
+       unsigned int flags;
+
+       printf("%s\n", vldb->name);
+       printf("   ");
+       flags = vldb->flags;
+       if (flags & VLF_RWEXISTS)   printf(" RWrite: %-12llu", vldb->volume_id[0]);
+       if (flags & VLF_ROEXISTS)   printf(" ROnly: %-12llu",  vldb->volume_id[1]);
+       if (flags & VLF_BACKEXISTS) printf(" Backup: %-12llu", vldb->volume_id[2]);
+       printf("\n");
+       kafs_display_vldb_site_list(ctx, vldb, "    ");
+       printf("\n");
+}
+
+static int kafs_cmp_entries_by_name(const void *_a, const void *_b)
+{
+       struct kafs_vldb_entry *const *a = _a, *const *b = _b;
+
+       return strcmp((*a)->name, (*b)->name);
+}
+
+/***
+ * COMMAND: vos listvldb - Query the VLDB
+ * ARG: "[-name <volume name>]"
+ * ARG: "[-server <machine name>]"
+ * ARG: "[-partition <partition name>]"
+ * ARG: "[-locked]"
+ * ARG: "[-quiet]"
+ * ARG: "[-nosort]"
+ * ARG: "[-cell <cell name>]"
+ * ARG: "[-noauth]"                            - Auth
+ * ARG: "[-localauth]"                         - Auth
+ * ARG: "[-verbose]"
+ * ARG: "[-encrypt]"                           - Auth
+ * ARG: "[-noresolve]"
+ * NOCOMBINE: name, server
+ * NOCOMBINE: name, partition
+ * NOCOMBINE: name, locked
+ *
+ * Displays a volume's VLDB entry
+ */
+bool COMMAND_vos_listvldb(
+       struct kafs_context             *ctx,
+       struct kafs_volume_spec         *a_name,
+       struct kafs_fileserver_spec     *a_server,
+       struct kafs_partition           *a_partition,
+       bool                            a_locked,
+       bool                            a_quiet,
+       bool                            a_nosort,
+       bool                            a_verbose,
+       bool                            a_noresolve)
+{
+       struct kafs_vldb_entry_list vlist = {};
+       int i;
+
+       _enter("");
+
+       ctx->no_resolve = a_noresolve;
+
+       if (!kafs_open_vl_service(ctx))
+               return false;
+
+       if (a_name &&
+           !a_server &&
+           !a_partition &&
+           !a_locked &&
+           !strchr(a_name->name, '*')) {
+               if (!kafs_look_up_volume_by_name(ctx, a_name, &vlist))
+                       return false;
+               kafs_print_vl_record(ctx, vlist.entries[0]);
+       } else {
+               if (!kafs_look_up_volumes_by_attributes(ctx, a_server,
+                                                       a_partition, a_locked,
+                                                       a_name ? a_name->name : NULL,
+                                                       &vlist))
+                       return false;
+               if (!a_quiet && a_server)
+                       printf("VLDB entries for server %s\n", a_server->name);
+
+               if (!a_nosort)
+                       qsort(vlist.entries, vlist.nr_entries,
+                             sizeof(vlist.entries[0]),
+                             kafs_cmp_entries_by_name);
+
+               for (i = 0; i < vlist.nr_entries; i++)
+                       kafs_print_vl_record(ctx, vlist.entries[i]);
+               if (!a_quiet)
+                       printf("Total entries: %u\n", vlist.nr_entries);
+       }
+
+       clear_kafs_vldb_entry_list(&vlist);
+       _leave(" = t");
+       return true;
+}
+
+/***
+ * ALIAS: vos listloc - listvldb
+ */