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
11 * Implementation of the volume operations used by the AFS user
16 * --------------------- Required definitions ---------------------
18 #include <afsconfig.h>
19 #include <afs/param.h>
23 #include <afs/com_err.h>
24 #include <afs/vlserver.h>
25 #include <afs/vldbint.h>
27 #include <afs/cellconfig.h>
28 #include <rx/rx_globals.h>
29 #include <afs/afsint.h>
30 #include <afs/volser.h>
31 #include <afs/volser_prototypes.h>
32 #include <afs/volint.h>
34 #include <afs/afsutil.h>
39 #include "uss_vol.h" /*Interface to this module */
40 #include "uss_common.h" /*Common definitions */
41 #include "uss_procs.h" /*Defs from procs module */
42 #include "uss_fs.h" /*CacheManager ops */
48 * ---------------------- Private definitions ---------------------
51 #undef USS_VOL_DB_SHOW_OVERRIDES
55 * --------------------- Exported definitions ---------------------
58 * The Volume Server interface imports the Ubik connection
59 * structure to use, expecting it to be named "cstruct". This
60 * is why we have two names here. Thus, the UV_CreateVolume()
61 * will work and we can avoid nasty little core dumps.
63 struct ubik_client
*uconn_vldbP
; /*Ubik connection struct */
64 struct ubik_client
*cstruct
; /*Required name for above */
67 * ------------------------ Private globals -----------------------
69 static int initDone
= 0; /*Module initialized? */
70 static int NoAuthFlag
= 0; /*Use -noauth? */
71 static struct rx_connection
72 *serverconns
[VLDB_MAXSERVERS
]; /*Connection(s) to VLDB
76 /*-----------------------------------------------------------------------
77 * static InitThisModule
80 * Set up this module, namely set up all the client state for
81 * dealing with the Volume Location Server(s), including
82 * network connections.
85 * a_noAuthFlag : Do we need authentication?
86 * a_confDir : Configuration directory to use.
87 * a_cellName : Cell we want to talk to.
90 * 0 if everything went fine, or
91 * lower-level error code otherwise.
94 * This routine will only be called once.
98 *------------------------------------------------------------------------*/
101 InitThisModule(int a_noAuthFlag
, char *a_confDir
, char *a_cellName
)
102 { /*InitThisModule */
104 static char rn
[] = "uss_vol:InitThisModule";
106 afs_int32 code
; /*Return code */
107 struct afsconf_dir
*tdir
; /*Ptr to conf dir info */
108 struct afsconf_cell info
; /*Info about chosen cell */
109 afs_int32 scIndex
; /*Chosen security index */
111 struct rx_securityClass
*sc
; /*Generated security object */
112 afs_int32 i
; /*Loop index */
115 * Only once, guys, will 'ya?
119 printf("[%s] Called multiple times!\n", rn
);
120 #endif /* USS_VOL_DB */
125 * Set up our Rx environment.
128 printf("[%s] Initializing Rx environment\n", rn
);
129 #endif /* USS_VOL_DB */
132 fprintf(stderr
, "%s: Couldn't initialize Rx.\n", uss_whoami
);
135 rx_SetRxDeadTime(50);
138 * Find out all about our configuration.
141 printf("[%s] Handling configuration info\n", rn
);
142 #endif /* USS_VOL_DB */
143 tdir
= afsconf_Open(a_confDir
);
145 fprintf(stderr
, "%s: Couldn't open configuration directory (%s).\n",
146 uss_whoami
, a_confDir
);
149 code
= afsconf_GetCellInfo(tdir
, a_cellName
, AFSCONF_VLDBSERVICE
, &info
);
151 printf("%s: Can't find VLDB server(s) for cell %s\n", uss_whoami
,
156 printf("[%s] Getting tickets if needed\n", rn
);
157 #endif /* USS_VOL_DB */
159 secFlags
= AFSCONF_SECOPTS_FALLBACK_NULL
;
161 secFlags
|= AFSCONF_SECOPTS_NOAUTH
;
163 code
= afsconf_PickClientSecObj(tdir
, secFlags
, &info
, a_cellName
,
164 &sc
, &scIndex
, NULL
);
166 printf("%s: Can't create client security object\n", uss_whoami
);
169 if (scIndex
== RX_SECIDX_NULL
&& !a_noAuthFlag
) {
171 "%s: Couldn't get AFS tokens, running unauthenticated.\n",
176 * Tell UV module about default authentication.
179 printf("[%s] Setting UV security: obj 0x%x, index %d\n", rn
, sc
, scIndex
);
180 #endif /* USS_VOL_DB */
181 UV_SetSecurity(sc
, scIndex
);
182 if (info
.numServers
> VLDB_MAXSERVERS
) {
183 fprintf(stderr
, "%s: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n",
184 uss_whoami
, info
.numServers
, VLDB_MAXSERVERS
);
189 * Connect to each VLDB server for the chosen cell.
191 for (i
= 0; i
< info
.numServers
; i
++) {
194 ("[%s] Connecting to VLDB server 0x%x, port %d, service id %d\n",
195 rn
, info
.hostAddr
[i
].sin_addr
.s_addr
, info
.hostAddr
[i
].sin_port
,
197 #endif /* USS_VOL_DB */
199 rx_NewConnection(info
.hostAddr
[i
].sin_addr
.s_addr
,
200 info
.hostAddr
[i
].sin_port
, USER_SERVICE_ID
, sc
,
205 * Set up to execute Ubik transactions on the VLDB.
208 printf("[%s] Initializing Ubik interface\n", rn
);
209 #endif /* USS_VOL_DB */
210 code
= ubik_ClientInit(serverconns
, &uconn_vldbP
);
212 fprintf(stderr
, "%s: Ubik client init failed.\n", uss_whoami
);
216 printf("[%s] VLDB ubik connection structure at 0x%x\n", rn
, uconn_vldbP
);
217 #endif /* USS_VOL_DB */
220 * Place the ubik VLDB connection structure in its advertised
223 cstruct
= uconn_vldbP
;
231 } /*InitThisModule */
234 /*-----------------------------------------------------------------------
235 * static HostIDToHostName
238 * Given a host ID (in network byte order), figure out the
239 * corresponding host name.
242 * a_hostID : Host ID in network byte order.
243 * a_hostName : Ptr to host name buffer.
249 * This routine simply calls the hostutil_GetNameByINet()
250 * function exported by the utility library (util.a).
254 *------------------------------------------------------------------------*/
257 HostIDToHostName(afs_int32 a_hostID
, char *a_hostName
)
258 { /*HostIDToHostName */
260 strcpy(a_hostName
, hostutil_GetNameByINet(a_hostID
));
262 } /*HostIDToHostName */
265 /*-----------------------------------------------------------------------
266 * static PartIDToPartName
269 * Given a partition ID (in network byte order), figure out the
270 * corresponding partition name.
273 * a_partID : Partition ID in network byte order.
274 * a_partName : Ptr to partition name buffer.
277 * 0 if everything went well, or
278 * -1 if the given partition ID couldn't be translated.
281 * Nothing interesting.
285 *------------------------------------------------------------------------*/
288 PartIDToPartName(afs_int32 a_partID
, char *a_partName
)
289 { /*PartIDToPartName */
291 static char rn
[] = "PartIDToPartName";
294 printf("[%s] Translating partition id %d to its name\n", rn
, a_partID
);
295 #endif /* USS_VOL_DB */
297 if ((a_partID
< 0) || (a_partID
> VOLMAXPARTS
))
301 strcpy(a_partName
, "/vicep");
302 a_partName
[6] = a_partID
+ 'a';
303 a_partName
[7] = '\0';
305 strcpy(a_partName
, "/vicep");
307 a_partName
[6] = 'a' + (a_partID
/ 26);
308 a_partName
[7] = 'a' + (a_partID
% 26);
309 a_partName
[8] = '\0';
313 printf("[%s] Translation for part ID %d is '%s'\n", rn
, a_partID
,
315 #endif /* USS_VOL_DB */
318 } /*PartIDToPartName */
321 /*------------------------------------------------------------------------
322 * EXPORTED uss_Vol_GetServer
325 * Nothing interesting.
329 *------------------------------------------------------------------------*/
332 uss_vol_GetServer(char *a_name
)
333 { /*uss_vol_GetServer */
337 afs_int32 b1
, b2
, b3
, b4
;
340 code
= sscanf(a_name
, "%d.%d.%d.%d", &b1
, &b2
, &b3
, &b4
);
343 * Parsed as 128.2.9.4, or similar; return it in network
344 * byte order (128 in byte 0).
346 addr
= (b1
<< 24) | (b2
<< 16) | (b3
<< 8) | b4
;
350 th
= gethostbyname(a_name
);
353 memcpy(&addr
, th
->h_addr
, sizeof(addr
));
356 } /*uss_vol_GetServer */
358 /* XXX - This function is unused, and could be deleted */
360 /*------------------------------------------------------------------------
361 * static GetVolumeType
364 * Translate the given char string representing a volume type to the
365 * numeric representation.
368 * a_type : Char string volume type.
371 * One of ROVOL, RWVOL, BACKVOL, or -1 on failure.
374 * Nothing interesting.
378 *------------------------------------------------------------------------*/
381 GetVolumeType(char *a_type
)
384 if (!strcmp(a_type
, "ro"))
386 else if (!strcmp(a_type
, "rw"))
388 else if (!strcmp(a_type
, "bk"))
396 /*------------------------------------------------------------------------
397 * EXPORTED uss_Vol_GetPartitionID
400 * It is assumed that partition names may begin with ``/vicep''.
404 *------------------------------------------------------------------------*/
407 uss_vol_GetPartitionID(char *a_name
)
408 { /*uss_vol_GetPartitionID */
418 * Numbers go straight through.
420 if (tc
>= '0' && tc
<= '9') {
421 return (atoi(a_name
));
425 * Otherwise, check for vicepa or /vicepa, or just plain "a"
428 if (strlen(a_name
) <= 2) {
429 strcpy(ascii
, a_name
);
430 } else if (!strncmp(a_name
, "/vicep", 6)) {
431 strncpy(ascii
, a_name
+ 6, 2);
432 } else if (!strncmp(a_name
, "vicep", 5)) {
433 strncpy(ascii
, a_name
+ 5, 2);
438 * Now, partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab,
439 * .../vicepzz, and are numbered from 0. Do the appropriate conversion.
443 * Single-char name, 0..25
445 if (ascii
[0] < 'a' || ascii
[0] > 'z')
446 return (-1); /* wrongo */
447 return (ascii
[0] - 'a');
450 * Two-char name, 26 .. <whatever>
452 if (ascii
[0] < 'a' || ascii
[0] > 'z')
454 if (ascii
[1] < 'a' || ascii
[1] > 'z')
456 return ((ascii
[0] - 'a') * 26 + (ascii
[1] - 'a') + 26);
458 } /*uss_vol_GetPartitionID */
461 /*-----------------------------------------------------------------------
462 * static CheckDoubleMount
465 * Make sure we're not trying to mount a volume in the same place
469 * a_mp : Mountpoint pathname to check.
470 * a_oldmp : Ptr to buffer into which the old value of the
471 * mountpoint is placed (if any).
474 * 0 if the volume was not previously mounted.
475 * uss_procs_ANCIENT if there was already a mountpoint AND the
476 * user was already recorded in the password
478 * uss_procs_YOUNG if there was a mountpoint for the user taken
479 * from the directory pool, yet the user was not
480 * yet in the password file.
483 * Nothing interesting.
486 * May fill in the a_oldmp buffer with the value of the old
488 *------------------------------------------------------------------------*/
491 CheckDoubleMount(char *a_mp
, char *a_oldmp
)
492 { /*CheckDoubleMount */
495 static char rn
[] = "uss_vol:CheckDoubleMount";
497 int start
, len
, mlen
, tlen
;
502 pws
= getpwuid(atoi(uss_Uid
));
505 * User exists in the password file, so they've been fully
506 * created and integrated. Return the ``ancient'' mountpoint.
508 strcpy(a_oldmp
, pws
->pw_dir
);
509 return (uss_procs_ANCIENT
);
514 * $AUTO used. Search among the possible directories.
516 len
= strlen(uss_Auto
);
518 while (strncmp(&a_mp
[i
], uss_Auto
, len
)) {
519 a_oldmp
[i
] = a_mp
[i
];
520 if (++i
> (mlen
- len
)) {
525 if ((start
= i
) != -1) {
527 * $AUTO used in mountpoint.
529 for (i
= 0; i
< uss_NumGroups
; i
++) {
531 * Copy in the base and tail components.
533 tlen
= strlen(uss_DirPool
[i
]);
534 strncpy(&a_oldmp
[start
], uss_DirPool
[i
], tlen
);
535 strcpy(&a_oldmp
[start
+ tlen
], &a_mp
[start
+ len
]);
537 printf("%s: Checking '%s' for mount point\n", rn
, a_oldmp
);
538 #endif /* USS_VOL_DB */
539 if (lstat(a_oldmp
, &stbuf
) == 0) /*mp exists */
540 if (strcmp(a_oldmp
, a_mp
))
541 /* and is different */
543 * The old mount point exists and is different
544 * from the current one, so return the fact
545 * that we have a ``young'' mountpoint.
547 return (uss_procs_YOUNG
);
548 } /*Check each $AUTO directory */
552 /*$AUTO has been used */
554 * No luck finding the old mount point, so we just return that
555 * this is the first time we've seen this volume.
559 } /*CheckDoubleMount */
562 /*------------------------------------------------------------------------
563 * EXPORTED uss_vol_CreateVol
566 * Called from the code generated by the uss grammar.
570 *------------------------------------------------------------------------*/
573 uss_vol_CreateVol(char *a_volname
, char *a_server
, char *a_partition
,
574 char *a_quota
, char *a_mpoint
, char *a_owner
,
576 { /*uss_vol_CreateVol */
578 static char rn
[] = "uss_vol_CreateVol"; /*Routine name */
580 afs_int32 pname
; /*Partition name */
581 afs_uint32 volid
; /*Volume ID */
582 afs_int32 code
; /*return code */
583 afs_int32 saddr
; /*Socket info for server */
584 int VolExistFlag
= 0; /*Does the volume exist? */
585 int mpExistFlag
= 0; /*Does the mountpoint exist? */
586 char *Oldmpoint
= NULL
; /*Old mountpoint name, if any */
587 char tmp_str
[uss_MAX_SIZE
]; /*Useful string buffer */
588 int o
; /*Owner's user id */
589 int checkch
, ch
; /*Read user's confirmation input */
590 struct uss_subdir
*new_dir
; /*Used to remember original ACL */
593 * Don't do anything if there's already a problem.
599 fprintf(stderr
, "%s:uss_vol_CreateVol params:\n", rn
);
601 "%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
602 rn
, a_volname
, a_server
, a_partition
, a_quota
, a_mpoint
, a_owner
,
604 #endif /* USS_VOL_DB */
607 * All of the parameters passed in are taken from the template
608 * file. Override these values if the user has explicitly set
609 * them, namely if the uss commons have non-null strings.
611 if (uss_Server
[0] != '\0') {
612 #ifdef USS_VOL_DB_SHOW_OVERRIDES
615 "%s: Overriding server field: template value is '%s', overridden to '%s'\n",
616 rn
, a_server
, uss_Server
);
617 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
618 a_server
= uss_Server
;
621 if (uss_Partition
[0] != '\0') {
622 #ifdef USS_VOL_DB_SHOW_OVERRIDES
625 "%s: Overriding partition field: template value is '%s', overridden to '%s'\n",
626 rn
, a_partition
, uss_Partition
);
627 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
628 a_partition
= uss_Partition
;
631 if (uss_MountPoint
[0] != '\0') {
632 #ifdef USS_VOL_DB_SHOW_OVERRIDES
635 "%s: overriding mountpoint field: template value is '%s', overridden to '%s'\n",
636 rn
, a_mpoint
, uss_MountPoint
);
637 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
638 a_mpoint
= uss_MountPoint
;
640 #ifdef USS_VOL_DB_SHOW_OVERRIDES
641 printf("%s: Params after overrides:\n", uss_whoami
);
643 ("%s: volname '%s', server '%s', partition '%s', quota '%s', mpoint '%s', owner '%s', acl '%s'\n",
644 uss_whoami
, a_volname
, a_server
, a_partition
, a_quota
, a_mpoint
,
646 #endif /* USS_VOL_DB_SHOW_OVERRIDES */
650 "Creating volume '%s' on server '%s', partition '%s'\n",
651 a_volname
, a_server
, a_partition
);
653 saddr
= uss_vol_GetServer(a_server
);
655 uss_procs_PrintErr(line
,
656 "File server '%s' not found in config info\n",
660 pname
= uss_vol_GetPartitionID(a_partition
);
662 uss_procs_PrintErr(line
, "Couldn't interpret partition name '%s'\n",
668 * Make sure our VLDB connection(s) is/are set up before actually
669 * trying to perform a volume creation creation.
672 code
= InitThisModule(NoAuthFlag
, uss_ConfDir
, uss_Cell
);
674 afs_com_err(uss_whoami
, code
,
675 "while inititializing VLDB connection(s)\n");
679 /*Initialize VLDB connection(s) */
682 printf("%s: Creating volume on srv 0x%x, part %d, vol name '%s'\n",
683 rn
, saddr
, pname
, a_volname
);
684 #endif /* USS_VOL_DB */
685 code
= UV_CreateVolume(saddr
, pname
, a_volname
, &volid
);
687 if (code
== VL_NAMEEXIST
) {
690 "%s: Warning; Volume '%s' exists, using existing one.\n",
691 uss_whoami
, a_volname
);
694 * We should get the volid here if we want to use it, but
695 * we don't need it right now. What we DO need, though, is
696 * to ask our caller if it's OK to overwrite the user's files
697 * if they're pre-existing.
699 if (!uss_OverwriteThisOne
) {
701 ("Overwrite files in pre-existing '%s' volume? [y, n]: ",
705 checkch
= ch
= getchar();
706 while (ch
!= '\n' && ch
!= EOF
)
708 if (checkch
== 'y' || checkch
== 'Y') {
709 printf("\t[Overwriting allowed]\n");
710 uss_OverwriteThisOne
= 1;
712 printf("\t[Overwriting not permitted]\n");
713 } /*Overwriting not previously allowed */
714 } /*Volume already existed */
716 uss_procs_PrintErr(line
,
717 "Couldn't create volume '%s' [error %d]: %s\n",
718 a_volname
, code
, strerror(errno
));
720 } /*Failure was NOT because it already existed */
721 } /*UV_CreateVolume failed */
725 "\t[Dry run: Creating volume '%s' on '%s', partition '%s']\n",
726 a_volname
, a_server
, a_partition
);
729 /* OK, we want to make sure we don't double-mount the volume.
730 * If the volume existed, it can be the case that it is
731 * already mounted somewhere else (because of $AUTO or others).
732 * Let's check for that. Note: we never enter this portion of
733 * the code if we're doing a dry run.
736 if ((Oldmpoint
= malloc(strlen(a_mpoint
) + 50)) == NULL
) {
737 fprintf(stderr
, "%s: No more memory!\n", uss_whoami
);
741 mpExistFlag
= CheckDoubleMount(a_mpoint
, Oldmpoint
);
742 if (mpExistFlag
== uss_procs_ANCIENT
) {
744 "%s:\t*** WARNING ***; This user (%s) is already in passwd file (or equivalent). IGNORED.\n",
745 uss_whoami
, uss_User
);
747 uss_syntax_err
= 1; /*I know, I know, it's not a SYNTAX error */
751 if (mpExistFlag
== uss_procs_YOUNG
) {
753 "%s: Warning; Volume '%s' is already mounted on %s. Using the existing one.\n",
754 uss_whoami
, a_volname
, Oldmpoint
);
755 a_mpoint
= Oldmpoint
;
759 if (mpExistFlag
== 0) {
760 extern int local_Cell
;
765 sprintf(tmp_str
, "#%s.", a_volname
);
767 sprintf(tmp_str
, "#%s:%s.", uss_Cell
, a_volname
);
769 if (symlink(tmp_str
, a_mpoint
)) {
770 if (errno
== EEXIST
) {
772 "%s: Warning: Mount point '%s' already exists.\n",
773 uss_whoami
, a_mpoint
);
776 "%s: Can't mount volume '%s' on '%s': %s\n",
777 uss_whoami
, a_volname
, a_mpoint
, strerror(errno
));
781 } /*There was already something mounted there */
785 fprintf(stderr
, "\t[Dry run: Mounting '%s' at '%s']\n", tmp_str
,
790 /*Mount point didn't already exist */
792 * Set the volume disk quota.
795 if ((code
= uss_acl_SetDiskQuota(a_mpoint
, atoi(a_quota
))))
800 "\t[Dry run: Setting disk quota for '%s' to %s blocks]\n",
804 /*Copy mpoint into $MTPT for others to use */
805 strcpy(uss_MountPoint
, a_mpoint
);
807 o
= uss_procs_GetOwner(a_owner
);
809 if (chown(a_mpoint
, o
, -1)) {
811 "%s: Can't chown() mountpoint '%s' to owner '%s' (uid %d): %s\n",
812 uss_whoami
, a_mpoint
, a_owner
, o
, strerror(errno
));
820 "\t[Dry run: chown() mountpoint '%s' to be owned by user]\n",
825 * Set the ACL on the user's home directory so that, for the duration of
826 * the account creation, only the uss_AccountCreator has any rights on the
827 * files therein. Make sure to clear this ACL to remove anyone that might
828 * already be there due to volume creation defaults. We will set this ACL
829 * properly, as well as all ACLs of future subdirectories,as the very last
830 * thing we do to the new account.
832 new_dir
= malloc(sizeof(struct uss_subdir
));
833 new_dir
->previous
= uss_currentDir
;
834 new_dir
->path
= strdup(a_mpoint
);
835 new_dir
->finalACL
= strdup(a_acl
);
836 uss_currentDir
= new_dir
;
837 sprintf(tmp_str
, "%s %s all", a_mpoint
, uss_AccountCreator
);
844 fprintf(stderr
, "Setting ACL: '%s'\n", tmp_str
);
845 if (uss_acl_SetAccess(tmp_str
, 1, 0))
849 fprintf(stderr
, "\t[Dry run: uss_acl_SetAccess(%s)]\n", tmp_str
);
852 } /*uss_vol_CreateVol */
855 /*------------------------------------------------------------------------
856 * EXPORTED uss_vol_DeleteVol
859 * Nothing interesting.
863 *------------------------------------------------------------------------*/
866 uss_vol_DeleteVol(char *a_volName
, afs_int32 a_volID
, char *a_servName
,
867 afs_int32 a_servID
, char *a_partName
, afs_int32 a_partID
)
868 { /*uss_vol_DeleteVol */
871 static char rn
[] = "uss_vol_DeleteVol"; /*Routine name */
873 afs_int32 code
= 0; /*Return code */
876 * Make sure we've initialized our VLDB connection(s) before
880 code
= InitThisModule(NoAuthFlag
, uss_ConfDir
, uss_Cell
);
887 * Go for the deletion.
891 ("%s: Deleting volume '%s' (ID %d) on FileServer '%s' (0x%x), partition '%s' (%d)\n",
892 rn
, a_volName
, a_volID
, a_servName
, a_servID
, a_partName
,
894 #endif /* USS_VOL_DB */
896 code
= UV_DeleteVolume(a_servID
, a_partID
, a_volID
);
898 printf("%s: Can't delete volume '%s'\n", uss_whoami
, a_volName
);
900 printf("\t[Dry run - volume '%s' NOT removed]\n", a_volName
);
904 } /*uss_vol_DeleteVol */
907 /*------------------------------------------------------------------------
908 * static GetServerAndPart
911 * Given a VLDB entry, return the server and partition IDs for
912 * the read/write volume.
915 * a_vldbEntryP : Ptr to VLDB entry.
916 * a_servIDP : Ptr to server ID to set.
917 * a_partIDP : Ptr to partition ID to set.
920 * 0 if everything went well, or
924 * Nothing interesting.
928 *------------------------------------------------------------------------*/
931 GetServerAndPart(struct nvldbentry
*a_vldbEntryP
, afs_int32
*a_servIDP
,
932 afs_int32
*a_partIDP
)
933 { /*GetServerAndPart */
936 * It really looks like all we need to do is pull off the
937 * first entry's info.
939 *a_servIDP
= a_vldbEntryP
->serverNumber
[0];
940 *a_partIDP
= a_vldbEntryP
->serverPartition
[0];
943 } /*GetServerAndPart */
946 /*------------------------------------------------------------------------
947 * static ovlentry_to_nvlentry
950 * Converts a vldbentry to nvldbentry.
953 * oentryp IN : Ptr to vldbentry.
954 * nentryp OUT : Ptr to nvldbentry.
960 * Nothing interesting.
964 *------------------------------------------------------------------------*/
967 ovlentry_to_nvlentry(struct vldbentry
*oentryp
,
968 struct nvldbentry
*nentryp
)
972 memset(nentryp
, 0, sizeof(struct nvldbentry
));
973 strncpy(nentryp
->name
, oentryp
->name
, sizeof(nentryp
->name
));
974 for (i
= 0; i
< oentryp
->nServers
; i
++) {
975 nentryp
->serverNumber
[i
] = oentryp
->serverNumber
[i
];
976 nentryp
->serverPartition
[i
] = oentryp
->serverPartition
[i
];
977 nentryp
->serverFlags
[i
] = oentryp
->serverFlags
[i
];
979 nentryp
->nServers
= oentryp
->nServers
;
980 for (i
= 0; i
< MAXTYPES
; i
++)
981 nentryp
->volumeId
[i
] = oentryp
->volumeId
[i
];
982 nentryp
->cloneId
= oentryp
->cloneId
;
983 nentryp
->flags
= oentryp
->flags
;
987 /*------------------------------------------------------------------------
988 * static uss_vol_GetEntryByID
991 * Obtains a nvldbentry whether new or old forms of
992 * ubik_VL_GetEntryByID are required.
995 * cstruct : Ptr to ubik_client.
996 * volid : Volume ID for which entry is being obtained.
997 * voltype : Required volume type
998 * entryp : Ptr to nvldbentry to receive the output on success.
1001 * 0 if everything went well, or
1002 * ubik return code otherwise.
1005 * Nothing interesting.
1009 *------------------------------------------------------------------------*/
1012 uss_vol_GetEntryByID(struct ubik_client
*cstruct
, afs_uint32 volid
,
1013 afs_int32 voltype
, struct nvldbentry
*entryp
)
1015 struct vldbentry oentry
;
1018 code
= ubik_VL_GetEntryByIDN(cstruct
, 0, volid
, voltype
, entryp
);
1019 if (code
== RXGEN_OPCODE
) {
1021 ubik_VL_GetEntryByID(cstruct
, 0, volid
, voltype
, &oentry
);
1023 ovlentry_to_nvlentry(&oentry
, entryp
);
1029 /*------------------------------------------------------------------------
1030 * EXPORTED uss_vol_GetVolInfoFromMountPoint
1033 * If the mountpoint path provided is not
1037 *------------------------------------------------------------------------*/
1040 uss_vol_GetVolInfoFromMountPoint(char *a_mountpoint
)
1041 { /*uss_vol_GetVolInfoFromMountPoint */
1043 static char rn
[] = "uss_vol_GetVolInfoFromMountPoint";
1045 afs_int32 code
; /*Return code */
1046 uss_VolumeStatus_t
*statusP
; /*Ptr to returned status */
1047 afs_int32 volID
; /*Volume ID */
1048 struct nvldbentry vldbEntry
; /*VLDB entry for volume */
1049 afs_int32 serverID
; /*Addr of host FileServer */
1050 afs_int32 partID
; /*Volume's partition ID */
1053 * Set up to ask the CacheManager to give us all the info
1054 * it has about the given mountpoint.
1056 code
= uss_fs_GetVolStat(a_mountpoint
, uss_fs_OutBuff
, USS_FS_MAX_SIZE
);
1058 printf("[%s] Result of uss_fs_GetVolStat: code = %d, errno = %d\n", rn
,
1060 #endif /* USS_VOL_DB */
1062 if (errno
== EINVAL
|| errno
== ENOENT
|| errno
== ENODEV
) {
1064 * We were given a mountpoint pathname that doesn't
1065 * point to a volume, or a mountpoint that has already
1066 * been deleted. This means that there is no info
1067 * to get from this pathname. Zero out the volume,
1068 * server & partition info and return successfully.
1070 uss_Volume
[0] = '\0';
1071 uss_Server
[0] = '\0';
1072 uss_Partition
[0] = '\0';
1075 uss_PartitionID
= 0;
1077 printf("%s: Warning: Mountpoint pathname '%s': ", uss_whoami
,
1079 if (errno
== EINVAL
)
1080 printf("Volume not reachable\n");
1081 else if (errno
== ENODEV
)
1082 printf("No such device\n");
1084 printf("Not found\n");
1088 printf("%s: Can't get volume information from mountpoint '%s'\n",
1089 uss_whoami
, a_mountpoint
);
1094 /*Can't get volume status */
1096 * Pull out the volume name from the returned information and store
1097 * it in the common area. It resides right after the basic volume
1100 statusP
= (uss_VolumeStatus_t
*) uss_fs_OutBuff
;
1101 strcpy(uss_Volume
, (((char *)statusP
) + sizeof(*statusP
)));
1102 volID
= statusP
->Vid
;
1103 uss_VolumeID
= volID
;
1105 printf("%s: Illegal volume ID: %d\n", uss_whoami
, volID
);
1110 * With the volume name in hand, find out where that volume
1111 * lives. Make sure our VLDB stuff has been initialized first.
1114 code
= InitThisModule(NoAuthFlag
, uss_ConfDir
, uss_Cell
);
1118 code
= uss_vol_GetEntryByID( uconn_vldbP
, volID
, -1, &vldbEntry
);
1120 printf("%s: Can't fetch VLDB entry for volume ID %d\n", uss_whoami
,
1126 * Translate the given VLDB entry from network to host format, then
1127 * checking on the volume's validity. Specifically, it must be a
1128 * read/write volume and must only exist on one server.
1130 MapHostToNetwork(&vldbEntry
);
1131 if (vldbEntry
.volumeId
[RWVOL
] != volID
) {
1132 printf("%s: Volume '%s' (ID %d) is not a read/write volume!!\n",
1133 uss_whoami
, uss_Volume
, volID
);
1136 if (vldbEntry
.nServers
!= 1) {
1137 printf("%s: Volume '%s' (ID %d) exists on multiple servers!!\n",
1138 uss_whoami
, uss_Volume
, volID
);
1143 * Pull out the int32words containing the server and partition info
1144 * for the read/write volume.
1146 code
= GetServerAndPart(&vldbEntry
, &serverID
, &partID
);
1149 ("%s: Can't get server/partition info from VLDB entry for volume '%s' (ID %d)\n",
1150 uss_whoami
, uss_Volume
, volID
);
1155 * Store the raw data, then translate the FileServer address to a
1156 * host name, and the partition ID to a partition name.
1158 uss_ServerID
= serverID
;
1159 uss_PartitionID
= partID
;
1160 HostIDToHostName(serverID
, uss_Server
);
1162 printf("[%s] Server ID 0x%x translated to '%s'\n", rn
, serverID
,
1164 #endif /* USS_VOL_DB */
1165 code
= PartIDToPartName(partID
, uss_Partition
);
1167 printf("%s: Error translating partition ID %d to partition name\n",
1168 uss_whoami
, partID
);
1173 * We got it, home boy.
1177 } /*uss_vol_GetVolInfoFromMountPoint */