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 * This file is a reimplementation of volser/vsproc.s. Every attempt
12 * has been made to keep it as similar as possible to aid comprehension
13 * of the code. For most functions, two parameters have been added
14 * the cell handle, and a status variable. For those functions that
15 * require one, a server handle may also be added.
17 * Other changes were made to provide thread safe functions and
18 * eliminate the practice of reporting errors to STDOUT.
21 #include <afsconfig.h>
22 #include <afs/param.h>
29 #include "lockprocs.h"
30 #include "../adminutil/afs_AdminInternal.h"
31 #include <afs/afs_AdminErrors.h>
32 #include "afs_vosAdmin.h"
41 static afs_int32 GroupEntries();
45 afs_int32 vldbEntryIndex;
48 static struct rx_connection *
49 UV_Bind(afs_cell_handle_p cellHandle, afs_int32 aserver, afs_int32 port)
51 return rx_GetCachedConnection(htonl(aserver), htons(port), VOLSERVICE_ID,
52 cellHandle->tokens->afs_sc[cellHandle->
55 cellHandle->tokens->sc_index);
59 /* if <okvol> is allright(indicated by beibg able to
60 * start a transaction, delete the <delvol> */
62 CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
63 afs_int32 okvol, afs_int32 delvol)
65 afs_int32 error, code, tid, rcode;
71 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
74 code = AFSVolDeleteVolume(aconn, tid);
77 code = AFSVolEndTrans(aconn, tid, &rcode);
84 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline, &tid);
86 code = AFSVolEndTrans(aconn, tid, &rcode);
91 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
94 code = AFSVolDeleteVolume(aconn, tid);
97 code = AFSVolEndTrans(aconn, tid, &rcode);
108 /* forcibly remove a volume. Very dangerous call */
110 UV_NukeVolume(afs_cell_handle_p cellHandle, struct rx_connection *server,
111 unsigned int partition, unsigned int volumeId, afs_status_p st)
114 afs_status_t tst = 0;
116 tst = AFSVolNukeVolume(server, partition, volumeId);
128 /* create a volume, given a server, partition number, volume name --> sends
129 * back new vol id in <anewid>*/
131 UV_CreateVolume(afs_cell_handle_p cellHandle, struct rx_connection *server,
132 unsigned int partition, const char *volumeName,
133 unsigned int quota, unsigned int *volumeId, afs_status_p st)
136 afs_status_t tst = 0;
139 struct nvldbentry entry;
140 struct volintInfo tstatus;
142 memset(&tstatus, 0, sizeof(tstatus));
144 tstatus.maxquota = quota;
146 /* next the next 3 available ids from the VLDB */
147 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 3, volumeId);
149 goto fail_UV_CreateVolume;
153 AFSVolCreateVolume(server, partition, volumeName, volser_RW, 0,
156 goto fail_UV_CreateVolume;
159 AFSVolSetInfo(server, tid, &tstatus);
161 tst = AFSVolSetFlags(server, tid, 0);
163 goto fail_UV_CreateVolume;
166 /* set up the vldb entry for this volume */
167 strncpy(entry.name, volumeName, VOLSER_OLDMAXVOLNAME);
169 entry.serverNumber[0] = ntohl(rx_HostOf(rx_PeerOf(server)));
170 entry.serverPartition[0] = partition;
171 entry.flags = RW_EXISTS;
172 entry.serverFlags[0] = ITSRWVOL;
173 entry.volumeId[RWVOL] = *volumeId;
174 entry.volumeId[ROVOL] = *volumeId + 1;
175 entry.volumeId[BACKVOL] = *volumeId + 2;
178 if (!VLDB_CreateEntry(cellHandle, &entry, &tst)) {
179 AFSVolDeleteVolume(server, tid);
180 goto fail_UV_CreateVolume;
183 tst = AFSVolEndTrans(server, tid, &rcode);
186 goto fail_UV_CreateVolume;
190 fail_UV_CreateVolume:
193 AFSVolEndTrans(server, tid, &rcode);
203 /* Delete the volume <volid>on <aserver> <apart>
204 * the physical entry gets removed from the vldb only if the ref count
208 UV_DeleteVolume(afs_cell_handle_p cellHandle, struct rx_connection *server,
209 unsigned int partition, unsigned int volumeId,
213 afs_status_t tst = 0;
214 afs_status_t temp = 0;
215 int serverAddr = ntohl(rx_HostOf(rx_PeerOf(server)));
219 struct nvldbentry entry;
221 afs_int32 avoltype = -1, vtype;
222 int notondisk = 0, notinvldb = 0;
224 /* Find and read the VLDB entry for this volume */
226 ubik_VL_SetLock(cellHandle->vos, 0, volumeId, avoltype,
229 if (tst != VL_NOENT) {
230 goto fail_UV_DeleteVolume;
236 if (!aVLDB_GetEntryByID(cellHandle, volumeId, avoltype, &entry, &tst)) {
237 goto fail_UV_DeleteVolume;
242 /* Whether volume is in the VLDB or not. Delete the volume on disk */
243 tst = AFSVolTransCreate(server, volumeId, partition, ITOffline, &ttid);
248 goto fail_UV_DeleteVolume;
251 tst = AFSVolDeleteVolume(server, ttid);
253 goto fail_UV_DeleteVolume;
255 tst = AFSVolEndTrans(server, ttid, &rcode);
256 tst = (tst ? tst : rcode);
259 goto fail_UV_DeleteVolume;
264 goto fail_UV_DeleteVolume;
267 if (volumeId == entry.volumeId[BACKVOL]) {
268 if (!(entry.flags & BACK_EXISTS)
269 || !Lp_Match(cellHandle, &entry, serverAddr, partition, &tst)) {
271 goto fail_UV_DeleteVolume;
274 entry.flags &= ~BACK_EXISTS;
278 else if (volumeId == entry.volumeId[ROVOL]) {
279 if (!Lp_ROMatch(cellHandle, &entry, serverAddr, partition, &tst)) {
281 goto fail_UV_DeleteVolume;
284 Lp_SetROValue(cellHandle, &entry, serverAddr, partition, 0, 0);
286 if (!Lp_ROMatch(cellHandle, &entry, 0, 0, &tst)) {
287 entry.flags &= ~RO_EXISTS;
292 else if (volumeId == entry.volumeId[RWVOL]) {
293 if (!(entry.flags & RW_EXISTS)
294 || !Lp_Match(cellHandle, &entry, serverAddr, partition, &tst)) {
296 goto fail_UV_DeleteVolume;
299 /* Delete backup if it exists */
301 AFSVolTransCreate(server, entry.volumeId[BACKVOL], partition,
304 tst = AFSVolDeleteVolume(server, ttid);
306 goto fail_UV_DeleteVolume;
308 tst = AFSVolEndTrans(server, ttid, &rcode);
310 tst = (tst ? tst : rcode);
312 goto fail_UV_DeleteVolume;
316 Lp_SetRWValue(cellHandle, &entry, serverAddr, partition, 0L, 0L);
318 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
324 notinvldb = 2; /* Not found on this server and partition */
325 goto fail_UV_DeleteVolume;
328 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
329 tst = ubik_VL_DeleteEntry(cellHandle->vos, 0, volumeId, vtype);
331 goto fail_UV_DeleteVolume;
334 if (!VLDB_ReplaceEntry
335 (cellHandle, volumeId, vtype, &entry,
336 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP), &tst)) {
337 goto fail_UV_DeleteVolume;
343 fail_UV_DeleteVolume:
345 if (notondisk && notinvldb) {
347 tst = ADMVOSVOLUMENOEXIST;
351 temp = AFSVolEndTrans(server, ttid, &rcode);
352 temp = (temp ? temp : rcode);
361 ubik_VL_ReleaseLock(cellHandle->vos, 0, volumeId, -1,
362 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
375 #define ONERR(ec, es, ep) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto mfail; }
377 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
378 * <atopart>. The operation is almost idempotent
382 UV_MoveVolume(afs_cell_handle_p cellHandle, afs_int32 afromvol,
383 afs_int32 afromserver, afs_int32 afrompart, afs_int32 atoserver,
384 afs_int32 atopart, afs_status_p st)
387 afs_status_t tst = 0;
388 afs_status_t etst = 0;
389 struct rx_connection *toconn, *fromconn;
390 afs_int32 fromtid, totid, clonetid;
393 char tmpName[VOLSER_MAXVOLNAME + 1];
396 struct restoreCookie cookie;
397 afs_int32 newVol, volid, backupId;
398 struct volser_status tstatus;
399 struct destServer destination;
401 struct nvldbentry entry;
405 afs_int32 store_flags;
407 #ifdef ENABLE_BUGFIX_1165
408 volEntries volumeInfo;
409 struct volintInfo *infop = 0;
413 fromconn = (struct rx_connection *)0;
414 toconn = (struct rx_connection *)0;
424 if (!aVLDB_GetEntryByID(cellHandle, afromvol, -1, &entry, &tst)) {
425 goto fail_UV_MoveVolume;
428 if (entry.volumeId[RWVOL] != afromvol) {
429 tst = ADMVOSVOLUMEMOVERWONLY;
430 goto fail_UV_MoveVolume;
434 ubik_VL_SetLock(cellHandle->vos, 0, afromvol, RWVOL, VLOP_MOVE);
436 goto fail_UV_MoveVolume;
440 if (!aVLDB_GetEntryByID(cellHandle, afromvol, RWVOL, &entry, &tst)) {
441 goto fail_UV_MoveVolume;
444 backupId = entry.volumeId[BACKVOL];
446 if (!Lp_Match(cellHandle, &entry, afromserver, afrompart, &tst)) {
447 /* the from server and partition do not exist in the vldb entry corresponding to volid */
448 if (!Lp_Match(cellHandle, &entry, atoserver, atopart, &tst)) {
449 /* the to server and partition do not exist in the vldb entry corresponding to volid */
451 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
452 (LOCKREL_OPCODE | LOCKREL_AFSID |
455 goto fail_UV_MoveVolume;
457 tst = VOLSERVOLMOVED;
458 goto fail_UV_MoveVolume;
461 /* delete the volume afromvol on src_server */
462 /* from-info does not exist but to-info does =>
463 * we have already done the move, but the volume
464 * may still be existing physically on from fileserver
466 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
471 AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline,
473 if (!tst) { /* volume exists - delete it */
475 AFSVolSetFlags(fromconn, fromtid,
476 VTDeleteOnSalvage | VTOutOfService);
478 goto fail_UV_MoveVolume;
481 tst = AFSVolDeleteVolume(fromconn, fromtid);
483 goto fail_UV_MoveVolume;
486 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
491 goto fail_UV_MoveVolume;
495 /*delete the backup volume now */
498 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
500 if (!tst) { /* backup volume exists - delete it */
502 AFSVolSetFlags(fromconn, fromtid,
503 VTDeleteOnSalvage | VTOutOfService);
505 goto fail_UV_MoveVolume;
508 tst = AFSVolDeleteVolume(fromconn, fromtid);
510 goto fail_UV_MoveVolume;
513 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
518 goto fail_UV_MoveVolume;
524 goto fail_UV_MoveVolume;
527 /* From-info matches the vldb info about volid,
528 * its ok start the move operation, the backup volume
529 * on the old site is deleted in the process
531 if (afrompart == atopart) {
532 if (!VLDB_IsSameAddrs
533 (cellHandle, afromserver, atoserver, &same, &tst)) {
534 goto fail_UV_MoveVolume;
537 tst = VOLSERVOLMOVED;
538 goto fail_UV_MoveVolume;
543 toconn = UV_Bind(cellHandle, atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
544 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
545 fromtid = totid = 0; /* initialize to uncreated */
548 * clone the read/write volume locally.
551 tst = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
553 goto fail_UV_MoveVolume;
558 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &newVol);
560 goto fail_UV_MoveVolume;
563 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
564 strcpy(vname, "move-clone-temp");
565 tst = AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &newVol);
567 goto fail_UV_MoveVolume;
570 /* lookup the name of the volume we just cloned */
572 tst = AFSVolGetName(fromconn, fromtid, &volName);
574 goto fail_UV_MoveVolume;
578 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
583 goto fail_UV_MoveVolume;
587 * Create the destination volume
591 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
593 goto fail_UV_MoveVolume;
595 tst = AFSVolSetFlags(fromconn, clonetid, VTDeleteOnSalvage | VTOutOfService); /*redundant */
597 goto fail_UV_MoveVolume;
600 /* remember time from which we've dumped the volume */
601 tst = AFSVolGetStatus(fromconn, clonetid, &tstatus);
603 goto fail_UV_MoveVolume;
606 fromDate = tstatus.creationDate - CLOCKSKEW;
608 #ifdef ENABLE_BUGFIX_1165
610 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
611 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
612 * don't use this information...
614 volumeInfo.volEntries_val = (volintInfo *) 0; /*this hints the stub to allocate space */
615 volumeInfo.volEntries_len = 0;
616 tst = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
618 goto fail_UV_MoveVolume;
621 infop = (volintInfo *) volumeInfo.volEntries_val;
622 infop->maxquota = -1; /* Else it will replace the default quota */
625 /* create a volume on the target machine */
627 tst = AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
628 if (!tst) { /*delete the existing volume */
630 tst = AFSVolDeleteVolume(toconn, totid);
632 goto fail_UV_MoveVolume;
635 tst = AFSVolEndTrans(toconn, totid, &rcode);
640 goto fail_UV_MoveVolume;
646 AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &volid,
649 goto fail_UV_MoveVolume;
652 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
656 tst = AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
658 goto fail_UV_MoveVolume;
662 * Now dump the clone to the new volume
665 destination.destHost = atoserver;
666 destination.destPort = AFSCONF_VOLUMEPORT;
667 destination.destSSID = 1;
669 /* Copy the clone to the new volume */
670 strncpy(cookie.name, tmpName, VOLSER_OLDMAXVOLNAME);
672 cookie.parent = entry.volumeId[RWVOL];
674 tst = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
676 goto fail_UV_MoveVolume;
679 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
684 goto fail_UV_MoveVolume;
688 * reattach to the main-line volume, and incrementally dump it.
691 tst = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
693 goto fail_UV_MoveVolume;
696 /* now do the incremental */
698 AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
701 goto fail_UV_MoveVolume;
704 /* now adjust the flags so that the new volume becomes official */
705 tst = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
707 goto fail_UV_MoveVolume;
710 tst = AFSVolSetFlags(toconn, totid, 0);
712 goto fail_UV_MoveVolume;
714 #ifdef ENABLE_BUGFIX_1165
715 tst = AFSVolSetInfo(toconn, totid, infop);
717 goto fail_UV_MoveVolume;
721 /* put new volume online */
722 tst = AFSVolEndTrans(toconn, totid, &rcode);
727 goto fail_UV_MoveVolume;
730 Lp_SetRWValue(cellHandle, &entry, afromserver, afrompart, atoserver,
732 store_flags = entry.flags;
733 entry.flags &= ~BACK_EXISTS;
735 if (!VLDB_ReplaceEntry
736 (cellHandle, afromvol, -1, &entry,
737 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP), &tst)) {
738 goto fail_UV_MoveVolume;
740 entry.flags = store_flags;
743 if (atoserver != afromserver) {
744 /* set forwarding pointer for moved volumes */
745 tst = AFSVolSetForwarding(fromconn, fromtid, htonl(atoserver));
747 goto fail_UV_MoveVolume;
751 tst = AFSVolDeleteVolume(fromconn, fromtid); /* zap original volume */
753 goto fail_UV_MoveVolume;
756 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
761 goto fail_UV_MoveVolume;
764 /* Delete the backup volume on the original site */
766 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
769 AFSVolSetFlags(fromconn, fromtid,
770 VTDeleteOnSalvage | VTOutOfService);
772 goto fail_UV_MoveVolume;
775 tst = AFSVolDeleteVolume(fromconn, fromtid);
777 goto fail_UV_MoveVolume;
780 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
785 goto fail_UV_MoveVolume;
789 tst = 0; /* no backup volume? that's okay */
794 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
796 goto fail_UV_MoveVolume;
799 /* now delete the clone */
801 tst = AFSVolDeleteVolume(fromconn, clonetid);
803 goto fail_UV_MoveVolume;
806 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
811 goto fail_UV_MoveVolume;
817 /* normal cleanup code */
821 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
822 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
830 etst = AFSVolEndTrans(fromconn, fromtid, &rcode);
833 tst = (etst ? etst : rcode);
838 etst = AFSVolEndTrans(fromconn, clonetid, &rcode);
841 tst = (etst ? etst : rcode);
846 etst = AFSVolEndTrans(toconn, totid, &rcode);
849 tst = (etst ? etst : rcode);
854 #ifdef ENABLE_BUGFIX_1165
859 rx_ReleaseCachedConnection(fromconn);
861 rx_ReleaseCachedConnection(toconn);
869 /* come here only when the sky falls */
873 /* unlock VLDB entry */
875 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
876 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
879 AFSVolEndTrans(fromconn, clonetid, &rcode);
881 AFSVolEndTrans(toconn, totid, &rcode);
882 if (fromtid) { /* put it on-line */
883 AFSVolSetFlags(fromconn, fromtid, 0);
884 AFSVolEndTrans(fromconn, fromtid, &rcode);
887 if (!aVLDB_GetEntryByID(cellHandle, afromvol, -1, &entry, &tst)) {
891 /* Delete either the volume on the source location or the target location.
892 * If the vldb entry still points to the source location, then we know the
893 * volume move didn't finish so we remove the volume from the target
894 * location. Otherwise, we remove the volume from the source location.
896 if (Lp_Match(cellHandle, &entry, afromserver, afrompart, &tst)) { /* didn't move - delete target volume */
898 if (volid && toconn) {
900 AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
902 AFSVolSetFlags(toconn, totid,
903 VTDeleteOnSalvage | VTOutOfService);
904 AFSVolDeleteVolume(toconn, totid);
905 AFSVolEndTrans(toconn, totid, &rcode);
909 /* put source volume on-line */
912 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
915 AFSVolSetFlags(fromconn, fromtid, 0);
916 AFSVolEndTrans(fromconn, fromtid, &rcode);
919 } else { /* yep, move complete */
920 /* delete backup volume */
923 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
926 AFSVolSetFlags(fromconn, fromtid,
927 VTDeleteOnSalvage | VTOutOfService);
928 AFSVolDeleteVolume(fromconn, fromtid);
929 AFSVolEndTrans(fromconn, fromtid, &rcode);
932 /* delete source volume */
934 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
937 AFSVolSetFlags(fromconn, fromtid,
938 VTDeleteOnSalvage | VTOutOfService);
939 if (atoserver != afromserver)
940 AFSVolSetForwarding(fromconn, fromtid, htonl(atoserver));
941 AFSVolDeleteVolume(fromconn, fromtid);
942 AFSVolEndTrans(fromconn, fromtid, &rcode);
947 /* common cleanup - delete local clone */
950 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
953 AFSVolDeleteVolume(fromconn, clonetid);
954 AFSVolEndTrans(fromconn, clonetid, &rcode);
958 /* unlock VLDB entry */
959 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
960 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
962 done: /* routine cleanup */
965 #ifdef ENABLE_BUGFIX_1165
970 rx_ReleaseCachedConnection(fromconn);
972 rx_ReleaseCachedConnection(toconn);
980 /* Make a new backup of volume <avolid> on <aserver> and <apart>
981 * if one already exists, update it
985 UV_BackupVolume(afs_cell_handle_p cellHandle, afs_int32 aserver,
986 afs_int32 apart, afs_int32 avolid, afs_status_p st)
989 afs_status_t tst = 0, temp = 0;
990 afs_int32 ttid = 0, btid = 0;
993 char vname[VOLSER_MAXVOLNAME + 1];
994 struct nvldbentry entry;
995 int vldblocked = 0, vldbmod = 0, backexists = 1;
996 struct rx_connection *aconn = UV_Bind(cellHandle, aserver,
1000 /* the calls to VLDB will succeed only if avolid is a RW volume,
1001 * since we are following the RW hash chain for searching */
1002 if (!aVLDB_GetEntryByID(cellHandle, avolid, RWVOL, &entry, &tst)) {
1003 goto fail_UV_BackupVolume;
1006 /* These operations require the VLDB be locked since it means the VLDB
1007 * will change or the vldb is already locked.
1009 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
1010 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
1011 (entry.volumeId[BACKVOL] == INVALID_BID)) {
1012 /* no assigned backup volume id */
1015 ubik_VL_SetLock(cellHandle->vos, 0, avolid, RWVOL,
1018 goto fail_UV_BackupVolume;
1022 /* Reread the vldb entry */
1023 if (!aVLDB_GetEntryByID(cellHandle, avolid, RWVOL, &entry, &tst)) {
1024 goto fail_UV_BackupVolume;
1028 if (!ISNAMEVALID(entry.name)) {
1029 tst = VOLSERBADNAME;
1030 goto fail_UV_BackupVolume;
1033 backupID = entry.volumeId[BACKVOL];
1034 if (backupID == INVALID_BID) {
1035 /* Get a backup volume id from the VLDB and update the vldb
1038 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &backupID);
1040 goto fail_UV_BackupVolume;
1042 entry.volumeId[BACKVOL] = backupID;
1046 /* Test to see if the backup volume exists by trying to create
1047 * a transaction on the backup volume. We've assumed the backup exists.
1049 tst = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1051 if (tst != VNOVOL) {
1052 goto fail_UV_BackupVolume;
1054 backexists = 0; /* backup volume does not exist */
1057 tst = AFSVolEndTrans(aconn, btid, &rcode);
1060 tst = (tst ? tst : rcode);
1061 goto fail_UV_BackupVolume;
1065 /* Now go ahead and try to clone the RW volume.
1066 * First start a transaction on the RW volume
1068 tst = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
1070 goto fail_UV_BackupVolume;
1073 /* Clone or reclone the volume, depending on whether the backup
1074 * volume exists or not
1077 tst = AFSVolReClone(aconn, ttid, backupID);
1079 goto fail_UV_BackupVolume;
1082 strcpy(vname, entry.name);
1083 strcat(vname, ".backup");
1085 tst = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID);
1087 goto fail_UV_BackupVolume;
1091 /* End transaction on the RW volume */
1092 tst = AFSVolEndTrans(aconn, ttid, &rcode);
1095 tst = (tst ? tst : rcode);
1096 goto fail_UV_BackupVolume;
1099 /* Mork vldb as backup exists */
1100 if (!(entry.flags & BACK_EXISTS)) {
1101 entry.flags |= BACK_EXISTS;
1105 /* Now go back to the backup volume and bring it on line */
1106 tst = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1108 goto fail_UV_BackupVolume;
1111 tst = AFSVolSetFlags(aconn, btid, 0);
1113 goto fail_UV_BackupVolume;
1116 tst = AFSVolEndTrans(aconn, btid, &rcode);
1119 tst = (tst ? tst : rcode);
1120 goto fail_UV_BackupVolume;
1124 /* Will update the vldb below */
1126 fail_UV_BackupVolume:
1129 temp = AFSVolEndTrans(aconn, ttid, &rcode);
1130 if (temp || rcode) {
1132 tst = (temp ? temp : rcode);
1137 temp = AFSVolEndTrans(aconn, btid, &rcode);
1138 if (temp || rcode) {
1140 tst = (temp ? temp : rcode);
1144 /* Now update the vldb - if modified */
1147 if (!VLDB_ReplaceEntry
1148 (cellHandle, avolid, RWVOL, &entry,
1149 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP),
1157 ubik_VL_ReleaseLock(cellHandle->vos, 0, avolid, RWVOL,
1158 (LOCKREL_OPCODE | LOCKREL_AFSID |
1159 LOCKREL_TIMESTAMP));
1169 rx_ReleaseCachedConnection(aconn);
1179 DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
1182 afs_int32 acode, ccode, rcode, tid;
1183 ccode = rcode = tid = 0;
1185 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
1186 if (!acode) { /* It really was there */
1187 acode = AFSVolDeleteVolume(conn, tid);
1188 ccode = AFSVolEndTrans(conn, tid, &rcode);
1196 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
1197 #define ERROREXIT(ec) { error = (ec); goto rfail; }
1199 #if 0 /* doesn't appear to be used, why compile it */
1201 CloneVol(afs_cell_handle_p cellHandle, struct rx_connection *conn,
1202 afs_int32 rwvid, afs_int32 part, afs_int32 * rovidp, int nottemp,
1203 struct nvldbentry *entry, afs_int32 * vidCreateDate, afs_status_p st)
1206 afs_status_t tst = 0, etst = 0;
1207 afs_int32 rcode = 0, tid = 0;
1208 struct volser_status volstatus;
1211 /* Begin transaction on RW volume marking it busy (clients will wait) */
1212 tst = AFSVolTransCreate(conn, rwvid, part, ITBusy, &tid);
1217 /* Get the RO volume id. Allocate a new one if need to */
1218 *rovidp = entry->volumeId[ROVOL];
1219 if (*rovidp == INVALID_BID) {
1220 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, rovidp);
1225 entry->volumeId[ROVOL] = *rovidp;
1228 /* If we are creating the ro clone, what are we calling it.
1229 * Depends on whether its a temporary clone or not.
1232 strcpy(vname, entry->name);
1233 strcat(vname, ".readonly");
1235 strcpy(vname, "readonly-clone-temp"); /* Should be unique? */
1238 /* Create the new clone. If it exists, then reclone it */
1239 tst = AFSVolClone(conn, tid, 0, readonlyVolume, vname, rovidp);
1240 if (tst == VVOLEXISTS) {
1241 tst = AFSVolReClone(conn, tid, *rovidp);
1250 /* Bring the volume back on-line as soon as possible */
1252 afs_int32 fromtid = 0;
1254 /* Now bring the RO clone on-line */
1255 tst = AFSVolTransCreate(conn, *rovidp, part, ITOffline, &fromtid);
1260 tst = AFSVolSetFlags(conn, fromtid, 0);
1265 tst = AFSVolEndTrans(conn, fromtid, &rcode);
1274 /* Get the time the RW was created for return information */
1275 tst = AFSVolGetStatus(conn, tid, &volstatus);
1279 *vidCreateDate = volstatus.creationDate;
1285 tst = AFSVolEndTrans(conn, tid, &rcode);
1302 /* Get a "transaction" on this replica. Create the volume
1303 * if necessary. Return the time from which a dump should
1304 * be made (0 if it's a new volume)
1307 GetTrans(afs_cell_handle_p cellHandle, struct nvldbentry *vldbEntryPtr,
1308 afs_int32 index, struct rx_connection **connPtr,
1309 afs_int32 * transPtr, afs_int32 * timePtr, afs_status_p st)
1312 afs_status_t tst = 0, etst = 0;
1314 struct volser_status tstatus;
1317 *connPtr = (struct rx_connection *)0;
1321 /* get connection to the replication site */
1323 UV_Bind(cellHandle, vldbEntryPtr->serverNumber[index],
1324 AFSCONF_VOLUMEPORT);
1326 /* server is down */
1331 volid = vldbEntryPtr->volumeId[ROVOL];
1334 AFSVolTransCreate(*connPtr, volid,
1335 vldbEntryPtr->serverPartition[index], ITOffline,
1339 /* If the volume does not exist, create it */
1340 if (!volid || tst) {
1343 if (volid && (tst != VNOVOL)) {
1347 strcpy(volname, vldbEntryPtr->name);
1348 strcat(volname, ".readonly");
1351 AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
1353 vldbEntryPtr->volumeId[RWVOL], &volid,
1358 vldbEntryPtr->volumeId[ROVOL] = volid;
1360 /* The following is a bit redundant, since create sets these flags by default */
1362 AFSVolSetFlags(*connPtr, *transPtr,
1363 VTDeleteOnSalvage | VTOutOfService);
1369 /* Otherwise, the transaction did succeed, so get the creation date of the
1370 * latest RO volume on the replication site
1373 tst = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
1377 *timePtr = tstatus.creationDate - CLOCKSKEW;
1383 if ((rc == 0) && (*transPtr)) {
1384 etst = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
1397 SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
1398 afs_int32 fromdate, manyDests * tr, afs_int32 flags,
1399 void *cookie, manyResults * results)
1403 for (i = 0; i < tr->manyDests_len; i++) {
1404 results->manyResults_val[i] =
1405 AFSVolForward(fromconn, fromtid, fromdate,
1406 &(tr->manyDests_val[i].server),
1407 tr->manyDests_val[i].trans, cookie);
1414 * Determine if a volume exists on a server and partition.
1415 * Try creating a transaction on the volume. If we can,
1416 * the volume exists, if not, then return the error code.
1417 * Some error codes mean the volume is unavailable but
1418 * still exists - so we catch these error codes.
1421 VolumeExists(afs_cell_handle_p cellHandle, afs_int32 server,
1422 afs_int32 partition, afs_int32 volumeid, afs_status_p st)
1425 afs_status_t tst = 0;
1426 struct rx_connection *conn = (struct rx_connection *)0;
1427 volEntries volumeInfo;
1429 conn = UV_Bind(cellHandle, server, AFSCONF_VOLUMEPORT);
1431 volumeInfo.volEntries_val = (volintInfo *) 0;
1432 volumeInfo.volEntries_len = 0;
1433 tst = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
1434 if (volumeInfo.volEntries_val)
1435 free(volumeInfo.volEntries_val);
1436 if (tst == VOLSERILLEGAL_PARTITION) {
1439 rx_ReleaseCachedConnection(conn);
1449 /* release volume <afromvol> on <afromserver> <afrompart> to all the
1450 * sites if forceflag is 1.If its 0 complete the release if the previous
1451 * release aborted else start a new release */
1453 UV_ReleaseVolume(afs_cell_handle_p cellHandle, afs_int32 afromvol,
1454 afs_int32 afromserver, afs_int32 afrompart, int forceflag,
1458 afs_status_t tst = 0, etst = 0;
1462 afs_int32 cloneVolId, roVolId;
1463 struct replica *replicas = 0;
1464 struct nvldbentry entry;
1465 int i, volcount, m, fullrelease, vldbindex;
1467 struct restoreCookie cookie;
1468 struct rx_connection **toconns = 0;
1469 struct release *times = 0;
1471 struct rx_connection *fromconn = (struct rx_connection *)0;
1473 afs_int32 clonetid = 0, onlinetid;
1474 afs_int32 fromtid = 0;
1475 afs_uint32 fromdate = 0, thisdate;
1478 manyResults results;
1479 int rwindex, roindex, roclone, roexists;
1480 afs_int32 rwcrdate = 0;
1484 } remembertime[NMAXNSERVERS];
1485 int releasecount = 0;
1486 struct volser_status volstatus;
1488 memset((char *)remembertime, 0, sizeof(remembertime));
1489 memset((char *)&results, 0, sizeof(results));
1492 ubik_VL_SetLock(cellHandle->vos, 0, afromvol, RWVOL,
1494 if ((tst) && (tst != VL_RERELEASE)) {
1495 goto fail_UV_ReleaseVolume;
1499 /* Get the vldb entry in readable format */
1500 if (!aVLDB_GetEntryByID(cellHandle, afromvol, RWVOL, &entry, &tst)) {
1501 goto fail_UV_ReleaseVolume;
1504 if (!ISNAMEVALID(entry.name)) {
1505 tst = VOLSERBADNAME;
1506 goto fail_UV_ReleaseVolume;
1509 if (entry.volumeId[RWVOL] != afromvol) {
1510 tst = ADMVOSVOLUMERELEASERWONLY;
1511 goto fail_UV_ReleaseVolume;
1514 if (entry.nServers <= 1) {
1515 tst = ADMVOSVOLUMENOREPLICAS;
1516 goto fail_UV_ReleaseVolume;
1519 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10)) {
1520 tst = VOLSERBADNAME;
1521 goto fail_UV_ReleaseVolume;
1524 /* roclone is true if one of the RO volumes is on the same
1525 * partition as the RW volume. In this case, we make the RO volume
1526 * on the same partition a clone instead of a complete copy.
1530 Lp_ROMatch(cellHandle, &entry, afromserver, afrompart, &tst) - 1;
1531 roclone = ((roindex == -1) ? 0 : 1);
1532 rwindex = Lp_GetRwIndex(cellHandle, &entry, 0);
1535 goto fail_UV_ReleaseVolume;
1538 /* Make sure we have a RO volume id to work with */
1539 if (entry.volumeId[ROVOL] == INVALID_BID) {
1540 /* need to get a new RO volume id */
1541 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &roVolId);
1543 goto fail_UV_ReleaseVolume;
1546 entry.volumeId[ROVOL] = roVolId;
1547 if (!VLDB_ReplaceEntry(cellHandle, afromvol, RWVOL, &entry, 0, &tst)) {
1548 goto fail_UV_ReleaseVolume;
1552 /* Will we be completing a previously unfinished release. -force overrides */
1553 for (fullrelease = 1, i = 0; (fullrelease && (i < entry.nServers)); i++) {
1554 if (entry.serverFlags[i] & NEW_REPSITE)
1557 if (forceflag && !fullrelease)
1560 /* Determine which volume id to use and see if it exists */
1563 || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
1564 VolumeExists(cellHandle, afromserver, afrompart, cloneVolId, &tst);
1565 roexists = ((tst == ENODEV) ? 0 : 1);
1566 if (!roexists && !fullrelease)
1567 fullrelease = 1; /* Do a full release if RO clone does not exist */
1569 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
1572 goto fail_UV_ReleaseVolume;
1576 /* If the RO clone exists, then if the clone is a temporary
1577 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
1578 * (it was recently added), then also delete it. We do not
1579 * want to "reclone" a temporary RO clone.
1582 && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
1583 tst = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
1584 if (tst && (tst != VNOVOL)) {
1585 goto fail_UV_ReleaseVolume;
1590 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
1591 * write this entry out to the vlserver until after the first
1592 * RO volume is released (temp RO clones don't count).
1594 for (i = 0; i < entry.nServers; i++) {
1595 entry.serverFlags[i] &= ~NEW_REPSITE;
1596 entry.serverFlags[i] |= RO_DONTUSE;
1598 entry.serverFlags[rwindex] |= NEW_REPSITE;
1599 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
1601 /* Begin transaction on RW and mark it busy while we clone it */
1603 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1606 goto fail_UV_ReleaseVolume;
1609 /* Clone or reclone the volume */
1611 tst = AFSVolReClone(fromconn, clonetid, cloneVolId);
1613 goto fail_UV_ReleaseVolume;
1617 strcpy(vname, entry.name);
1618 strcat(vname, ".readonly");
1620 strcpy(vname, "readonly-clone-temp");
1623 AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
1626 goto fail_UV_ReleaseVolume;
1630 /* Get the time the RW was created for future information */
1631 tst = AFSVolGetStatus(fromconn, clonetid, &volstatus);
1633 goto fail_UV_ReleaseVolume;
1635 rwcrdate = volstatus.creationDate;
1637 /* End the transaction on the RW volume */
1638 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
1640 tst = (tst ? tst : rcode);
1642 goto fail_UV_ReleaseVolume;
1645 /* Remember clone volume ID in case we fail or are interrupted */
1646 entry.cloneId = cloneVolId;
1649 /* Bring the RO clone online - though not if it's a temporary clone */
1651 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
1654 goto fail_UV_ReleaseVolume;
1657 etst = AFSVolSetFlags(fromconn, onlinetid, 0);
1659 tst = AFSVolEndTrans(fromconn, onlinetid, &rcode);
1660 tst = (tst ? tst : rcode);
1662 goto fail_UV_ReleaseVolume;
1666 goto fail_UV_ReleaseVolume;
1669 /* Sleep so that a client searching for an online volume won't
1670 * find the clone offline and then the next RO offline while the
1671 * release brings the clone online and the next RO offline (race).
1672 * There is a fix in the 3.4 client that does not need this sleep
1673 * anymore, but we don't know what clients we have.
1675 if (entry.nServers > 2)
1678 /* Mark the RO clone in the VLDB as a good site (already released) */
1679 entry.serverFlags[roindex] |= NEW_REPSITE;
1680 entry.serverFlags[roindex] &= ~RO_DONTUSE;
1681 entry.flags |= RO_EXISTS;
1685 /* Write out the VLDB entry only if the clone is not a temporary
1686 * clone. If we did this to a temporary clone then we would end
1687 * up marking all the ROs as "old release" making the ROs
1688 * temporarily unavailable.
1690 if (!VLDB_ReplaceEntry
1691 (cellHandle, afromvol, RWVOL, &entry, 0, &tst)) {
1692 goto fail_UV_ReleaseVolume;
1697 /* Now we will release from the clone to the remaining RO replicas.
1698 * The first 2 ROs (counting the non-temporary RO clone) are released
1699 * individually: releasecount. This is to reduce the race condition
1700 * of clients trying to find an on-line RO volume. The remaining ROs
1701 * are released in parallel but no more than half the number of ROs
1702 * (rounded up) at a time: nservers.
1705 strcpy(vname, entry.name);
1706 strcat(vname, ".readonly");
1707 memset(&cookie, 0, sizeof(cookie));
1708 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
1709 cookie.type = ROVOL;
1710 cookie.parent = entry.volumeId[RWVOL];
1713 nservers = entry.nServers / 2; /* how many to do at once, excluding clone */
1715 (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
1716 times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
1718 (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
1720 results.manyResults_val =
1721 (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
1722 if (!replicas || !times || !!!results.manyResults_val || !toconns) {
1724 goto fail_UV_ReleaseVolume;
1727 memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
1728 memset(times, 0, (sizeof(struct release) * nservers + 1));
1729 memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
1730 memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
1732 /* Create a transaction on the cloned volume */
1734 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
1736 goto fail_UV_ReleaseVolume;
1739 /* For each index in the VLDB */
1740 for (vldbindex = 0; vldbindex < entry.nServers;) {
1742 /* Get a transaction on the replicas. Pick replacas which have an old release. */
1744 ((volcount < nservers) && (vldbindex < entry.nServers));
1746 /* The first two RO volumes will be released individually.
1747 * The rest are then released in parallel. This is a hack
1748 * for clients not recognizing right away when a RO volume
1749 * comes back on-line.
1751 if ((volcount == 1) && (releasecount < 2))
1754 if (vldbindex == roindex)
1755 continue; /* the clone */
1756 if ((entry.serverFlags[vldbindex] & NEW_REPSITE)
1757 && !(entry.serverFlags[vldbindex] & RO_DONTUSE))
1759 if (!(entry.serverFlags[vldbindex] & ITSROVOL))
1760 continue; /* not a RO vol */
1763 /* Get a Transaction on this replica. Get a new connection if
1764 * necessary. Create the volume if necessary. Return the
1765 * time from which the dump should be made (0 if it's a new
1766 * volume). Each volume might have a different time.
1768 replicas[volcount].server.destHost =
1769 entry.serverNumber[vldbindex];
1770 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
1771 replicas[volcount].server.destSSID = 1;
1772 times[volcount].vldbEntryIndex = vldbindex;
1775 (cellHandle, &entry, vldbindex, &(toconns[volcount]),
1776 &(replicas[volcount].trans), &(times[volcount].time),
1781 /* Thisdate is the date from which we want to pick up all changes */
1782 if (forceflag || !fullrelease
1783 || (rwcrdate > times[volcount].time)) {
1784 /* If the forceflag is set, then we want to do a full dump.
1785 * If it's not a full release, we can't be sure that the creation
1786 * date is good (so we also do a full dump).
1787 * If the RW volume was replaced (its creation date is newer than
1788 * the last release), then we can't be sure what has changed (so
1789 * we do a full dump).
1792 } else if (remembertime[vldbindex].validtime) {
1793 /* Trans was prev ended. Use the time from the prev trans
1794 * because, prev trans may have created the volume. In which
1795 * case time[volcount].time would be now instead of 0.
1798 (remembertime[vldbindex].time <
1799 times[volcount].time) ? remembertime[vldbindex].
1800 time : times[volcount].time;
1802 thisdate = times[volcount].time;
1804 remembertime[vldbindex].validtime = 1;
1805 remembertime[vldbindex].time = thisdate;
1807 if (volcount == 0) {
1808 fromdate = thisdate;
1810 /* Include this volume if it is within 15 minutes of the earliest */
1812 thisdate) ? (fromdate - thisdate) : (thisdate -
1814 AFSVolEndTrans(toconns[volcount],
1815 replicas[volcount].trans, &rcode);
1816 replicas[volcount].trans = 0;
1819 if (thisdate < fromdate)
1820 fromdate = thisdate;
1827 /* Release the ones we have collected */
1828 tr.manyDests_val = &(replicas[0]);
1829 tr.manyDests_len = results.manyResults_len = volcount;
1831 AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr,
1832 0 /*spare */ , &cookie, &results);
1833 if (tst == RXGEN_OPCODE) { /* RPC Interface Mismatch */
1835 SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr,
1836 0 /*spare */ , &cookie, &results);
1841 goto fail_UV_ReleaseVolume;
1843 for (m = 0; m < volcount; m++) {
1844 if (results.manyResults_val[m]) {
1849 AFSVolSetIdsTypes(toconns[m], replicas[m].trans, vname,
1850 ROVOL, entry.volumeId[RWVOL], 0, 0);
1855 /* have to clear dest. flags to ensure new vol goes online:
1856 * because the restore (forwarded) operation copied
1857 * the V_inService(=0) flag over to the destination.
1859 tst = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
1864 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
1865 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
1866 entry.flags |= RO_EXISTS;
1871 /* End the transactions and destroy the connections */
1872 for (s = 0; s < volcount; s++) {
1873 if (replicas[s].trans)
1874 tst = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
1875 replicas[s].trans = 0;
1879 if ((s == 0) || (tst != ENOENT)) {
1881 if (times[s].vldbEntryIndex < vldbindex)
1882 vldbindex = times[s].vldbEntryIndex;
1887 rx_ReleaseCachedConnection(toconns[s]);
1891 if (!VLDB_ReplaceEntry(cellHandle, afromvol, RWVOL, &entry, 0, &tst)) {
1892 goto fail_UV_ReleaseVolume;
1894 } /* for each index in the vldb */
1896 /* End the transaction on the cloned volume */
1897 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
1900 /* Figure out if any volume were not released and say so */
1901 for (failure = 0, i = 0; i < entry.nServers; i++) {
1902 if (!(entry.serverFlags[i] & NEW_REPSITE))
1906 if (!VLDB_ReplaceEntry
1907 (cellHandle, afromvol, RWVOL, &entry, LOCKREL_TIMESTAMP, &tst)) {
1908 goto fail_UV_ReleaseVolume;
1911 tst = VOLSERBADRELEASE;
1912 goto fail_UV_ReleaseVolume;
1915 /* All the ROs were release successfully. Remove the temporary clone */
1917 tst = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
1919 goto fail_UV_ReleaseVolume;
1924 for (i = 0; i < entry.nServers; i++)
1925 entry.serverFlags[i] &= ~NEW_REPSITE;
1927 /* Update the VLDB */
1928 if (!VLDB_ReplaceEntry
1929 (cellHandle, afromvol, RWVOL, &entry,
1930 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP, &tst)) {
1931 goto fail_UV_ReleaseVolume;
1935 fail_UV_ReleaseVolume:
1938 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
1945 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
1951 for (i = 0; i < nservers; i++) {
1952 if (replicas && replicas[i].trans) {
1953 tst = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
1954 replicas[i].trans = 0;
1959 if (toconns && toconns[i]) {
1960 rx_ReleaseCachedConnection(toconns[i]);
1966 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, RWVOL,
1967 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
1974 rx_ReleaseCachedConnection(fromconn);
1975 if (results.manyResults_val)
1976 free(results.manyResults_val);
1991 ReceiveFile(register int fd, register struct rx_call *call,
1992 register struct stat *status)
1994 register char *buffer = (char *)0;
1995 register int blockSize;
1996 afs_int32 bytesread, nbytes, bytesleft, w;
1998 afs_int32 error = 0;
2005 struct statfs tstatfs;
2007 /* Unfortunately in AIX valuable fields such as st_blksize are gone from the sta
2009 fstatfs(fd, &tstatfs);
2010 blockSize = tstatfs.f_bsize;
2012 blockSize = status->st_blksize;
2019 buffer = (char *)malloc(blockSize);
2024 while (!error && (bytesread > 0)) {
2025 bytesread = rx_Read(call, buffer, nbytes);
2026 bytesleft = bytesread;
2027 while (!error && (bytesleft > 0)) {
2030 #ifndef AFS_NT40_ENV /* NT csn't select on non-socket fd's */
2031 select(fd + 1, 0, &out, 0, 0); /* don't timeout if write bl
2034 w = write(fd, &buffer[bytesread - bytesleft], bytesleft);
2036 error = ADMVOSDUMPFILEWRITEFAIL;
2052 DumpFunction(struct rx_call *call, const char *filename)
2056 afs_int32 error, code;
2061 fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0666);
2062 if (fd < 0 || fstat(fd, &status) < 0) {
2063 error = VOLSERBADOP;
2066 code = ReceiveFile(fd, call, &status);
2084 /*dump the volume <afromvol> on <afromserver> and
2085 * <afrompart> to <afilename> starting from <fromdate>.
2086 * DumpFunction does the real work behind the scenes after
2087 * extracting parameters from the rock */
2089 UV_DumpVolume(afs_cell_handle_p cellHandle, afs_int32 afromvol,
2090 afs_int32 afromserver, afs_int32 afrompart, afs_int32 fromdate,
2091 const char *filename, afs_status_p st)
2094 afs_status_t tst = 0;
2095 afs_status_t etst = 0;
2096 struct rx_connection *fromconn;
2097 struct rx_call *fromcall;
2102 struct nvldbentry entry;
2109 fromcall = (struct rx_call *)0;
2110 fromconn = (struct rx_connection *)0;
2112 fromcall = (struct rx_call *)0;
2115 if (!aVLDB_GetEntryByID(cellHandle, afromvol, -1, &entry, &tst)) {
2116 goto fail_UV_DumpVolume;
2119 /* get connections to the servers */
2120 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
2121 tst = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2123 goto fail_UV_DumpVolume;
2125 fromcall = rx_NewCall(fromconn);
2126 tst = StartAFSVolDump(fromcall, fromtid, fromdate);
2128 goto fail_UV_DumpVolume;
2130 if ((tst = DumpFunction(fromcall, filename))) {
2131 goto fail_UV_DumpVolume;
2133 tst = rx_EndCall(fromcall, rxError);
2134 fromcall = (struct rx_call *)0;
2136 goto fail_UV_DumpVolume;
2138 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
2143 goto fail_UV_DumpVolume;
2151 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
2152 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2160 etst = rx_EndCall(fromcall, rxError);
2168 etst = AFSVolEndTrans(fromconn, fromtid, &rcode);
2178 rx_ReleaseCachedConnection(fromconn);
2188 SendFile(register int fd, register struct rx_call *call,
2189 register struct stat *status)
2191 char *buffer = (char *)0;
2194 afs_int32 error = 0;
2203 struct statfs tstatfs;
2205 /* Unfortunately in AIX valuable fields such as st_blksize are gone from the sta
2207 fstatfs(fd, &tstatfs);
2208 blockSize = tstatfs.f_bsize;
2210 blockSize = status->st_blksize;
2216 buffer = (char *)malloc(blockSize);
2221 while (!error && !done) {
2224 #ifndef AFS_NT40_ENV /* NT csn't select on non-socket fd's */
2225 select(fd + 1, &in, 0, 0, 0); /* don't timeout if read blocks */
2227 nbytes = read(fd, buffer, blockSize);
2229 error = ADMVOSRESTOREFILEREADFAIL;
2236 if (rx_Write(call, buffer, nbytes) != nbytes) {
2237 error = ADMVOSRESTOREFILEWRITEFAIL;
2247 WriteData(struct rx_call *call, const char *filename)
2251 afs_int32 error, code;
2256 fd = open(filename, 0);
2257 if (fd < 0 || fstat(fd, &status) < 0) {
2258 fprintf(STDERR, "Could access file '%s'\n", filename);
2259 error = ADMVOSRESTOREFILEOPENFAIL;
2260 goto fail_WriteData;
2262 code = SendFile(fd, call, &status);
2265 goto fail_WriteData;
2276 error = ADMVOSRESTOREFILECLOSEFAIL;
2282 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
2283 * the dump file <afilename>. WriteData does all the real work
2284 * after extracting params from the rock
2287 UV_RestoreVolume(afs_cell_handle_p cellHandle, afs_int32 toserver,
2288 afs_int32 topart, afs_int32 tovolid, const char *tovolname,
2289 int flags, const char *dumpFile, afs_status_p st)
2292 afs_status_t tst = 0;
2293 afs_status_t etst = 0;
2294 struct rx_connection *toconn, *tempconn;
2295 struct rx_call *tocall;
2296 afs_int32 totid, rcode;
2297 afs_int32 rxError = 0;
2298 struct volser_status tstatus;
2303 struct nvldbentry entry;
2306 struct restoreCookie cookie;
2308 afs_int32 newDate, volflag;
2312 memset(&cookie, 0, sizeof(cookie));
2317 tocall = (struct rx_call *)0;
2318 toconn = (struct rx_connection *)0;
2319 tempconn = (struct rx_connection *)0;
2324 toconn = UV_Bind(cellHandle, toserver, AFSCONF_VOLUMEPORT);
2325 if (pvolid == 0) { /*alot a new id if needed */
2326 aVLDB_GetEntryByName(cellHandle, tovolname, &entry, &tst);
2327 if (tst == VL_NOENT) {
2329 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &pvolid);
2331 goto fail_UV_RestoreVolume;
2335 pvolid = entry.volumeId[RWVOL];
2340 * at this point we have a volume id to use/reuse for the
2341 * volume to be restored
2343 if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
2344 tst = ADMVOSRESTOREVOLUMENAMETOOBIG;
2345 goto fail_UV_RestoreVolume;
2348 if (!vos_PartitionIdToName(topart, partName, &tst)) {
2349 goto fail_UV_RestoreVolume;
2351 /*what should the volume be restored as ? rw or ro or bk ?
2352 * right now the default is rw always */
2354 AFSVolCreateVolume(toconn, topart, tovolname, volser_RW, 0, &pvolid,
2357 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
2359 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2361 goto fail_UV_RestoreVolume;
2364 AFSVolSetFlags(toconn, totid,
2365 VTDeleteOnSalvage | VTOutOfService);
2367 goto fail_UV_RestoreVolume;
2369 tst = AFSVolDeleteVolume(toconn, totid);
2371 goto fail_UV_RestoreVolume;
2373 tst = AFSVolEndTrans(toconn, totid, &rcode);
2378 goto fail_UV_RestoreVolume;
2381 AFSVolCreateVolume(toconn, topart, tovolname, volser_RW, 0,
2384 goto fail_UV_RestoreVolume;
2388 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2390 goto fail_UV_RestoreVolume;
2394 cookie.parent = pvolid;
2395 cookie.type = RWVOL;
2397 strncpy(cookie.name, tovolname, VOLSER_OLDMAXVOLNAME);
2399 tocall = rx_NewCall(toconn);
2400 tst = StartAFSVolRestore(tocall, totid, 1, &cookie);
2402 goto fail_UV_RestoreVolume;
2404 tst = WriteData(tocall, dumpFile);
2406 goto fail_UV_RestoreVolume;
2408 tst = rx_EndCall(tocall, rxError);
2409 tocall = (struct rx_call *)0;
2411 goto fail_UV_RestoreVolume;
2413 tst = AFSVolGetStatus(toconn, totid, &tstatus);
2415 goto fail_UV_RestoreVolume;
2417 tst = AFSVolSetIdsTypes(toconn, totid, tovolname, RWVOL, pvolid, 0, 0);
2419 goto fail_UV_RestoreVolume;
2422 tst = AFSVolSetDate(toconn, totid, newDate);
2424 goto fail_UV_RestoreVolume;
2427 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
2428 tst = AFSVolSetFlags(toconn, totid, volflag);
2430 goto fail_UV_RestoreVolume;
2433 /* It isn't handled right in fail_UV_RestoreVolume */
2434 tst = AFSVolEndTrans(toconn, totid, &rcode);
2439 goto fail_UV_RestoreVolume;
2443 if (success && (!reuseID || (flags & RV_FULLRST))) {
2444 /* Volume was restored on the file server, update the
2445 * VLDB to reflect the change.
2447 aVLDB_GetEntryByID(cellHandle, pvolid, RWVOL, &entry, &tst);
2448 if (tst && tst != VL_NOENT && tst != VL_ENTDELETED) {
2449 goto fail_UV_RestoreVolume;
2451 if (tst == VL_NOENT) { /* it doesnot exist already */
2452 /*make the vldb return this indication specifically */
2453 strcpy(entry.name, tovolname);
2455 entry.serverNumber[0] = toserver; /*should be indirect */
2456 entry.serverPartition[0] = topart;
2457 entry.serverFlags[0] = ITSRWVOL;
2458 entry.flags = RW_EXISTS;
2459 if (tstatus.cloneID != 0) {
2460 entry.volumeId[ROVOL] = tstatus.cloneID; /*this should come from status info on the volume if non zero */
2462 entry.volumeId[ROVOL] = INVALID_BID;
2463 entry.volumeId[RWVOL] = pvolid;
2465 if (tstatus.backupID != 0) {
2466 entry.volumeId[BACKVOL] = tstatus.backupID;
2467 /*this should come from status info on the volume if non zero */
2469 entry.volumeId[BACKVOL] = INVALID_BID;
2470 if (!VLDB_CreateEntry(cellHandle, &entry, &tst)) {
2471 goto fail_UV_RestoreVolume;
2474 } else { /*update the existing entry */
2476 ubik_VL_SetLock(cellHandle->vos, 0, pvolid, RWVOL,
2479 goto fail_UV_RestoreVolume;
2482 strcpy(entry.name, tovolname);
2484 /* Update the vlentry with the new information */
2485 index = Lp_GetRwIndex(cellHandle, &entry, 0);
2487 /* Add the rw site for the volume being restored */
2488 entry.serverNumber[entry.nServers] = toserver;
2489 entry.serverPartition[entry.nServers] = topart;
2490 entry.serverFlags[entry.nServers] = ITSRWVOL;
2493 /* This volume should be deleted on the old site
2494 * if its different from new site.
2496 VLDB_IsSameAddrs(cellHandle, toserver,
2497 entry.serverNumber[index], &same, &tst);
2499 || (entry.serverPartition[index] != topart)) {
2501 UV_Bind(cellHandle, entry.serverNumber[index],
2502 AFSCONF_VOLUMEPORT);
2504 AFSVolTransCreate(tempconn, pvolid,
2505 entry.serverPartition[index],
2506 ITOffline, &temptid);
2509 AFSVolSetFlags(tempconn, temptid,
2513 goto fail_UV_RestoreVolume;
2515 tst = AFSVolDeleteVolume(tempconn, temptid);
2517 goto fail_UV_RestoreVolume;
2519 tst = AFSVolEndTrans(tempconn, temptid, &rcode);
2524 goto fail_UV_RestoreVolume;
2526 vos_PartitionIdToName(entry.serverPartition[index],
2530 entry.serverNumber[index] = toserver;
2531 entry.serverPartition[index] = topart;
2534 entry.flags |= RW_EXISTS;
2535 if (!VLDB_ReplaceEntry
2536 (cellHandle, pvolid, RWVOL, &entry,
2537 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP, &tst)) {
2538 goto fail_UV_RestoreVolume;
2545 fail_UV_RestoreVolume:
2548 etst = rx_EndCall(tocall, rxError);
2554 ubik_VL_ReleaseLock(cellHandle->vos, 0, pvolid, RWVOL,
2555 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2562 etst = AFSVolEndTrans(toconn, totid, &rcode);
2571 etst = AFSVolEndTrans(toconn, temptid, &rcode);
2581 rx_ReleaseCachedConnection(tempconn);
2583 rx_ReleaseCachedConnection(toconn);
2591 /*adds <server> and <part> as a readonly replication site for <volid>
2594 UV_AddSite(afs_cell_handle_p cellHandle, afs_int32 server, afs_int32 part,
2595 afs_int32 volid, afs_status_p st)
2598 afs_status_t tst = 0;
2599 int j, nro = 0, islocked = 0;
2600 struct nvldbentry entry;
2604 ubik_VL_SetLock(cellHandle->vos, 0, volid, RWVOL, VLOP_ADDSITE);
2606 goto fail_UV_AddSite;
2610 if (!aVLDB_GetEntryByID(cellHandle, volid, RWVOL, &entry, &tst)) {
2611 goto fail_UV_AddSite;
2613 if (!ISNAMEVALID(entry.name)) {
2615 goto fail_UV_AddSite;
2618 /* See if it's too many entries */
2619 if (entry.nServers >= NMAXNSERVERS) {
2621 goto fail_UV_AddSite;
2624 /* See if it's on the same server */
2625 for (j = 0; j < entry.nServers; j++) {
2626 if (entry.serverFlags[j] & ITSROVOL) {
2628 if (!VLDB_IsSameAddrs
2629 (cellHandle, server, entry.serverNumber[j], &same, &tst)) {
2630 goto fail_UV_AddSite;
2634 goto fail_UV_AddSite;
2639 /* See if it's too many RO sites - leave one for the RW */
2640 if (nro >= NMAXNSERVERS - 1) {
2642 goto fail_UV_AddSite;
2645 entry.serverNumber[entry.nServers] = server;
2646 entry.serverPartition[entry.nServers] = part;
2647 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
2650 if (!VLDB_ReplaceEntry
2651 (cellHandle, volid, RWVOL, &entry,
2652 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP, &tst)) {
2653 goto fail_UV_AddSite;
2662 ubik_VL_ReleaseLock(cellHandle->vos, 0, volid, RWVOL,
2663 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2672 /*removes <server> <part> as read only site for <volid> from the vldb */
2674 UV_RemoveSite(afs_cell_handle_p cellHandle, afs_int32 server, afs_int32 part,
2675 afs_int32 volid, afs_status_p st)
2678 afs_status_t tst = 0;
2679 struct nvldbentry entry;
2683 ubik_VL_SetLock(cellHandle->vos, 0, volid, RWVOL, VLOP_ADDSITE);
2685 goto fail_UV_RemoveSite;
2689 if (!aVLDB_GetEntryByID(cellHandle, volid, RWVOL, &entry, &tst)) {
2690 goto fail_UV_RemoveSite;
2692 if (!Lp_ROMatch(cellHandle, &entry, server, part, &tst)) {
2693 /*this site doesnot exist */
2694 goto fail_UV_RemoveSite;
2695 } else { /*remove the rep site */
2696 Lp_SetROValue(cellHandle, &entry, server, part, 0, 0);
2698 if ((entry.nServers == 1) && (entry.flags & RW_EXISTS))
2699 entry.flags &= ~RO_EXISTS;
2700 if (entry.nServers < 1) { /*this is the last ref */
2701 tst = ubik_VL_DeleteEntry(cellHandle->vos, 0, volid, ROVOL);
2703 goto fail_UV_RemoveSite;
2706 if (!VLDB_ReplaceEntry
2707 (cellHandle, volid, RWVOL, &entry,
2708 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP), &tst)) {
2709 goto fail_UV_RemoveSite;
2718 t = ubik_VL_ReleaseLock(cellHandle->vos, 0, volid, RWVOL,
2719 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2731 /*list all the partitions on <aserver> */
2733 UV_ListPartitions(struct rx_connection *server, struct partList *ptrPartList,
2734 afs_int32 * cntp, afs_status_p st)
2737 afs_status_t tst = 0;
2738 struct pIDs partIds;
2739 struct partEntries partEnts;
2740 register int i, j = 0;
2744 partEnts.partEntries_len = 0;
2745 partEnts.partEntries_val = NULL;
2746 /* this is available only on new servers */
2747 tst = AFSVolXListPartitions(server, &partEnts);
2749 /* next, try old interface */
2750 if (tst == RXGEN_OPCODE) {
2751 for (i = 0; i < 26; i++)
2752 partIds.partIds[i] = -1;
2753 tst = AFSVolListPartitions(server, &partIds);
2755 for (i = 0; i < 26; i++) {
2756 if ((partIds.partIds[i]) != -1) {
2757 ptrPartList->partId[j] = partIds.partIds[i];
2758 ptrPartList->partFlags[j] = PARTVALID;
2761 ptrPartList->partFlags[i] = 0;
2765 goto fail_UV_ListPartitions;
2768 *cntp = partEnts.partEntries_len;
2769 if (*cntp > VOLMAXPARTS) {
2770 *cntp = VOLMAXPARTS;
2772 for (i = 0; i < *cntp; i++) {
2773 ptrPartList->partId[i] = partEnts.partEntries_val[i];
2774 ptrPartList->partFlags[i] = PARTVALID;
2776 free(partEnts.partEntries_val);
2778 goto fail_UV_ListPartitions;
2782 fail_UV_ListPartitions:
2790 /*------------------------------------------------------------------------
2791 * EXPORTED UV_XListVolumes
2794 * List the extended information for all the volumes on a particular
2795 * File Server and partition. We may either return the volume's ID
2796 * or all of its extended information.
2799 * a_serverID : Address of the File Server for which we want
2800 * extended volume info.
2801 * a_partID : Partition for which we want the extended
2803 * a_all : If non-zero, fetch ALL the volume info,
2804 * otherwise just the volume ID.
2805 * a_resultPP : Ptr to the address of the area containing
2806 * the returned volume info.
2807 * a_numEntsInResultP : Ptr for the value we set for the number of
2812 * Otherise, the return value of AFSVolXListVolumes.
2815 * This routine is closely related to UV_ListVolumes, which returns
2816 * only the standard level of detail on AFS volumes. It is a
2817 * heavyweight operation, zipping through all the volume entries for
2818 * a given server/partition.
2822 *------------------------------------------------------------------------*/
2825 UV_XListVolumes(struct rx_connection *server, afs_int32 a_partID, int a_all,
2826 struct volintXInfo **a_resultPP,
2827 afs_int32 * a_numEntsInResultP, afs_status_p st)
2830 afs_status_t tst = 0;
2832 volXEntries volumeXInfo; /*Area for returned extended vol info */
2835 * Set up our error code and the area for returned extended volume info.
2836 * We set the val field to a null pointer as a hint for the stub to
2839 *a_numEntsInResultP = 0;
2840 *a_resultPP = (volintXInfo *) 0;
2841 volumeXInfo.volXEntries_val = (volintXInfo *) 0;
2842 volumeXInfo.volXEntries_len = 0;
2845 * Bind to the Volume Server port on the File Server machine in question,
2848 tst = AFSVolXListVolumes(server, a_partID, a_all, &volumeXInfo);
2850 goto fail_UV_XListVolumes;
2853 * We got the info; pull out the pointer to where the results lie
2854 * and how many entries are there.
2856 *a_resultPP = volumeXInfo.volXEntries_val;
2857 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
2861 fail_UV_XListVolumes:
2869 /*------------------------------------------------------------------------
2870 * EXPORTED UV_XListOneVolume
2873 * List the extended information for a volume on a particular File
2874 * Server and partition.
2877 * server : a handle to the server where the volume resides.
2878 * a_partID : Partition for which we want the extended
2880 * a_volID : Volume ID for which we want the info.
2881 * a_resultPP : Ptr to the address of the area containing
2882 * the returned volume info.
2886 * Otherise, the return value of AFSVolXListOneVolume.
2889 * This routine is closely related to UV_ListOneVolume, which returns
2890 * only the standard level of detail on the chosen AFS volume.
2894 *------------------------------------------------------------------------*/
2897 UV_XListOneVolume(struct rx_connection *server, afs_int32 a_partID,
2898 afs_int32 a_volID, struct volintXInfo **a_resultPP,
2902 afs_status_t tst = 0;
2903 volXEntries volumeXInfo; /*Area for returned info */
2906 * Set the area we're in which we are returning
2907 * the info. Setting the val field to a null pointer tells the stub
2908 * to allocate space for us.
2910 *a_resultPP = (volintXInfo *) 0;
2911 volumeXInfo.volXEntries_val = (volintXInfo *) 0;
2912 volumeXInfo.volXEntries_len = 0;
2914 tst = AFSVolXListOneVolume(server, a_partID, a_volID, &volumeXInfo);
2917 goto fail_UV_XListOneVolume;
2920 * We got the info; pull out the pointer to where the results lie.
2922 *a_resultPP = volumeXInfo.volXEntries_val;
2926 fail_UV_XListOneVolume:
2933 } /*UV_XListOneVolume */
2935 /*------------------------------------------------------------------------
2936 * EXPORTED UV_ListOneVolume
2939 * List the volume information for a volume on a particular File
2940 * Server and partition.
2943 * server : a handle to the server where the volume resides.
2944 * a_partID : Partition for which we want the extended
2946 * a_volID : Volume ID for which we want the info.
2947 * a_resultPP : Ptr to the address of the area containing
2948 * the returned volume info.
2952 * Otherise, the return value of AFSVolXListOneVolume.
2956 *------------------------------------------------------------------------*/
2958 int UV_ListOneVolume(struct rx_connection *server, afs_int32 a_partID,
2959 afs_int32 a_volID, struct volintInfo **a_resultPP,
2963 afs_status_t tst = 0;
2964 volEntries volumeInfo; /*Area for returned info */
2967 * Set the area we're in which we are returning
2968 * the info. Setting the val field to a null pointer tells the stub
2969 * to allocate space for us.
2971 *a_resultPP = (volintInfo *) 0;
2972 volumeInfo.volEntries_val = (volintInfo *) 0;
2973 volumeInfo.volEntries_len = 0;
2975 tst = AFSVolListOneVolume(server, a_partID, a_volID, &volumeInfo);
2978 goto fail_UV_ListOneVolume;
2981 * We got the info; pull out the pointer to where the results lie.
2983 *a_resultPP = volumeInfo.volEntries_val;
2987 fail_UV_ListOneVolume:
2993 }/*UV_ListOneVolume*/
2995 /*sync vldb with all the entries on <myQueue> on <aserver> and <apart>*/
2997 ProcessEntries(afs_cell_handle_p cellHandle, struct qHead *myQueue,
2998 struct rx_connection *server, afs_int32 apart, afs_int32 force)
3001 int success, temp, temp1, temp2;
3002 afs_int32 vcode, maxVolid = 0;
3003 struct nvldbentry entry;
3004 int noError = 1, error, same;
3005 int totalC, totalU, totalCE, totalUE, totalG;
3007 int aserver = ntohl(rx_HostOf(rx_PeerOf(server)));
3010 totalC = totalU = totalCE = totalUE = totalG = 0;
3013 /* get the next available id's from the vldb server */
3014 vcode = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 0, &maxVolid);
3018 totalG = myQueue->count;
3022 Lp_QEnumerate(myQueue, &success, &elem, 0);
3027 if (!elem.isValid[RWVOL] && !elem.isValid[ROVOL] && !elem.isValid[BACKVOL]) { /*something is wrong with elem */
3031 if (maxVolid <= elem.ids[RWVOL]) {
3033 temp2 = elem.ids[RWVOL] - maxVolid + 1;
3036 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, temp2,
3042 if (maxVolid <= elem.ids[ROVOL]) {
3045 temp2 = elem.ids[ROVOL] - maxVolid + 1;
3048 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, temp2,
3053 if (maxVolid <= elem.ids[BACKVOL]) {
3055 temp2 = elem.ids[BACKVOL] - temp1 + 1;
3058 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, temp2,
3063 aVLDB_GetEntryByID(cellHandle, elem.ids[RWVOL], RWVOL, &entry, &tst);
3064 if (tst && (tst != VL_NOENT)) {
3067 } else if (tst && (tst == VL_NOENT)) { /*entry doesnot exist */
3068 /*set up a vldb entry for elem */
3069 memset(&entry, 0, sizeof(entry));
3070 strncpy(entry.name, elem.name, VOLSER_OLDMAXVOLNAME);
3071 if (elem.isValid[RWVOL]) { /*rw exists */
3072 entry.flags |= RW_EXISTS;
3073 entry.serverFlags[entry.nServers] = ITSRWVOL;
3074 entry.serverNumber[entry.nServers] = aserver;
3075 entry.serverPartition[entry.nServers] = apart;
3076 entry.nServers += 1;
3077 entry.volumeId[RWVOL] = elem.ids[RWVOL];
3078 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3079 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3081 if (elem.isValid[ROVOL]) { /*ro volume exists */
3082 entry.flags |= RO_EXISTS;
3083 entry.serverFlags[entry.nServers] = ITSROVOL;
3084 entry.serverNumber[entry.nServers] = aserver;
3085 entry.serverPartition[entry.nServers] = apart;
3086 entry.nServers += 1;
3087 entry.volumeId[RWVOL] = elem.ids[RWVOL];
3088 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3091 if (elem.isValid[BACKVOL]) { /*backup volume exists */
3092 entry.flags |= BACK_EXISTS;
3093 if (!(entry.flags & RW_EXISTS)) { /*this helps to check for a stray backup if parent moves */
3094 entry.serverFlags[entry.nServers] = ITSRWVOL;
3095 entry.serverNumber[entry.nServers] = aserver;
3096 entry.serverPartition[entry.nServers] = apart;
3097 entry.nServers += 1;
3100 entry.volumeId[RWVOL] = elem.ids[RWVOL];
3101 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3104 VLDB_CreateEntry(cellHandle, &entry, &tst);
3110 } else { /* Update the existing entry */
3111 strncpy(entry.name, elem.name, VOLSER_OLDMAXVOLNAME); /*the name Could have changed */
3113 if (elem.isValid[RWVOL]) { /* A RW volume */
3114 temp = Lp_GetRwIndex(cellHandle, &entry, 0);
3116 /* A RW index is not found in the VLDB entry - will add it */
3118 entry.flags |= RW_EXISTS;
3119 entry.serverNumber[entry.nServers] = aserver;
3120 entry.serverPartition[entry.nServers] = apart;
3121 entry.serverFlags[entry.nServers] = ITSRWVOL;
3124 /* A RW index is found in the VLDB entry.
3125 * Verify that the volume location matches the VLDB location.
3126 * Fix the VLDB entry if it is not correct.
3130 VLDB_IsSameAddrs(cellHandle, aserver,
3131 entry.serverNumber[temp], &same,
3136 if (!same || (apart != entry.serverPartition[temp])) {
3137 /* VLDB says volume is in another place. Fix the VLDB entry */
3138 entry.serverNumber[temp] = aserver;
3139 entry.serverPartition[temp] = apart;
3142 entry.flags |= RW_EXISTS;
3144 if ((elem.ids[BACKVOL] != 0) && elem.isValid[BACKVOL])
3145 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3146 if ((elem.ids[ROVOL] != 0) && elem.isValid[ROVOL])
3147 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3150 if (elem.isValid[ROVOL]) {
3151 /*tackle a ro volume */
3153 if (!Lp_ROMatch(cellHandle, &entry, aserver, apart, 0)) {
3155 if (elem.ids[ROVOL] > entry.volumeId[ROVOL]) {
3156 /*there is a conflict of ids, keep the later volume */
3157 /*delete all the ro volumes listed in vldb entry since they
3160 int j, count, rwsite;
3163 count = entry.nServers;
3165 for (j = 0; j < count; j++) {
3166 if (entry.serverFlags[j] & ITSROVOL) {
3168 /*delete the site */
3169 entry.serverNumber[j] = 0;
3170 entry.serverPartition[j] = 0;
3171 entry.serverFlags[j] = 0;
3173 } else if (entry.serverFlags[j] & ITSRWVOL)
3178 entry.serverNumber[entry.nServers] =
3179 entry.serverNumber[rwsite];
3180 entry.serverPartition[entry.nServers] =
3181 entry.serverPartition[rwsite];
3182 entry.serverFlags[entry.nServers] =
3183 entry.serverFlags[rwsite];
3186 entry.serverNumber[entry.nServers] = aserver;
3187 entry.serverPartition[entry.nServers] = apart;
3188 entry.serverFlags[entry.nServers] = ITSROVOL;
3190 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3191 entry.flags |= RO_EXISTS;
3193 } else if (elem.ids[ROVOL] < entry.volumeId[ROVOL]) {
3194 if (!(entry.flags & RO_EXISTS)) {
3195 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3196 entry.serverNumber[entry.nServers] = aserver;
3197 entry.serverPartition[entry.nServers] = apart;
3198 entry.serverFlags[entry.nServers] = ITSROVOL;
3200 entry.flags |= RO_EXISTS;
3205 else if (elem.ids[ROVOL] == entry.volumeId[ROVOL]) {
3206 entry.serverNumber[entry.nServers] = aserver;
3207 entry.serverPartition[entry.nServers] = apart;
3208 entry.serverFlags[entry.nServers] = ITSROVOL;
3210 entry.flags |= RO_EXISTS;
3211 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3214 if (entry.volumeId[ROVOL] == INVALID_BID)
3215 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3218 if (elem.isValid[BACKVOL]) {
3219 temp = Lp_GetRwIndex(cellHandle, &entry, 0);
3220 if (temp != -1) { /*check if existing backup site matches with the given arguments */
3222 VLDB_IsSameAddrs(cellHandle, aserver,
3223 entry.serverNumber[temp], &same,
3229 /*tackle the backup volume */
3230 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3231 entry.flags |= BACK_EXISTS;
3233 if (entry.volumeId[BACKVOL] == INVALID_BID)
3234 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3237 VLDB_ReplaceEntry(cellHandle, elem.ids[RWVOL], RWVOL, &entry,
3238 LOCKREL_OPCODE | LOCKREL_AFSID |
3239 LOCKREL_TIMESTAMP, &tst);
3245 ubik_VL_ReleaseLock(cellHandle->vos, 0,
3246 elem.ids[RWVOL], RWVOL,
3247 LOCKREL_OPCODE | LOCKREL_AFSID |
3253 } /* else update the existing entry */
3255 } /* End of while(1) */
3263 /*synchronise vldb with the file server <aserver> and <apart>(if flags=1).
3264 *else synchronise with all the valid partitions on <aserver>
3267 UV_SyncVldb(afs_cell_handle_p cellHandle, struct rx_connection *server,
3268 afs_int32 apart, int flags, int force, afs_status_p st)
3271 afs_status_t tst = 0;
3274 volEntries volumeInfo;
3276 struct qHead myQueue;
3277 struct partList PartList;
3282 /*this hints the stub to allocate space */
3283 volumeInfo.volEntries_val = (volintInfo *) 0;
3284 volumeInfo.volEntries_len = 0;
3286 if (!flags) { /*generate all the valid partitions */
3287 UV_ListPartitions(server, &PartList, &cnt, &tst);
3289 goto fail_UV_SyncVldb;
3292 PartList.partId[0] = apart;
3296 for (i = 0; i < cnt; i++) {
3297 apart = PartList.partId[i];
3298 /*this hints the stub to allocate space */
3299 volumeInfo.volEntries_val = (volintInfo *) 0;
3300 volumeInfo.volEntries_len = 0;
3301 tst = AFSVolListVolumes(server, apart, 1, &volumeInfo);
3303 goto fail_UV_SyncVldb;
3305 count = volumeInfo.volEntries_len;
3306 pntr = volumeInfo.volEntries_val;
3308 if (!vos_PartitionIdToName(apart, pname, &tst)) {
3309 goto fail_UV_SyncVldb;
3311 /*collect all vol entries by their parentid */
3312 tst = GroupEntries(server, pntr, count, &myQueue, apart);
3315 if (volumeInfo.volEntries_val) {
3316 /*free the space allocated by the stub */
3317 free(volumeInfo.volEntries_val);
3318 volumeInfo.volEntries_val = 0;
3322 tst = ProcessEntries(cellHandle, &myQueue, server, apart, force);
3324 tst = VOLSERFAILEDOP;
3325 if (volumeInfo.volEntries_val) {
3326 /*free the space allocated by the stub */
3327 free(volumeInfo.volEntries_val);
3328 volumeInfo.volEntries_val = 0;
3335 tst = VOLSERFAILEDOP;
3336 } /* thru all partitions */
3341 if (volumeInfo.volEntries_val)
3342 free(volumeInfo.volEntries_val);
3355 CheckVldbRWBK(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3356 afs_int32 * modified, afs_status_p st)
3359 afs_status_t tst = 0;
3365 idx = Lp_GetRwIndex(cellHandle, entry, 0);
3367 /* Check to see if the RW volume exists and set the RW_EXISTS
3370 if (idx == -1) { /* Did not find a RW entry */
3371 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
3372 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
3377 (cellHandle, entry->serverNumber[idx],
3378 entry->serverPartition[idx], entry->volumeId[RWVOL], &tst)) {
3379 if (!(entry->flags & RW_EXISTS)) { /* ... yet entry says RW does no
3381 entry->flags |= RW_EXISTS; /* ... so say RW does exist */
3384 } else if (tst == ENODEV) { /* RW volume does not exist */
3385 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists
3387 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist
3392 /* If VLDB says it didn't exist, then ignore error */
3393 if (entry->flags & RW_EXISTS) {
3394 goto fail_CheckVldbRWBK;
3399 /* Check to see if the BK volume exists and set the BACK_EXISTS
3400 * flag accordingly. idx already ponts to the RW entry.
3402 if (idx == -1) { /* Did not find a RW entry */
3403 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
3404 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
3407 } else { /* Found a RW entry */
3409 (cellHandle, entry->serverNumber[idx],
3410 entry->serverPartition[idx], entry->volumeId[BACKVOL], &tst)) {
3411 if (!(entry->flags & BACK_EXISTS)) { /* ... yet entry says BK does n
3413 entry->flags |= BACK_EXISTS; /* ... so say BK does exist */
3416 } else if (tst == ENODEV) { /* BK volume does not exist */
3417 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists
3419 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist
3424 /* If VLDB says it didn't exist, then ignore error */
3425 if (entry->flags & BACK_EXISTS) {
3426 goto fail_CheckVldbRWBK;
3431 /* If there is an idx but the BK and RW volumes no
3432 * longer exist, then remove the RW entry.
3434 if ((idx != -1) && !(entry->flags & RW_EXISTS)
3435 && !(entry->flags & BACK_EXISTS)) {
3436 Lp_SetRWValue(cellHandle, entry, entry->serverNumber[idx],
3437 entry->serverPartition[idx], 0L, 0L);
3446 *modified = modentry;
3456 CheckVldbRO(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3457 afs_int32 * modified, afs_status_p st)
3460 afs_status_t tst = 0;
3462 int foundro = 0, modentry = 0;
3467 /* Check to see if the RO volumes exist and set the RO_EXISTS
3470 for (idx = 0; idx < entry->nServers; idx++) {
3471 if (!(entry->serverFlags[idx] & ITSROVOL)) {
3472 continue; /* not a RO */
3476 (cellHandle, entry->serverNumber[idx],
3477 entry->serverPartition[idx], entry->volumeId[ROVOL], &tst)) {
3479 } else if (tst == ENODEV) { /* RW volume does not exist */
3480 Lp_SetROValue(cellHandle, entry, entry->serverNumber[idx],
3481 entry->serverPartition[idx], 0L, 0L);
3486 goto fail_CheckVldbRO;
3490 if (foundro) { /* A RO volume exists */
3491 if (!(entry->flags & RO_EXISTS)) { /* ... yet entry says RW does not e
3493 entry->flags |= RO_EXISTS; /* ... so say RW does exist */
3496 } else { /* A RO volume does not exist */
3497 if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
3498 entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
3507 *modified = modentry;
3515 /*ensure that <entry> matches with the info on file servers */
3517 CheckVldb(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3518 afs_int32 * modified, afs_status_p st)
3521 afs_status_t tst = 0;
3525 afs_int32 modentry = 0;
3526 afs_int32 delentry = 0;
3532 if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
3534 goto fail_CheckVldb;
3539 /* Check to see if the VLDB is ok without locking it (pass 1).
3540 * If it will change, then lock the VLDB entry, read it again,
3541 * then make the changes to it (pass 2).
3545 ubik_VL_SetLock(cellHandle->vos, 0, entry->volumeId[RWVOL],
3546 RWVOL, VLOP_DELETE);
3548 goto fail_CheckVldb;
3552 if (!aVLDB_GetEntryByID
3553 (cellHandle, entry->volumeId[RWVOL], RWVOL, entry, &tst)) {
3554 goto fail_CheckVldb;
3560 /* Check if the RW and BK entries are ok */
3561 if (!CheckVldbRWBK(cellHandle, entry, &modentry, &tst)) {
3562 goto fail_CheckVldb;
3564 if (modentry && (pass == 1))
3567 /* Check if the RO volumes entries are ok */
3568 if (!CheckVldbRO(cellHandle, entry, &modentry, &tst)) {
3569 goto fail_CheckVldb;
3571 if (modentry && (pass == 1))
3574 /* The VLDB entry has been updated. If it as been modified, then
3575 * write the entry back out the the VLDB.
3581 if (!(entry->flags & RW_EXISTS) && !(entry->flags & BACK_EXISTS)
3582 && !(entry->flags & RO_EXISTS)) {
3583 /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
3585 ubik_VL_DeleteEntry(cellHandle->vos, 0,
3586 entry->volumeId[RWVOL], RWVOL);
3588 goto fail_CheckVldb;
3592 /* Replace old entry with our new one */
3593 if (!VLDB_ReplaceEntry
3594 (cellHandle, entry->volumeId[RWVOL], RWVOL, entry,
3595 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP),
3597 goto fail_CheckVldb;
3610 ubik_VL_ReleaseLock(cellHandle->vos, 0,
3611 entry->volumeId[RWVOL], RWVOL,
3612 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
3625 /*synchronise <aserver> <apart>(if flags = 1) with the vldb .
3626 *if flags = 0, synchronise all the valid partitions on <aserver>*/
3628 UV_SyncServer(afs_cell_handle_p cellHandle, struct rx_connection *server,
3629 afs_int32 apart, int flags, afs_status_p st)
3632 afs_status_t tst = 0;
3633 afs_int32 code, vcode;
3635 afs_int32 nentries, tentries = 0;
3636 struct VldbListByAttributes attributes;
3637 nbulkentries arrayEntries;
3639 register struct nvldbentry *vllist;
3642 afs_int32 modified = 0;
3647 arrayEntries.nbulkentries_val = 0;
3649 /* Set up attributes to search VLDB */
3650 attributes.server = ntohl(rx_HostOf(rx_PeerOf(server)));
3651 attributes.Mask = VLLIST_SERVER;
3653 attributes.partition = apart;
3654 attributes.Mask |= VLLIST_PARTITION;
3657 for (si = 0; si != -1; si = nsi) {
3658 /*initialize to hint the stub to alloc space */
3659 memset(&arrayEntries, 0, sizeof(arrayEntries));
3660 if (!VLDB_ListAttributes
3661 (cellHandle, &attributes, &nentries, &arrayEntries, &tst)) {
3662 goto fail_UV_SyncServer;
3665 tentries += nentries;
3667 for (j = 0; j < nentries; j++) { /* process each entry */
3668 vllist = &arrayEntries.nbulkentries_val[j];
3669 if (!CheckVldb(cellHandle, vllist, &modified, &tst)) {
3674 if (arrayEntries.nbulkentries_val) {
3675 free(arrayEntries.nbulkentries_val);
3676 arrayEntries.nbulkentries_val = 0;
3683 if (arrayEntries.nbulkentries_val) {
3684 free(arrayEntries.nbulkentries_val);
3687 tst = VOLSERFAILEDOP;
3694 /*rename volume <oldname> to <newname>, changing the names of the related
3695 *readonly and backup volumes. This operation is also idempotent.
3696 *salvager is capable of recovering from rename operation stopping halfway.
3697 *to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
3699 UV_RenameVolume(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3700 const char *newname, afs_status_p st)
3703 afs_status_t tst = 0;
3704 afs_status_t etst = 0;
3705 afs_int32 rcode, error;
3707 char nameBuffer[256];
3709 struct rx_connection *aconn;
3713 aconn = (struct rx_connection *)0;
3717 tst = ubik_VL_SetLock(cellHandle->vos, 0, entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE); /*last param is dummy */
3719 goto fail_UV_RenameVolume;
3723 strncpy(entry->name, newname, VOLSER_OLDMAXVOLNAME);
3725 if (!VLDB_ReplaceEntry
3726 (cellHandle, entry->volumeId[RWVOL], RWVOL, entry, 0, &tst)) {
3727 goto fail_UV_RenameVolume;
3729 /*at this stage the intent to rename is recorded in the vldb, as far
3731 * is concerned, oldname is lost */
3732 if (entry->flags & RW_EXISTS) {
3733 index = Lp_GetRwIndex(cellHandle, entry, 0);
3734 if (index == -1) { /* there is a serious discrepancy */
3735 tst = VOLSERVLDB_ERROR;
3736 goto fail_UV_RenameVolume;
3739 UV_Bind(cellHandle, entry->serverNumber[index],
3740 AFSCONF_VOLUMEPORT);
3742 AFSVolTransCreate(aconn, entry->volumeId[RWVOL],
3743 entry->serverPartition[index], ITOffline, &tid);
3744 if (tst) { /*volume doesnot exist */
3745 goto fail_UV_RenameVolume;
3746 } else { /*volume exists, process it */
3749 AFSVolSetIdsTypes(aconn, tid, newname, RWVOL,
3750 entry->volumeId[RWVOL],
3751 entry->volumeId[ROVOL],
3752 entry->volumeId[BACKVOL]);
3754 tst = AFSVolEndTrans(aconn, tid, &rcode);
3757 goto fail_UV_RenameVolume;
3760 goto fail_UV_RenameVolume;
3764 rx_ReleaseCachedConnection(aconn);
3765 aconn = (struct rx_connection *)0;
3767 /*end rw volume processing */
3768 if (entry->flags & BACK_EXISTS) { /*process the backup volume */
3769 index = Lp_GetRwIndex(cellHandle, entry, 0);
3770 if (index == -1) { /* there is a serious discrepancy */
3771 tst = VOLSERVLDB_ERROR;
3772 goto fail_UV_RenameVolume;
3775 UV_Bind(cellHandle, entry->serverNumber[index],
3776 AFSCONF_VOLUMEPORT);
3778 AFSVolTransCreate(aconn, entry->volumeId[BACKVOL],
3779 entry->serverPartition[index], ITOffline, &tid);
3780 if (tst) { /*volume doesnot exist */
3781 goto fail_UV_RenameVolume;
3782 } else { /*volume exists, process it */
3783 if (strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)) {
3784 goto fail_UV_RenameVolume;
3786 strcpy(nameBuffer, newname);
3787 strcat(nameBuffer, ".backup");
3790 AFSVolSetIdsTypes(aconn, tid, nameBuffer, BACKVOL,
3791 entry->volumeId[RWVOL], 0, 0);
3793 tst = AFSVolEndTrans(aconn, tid, &rcode);
3796 goto fail_UV_RenameVolume;
3799 goto fail_UV_RenameVolume;
3802 } /* end backup processing */
3804 rx_ReleaseCachedConnection(aconn);
3805 aconn = (struct rx_connection *)0;
3806 if (entry->flags & RO_EXISTS) { /*process the ro volumes */
3807 for (i = 0; i < entry->nServers; i++) {
3808 if (entry->serverFlags[i] & ITSROVOL) {
3810 UV_Bind(cellHandle, entry->serverNumber[i],
3811 AFSCONF_VOLUMEPORT);
3813 AFSVolTransCreate(aconn, entry->volumeId[ROVOL],
3814 entry->serverPartition[i], ITOffline,
3816 if (tst) { /*volume doesnot exist */
3817 goto fail_UV_RenameVolume;
3818 } else { /*volume exists, process it */
3819 strcpy(nameBuffer, newname);
3820 strcat(nameBuffer, ".readonly");
3821 if (strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)) {
3822 goto fail_UV_RenameVolume;
3825 AFSVolSetIdsTypes(aconn, tid, nameBuffer, ROVOL,
3826 entry->volumeId[RWVOL], 0, 0);
3828 tst = AFSVolEndTrans(aconn, tid, &rcode);
3831 goto fail_UV_RenameVolume;
3834 goto fail_UV_RenameVolume;
3838 rx_ReleaseCachedConnection(aconn);
3839 aconn = (struct rx_connection *)0;
3845 fail_UV_RenameVolume:
3849 ubik_VL_ReleaseLock(cellHandle->vos, 0,
3850 entry->volumeId[RWVOL], RWVOL,
3851 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3858 etst = AFSVolEndTrans(aconn, tid, &rcode);
3865 rx_ReleaseCachedConnection(aconn);
3873 /*group all the volume entries on< apart >by their parentid or by their ids'
3874 *if the volume is rw. <count> is the number of entries to be processesd.
3875 *<pntr> points to the first entry.< myQueue> is the queue with entries
3878 GroupEntries(struct rx_connection *server, volintInfo * pntr, afs_int32 count,
3879 struct qHead *myQueue, afs_int32 apart)
3881 struct aqueue *qPtr;
3883 afs_int32 curId, code;
3885 afs_int32 error = 0;
3891 for (i = 0; i < count; i++) { /*process each entry */
3892 if (pntr->status) { /* entry is valid */
3893 if (pntr->type == RWVOL)
3894 curId = pntr->volid;
3896 curId = pntr->parentID;
3897 Lp_QScan(myQueue, curId, &success, &qPtr, 0);
3898 if (success) { /*entry exists in the queue */
3899 if (pntr->type == RWVOL) {
3900 /*check if the rw exists already, if so hang on the
3901 * later version if the present version is ok */
3902 if (qPtr->isValid[RWVOL]) {
3903 /*this should not happen, there is a serious error here */
3905 error = VOLSERMULTIRWVOL;
3907 qPtr->isValid[RWVOL] = 1;
3908 qPtr->copyDate[RWVOL] = pntr->copyDate;
3909 if (!qPtr->isValid[BACKVOL])
3910 qPtr->ids[BACKVOL] = pntr->backupID;
3911 if (!qPtr->isValid[ROVOL])
3912 qPtr->ids[ROVOL] = pntr->cloneID;
3914 } else if (pntr->type == BACKVOL) {
3915 if (qPtr->isValid[BACKVOL]) {
3916 /*do different checks, delete superflous volume */
3917 if (qPtr->copyDate[BACKVOL] > pntr->copyDate) {
3918 /*delete the present volume . */
3920 CheckAndDeleteVolume(server, apart, 0,
3928 /*delete the older volume after making sure, current one is ok */
3930 CheckAndDeleteVolume(server, apart,
3932 qPtr->ids[BACKVOL]);
3938 qPtr->copyDate[BACKVOL] = pntr->copyDate;
3939 qPtr->ids[BACKVOL] = pntr->volid;
3943 qPtr->isValid[BACKVOL] = 1;
3944 qPtr->ids[BACKVOL] = pntr->volid;
3945 qPtr->copyDate[BACKVOL] = pntr->copyDate;
3947 } else if (pntr->type == ROVOL) {
3948 if (qPtr->isValid[ROVOL]) {
3949 /*do different checks, delete superflous volume */
3950 if (qPtr->copyDate[ROVOL] > pntr->copyDate) {
3951 /*delete the present volume . */
3954 CheckAndDeleteVolume(server, apart, 0,
3961 /*delete the older volume after making sure, current one is ok */
3963 CheckAndDeleteVolume(server, apart,
3971 qPtr->copyDate[ROVOL] = pntr->copyDate;
3972 qPtr->ids[ROVOL] = pntr->volid;
3976 qPtr->isValid[ROVOL] = 1;
3977 qPtr->ids[ROVOL] = pntr->volid;
3978 qPtr->copyDate[ROVOL] = pntr->copyDate;
3982 error = VOLSERBADOP;
3984 } else { /*create a fresh entry */
3985 qPtr = (struct aqueue *)malloc(sizeof(struct aqueue));
3986 if (pntr->type == RWVOL) {
3987 qPtr->isValid[RWVOL] = 1;
3988 qPtr->isValid[BACKVOL] = 0;
3989 qPtr->isValid[ROVOL] = 0;
3990 qPtr->ids[RWVOL] = pntr->volid;
3991 qPtr->ids[BACKVOL] = pntr->backupID;
3992 qPtr->ids[ROVOL] = pntr->cloneID;
3993 qPtr->copyDate[RWVOL] = pntr->copyDate;
3994 strncpy(qPtr->name, pntr->name, VOLSER_OLDMAXVOLNAME);
3996 } else if (pntr->type == BACKVOL) {
3997 qPtr->isValid[RWVOL] = 0;
3998 qPtr->isValid[BACKVOL] = 1;
3999 qPtr->isValid[ROVOL] = 0;
4000 qPtr->ids[RWVOL] = pntr->parentID;
4001 qPtr->ids[BACKVOL] = pntr->volid;
4002 qPtr->ids[ROVOL] = 0;
4003 qPtr->copyDate[BACKVOL] = pntr->copyDate;
4004 vsu_ExtractName(qPtr->name, pntr->name);
4006 } else if (pntr->type == ROVOL) {
4007 qPtr->isValid[RWVOL] = 0;
4008 qPtr->isValid[BACKVOL] = 0;
4009 qPtr->isValid[ROVOL] = 1;
4010 qPtr->ids[RWVOL] = pntr->parentID;
4011 qPtr->ids[BACKVOL] = 0;
4012 qPtr->ids[ROVOL] = pntr->volid;
4013 qPtr->copyDate[ROVOL] = pntr->copyDate;
4014 vsu_ExtractName(qPtr->name, pntr->name);
4018 Lp_QAdd(myQueue, qPtr);
4020 pntr++; /*get next entry */
4030 /*report on all the active transactions on volser */
4032 UV_VolserStatus(struct rx_connection *server, transDebugInfo ** rpntr,
4033 afs_int32 * rcount, afs_status_p st)
4036 afs_status_t tst = 0;
4037 transDebugEntries transInfo;
4039 transInfo.transDebugEntries_val = (transDebugInfo *) 0;
4040 transInfo.transDebugEntries_len = 0;
4041 tst = AFSVolMonitor(server, &transInfo);
4043 goto fail_UV_VolserStatus;
4046 *rcount = transInfo.transDebugEntries_len;
4047 *rpntr = transInfo.transDebugEntries_val;
4050 fail_UV_VolserStatus:
4053 if (transInfo.transDebugEntries_val) {
4054 free(transInfo.transDebugEntries_val);
4064 /*delete the volume without interacting with the vldb */
4066 UV_VolumeZap(afs_cell_handle_p cellHandle, struct rx_connection *server,
4067 unsigned int partition, unsigned int volumeId, afs_status_p st)
4069 afs_int32 rcode, ttid, error, code;
4071 afs_status_t tst = 0;
4077 tst = AFSVolTransCreate(server, volumeId, partition, ITOffline, &ttid);
4079 tst = AFSVolDeleteVolume(server, ttid);
4081 tst = AFSVolEndTrans(server, ttid, &rcode);
4089 * We failed to delete the volume, but we still need
4090 * to end the transaction.
4092 AFSVolEndTrans(server, ttid, &rcode);
4104 UV_SetVolume(struct rx_connection *server, afs_int32 partition,
4105 afs_int32 volid, afs_int32 transflag, afs_int32 setflag,
4106 unsigned int sleepTime, afs_status_p st)
4109 afs_status_t tst = 0;
4110 afs_status_t etst = 0;
4114 tst = AFSVolTransCreate(server, volid, partition, transflag, &tid);
4116 goto fail_UV_SetVolume;
4119 tst = AFSVolSetFlags(server, tid, setflag);
4121 goto fail_UV_SetVolume;
4132 etst = AFSVolEndTrans(server, tid, &rcode);
4133 /* FIXME: this looks like a typo */
4136 tst = (etst ? etst : rcode);