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>
27 #include "lockprocs.h"
28 #include "../adminutil/afs_AdminInternal.h"
29 #include <afs/afs_AdminErrors.h>
30 #include "afs_vosAdmin.h"
39 static afs_int32 GroupEntries(struct rx_connection *server, volintInfo * pntr, afs_int32 count,
40 struct qHead *myQueue, afs_int32 apart);
44 afs_int32 vldbEntryIndex;
47 static struct rx_connection *
48 UV_Bind(afs_cell_handle_p cellHandle, afs_int32 aserver, afs_int32 port)
50 return rx_GetCachedConnection(htonl(aserver), htons(port), VOLSERVICE_ID,
51 cellHandle->tokens->afs_sc[cellHandle->
54 cellHandle->tokens->sc_index);
58 /* if <okvol> is allright(indicated by beibg able to
59 * start a transaction, delete the <delvol> */
61 CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
62 afs_uint32 okvol, afs_uint32 delvol)
64 afs_int32 error, code, tid, rcode;
70 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
73 code = AFSVolDeleteVolume(aconn, tid);
76 code = AFSVolEndTrans(aconn, tid, &rcode);
83 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline, &tid);
85 code = AFSVolEndTrans(aconn, tid, &rcode);
90 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
93 code = AFSVolDeleteVolume(aconn, tid);
96 code = AFSVolEndTrans(aconn, tid, &rcode);
107 /* forcibly remove a volume. Very dangerous call */
109 UV_NukeVolume(afs_cell_handle_p cellHandle, struct rx_connection *server,
110 unsigned int partition, afs_uint32 volumeId, afs_status_p st)
113 afs_status_t tst = 0;
115 tst = AFSVolNukeVolume(server, partition, volumeId);
127 /* create a volume, given a server, partition number, volume name --> sends
128 * back new vol id in <anewid>*/
130 UV_CreateVolume(afs_cell_handle_p cellHandle, struct rx_connection *server,
131 unsigned int partition, char *volumeName,
132 unsigned int quota, afs_uint32 *volumeId, afs_status_p st)
135 afs_status_t tst = 0;
138 struct nvldbentry entry;
139 struct volintInfo tstatus;
141 memset(&tstatus, 0, sizeof(tstatus));
143 tstatus.maxquota = quota;
145 /* next the next 3 available ids from the VLDB */
146 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 3, volumeId);
148 goto fail_UV_CreateVolume;
152 AFSVolCreateVolume(server, partition, volumeName, volser_RW, 0,
155 goto fail_UV_CreateVolume;
158 AFSVolSetInfo(server, tid, &tstatus);
160 tst = AFSVolSetFlags(server, tid, 0);
162 goto fail_UV_CreateVolume;
165 /* set up the vldb entry for this volume */
166 strncpy(entry.name, volumeName, VOLSER_OLDMAXVOLNAME);
168 entry.serverNumber[0] = ntohl(rx_HostOf(rx_PeerOf(server)));
169 entry.serverPartition[0] = partition;
170 entry.flags = RW_EXISTS;
171 entry.serverFlags[0] = ITSRWVOL;
172 entry.volumeId[RWVOL] = *volumeId;
173 entry.volumeId[ROVOL] = *volumeId + 1;
174 entry.volumeId[BACKVOL] = *volumeId + 2;
177 if (!VLDB_CreateEntry(cellHandle, &entry, &tst)) {
178 AFSVolDeleteVolume(server, tid);
179 goto fail_UV_CreateVolume;
182 tst = AFSVolEndTrans(server, tid, &rcode);
185 goto fail_UV_CreateVolume;
189 fail_UV_CreateVolume:
192 AFSVolEndTrans(server, tid, &rcode);
202 /* Delete the volume <volid>on <aserver> <apart>
203 * the physical entry gets removed from the vldb only if the ref count
207 UV_DeleteVolume(afs_cell_handle_p cellHandle, struct rx_connection *server,
208 unsigned int partition, afs_uint32 volumeId,
212 afs_status_t tst = 0;
213 afs_status_t temp = 0;
214 int serverAddr = ntohl(rx_HostOf(rx_PeerOf(server)));
218 struct nvldbentry entry;
220 afs_int32 avoltype = -1, vtype;
221 int notondisk = 0, notinvldb = 0;
223 /* Find and read the VLDB entry for this volume */
225 ubik_VL_SetLock(cellHandle->vos, 0, volumeId, avoltype,
228 if (tst != VL_NOENT) {
229 goto fail_UV_DeleteVolume;
235 if (!aVLDB_GetEntryByID(cellHandle, volumeId, avoltype, &entry, &tst)) {
236 goto fail_UV_DeleteVolume;
241 /* Whether volume is in the VLDB or not. Delete the volume on disk */
242 tst = AFSVolTransCreate(server, volumeId, partition, ITOffline, &ttid);
247 goto fail_UV_DeleteVolume;
250 tst = AFSVolDeleteVolume(server, ttid);
252 goto fail_UV_DeleteVolume;
254 tst = AFSVolEndTrans(server, ttid, &rcode);
255 tst = (tst ? tst : rcode);
258 goto fail_UV_DeleteVolume;
263 goto fail_UV_DeleteVolume;
266 if (volumeId == entry.volumeId[BACKVOL]) {
267 if (!(entry.flags & BACK_EXISTS)
268 || !Lp_Match(cellHandle, &entry, serverAddr, partition, &tst)) {
270 goto fail_UV_DeleteVolume;
273 entry.flags &= ~BACK_EXISTS;
277 else if (volumeId == entry.volumeId[ROVOL]) {
278 if (!Lp_ROMatch(cellHandle, &entry, serverAddr, partition, &tst)) {
280 goto fail_UV_DeleteVolume;
283 Lp_SetROValue(cellHandle, &entry, serverAddr, partition, 0, 0);
285 if (!Lp_ROMatch(cellHandle, &entry, 0, 0, &tst)) {
286 entry.flags &= ~RO_EXISTS;
291 else if (volumeId == entry.volumeId[RWVOL]) {
292 if (!(entry.flags & RW_EXISTS)
293 || !Lp_Match(cellHandle, &entry, serverAddr, partition, &tst)) {
295 goto fail_UV_DeleteVolume;
298 /* Delete backup if it exists */
300 AFSVolTransCreate(server, entry.volumeId[BACKVOL], partition,
303 tst = AFSVolDeleteVolume(server, ttid);
305 goto fail_UV_DeleteVolume;
307 tst = AFSVolEndTrans(server, ttid, &rcode);
309 tst = (tst ? tst : rcode);
311 goto fail_UV_DeleteVolume;
315 Lp_SetRWValue(cellHandle, &entry, serverAddr, partition, 0L, 0L);
317 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
323 notinvldb = 2; /* Not found on this server and partition */
324 goto fail_UV_DeleteVolume;
327 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
328 tst = ubik_VL_DeleteEntry(cellHandle->vos, 0, volumeId, vtype);
330 goto fail_UV_DeleteVolume;
333 if (!VLDB_ReplaceEntry
334 (cellHandle, volumeId, vtype, &entry,
335 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP), &tst)) {
336 goto fail_UV_DeleteVolume;
342 fail_UV_DeleteVolume:
344 if (notondisk && notinvldb) {
346 tst = ADMVOSVOLUMENOEXIST;
350 temp = AFSVolEndTrans(server, ttid, &rcode);
351 temp = (temp ? temp : rcode);
360 ubik_VL_ReleaseLock(cellHandle->vos, 0, volumeId, -1,
361 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
374 #define ONERR(ec, es, ep) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto mfail; }
376 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
377 * <atopart>. The operation is almost idempotent
381 UV_MoveVolume(afs_cell_handle_p cellHandle, afs_uint32 afromvol,
382 afs_int32 afromserver, afs_int32 afrompart, afs_int32 atoserver,
383 afs_int32 atopart, afs_status_p st)
386 afs_status_t tst = 0;
387 afs_status_t etst = 0;
388 struct rx_connection *toconn, *fromconn;
389 afs_int32 fromtid, totid, clonetid;
392 char tmpName[VOLSER_MAXVOLNAME + 1];
395 struct restoreCookie cookie;
396 afs_uint32 newVol, volid, backupId;
397 struct volser_status tstatus;
398 struct destServer destination;
400 struct nvldbentry entry;
404 afs_int32 store_flags;
406 #ifdef ENABLE_BUGFIX_1165
407 volEntries volumeInfo;
408 struct volintInfo *infop = 0;
412 fromconn = (struct rx_connection *)0;
413 toconn = (struct rx_connection *)0;
423 if (!aVLDB_GetEntryByID(cellHandle, afromvol, -1, &entry, &tst)) {
424 goto fail_UV_MoveVolume;
427 if (entry.volumeId[RWVOL] != afromvol) {
428 tst = ADMVOSVOLUMEMOVERWONLY;
429 goto fail_UV_MoveVolume;
433 ubik_VL_SetLock(cellHandle->vos, 0, afromvol, RWVOL, VLOP_MOVE);
435 goto fail_UV_MoveVolume;
439 if (!aVLDB_GetEntryByID(cellHandle, afromvol, RWVOL, &entry, &tst)) {
440 goto fail_UV_MoveVolume;
443 backupId = entry.volumeId[BACKVOL];
445 if (!Lp_Match(cellHandle, &entry, afromserver, afrompart, &tst)) {
446 /* the from server and partition do not exist in the vldb entry corresponding to volid */
447 if (!Lp_Match(cellHandle, &entry, atoserver, atopart, &tst)) {
448 /* the to server and partition do not exist in the vldb entry corresponding to volid */
450 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
451 (LOCKREL_OPCODE | LOCKREL_AFSID |
454 goto fail_UV_MoveVolume;
456 tst = VOLSERVOLMOVED;
457 goto fail_UV_MoveVolume;
460 /* delete the volume afromvol on src_server */
461 /* from-info does not exist but to-info does =>
462 * we have already done the move, but the volume
463 * may still be existing physically on from fileserver
465 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
470 AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline,
472 if (!tst) { /* volume exists - delete it */
474 AFSVolSetFlags(fromconn, fromtid,
475 VTDeleteOnSalvage | VTOutOfService);
477 goto fail_UV_MoveVolume;
480 tst = AFSVolDeleteVolume(fromconn, fromtid);
482 goto fail_UV_MoveVolume;
485 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
490 goto fail_UV_MoveVolume;
494 /*delete the backup volume now */
497 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
499 if (!tst) { /* backup volume exists - delete it */
501 AFSVolSetFlags(fromconn, fromtid,
502 VTDeleteOnSalvage | VTOutOfService);
504 goto fail_UV_MoveVolume;
507 tst = AFSVolDeleteVolume(fromconn, fromtid);
509 goto fail_UV_MoveVolume;
512 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
517 goto fail_UV_MoveVolume;
523 goto fail_UV_MoveVolume;
526 /* From-info matches the vldb info about volid,
527 * its ok start the move operation, the backup volume
528 * on the old site is deleted in the process
530 if (afrompart == atopart) {
531 if (!VLDB_IsSameAddrs
532 (cellHandle, afromserver, atoserver, &same, &tst)) {
533 goto fail_UV_MoveVolume;
536 tst = VOLSERVOLMOVED;
537 goto fail_UV_MoveVolume;
542 toconn = UV_Bind(cellHandle, atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
543 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
544 fromtid = totid = 0; /* initialize to uncreated */
547 * clone the read/write volume locally.
550 tst = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
552 goto fail_UV_MoveVolume;
557 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &newVol);
559 goto fail_UV_MoveVolume;
562 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
563 strcpy(vname, "move-clone-temp");
564 tst = AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &newVol);
566 goto fail_UV_MoveVolume;
569 /* lookup the name of the volume we just cloned */
571 tst = AFSVolGetName(fromconn, fromtid, &volName);
573 goto fail_UV_MoveVolume;
577 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
582 goto fail_UV_MoveVolume;
586 * Create the destination volume
590 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
592 goto fail_UV_MoveVolume;
594 tst = AFSVolSetFlags(fromconn, clonetid, VTDeleteOnSalvage | VTOutOfService); /*redundant */
596 goto fail_UV_MoveVolume;
599 /* remember time from which we've dumped the volume */
600 tst = AFSVolGetStatus(fromconn, clonetid, &tstatus);
602 goto fail_UV_MoveVolume;
605 fromDate = tstatus.creationDate - CLOCKSKEW;
607 #ifdef ENABLE_BUGFIX_1165
609 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
610 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
611 * don't use this information...
613 volumeInfo.volEntries_val = (volintInfo *) 0; /*this hints the stub to allocate space */
614 volumeInfo.volEntries_len = 0;
615 tst = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
617 goto fail_UV_MoveVolume;
620 infop = (volintInfo *) volumeInfo.volEntries_val;
621 infop->maxquota = -1; /* Else it will replace the default quota */
624 /* create a volume on the target machine */
626 tst = AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
627 if (!tst) { /*delete the existing volume */
629 tst = AFSVolDeleteVolume(toconn, totid);
631 goto fail_UV_MoveVolume;
634 tst = AFSVolEndTrans(toconn, totid, &rcode);
639 goto fail_UV_MoveVolume;
645 AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &volid,
648 goto fail_UV_MoveVolume;
651 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
655 tst = AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
657 goto fail_UV_MoveVolume;
661 * Now dump the clone to the new volume
664 destination.destHost = atoserver;
665 destination.destPort = AFSCONF_VOLUMEPORT;
666 destination.destSSID = 1;
668 /* Copy the clone to the new volume */
669 strncpy(cookie.name, tmpName, VOLSER_OLDMAXVOLNAME);
671 cookie.parent = entry.volumeId[RWVOL];
673 tst = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
675 goto fail_UV_MoveVolume;
678 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
683 goto fail_UV_MoveVolume;
687 * reattach to the main-line volume, and incrementally dump it.
690 tst = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
692 goto fail_UV_MoveVolume;
695 /* now do the incremental */
697 AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
700 goto fail_UV_MoveVolume;
703 /* now adjust the flags so that the new volume becomes official */
704 tst = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
706 goto fail_UV_MoveVolume;
709 tst = AFSVolSetFlags(toconn, totid, 0);
711 goto fail_UV_MoveVolume;
713 #ifdef ENABLE_BUGFIX_1165
714 tst = AFSVolSetInfo(toconn, totid, infop);
716 goto fail_UV_MoveVolume;
720 /* put new volume online */
721 tst = AFSVolEndTrans(toconn, totid, &rcode);
726 goto fail_UV_MoveVolume;
729 Lp_SetRWValue(cellHandle, &entry, afromserver, afrompart, atoserver,
731 store_flags = entry.flags;
732 entry.flags &= ~BACK_EXISTS;
734 if (!VLDB_ReplaceEntry
735 (cellHandle, afromvol, -1, &entry,
736 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP), &tst)) {
737 goto fail_UV_MoveVolume;
739 entry.flags = store_flags;
742 if (atoserver != afromserver) {
743 /* set forwarding pointer for moved volumes */
744 tst = AFSVolSetForwarding(fromconn, fromtid, htonl(atoserver));
746 goto fail_UV_MoveVolume;
750 tst = AFSVolDeleteVolume(fromconn, fromtid); /* zap original volume */
752 goto fail_UV_MoveVolume;
755 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
760 goto fail_UV_MoveVolume;
763 /* Delete the backup volume on the original site */
765 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
768 AFSVolSetFlags(fromconn, fromtid,
769 VTDeleteOnSalvage | VTOutOfService);
771 goto fail_UV_MoveVolume;
774 tst = AFSVolDeleteVolume(fromconn, fromtid);
776 goto fail_UV_MoveVolume;
779 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
784 goto fail_UV_MoveVolume;
788 tst = 0; /* no backup volume? that's okay */
793 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
795 goto fail_UV_MoveVolume;
798 /* now delete the clone */
800 tst = AFSVolDeleteVolume(fromconn, clonetid);
802 goto fail_UV_MoveVolume;
805 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
810 goto fail_UV_MoveVolume;
816 /* normal cleanup code */
820 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
821 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
829 etst = AFSVolEndTrans(fromconn, fromtid, &rcode);
832 tst = (etst ? etst : rcode);
837 etst = AFSVolEndTrans(fromconn, clonetid, &rcode);
840 tst = (etst ? etst : rcode);
845 etst = AFSVolEndTrans(toconn, totid, &rcode);
848 tst = (etst ? etst : rcode);
853 #ifdef ENABLE_BUGFIX_1165
858 rx_ReleaseCachedConnection(fromconn);
860 rx_ReleaseCachedConnection(toconn);
868 /* come here only when the sky falls */
872 /* unlock VLDB entry */
874 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
875 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
878 AFSVolEndTrans(fromconn, clonetid, &rcode);
880 AFSVolEndTrans(toconn, totid, &rcode);
881 if (fromtid) { /* put it on-line */
882 AFSVolSetFlags(fromconn, fromtid, 0);
883 AFSVolEndTrans(fromconn, fromtid, &rcode);
886 if (!aVLDB_GetEntryByID(cellHandle, afromvol, -1, &entry, &tst)) {
890 /* Delete either the volume on the source location or the target location.
891 * If the vldb entry still points to the source location, then we know the
892 * volume move didn't finish so we remove the volume from the target
893 * location. Otherwise, we remove the volume from the source location.
895 if (Lp_Match(cellHandle, &entry, afromserver, afrompart, &tst)) { /* didn't move - delete target volume */
897 if (volid && toconn) {
899 AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
901 AFSVolSetFlags(toconn, totid,
902 VTDeleteOnSalvage | VTOutOfService);
903 AFSVolDeleteVolume(toconn, totid);
904 AFSVolEndTrans(toconn, totid, &rcode);
908 /* put source volume on-line */
911 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
914 AFSVolSetFlags(fromconn, fromtid, 0);
915 AFSVolEndTrans(fromconn, fromtid, &rcode);
918 } else { /* yep, move complete */
919 /* delete backup volume */
922 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
925 AFSVolSetFlags(fromconn, fromtid,
926 VTDeleteOnSalvage | VTOutOfService);
927 AFSVolDeleteVolume(fromconn, fromtid);
928 AFSVolEndTrans(fromconn, fromtid, &rcode);
931 /* delete source volume */
933 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
936 AFSVolSetFlags(fromconn, fromtid,
937 VTDeleteOnSalvage | VTOutOfService);
938 if (atoserver != afromserver)
939 AFSVolSetForwarding(fromconn, fromtid, htonl(atoserver));
940 AFSVolDeleteVolume(fromconn, fromtid);
941 AFSVolEndTrans(fromconn, fromtid, &rcode);
946 /* common cleanup - delete local clone */
949 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
952 AFSVolDeleteVolume(fromconn, clonetid);
953 AFSVolEndTrans(fromconn, clonetid, &rcode);
957 /* unlock VLDB entry */
958 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
959 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
961 done: /* routine cleanup */
964 #ifdef ENABLE_BUGFIX_1165
969 rx_ReleaseCachedConnection(fromconn);
971 rx_ReleaseCachedConnection(toconn);
979 /* Make a new backup of volume <avolid> on <aserver> and <apart>
980 * if one already exists, update it
984 UV_BackupVolume(afs_cell_handle_p cellHandle, afs_int32 aserver,
985 afs_int32 apart, afs_uint32 avolid, afs_status_p st)
988 afs_status_t tst = 0, temp = 0;
989 afs_int32 ttid = 0, btid = 0;
992 char vname[VOLSER_MAXVOLNAME + 1];
993 struct nvldbentry entry;
994 int vldblocked = 0, vldbmod = 0, backexists = 1;
995 struct rx_connection *aconn = UV_Bind(cellHandle, aserver,
999 /* the calls to VLDB will succeed only if avolid is a RW volume,
1000 * since we are following the RW hash chain for searching */
1001 if (!aVLDB_GetEntryByID(cellHandle, avolid, RWVOL, &entry, &tst)) {
1002 goto fail_UV_BackupVolume;
1005 /* These operations require the VLDB be locked since it means the VLDB
1006 * will change or the vldb is already locked.
1008 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
1009 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
1010 (entry.volumeId[BACKVOL] == INVALID_BID)) {
1011 /* no assigned backup volume id */
1014 ubik_VL_SetLock(cellHandle->vos, 0, avolid, RWVOL,
1017 goto fail_UV_BackupVolume;
1021 /* Reread the vldb entry */
1022 if (!aVLDB_GetEntryByID(cellHandle, avolid, RWVOL, &entry, &tst)) {
1023 goto fail_UV_BackupVolume;
1027 if (!ISNAMEVALID(entry.name)) {
1028 tst = VOLSERBADNAME;
1029 goto fail_UV_BackupVolume;
1032 backupID = entry.volumeId[BACKVOL];
1033 if (backupID == INVALID_BID) {
1034 /* Get a backup volume id from the VLDB and update the vldb
1037 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &backupID);
1039 goto fail_UV_BackupVolume;
1041 entry.volumeId[BACKVOL] = backupID;
1045 /* Test to see if the backup volume exists by trying to create
1046 * a transaction on the backup volume. We've assumed the backup exists.
1048 tst = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1050 if (tst != VNOVOL) {
1051 goto fail_UV_BackupVolume;
1053 backexists = 0; /* backup volume does not exist */
1056 tst = AFSVolEndTrans(aconn, btid, &rcode);
1059 tst = (tst ? tst : rcode);
1060 goto fail_UV_BackupVolume;
1064 /* Now go ahead and try to clone the RW volume.
1065 * First start a transaction on the RW volume
1067 tst = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
1069 goto fail_UV_BackupVolume;
1072 /* Clone or reclone the volume, depending on whether the backup
1073 * volume exists or not
1076 tst = AFSVolReClone(aconn, ttid, backupID);
1078 goto fail_UV_BackupVolume;
1081 strcpy(vname, entry.name);
1082 strcat(vname, ".backup");
1084 tst = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID);
1086 goto fail_UV_BackupVolume;
1090 /* End transaction on the RW volume */
1091 tst = AFSVolEndTrans(aconn, ttid, &rcode);
1094 tst = (tst ? tst : rcode);
1095 goto fail_UV_BackupVolume;
1098 /* Mork vldb as backup exists */
1099 if (!(entry.flags & BACK_EXISTS)) {
1100 entry.flags |= BACK_EXISTS;
1104 /* Now go back to the backup volume and bring it on line */
1105 tst = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1107 goto fail_UV_BackupVolume;
1110 tst = AFSVolSetFlags(aconn, btid, 0);
1112 goto fail_UV_BackupVolume;
1115 tst = AFSVolEndTrans(aconn, btid, &rcode);
1118 tst = (tst ? tst : rcode);
1119 goto fail_UV_BackupVolume;
1123 /* Will update the vldb below */
1125 fail_UV_BackupVolume:
1128 temp = AFSVolEndTrans(aconn, ttid, &rcode);
1129 if (temp || rcode) {
1131 tst = (temp ? temp : rcode);
1136 temp = AFSVolEndTrans(aconn, btid, &rcode);
1137 if (temp || rcode) {
1139 tst = (temp ? temp : rcode);
1143 /* Now update the vldb - if modified */
1146 if (!VLDB_ReplaceEntry
1147 (cellHandle, avolid, RWVOL, &entry,
1148 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP),
1156 ubik_VL_ReleaseLock(cellHandle->vos, 0, avolid, RWVOL,
1157 (LOCKREL_OPCODE | LOCKREL_AFSID |
1158 LOCKREL_TIMESTAMP));
1168 rx_ReleaseCachedConnection(aconn);
1178 DelVol(struct rx_connection *conn, afs_uint32 vid, afs_int32 part,
1181 afs_int32 acode, ccode, rcode, tid;
1182 ccode = rcode = tid = 0;
1184 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
1185 if (!acode) { /* It really was there */
1186 acode = AFSVolDeleteVolume(conn, tid);
1187 ccode = AFSVolEndTrans(conn, tid, &rcode);
1195 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
1196 #define ERROREXIT(ec) { error = (ec); goto rfail; }
1198 #if 0 /* doesn't appear to be used, why compile it */
1200 CloneVol(afs_cell_handle_p cellHandle, struct rx_connection *conn,
1201 afs_uint32 rwvid, afs_int32 part, afs_uint32 * rovidp, int nottemp,
1202 struct nvldbentry *entry, afs_int32 * vidCreateDate, afs_status_p st)
1205 afs_status_t tst = 0, etst = 0;
1206 afs_int32 rcode = 0, tid = 0;
1207 struct volser_status volstatus;
1210 /* Begin transaction on RW volume marking it busy (clients will wait) */
1211 tst = AFSVolTransCreate(conn, rwvid, part, ITBusy, &tid);
1216 /* Get the RO volume id. Allocate a new one if need to */
1217 *rovidp = entry->volumeId[ROVOL];
1218 if (*rovidp == INVALID_BID) {
1219 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, rovidp);
1224 entry->volumeId[ROVOL] = *rovidp;
1227 /* If we are creating the ro clone, what are we calling it.
1228 * Depends on whether its a temporary clone or not.
1231 strcpy(vname, entry->name);
1232 strcat(vname, ".readonly");
1234 strcpy(vname, "readonly-clone-temp"); /* Should be unique? */
1237 /* Create the new clone. If it exists, then reclone it */
1238 tst = AFSVolClone(conn, tid, 0, readonlyVolume, vname, rovidp);
1239 if (tst == VVOLEXISTS) {
1240 tst = AFSVolReClone(conn, tid, *rovidp);
1249 /* Bring the volume back on-line as soon as possible */
1251 afs_int32 fromtid = 0;
1253 /* Now bring the RO clone on-line */
1254 tst = AFSVolTransCreate(conn, *rovidp, part, ITOffline, &fromtid);
1259 tst = AFSVolSetFlags(conn, fromtid, 0);
1264 tst = AFSVolEndTrans(conn, fromtid, &rcode);
1273 /* Get the time the RW was created for return information */
1274 tst = AFSVolGetStatus(conn, tid, &volstatus);
1278 *vidCreateDate = volstatus.creationDate;
1284 tst = AFSVolEndTrans(conn, tid, &rcode);
1301 /* Get a "transaction" on this replica. Create the volume
1302 * if necessary. Return the time from which a dump should
1303 * be made (0 if it's a new volume)
1306 GetTrans(afs_cell_handle_p cellHandle, struct nvldbentry *vldbEntryPtr,
1307 afs_int32 index, struct rx_connection **connPtr,
1308 afs_int32 * transPtr, afs_int32 * timePtr, afs_status_p st)
1311 afs_status_t tst = 0, etst = 0;
1313 struct volser_status tstatus;
1316 *connPtr = (struct rx_connection *)0;
1320 /* get connection to the replication site */
1322 UV_Bind(cellHandle, vldbEntryPtr->serverNumber[index],
1323 AFSCONF_VOLUMEPORT);
1325 /* server is down */
1330 volid = vldbEntryPtr->volumeId[ROVOL];
1333 AFSVolTransCreate(*connPtr, volid,
1334 vldbEntryPtr->serverPartition[index], ITOffline,
1338 /* If the volume does not exist, create it */
1339 if (!volid || tst) {
1342 if (volid && (tst != VNOVOL)) {
1346 strcpy(volname, vldbEntryPtr->name);
1347 strcat(volname, ".readonly");
1350 AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
1352 vldbEntryPtr->volumeId[RWVOL], &volid,
1357 vldbEntryPtr->volumeId[ROVOL] = volid;
1359 /* The following is a bit redundant, since create sets these flags by default */
1361 AFSVolSetFlags(*connPtr, *transPtr,
1362 VTDeleteOnSalvage | VTOutOfService);
1368 /* Otherwise, the transaction did succeed, so get the creation date of the
1369 * latest RO volume on the replication site
1372 tst = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
1376 *timePtr = tstatus.creationDate - CLOCKSKEW;
1382 if ((rc == 0) && (*transPtr)) {
1383 etst = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
1396 SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
1397 afs_int32 fromdate, manyDests * tr, afs_int32 flags,
1398 void *cookie, manyResults * results)
1402 for (i = 0; i < tr->manyDests_len; i++) {
1403 results->manyResults_val[i] =
1404 AFSVolForward(fromconn, fromtid, fromdate,
1405 &(tr->manyDests_val[i].server),
1406 tr->manyDests_val[i].trans, cookie);
1413 * Determine if a volume exists on a server and partition.
1414 * Try creating a transaction on the volume. If we can,
1415 * the volume exists, if not, then return the error code.
1416 * Some error codes mean the volume is unavailable but
1417 * still exists - so we catch these error codes.
1420 VolumeExists(afs_cell_handle_p cellHandle, afs_int32 server,
1421 afs_int32 partition, afs_int32 volumeid, afs_status_p st)
1424 afs_status_t tst = 0;
1425 struct rx_connection *conn = (struct rx_connection *)0;
1426 volEntries volumeInfo;
1428 conn = UV_Bind(cellHandle, server, AFSCONF_VOLUMEPORT);
1430 volumeInfo.volEntries_val = (volintInfo *) 0;
1431 volumeInfo.volEntries_len = 0;
1432 tst = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
1433 if (volumeInfo.volEntries_val)
1434 free(volumeInfo.volEntries_val);
1435 if (tst == VOLSERILLEGAL_PARTITION) {
1438 rx_ReleaseCachedConnection(conn);
1448 /* release volume <afromvol> on <afromserver> <afrompart> to all the
1449 * sites if forceflag is 1.If its 0 complete the release if the previous
1450 * release aborted else start a new release */
1452 UV_ReleaseVolume(afs_cell_handle_p cellHandle, afs_uint32 afromvol,
1453 afs_int32 afromserver, afs_int32 afrompart, int forceflag,
1457 afs_status_t tst = 0, etst = 0;
1461 afs_uint32 cloneVolId, roVolId;
1462 struct replica *replicas = 0;
1463 struct nvldbentry entry;
1464 int i, volcount, m, fullrelease, vldbindex;
1466 struct restoreCookie cookie;
1467 struct rx_connection **toconns = 0;
1468 struct release *times = 0;
1470 struct rx_connection *fromconn = (struct rx_connection *)0;
1472 afs_int32 clonetid = 0, onlinetid;
1473 afs_int32 fromtid = 0;
1474 afs_uint32 fromdate = 0, thisdate;
1477 manyResults results;
1478 int rwindex, roindex, roclone, roexists;
1479 afs_int32 rwcrdate = 0;
1483 } remembertime[NMAXNSERVERS];
1484 int releasecount = 0;
1485 struct volser_status volstatus;
1487 memset(remembertime, 0, sizeof(remembertime));
1488 memset(&results, 0, sizeof(results));
1491 ubik_VL_SetLock(cellHandle->vos, 0, afromvol, RWVOL,
1493 if ((tst) && (tst != VL_RERELEASE)) {
1494 goto fail_UV_ReleaseVolume;
1498 /* Get the vldb entry in readable format */
1499 if (!aVLDB_GetEntryByID(cellHandle, afromvol, RWVOL, &entry, &tst)) {
1500 goto fail_UV_ReleaseVolume;
1503 if (!ISNAMEVALID(entry.name)) {
1504 tst = VOLSERBADNAME;
1505 goto fail_UV_ReleaseVolume;
1508 if (entry.volumeId[RWVOL] != afromvol) {
1509 tst = ADMVOSVOLUMERELEASERWONLY;
1510 goto fail_UV_ReleaseVolume;
1513 if (entry.nServers <= 1) {
1514 tst = ADMVOSVOLUMENOREPLICAS;
1515 goto fail_UV_ReleaseVolume;
1518 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10)) {
1519 tst = VOLSERBADNAME;
1520 goto fail_UV_ReleaseVolume;
1523 /* roclone is true if one of the RO volumes is on the same
1524 * partition as the RW volume. In this case, we make the RO volume
1525 * on the same partition a clone instead of a complete copy.
1529 Lp_ROMatch(cellHandle, &entry, afromserver, afrompart, &tst) - 1;
1530 roclone = ((roindex == -1) ? 0 : 1);
1531 rwindex = Lp_GetRwIndex(cellHandle, &entry, 0);
1534 goto fail_UV_ReleaseVolume;
1537 /* Make sure we have a RO volume id to work with */
1538 if (entry.volumeId[ROVOL] == INVALID_BID) {
1539 /* need to get a new RO volume id */
1540 tst = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &roVolId);
1542 goto fail_UV_ReleaseVolume;
1545 entry.volumeId[ROVOL] = roVolId;
1546 if (!VLDB_ReplaceEntry(cellHandle, afromvol, RWVOL, &entry, 0, &tst)) {
1547 goto fail_UV_ReleaseVolume;
1551 /* Will we be completing a previously unfinished release. -force overrides */
1552 for (fullrelease = 1, i = 0; (fullrelease && (i < entry.nServers)); i++) {
1553 if (entry.serverFlags[i] & NEW_REPSITE)
1556 if (forceflag && !fullrelease)
1559 /* Determine which volume id to use and see if it exists */
1562 || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
1563 VolumeExists(cellHandle, afromserver, afrompart, cloneVolId, &tst);
1564 roexists = ((tst == ENODEV) ? 0 : 1);
1565 if (!roexists && !fullrelease)
1566 fullrelease = 1; /* Do a full release if RO clone does not exist */
1568 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
1571 goto fail_UV_ReleaseVolume;
1575 /* If the RO clone exists, then if the clone is a temporary
1576 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
1577 * (it was recently added), then also delete it. We do not
1578 * want to "reclone" a temporary RO clone.
1581 && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
1582 tst = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
1583 if (tst && (tst != VNOVOL)) {
1584 goto fail_UV_ReleaseVolume;
1589 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
1590 * write this entry out to the vlserver until after the first
1591 * RO volume is released (temp RO clones don't count).
1593 for (i = 0; i < entry.nServers; i++) {
1594 entry.serverFlags[i] &= ~NEW_REPSITE;
1595 entry.serverFlags[i] |= RO_DONTUSE;
1597 entry.serverFlags[rwindex] |= NEW_REPSITE;
1598 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
1600 /* Begin transaction on RW and mark it busy while we clone it */
1602 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1605 goto fail_UV_ReleaseVolume;
1608 /* Clone or reclone the volume */
1610 tst = AFSVolReClone(fromconn, clonetid, cloneVolId);
1612 goto fail_UV_ReleaseVolume;
1616 strcpy(vname, entry.name);
1617 strcat(vname, ".readonly");
1619 strcpy(vname, "readonly-clone-temp");
1622 AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
1625 goto fail_UV_ReleaseVolume;
1629 /* Get the time the RW was created for future information */
1630 tst = AFSVolGetStatus(fromconn, clonetid, &volstatus);
1632 goto fail_UV_ReleaseVolume;
1634 rwcrdate = volstatus.creationDate;
1636 /* End the transaction on the RW volume */
1637 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
1639 tst = (tst ? tst : rcode);
1641 goto fail_UV_ReleaseVolume;
1644 /* Remember clone volume ID in case we fail or are interrupted */
1645 entry.cloneId = cloneVolId;
1648 /* Bring the RO clone online - though not if it's a temporary clone */
1650 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
1653 goto fail_UV_ReleaseVolume;
1656 etst = AFSVolSetFlags(fromconn, onlinetid, 0);
1658 tst = AFSVolEndTrans(fromconn, onlinetid, &rcode);
1659 tst = (tst ? tst : rcode);
1661 goto fail_UV_ReleaseVolume;
1665 goto fail_UV_ReleaseVolume;
1668 /* Sleep so that a client searching for an online volume won't
1669 * find the clone offline and then the next RO offline while the
1670 * release brings the clone online and the next RO offline (race).
1671 * There is a fix in the 3.4 client that does not need this sleep
1672 * anymore, but we don't know what clients we have.
1674 if (entry.nServers > 2)
1677 /* Mark the RO clone in the VLDB as a good site (already released) */
1678 entry.serverFlags[roindex] |= NEW_REPSITE;
1679 entry.serverFlags[roindex] &= ~RO_DONTUSE;
1680 entry.flags |= RO_EXISTS;
1684 /* Write out the VLDB entry only if the clone is not a temporary
1685 * clone. If we did this to a temporary clone then we would end
1686 * up marking all the ROs as "old release" making the ROs
1687 * temporarily unavailable.
1689 if (!VLDB_ReplaceEntry
1690 (cellHandle, afromvol, RWVOL, &entry, 0, &tst)) {
1691 goto fail_UV_ReleaseVolume;
1696 /* Now we will release from the clone to the remaining RO replicas.
1697 * The first 2 ROs (counting the non-temporary RO clone) are released
1698 * individually: releasecount. This is to reduce the race condition
1699 * of clients trying to find an on-line RO volume. The remaining ROs
1700 * are released in parallel but no more than half the number of ROs
1701 * (rounded up) at a time: nservers.
1704 strcpy(vname, entry.name);
1705 strcat(vname, ".readonly");
1706 memset(&cookie, 0, sizeof(cookie));
1707 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
1708 cookie.type = ROVOL;
1709 cookie.parent = entry.volumeId[RWVOL];
1712 nservers = entry.nServers / 2; /* how many to do at once, excluding clone */
1714 (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
1715 times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
1717 (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
1719 results.manyResults_val =
1720 (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
1721 if (!replicas || !times || !!!results.manyResults_val || !toconns) {
1723 goto fail_UV_ReleaseVolume;
1726 memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
1727 memset(times, 0, (sizeof(struct release) * nservers + 1));
1728 memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
1729 memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
1731 /* Create a transaction on the cloned volume */
1733 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
1735 goto fail_UV_ReleaseVolume;
1738 /* For each index in the VLDB */
1739 for (vldbindex = 0; vldbindex < entry.nServers;) {
1741 /* Get a transaction on the replicas. Pick replacas which have an old release. */
1743 ((volcount < nservers) && (vldbindex < entry.nServers));
1745 /* The first two RO volumes will be released individually.
1746 * The rest are then released in parallel. This is a hack
1747 * for clients not recognizing right away when a RO volume
1748 * comes back on-line.
1750 if ((volcount == 1) && (releasecount < 2))
1753 if (vldbindex == roindex)
1754 continue; /* the clone */
1755 if ((entry.serverFlags[vldbindex] & NEW_REPSITE)
1756 && !(entry.serverFlags[vldbindex] & RO_DONTUSE))
1758 if (!(entry.serverFlags[vldbindex] & ITSROVOL))
1759 continue; /* not a RO vol */
1762 /* Get a Transaction on this replica. Get a new connection if
1763 * necessary. Create the volume if necessary. Return the
1764 * time from which the dump should be made (0 if it's a new
1765 * volume). Each volume might have a different time.
1767 replicas[volcount].server.destHost =
1768 entry.serverNumber[vldbindex];
1769 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
1770 replicas[volcount].server.destSSID = 1;
1771 times[volcount].vldbEntryIndex = vldbindex;
1774 (cellHandle, &entry, vldbindex, &(toconns[volcount]),
1775 &(replicas[volcount].trans), &(times[volcount].time),
1780 /* Thisdate is the date from which we want to pick up all changes */
1781 if (forceflag || !fullrelease
1782 || (rwcrdate > times[volcount].time)) {
1783 /* If the forceflag is set, then we want to do a full dump.
1784 * If it's not a full release, we can't be sure that the creation
1785 * date is good (so we also do a full dump).
1786 * If the RW volume was replaced (its creation date is newer than
1787 * the last release), then we can't be sure what has changed (so
1788 * we do a full dump).
1791 } else if (remembertime[vldbindex].validtime) {
1792 /* Trans was prev ended. Use the time from the prev trans
1793 * because, prev trans may have created the volume. In which
1794 * case time[volcount].time would be now instead of 0.
1797 (remembertime[vldbindex].time <
1798 times[volcount].time) ? remembertime[vldbindex].
1799 time : times[volcount].time;
1801 thisdate = times[volcount].time;
1803 remembertime[vldbindex].validtime = 1;
1804 remembertime[vldbindex].time = thisdate;
1806 if (volcount == 0) {
1807 fromdate = thisdate;
1809 /* Include this volume if it is within 15 minutes of the earliest */
1811 thisdate) ? (fromdate - thisdate) : (thisdate -
1813 AFSVolEndTrans(toconns[volcount],
1814 replicas[volcount].trans, &rcode);
1815 replicas[volcount].trans = 0;
1818 if (thisdate < fromdate)
1819 fromdate = thisdate;
1826 /* Release the ones we have collected */
1827 tr.manyDests_val = &(replicas[0]);
1828 tr.manyDests_len = results.manyResults_len = volcount;
1830 AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr,
1831 0 /*spare */ , &cookie, &results);
1832 if (tst == RXGEN_OPCODE) { /* RPC Interface Mismatch */
1834 SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr,
1835 0 /*spare */ , &cookie, &results);
1840 goto fail_UV_ReleaseVolume;
1842 for (m = 0; m < volcount; m++) {
1843 if (results.manyResults_val[m]) {
1848 AFSVolSetIdsTypes(toconns[m], replicas[m].trans, vname,
1849 ROVOL, entry.volumeId[RWVOL], 0, 0);
1854 /* have to clear dest. flags to ensure new vol goes online:
1855 * because the restore (forwarded) operation copied
1856 * the V_inService(=0) flag over to the destination.
1858 tst = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
1863 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
1864 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
1865 entry.flags |= RO_EXISTS;
1870 /* End the transactions and destroy the connections */
1871 for (s = 0; s < volcount; s++) {
1872 if (replicas[s].trans)
1873 tst = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
1874 replicas[s].trans = 0;
1878 if ((s == 0) || (tst != ENOENT)) {
1880 if (times[s].vldbEntryIndex < vldbindex)
1881 vldbindex = times[s].vldbEntryIndex;
1886 rx_ReleaseCachedConnection(toconns[s]);
1890 if (!VLDB_ReplaceEntry(cellHandle, afromvol, RWVOL, &entry, 0, &tst)) {
1891 goto fail_UV_ReleaseVolume;
1893 } /* for each index in the vldb */
1895 /* End the transaction on the cloned volume */
1896 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
1899 /* Figure out if any volume were not released and say so */
1900 for (failure = 0, i = 0; i < entry.nServers; i++) {
1901 if (!(entry.serverFlags[i] & NEW_REPSITE))
1905 if (!VLDB_ReplaceEntry
1906 (cellHandle, afromvol, RWVOL, &entry, LOCKREL_TIMESTAMP, &tst)) {
1907 goto fail_UV_ReleaseVolume;
1910 tst = VOLSERBADRELEASE;
1911 goto fail_UV_ReleaseVolume;
1914 /* All the ROs were release successfully. Remove the temporary clone */
1916 tst = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
1918 goto fail_UV_ReleaseVolume;
1923 for (i = 0; i < entry.nServers; i++)
1924 entry.serverFlags[i] &= ~NEW_REPSITE;
1926 /* Update the VLDB */
1927 if (!VLDB_ReplaceEntry
1928 (cellHandle, afromvol, RWVOL, &entry,
1929 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP, &tst)) {
1930 goto fail_UV_ReleaseVolume;
1934 fail_UV_ReleaseVolume:
1937 tst = AFSVolEndTrans(fromconn, clonetid, &rcode);
1944 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
1950 for (i = 0; i < nservers; i++) {
1951 if (replicas && replicas[i].trans) {
1952 tst = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
1953 replicas[i].trans = 0;
1958 if (toconns && toconns[i]) {
1959 rx_ReleaseCachedConnection(toconns[i]);
1965 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, RWVOL,
1966 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
1973 rx_ReleaseCachedConnection(fromconn);
1974 if (results.manyResults_val)
1975 free(results.manyResults_val);
1990 ReceiveFile(register int fd, register struct rx_call *call,
1991 register struct stat *status)
1993 register char *buffer = (char *)0;
1994 register int blockSize;
1995 afs_int32 bytesread, nbytes, bytesleft, w;
1997 afs_int32 error = 0;
2004 struct statfs tstatfs;
2006 /* Unfortunately in AIX valuable fields such as st_blksize are gone from the sta
2008 fstatfs(fd, &tstatfs);
2009 blockSize = tstatfs.f_bsize;
2011 blockSize = status->st_blksize;
2018 buffer = (char *)malloc(blockSize);
2023 while (!error && (bytesread > 0)) {
2024 bytesread = rx_Read(call, buffer, nbytes);
2025 bytesleft = bytesread;
2026 while (!error && (bytesleft > 0)) {
2029 #ifndef AFS_NT40_ENV /* NT csn't select on non-socket fd's */
2030 select(fd + 1, 0, &out, 0, 0); /* don't timeout if write bl
2033 w = write(fd, &buffer[bytesread - bytesleft], bytesleft);
2035 error = ADMVOSDUMPFILEWRITEFAIL;
2051 DumpFunction(struct rx_call *call, const char *filename)
2055 afs_int32 error, code;
2060 fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0666);
2061 if (fd < 0 || fstat(fd, &status) < 0) {
2062 error = VOLSERBADOP;
2065 code = ReceiveFile(fd, call, &status);
2083 /*dump the volume <afromvol> on <afromserver> and
2084 * <afrompart> to <afilename> starting from <fromdate>.
2085 * DumpFunction does the real work behind the scenes after
2086 * extracting parameters from the rock */
2088 UV_DumpVolume(afs_cell_handle_p cellHandle, afs_uint32 afromvol,
2089 afs_int32 afromserver, afs_int32 afrompart, afs_int32 fromdate,
2090 const char *filename, afs_status_p st)
2093 afs_status_t tst = 0;
2094 afs_status_t etst = 0;
2095 struct rx_connection *fromconn;
2096 struct rx_call *fromcall;
2101 struct nvldbentry entry;
2108 fromcall = (struct rx_call *)0;
2109 fromconn = (struct rx_connection *)0;
2111 fromcall = (struct rx_call *)0;
2114 if (!aVLDB_GetEntryByID(cellHandle, afromvol, -1, &entry, &tst)) {
2115 goto fail_UV_DumpVolume;
2118 /* get connections to the servers */
2119 fromconn = UV_Bind(cellHandle, afromserver, AFSCONF_VOLUMEPORT);
2120 tst = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2122 goto fail_UV_DumpVolume;
2124 fromcall = rx_NewCall(fromconn);
2125 tst = StartAFSVolDump(fromcall, fromtid, fromdate);
2127 goto fail_UV_DumpVolume;
2129 if ((tst = DumpFunction(fromcall, filename))) {
2130 goto fail_UV_DumpVolume;
2132 tst = rx_EndCall(fromcall, rxError);
2133 fromcall = (struct rx_call *)0;
2135 goto fail_UV_DumpVolume;
2137 tst = AFSVolEndTrans(fromconn, fromtid, &rcode);
2142 goto fail_UV_DumpVolume;
2150 ubik_VL_ReleaseLock(cellHandle->vos, 0, afromvol, -1,
2151 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2159 etst = rx_EndCall(fromcall, rxError);
2167 etst = AFSVolEndTrans(fromconn, fromtid, &rcode);
2177 rx_ReleaseCachedConnection(fromconn);
2187 SendFile(register int fd, register struct rx_call *call,
2188 register struct stat *status)
2190 char *buffer = (char *)0;
2193 afs_int32 error = 0;
2202 struct statfs tstatfs;
2204 /* Unfortunately in AIX valuable fields such as st_blksize are gone from the sta
2206 fstatfs(fd, &tstatfs);
2207 blockSize = tstatfs.f_bsize;
2209 blockSize = status->st_blksize;
2215 buffer = (char *)malloc(blockSize);
2220 while (!error && !done) {
2223 #ifndef AFS_NT40_ENV /* NT csn't select on non-socket fd's */
2224 select(fd + 1, &in, 0, 0, 0); /* don't timeout if read blocks */
2226 nbytes = read(fd, buffer, blockSize);
2228 error = ADMVOSRESTOREFILEREADFAIL;
2235 if (rx_Write(call, buffer, nbytes) != nbytes) {
2236 error = ADMVOSRESTOREFILEWRITEFAIL;
2246 WriteData(struct rx_call *call, const char *filename)
2250 afs_int32 error, code;
2255 fd = open(filename, 0);
2256 if (fd < 0 || fstat(fd, &status) < 0) {
2257 fprintf(STDERR, "Could access file '%s'\n", filename);
2258 error = ADMVOSRESTOREFILEOPENFAIL;
2259 goto fail_WriteData;
2261 code = SendFile(fd, call, &status);
2264 goto fail_WriteData;
2275 error = ADMVOSRESTOREFILECLOSEFAIL;
2281 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
2282 * the dump file <afilename>. WriteData does all the real work
2283 * after extracting params from the rock
2286 UV_RestoreVolume(afs_cell_handle_p cellHandle, afs_int32 toserver,
2287 afs_int32 topart, afs_uint32 tovolid, char *tovolname,
2288 int flags, const char *dumpFile, afs_status_p st)
2291 afs_status_t tst = 0;
2292 afs_status_t etst = 0;
2293 struct rx_connection *toconn, *tempconn;
2294 struct rx_call *tocall;
2295 afs_int32 totid, rcode;
2296 afs_int32 rxError = 0;
2297 struct volser_status tstatus;
2302 struct nvldbentry entry;
2305 struct restoreCookie cookie;
2307 afs_int32 newDate, volflag;
2311 memset(&cookie, 0, sizeof(cookie));
2316 tocall = (struct rx_call *)0;
2317 toconn = (struct rx_connection *)0;
2318 tempconn = (struct rx_connection *)0;
2323 toconn = UV_Bind(cellHandle, toserver, AFSCONF_VOLUMEPORT);
2324 if (pvolid == 0) { /*alot a new id if needed */
2325 aVLDB_GetEntryByName(cellHandle, tovolname, &entry, &tst);
2326 if (tst == VL_NOENT) {
2328 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 1, &pvolid);
2330 goto fail_UV_RestoreVolume;
2334 pvolid = entry.volumeId[RWVOL];
2339 * at this point we have a volume id to use/reuse for the
2340 * volume to be restored
2342 if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
2343 tst = ADMVOSRESTOREVOLUMENAMETOOBIG;
2344 goto fail_UV_RestoreVolume;
2347 if (!vos_PartitionIdToName(topart, partName, &tst)) {
2348 goto fail_UV_RestoreVolume;
2350 /*what should the volume be restored as ? rw or ro or bk ?
2351 * right now the default is rw always */
2353 AFSVolCreateVolume(toconn, topart, tovolname, volser_RW, 0, &pvolid,
2356 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
2358 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2360 goto fail_UV_RestoreVolume;
2363 AFSVolSetFlags(toconn, totid,
2364 VTDeleteOnSalvage | VTOutOfService);
2366 goto fail_UV_RestoreVolume;
2368 tst = AFSVolDeleteVolume(toconn, totid);
2370 goto fail_UV_RestoreVolume;
2372 tst = AFSVolEndTrans(toconn, totid, &rcode);
2377 goto fail_UV_RestoreVolume;
2380 AFSVolCreateVolume(toconn, topart, tovolname, volser_RW, 0,
2383 goto fail_UV_RestoreVolume;
2387 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2389 goto fail_UV_RestoreVolume;
2393 cookie.parent = pvolid;
2394 cookie.type = RWVOL;
2396 strncpy(cookie.name, tovolname, VOLSER_OLDMAXVOLNAME);
2398 tocall = rx_NewCall(toconn);
2399 tst = StartAFSVolRestore(tocall, totid, 1, &cookie);
2401 goto fail_UV_RestoreVolume;
2403 tst = WriteData(tocall, dumpFile);
2405 goto fail_UV_RestoreVolume;
2407 tst = rx_EndCall(tocall, rxError);
2408 tocall = (struct rx_call *)0;
2410 goto fail_UV_RestoreVolume;
2412 tst = AFSVolGetStatus(toconn, totid, &tstatus);
2414 goto fail_UV_RestoreVolume;
2416 tst = AFSVolSetIdsTypes(toconn, totid, tovolname, RWVOL, pvolid, 0, 0);
2418 goto fail_UV_RestoreVolume;
2421 tst = AFSVolSetDate(toconn, totid, newDate);
2423 goto fail_UV_RestoreVolume;
2426 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
2427 tst = AFSVolSetFlags(toconn, totid, volflag);
2429 goto fail_UV_RestoreVolume;
2432 /* It isn't handled right in fail_UV_RestoreVolume */
2433 tst = AFSVolEndTrans(toconn, totid, &rcode);
2438 goto fail_UV_RestoreVolume;
2442 if (success && (!reuseID || (flags & RV_FULLRST))) {
2443 /* Volume was restored on the file server, update the
2444 * VLDB to reflect the change.
2446 aVLDB_GetEntryByID(cellHandle, pvolid, RWVOL, &entry, &tst);
2447 if (tst && tst != VL_NOENT && tst != VL_ENTDELETED) {
2448 goto fail_UV_RestoreVolume;
2450 if (tst == VL_NOENT) { /* it doesnot exist already */
2451 /*make the vldb return this indication specifically */
2452 strcpy(entry.name, tovolname);
2454 entry.serverNumber[0] = toserver; /*should be indirect */
2455 entry.serverPartition[0] = topart;
2456 entry.serverFlags[0] = ITSRWVOL;
2457 entry.flags = RW_EXISTS;
2458 if (tstatus.cloneID != 0) {
2459 entry.volumeId[ROVOL] = tstatus.cloneID; /*this should come from status info on the volume if non zero */
2461 entry.volumeId[ROVOL] = INVALID_BID;
2462 entry.volumeId[RWVOL] = pvolid;
2464 if (tstatus.backupID != 0) {
2465 entry.volumeId[BACKVOL] = tstatus.backupID;
2466 /*this should come from status info on the volume if non zero */
2468 entry.volumeId[BACKVOL] = INVALID_BID;
2469 if (!VLDB_CreateEntry(cellHandle, &entry, &tst)) {
2470 goto fail_UV_RestoreVolume;
2473 } else { /*update the existing entry */
2475 ubik_VL_SetLock(cellHandle->vos, 0, pvolid, RWVOL,
2478 goto fail_UV_RestoreVolume;
2481 strcpy(entry.name, tovolname);
2483 /* Update the vlentry with the new information */
2484 index = Lp_GetRwIndex(cellHandle, &entry, 0);
2486 /* Add the rw site for the volume being restored */
2487 entry.serverNumber[entry.nServers] = toserver;
2488 entry.serverPartition[entry.nServers] = topart;
2489 entry.serverFlags[entry.nServers] = ITSRWVOL;
2492 /* This volume should be deleted on the old site
2493 * if its different from new site.
2495 VLDB_IsSameAddrs(cellHandle, toserver,
2496 entry.serverNumber[index], &same, &tst);
2498 || (entry.serverPartition[index] != topart)) {
2500 UV_Bind(cellHandle, entry.serverNumber[index],
2501 AFSCONF_VOLUMEPORT);
2503 AFSVolTransCreate(tempconn, pvolid,
2504 entry.serverPartition[index],
2505 ITOffline, &temptid);
2508 AFSVolSetFlags(tempconn, temptid,
2512 goto fail_UV_RestoreVolume;
2514 tst = AFSVolDeleteVolume(tempconn, temptid);
2516 goto fail_UV_RestoreVolume;
2518 tst = AFSVolEndTrans(tempconn, temptid, &rcode);
2523 goto fail_UV_RestoreVolume;
2525 vos_PartitionIdToName(entry.serverPartition[index],
2529 entry.serverNumber[index] = toserver;
2530 entry.serverPartition[index] = topart;
2533 entry.flags |= RW_EXISTS;
2534 if (!VLDB_ReplaceEntry
2535 (cellHandle, pvolid, RWVOL, &entry,
2536 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP, &tst)) {
2537 goto fail_UV_RestoreVolume;
2544 fail_UV_RestoreVolume:
2547 etst = rx_EndCall(tocall, rxError);
2553 ubik_VL_ReleaseLock(cellHandle->vos, 0, pvolid, RWVOL,
2554 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2561 etst = AFSVolEndTrans(toconn, totid, &rcode);
2570 etst = AFSVolEndTrans(toconn, temptid, &rcode);
2580 rx_ReleaseCachedConnection(tempconn);
2582 rx_ReleaseCachedConnection(toconn);
2590 /*adds <server> and <part> as a readonly replication site for <volid>
2593 UV_AddSite(afs_cell_handle_p cellHandle, afs_int32 server, afs_int32 part,
2594 afs_uint32 volid, afs_status_p st)
2597 afs_status_t tst = 0;
2598 int j, nro = 0, islocked = 0;
2599 struct nvldbentry entry;
2603 ubik_VL_SetLock(cellHandle->vos, 0, volid, RWVOL, VLOP_ADDSITE);
2605 goto fail_UV_AddSite;
2609 if (!aVLDB_GetEntryByID(cellHandle, volid, RWVOL, &entry, &tst)) {
2610 goto fail_UV_AddSite;
2612 if (!ISNAMEVALID(entry.name)) {
2614 goto fail_UV_AddSite;
2617 /* See if it's too many entries */
2618 if (entry.nServers >= NMAXNSERVERS) {
2620 goto fail_UV_AddSite;
2623 /* See if it's on the same server */
2624 for (j = 0; j < entry.nServers; j++) {
2625 if (entry.serverFlags[j] & ITSROVOL) {
2627 if (!VLDB_IsSameAddrs
2628 (cellHandle, server, entry.serverNumber[j], &same, &tst)) {
2629 goto fail_UV_AddSite;
2633 goto fail_UV_AddSite;
2638 /* See if it's too many RO sites - leave one for the RW */
2639 if (nro >= NMAXNSERVERS - 1) {
2641 goto fail_UV_AddSite;
2644 entry.serverNumber[entry.nServers] = server;
2645 entry.serverPartition[entry.nServers] = part;
2646 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
2649 if (!VLDB_ReplaceEntry
2650 (cellHandle, volid, RWVOL, &entry,
2651 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP, &tst)) {
2652 goto fail_UV_AddSite;
2661 ubik_VL_ReleaseLock(cellHandle->vos, 0, volid, RWVOL,
2662 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2671 /*removes <server> <part> as read only site for <volid> from the vldb */
2673 UV_RemoveSite(afs_cell_handle_p cellHandle, afs_int32 server, afs_int32 part,
2674 afs_uint32 volid, afs_status_p st)
2677 afs_status_t tst = 0;
2678 struct nvldbentry entry;
2682 ubik_VL_SetLock(cellHandle->vos, 0, volid, RWVOL, VLOP_ADDSITE);
2684 goto fail_UV_RemoveSite;
2688 if (!aVLDB_GetEntryByID(cellHandle, volid, RWVOL, &entry, &tst)) {
2689 goto fail_UV_RemoveSite;
2691 if (!Lp_ROMatch(cellHandle, &entry, server, part, &tst)) {
2692 /*this site doesnot exist */
2693 goto fail_UV_RemoveSite;
2694 } else { /*remove the rep site */
2695 Lp_SetROValue(cellHandle, &entry, server, part, 0, 0);
2697 if ((entry.nServers == 1) && (entry.flags & RW_EXISTS))
2698 entry.flags &= ~RO_EXISTS;
2699 if (entry.nServers < 1) { /*this is the last ref */
2700 tst = ubik_VL_DeleteEntry(cellHandle->vos, 0, volid, ROVOL);
2702 goto fail_UV_RemoveSite;
2705 if (!VLDB_ReplaceEntry
2706 (cellHandle, volid, RWVOL, &entry,
2707 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP), &tst)) {
2708 goto fail_UV_RemoveSite;
2717 t = ubik_VL_ReleaseLock(cellHandle->vos, 0, volid, RWVOL,
2718 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2730 /*list all the partitions on <aserver> */
2732 UV_ListPartitions(struct rx_connection *server, struct partList *ptrPartList,
2733 afs_int32 * cntp, afs_status_p st)
2736 afs_status_t tst = 0;
2737 struct pIDs partIds;
2738 struct partEntries partEnts;
2739 register int i, j = 0;
2743 partEnts.partEntries_len = 0;
2744 partEnts.partEntries_val = NULL;
2745 /* this is available only on new servers */
2746 tst = AFSVolXListPartitions(server, &partEnts);
2748 /* next, try old interface */
2749 if (tst == RXGEN_OPCODE) {
2750 for (i = 0; i < 26; i++)
2751 partIds.partIds[i] = -1;
2752 tst = AFSVolListPartitions(server, &partIds);
2754 for (i = 0; i < 26; i++) {
2755 if ((partIds.partIds[i]) != -1) {
2756 ptrPartList->partId[j] = partIds.partIds[i];
2757 ptrPartList->partFlags[j] = PARTVALID;
2760 ptrPartList->partFlags[i] = 0;
2764 goto fail_UV_ListPartitions;
2767 *cntp = partEnts.partEntries_len;
2768 if (*cntp > VOLMAXPARTS) {
2769 *cntp = VOLMAXPARTS;
2771 for (i = 0; i < *cntp; i++) {
2772 ptrPartList->partId[i] = partEnts.partEntries_val[i];
2773 ptrPartList->partFlags[i] = PARTVALID;
2775 free(partEnts.partEntries_val);
2777 goto fail_UV_ListPartitions;
2781 fail_UV_ListPartitions:
2789 /*------------------------------------------------------------------------
2790 * EXPORTED UV_XListVolumes
2793 * List the extended information for all the volumes on a particular
2794 * File Server and partition. We may either return the volume's ID
2795 * or all of its extended information.
2798 * a_serverID : Address of the File Server for which we want
2799 * extended volume info.
2800 * a_partID : Partition for which we want the extended
2802 * a_all : If non-zero, fetch ALL the volume info,
2803 * otherwise just the volume ID.
2804 * a_resultPP : Ptr to the address of the area containing
2805 * the returned volume info.
2806 * a_numEntsInResultP : Ptr for the value we set for the number of
2811 * Otherise, the return value of AFSVolXListVolumes.
2814 * This routine is closely related to UV_ListVolumes, which returns
2815 * only the standard level of detail on AFS volumes. It is a
2816 * heavyweight operation, zipping through all the volume entries for
2817 * a given server/partition.
2821 *------------------------------------------------------------------------*/
2824 UV_XListVolumes(struct rx_connection *server, afs_int32 a_partID, int a_all,
2825 struct volintXInfo **a_resultPP,
2826 afs_int32 * a_numEntsInResultP, afs_status_p st)
2829 afs_status_t tst = 0;
2831 volXEntries volumeXInfo; /*Area for returned extended vol info */
2834 * Set up our error code and the area for returned extended volume info.
2835 * We set the val field to a null pointer as a hint for the stub to
2838 *a_numEntsInResultP = 0;
2839 *a_resultPP = (volintXInfo *) 0;
2840 volumeXInfo.volXEntries_val = (volintXInfo *) 0;
2841 volumeXInfo.volXEntries_len = 0;
2844 * Bind to the Volume Server port on the File Server machine in question,
2847 tst = AFSVolXListVolumes(server, a_partID, a_all, &volumeXInfo);
2849 goto fail_UV_XListVolumes;
2852 * We got the info; pull out the pointer to where the results lie
2853 * and how many entries are there.
2855 *a_resultPP = volumeXInfo.volXEntries_val;
2856 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
2860 fail_UV_XListVolumes:
2868 /*------------------------------------------------------------------------
2869 * EXPORTED UV_XListOneVolume
2872 * List the extended information for a volume on a particular File
2873 * Server and partition.
2876 * server : a handle to the server where the volume resides.
2877 * a_partID : Partition for which we want the extended
2879 * a_volID : Volume ID for which we want the info.
2880 * a_resultPP : Ptr to the address of the area containing
2881 * the returned volume info.
2885 * Otherise, the return value of AFSVolXListOneVolume.
2888 * This routine is closely related to UV_ListOneVolume, which returns
2889 * only the standard level of detail on the chosen AFS volume.
2893 *------------------------------------------------------------------------*/
2896 UV_XListOneVolume(struct rx_connection *server, afs_int32 a_partID,
2897 afs_uint32 a_volID, struct volintXInfo **a_resultPP,
2901 afs_status_t tst = 0;
2902 volXEntries volumeXInfo; /*Area for returned info */
2905 * Set the area we're in which we are returning
2906 * the info. Setting the val field to a null pointer tells the stub
2907 * to allocate space for us.
2909 *a_resultPP = (volintXInfo *) 0;
2910 volumeXInfo.volXEntries_val = (volintXInfo *) 0;
2911 volumeXInfo.volXEntries_len = 0;
2913 tst = AFSVolXListOneVolume(server, a_partID, a_volID, &volumeXInfo);
2916 goto fail_UV_XListOneVolume;
2919 * We got the info; pull out the pointer to where the results lie.
2921 *a_resultPP = volumeXInfo.volXEntries_val;
2925 fail_UV_XListOneVolume:
2932 } /*UV_XListOneVolume */
2934 /*------------------------------------------------------------------------
2935 * EXPORTED UV_ListOneVolume
2938 * List the volume information for a volume on a particular File
2939 * Server and partition.
2942 * server : a handle to the server where the volume resides.
2943 * a_partID : Partition for which we want the extended
2945 * a_volID : Volume ID for which we want the info.
2946 * a_resultPP : Ptr to the address of the area containing
2947 * the returned volume info.
2951 * Otherise, the return value of AFSVolXListOneVolume.
2955 *------------------------------------------------------------------------*/
2957 int UV_ListOneVolume(struct rx_connection *server, afs_int32 a_partID,
2958 afs_uint32 a_volID, struct volintInfo **a_resultPP,
2962 afs_status_t tst = 0;
2963 volEntries volumeInfo; /*Area for returned info */
2966 * Set the area we're in which we are returning
2967 * the info. Setting the val field to a null pointer tells the stub
2968 * to allocate space for us.
2970 *a_resultPP = (volintInfo *) 0;
2971 volumeInfo.volEntries_val = (volintInfo *) 0;
2972 volumeInfo.volEntries_len = 0;
2974 tst = AFSVolListOneVolume(server, a_partID, a_volID, &volumeInfo);
2977 goto fail_UV_ListOneVolume;
2980 * We got the info; pull out the pointer to where the results lie.
2982 *a_resultPP = volumeInfo.volEntries_val;
2986 fail_UV_ListOneVolume:
2992 }/*UV_ListOneVolume*/
2994 /*sync vldb with all the entries on <myQueue> on <aserver> and <apart>*/
2996 ProcessEntries(afs_cell_handle_p cellHandle, struct qHead *myQueue,
2997 struct rx_connection *server, afs_int32 apart, afs_int32 force)
3001 afs_uint32 temp1, temp2;
3003 afs_uint32 maxVolid = 0;
3004 struct nvldbentry entry;
3005 int noError = 1, error, same;
3006 int totalC, totalU, totalCE, totalUE, totalG;
3008 int aserver = ntohl(rx_HostOf(rx_PeerOf(server)));
3011 totalC = totalU = totalCE = totalUE = totalG = 0;
3014 /* get the next available id's from the vldb server */
3015 vcode = ubik_VL_GetNewVolumeId(cellHandle->vos, 0, 0, &maxVolid);
3019 totalG = myQueue->count;
3023 Lp_QEnumerate(myQueue, &success, &elem, 0);
3028 if (!elem.isValid[RWVOL] && !elem.isValid[ROVOL] && !elem.isValid[BACKVOL]) { /*something is wrong with elem */
3032 if (maxVolid <= elem.ids[RWVOL]) {
3034 temp2 = elem.ids[RWVOL] - maxVolid + 1;
3037 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, temp2,
3041 if (maxVolid <= elem.ids[ROVOL]) {
3043 temp2 = elem.ids[ROVOL] - maxVolid + 1;
3046 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, temp2,
3050 if (maxVolid <= elem.ids[BACKVOL]) {
3052 temp2 = elem.ids[BACKVOL] - temp1 + 1;
3055 ubik_VL_GetNewVolumeId(cellHandle->vos, 0, temp2,
3059 aVLDB_GetEntryByID(cellHandle, elem.ids[RWVOL], RWVOL, &entry, &tst);
3060 if (tst && (tst != VL_NOENT)) {
3063 } else if (tst && (tst == VL_NOENT)) { /*entry doesnot exist */
3064 /*set up a vldb entry for elem */
3065 memset(&entry, 0, sizeof(entry));
3066 strncpy(entry.name, elem.name, VOLSER_OLDMAXVOLNAME);
3067 if (elem.isValid[RWVOL]) { /*rw exists */
3068 entry.flags |= RW_EXISTS;
3069 entry.serverFlags[entry.nServers] = ITSRWVOL;
3070 entry.serverNumber[entry.nServers] = aserver;
3071 entry.serverPartition[entry.nServers] = apart;
3072 entry.nServers += 1;
3073 entry.volumeId[RWVOL] = elem.ids[RWVOL];
3074 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3075 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3077 if (elem.isValid[ROVOL]) { /*ro volume exists */
3078 entry.flags |= RO_EXISTS;
3079 entry.serverFlags[entry.nServers] = ITSROVOL;
3080 entry.serverNumber[entry.nServers] = aserver;
3081 entry.serverPartition[entry.nServers] = apart;
3082 entry.nServers += 1;
3083 entry.volumeId[RWVOL] = elem.ids[RWVOL];
3084 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3087 if (elem.isValid[BACKVOL]) { /*backup volume exists */
3088 entry.flags |= BACK_EXISTS;
3089 if (!(entry.flags & RW_EXISTS)) { /*this helps to check for a stray backup if parent moves */
3090 entry.serverFlags[entry.nServers] = ITSRWVOL;
3091 entry.serverNumber[entry.nServers] = aserver;
3092 entry.serverPartition[entry.nServers] = apart;
3093 entry.nServers += 1;
3096 entry.volumeId[RWVOL] = elem.ids[RWVOL];
3097 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3100 VLDB_CreateEntry(cellHandle, &entry, &tst);
3106 } else { /* Update the existing entry */
3107 strncpy(entry.name, elem.name, VOLSER_OLDMAXVOLNAME); /*the name Could have changed */
3109 if (elem.isValid[RWVOL]) { /* A RW volume */
3110 temp = Lp_GetRwIndex(cellHandle, &entry, 0);
3112 /* A RW index is not found in the VLDB entry - will add it */
3114 entry.flags |= RW_EXISTS;
3115 entry.serverNumber[entry.nServers] = aserver;
3116 entry.serverPartition[entry.nServers] = apart;
3117 entry.serverFlags[entry.nServers] = ITSRWVOL;
3120 /* A RW index is found in the VLDB entry.
3121 * Verify that the volume location matches the VLDB location.
3122 * Fix the VLDB entry if it is not correct.
3126 VLDB_IsSameAddrs(cellHandle, aserver,
3127 entry.serverNumber[temp], &same,
3132 if (!same || (apart != entry.serverPartition[temp])) {
3133 /* VLDB says volume is in another place. Fix the VLDB entry */
3134 entry.serverNumber[temp] = aserver;
3135 entry.serverPartition[temp] = apart;
3138 entry.flags |= RW_EXISTS;
3140 if ((elem.ids[BACKVOL] != 0) && elem.isValid[BACKVOL])
3141 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3142 if ((elem.ids[ROVOL] != 0) && elem.isValid[ROVOL])
3143 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3146 if (elem.isValid[ROVOL]) {
3147 /*tackle a ro volume */
3149 if (!Lp_ROMatch(cellHandle, &entry, aserver, apart, 0)) {
3151 if (elem.ids[ROVOL] > entry.volumeId[ROVOL]) {
3152 /*there is a conflict of ids, keep the later volume */
3153 /*delete all the ro volumes listed in vldb entry since they
3156 int j, count, rwsite;
3159 count = entry.nServers;
3161 for (j = 0; j < count; j++) {
3162 if (entry.serverFlags[j] & ITSROVOL) {
3164 /*delete the site */
3165 entry.serverNumber[j] = 0;
3166 entry.serverPartition[j] = 0;
3167 entry.serverFlags[j] = 0;
3169 } else if (entry.serverFlags[j] & ITSRWVOL)
3174 entry.serverNumber[entry.nServers] =
3175 entry.serverNumber[rwsite];
3176 entry.serverPartition[entry.nServers] =
3177 entry.serverPartition[rwsite];
3178 entry.serverFlags[entry.nServers] =
3179 entry.serverFlags[rwsite];
3182 entry.serverNumber[entry.nServers] = aserver;
3183 entry.serverPartition[entry.nServers] = apart;
3184 entry.serverFlags[entry.nServers] = ITSROVOL;
3186 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3187 entry.flags |= RO_EXISTS;
3189 } else if (elem.ids[ROVOL] < entry.volumeId[ROVOL]) {
3190 if (!(entry.flags & RO_EXISTS)) {
3191 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3192 entry.serverNumber[entry.nServers] = aserver;
3193 entry.serverPartition[entry.nServers] = apart;
3194 entry.serverFlags[entry.nServers] = ITSROVOL;
3196 entry.flags |= RO_EXISTS;
3201 else if (elem.ids[ROVOL] == entry.volumeId[ROVOL]) {
3202 entry.serverNumber[entry.nServers] = aserver;
3203 entry.serverPartition[entry.nServers] = apart;
3204 entry.serverFlags[entry.nServers] = ITSROVOL;
3206 entry.flags |= RO_EXISTS;
3207 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3210 if (entry.volumeId[ROVOL] == INVALID_BID)
3211 entry.volumeId[ROVOL] = elem.ids[ROVOL];
3214 if (elem.isValid[BACKVOL]) {
3215 temp = Lp_GetRwIndex(cellHandle, &entry, 0);
3216 if (temp != -1) { /*check if existing backup site matches with the given arguments */
3218 VLDB_IsSameAddrs(cellHandle, aserver,
3219 entry.serverNumber[temp], &same,
3225 /*tackle the backup volume */
3226 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3227 entry.flags |= BACK_EXISTS;
3229 if (entry.volumeId[BACKVOL] == INVALID_BID)
3230 entry.volumeId[BACKVOL] = elem.ids[BACKVOL];
3233 VLDB_ReplaceEntry(cellHandle, elem.ids[RWVOL], RWVOL, &entry,
3234 LOCKREL_OPCODE | LOCKREL_AFSID |
3235 LOCKREL_TIMESTAMP, &tst);
3241 ubik_VL_ReleaseLock(cellHandle->vos, 0,
3242 elem.ids[RWVOL], RWVOL,
3243 LOCKREL_OPCODE | LOCKREL_AFSID |
3249 } /* else update the existing entry */
3251 } /* End of while(1) */
3259 /*synchronise vldb with the file server <aserver> and <apart>(if flags=1).
3260 *else synchronise with all the valid partitions on <aserver>
3263 UV_SyncVldb(afs_cell_handle_p cellHandle, struct rx_connection *server,
3264 afs_int32 apart, int flags, int force, afs_status_p st)
3267 afs_status_t tst = 0;
3270 volEntries volumeInfo;
3272 struct qHead myQueue;
3273 struct partList PartList;
3278 /*this hints the stub to allocate space */
3279 volumeInfo.volEntries_val = (volintInfo *) 0;
3280 volumeInfo.volEntries_len = 0;
3282 if (!flags) { /*generate all the valid partitions */
3283 UV_ListPartitions(server, &PartList, &cnt, &tst);
3285 goto fail_UV_SyncVldb;
3288 PartList.partId[0] = apart;
3292 for (i = 0; i < cnt; i++) {
3293 apart = PartList.partId[i];
3294 /*this hints the stub to allocate space */
3295 volumeInfo.volEntries_val = (volintInfo *) 0;
3296 volumeInfo.volEntries_len = 0;
3297 tst = AFSVolListVolumes(server, apart, 1, &volumeInfo);
3299 goto fail_UV_SyncVldb;
3301 count = volumeInfo.volEntries_len;
3302 pntr = volumeInfo.volEntries_val;
3304 if (!vos_PartitionIdToName(apart, pname, &tst)) {
3305 goto fail_UV_SyncVldb;
3307 /*collect all vol entries by their parentid */
3308 tst = GroupEntries(server, pntr, count, &myQueue, apart);
3311 if (volumeInfo.volEntries_val) {
3312 /*free the space allocated by the stub */
3313 free(volumeInfo.volEntries_val);
3314 volumeInfo.volEntries_val = 0;
3318 tst = ProcessEntries(cellHandle, &myQueue, server, apart, force);
3320 tst = VOLSERFAILEDOP;
3321 if (volumeInfo.volEntries_val) {
3322 /*free the space allocated by the stub */
3323 free(volumeInfo.volEntries_val);
3324 volumeInfo.volEntries_val = 0;
3331 tst = VOLSERFAILEDOP;
3332 } /* thru all partitions */
3337 if (volumeInfo.volEntries_val)
3338 free(volumeInfo.volEntries_val);
3351 CheckVldbRWBK(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3352 afs_int32 * modified, afs_status_p st)
3355 afs_status_t tst = 0;
3361 idx = Lp_GetRwIndex(cellHandle, entry, 0);
3363 /* Check to see if the RW volume exists and set the RW_EXISTS
3366 if (idx == -1) { /* Did not find a RW entry */
3367 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
3368 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
3373 (cellHandle, entry->serverNumber[idx],
3374 entry->serverPartition[idx], entry->volumeId[RWVOL], &tst)) {
3375 if (!(entry->flags & RW_EXISTS)) { /* ... yet entry says RW does no
3377 entry->flags |= RW_EXISTS; /* ... so say RW does exist */
3380 } else if (tst == ENODEV) { /* RW volume does not exist */
3381 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists
3383 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist
3388 /* If VLDB says it didn't exist, then ignore error */
3389 if (entry->flags & RW_EXISTS) {
3390 goto fail_CheckVldbRWBK;
3395 /* Check to see if the BK volume exists and set the BACK_EXISTS
3396 * flag accordingly. idx already ponts to the RW entry.
3398 if (idx == -1) { /* Did not find a RW entry */
3399 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
3400 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
3403 } else { /* Found a RW entry */
3405 (cellHandle, entry->serverNumber[idx],
3406 entry->serverPartition[idx], entry->volumeId[BACKVOL], &tst)) {
3407 if (!(entry->flags & BACK_EXISTS)) { /* ... yet entry says BK does n
3409 entry->flags |= BACK_EXISTS; /* ... so say BK does exist */
3412 } else if (tst == ENODEV) { /* BK volume does not exist */
3413 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists
3415 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist
3420 /* If VLDB says it didn't exist, then ignore error */
3421 if (entry->flags & BACK_EXISTS) {
3422 goto fail_CheckVldbRWBK;
3427 /* If there is an idx but the BK and RW volumes no
3428 * longer exist, then remove the RW entry.
3430 if ((idx != -1) && !(entry->flags & RW_EXISTS)
3431 && !(entry->flags & BACK_EXISTS)) {
3432 Lp_SetRWValue(cellHandle, entry, entry->serverNumber[idx],
3433 entry->serverPartition[idx], 0L, 0L);
3442 *modified = modentry;
3452 CheckVldbRO(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3453 afs_int32 * modified, afs_status_p st)
3456 afs_status_t tst = 0;
3458 int foundro = 0, modentry = 0;
3463 /* Check to see if the RO volumes exist and set the RO_EXISTS
3466 for (idx = 0; idx < entry->nServers; idx++) {
3467 if (!(entry->serverFlags[idx] & ITSROVOL)) {
3468 continue; /* not a RO */
3472 (cellHandle, entry->serverNumber[idx],
3473 entry->serverPartition[idx], entry->volumeId[ROVOL], &tst)) {
3475 } else if (tst == ENODEV) { /* RW volume does not exist */
3476 Lp_SetROValue(cellHandle, entry, entry->serverNumber[idx],
3477 entry->serverPartition[idx], 0L, 0L);
3482 goto fail_CheckVldbRO;
3486 if (foundro) { /* A RO volume exists */
3487 if (!(entry->flags & RO_EXISTS)) { /* ... yet entry says RW does not e
3489 entry->flags |= RO_EXISTS; /* ... so say RW does exist */
3492 } else { /* A RO volume does not exist */
3493 if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
3494 entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
3503 *modified = modentry;
3511 /*ensure that <entry> matches with the info on file servers */
3513 CheckVldb(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3514 afs_int32 * modified, afs_status_p st)
3517 afs_status_t tst = 0;
3521 afs_int32 modentry = 0;
3522 afs_int32 delentry = 0;
3528 if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
3530 goto fail_CheckVldb;
3535 /* Check to see if the VLDB is ok without locking it (pass 1).
3536 * If it will change, then lock the VLDB entry, read it again,
3537 * then make the changes to it (pass 2).
3541 ubik_VL_SetLock(cellHandle->vos, 0, entry->volumeId[RWVOL],
3542 RWVOL, VLOP_DELETE);
3544 goto fail_CheckVldb;
3548 if (!aVLDB_GetEntryByID
3549 (cellHandle, entry->volumeId[RWVOL], RWVOL, entry, &tst)) {
3550 goto fail_CheckVldb;
3556 /* Check if the RW and BK entries are ok */
3557 if (!CheckVldbRWBK(cellHandle, entry, &modentry, &tst)) {
3558 goto fail_CheckVldb;
3560 if (modentry && (pass == 1))
3563 /* Check if the RO volumes entries are ok */
3564 if (!CheckVldbRO(cellHandle, entry, &modentry, &tst)) {
3565 goto fail_CheckVldb;
3567 if (modentry && (pass == 1))
3570 /* The VLDB entry has been updated. If it as been modified, then
3571 * write the entry back out the the VLDB.
3577 if (!(entry->flags & RW_EXISTS) && !(entry->flags & BACK_EXISTS)
3578 && !(entry->flags & RO_EXISTS)) {
3579 /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
3581 ubik_VL_DeleteEntry(cellHandle->vos, 0,
3582 entry->volumeId[RWVOL], RWVOL);
3584 goto fail_CheckVldb;
3588 /* Replace old entry with our new one */
3589 if (!VLDB_ReplaceEntry
3590 (cellHandle, entry->volumeId[RWVOL], RWVOL, entry,
3591 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP),
3593 goto fail_CheckVldb;
3606 ubik_VL_ReleaseLock(cellHandle->vos, 0,
3607 entry->volumeId[RWVOL], RWVOL,
3608 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
3621 /*synchronise <aserver> <apart>(if flags = 1) with the vldb .
3622 *if flags = 0, synchronise all the valid partitions on <aserver>*/
3624 UV_SyncServer(afs_cell_handle_p cellHandle, struct rx_connection *server,
3625 afs_int32 apart, int flags, afs_status_p st)
3628 afs_status_t tst = 0;
3629 afs_int32 code, vcode;
3631 afs_int32 nentries, tentries = 0;
3632 struct VldbListByAttributes attributes;
3633 nbulkentries arrayEntries;
3635 register struct nvldbentry *vllist;
3638 afs_int32 modified = 0;
3643 arrayEntries.nbulkentries_val = 0;
3645 /* Set up attributes to search VLDB */
3646 attributes.server = ntohl(rx_HostOf(rx_PeerOf(server)));
3647 attributes.Mask = VLLIST_SERVER;
3649 attributes.partition = apart;
3650 attributes.Mask |= VLLIST_PARTITION;
3653 for (si = 0; si != -1; si = nsi) {
3654 /*initialize to hint the stub to alloc space */
3655 memset(&arrayEntries, 0, sizeof(arrayEntries));
3656 if (!VLDB_ListAttributes
3657 (cellHandle, &attributes, &nentries, &arrayEntries, &tst)) {
3658 goto fail_UV_SyncServer;
3661 tentries += nentries;
3663 for (j = 0; j < nentries; j++) { /* process each entry */
3664 vllist = &arrayEntries.nbulkentries_val[j];
3665 if (!CheckVldb(cellHandle, vllist, &modified, &tst)) {
3670 if (arrayEntries.nbulkentries_val) {
3671 free(arrayEntries.nbulkentries_val);
3672 arrayEntries.nbulkentries_val = 0;
3679 if (arrayEntries.nbulkentries_val) {
3680 free(arrayEntries.nbulkentries_val);
3683 tst = VOLSERFAILEDOP;
3690 /* rename volume <oldname> to <newname>, changing the names of the related
3691 * readonly and backup volumes. This operation is also idempotent.
3692 * salvager is capable of recovering from rename operation stopping halfway.
3693 * to recover run syncserver on the affected machines,it will force
3694 * renaming to completion. name clashes should have been detected before
3698 UV_RenameVolume(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
3699 char *newname, afs_status_p st)
3702 afs_status_t tst = 0;
3703 afs_status_t etst = 0;
3704 afs_int32 rcode, error;
3706 char nameBuffer[256];
3708 struct rx_connection *aconn;
3712 aconn = (struct rx_connection *)0;
3716 tst = ubik_VL_SetLock(cellHandle->vos, 0, entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE); /*last param is dummy */
3718 goto fail_UV_RenameVolume;
3722 strncpy(entry->name, newname, VOLSER_OLDMAXVOLNAME);
3724 if (!VLDB_ReplaceEntry
3725 (cellHandle, entry->volumeId[RWVOL], RWVOL, entry, 0, &tst)) {
3726 goto fail_UV_RenameVolume;
3728 /*at this stage the intent to rename is recorded in the vldb, as far
3730 * is concerned, oldname is lost */
3731 if (entry->flags & RW_EXISTS) {
3732 index = Lp_GetRwIndex(cellHandle, entry, 0);
3733 if (index == -1) { /* there is a serious discrepancy */
3734 tst = VOLSERVLDB_ERROR;
3735 goto fail_UV_RenameVolume;
3738 UV_Bind(cellHandle, entry->serverNumber[index],
3739 AFSCONF_VOLUMEPORT);
3741 AFSVolTransCreate(aconn, entry->volumeId[RWVOL],
3742 entry->serverPartition[index], ITOffline, &tid);
3743 if (tst) { /*volume doesnot exist */
3744 goto fail_UV_RenameVolume;
3745 } else { /*volume exists, process it */
3748 AFSVolSetIdsTypes(aconn, tid, newname, RWVOL,
3749 entry->volumeId[RWVOL],
3750 entry->volumeId[ROVOL],
3751 entry->volumeId[BACKVOL]);
3753 tst = AFSVolEndTrans(aconn, tid, &rcode);
3756 goto fail_UV_RenameVolume;
3759 goto fail_UV_RenameVolume;
3763 rx_ReleaseCachedConnection(aconn);
3764 aconn = (struct rx_connection *)0;
3766 /*end rw volume processing */
3767 if (entry->flags & BACK_EXISTS) { /*process the backup volume */
3768 index = Lp_GetRwIndex(cellHandle, entry, 0);
3769 if (index == -1) { /* there is a serious discrepancy */
3770 tst = VOLSERVLDB_ERROR;
3771 goto fail_UV_RenameVolume;
3774 UV_Bind(cellHandle, entry->serverNumber[index],
3775 AFSCONF_VOLUMEPORT);
3777 AFSVolTransCreate(aconn, entry->volumeId[BACKVOL],
3778 entry->serverPartition[index], ITOffline, &tid);
3779 if (tst) { /*volume doesnot exist */
3780 goto fail_UV_RenameVolume;
3781 } else { /*volume exists, process it */
3782 if (strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)) {
3783 goto fail_UV_RenameVolume;
3785 strcpy(nameBuffer, newname);
3786 strcat(nameBuffer, ".backup");
3789 AFSVolSetIdsTypes(aconn, tid, nameBuffer, BACKVOL,
3790 entry->volumeId[RWVOL], 0, 0);
3792 tst = AFSVolEndTrans(aconn, tid, &rcode);
3795 goto fail_UV_RenameVolume;
3798 goto fail_UV_RenameVolume;
3801 } /* end backup processing */
3803 rx_ReleaseCachedConnection(aconn);
3804 aconn = (struct rx_connection *)0;
3805 if (entry->flags & RO_EXISTS) { /*process the ro volumes */
3806 for (i = 0; i < entry->nServers; i++) {
3807 if (entry->serverFlags[i] & ITSROVOL) {
3809 UV_Bind(cellHandle, entry->serverNumber[i],
3810 AFSCONF_VOLUMEPORT);
3812 AFSVolTransCreate(aconn, entry->volumeId[ROVOL],
3813 entry->serverPartition[i], ITOffline,
3815 if (tst) { /*volume doesnot exist */
3816 goto fail_UV_RenameVolume;
3817 } else { /*volume exists, process it */
3818 strcpy(nameBuffer, newname);
3819 strcat(nameBuffer, ".readonly");
3820 if (strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)) {
3821 goto fail_UV_RenameVolume;
3824 AFSVolSetIdsTypes(aconn, tid, nameBuffer, ROVOL,
3825 entry->volumeId[RWVOL], 0, 0);
3827 tst = AFSVolEndTrans(aconn, tid, &rcode);
3830 goto fail_UV_RenameVolume;
3833 goto fail_UV_RenameVolume;
3837 rx_ReleaseCachedConnection(aconn);
3838 aconn = (struct rx_connection *)0;
3844 fail_UV_RenameVolume:
3848 ubik_VL_ReleaseLock(cellHandle->vos, 0,
3849 entry->volumeId[RWVOL], RWVOL,
3850 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3857 etst = AFSVolEndTrans(aconn, tid, &rcode);
3864 rx_ReleaseCachedConnection(aconn);
3872 /*group all the volume entries on< apart >by their parentid or by their ids'
3873 *if the volume is rw. <count> is the number of entries to be processesd.
3874 *<pntr> points to the first entry.< myQueue> is the queue with entries
3877 GroupEntries(struct rx_connection *server, volintInfo * pntr, afs_int32 count,
3878 struct qHead *myQueue, afs_int32 apart)
3880 struct aqueue *qPtr;
3882 afs_int32 curId, code;
3884 afs_int32 error = 0;
3890 for (i = 0; i < count; i++) { /*process each entry */
3891 if (pntr->status) { /* entry is valid */
3892 if (pntr->type == RWVOL)
3893 curId = pntr->volid;
3895 curId = pntr->parentID;
3896 Lp_QScan(myQueue, curId, &success, &qPtr, 0);
3897 if (success) { /*entry exists in the queue */
3898 if (pntr->type == RWVOL) {
3899 /*check if the rw exists already, if so hang on the
3900 * later version if the present version is ok */
3901 if (qPtr->isValid[RWVOL]) {
3902 /*this should not happen, there is a serious error here */
3904 error = VOLSERMULTIRWVOL;
3906 qPtr->isValid[RWVOL] = 1;
3907 qPtr->copyDate[RWVOL] = pntr->copyDate;
3908 if (!qPtr->isValid[BACKVOL])
3909 qPtr->ids[BACKVOL] = pntr->backupID;
3910 if (!qPtr->isValid[ROVOL])
3911 qPtr->ids[ROVOL] = pntr->cloneID;
3913 } else if (pntr->type == BACKVOL) {
3914 if (qPtr->isValid[BACKVOL]) {
3915 /*do different checks, delete superflous volume */
3916 if (qPtr->copyDate[BACKVOL] > pntr->copyDate) {
3917 /*delete the present volume . */
3919 CheckAndDeleteVolume(server, apart, 0,
3927 /*delete the older volume after making sure, current one is ok */
3929 CheckAndDeleteVolume(server, apart,
3931 qPtr->ids[BACKVOL]);
3937 qPtr->copyDate[BACKVOL] = pntr->copyDate;
3938 qPtr->ids[BACKVOL] = pntr->volid;
3942 qPtr->isValid[BACKVOL] = 1;
3943 qPtr->ids[BACKVOL] = pntr->volid;
3944 qPtr->copyDate[BACKVOL] = pntr->copyDate;
3946 } else if (pntr->type == ROVOL) {
3947 if (qPtr->isValid[ROVOL]) {
3948 /*do different checks, delete superflous volume */
3949 if (qPtr->copyDate[ROVOL] > pntr->copyDate) {
3950 /*delete the present volume . */
3953 CheckAndDeleteVolume(server, apart, 0,
3960 /*delete the older volume after making sure, current one is ok */
3962 CheckAndDeleteVolume(server, apart,
3970 qPtr->copyDate[ROVOL] = pntr->copyDate;
3971 qPtr->ids[ROVOL] = pntr->volid;
3975 qPtr->isValid[ROVOL] = 1;
3976 qPtr->ids[ROVOL] = pntr->volid;
3977 qPtr->copyDate[ROVOL] = pntr->copyDate;
3981 error = VOLSERBADOP;
3983 } else { /*create a fresh entry */
3984 qPtr = (struct aqueue *)malloc(sizeof(struct aqueue));
3985 if (pntr->type == RWVOL) {
3986 qPtr->isValid[RWVOL] = 1;
3987 qPtr->isValid[BACKVOL] = 0;
3988 qPtr->isValid[ROVOL] = 0;
3989 qPtr->ids[RWVOL] = pntr->volid;
3990 qPtr->ids[BACKVOL] = pntr->backupID;
3991 qPtr->ids[ROVOL] = pntr->cloneID;
3992 qPtr->copyDate[RWVOL] = pntr->copyDate;
3993 strncpy(qPtr->name, pntr->name, VOLSER_OLDMAXVOLNAME);
3995 } else if (pntr->type == BACKVOL) {
3996 qPtr->isValid[RWVOL] = 0;
3997 qPtr->isValid[BACKVOL] = 1;
3998 qPtr->isValid[ROVOL] = 0;
3999 qPtr->ids[RWVOL] = pntr->parentID;
4000 qPtr->ids[BACKVOL] = pntr->volid;
4001 qPtr->ids[ROVOL] = 0;
4002 qPtr->copyDate[BACKVOL] = pntr->copyDate;
4003 vsu_ExtractName(qPtr->name, pntr->name);
4005 } else if (pntr->type == ROVOL) {
4006 qPtr->isValid[RWVOL] = 0;
4007 qPtr->isValid[BACKVOL] = 0;
4008 qPtr->isValid[ROVOL] = 1;
4009 qPtr->ids[RWVOL] = pntr->parentID;
4010 qPtr->ids[BACKVOL] = 0;
4011 qPtr->ids[ROVOL] = pntr->volid;
4012 qPtr->copyDate[ROVOL] = pntr->copyDate;
4013 vsu_ExtractName(qPtr->name, pntr->name);
4017 Lp_QAdd(myQueue, qPtr);
4019 pntr++; /*get next entry */
4029 /*report on all the active transactions on volser */
4031 UV_VolserStatus(struct rx_connection *server, transDebugInfo ** rpntr,
4032 afs_int32 * rcount, afs_status_p st)
4035 afs_status_t tst = 0;
4036 transDebugEntries transInfo;
4038 transInfo.transDebugEntries_val = (transDebugInfo *) 0;
4039 transInfo.transDebugEntries_len = 0;
4040 tst = AFSVolMonitor(server, &transInfo);
4042 goto fail_UV_VolserStatus;
4045 *rcount = transInfo.transDebugEntries_len;
4046 *rpntr = transInfo.transDebugEntries_val;
4049 fail_UV_VolserStatus:
4052 if (transInfo.transDebugEntries_val) {
4053 free(transInfo.transDebugEntries_val);
4063 /*delete the volume without interacting with the vldb */
4065 UV_VolumeZap(afs_cell_handle_p cellHandle, struct rx_connection *server,
4066 unsigned int partition, afs_uint32 volumeId, afs_status_p st)
4068 afs_int32 rcode, ttid, error, code;
4070 afs_status_t tst = 0;
4076 tst = AFSVolTransCreate(server, volumeId, partition, ITOffline, &ttid);
4078 tst = AFSVolDeleteVolume(server, ttid);
4080 tst = AFSVolEndTrans(server, ttid, &rcode);
4088 * We failed to delete the volume, but we still need
4089 * to end the transaction.
4091 AFSVolEndTrans(server, ttid, &rcode);
4103 UV_SetVolume(struct rx_connection *server, afs_int32 partition,
4104 afs_uint32 volid, afs_int32 transflag, afs_int32 setflag,
4105 unsigned int sleepTime, afs_status_p st)
4108 afs_status_t tst = 0;
4109 afs_status_t etst = 0;
4113 tst = AFSVolTransCreate(server, volid, partition, transflag, &tid);
4115 goto fail_UV_SetVolume;
4118 tst = AFSVolSetFlags(server, tid, setflag);
4120 goto fail_UV_SetVolume;
4131 etst = AFSVolEndTrans(server, tid, &rcode);
4132 /* FIXME: this looks like a typo */
4135 tst = (etst ? etst : rcode);