2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #ifdef IGNORE_SOME_GCC_WARNINGS
16 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
20 #include <WINNT/afsreg.h>
24 #include <sys/statfs.h>
29 #include <rx/rx_queue.h>
32 #include <rx/rx_globals.h>
34 #include <afs/vlserver.h>
35 #include <afs/cellconfig.h>
37 #include <afs/afsutil.h>
39 #include <afs/afsint.h>
44 #include <afs/ihandle.h>
45 #include <afs/vnode.h>
46 #include <afs/volume.h>
47 #include <afs/com_err.h>
51 #include "volser_internal.h"
52 #include "volser_prototypes.h"
53 #include "vsutils_prototypes.h"
54 #include "lockprocs_prototypes.h"
56 #ifdef HAVE_POSIX_REGEX
60 /* Local Prototypes */
61 int PrintDiagnostics(char *astring, afs_int32 acode);
62 int GetVolumeInfo(afs_uint32 volid, afs_uint32 *server, afs_int32 *part,
63 afs_int32 *voltype, struct nvldbentry *rentry);
76 COMMONPARM_OFFSET_CELL = 25,
77 COMMONPARM_OFFSET_NOAUTH = 26,
78 COMMONPARM_OFFSET_LOCALAUTH = 27,
79 COMMONPARM_OFFSET_VERBOSE = 28,
80 COMMONPARM_OFFSET_ENCRYPT = 29,
81 COMMONPARM_OFFSET_NORESOLVE = 30,
82 COMMONPARM_OFFSET_CONFIG = 31,
86 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_CELL, \
87 "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");\
88 cmd_AddParmAlias(ts, COMMONPARM_OFFSET_CELL, "-c"); /* original -cell option */ \
89 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_NOAUTH, \
90 "-noauth", CMD_FLAG, CMD_OPTIONAL, "don't authenticate");\
91 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_LOCALAUTH, \
92 "-localauth",CMD_FLAG,CMD_OPTIONAL,"use server tickets");\
93 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_VERBOSE, \
94 "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose");\
95 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_ENCRYPT, \
96 "-encrypt", CMD_FLAG, CMD_OPTIONAL, "encrypt commands");\
97 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_NORESOLVE, \
98 "-noresolve", CMD_FLAG, CMD_OPTIONAL, "don't resolve addresses"); \
99 cmd_AddParmAtOffset(ts, COMMONPARM_OFFSET_CONFIG, \
100 "-config", CMD_SINGLE, CMD_OPTIONAL, "config location"); \
102 #define ERROR_EXIT(code) do { \
108 extern struct ubik_client *cstruct;
111 static struct tqHead busyHead, notokHead;
114 qInit(struct tqHead *ahead)
116 memset(ahead, 0, sizeof(struct tqHead));
122 qPut(struct tqHead *ahead, afs_uint32 volid)
126 elem = malloc(sizeof(struct tqElem));
127 elem->next = ahead->next;
135 qGet(struct tqHead *ahead, afs_uint32 *volid)
139 if (ahead->count <= 0)
141 *volid = ahead->next->volid;
143 ahead->next = tmp->next;
149 /* returns 1 if <filename> exists else 0 */
151 FileExists(char *filename)
157 code = usd_Open(filename, USD_OPEN_RDONLY, 0, &ufd);
161 code = USD_IOCTL(ufd, USD_IOCTL_GETSIZE, &size);
169 /* returns 1 if <name> doesnot end in .readonly or .backup, else 0 */
171 VolNameOK(char *name)
176 total = strlen(name);
177 if (!strcmp(&name[total - 9], ".readonly")) {
179 } else if (!strcmp(&name[total - 7], ".backup")) {
186 /* return 1 if name is a number else 0 */
188 IsNumeric(char *name)
197 for (i = 0; i < len; i++) {
198 if (*ptr < '0' || *ptr > '9') {
210 * Parse a server dotted address and return the address in network byte order
213 GetServerNoresolve(char *aname)
219 code = sscanf(aname, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
221 addr = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
222 addr = htonl(addr); /* convert to network byte order */
228 * Parse a server name/address and return a non-loopback address in network byte order
231 GetServer(char *aname)
234 afs_uint32 addr; /* in network byte order */
236 char hostname[MAXHOSTCHARS];
239 addr = GetServerNoresolve(aname);
241 if (!rx_IsLoopbackAddr(ntohl(addr)))
247 th = gethostbyname(aname);
249 for (i=0; i < th->h_length; i++) {
250 if (!rx_IsLoopbackAddr(ntohl(*(afs_uint32 *)th->h_addr_list[i]))) {
251 memcpy(&addr, th->h_addr_list[i], sizeof(addr));
257 * If we reach this point all of the addresses returned by
258 * gethostbyname() are loopback addresses. We assume that means
259 * that the name is supposed to describe the machine this code
260 * is executing on. Try gethostname() to and check to see if
261 * that name can provide us a non-loopback address.
263 code = gethostname(hostname, MAXHOSTCHARS);
265 th = gethostbyname(hostname);
267 for (i=0; i < th->h_length; i++) {
268 if (!rx_IsLoopbackAddr(ntohl(*(afs_uint32 *)th->h_addr_list[i]))) {
269 memcpy(&addr, th->h_addr_list[i], sizeof(addr));
278 * No non-loopback address could be obtained for 'aname'.
284 GetVolumeType(char *aname)
287 if (!strcmp(aname, "ro"))
289 else if (!strcmp(aname, "rw"))
291 else if (!strcmp(aname, "bk"))
298 IsPartValid(afs_int32 partId, afs_uint32 server, afs_int32 *code)
300 struct partList dummyPartList;
306 *code = UV_ListPartitions(server, &dummyPartList, &cnt);
309 for (i = 0; i < cnt; i++) {
310 if (dummyPartList.partFlags[i] & PARTVALID)
311 if (dummyPartList.partId[i] == partId)
319 /*sends the contents of file associated with <fd> and <blksize> to Rx Stream
320 * associated with <call> */
322 SendFile(usd_handle_t ufd, struct rx_call *call, long blksize)
324 char *buffer = (char *)0;
328 buffer = malloc(blksize);
330 fprintf(STDERR, "malloc failed\n");
335 #if !defined(AFS_NT40_ENV) && !defined(AFS_PTHREAD_ENV)
336 /* Only for this for non-NT, non-pthread. For NT, we can't select on
337 * non-socket FDs. For pthread environments, we don't need to select at
338 * all, since the following read() will block. */
341 FD_SET((intptr_t)(ufd->handle), &in);
342 /* don't timeout if read blocks */
343 IOMGR_Select(((intptr_t)(ufd->handle)) + 1, &in, 0, 0, 0);
345 error = USD_READ(ufd, buffer, blksize, &nbytes);
347 fprintf(STDERR, "File system read failed: %s\n",
348 afs_error_message(error));
355 if (rx_Write(call, buffer, nbytes) != nbytes) {
365 /* function invoked by UV_RestoreVolume, reads the data from rx_trx_stream and
366 * writes it out to the volume. */
368 WriteData(struct rx_call *call, void *rock)
370 char *filename = (char *) rock;
373 afs_int32 error, code;
375 afs_int64 currOffset;
381 if (!filename || !*filename) {
382 usd_StandardInput(&ufd);
386 code = usd_Open(filename, USD_OPEN_RDONLY, 0, &ufd);
389 code = USD_IOCTL(ufd, USD_IOCTL_GETBLKSIZE, &blksize);
392 fprintf(STDERR, "Could not access file '%s': %s\n", filename,
393 afs_error_message(code));
397 /* test if we have a valid dump */
398 USD_SEEK(ufd, 0, SEEK_END, &currOffset);
399 USD_SEEK(ufd, currOffset - sizeof(afs_uint32), SEEK_SET, &currOffset);
400 USD_READ(ufd, (char *)&buffer, sizeof(afs_uint32), &got);
401 if ((got != sizeof(afs_uint32)) || (ntohl(buffer) != DUMPENDMAGIC)) {
402 fprintf(STDERR, "Signature missing from end of file '%s'\n", filename);
406 USD_SEEK(ufd, 0, SEEK_SET, &currOffset);
408 code = SendFile(ufd, call, blksize);
415 code = USD_CLOSE(ufd);
417 fprintf(STDERR, "Could not close dump file %s\n",
418 (filename && *filename) ? filename : "STDOUT");
426 /* Receive data from <call> stream into file associated
427 * with <fd> <blksize>
430 ReceiveFile(usd_handle_t ufd, struct rx_call *call, long blksize)
434 afs_uint32 bytesleft, w;
437 buffer = malloc(blksize);
439 fprintf(STDERR, "memory allocation failed\n");
443 while ((bytesread = rx_Read(call, buffer, blksize)) > 0) {
444 for (bytesleft = bytesread; bytesleft; bytesleft -= w) {
445 #if !defined(AFS_NT40_ENV) && !defined(AFS_PTHREAD_ENV)
446 /* Only for this for non-NT, non-pthread. For NT, we can't select
447 * on non-socket FDs. For pthread environments, we don't need to
448 * select at all, since the following write() will block. */
451 FD_SET((intptr_t)(ufd->handle), &out);
452 /* don't timeout if write blocks */
453 IOMGR_Select(((intptr_t)(ufd->handle)) + 1, 0, &out, 0, 0);
456 USD_WRITE(ufd, &buffer[bytesread - bytesleft], bytesleft, &w);
458 fprintf(STDERR, "File system write failed: %s\n",
459 afs_error_message(error));
472 DumpFunction(struct rx_call *call, void *rock)
474 char *filename = (char *)rock;
475 usd_handle_t ufd; /* default is to stdout */
476 afs_int32 error = 0, code;
481 /* Open the output file */
482 if (!filename || !*filename) {
483 usd_StandardOutput(&ufd);
488 usd_Open(filename, USD_OPEN_CREATE | USD_OPEN_RDWR, 0666, &ufd);
492 code = USD_IOCTL(ufd, USD_IOCTL_SETSIZE, &size);
495 code = USD_IOCTL(ufd, USD_IOCTL_GETBLKSIZE, &blksize);
498 fprintf(STDERR, "Could not create file '%s': %s\n", filename,
499 afs_error_message(code));
500 ERROR_EXIT(VOLSERBADOP);
504 code = ReceiveFile(ufd, call, blksize);
509 /* Close the output file */
511 code = USD_CLOSE(ufd);
513 fprintf(STDERR, "Could not close dump file %s\n",
514 (filename && *filename) ? filename : "STDIN");
524 DisplayFormat(volintInfo *pntr, afs_uint32 server, afs_int32 part,
525 int *totalOK, int *totalNotOK, int *totalBusy, int fast,
526 int longlist, int disp)
532 fprintf(STDOUT, "%-10lu\n", (unsigned long)pntr->volid);
533 } else if (longlist) {
534 if (pntr->status == VOK) {
535 fprintf(STDOUT, "%-32s ", pntr->name);
536 fprintf(STDOUT, "%10lu ", (unsigned long)pntr->volid);
538 fprintf(STDOUT, "RW ");
540 fprintf(STDOUT, "RO ");
542 fprintf(STDOUT, "BK ");
543 fprintf(STDOUT, "%10d K ", pntr->size);
544 if (pntr->inUse == 1) {
545 fprintf(STDOUT, "On-line");
548 fprintf(STDOUT, "Off-line");
551 if (pntr->needsSalvaged == 1)
552 fprintf(STDOUT, "**needs salvage**");
553 fprintf(STDOUT, "\n");
554 MapPartIdIntoName(part, pname);
555 fprintf(STDOUT, " %s %s \n", hostutil_GetNameByINet(server),
557 fprintf(STDOUT, " RWrite %10lu ROnly %10lu Backup %10lu \n",
558 (unsigned long)pntr->parentID,
559 (unsigned long)pntr->cloneID,
560 (unsigned long)pntr->backupID);
561 fprintf(STDOUT, " MaxQuota %10d K \n", pntr->maxquota);
562 t = pntr->creationDate;
563 fprintf(STDOUT, " Creation %s",
566 fprintf(STDOUT, " Copy %s",
569 t = pntr->backupDate;
571 fprintf(STDOUT, " Backup Never\n");
573 fprintf(STDOUT, " Backup %s",
576 t = pntr->accessDate;
578 fprintf(STDOUT, " Last Access %s",
581 t = pntr->updateDate;
583 fprintf(STDOUT, " Last Update Never\n");
585 fprintf(STDOUT, " Last Update %s",
588 " %d accesses in the past day (i.e., vnode references)\n",
590 } else if (pntr->status == VBUSY) {
592 qPut(&busyHead, pntr->volid);
594 fprintf(STDOUT, "**** Volume %lu is busy ****\n",
595 (unsigned long)pntr->volid);
598 qPut(¬okHead, pntr->volid);
600 fprintf(STDOUT, "**** Could not attach volume %lu ****\n",
601 (unsigned long)pntr->volid);
603 fprintf(STDOUT, "\n");
604 } else { /* default listing */
605 if (pntr->status == VOK) {
606 fprintf(STDOUT, "%-32s ", pntr->name);
607 fprintf(STDOUT, "%10lu ", (unsigned long)pntr->volid);
609 fprintf(STDOUT, "RW ");
611 fprintf(STDOUT, "RO ");
613 fprintf(STDOUT, "BK ");
614 fprintf(STDOUT, "%10d K ", pntr->size);
615 if (pntr->inUse == 1) {
616 fprintf(STDOUT, "On-line");
619 fprintf(STDOUT, "Off-line");
622 if (pntr->needsSalvaged == 1)
623 fprintf(STDOUT, "**needs salvage**");
624 fprintf(STDOUT, "\n");
625 } else if (pntr->status == VBUSY) {
627 qPut(&busyHead, pntr->volid);
629 fprintf(STDOUT, "**** Volume %lu is busy ****\n",
630 (unsigned long)pntr->volid);
633 qPut(¬okHead, pntr->volid);
635 fprintf(STDOUT, "**** Could not attach volume %lu ****\n",
636 (unsigned long)pntr->volid);
641 /*------------------------------------------------------------------------
642 * PRIVATE XDisplayFormat
645 * Display the contents of one extended volume info structure.
648 * a_xInfoP : Ptr to extended volume info struct to print.
649 * a_servID : Server ID to print.
650 * a_partID : Partition ID to print.
651 * a_totalOKP : Ptr to total-OK counter.
652 * a_totalNotOKP : Ptr to total-screwed counter.
653 * a_totalBusyP : Ptr to total-busy counter.
654 * a_fast : Fast listing?
655 * a_int32 : Int32 listing?
656 * a_showProblems : Show volume problems?
662 * Nothing interesting.
666 *------------------------------------------------------------------------*/
669 XDisplayFormat(volintXInfo *a_xInfoP, afs_uint32 a_servID, afs_int32 a_partID,
670 int *a_totalOKP, int *a_totalNotOKP, int *a_totalBusyP,
671 int a_fast, int a_int32, int a_showProblems)
672 { /*XDisplayFormat */
680 fprintf(STDOUT, "%-10lu\n", (unsigned long)a_xInfoP->volid);
681 } else if (a_int32) {
683 * Fully-detailed listing.
685 if (a_xInfoP->status == VOK) {
687 * Volume's status is OK - all the fields are valid.
689 fprintf(STDOUT, "%-32s ", a_xInfoP->name);
690 fprintf(STDOUT, "%10lu ", (unsigned long)a_xInfoP->volid);
691 if (a_xInfoP->type == 0)
692 fprintf(STDOUT, "RW ");
693 if (a_xInfoP->type == 1)
694 fprintf(STDOUT, "RO ");
695 if (a_xInfoP->type == 2)
696 fprintf(STDOUT, "BK ");
697 fprintf(STDOUT, "%10d K used ", a_xInfoP->size);
698 fprintf(STDOUT, "%d files ", a_xInfoP->filecount);
699 if (a_xInfoP->inUse == 1) {
700 fprintf(STDOUT, "On-line");
703 fprintf(STDOUT, "Off-line");
706 fprintf(STDOUT, "\n");
707 MapPartIdIntoName(a_partID, pname);
708 fprintf(STDOUT, " %s %s \n", hostutil_GetNameByINet(a_servID),
710 fprintf(STDOUT, " RWrite %10lu ROnly %10lu Backup %10lu \n",
711 (unsigned long)a_xInfoP->parentID,
712 (unsigned long)a_xInfoP->cloneID,
713 (unsigned long)a_xInfoP->backupID);
714 fprintf(STDOUT, " MaxQuota %10d K \n", a_xInfoP->maxquota);
716 t = a_xInfoP->creationDate;
717 fprintf(STDOUT, " Creation %s",
720 t = a_xInfoP->copyDate;
721 fprintf(STDOUT, " Copy %s",
724 t = a_xInfoP->backupDate;
726 fprintf(STDOUT, " Backup Never\n");
728 fprintf(STDOUT, " Backup %s",
731 t = a_xInfoP->accessDate;
733 fprintf(STDOUT, " Last Access %s",
736 t = a_xInfoP->updateDate;
738 fprintf(STDOUT, " Last Update Never\n");
740 fprintf(STDOUT, " Last Update %s",
743 " %d accesses in the past day (i.e., vnode references)\n",
747 * Print all the read/write and authorship stats.
749 fprintf(STDOUT, "\n Raw Read/Write Stats\n");
751 " |-------------------------------------------|\n");
753 " | Same Network | Diff Network |\n");
755 " |----------|----------|----------|----------|\n");
757 " | Total | Auth | Total | Auth |\n");
759 " |----------|----------|----------|----------|\n");
760 fprintf(STDOUT, "Reads | %8d | %8d | %8d | %8d |\n",
761 a_xInfoP->stat_reads[VOLINT_STATS_SAME_NET],
762 a_xInfoP->stat_reads[VOLINT_STATS_SAME_NET_AUTH],
763 a_xInfoP->stat_reads[VOLINT_STATS_DIFF_NET],
764 a_xInfoP->stat_reads[VOLINT_STATS_DIFF_NET_AUTH]);
765 fprintf(STDOUT, "Writes | %8d | %8d | %8d | %8d |\n",
766 a_xInfoP->stat_writes[VOLINT_STATS_SAME_NET],
767 a_xInfoP->stat_writes[VOLINT_STATS_SAME_NET_AUTH],
768 a_xInfoP->stat_writes[VOLINT_STATS_DIFF_NET],
769 a_xInfoP->stat_writes[VOLINT_STATS_DIFF_NET_AUTH]);
771 " |-------------------------------------------|\n\n");
774 " Writes Affecting Authorship\n");
776 " |-------------------------------------------|\n");
778 " | File Authorship | Directory Authorship|\n");
780 " |----------|----------|----------|----------|\n");
782 " | Same | Diff | Same | Diff |\n");
784 " |----------|----------|----------|----------|\n");
785 fprintf(STDOUT, "0-60 sec | %8d | %8d | %8d | %8d |\n",
786 a_xInfoP->stat_fileSameAuthor[VOLINT_STATS_TIME_IDX_0],
787 a_xInfoP->stat_fileDiffAuthor[VOLINT_STATS_TIME_IDX_0],
788 a_xInfoP->stat_dirSameAuthor[VOLINT_STATS_TIME_IDX_0],
789 a_xInfoP->stat_dirDiffAuthor[VOLINT_STATS_TIME_IDX_0]);
790 fprintf(STDOUT, "1-10 min | %8d | %8d | %8d | %8d |\n",
791 a_xInfoP->stat_fileSameAuthor[VOLINT_STATS_TIME_IDX_1],
792 a_xInfoP->stat_fileDiffAuthor[VOLINT_STATS_TIME_IDX_1],
793 a_xInfoP->stat_dirSameAuthor[VOLINT_STATS_TIME_IDX_1],
794 a_xInfoP->stat_dirDiffAuthor[VOLINT_STATS_TIME_IDX_1]);
795 fprintf(STDOUT, "10min-1hr | %8d | %8d | %8d | %8d |\n",
796 a_xInfoP->stat_fileSameAuthor[VOLINT_STATS_TIME_IDX_2],
797 a_xInfoP->stat_fileDiffAuthor[VOLINT_STATS_TIME_IDX_2],
798 a_xInfoP->stat_dirSameAuthor[VOLINT_STATS_TIME_IDX_2],
799 a_xInfoP->stat_dirDiffAuthor[VOLINT_STATS_TIME_IDX_2]);
800 fprintf(STDOUT, "1hr-1day | %8d | %8d | %8d | %8d |\n",
801 a_xInfoP->stat_fileSameAuthor[VOLINT_STATS_TIME_IDX_3],
802 a_xInfoP->stat_fileDiffAuthor[VOLINT_STATS_TIME_IDX_3],
803 a_xInfoP->stat_dirSameAuthor[VOLINT_STATS_TIME_IDX_3],
804 a_xInfoP->stat_dirDiffAuthor[VOLINT_STATS_TIME_IDX_3]);
805 fprintf(STDOUT, "1day-1wk | %8d | %8d | %8d | %8d |\n",
806 a_xInfoP->stat_fileSameAuthor[VOLINT_STATS_TIME_IDX_4],
807 a_xInfoP->stat_fileDiffAuthor[VOLINT_STATS_TIME_IDX_4],
808 a_xInfoP->stat_dirSameAuthor[VOLINT_STATS_TIME_IDX_4],
809 a_xInfoP->stat_dirDiffAuthor[VOLINT_STATS_TIME_IDX_4]);
810 fprintf(STDOUT, "> 1wk | %8d | %8d | %8d | %8d |\n",
811 a_xInfoP->stat_fileSameAuthor[VOLINT_STATS_TIME_IDX_5],
812 a_xInfoP->stat_fileDiffAuthor[VOLINT_STATS_TIME_IDX_5],
813 a_xInfoP->stat_dirSameAuthor[VOLINT_STATS_TIME_IDX_5],
814 a_xInfoP->stat_dirDiffAuthor[VOLINT_STATS_TIME_IDX_5]);
816 " |-------------------------------------------|\n");
817 } /*Volume status OK */
818 else if (a_xInfoP->status == VBUSY) {
820 qPut(&busyHead, a_xInfoP->volid);
822 fprintf(STDOUT, "**** Volume %lu is busy ****\n",
823 (unsigned long)a_xInfoP->volid);
827 qPut(¬okHead, a_xInfoP->volid);
829 fprintf(STDOUT, "**** Could not attach volume %lu ****\n",
830 (unsigned long)a_xInfoP->volid);
831 } /*Screwed volume */
832 fprintf(STDOUT, "\n");
838 if (a_xInfoP->status == VOK) {
839 fprintf(STDOUT, "%-32s ", a_xInfoP->name);
840 fprintf(STDOUT, "%10lu ", (unsigned long)a_xInfoP->volid);
841 if (a_xInfoP->type == 0)
842 fprintf(STDOUT, "RW ");
843 if (a_xInfoP->type == 1)
844 fprintf(STDOUT, "RO ");
845 if (a_xInfoP->type == 2)
846 fprintf(STDOUT, "BK ");
847 fprintf(STDOUT, "%10d K ", a_xInfoP->size);
848 if (a_xInfoP->inUse == 1) {
849 fprintf(STDOUT, "On-line");
852 fprintf(STDOUT, "Off-line");
855 fprintf(STDOUT, "\n");
857 else if (a_xInfoP->status == VBUSY) {
859 qPut(&busyHead, a_xInfoP->volid);
861 fprintf(STDOUT, "**** Volume %lu is busy ****\n",
862 (unsigned long)a_xInfoP->volid);
866 qPut(¬okHead, a_xInfoP->volid);
868 fprintf(STDOUT, "**** Could not attach volume %lu ****\n",
869 (unsigned long)a_xInfoP->volid);
870 } /*Screwed volume */
871 } /*Default listing */
872 } /*XDisplayFormat */
874 /*------------------------------------------------------------------------
875 * PRIVATE XDisplayFormat2
878 * Display the formated contents of one extended volume info structure.
881 * a_xInfoP : Ptr to extended volume info struct to print.
882 * a_servID : Server ID to print.
883 * a_partID : Partition ID to print.
884 * a_totalOKP : Ptr to total-OK counter.
885 * a_totalNotOKP : Ptr to total-screwed counter.
886 * a_totalBusyP : Ptr to total-busy counter.
887 * a_fast : Fast listing?
888 * a_int32 : Int32 listing?
889 * a_showProblems : Show volume problems?
895 * Nothing interesting.
899 *------------------------------------------------------------------------*/
902 XDisplayFormat2(volintXInfo *a_xInfoP, afs_uint32 a_servID, afs_int32 a_partID,
903 int *a_totalOKP, int *a_totalNotOKP, int *a_totalBusyP,
904 int a_fast, int a_int32, int a_showProblems)
905 { /*XDisplayFormat */
911 fprintf(STDOUT, "vold_id\t%-10lu\n", (unsigned long)a_xInfoP->volid);
912 } else if (a_int32) {
914 * Fully-detailed listing.
916 if (a_xInfoP->status == VOK) {
918 * Volume's status is OK - all the fields are valid.
921 static long server_cache = -1, partition_cache = -1;
922 static char hostname[256], address[32], pname[16];
923 int i,ai[] = {VOLINT_STATS_TIME_IDX_0,VOLINT_STATS_TIME_IDX_1,VOLINT_STATS_TIME_IDX_2,
924 VOLINT_STATS_TIME_IDX_3,VOLINT_STATS_TIME_IDX_4,VOLINT_STATS_TIME_IDX_5};
926 if (a_servID != server_cache) {
930 strcpy(hostname, hostutil_GetNameByINet(a_servID));
931 strcpy(address, inet_ntoa(s));
932 server_cache = a_servID;
934 if (a_partID != partition_cache) {
935 MapPartIdIntoName(a_partID, pname);
936 partition_cache = a_partID;
939 fprintf(STDOUT, "name\t\t%s\n", a_xInfoP->name);
940 fprintf(STDOUT, "id\t\t%lu\n", afs_printable_uint32_lu(a_xInfoP->volid));
941 fprintf(STDOUT, "serv\t\t%s\t%s\n", address, hostname);
942 fprintf(STDOUT, "part\t\t%s\n", pname);
943 fprintf(STDOUT, "status\t\tOK\n");
944 fprintf(STDOUT, "backupID\t%lu\n",
945 afs_printable_uint32_lu(a_xInfoP->backupID));
946 fprintf(STDOUT, "parentID\t%lu\n",
947 afs_printable_uint32_lu(a_xInfoP->parentID));
948 fprintf(STDOUT, "cloneID\t\t%lu\n",
949 afs_printable_uint32_lu(a_xInfoP->cloneID));
950 fprintf(STDOUT, "inUse\t\t%s\n", a_xInfoP->inUse ? "Y" : "N");
951 switch (a_xInfoP->type) {
953 fprintf(STDOUT, "type\t\tRW\n");
956 fprintf(STDOUT, "type\t\tRO\n");
959 fprintf(STDOUT, "type\t\tBK\n");
962 fprintf(STDOUT, "type\t\t?\n");
965 t = a_xInfoP->creationDate;
966 fprintf(STDOUT, "creationDate\t%-9lu\t%s",
967 afs_printable_uint32_lu(a_xInfoP->creationDate),
970 t = a_xInfoP->accessDate;
971 fprintf(STDOUT, "accessDate\t%-9lu\t%s",
972 afs_printable_uint32_lu(a_xInfoP->accessDate),
975 t = a_xInfoP->updateDate;
976 fprintf(STDOUT, "updateDate\t%-9lu\t%s",
977 afs_printable_uint32_lu(a_xInfoP->updateDate),
980 t = a_xInfoP->backupDate;
981 fprintf(STDOUT, "backupDate\t%-9lu\t%s",
982 afs_printable_uint32_lu(a_xInfoP->backupDate),
985 t = a_xInfoP->copyDate;
986 fprintf(STDOUT, "copyDate\t%-9lu\t%s",
987 afs_printable_uint32_lu(a_xInfoP->copyDate),
990 fprintf(STDOUT, "diskused\t%u\n", a_xInfoP->size);
991 fprintf(STDOUT, "maxquota\t%u\n", a_xInfoP->maxquota);
993 fprintf(STDOUT, "filecount\t%u\n", a_xInfoP->filecount);
994 fprintf(STDOUT, "dayUse\t\t%u\n", a_xInfoP->dayUse);
998 fprintf(STDOUT,"reads_same_net\t%8d\n",a_xInfoP->stat_reads[VOLINT_STATS_SAME_NET]);
999 fprintf(STDOUT,"reads_same_net_auth\t%8d\n",a_xInfoP->stat_reads[VOLINT_STATS_SAME_NET_AUTH]);
1000 fprintf(STDOUT,"reads_diff_net\t%8d\n",a_xInfoP->stat_reads[VOLINT_STATS_DIFF_NET]);
1001 fprintf(STDOUT,"reads_diff_net_auth\t%8d\n",a_xInfoP->stat_reads[VOLINT_STATS_DIFF_NET_AUTH]);
1003 fprintf(STDOUT,"writes_same_net\t%8d\n",a_xInfoP->stat_writes[VOLINT_STATS_SAME_NET]);
1004 fprintf(STDOUT,"writes_same_net_auth\t%8d\n",a_xInfoP->stat_writes[VOLINT_STATS_SAME_NET_AUTH]);
1005 fprintf(STDOUT,"writes_diff_net\t%8d\n",a_xInfoP->stat_writes[VOLINT_STATS_DIFF_NET]);
1006 fprintf(STDOUT,"writes_diff_net_auth\t%8d\n",a_xInfoP->stat_writes[VOLINT_STATS_DIFF_NET_AUTH]);
1010 fprintf(STDOUT,"file_same_author_idx_%d\t%8d\n",i+1,a_xInfoP->stat_fileSameAuthor[ai[i]]);
1011 fprintf(STDOUT,"file_diff_author_idx_%d\t%8d\n",i+1,a_xInfoP->stat_fileDiffAuthor[ai[i]]);
1012 fprintf(STDOUT,"dir_same_author_idx_%d\t%8d\n",i+1,a_xInfoP->stat_dirSameAuthor[ai[i]]);
1013 fprintf(STDOUT,"dir_dif_author_idx_%d\t%8d\n",i+1,a_xInfoP->stat_dirDiffAuthor[ai[i]]);
1016 } /*Volume status OK */
1017 else if (a_xInfoP->status == VBUSY) {
1019 qPut(&busyHead, a_xInfoP->volid);
1021 fprintf(STDOUT, "BUSY_VOL\t%lu\n",
1022 (unsigned long)a_xInfoP->volid);
1026 qPut(¬okHead, a_xInfoP->volid);
1028 fprintf(STDOUT, "COULD_NOT_ATTACH\t%lu\n",
1029 (unsigned long)a_xInfoP->volid);
1030 } /*Screwed volume */
1036 if (a_xInfoP->status == VOK) {
1037 fprintf(STDOUT, "name\t%-32s\n", a_xInfoP->name);
1038 fprintf(STDOUT, "volID\t%10lu\n", (unsigned long)a_xInfoP->volid);
1039 if (a_xInfoP->type == 0)
1040 fprintf(STDOUT, "type\tRW\n");
1041 if (a_xInfoP->type == 1)
1042 fprintf(STDOUT, "type\tRO\n");
1043 if (a_xInfoP->type == 2)
1044 fprintf(STDOUT, "type\tBK\n");
1045 fprintf(STDOUT, "size\t%10dK\n", a_xInfoP->size);
1047 fprintf(STDOUT, "inUse\t%d\n",a_xInfoP->inUse);
1048 if (a_xInfoP->inUse == 1)
1054 else if (a_xInfoP->status == VBUSY) {
1056 qPut(&busyHead, a_xInfoP->volid);
1058 fprintf(STDOUT, "VOLUME_BUSY\t%lu\n",
1059 (unsigned long)a_xInfoP->volid);
1063 qPut(¬okHead, a_xInfoP->volid);
1065 fprintf(STDOUT, "COULD_NOT_ATTACH_VOLUME\t%lu\n",
1066 (unsigned long)a_xInfoP->volid);
1067 } /*Screwed volume */
1068 } /*Default listing */
1069 } /*XDisplayFormat */
1072 DisplayFormat2(long server, long partition, volintInfo *pntr)
1074 static long server_cache = -1, partition_cache = -1;
1075 static char hostname[256], address[32], pname[16];
1078 if (server != server_cache) {
1082 strcpy(hostname, hostutil_GetNameByINet(server));
1083 strcpy(address, inet_ntoa(s));
1084 server_cache = server;
1086 if (partition != partition_cache) {
1087 MapPartIdIntoName(partition, pname);
1088 partition_cache = partition;
1091 if (pntr->status == VOK)
1092 fprintf(STDOUT, "name\t\t%s\n", pntr->name);
1094 fprintf(STDOUT, "id\t\t%lu\n",
1095 afs_printable_uint32_lu(pntr->volid));
1096 fprintf(STDOUT, "serv\t\t%s\t%s\n", address, hostname);
1097 fprintf(STDOUT, "part\t\t%s\n", pname);
1098 switch (pntr->status) {
1100 fprintf(STDOUT, "status\t\tOK\n");
1103 fprintf(STDOUT, "status\t\tBUSY\n");
1106 fprintf(STDOUT, "status\t\tUNATTACHABLE\n");
1109 fprintf(STDOUT, "backupID\t%lu\n",
1110 afs_printable_uint32_lu(pntr->backupID));
1111 fprintf(STDOUT, "parentID\t%lu\n",
1112 afs_printable_uint32_lu(pntr->parentID));
1113 fprintf(STDOUT, "cloneID\t\t%lu\n",
1114 afs_printable_uint32_lu(pntr->cloneID));
1115 fprintf(STDOUT, "inUse\t\t%s\n", pntr->inUse ? "Y" : "N");
1116 fprintf(STDOUT, "needsSalvaged\t%s\n", pntr->needsSalvaged ? "Y" : "N");
1117 /* 0xD3 is from afs/volume.h since I had trouble including the file */
1118 fprintf(STDOUT, "destroyMe\t%s\n", pntr->destroyMe == 0xD3 ? "Y" : "N");
1119 switch (pntr->type) {
1121 fprintf(STDOUT, "type\t\tRW\n");
1124 fprintf(STDOUT, "type\t\tRO\n");
1127 fprintf(STDOUT, "type\t\tBK\n");
1130 fprintf(STDOUT, "type\t\t?\n");
1133 t = pntr->creationDate;
1134 fprintf(STDOUT, "creationDate\t%-9lu\t%s",
1135 afs_printable_uint32_lu(pntr->creationDate),
1138 t = pntr->accessDate;
1139 fprintf(STDOUT, "accessDate\t%-9lu\t%s",
1140 afs_printable_uint32_lu(pntr->accessDate),
1143 t = pntr->updateDate;
1144 fprintf(STDOUT, "updateDate\t%-9lu\t%s",
1145 afs_printable_uint32_lu(pntr->updateDate),
1148 t = pntr->backupDate;
1149 fprintf(STDOUT, "backupDate\t%-9lu\t%s",
1150 afs_printable_uint32_lu(pntr->backupDate),
1154 fprintf(STDOUT, "copyDate\t%-9lu\t%s",
1155 afs_printable_uint32_lu(pntr->copyDate),
1158 fprintf(STDOUT, "flags\t\t%#lx\t(Optional)\n",
1159 afs_printable_uint32_lu(pntr->flags));
1160 fprintf(STDOUT, "diskused\t%u\n", pntr->size);
1161 fprintf(STDOUT, "maxquota\t%u\n", pntr->maxquota);
1162 fprintf(STDOUT, "minquota\t%lu\t(Optional)\n",
1163 afs_printable_uint32_lu(pntr->spare0));
1164 fprintf(STDOUT, "filecount\t%u\n", pntr->filecount);
1165 fprintf(STDOUT, "dayUse\t\t%u\n", pntr->dayUse);
1166 fprintf(STDOUT, "weekUse\t\t%lu\t(Optional)\n",
1167 afs_printable_uint32_lu(pntr->spare1));
1168 fprintf(STDOUT, "spare2\t\t%lu\t(Optional)\n",
1169 afs_printable_uint32_lu(pntr->spare2));
1170 fprintf(STDOUT, "spare3\t\t%lu\t(Optional)\n",
1171 afs_printable_uint32_lu(pntr->spare3));
1176 DisplayVolumes2(long server, long partition, volintInfo *pntr, long count)
1180 for (i = 0; i < count; i++) {
1181 fprintf(STDOUT, "BEGIN_OF_ENTRY\n");
1182 DisplayFormat2(server, partition, pntr);
1183 fprintf(STDOUT, "END_OF_ENTRY\n\n");
1190 DisplayVolumes(afs_uint32 server, afs_int32 part, volintInfo *pntr,
1191 afs_int32 count, afs_int32 longlist, afs_int32 fast,
1194 int totalOK, totalNotOK, totalBusy, i;
1195 afs_uint32 volid = 0;
1202 for (i = 0; i < count; i++) {
1203 DisplayFormat(pntr, server, part, &totalOK, &totalNotOK, &totalBusy,
1208 while (busyHead.count) {
1209 qGet(&busyHead, &volid);
1210 fprintf(STDOUT, "**** Volume %lu is busy ****\n",
1211 (unsigned long)volid);
1215 while (notokHead.count) {
1216 qGet(¬okHead, &volid);
1217 fprintf(STDOUT, "**** Could not attach volume %lu ****\n",
1218 (unsigned long)volid);
1222 fprintf(STDOUT, "\n");
1225 "Total volumes onLine %d ; Total volumes offLine %d ; Total busy %d\n\n",
1226 totalOK, totalNotOK, totalBusy);
1230 /*------------------------------------------------------------------------
1231 * PRIVATE XDisplayVolumes
1234 * Display extended volume information.
1237 * a_servID : Pointer to the Rx call we're performing.
1238 * a_partID : Partition for which we want the extended list.
1239 * a_xInfoP : Ptr to extended volume info.
1240 * a_count : Number of volume records contained above.
1241 * a_int32 : Int32 listing generated?
1242 * a_fast : Fast listing generated?
1243 * a_quiet : Quiet listing generated?
1249 * Nothing interesting.
1253 *------------------------------------------------------------------------*/
1256 XDisplayVolumes(afs_uint32 a_servID, afs_int32 a_partID, volintXInfo *a_xInfoP,
1257 afs_int32 a_count, afs_int32 a_int32, afs_int32 a_fast,
1259 { /*XDisplayVolumes */
1261 int totalOK; /*Total OK volumes */
1262 int totalNotOK; /*Total screwed volumes */
1263 int totalBusy; /*Total busy volumes */
1264 int i; /*Loop variable */
1265 afs_uint32 volid = 0; /*Current volume ID */
1268 * Initialize counters and (global!!) queues.
1277 * Display each volume in the list.
1279 for (i = 0; i < a_count; i++) {
1280 XDisplayFormat(a_xInfoP, a_servID, a_partID, &totalOK, &totalNotOK,
1281 &totalBusy, a_fast, a_int32, 0);
1286 * If any volumes were found to be busy or screwed, display them.
1289 while (busyHead.count) {
1290 qGet(&busyHead, &volid);
1291 fprintf(STDOUT, "**** Volume %lu is busy ****\n",
1292 (unsigned long)volid);
1296 while (notokHead.count) {
1297 qGet(¬okHead, &volid);
1298 fprintf(STDOUT, "**** Could not attach volume %lu ****\n",
1299 (unsigned long)volid);
1304 fprintf(STDOUT, "\n");
1307 "Total volumes: %d on-line, %d off-line, %d busyd\n\n",
1308 totalOK, totalNotOK, totalBusy);
1312 } /*XDisplayVolumes */
1314 /*------------------------------------------------------------------------
1315 * PRIVATE XDisplayVolumes2
1318 * Display extended formated volume information.
1321 * a_servID : Pointer to the Rx call we're performing.
1322 * a_partID : Partition for which we want the extended list.
1323 * a_xInfoP : Ptr to extended volume info.
1324 * a_count : Number of volume records contained above.
1325 * a_int32 : Int32 listing generated?
1326 * a_fast : Fast listing generated?
1327 * a_quiet : Quiet listing generated?
1333 * Nothing interesting.
1337 *------------------------------------------------------------------------*/
1340 XDisplayVolumes2(afs_uint32 a_servID, afs_int32 a_partID, volintXInfo *a_xInfoP,
1341 afs_int32 a_count, afs_int32 a_int32, afs_int32 a_fast,
1343 { /*XDisplayVolumes */
1345 int totalOK; /*Total OK volumes */
1346 int totalNotOK; /*Total screwed volumes */
1347 int totalBusy; /*Total busy volumes */
1348 int i; /*Loop variable */
1349 afs_uint32 volid = 0; /*Current volume ID */
1352 * Initialize counters and (global!!) queues.
1361 * Display each volume in the list.
1363 for (i = 0; i < a_count; i++) {
1364 fprintf(STDOUT, "BEGIN_OF_ENTRY\n");
1365 XDisplayFormat2(a_xInfoP, a_servID, a_partID, &totalOK, &totalNotOK,
1366 &totalBusy, a_fast, a_int32, 0);
1367 fprintf(STDOUT, "END_OF_ENTRY\n");
1372 * If any volumes were found to be busy or screwed, display them.
1375 while (busyHead.count) {
1376 qGet(&busyHead, &volid);
1377 fprintf(STDOUT, "BUSY_VOL\t%lu\n",
1378 (unsigned long)volid);
1382 while (notokHead.count) {
1383 qGet(¬okHead, &volid);
1384 fprintf(STDOUT, "COULD_NOT_ATTACH\t%lu\n",
1385 (unsigned long)volid);
1390 fprintf(STDOUT, "\n");
1393 "VOLUMES_ONLINE\t%d\nVOLUMES_OFFLINE\t%d\nVOLUMES_BUSY\t%d\n",
1394 totalOK, totalNotOK, totalBusy);
1398 } /*XDisplayVolumes2 */
1401 /* set <server> and <part> to the correct values depending on
1402 * <voltype> and <entry> */
1404 GetServerAndPart(struct nvldbentry *entry, int voltype, afs_uint32 *server,
1405 afs_int32 *part, int *previdx)
1407 int i, istart, vtype;
1412 /* Doesn't check for non-existance of backup volume */
1413 if ((voltype == RWVOL) || (voltype == BACKVOL)) {
1415 istart = 0; /* seach the entire entry */
1418 /* Seach from beginning of entry or pick up where we left off */
1419 istart = ((*previdx < 0) ? 0 : *previdx + 1);
1422 for (i = istart; i < entry->nServers; i++) {
1423 if (entry->serverFlags[i] & vtype) {
1424 *server = entry->serverNumber[i];
1425 *part = entry->serverPartition[i];
1431 /* Didn't find any, return -1 */
1437 PrintLocked(afs_int32 aflags)
1439 afs_int32 flags = aflags & VLOP_ALLOPERS;
1442 fprintf(STDOUT, " Volume is currently LOCKED \n");
1444 if (flags & VLOP_MOVE) {
1445 fprintf(STDOUT, " Volume is locked for a move operation\n");
1447 if (flags & VLOP_RELEASE) {
1448 fprintf(STDOUT, " Volume is locked for a release operation\n");
1450 if (flags & VLOP_BACKUP) {
1451 fprintf(STDOUT, " Volume is locked for a backup operation\n");
1453 if (flags & VLOP_DELETE) {
1454 fprintf(STDOUT, " Volume is locked for a delete/misc operation\n");
1456 if (flags & VLOP_DUMP) {
1457 fprintf(STDOUT, " Volume is locked for a dump/restore operation\n");
1463 PostVolumeStats(struct nvldbentry *entry)
1465 SubEnumerateEntry(entry);
1466 /* Check for VLOP_ALLOPERS */
1467 PrintLocked(entry->flags);
1471 /*------------------------------------------------------------------------
1472 * PRIVATE XVolumeStats
1475 * Display extended volume information.
1478 * a_xInfoP : Ptr to extended volume info.
1479 * a_entryP : Ptr to the volume's VLDB entry.
1480 * a_srvID : Server ID.
1481 * a_partID : Partition ID.
1482 * a_volType : Type of volume to print.
1488 * Nothing interesting.
1492 *------------------------------------------------------------------------*/
1495 XVolumeStats(volintXInfo *a_xInfoP, struct nvldbentry *a_entryP,
1496 afs_int32 a_srvID, afs_int32 a_partID, int a_volType)
1499 int totalOK, totalNotOK, totalBusy; /*Dummies - we don't really count here */
1501 XDisplayFormat(a_xInfoP, /*Ptr to extended volume info */
1502 a_srvID, /*Server ID to print */
1503 a_partID, /*Partition ID to print */
1504 &totalOK, /*Ptr to total-OK counter */
1505 &totalNotOK, /*Ptr to total-screwed counter */
1506 &totalBusy, /*Ptr to total-busy counter */
1507 0, /*Don't do a fast listing */
1508 1, /*Do a long listing */
1509 1); /*Show volume problems */
1515 VolumeStats_int(volintInfo *pntr, struct nvldbentry *entry, afs_uint32 server,
1516 afs_int32 part, int voltype)
1522 DisplayFormat(pntr, server, part, &totalOK, &totalNotOK, &totalBusy, 0, 1,
1527 /* command to forcibly remove a volume */
1529 NukeVolume(struct cmd_syndesc *as)
1538 server = GetServer(tp = as->parms[0].items->data);
1540 fprintf(STDERR, "vos: server '%s' not found in host table\n", tp);
1544 partID = volutil_GetPartitionID(tp = as->parms[1].items->data);
1546 fprintf(STDERR, "vos: could not parse '%s' as a partition name", tp);
1550 volID = vsu_GetVolumeID(tp = as->parms[2].items->data, cstruct, &err);
1553 PrintError("", err);
1556 "vos: could not parse '%s' as a numeric volume ID", tp);
1561 "vos: forcibly removing all traces of volume %d, please wait...",
1564 code = UV_NukeVolume(server, partID, volID);
1566 fprintf(STDOUT, "done.\n");
1568 fprintf(STDOUT, "failed with code %d.\n", code);
1573 /*------------------------------------------------------------------------
1574 * PRIVATE ExamineVolume
1577 * Routine used to examine a single volume, contacting the VLDB as
1578 * well as the Volume Server.
1581 * as : Ptr to parsed command line arguments.
1584 * 0 for a successful operation,
1585 * Otherwise, one of the ubik or VolServer error values.
1588 * Nothing interesting.
1592 *------------------------------------------------------------------------
1595 ExamineVolume(struct cmd_syndesc *as, void *arock)
1597 struct nvldbentry entry;
1598 afs_int32 vcode = 0;
1599 volintInfo *pntr = (volintInfo *) 0;
1600 volintXInfo *xInfoP = (volintXInfo *) 0;
1602 afs_int32 code, err, error = 0;
1603 int voltype, foundserv = 0, foundentry = 0;
1607 int wantExtendedInfo; /*Do we want extended vol info? */
1608 int isSubEnum=0; /* Keep track whether sub enumerate called. */
1609 wantExtendedInfo = (as->parms[1].items ? 1 : 0); /* -extended */
1611 volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err); /* -id */
1614 PrintError("", err);
1616 fprintf(STDERR, "Unknown volume ID or name '%s'\n",
1617 as->parms[0].items->data);
1622 fprintf(STDOUT, "Fetching VLDB entry for %lu .. ",
1623 (unsigned long)volid);
1626 vcode = VLDB_GetEntryByID(volid, -1, &entry);
1629 "Could not fetch the entry for volume number %lu from VLDB \n",
1630 (unsigned long)volid);
1634 fprintf(STDOUT, "done\n");
1635 MapHostToNetwork(&entry);
1637 if (entry.volumeId[RWVOL] == volid)
1639 else if (entry.volumeId[BACKVOL] == volid)
1641 else /* (entry.volumeId[ROVOL] == volid) */
1644 do { /* do {...} while (voltype == ROVOL) */
1645 /* Get the entry for the volume. If its a RW vol, get the RW entry.
1646 * It its a BK vol, get the RW entry (even if VLDB may say the BK doen't exist).
1647 * If its a RO vol, get the next RO entry.
1649 GetServerAndPart(&entry, ((voltype == ROVOL) ? ROVOL : RWVOL),
1650 &aserver, &apart, &previdx);
1651 if (previdx == -1) { /* searched all entries */
1653 fprintf(STDERR, "Volume %s does not exist in VLDB\n\n",
1654 as->parms[0].items->data);
1661 /* Get information about the volume from the server */
1663 fprintf(STDOUT, "Getting volume listing from the server %s .. ",
1664 hostutil_GetNameByINet(aserver));
1667 if (wantExtendedInfo)
1668 code = UV_XListOneVolume(aserver, apart, volid, &xInfoP);
1670 code = UV_ListOneVolume(aserver, apart, volid, &pntr);
1672 fprintf(STDOUT, "done\n");
1676 if (code == ENODEV) {
1677 if ((voltype == BACKVOL) && !(entry.flags & BACK_EXISTS)) {
1678 /* The VLDB says there is no backup volume and its not on disk */
1679 fprintf(STDERR, "Volume %s does not exist\n",
1680 as->parms[0].items->data);
1684 "Volume does not exist on server %s as indicated by the VLDB\n",
1685 hostutil_GetNameByINet(aserver));
1688 PrintDiagnostics("examine", code);
1690 fprintf(STDOUT, "\n");
1693 if (wantExtendedInfo)
1694 XVolumeStats(xInfoP, &entry, aserver, apart, voltype);
1695 else if (as->parms[2].items) {
1696 DisplayFormat2(aserver, apart, pntr);
1697 EnumerateEntry(&entry);
1700 VolumeStats_int(pntr, &entry, aserver, apart, voltype);
1702 if ((voltype == BACKVOL) && !(entry.flags & BACK_EXISTS)) {
1703 /* The VLDB says there is no backup volume yet we found one on disk */
1704 fprintf(STDERR, "Volume %s does not exist in VLDB\n",
1705 as->parms[0].items->data);
1714 } while (voltype == ROVOL);
1717 fprintf(STDERR, "Dump only information from VLDB\n\n");
1718 fprintf(STDOUT, "%s \n", entry.name); /* PostVolumeStats doesn't print name */
1722 PostVolumeStats(&entry);
1727 /*------------------------------------------------------------------------
1731 * Routine used to change the status of a single volume.
1734 * as : Ptr to parsed command line arguments.
1737 * 0 for a successful operation,
1738 * Otherwise, one of the ubik or VolServer error values.
1741 * Nothing interesting.
1745 *------------------------------------------------------------------------
1748 SetFields(struct cmd_syndesc *as, void *arock)
1750 struct nvldbentry entry;
1753 afs_int32 code, err;
1759 volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err); /* -id */
1762 PrintError("", err);
1764 fprintf(STDERR, "Unknown volume ID or name '%s'\n",
1765 as->parms[0].items->data);
1769 code = VLDB_GetEntryByID(volid, RWVOL, &entry);
1772 "Could not fetch the entry for volume number %lu from VLDB \n",
1773 (unsigned long)volid);
1776 MapHostToNetwork(&entry);
1778 GetServerAndPart(&entry, RWVOL, &aserver, &apart, &previdx);
1779 if (previdx == -1) {
1780 fprintf(STDERR, "Volume %s does not exist in VLDB\n\n",
1781 as->parms[0].items->data);
1785 init_volintInfo(&info);
1789 if (as->parms[1].items) {
1792 code = util_GetHumanInt32(as->parms[1].items->data, &info.maxquota);
1794 fprintf(STDERR, "invalid quota value\n");
1798 if (as->parms[2].items) {
1803 if (as->parms[3].items) {
1804 /* -clearVolUpCounter */
1809 fprintf(STDERR,"Nothing to set.\n");
1812 code = UV_SetVolumeInfo(aserver, apart, volid, &info);
1815 "Could not update volume info fields for volume number %lu\n",
1816 (unsigned long)volid);
1820 /*------------------------------------------------------------------------
1824 * Brings a volume online.
1827 * as : Ptr to parsed command line arguments.
1830 * 0 for a successful operation,
1833 * Nothing interesting.
1837 *------------------------------------------------------------------------
1840 volOnline(struct cmd_syndesc *as, void *arock)
1843 afs_int32 partition;
1845 afs_int32 code, err = 0;
1847 server = GetServer(as->parms[0].items->data);
1849 fprintf(STDERR, "vos: server '%s' not found in host table\n",
1850 as->parms[0].items->data);
1854 partition = volutil_GetPartitionID(as->parms[1].items->data);
1855 if (partition < 0) {
1856 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
1857 as->parms[1].items->data);
1861 volid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err); /* -id */
1864 PrintError("", err);
1866 fprintf(STDERR, "Unknown volume ID or name '%s'\n",
1867 as->parms[0].items->data);
1871 code = UV_SetVolume(server, partition, volid, ITOffline, 0 /*online */ ,
1874 fprintf(STDERR, "Failed to set volume. Code = %d\n", code);
1881 /*------------------------------------------------------------------------
1882 * PRIVATE volOffline
1885 * Brings a volume offline.
1888 * as : Ptr to parsed command line arguments.
1891 * 0 for a successful operation,
1894 * Nothing interesting.
1898 *------------------------------------------------------------------------
1901 volOffline(struct cmd_syndesc *as, void *arock)
1904 afs_int32 partition;
1906 afs_int32 code, err = 0;
1907 afs_int32 transflag, sleeptime, transdone;
1909 server = GetServer(as->parms[0].items->data);
1911 fprintf(STDERR, "vos: server '%s' not found in host table\n",
1912 as->parms[0].items->data);
1916 partition = volutil_GetPartitionID(as->parms[1].items->data);
1917 if (partition < 0) {
1918 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
1919 as->parms[1].items->data);
1923 volid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err); /* -id */
1926 PrintError("", err);
1928 fprintf(STDERR, "Unknown volume ID or name '%s'\n",
1929 as->parms[0].items->data);
1933 transflag = (as->parms[4].items ? ITBusy : ITOffline);
1934 sleeptime = (as->parms[3].items ? atol(as->parms[3].items->data) : 0);
1935 transdone = ((sleeptime || as->parms[4].items) ? 0 /*online */ : VTOutOfService);
1936 if (as->parms[4].items && !as->parms[3].items) {
1937 fprintf(STDERR, "-sleep option must be used with -busy flag\n");
1942 UV_SetVolume(server, partition, volid, transflag, transdone,
1945 fprintf(STDERR, "Failed to set volume. Code = %d\n", code);
1953 CreateVolume(struct cmd_syndesc *as, void *arock)
1957 afs_uint32 volid = 0, rovolid = 0, bkvolid = 0;
1958 afs_uint32 *arovolid;
1960 struct nvldbentry entry;
1965 arovolid = &rovolid;
1968 tserver = GetServer(as->parms[0].items->data);
1970 fprintf(STDERR, "vos: host '%s' not found in host table\n",
1971 as->parms[0].items->data);
1974 pnum = volutil_GetPartitionID(as->parms[1].items->data);
1976 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
1977 as->parms[1].items->data);
1980 if (!IsPartValid(pnum, tserver, &code)) { /*check for validity of the partition */
1982 PrintError("", code);
1985 "vos : partition %s does not exist on the server\n",
1986 as->parms[1].items->data);
1989 if (!ISNAMEVALID(as->parms[2].items->data)) {
1991 "vos: the name of the root volume %s exceeds the size limit of %d\n",
1992 as->parms[2].items->data, VOLSER_OLDMAXVOLNAME - 10);
1995 if (!VolNameOK(as->parms[2].items->data)) {
1997 "Illegal volume name %s, should not end in .readonly or .backup\n",
1998 as->parms[2].items->data);
2001 if (IsNumeric(as->parms[2].items->data)) {
2002 fprintf(STDERR, "Illegal volume name %s, should not be a number\n",
2003 as->parms[2].items->data);
2006 vcode = VLDB_GetEntryByName(as->parms[2].items->data, &entry);
2008 fprintf(STDERR, "Volume %s already exists\n",
2009 as->parms[2].items->data);
2010 PrintDiagnostics("create", code);
2014 if (as->parms[3].items) {
2015 code = util_GetHumanInt32(as->parms[3].items->data, "a);
2017 fprintf(STDERR, "vos: bad integer specified for quota.\n");
2022 if (as->parms[4].items) {
2023 if (!IsNumeric(as->parms[4].items->data)) {
2024 fprintf(STDERR, "vos: Given volume ID %s should be numeric.\n",
2025 as->parms[4].items->data);
2029 code = util_GetUInt32(as->parms[4].items->data, &volid);
2031 fprintf(STDERR, "vos: bad integer specified for volume ID.\n");
2036 if (as->parms[5].items) {
2037 if (!IsNumeric(as->parms[5].items->data)) {
2038 fprintf(STDERR, "vos: Given RO volume ID %s should be numeric.\n",
2039 as->parms[5].items->data);
2043 code = util_GetUInt32(as->parms[5].items->data, &rovolid);
2045 fprintf(STDERR, "vos: bad integer specified for volume ID.\n");
2055 UV_CreateVolume3(tserver, pnum, as->parms[2].items->data, quota, 0,
2056 0, 0, 0, &volid, arovolid, &bkvolid);
2058 PrintDiagnostics("create", code);
2061 MapPartIdIntoName(pnum, part);
2062 fprintf(STDOUT, "Volume %lu created on partition %s of %s\n",
2063 (unsigned long)volid, part, as->parms[0].items->data);
2070 DeleteAll(struct nvldbentry *entry)
2073 afs_int32 error, code, curserver, curpart;
2076 MapHostToNetwork(entry);
2078 for (i = 0; i < entry->nServers; i++) {
2079 curserver = entry->serverNumber[i];
2080 curpart = entry->serverPartition[i];
2081 if (entry->serverFlags[i] & ITSROVOL) {
2082 volid = entry->volumeId[ROVOL];
2084 volid = entry->volumeId[RWVOL];
2086 code = UV_DeleteVolume(curserver, curpart, volid);
2095 DeleteVolume(struct cmd_syndesc *as, void *arock)
2097 afs_int32 err, code = 0;
2098 afs_uint32 server = 0;
2099 afs_int32 partition = -1;
2104 if (as->parms[0].items) {
2105 server = GetServer(as->parms[0].items->data);
2107 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2108 as->parms[0].items->data);
2113 if (as->parms[1].items) {
2114 partition = volutil_GetPartitionID(as->parms[1].items->data);
2115 if (partition < 0) {
2116 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2117 as->parms[1].items->data);
2121 /* Check for validity of the partition */
2122 if (!IsPartValid(partition, server, &code)) {
2124 PrintError("", code);
2127 "vos : partition %s does not exist on the server\n",
2128 as->parms[1].items->data);
2134 volid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err);
2136 fprintf(STDERR, "Can't find volume name '%s' in VLDB\n",
2137 as->parms[2].items->data);
2139 PrintError("", err);
2143 /* If the server or partition option are not complete, try to fill
2144 * them in from the VLDB entry.
2146 if ((partition == -1) || !server) {
2147 struct nvldbentry entry;
2149 code = VLDB_GetEntryByID(volid, -1, &entry);
2152 "Could not fetch the entry for volume %lu from VLDB\n",
2153 (unsigned long)volid);
2154 PrintError("", code);
2158 if (((volid == entry.volumeId[RWVOL]) && (entry.flags & RW_EXISTS))
2159 || ((volid == entry.volumeId[BACKVOL])
2160 && (entry.flags & BACK_EXISTS))) {
2161 idx = Lp_GetRwIndex(&entry);
2162 if ((idx == -1) || (server && (server != entry.serverNumber[idx]))
2163 || ((partition != -1)
2164 && (partition != entry.serverPartition[idx]))) {
2165 fprintf(STDERR, "VLDB: Volume '%s' no match\n",
2166 as->parms[2].items->data);
2169 } else if ((volid == entry.volumeId[ROVOL])
2170 && (entry.flags & RO_EXISTS)) {
2171 for (idx = -1, j = 0; j < entry.nServers; j++) {
2172 if (entry.serverFlags[j] != ITSROVOL)
2175 if (((server == 0) || (server == entry.serverNumber[j]))
2176 && ((partition == -1)
2177 || (partition == entry.serverPartition[j]))) {
2180 "VLDB: Volume '%s' matches more than one RO\n",
2181 as->parms[2].items->data);
2188 fprintf(STDERR, "VLDB: Volume '%s' no match\n",
2189 as->parms[2].items->data);
2193 fprintf(STDERR, "VLDB: Volume '%s' no match\n",
2194 as->parms[2].items->data);
2198 server = htonl(entry.serverNumber[idx]);
2199 partition = entry.serverPartition[idx];
2203 code = UV_DeleteVolume(server, partition, volid);
2205 PrintDiagnostics("remove", code);
2209 MapPartIdIntoName(partition, pname);
2210 fprintf(STDOUT, "Volume %lu on partition %s server %s deleted\n",
2211 (unsigned long)volid, pname, hostutil_GetNameByINet(server));
2215 #define TESTM 0 /* set for move space tests, clear for production */
2217 MoveVolume(struct cmd_syndesc *as, void *arock)
2221 afs_uint32 fromserver, toserver;
2222 afs_int32 frompart, topart;
2223 afs_int32 flags, code, err;
2224 char fromPartName[10], toPartName[10];
2226 struct diskPartition64 partition; /* for space check */
2229 volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2232 PrintError("", err);
2234 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2235 as->parms[0].items->data);
2238 fromserver = GetServer(as->parms[1].items->data);
2239 if (fromserver == 0) {
2240 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2241 as->parms[1].items->data);
2244 toserver = GetServer(as->parms[3].items->data);
2245 if (toserver == 0) {
2246 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2247 as->parms[3].items->data);
2250 frompart = volutil_GetPartitionID(as->parms[2].items->data);
2252 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2253 as->parms[2].items->data);
2256 if (!IsPartValid(frompart, fromserver, &code)) { /*check for validity of the partition */
2258 PrintError("", code);
2261 "vos : partition %s does not exist on the server\n",
2262 as->parms[2].items->data);
2265 topart = volutil_GetPartitionID(as->parms[4].items->data);
2267 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2268 as->parms[4].items->data);
2271 if (!IsPartValid(topart, toserver, &code)) { /*check for validity of the partition */
2273 PrintError("", code);
2276 "vos : partition %s does not exist on the server\n",
2277 as->parms[4].items->data);
2282 if (as->parms[5].items) flags |= RV_NOCLONE;
2285 * check source partition for space to clone volume
2288 MapPartIdIntoName(topart, toPartName);
2289 MapPartIdIntoName(frompart, fromPartName);
2292 * check target partition for space to move volume
2295 code = UV_PartitionInfo64(toserver, toPartName, &partition);
2297 fprintf(STDERR, "vos: cannot access partition %s\n", toPartName);
2301 fprintf(STDOUT, "target partition %s free space %" AFS_INT64_FMT "\n", toPartName,
2304 p = (volintInfo *) 0;
2305 code = UV_ListOneVolume(fromserver, frompart, volid, &p);
2307 fprintf(STDERR, "vos:cannot access volume %lu\n",
2308 (unsigned long)volid);
2312 fprintf(STDOUT, "volume %lu size %d\n", (unsigned long)volid,
2314 if (partition.free <= p->size) {
2316 "vos: no space on target partition %s to move volume %lu\n",
2317 toPartName, (unsigned long)volid);
2324 fprintf(STDOUT, "size test - don't do move\n");
2328 /* successful move still not guaranteed but shoot for it */
2331 UV_MoveVolume2(volid, fromserver, frompart, toserver, topart, flags);
2333 PrintDiagnostics("move", code);
2336 MapPartIdIntoName(topart, toPartName);
2337 MapPartIdIntoName(frompart, fromPartName);
2338 fprintf(STDOUT, "Volume %lu moved from %s %s to %s %s \n",
2339 (unsigned long)volid, as->parms[1].items->data, fromPartName,
2340 as->parms[3].items->data, toPartName);
2346 CopyVolume(struct cmd_syndesc *as, void *arock)
2349 afs_uint32 fromserver, toserver;
2350 afs_int32 frompart, topart, code, err, flags;
2351 char fromPartName[10], toPartName[10], *tovolume;
2352 struct nvldbentry entry;
2353 struct diskPartition64 partition; /* for space check */
2356 volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2359 PrintError("", err);
2361 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2362 as->parms[0].items->data);
2365 fromserver = GetServer(as->parms[1].items->data);
2366 if (fromserver == 0) {
2367 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2368 as->parms[1].items->data);
2372 toserver = GetServer(as->parms[4].items->data);
2373 if (toserver == 0) {
2374 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2375 as->parms[4].items->data);
2379 tovolume = as->parms[3].items->data;
2380 if (!ISNAMEVALID(tovolume)) {
2382 "vos: the name of the root volume %s exceeds the size limit of %d\n",
2383 tovolume, VOLSER_OLDMAXVOLNAME - 10);
2386 if (!VolNameOK(tovolume)) {
2388 "Illegal volume name %s, should not end in .readonly or .backup\n",
2392 if (IsNumeric(tovolume)) {
2393 fprintf(STDERR, "Illegal volume name %s, should not be a number\n",
2397 code = VLDB_GetEntryByName(tovolume, &entry);
2399 fprintf(STDERR, "Volume %s already exists\n", tovolume);
2400 PrintDiagnostics("copy", code);
2404 frompart = volutil_GetPartitionID(as->parms[2].items->data);
2406 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2407 as->parms[2].items->data);
2410 if (!IsPartValid(frompart, fromserver, &code)) { /*check for validity of the partition */
2412 PrintError("", code);
2415 "vos : partition %s does not exist on the server\n",
2416 as->parms[2].items->data);
2420 topart = volutil_GetPartitionID(as->parms[5].items->data);
2422 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2423 as->parms[5].items->data);
2426 if (!IsPartValid(topart, toserver, &code)) { /*check for validity of the partition */
2428 PrintError("", code);
2431 "vos : partition %s does not exist on the server\n",
2432 as->parms[5].items->data);
2437 if (as->parms[6].items) flags |= RV_OFFLINE;
2438 if (as->parms[7].items) flags |= RV_RDONLY;
2439 if (as->parms[8].items) flags |= RV_NOCLONE;
2441 MapPartIdIntoName(topart, toPartName);
2442 MapPartIdIntoName(frompart, fromPartName);
2445 * check target partition for space to move volume
2448 code = UV_PartitionInfo64(toserver, toPartName, &partition);
2450 fprintf(STDERR, "vos: cannot access partition %s\n", toPartName);
2454 fprintf(STDOUT, "target partition %s free space %" AFS_INT64_FMT "\n", toPartName,
2457 p = (volintInfo *) 0;
2458 code = UV_ListOneVolume(fromserver, frompart, volid, &p);
2460 fprintf(STDERR, "vos:cannot access volume %lu\n",
2461 (unsigned long)volid);
2465 if (partition.free <= p->size) {
2467 "vos: no space on target partition %s to copy volume %lu\n",
2468 toPartName, (unsigned long)volid);
2474 /* successful copy still not guaranteed but shoot for it */
2477 UV_CopyVolume2(volid, fromserver, frompart, tovolume, toserver,
2480 PrintDiagnostics("copy", code);
2483 MapPartIdIntoName(topart, toPartName);
2484 MapPartIdIntoName(frompart, fromPartName);
2485 fprintf(STDOUT, "Volume %lu copied from %s %s to %s on %s %s \n",
2486 (unsigned long)volid, as->parms[1].items->data, fromPartName,
2487 tovolume, as->parms[4].items->data, toPartName);
2494 ShadowVolume(struct cmd_syndesc *as, void *arock)
2496 afs_uint32 volid, tovolid;
2497 afs_uint32 fromserver, toserver;
2498 afs_int32 frompart, topart;
2499 afs_int32 code, err, flags;
2500 char fromPartName[10], toPartName[10], toVolName[32], *tovolume;
2501 struct diskPartition64 partition; /* for space check */
2504 p = (volintInfo *) 0;
2505 q = (volintInfo *) 0;
2507 volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2510 PrintError("", err);
2512 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2513 as->parms[0].items->data);
2516 fromserver = GetServer(as->parms[1].items->data);
2517 if (fromserver == 0) {
2518 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2519 as->parms[1].items->data);
2523 toserver = GetServer(as->parms[3].items->data);
2524 if (toserver == 0) {
2525 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2526 as->parms[3].items->data);
2530 frompart = volutil_GetPartitionID(as->parms[2].items->data);
2532 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2533 as->parms[2].items->data);
2536 if (!IsPartValid(frompart, fromserver, &code)) { /*check for validity of the partition */
2538 PrintError("", code);
2541 "vos : partition %s does not exist on the server\n",
2542 as->parms[2].items->data);
2546 topart = volutil_GetPartitionID(as->parms[4].items->data);
2548 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2549 as->parms[4].items->data);
2552 if (!IsPartValid(topart, toserver, &code)) { /*check for validity of the partition */
2554 PrintError("", code);
2557 "vos : partition %s does not exist on the server\n",
2558 as->parms[4].items->data);
2562 if (as->parms[5].items) {
2563 tovolume = as->parms[5].items->data;
2564 if (!ISNAMEVALID(tovolume)) {
2566 "vos: the name of the root volume %s exceeds the size limit of %d\n",
2567 tovolume, VOLSER_OLDMAXVOLNAME - 10);
2570 if (!VolNameOK(tovolume)) {
2572 "Illegal volume name %s, should not end in .readonly or .backup\n",
2576 if (IsNumeric(tovolume)) {
2578 "Illegal volume name %s, should not be a number\n",
2583 /* use actual name of source volume */
2584 code = UV_ListOneVolume(fromserver, frompart, volid, &p);
2586 fprintf(STDERR, "vos:cannot access volume %lu\n",
2587 (unsigned long)volid);
2590 strcpy(toVolName, p->name);
2591 tovolume = toVolName;
2592 /* save p for size checks later */
2595 if (as->parms[6].items) {
2596 tovolid = vsu_GetVolumeID(as->parms[6].items->data, cstruct, &err);
2599 PrintError("", err);
2601 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2602 as->parms[6].items->data);
2608 tovolid = vsu_GetVolumeID(tovolume, cstruct, &err);
2611 PrintError("", err);
2613 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2622 if (as->parms[7].items) flags |= RV_OFFLINE;
2623 if (as->parms[8].items) flags |= RV_RDONLY;
2624 if (as->parms[9].items) flags |= RV_NOCLONE;
2625 if (as->parms[10].items) flags |= RV_CPINCR;
2627 MapPartIdIntoName(topart, toPartName);
2628 MapPartIdIntoName(frompart, fromPartName);
2631 * check target partition for space to move volume
2634 code = UV_PartitionInfo64(toserver, toPartName, &partition);
2636 fprintf(STDERR, "vos: cannot access partition %s\n", toPartName);
2640 fprintf(STDOUT, "target partition %s free space %" AFS_INT64_FMT "\n", toPartName,
2643 /* Don't do this again if we did it above */
2645 code = UV_ListOneVolume(fromserver, frompart, volid, &p);
2647 fprintf(STDERR, "vos:cannot access volume %lu\n",
2648 (unsigned long)volid);
2653 /* OK if this fails */
2654 code = UV_ListOneVolume(toserver, topart, tovolid, &q);
2656 /* Treat existing volume size as "free" */
2658 p->size = (q->size < p->size) ? p->size - q->size : 0;
2660 if (partition.free <= p->size) {
2662 "vos: no space on target partition %s to copy volume %lu\n",
2663 toPartName, (unsigned long)volid);
2671 /* successful copy still not guaranteed but shoot for it */
2674 UV_CopyVolume2(volid, fromserver, frompart, tovolume, toserver,
2675 topart, tovolid, flags);
2677 PrintDiagnostics("shadow", code);
2680 MapPartIdIntoName(topart, toPartName);
2681 MapPartIdIntoName(frompart, fromPartName);
2682 fprintf(STDOUT, "Volume %lu shadowed from %s %s to %s %s \n",
2683 (unsigned long)volid, as->parms[1].items->data, fromPartName,
2684 as->parms[3].items->data, toPartName);
2691 CloneVolume(struct cmd_syndesc *as, void *arock)
2693 afs_uint32 volid, cloneid;
2695 afs_int32 part, voltype;
2696 char partName[10], *volname;
2697 afs_int32 code, err, flags;
2698 struct nvldbentry entry;
2700 volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2703 PrintError("", err);
2705 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2706 as->parms[0].items->data);
2710 if (as->parms[1].items || as->parms[2].items) {
2711 if (!as->parms[1].items || !as->parms[2].items) {
2713 "Must specify both -server and -partition options\n");
2716 server = GetServer(as->parms[1].items->data);
2718 fprintf(STDERR, "vos: server '%s' not found in host table\n",
2719 as->parms[1].items->data);
2722 part = volutil_GetPartitionID(as->parms[2].items->data);
2724 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
2725 as->parms[2].items->data);
2728 if (!IsPartValid(part, server, &code)) { /*check for validity of the partition */
2730 PrintError("", code);
2733 "vos : partition %s does not exist on the server\n",
2734 as->parms[2].items->data);
2738 code = GetVolumeInfo(volid, &server, &part, &voltype, &entry);
2744 if (as->parms[3].items) {
2745 volname = as->parms[3].items->data;
2746 if (strlen(volname) > VOLSER_OLDMAXVOLNAME - 1) {
2748 "vos: the name of the root volume %s exceeds the size limit of %d\n",
2749 volname, VOLSER_OLDMAXVOLNAME - 1);
2754 * In order that you be able to make clones of RO or BK, this
2755 * check must be omitted.
2757 if (!VolNameOK(volname)) {
2759 "Illegal volume name %s, should not end in .readonly or .backup\n",
2764 if (IsNumeric(volname)) {
2766 "Illegal volume name %s, should not be a number\n",
2773 if (as->parms[4].items) {
2774 cloneid = vsu_GetVolumeID(as->parms[4].items->data, cstruct, &err);
2777 PrintError("", err);
2779 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2780 as->parms[4].items->data);
2786 if (as->parms[5].items) flags |= RV_OFFLINE;
2787 if (as->parms[6].items && as->parms[7].items) {
2788 fprintf(STDERR, "vos: cannot specify that a volume be -readwrite and -readonly\n");
2791 if (as->parms[6].items) flags |= RV_RDONLY;
2792 if (as->parms[7].items) flags |= RV_RWONLY;
2796 UV_CloneVolume(server, part, volid, cloneid, volname, flags);
2799 PrintDiagnostics("clone", code);
2802 MapPartIdIntoName(part, partName);
2803 fprintf(STDOUT, "Created clone for volume %s\n",
2804 as->parms[0].items->data);
2811 BackupVolume(struct cmd_syndesc *as, void *arock)
2815 afs_int32 apart, vtype, code, err;
2816 struct nvldbentry entry;
2819 afs_uint32 buserver;
2820 afs_int32 bupart, butype;
2821 struct nvldbentry buentry;
2823 avolid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2826 PrintError("", err);
2828 fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
2829 as->parms[0].items->data);
2832 code = GetVolumeInfo(avolid, &aserver, &apart, &vtype, &entry);
2836 /* verify this is a readwrite volume */
2838 if (vtype != RWVOL) {
2839 fprintf(STDERR, "%s not RW volume\n", as->parms[0].items->data);
2843 /* is there a backup volume already? */
2845 if (entry.flags & BACK_EXISTS) {
2846 /* yep, where is it? */
2848 buvolid = entry.volumeId[BACKVOL];
2849 code = GetVolumeInfo(buvolid, &buserver, &bupart, &butype, &buentry);
2854 code = VLDB_IsSameAddrs(buserver, aserver, &err);
2857 "Failed to get info about server's %d address(es) from vlserver; aborting call!\n",
2863 "FATAL ERROR: backup volume %lu exists on server %lu\n",
2864 (unsigned long)buvolid, (unsigned long)buserver);
2869 /* nope, carry on */
2871 code = UV_BackupVolume(aserver, apart, avolid);
2874 PrintDiagnostics("backup", code);
2877 fprintf(STDOUT, "Created backup volume for %s \n",
2878 as->parms[0].items->data);
2883 ReleaseVolume(struct cmd_syndesc *as, void *arock)
2886 struct nvldbentry entry;
2889 afs_int32 apart, vtype, code, err;
2892 if (as->parms[1].items) /* -force */
2893 flags |= (REL_COMPLETE | REL_FULLDUMPS);
2894 if (as->parms[2].items) /* -stayonline */
2895 flags |= REL_STAYUP;
2896 if (as->parms[3].items) /* -force-reclone */
2897 flags |= REL_COMPLETE;
2899 avolid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2902 PrintError("", err);
2904 fprintf(STDERR, "vos: can't find volume '%s'\n",
2905 as->parms[0].items->data);
2908 code = GetVolumeInfo(avolid, &aserver, &apart, &vtype, &entry);
2912 if (vtype != RWVOL) {
2913 fprintf(STDERR, "%s not a RW volume\n", as->parms[0].items->data);
2917 if (!ISNAMEVALID(entry.name)) {
2919 "Volume name %s is too long, rename before releasing\n",
2924 code = UV_ReleaseVolume(avolid, aserver, apart, flags);
2927 PrintDiagnostics("release", code);
2930 fprintf(STDOUT, "Released volume %s successfully\n",
2931 as->parms[0].items->data);
2936 DumpVolumeCmd(struct cmd_syndesc *as, void *arock)
2940 afs_int32 apart, voltype, fromdate = 0, code, err, i, flags;
2941 char filename[MAXPATHLEN];
2942 struct nvldbentry entry;
2944 rx_SetRxDeadTime(60 * 10);
2945 for (i = 0; i < MAXSERVERS; i++) {
2946 struct rx_connection *rxConn = ubik_GetRPCConn(cstruct, i);
2949 rx_SetConnDeadTime(rxConn, rx_connDeadTime);
2950 if (rx_ServiceOf(rxConn))
2951 rx_ServiceOf(rxConn)->connDeadTime = rx_connDeadTime;
2954 avolid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
2957 PrintError("", err);
2959 fprintf(STDERR, "vos: can't find volume '%s'\n",
2960 as->parms[0].items->data);
2964 if (as->parms[3].items || as->parms[4].items) {
2965 if (!as->parms[3].items || !as->parms[4].items) {
2967 "Must specify both -server and -partition options\n");
2970 aserver = GetServer(as->parms[3].items->data);
2972 fprintf(STDERR, "Invalid server name\n");
2975 apart = volutil_GetPartitionID(as->parms[4].items->data);
2977 fprintf(STDERR, "Invalid partition name\n");
2981 code = GetVolumeInfo(avolid, &aserver, &apart, &voltype, &entry);
2986 if (as->parms[1].items && strcmp(as->parms[1].items->data, "0")) {
2987 code = ktime_DateToInt32(as->parms[1].items->data, &fromdate);
2989 fprintf(STDERR, "vos: failed to parse date '%s' (error=%d))\n",
2990 as->parms[1].items->data, code);
2994 if (as->parms[2].items) {
2995 strcpy(filename, as->parms[2].items->data);
2997 strcpy(filename, "");
3000 flags = as->parms[6].items ? VOLDUMPV2_OMITDIRS : 0;
3002 if (as->parms[5].items) {
3004 UV_DumpClonedVolume(avolid, aserver, apart, fromdate,
3005 DumpFunction, filename, flags);
3008 UV_DumpVolume(avolid, aserver, apart, fromdate, DumpFunction,
3011 if ((code == RXGEN_OPCODE) && (as->parms[6].items)) {
3012 flags &= ~VOLDUMPV2_OMITDIRS;
3016 PrintDiagnostics("dump", code);
3019 if (strcmp(filename, ""))
3020 fprintf(STDERR, "Dumped volume %s in file %s\n",
3021 as->parms[0].items->data, filename);
3023 fprintf(STDERR, "Dumped volume %s in stdout \n",
3024 as->parms[0].items->data);
3038 RestoreVolumeCmd(struct cmd_syndesc *as, void *arock)
3040 afs_uint32 avolid, aparentid;
3042 afs_int32 apart, code, vcode, err;
3043 afs_int32 aoverwrite = ASK;
3044 afs_int32 acreation = 0, alastupdate = 0;
3045 int restoreflags = 0;
3046 int readonly = 0, offline = 0, voltype = RWVOL;
3047 char afilename[MAXPATHLEN], avolname[VOLSER_MAXVOLNAME + 1], apartName[10];
3048 char volname[VOLSER_MAXVOLNAME + 1];
3049 struct nvldbentry entry;
3052 if (as->parms[4].items) {
3053 avolid = vsu_GetVolumeID(as->parms[4].items->data, cstruct, &err);
3056 PrintError("", err);
3058 fprintf(STDERR, "vos: can't find volume '%s'\n",
3059 as->parms[4].items->data);
3065 if (as->parms[5].items) {
3066 if ((strcmp(as->parms[5].items->data, "a") == 0)
3067 || (strcmp(as->parms[5].items->data, "abort") == 0)) {
3069 } else if ((strcmp(as->parms[5].items->data, "f") == 0)
3070 || (strcmp(as->parms[5].items->data, "full") == 0)) {
3072 } else if ((strcmp(as->parms[5].items->data, "i") == 0)
3073 || (strcmp(as->parms[5].items->data, "inc") == 0)
3074 || (strcmp(as->parms[5].items->data, "increment") == 0)
3075 || (strcmp(as->parms[5].items->data, "incremental") == 0)) {
3078 fprintf(STDERR, "vos: %s is not a valid argument to -overwrite\n",
3079 as->parms[5].items->data);
3083 if (as->parms[6].items)
3085 if (as->parms[7].items) {
3090 if (as->parms[8].items) {
3091 if ((strcmp(as->parms[8].items->data, "d") == 0)
3092 || (strcmp(as->parms[8].items->data, "dump") == 0)) {
3093 acreation = TS_DUMP;
3094 } else if ((strcmp(as->parms[8].items->data, "k") == 0)
3095 || (strcmp(as->parms[8].items->data, "keep") == 0)) {
3096 acreation = TS_KEEP;
3097 } else if ((strcmp(as->parms[8].items->data, "n") == 0)
3098 || (strcmp(as->parms[8].items->data, "new") == 0)) {
3101 fprintf(STDERR, "vos: %s is not a valid argument to -creation\n",
3102 as->parms[8].items->data);
3107 if (as->parms[9].items) {
3108 if ((strcmp(as->parms[9].items->data, "d") == 0)
3109 || (strcmp(as->parms[9].items->data, "dump") == 0)) {
3110 alastupdate = TS_DUMP;
3111 } else if ((strcmp(as->parms[9].items->data, "k") == 0)
3112 || (strcmp(as->parms[9].items->data, "keep") == 0)) {
3113 alastupdate = TS_KEEP;
3114 } else if ((strcmp(as->parms[9].items->data, "n") == 0)
3115 || (strcmp(as->parms[9].items->data, "new") == 0)) {
3116 alastupdate = TS_NEW;
3118 fprintf(STDERR, "vos: %s is not a valid argument to -lastupdate\n",
3119 as->parms[9].items->data);
3124 aserver = GetServer(as->parms[0].items->data);
3126 fprintf(STDERR, "vos: server '%s' not found in host table\n",
3127 as->parms[0].items->data);
3130 apart = volutil_GetPartitionID(as->parms[1].items->data);
3132 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
3133 as->parms[1].items->data);
3136 if (!IsPartValid(apart, aserver, &code)) { /*check for validity of the partition */
3138 PrintError("", code);
3141 "vos : partition %s does not exist on the server\n",
3142 as->parms[1].items->data);
3145 strcpy(avolname, as->parms[2].items->data);
3146 if (!ISNAMEVALID(avolname)) {
3148 "vos: the name of the volume %s exceeds the size limit\n",
3152 if (!VolNameOK(avolname)) {
3154 "Illegal volume name %s, should not end in .readonly or .backup\n",
3158 if (as->parms[3].items) {
3159 strcpy(afilename, as->parms[3].items->data);
3160 if (!FileExists(afilename)) {
3161 fprintf(STDERR, "Can't access file %s\n", afilename);
3165 strcpy(afilename, "");
3168 /* Check if volume exists or not */
3170 vsu_ExtractName(volname, avolname);
3171 vcode = VLDB_GetEntryByName(volname, &entry);
3172 if (vcode) { /* no volume - do a full restore */
3173 restoreflags = RV_FULLRST;
3174 if ((aoverwrite == INC) || (aoverwrite == ABORT))
3176 "Volume does not exist; Will perform a full restore\n");
3179 else if ((!readonly && Lp_GetRwIndex(&entry) == -1) /* RW volume does not exist - do a full */
3180 ||(readonly && !Lp_ROMatch(0, 0, &entry))) { /* RO volume does not exist - do a full */
3181 restoreflags = RV_FULLRST;
3182 if ((aoverwrite == INC) || (aoverwrite == ABORT))
3184 "%s Volume does not exist; Will perform a full restore\n",
3185 readonly ? "RO" : "RW");
3188 avolid = entry.volumeId[voltype];
3189 } else if (entry.volumeId[voltype] != 0
3190 && entry.volumeId[voltype] != avolid) {
3191 avolid = entry.volumeId[voltype];
3193 aparentid = entry.volumeId[RWVOL];
3196 else { /* volume exists - do we do a full incremental or abort */
3198 afs_int32 Opart, Otype, vol_elsewhere = 0;
3199 struct nvldbentry Oentry;
3203 avolid = entry.volumeId[voltype];
3204 } else if (entry.volumeId[voltype] != 0
3205 && entry.volumeId[voltype] != avolid) {
3206 avolid = entry.volumeId[voltype];
3208 aparentid = entry.volumeId[RWVOL];
3210 /* A file name was specified - check if volume is on another partition */
3211 vcode = GetVolumeInfo(avolid, &Oserver, &Opart, &Otype, &Oentry);
3215 vcode = VLDB_IsSameAddrs(Oserver, aserver, &err);
3218 "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
3222 if (!vcode || (Opart != apart))
3225 if (aoverwrite == ASK) {
3226 if (strcmp(afilename, "") == 0) { /* The file is from standard in */
3228 "Volume exists and no -overwrite option specified; Aborting restore command\n");
3232 /* Ask what to do */
3233 if (vol_elsewhere) {
3235 "The volume %s %u already exists on a different server/part\n",
3236 volname, entry.volumeId[voltype]);
3238 "Do you want to do a full restore or abort? [fa](a): ");
3241 "The volume %s %u already exists in the VLDB\n",
3242 volname, entry.volumeId[voltype]);
3244 "Do you want to do a full/incremental restore or abort? [fia](a): ");
3247 while (!(dc == EOF || dc == '\n'))
3248 dc = getchar(); /* goto end of line */
3249 if ((c == 'f') || (c == 'F'))
3251 else if ((c == 'i') || (c == 'I'))
3257 if (aoverwrite == ABORT) {
3258 fprintf(STDERR, "Volume exists; Aborting restore command\n");
3260 } else if (aoverwrite == FULL) {
3261 restoreflags = RV_FULLRST;
3263 "Volume exists; Will delete and perform full restore\n");
3264 } else if (aoverwrite == INC) {
3266 if (vol_elsewhere) {
3268 "%s volume %lu already exists on a different server/part; not allowed\n",
3269 readonly ? "RO" : "RW", (unsigned long)avolid);
3275 restoreflags |= RV_OFFLINE;
3277 restoreflags |= RV_RDONLY;
3279 switch (acreation) {
3281 restoreflags |= RV_CRDUMP;
3284 restoreflags |= RV_CRKEEP;
3287 restoreflags |= RV_CRNEW;
3290 if (aoverwrite == FULL)
3291 restoreflags |= RV_CRNEW;
3293 restoreflags |= RV_CRKEEP;
3296 switch (alastupdate) {
3298 restoreflags |= RV_LUDUMP;
3301 restoreflags |= RV_LUKEEP;
3304 restoreflags |= RV_LUNEW;
3307 restoreflags |= RV_LUDUMP;
3309 if (as->parms[10].items) {
3310 restoreflags |= RV_NODEL;
3315 UV_RestoreVolume2(aserver, apart, avolid, aparentid,
3316 avolname, restoreflags, WriteData, afilename);
3318 PrintDiagnostics("restore", code);
3321 MapPartIdIntoName(apart, apartName);
3324 * patch typo here - originally "parms[1]", should be "parms[0]"
3327 fprintf(STDOUT, "Restored volume %s on %s %s\n", avolname,
3328 as->parms[0].items->data, apartName);
3333 LockReleaseCmd(struct cmd_syndesc *as, void *arock)
3336 afs_int32 code, err;
3338 avolid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
3341 PrintError("", err);
3343 fprintf(STDERR, "vos: can't find volume '%s'\n",
3344 as->parms[0].items->data);
3348 code = UV_LockRelease(avolid);
3350 PrintDiagnostics("unlock", code);
3353 fprintf(STDOUT, "Released lock on vldb entry for volume %s\n",
3354 as->parms[0].items->data);
3359 AddSite(struct cmd_syndesc *as, void *arock)
3363 afs_int32 apart, code, err, arovolid, valid = 0;
3364 char apartName[10], avolname[VOLSER_MAXVOLNAME + 1];
3366 vsu_ExtractName(avolname, as->parms[2].items->data);;
3367 avolid = vsu_GetVolumeID(avolname, cstruct, &err);
3370 PrintError("", err);
3372 fprintf(STDERR, "vos: can't find volume '%s'\n",
3373 as->parms[2].items->data);
3377 if (as->parms[3].items) {
3378 vsu_ExtractName(avolname, as->parms[3].items->data);
3379 arovolid = vsu_GetVolumeID(avolname, cstruct, &err);
3381 fprintf(STDERR, "vos: invalid ro volume id '%s'\n",
3382 as->parms[3].items->data);
3386 aserver = GetServer(as->parms[0].items->data);
3388 fprintf(STDERR, "vos: server '%s' not found in host table\n",
3389 as->parms[0].items->data);
3392 apart = volutil_GetPartitionID(as->parms[1].items->data);
3394 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
3395 as->parms[1].items->data);
3398 if (!IsPartValid(apart, aserver, &code)) { /*check for validity of the partition */
3400 PrintError("", code);
3403 "vos : partition %s does not exist on the server\n",
3404 as->parms[1].items->data);
3407 if (as->parms[4].items) {
3410 code = UV_AddSite2(aserver, apart, avolid, arovolid, valid);
3412 PrintDiagnostics("addsite", code);
3415 MapPartIdIntoName(apart, apartName);
3416 fprintf(STDOUT, "Added replication site %s %s for volume %s\n",
3417 as->parms[0].items->data, apartName, as->parms[2].items->data);
3422 RemoveSite(struct cmd_syndesc *as, void *arock)
3427 afs_int32 apart, code, err;
3428 char apartName[10], avolname[VOLSER_MAXVOLNAME + 1];
3430 vsu_ExtractName(avolname, as->parms[2].items->data);
3431 avolid = vsu_GetVolumeID(avolname, cstruct, &err);
3434 PrintError("", err);
3436 fprintf(STDERR, "vos: can't find volume '%s'\n",
3437 as->parms[2].items->data);
3440 aserver = GetServer(as->parms[0].items->data);
3442 fprintf(STDERR, "vos: server '%s' not found in host table\n",
3443 as->parms[0].items->data);
3446 apart = volutil_GetPartitionID(as->parms[1].items->data);
3448 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
3449 as->parms[1].items->data);
3453 *skip the partition validity check, since it is possible that the partition
3454 *has since been decomissioned.
3457 if (!IsPartValid(apart,aserver,&code)){
3458 if(code) PrintError("",code);
3459 else fprintf(STDERR,"vos : partition %s does not exist on the server\n",as->parms[1].items->data);
3463 code = UV_RemoveSite(aserver, apart, avolid);
3465 PrintDiagnostics("remsite", code);
3468 MapPartIdIntoName(apart, apartName);
3469 fprintf(STDOUT, "Removed replication site %s %s for volume %s\n",
3470 as->parms[0].items->data, apartName, as->parms[2].items->data);
3475 ChangeLocation(struct cmd_syndesc *as, void *arock)
3479 afs_int32 apart, code, err;
3482 avolid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err);
3485 PrintError("", err);
3487 fprintf(STDERR, "vos: can't find volume '%s'\n",
3488 as->parms[2].items->data);
3491 aserver = GetServer(as->parms[0].items->data);
3493 fprintf(STDERR, "vos: server '%s' not found in host table\n",
3494 as->parms[0].items->data);
3497 apart = volutil_GetPartitionID(as->parms[1].items->data);
3499 fprintf(STDERR, "vos: could not interpret partition name '%s'\n",
3500 as->parms[1].items->data);
3503 if (!IsPartValid(apart, aserver, &code)) { /*check for validity of the partition */
3505 PrintError("", code);
3508 "vos : partition %s does not exist on the server\n",
3509 as->parms[1].items->data);
3512 code = UV_ChangeLocation(aserver, apart, avolid);
3514 PrintDiagnostics("changeloc", code);
3517 MapPartIdIntoName(apart, apartName);
3518 fprintf(STDOUT, "Changed location to %s %s for volume %s\n",
3519 as->parms[0].items->data, apartName, as->parms[2].items->data);
3524 ListPartitions(struct cmd_syndesc *as, void *arock)
3528 struct partList dummyPartList;
3533 aserver = GetServer(as->parms[0].items->data);
3535 fprintf(STDERR, "vos: server '%s' not found in host table\n",
3536 as->parms[0].items->data);
3541 code = UV_ListPartitions(aserver, &dummyPartList, &cnt);
3543 PrintDiagnostics("listpart", code);
3547 fprintf(STDOUT, "The partitions on the server are:\n");
3548 for (i = 0; i < cnt; i++) {
3549 if (dummyPartList.partFlags[i] & PARTVALID) {
3550 memset(pname, 0, sizeof(pname));
3551 MapPartIdIntoName(dummyPartList.partId[i], pname);
3552 fprintf(STDOUT, " %10s ", pname);
3554 if ((i % 5) == 0 && (i != 0))
3555 fprintf(STDOUT, "\n");
3558 fprintf(STDOUT, "\n");
3559 fprintf(STDOUT, "Total: %d\n", total);
3565 CompareVolName(const void *p1, const void *p2)
3567 volintInfo *arg1, *arg2;
3569 arg1 = (volintInfo *) p1;
3570 arg2 = (volintInfo *) p2;
3571 return (strcmp(arg1->name, arg2->name));
3575 /*------------------------------------------------------------------------
3576 * PRIVATE XCompareVolName
3579 * Comparison routine for volume names coming from an extended
3583 * a_obj1P : Char ptr to first extended vol info object
3584 * a_obj1P : Char ptr to second extended vol info object
3587 * The value of strcmp() on the volume names within the passed
3588 * objects (i,e., -1, 0, or 1).
3591 * Passed to qsort() as the designated comparison routine.
3595 *------------------------------------------------------------------------*/
3598 XCompareVolName(const void *a_obj1P, const void *a_obj2P)
3599 { /*XCompareVolName */
3602 (((struct volintXInfo *)(a_obj1P))->name,
3603 ((struct volintXInfo *)(a_obj2P))->name));
3605 } /*XCompareVolName */
3608 CompareVolID(const void *p1, const void *p2)
3610 volintInfo *arg1, *arg2;
3612 arg1 = (volintInfo *) p1;
3613 arg2 = (volintInfo *) p2;
3614 if (arg1->volid == arg2->volid)
3616 if (arg1->volid > arg2->volid)
3623 /*------------------------------------------------------------------------
3624 * PRIVATE XCompareVolID
3627 * Comparison routine for volume IDs coming from an extended
3631 * a_obj1P : Char ptr to first extended vol info object
3632 * a_obj1P : Char ptr to second extended vol info object
3635 * The value of strcmp() on the volume names within the passed
3636 * objects (i,e., -1, 0, or 1).
3639 * Passed to qsort() as the designated comparison routine.
3643 *------------------------------------------------------------------------*/
3646 XCompareVolID(const void *a_obj1P, const void *a_obj2P)
3647 { /*XCompareVolID */
3649 afs_int32 id1, id2; /*Volume IDs we're comparing */
3651 id1 = ((struct volintXInfo *)(a_obj1P))->volid;
3652 id2 = ((struct volintXInfo *)(a_obj2P))->volid;
3660 } /*XCompareVolID */