vos_help.c \
vos_listaddrs.c \
vos_listvldb.c \
+ vos_listvol.c \
vos_status.c
CORE_OBJS := $(patsubst %.c,%.o,$(CORE_SRCS))
void free_kafs_partition(struct kafs_partition *part)
{
- free(part);
+ if (part) {
+ free(part->name);
+ free(part);
+ }
}
* 2 of the Licence, or (at your option) any later version.
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <netdb.h>
*
* Print a time in a standard format for AFS tools to stdout.
*/
-void kafs_print_time(time_t time)
+void kafs_print_time(const struct timespec *t)
{
struct tm tm;
char buf[128];
- localtime_r(&time, &tm);
+ localtime_r(&t->tv_sec, &tm);
strftime(buf, 128, "%a %b %d %H:%M:%S %Y", &tm);
printf("%s", buf);
}
* Print a time in a standard format for AFS tools to stdout. If @time is 0,
* then "Never" will be printed instead.
*/
-void kafs_print_time_or_never(time_t time)
+void kafs_print_time_or_never(const struct timespec *t)
{
- if (!time)
+ if (!t->tv_sec)
printf("Never");
- return kafs_print_time(time);
+ return kafs_print_time(t);
}
* kafs_sprint_address - Convert a numeric ID into a partition name string.
* @ctx: The cell and authentication context
* @partition: The partition specified to convert
- * @buf: The buffer to write into
- * @buf_len: The size of the buffer
*
* Render the numeric partition ID to the standard string representation and
- * write it into the buffer.
+ * attach it to the partition record. Returns a pointer to the buffer.
*/
-void kafs_sprint_partition(struct kafs_context *ctx,
- struct kafs_partition *partition,
- char *buf, size_t buf_len)
+const char *kafs_sprint_partition(struct kafs_context *ctx,
+ struct kafs_partition *partition)
{
unsigned int n = partition->id;
+ int len;
+
+ if (partition->name)
+ return partition->name;
if (n < 26) {
- snprintf(buf, buf_len, "/vicep%c", n + 97);
+ len = asprintf(&partition->name, "/vicep%c", n + 97);
} else if (n <= 255) {
n -= 26;
- snprintf(buf, buf_len, "/vicep%c%c", n / 26 + 97, n % 26 + 97);
+ len = asprintf(&partition->name, "/vicep%c%c", n / 26 + 97, n % 26 + 97);
} else {
- snprintf(buf, buf_len, "/vicep?%u", n);
+ len = asprintf(&partition->name, "/vicep?%u", n);
}
+
+ if (len == -1)
+ return kafs_nomem(ctx), NULL;
+ return partition->name;
}
/*
* display.c
*/
-extern void kafs_print_time(time_t);
-extern void kafs_print_time_or_never(time_t);
+extern void kafs_print_time(const struct timespec *t);
+extern void kafs_print_time_or_never(const struct timespec *t);
extern void kafs_sprint_address(struct kafs_context *, struct sockaddr_rxrpc *, char *, size_t);
-extern void kafs_sprint_partition(struct kafs_context *, struct kafs_partition *, char *, size_t);
+extern const char *kafs_sprint_partition(struct kafs_context *, struct kafs_partition *);
/*
* display_error.c
* display_vol.c
*/
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 *,
+extern bool 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 *,
+extern bool 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 *);
-
+extern bool display_vol_oneline_summary(struct kafs_context *, struct kafs_fileserver *,
+ struct kafs_partition *, struct kafs_volume_info *);
+
#endif /* DISPLAY_H */
* server fserver.abc.com partition /vicepa RW Site
* server fserver.abc.com partition /vicepa RO Site
*/
-void kafs_display_vldb_site_list(struct kafs_context *ctx,
+bool kafs_display_vldb_site_list(struct kafs_context *ctx,
struct kafs_vldb_entry *vldb,
const char *indent)
{
- const char *ptype;
+ const char *ptype, *part;
unsigned int i;
- char abuf[1024], pbuf[64];
+ char abuf[1024];
printf("%snumber of sites -> %u\n", indent, vldb->nr_sites);
for (i = 0; i < vldb->nr_sites; i++) {
unsigned int flags = site->flags;
kafs_sprint_site(ctx, site, abuf, sizeof(abuf));
- kafs_sprint_partition(ctx, &site->partition, pbuf, sizeof(pbuf));
+ part = kafs_sprint_partition(ctx, &site->partition);
+ if (!part)
+ return false;
if (flags & VLSF_ROVOL)
ptype = "RO";
ptype = "Back";
printf("%s server %s partition %s %s Site\n",
- indent, abuf, pbuf, ptype);
+ indent, abuf, part, ptype);
}
if (vldb->flags & (VLOP_MOVE |
if (vldb->flags & VLOP_DUMP)
printf("%sVolume is locked for a dump/restore operation", indent);
}
+
+ return true;
}
/*
* proj.foo 536870957 RW 40475760 K On-line
*
*/
-void display_vol_oneline_summary(struct kafs_context *ctx,
+bool display_vol_oneline_summary(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *partition,
struct kafs_volume_info *vi)
{
char tbuf[32];
vol_type(vi, tbuf),
vi->size,
vol_state(vi));
+ return true;
}
/*
* Display a volume information timestamp.
*/
-static void display_vol_timestamp(const char *key, time_t t)
+static void display_vol_timestamp(const char *key, struct timespec *t)
{
printf("%s", key);
kafs_print_time_or_never(t);
* <blank>
*
*/
-void display_vol_information(struct kafs_context *ctx,
+bool 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];
+ const char *part_name;
+ char abuf[1024];
kafs_sprint_address(ctx, &server->vs_addrs[0], abuf, sizeof(abuf));
- kafs_sprint_partition(ctx, part, pbuf, sizeof(pbuf));
+ part_name = kafs_sprint_partition(ctx, part);
- display_vol_oneline_summary(ctx, vi);
- printf(" %s %s\n", abuf, pbuf);
+ display_vol_oneline_summary(ctx, server, part, vi);
+ printf(" %s %s\n", abuf, part_name);
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",
+ printf(" MaxQuota %10llu 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(" %llu accesses in the past day (i.e., vnode references)\n",
vi->day_use);
printf("\n");
+ return true;
}
/*
/*
* Display a volume information timestamp in machine-parseable format
*/
-static void display_vol_mp_timestamp(const char *key, time_t t)
+static void display_vol_mp_timestamp(const char *key, const struct timespec *t)
{
- printf("%s\t%-10lu\t", key, t);
+ printf("%s\t%-10lu\t", key, t->tv_sec);
kafs_print_time(t);
printf("\n");
}
struct kafs_partition *partition,
struct kafs_volume_info *vi)
{
- char abuf[20], sbuf[1024], pbuf[64], tbuf[16];
+ const char *part;
+ char abuf[20], sbuf[1024], tbuf[16];
int i;
abuf[0] = 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));
+ part = kafs_sprint_partition(ctx, partition);
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("part\t\t%s\n", part);
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("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);
+ 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);
+ printf("maxquota\t%llu\n", vi->max_quota);
if (vi->has_min_quota)
- printf("minquota\t%-7u\t(Optional)\n", vi->min_quota);
+ printf("minquota\t%-7llu\t(Optional)\n", vi->min_quota);
- printf("filecount\t%u\n", vi->file_count);
- printf("dayUse\t\t%u\n", vi->day_use);
+ printf("filecount\t%llu\n", vi->file_count);
+ printf("dayUse\t\t%llu\n", vi->day_use);
}
/*
{
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->nr_week_use > 0)
+ printf("weekUse\t\t%-7llu\t(Optional)\n", vi->week_use[0]);
if (vi->has_spare2)
printf("spare2\t\t%-7u\t(Optional)\n", vi->spare2);
if (vi->has_spare3)
struct kafs_partition {
unsigned int id;
+ char *name; /* "/vicepa" ... "/vicepzz" */
};
struct kafs_fileserver_spec {
#include "volservice.h"
#include "afs_xg.h"
+/*
+ * Convert an AFS 32-bit time into a timespec.
+ */
+static struct timespec afs_time_to_timespec(unsigned int t)
+{
+ struct timespec ts;
+
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+
+ return ts;
+}
+
+/*
+ * Convert a signed 100ns-resolution 64-bit time into a timespec.
+ */
+static struct timespec yfs_time_to_timespec(struct opr_time yt)
+{
+ struct timespec ts;
+ unsigned long long abs_t, div, rem, t = yt.time;
+
+ /*
+ * Unfortunately can not use normal 64 bit division on 32 bit arch, but
+ * the alternative, do_div, does not work with negative numbers so have
+ * to special case them
+ */
+ if (t < 0) {
+ abs_t = -t;
+ div = abs_t / 10000000;
+ rem = abs_t % 10000000;
+ ts.tv_nsec = -(div * 100);
+ ts.tv_sec = rem;
+ } else {
+ abs_t = t;
+ div = abs_t / 10000000;
+ rem = abs_t % 10000000;
+ ts.tv_nsec = div * 100;
+ ts.tv_sec = rem;
+ }
+
+ return ts;
+}
+
+/*
+ * Expand a volume information list by a number of entries.
+ */
+static bool expand_kafs_volume_info_list(struct kafs_context *ctx,
+ struct kafs_volume_info_list *vlist,
+ size_t add_entries)
+{
+ struct kafs_volume_info **list = vlist->entries;
+ size_t max;
+
+ if (vlist->nr_entries + add_entries <= vlist->max_entries)
+ return true;
+
+ max = vlist->nr_entries + add_entries + 1;
+ list = reallocarray(list, max, sizeof(list[0]));
+ if (!list)
+ return kafs_nomem(ctx);
+
+ memset(list + vlist->max_entries, 0, (max - vlist->max_entries) * sizeof(list[0]));
+ vlist->max_entries = max - 1;
+ vlist->entries = list;
+ return true;
+}
+
/**
* kafs_vol_monitor_transaction - Get the state of ongoing transactions on a volume server
* @ctx: The cell and authentication context
struct kafs_vol_transaction_info *info = &list[i];
struct 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 = 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->tid = r->tid;
+ info->time.tv_sec = r->time;
+ info->creation_time.tv_sec = r->creationTime;
+ info->return_code = r->returnCode;
+ info->volid = r->volid;
+ info->partition = 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.tv_sec = r->lastSendTime;
+ info->last_receive_time.tv_sec = r->lastReceiveTime;
strncpy(info->last_proc_name, r->lastProcName, sizeof(info->last_proc_name));
}
vi->parent_id = info->parentID;
vi->clone_id = info->cloneID;
vi->status = info->status;
- vi->copy_date = info->copyDate;
+ vi->copy_date = afs_time_to_timespec(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->creation_date = afs_time_to_timespec(info->creationDate);
+ vi->access_date = afs_time_to_timespec(info->accessDate);
+ vi->update_date = afs_time_to_timespec(info->updateDate);
+ vi->backup_date = afs_time_to_timespec(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 = info->spare1;
+ vi->week_use[0] = info->spare1;
vi->spare2 = info->spare2;
vi->spare3 = info->spare3;
vi->has_flags = true;
- vi->has_need_salvage = true;
+ vi->has_in_use = true;
vi->has_min_quota = true;
- vi->has_week_use = true;
+ vi->has_need_salvage = true;
+ vi->has_size = true;
vi->has_spare2 = true;
vi->has_spare3 = true;
+ vi->nr_week_use = 1;
}
/*
vi->parent_id = xinfo->parentID;
vi->clone_id = xinfo->cloneID;
vi->status = xinfo->status;
- vi->copy_date = xinfo->copyDate;
+ vi->copy_date = afs_time_to_timespec(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->creation_date = afs_time_to_timespec(xinfo->creationDate);
+ vi->access_date = afs_time_to_timespec(xinfo->accessDate);
+ vi->update_date = afs_time_to_timespec(xinfo->updateDate);
+ vi->backup_date = afs_time_to_timespec(xinfo->backupDate);
vi->day_use = xinfo->dayUse;
vi->file_count = xinfo->filecount;
vi->max_quota = xinfo->maxquota;
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;
+}
+
+/*
+ * Convert an xvolintInfo struct to a kafs_volume_info record.
+ */
+static void kafs_volintInfo64_to_volume_info(struct volintInfo64 *info,
+ struct volintStats64 *stats,
+ struct kafs_volume_info *vi)
+{
+ int i;
+
+ strcpy(vi->name, info->name);
+ if (info->offlineMessage && info->offlineMessage[0]) {
+ vi->offline_msg = info->offlineMessage;
+ info->offlineMessage = NULL;
+ }
+
+ 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->flags = info->flags;
+ vi->owner = info->owner;
+
+ vi->creation_date = yfs_time_to_timespec(info->creationDate);
+ vi->access_date = yfs_time_to_timespec(info->accessDate);
+ vi->update_date = yfs_time_to_timespec(info->updateDate);
+ vi->expiration_date = yfs_time_to_timespec(info->expirationDate);
+ vi->backup_date = yfs_time_to_timespec(info->backupDate);
+ vi->copy_date = yfs_time_to_timespec(info->copyDate);
+
+ vi->max_quota = info->maxquota;
+ vi->min_quota = info->minquota;
+ vi->max_files = info->maxfiles;
+ vi->disk_used = info->diskused;
+ vi->file_count = info->filecount;
+ vi->vol_update_counter = info->volUpdateCounter;
+
+ vi->day_use_date = yfs_time_to_timespec(info->dayUseDate);
+ vi->day_use = info->dayUse;
+ for (i = 0; i < 7; i++)
+ vi->week_use[i] = info->weekUse[i];
+
+ vi->has_day_use_date = true;
+ vi->has_disk_used = true;
+ vi->has_expiration_date = true;
+ vi->has_flags = true;
+ vi->has_max_files = true;
+ vi->has_min_quota = true;
+ vi->has_owner = true;
+ vi->has_vol_update_counter = true;
+ vi->nr_week_use = 7;
}
/**
return ret;
}
+/**
+ * kafs_YFSVOL_FetchVolumeInfo64 - Get the state of an instance of a volume
+ * @ctx: The cell and authentication context
+ * @server: The volume server to contact
+ * @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.
+ */
+bool kafs_YFSVOL_FetchVolumeInfo64(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *partition,
+ kafs_volume_id_t volid,
+ struct kafs_volume_info *vi)
+{
+ struct volintInfo64 result_entry;
+ struct volintStats64 result_stats;
+ bool ret;
+
+ ret = YFSVOL_FetchVolumeInfo64(&server->vs_params, partition->id, volid,
+ 1, 1, &result_entry, &result_stats,
+ &ctx->result);
+ if (ret)
+ kafs_volintInfo64_to_volume_info(&result_entry, &result_stats, vi);
+
+ return ret;
+}
+
/**
* kafs_query_volume_state - Query the state of an instance of a volume
* @ctx: The cell and authentication context
return true;
}
+/**
+ * kafs_VOLSER_ListVolumes - Get the ordinary states of volume instances on a partition
+ * @ctx: The cell and authentication context
+ * @server: The volume server to contact
+ * @partition: The partition on which the volumes reside
+ * @vilist: 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.
+ */
+bool kafs_VOLSER_ListVolumes(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *partition,
+ struct kafs_volume_info *vi)
+{
+ struct volintInfo **infos;
+ unsigned int nr;
+ bool ret;
+
+ ret = VOLSER_ListVolumes(&server->vs_params, partition->id, 1,
+ &infos, &nr, &ctx->result);
+ if (ret) {
+ if (nr)
+ kafs_volintinfo_to_volume_info(infos[0], vi);
+ else
+ ret = kafs_error(ctx, "No volume information results returned");
+ rxgen_bulk_free_volintInfo(infos, nr);
+ }
+
+ return ret;
+}
+
+/*
+ * Query the extended state of a volume.
+ */
+bool kafs_VOLSER_XListVolumes(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *partition,
+ struct kafs_volume_info *vi)
+{
+ struct xvolintInfo **xinfos;
+ unsigned int nr;
+ bool ret;
+
+ ret = VOLSER_XListVolumes(&server->vs_params, partition->id, 1,
+ &xinfos, &nr, &ctx->result);
+ if (ret) {
+ if (nr)
+ kafs_xvolintinfo_to_volume_info(xinfos[0], vi);
+ else
+ ret = kafs_error(ctx, "No volume information results returned");
+ rxgen_bulk_free_xvolintInfo(xinfos, nr);
+ }
+
+ return ret;
+}
+
+/**
+ * kafs_query_volume_states - Query the state of the volumes on a partition
+ * @ctx: The cell and authentication context
+ * @server: The volume server to contact
+ * @partition: The partition to search
+ * @extended: Whether extended info is required
+ * @vilist: The list to add the returned record to
+ *
+ * Query the state of a volume residing in a particular partition on a
+ * particular volume server. If successful, a record is allocated and
+ * added to the list.
+ */
+bool kafs_query_volume_states(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *partition,
+ bool extended,
+ struct kafs_volume_info_list *vilist)
+{
+ struct kafs_volume_info *vi;
+ bool ret;
+
+ if (!expand_kafs_volume_info_list(ctx, vilist, 1))
+ return false;
+
+ vi = calloc(1, sizeof(*vi));
+ if (!vi)
+ return kafs_nomem(ctx);
+
+ if (extended)
+ ret = kafs_VOLSER_XListVolumes(ctx, server, partition, vi);
+ else
+ ret = kafs_VOLSER_ListVolumes(ctx, server, partition, vi);
+ if (!ret) {
+ free(vi);
+ return false;
+ }
+
+ vilist->entries[vilist->nr_entries++] = vi;
+ return true;
+}
+
/**
* kafs_list_partitions - Get a list of partitions on a server.
* @ctx: The cell and authentication context
* Source transDebugInfo.
*/
struct kafs_vol_transaction_info {
- uint32_t tid;
- time_t time;
- time_t creation_time;
- uint32_t return_code;
- uint32_t volid;
- uint32_t partition;
- uint16_t iflags;
- uint8_t vflags;
- uint8_t tflags;
- char last_proc_name[30];
- uint32_t call_valid;
- uint32_t read_next;
- uint32_t transmit_next;
- time_t last_send_time;
- time_t last_receive_time;
+ uint32_t tid;
+ struct timespec time;
+ struct timespec creation_time;
+ uint32_t return_code;
+ uint32_t volid;
+ uint32_t partition;
+ uint16_t iflags;
+ uint8_t vflags;
+ uint8_t tflags;
+ char last_proc_name[30];
+ uint32_t call_valid;
+ uint32_t read_next;
+ uint32_t transmit_next;
+ struct timespec last_send_time;
+ struct timespec last_receive_time;
};
struct kafs_vol_transaction_info_list {
* Source: volintInfo, xvolintInfo.
*/
struct kafs_volume_info {
- kafs_volume_id_t volid;
- kafs_volume_id_t backup_id;
- kafs_volume_id_t parent_id;
- kafs_volume_id_t clone_id;
- unsigned int type;
- unsigned int status;
- unsigned int copy_date;
- bool in_use;
- bool needs_salvage;
- bool destroy_me;
- time_t creation_date;
- time_t access_date;
- time_t update_date;
- time_t backup_date;
- unsigned int day_use;
- unsigned int week_use; /* spare1 */
- unsigned int file_count;
- unsigned int max_quota;
- unsigned int min_quota; /* spare0 */
- 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 has_flags:1;
- bool has_need_salvage:1;
- bool has_min_quota:1;
- bool has_stats:1;
- bool has_week_use:1;
- bool has_spare2:1;
- bool has_spare3:1;
-
- char name[VNAMESIZE];
+ kafs_volume_id_t volid;
+ kafs_volume_id_t backup_id;
+ kafs_volume_id_t parent_id;
+ kafs_volume_id_t clone_id;
+ unsigned int type;
+ unsigned int status;
+ unsigned long long owner;
+
+ struct timespec creation_date;
+ struct timespec access_date;
+ struct timespec update_date;
+ struct timespec expiration_date;
+ struct timespec backup_date;
+ struct timespec copy_date;
+ struct timespec 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;
+
+ char *offline_msg;
+ char name[YVNAMESIZE];
+};
+
+/*
+ * List of volume information objects.
+ */
+struct kafs_volume_info_list {
+ unsigned int nr_entries;
+ unsigned int max_entries;
+ struct kafs_volume_info **entries;
};
/*
extern bool kafs_query_volume_state(struct kafs_context *, struct kafs_fileserver *,
struct kafs_partition *, kafs_volume_id_t, bool,
struct kafs_volume_info **);
+extern bool kafs_query_volume_states(struct kafs_context *, struct kafs_fileserver *,
+ struct kafs_partition *, bool,
+ struct kafs_volume_info_list *);
/*
* Inline functions
*/
+static inline
+void clear_kafs_partition(struct kafs_partition *partition)
+{
+ free(partition->name);
+ partition->name = NULL;
+}
+
static inline
void clear_kafs_partition_list(struct kafs_partition_list *partitions)
{
free(partitions->parts);
}
-static inline
-void clear_kafs_vol_transaction_info_list(struct kafs_vol_transaction_info_list *info_list)
+static inline void clear_kafs_vol_transaction_info_list(struct kafs_vol_transaction_info_list *list)
{
- free(info_list->info);
- info_list->info = NULL;
+ free(list->info);
+ list->info = NULL;
+ list->count = 0;
}
+static inline void clear_kafs_volume_info_list(struct kafs_volume_info_list *list)
+{
+ free(list->entries);
+ list->entries = NULL;
+ list->nr_entries = 0;
+ list->max_entries = 0;
+}
+
+
#endif /* VLSERVICE_H */
#include "afs_xg.h"
#include "display.h"
-static void display_vldb(struct kafs_context *ctx, struct kafs_vldb_entry *vldb)
+static bool display_vldb(struct kafs_context *ctx, struct kafs_vldb_entry *vldb)
{
if (vldb->volume_id[RWVOL] != 0)
printf(" RWrite: %10llu", vldb->volume_id[RWVOL]);
printf(" Backup: %10llu", vldb->volume_id[BACKVOL]);
printf("\n");
- kafs_display_vldb_site_list(ctx, vldb, " ");
+ return kafs_display_vldb_site_list(ctx, vldb, " ");
}
-static void display_normal(struct kafs_context *ctx,
+static bool display_normal(struct kafs_context *ctx,
struct kafs_vldb_entry *vldb,
struct kafs_vldb_site *site,
struct kafs_volume_info *vi,
if (extended)
display_vol_statistics(ctx, vi);
}
- display_vldb(ctx, vldb);
+ return display_vldb(ctx, vldb);
}
-static void display_format(struct kafs_context *ctx,
+static bool display_format(struct kafs_context *ctx,
struct kafs_vldb_entry *vldb,
struct kafs_vldb_site *site,
struct kafs_volume_info *vi)
display_vol_mp_information(ctx, site->server, &site->partition, vi);
printf("\n");
}
- display_vldb(ctx, vldb);
+ return display_vldb(ctx, vldb);
}
/***
}
if (a_format && !a_extended)
- display_format(ctx, vldb, site, vi);
+ ret = display_format(ctx, vldb, site, vi);
else
- display_normal(ctx, vldb, site, vi, a_extended);
- ret = true;
+ ret = display_normal(ctx, vldb, site, vi, a_extended);
error:
clear_kafs_vldb_entry_list(&vlist);
#include "afs_xg.h"
#include "display.h"
-static void kafs_print_vl_record(struct kafs_context *ctx,
+static bool kafs_print_vl_record(struct kafs_context *ctx,
struct kafs_vldb_entry *vldb)
{
unsigned int flags;
+ bool ret;
printf("%s\n", vldb->name);
printf(" ");
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, " ");
+ ret = kafs_display_vldb_site_list(ctx, vldb, " ");
printf("\n");
+ return ret;
}
static int kafs_cmp_entries_by_name(const void *_a, const void *_b)
!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]);
+ if (!kafs_print_vl_record(ctx, vlist.entries[0]))
+ return false;
} else {
if (!kafs_look_up_volumes_by_attributes(ctx, a_server,
a_partition, a_locked,
kafs_cmp_entries_by_name);
for (i = 0; i < vlist.nr_entries; i++)
- kafs_print_vl_record(ctx, vlist.entries[i]);
+ if (!kafs_print_vl_record(ctx, vlist.entries[i]))
+ return false;
if (!a_quiet)
printf("Total entries: %u\n", vlist.nr_entries);
}
--- /dev/null
+/* The "vos listvol" 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 "volservice.h"
+#include "arg_parse.h"
+#include "display.h"
+#include "afs_xg.h"
+
+static bool display_fast(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *part,
+ struct kafs_volume_info *vi)
+{
+ printf("%llu\n", vi->volid);
+ return true;
+}
+
+static bool display_extended(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *part,
+ struct kafs_volume_info *vi)
+{
+ display_vol_information(ctx, server, part, vi);
+ display_vol_statistics(ctx, vi);
+ return true;
+}
+
+static bool display_format_normal(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *part,
+ struct kafs_volume_info *vi)
+{
+ display_vol_mp_information(ctx, server, part, vi);
+ printf("END_OF_ENTRY\n");
+ return true;
+}
+
+static const char *const reads_labels[] = {
+ "reads_same_net",
+ "reads_same_net_auth",
+ "reads_diff_net",
+ "reads_diff_net_auth",
+};
+
+static const char *const writes_labels[] = {
+ "writes_same_net",
+ "writes_same_net_auth",
+ "writes_diff_net",
+ "writes_diff_net_auth",
+};
+
+static bool display_format_extended(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *part,
+ struct kafs_volume_info *vi)
+{
+ int i;
+
+ if (vi->status != VOK) {
+ if (vi->status == VBUSY)
+ printf("VOLUME_BUSY\t%llu\n", vi->volid);
+ else
+ printf("COULD_NOT_ATTACH_VOLUME\t%llu\n", vi->volid);
+ return true;
+ }
+
+ display_vol_mp_basic_information(ctx, server, part, vi);
+
+ for (i = 0; i < 4; i++)
+ printf("%s\t%8d\n", reads_labels[i], vi->stat_reads[i]);
+ for (i = 0; i < 4; i++)
+ printf("%s\t%8d\n", writes_labels[i], vi->stat_writes[i]);
+ for (i = 0; i < 6; i++) {
+ printf("file_same_author_idx_%d\t%8d\n", i, vi->stat_fileSameAuthor[i]);
+ printf("file_diff_author_idx_%d\t%8d\n", i, vi->stat_fileDiffAuthor[i]);
+ printf("dir_same_author_idx_%d\t%8d\n", i, vi->stat_dirSameAuthor[i]);
+ printf("dir_dif_author_idx_%d\t%8d\n", i, vi->stat_dirDiffAuthor[i]);
+ }
+
+ printf("END_OF_ENTRY");
+ return true;
+}
+
+static int compare_entries(const void *_a, const void *_b)
+{
+ const struct kafs_volume_info *a = _a;
+ const struct kafs_volume_info *b = _b;
+
+ return strcmp(a->name, b->name);
+}
+
+/*
+ * Display the records for a single partition in the appropriate format
+ */
+static bool display_one_partition(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *partition,
+ bool a_fast,
+ bool a_long,
+ bool a_quiet,
+ bool a_extended,
+ bool a_format)
+{
+ struct kafs_volume_info_list vilist = {};
+ struct kafs_volume_info *vi;
+ const char *part_name;
+ unsigned int n_online = 0, n_offline = 0, n_busy = 0, i;
+
+ bool (*display_func)(struct kafs_context *ctx,
+ struct kafs_fileserver *server,
+ struct kafs_partition *part,
+ struct kafs_volume_info *vi);
+
+ if (!kafs_query_volume_states(ctx, server, partition, a_extended, &vilist))
+ return false;
+
+ part_name = kafs_sprint_partition(ctx, partition);
+ if (!part_name)
+ return false;
+
+ if (!a_quiet)
+ printf("Total number of volumes on server %s partition %s: %u\n",
+ server->name, part_name, vilist.nr_entries);
+
+ display_func = display_vol_oneline_summary;
+ if (a_fast)
+ display_func = display_fast;
+ else if (a_format && a_extended)
+ display_func = display_format_extended;
+ else if (a_format)
+ display_func = display_format_normal;
+ else if (a_extended)
+ display_func = display_extended;
+ else if (a_long)
+ display_func = display_vol_information;
+
+ qsort(vilist.entries, vilist.nr_entries, sizeof(vilist.entries[0]),
+ compare_entries);
+
+ for (i = 0; i < vilist.nr_entries; i++) {
+ vi = vilist.entries[i];
+ if (vi->in_use)
+ n_online += 1;
+ if (vi->status == VBUSY)
+ n_busy += 1;
+ display_func(ctx, server, partition, vi);
+ }
+
+ if (!a_quiet) {
+ printf("\n");
+ if (!a_fast && !a_format) {
+ printf("Total volumes onLine %u; Total volumes offLine %u; Total busy %u\n",
+ n_online, n_offline, n_busy);
+ printf("\n");
+ } else if (a_format && a_extended) {
+ printf("VOLUMES_ONLINE %u\n", n_online);
+ printf("VOLUMES_OFFLINE %u\n", n_offline);
+ printf("VOLUMES_BUSY %u\n", n_busy);
+ }
+ }
+
+ clear_kafs_volume_info_list(&vilist);
+ return true;
+}
+
+/***
+ * COMMAND: vos listvol - Display information from a volume header
+ * ARG: "[-server <machine name>]"
+ * ARG: "[-partition <partition name>]"
+ * ARG: "[-fast]"
+ * ARG: "[-long]"
+ * ARG: "[-quiet]"
+ * ARG: "[-extended]"
+ * ARG: "[-format]"
+ * ARG: "[-cell <cell name>]"
+ * ARG: "[-noauth]" - Auth
+ * ARG: "[-localauth]" - Auth
+ * ARG: "[-verbose]"
+ * ARG: "[-encrypt]" - Auth
+ * ARG: "[-noresolve]"
+ * NOCOMBINE: fast, extended
+ *
+ * Display information from a volume header.
+ */
+bool COMMAND_vos_listvol(
+ struct kafs_context *ctx,
+ struct kafs_volserver_spec *a_server,
+ struct kafs_partition *a_partition,
+ bool a_fast,
+ bool a_long,
+ bool a_quiet,
+ bool a_extended,
+ bool a_format,
+ bool a_verbose,
+ bool a_noresolve)
+{
+ struct kafs_partition_list partitions = {};
+ struct kafs_fileserver *server;
+ const char *part;
+ unsigned int i;
+ bool ret;
+
+ _enter("");
+
+ ctx->no_resolve = a_noresolve;
+
+ if (!kafs_resolve_volserver_spec(ctx, a_server, &server))
+ return false;
+
+ if (!kafs_open_volserver(ctx, server))
+ return false;
+
+ if (a_partition) {
+ ret = display_one_partition(ctx, server, a_partition,
+ a_fast, a_long, a_quiet, a_extended,
+ a_format);
+ if (!ret) {
+ if (ctx->result.source == rxrpc_error_remote_abort &&
+ ctx->result.abort_code == VOLSERILLEGAL_PARTITION) {
+ part = kafs_sprint_partition(ctx, a_partition);
+ kafs_error(ctx, "vos : partition %s does not exist on the server",
+ part);
+ }
+ }
+ } else {
+ ret = kafs_list_partitions(ctx, server, &partitions);
+ if (!ret)
+ goto out;
+ for (i = 0; i < partitions.count; i++)
+ if (!display_one_partition(ctx, server, &partitions.parts[i],
+ a_fast, a_long, a_quiet, a_extended,
+ a_format))
+ goto out;
+ }
+
+out:
+ clear_kafs_partition_list(&partitions);
+ return ret;
+}
struct kafs_vol_transaction_info_list transactions = {};
struct kafs_fileserver *server;
unsigned int i;
- char pbuf[32];
int ret = false;
_enter("");
printf("--------------------------------------------\n");
for (i = 0; i < transactions.count; i++) {
struct kafs_vol_transaction_info *trans = &transactions.info[i];
- struct kafs_partition part;
+ struct kafs_partition partition;
+ const char *part;
unsigned int iflags = trans->iflags;
printf("transaction: %d created: ", trans->tid);
- kafs_print_time(trans->creation_time);
+ kafs_print_time(&trans->creation_time);
printf("\n");
printf("lastActiveTime: ");
- kafs_print_time(trans->time);
+ kafs_print_time(&trans->time);
printf("\n");
if (iflags & ITOffline)
else
printf("attachFlags: %u\n", trans->iflags);
- memset(&part, 0, sizeof(part));
- part.id = trans->partition;
- kafs_sprint_partition(ctx, &part, pbuf, sizeof(pbuf)),
+ memset(&partition, 0, sizeof(partition));
+ partition.id = trans->partition;
+ part = kafs_sprint_partition(ctx, &partition),
printf("volume: %u partition %s procedure %s",
- trans->volid, pbuf, trans->last_proc_name);
+ trans->volid, part, trans->last_proc_name);
+ clear_kafs_partition(&partition);
printf("packetRead: %u", trans->read_next);
- printf(" lastReceiveTime: %lu", trans->last_receive_time);
+ printf(" lastReceiveTime: %lu", trans->last_receive_time.tv_sec);
printf(" packetSend: %u", trans->transmit_next);
printf("\n");
- printf(" lastSendTime: %lu\n", trans->last_send_time);
+ printf(" lastSendTime: %lu\n", trans->last_send_time.tv_sec);
printf("--------------------------------------------\n");
}