2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
19 #include <sys/statfs.h>
26 #include <netinet/in.h>
29 #include <afs/voldefs.h>
32 #include <afs/vlserver.h>
35 #include <afs/cellconfig.h>
38 #include <afs/afsint.h>
42 #include <afs/com_err.h>
44 #include <afs/kautils.h>
47 #define ERRCODE_RANGE 8 /* from error_table.h */
48 #define CLOCKSKEW 2 /* not really skew, but resolution */
50 /* for UV_MoveVolume() recovery */
52 #include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
55 afs_int32 VolumeExists(), CheckVldbRWBK(), CheckVldb();
57 struct ubik_client *cstruct;
59 extern struct rx_securityClass *rxnull_NewClientSecurityObject();
60 extern struct rx_connection *rx_NewConnection();
61 extern void AFSVolExecuteRequest();
62 extern struct rx_securityClass *rxnull_NewServerSecurityObject();
63 extern int VL_GetNewVolumeId();
64 extern int VL_SetLock();
65 extern int VL_ReleaseLock();
66 extern int VL_DeleteEntry();
68 void MapNetworkToHost();
69 void MapHostToNetwork();
73 afs_int32 vldbEntryIndex;
76 /*map the partition <partId> into partition name <partName>*/
78 MapPartIdIntoName(partId, partName)
82 if(partId < 26) {/* what if partId > = 26 ? */
83 strcpy(partName,"/vicep");
84 partName[6] = partId + 'a';
87 } else if (partId < VOLMAXPARTS) {
88 strcpy(partName,"/vicep");
90 partName[6] = 'a' + (partId/26);
91 partName[7] = 'a' + (partId%26);
103 fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
104 response = c = getchar();
105 while (!(c==EOF || c=='\n')) c=getchar(); /*skip to end of line*/
106 code = (response=='y'||response=='Y');
111 PrintError(msg, errcode)
116 /*replace by a big switch statement*/
120 case -1 : fprintf(STDERR,"Possible communication failure\n");
122 case VSALVAGE: fprintf(STDERR,"Volume needs to be salvaged\n");
124 case VNOVNODE: fprintf(STDERR,"Bad vnode number quoted\n");
126 case VNOVOL: fprintf(STDERR,"Volume not attached, does not exist, or not on line\n");
128 case VVOLEXISTS:fprintf(STDERR,"Volume already exists\n");
130 case VNOSERVICE:fprintf(STDERR,"Volume is not in service\n");
132 case VOFFLINE: fprintf(STDERR,"Volume is off line\n");
134 case VONLINE: fprintf(STDERR,"Volume is already on line\n");
136 case VDISKFULL: fprintf(STDERR,"Partition is full\n");
138 case VOVERQUOTA:fprintf(STDERR,"Volume max quota exceeded\n");
140 case VBUSY: fprintf(STDERR,"Volume temporarily unavailable\n");
142 case VMOVED:fprintf(STDERR,"Volume has moved to another server\n");
144 case VL_IDEXIST : fprintf(STDERR,"VLDB: volume Id exists in the vldb\n");
146 case VL_IO: fprintf(STDERR,"VLDB: a read terminated too early\n");
148 case VL_NAMEEXIST: fprintf(STDERR,"VLDB: volume entry exists in the vldb\n");
150 case VL_CREATEFAIL: fprintf(STDERR,"VLDB: internal creation failure\n");
152 case VL_NOENT: fprintf(STDERR,"VLDB: no such entry\n");
154 case VL_EMPTY: fprintf(STDERR,"VLDB: vldb database is empty\n");
156 case VL_ENTDELETED: fprintf(STDERR,"VLDB: entry is deleted (soft delete)\n");
158 case VL_BADNAME: fprintf(STDERR,"VLDB: volume name is illegal\n");
160 case VL_BADINDEX: fprintf(STDERR,"VLDB: index was out of range\n");
162 case VL_BADVOLTYPE: fprintf(STDERR,"VLDB: bad volume type\n");
164 case VL_BADSERVER: fprintf(STDERR,"VLDB: illegal server number (not within limits)\n");
166 case VL_BADPARTITION: fprintf(STDERR,"VLDB: bad partition number\n");
168 case VL_REPSFULL: fprintf(STDERR,"VLDB: run out of space for replication sites\n");
170 case VL_NOREPSERVER: fprintf(STDERR,"VLDB: no such repsite server exists\n");
172 case VL_DUPREPSERVER: fprintf(STDERR,"VLDB: replication site server already exists\n");
174 case VL_RWNOTFOUND: fprintf(STDERR,"VLDB: parent r/w entry not found\n");
176 case VL_BADREFCOUNT: fprintf(STDERR,"VLDB: illegal reference count number\n");
178 case VL_SIZEEXCEEDED: fprintf(STDERR,"VLDB: vldb size for attributes exceeded\n");
180 case VL_BADENTRY: fprintf(STDERR,"VLDB: bad incoming vldb entry\n");
182 case VL_BADVOLIDBUMP: fprintf(STDERR,"VLDB: illegal max volid increment\n");
184 case VL_IDALREADYHASHED: fprintf(STDERR,"VLDB: (RO/BACK) Id already hashed\n");
186 case VL_ENTRYLOCKED: fprintf(STDERR,"VLDB: vldb entry is already locked\n");
188 case VL_BADVOLOPER: fprintf(STDERR,"VLDB: bad volume operation code\n");
190 case VL_BADRELLOCKTYPE: fprintf(STDERR,"VLDB: bad release lock type\n");
192 case VL_RERELEASE: fprintf(STDERR,"VLDB: status report: last release was aborted\n");
194 case VL_BADSERVERFLAG: fprintf(STDERR,"VLDB: invalid replication site server flag\n");
196 case VL_PERM: fprintf(STDERR,"VLDB: no permission access for call\n");
198 case VOLSERREAD_DUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in reading the dump file !\n");
200 case VOLSERDUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in doing the dump !\n");
202 case VOLSERATTACH_ERROR: fprintf(STDERR,"VOLSER: Could not attach the volume\n");
204 case VOLSERDETACH_ERROR: fprintf(STDERR,"VOLSER: Could not detach the volume\n");
206 case VOLSERILLEGAL_PARTITION: fprintf(STDERR,"VOLSER: encountered illegal partition number\n");
208 case VOLSERBAD_ACCESS: fprintf(STDERR,"VOLSER: permission denied, not a super user\n");
210 case VOLSERVLDB_ERROR: fprintf(STDERR,"VOLSER: error detected in the VLDB\n");
212 case VOLSERBADNAME: fprintf(STDERR,"VOLSER: error in volume name\n");
214 case VOLSERVOLMOVED: fprintf(STDERR,"VOLSER: volume has moved\n");
216 case VOLSERBADOP: fprintf(STDERR,"VOLSER: illegal operation\n");
218 case VOLSERBADRELEASE: fprintf(STDERR,"VOLSER: release could not be completed\n");
220 case VOLSERVOLBUSY: fprintf(STDERR,"VOLSER: volume is busy\n");
222 case VOLSERNO_MEMORY: fprintf(STDERR,"VOLSER: volume server is out of memory\n");
224 case VOLSERNOVOL:fprintf(STDERR,"VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
226 case VOLSERMULTIRWVOL: fprintf(STDERR,"VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
228 case VOLSERFAILEDOP: fprintf(STDERR,"VOLSER: not all entries were successfully processed\n");
235 initialize_KA_error_table();
236 initialize_RXK_error_table();
237 initialize_KTC_error_table();
238 initialize_ACFG_error_table();
239 initialize_CMD_error_table();
240 initialize_VL_error_table();
242 offset = errcode & ((1<<ERRCODE_RANGE)-1);
243 fprintf(STDERR,"%s: %s\n",error_table_name (errcode), error_message (errcode));
251 static struct rx_securityClass *uvclass=0;
252 static int uvindex = -1;
253 /* called by VLDBClient_Init to set the security module to be used in the RPC */
254 UV_SetSecurity(as, aindex)
255 register struct rx_securityClass *as;
261 /* bind to volser on <port> <aserver> */
262 /* takes server address in network order, port in host order. dumb */
263 struct rx_connection *UV_Bind(aserver, port)
264 afs_int32 aserver, port;
266 register struct rx_connection *tc;
268 tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass, uvindex);
272 /* if <okvol> is allright(indicated by beibg able to
273 * start a transaction, delete the <delvol> */
274 static afs_int32 CheckAndDeleteVolume(aconn,apart,okvol,delvol)
275 struct rx_connection *aconn;
276 afs_int32 apart,okvol,delvol;
278 afs_int32 error,code,tid,rcode;
284 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
285 if(!error && code) error = code;
286 code = AFSVolDeleteVolume(aconn,tid);
287 if(!error && code) error = code;
288 code = AFSVolEndTrans(aconn,tid, &rcode);
289 if(!code) code = rcode;
290 if(!error && code) error = code;
294 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline,&tid);
296 code = AFSVolEndTrans(aconn,tid, &rcode);
297 if(!code) code = rcode;
298 if(!error && code) error = code;
299 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
300 if(!error && code) error = code;
301 code = AFSVolDeleteVolume(aconn,tid);
302 if(!error && code) error = code;
303 code = AFSVolEndTrans(aconn,tid, &rcode);
304 if(!code) code = rcode;
305 if(!error && code) error = code;
313 /* called by EmuerateEntry, show vldb entry in a reasonable format */
314 void SubEnumerateEntry(entry)
315 struct nvldbentry *entry;
322 fprintf(STDOUT," readWriteID %-10u ",entry->volumeId[RWVOL]);
323 if(entry->flags & RW_EXISTS) fprintf(STDOUT," valid \n");else fprintf(STDOUT," invalid \n");
324 fprintf(STDOUT," readOnlyID %-10u ",entry->volumeId[ROVOL]);
325 if(entry->flags & RO_EXISTS) fprintf(STDOUT," valid \n") ;else fprintf(STDOUT," invalid \n");
326 fprintf(STDOUT," backUpID %-10u ",entry->volumeId[BACKVOL]);
327 if(entry->flags & BACK_EXISTS) fprintf(STDOUT," valid \n"); else fprintf(STDOUT," invalid \n");
328 if((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
329 fprintf(STDOUT," releaseClone %-10u \n",entry->cloneId);
331 if (entry->flags & RW_EXISTS)
332 fprintf(STDOUT," RWrite: %-10u",entry->volumeId[RWVOL]);
333 if (entry->flags & RO_EXISTS)
334 fprintf(STDOUT," ROnly: %-10u",entry->volumeId[ROVOL]);
335 if (entry->flags & BACK_EXISTS)
336 fprintf(STDOUT," Backup: %-10u",entry->volumeId[BACKVOL]);
337 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
338 fprintf(STDOUT," RClone: %-10u",entry->cloneId);
339 fprintf(STDOUT,"\n");
341 fprintf(STDOUT," number of sites -> %u\n",entry->nServers);
342 for(i = 0; i < entry->nServers; i++) {
343 if(entry->serverFlags[i] & NEW_REPSITE)
346 for(i = 0; i < entry->nServers; i++) {
347 MapPartIdIntoName(entry->serverPartition[i],pname);
348 fprintf(STDOUT," server %s partition %s ",
349 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
350 if(entry->serverFlags[i] & ITSRWVOL) fprintf(STDOUT,"RW Site ") ; else fprintf(STDOUT,"RO Site ");
352 if (entry->serverFlags[i] & NEW_REPSITE)
353 fprintf(STDOUT," -- New release");
355 fprintf(STDOUT," -- Old release");
357 if (entry->serverFlags[i] & RO_DONTUSE)
358 fprintf(STDOUT," -- Not released");
360 fprintf(STDOUT,"\n");
367 /*enumerate the vldb entry corresponding to <entry> */
368 void EnumerateEntry(entry)
369 struct nvldbentry *entry;
372 fprintf(STDOUT,"\n");
373 fprintf(STDOUT,"%s \n",entry->name);
374 SubEnumerateEntry(entry);
378 /* forcibly remove a volume. Very dangerous call */
379 UV_NukeVolume(server, partid, volid)
381 afs_int32 partid, volid; {
382 register struct rx_connection *tconn;
383 register afs_int32 code;
385 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
387 code = AFSVolNukeVolume(tconn, partid, volid);
388 rx_DestroyConnection(tconn);
394 /* like df. Return usage of <pname> on <server> in <partition> */
395 UV_PartitionInfo(server,pname,partition)
398 struct diskPartition *partition;
400 register struct rx_connection *aconn;
404 aconn = (struct rx_connection *)0;
405 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
406 code = AFSVolPartitionInfo(aconn,pname,partition);
408 fprintf(STDERR,"Could not get information on partition %s\n",pname);
411 if(aconn) rx_DestroyConnection(aconn);
415 /* old interface to create volume */
416 UV_CreateVolume(aserver, apart, aname, anewid)
417 afs_int32 apart, aserver;
422 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
426 /* create a volume, given a server, partition number, volume name --> sends
427 * back new vol id in <anewid>*/
428 UV_CreateVolume2(aserver, apart, aname, aquota, aspare1, aspare2, aspare3, aspare4, anewid)
429 afs_int32 apart, aserver;
430 afs_int32 aspare1, aspare2, aspare3, aspare4;
436 register struct rx_connection *aconn;
438 register afs_int32 code;
440 afs_int32 rcode,vcode;
441 struct nvldbentry entry,storeEntry;/*the new vldb entry */
442 struct volintInfo tstatus;
445 aconn = (struct rx_connection *)0;
447 memset(&tstatus, 0, sizeof(struct volintInfo));
449 tstatus.maxquota = aquota;
451 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
452 /* next the next 3 available ids from the VLDB */
453 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 3, anewid);
455 fprintf(STDERR,"Could not get an Id for volume %s\n",aname);
459 code = AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
461 fprintf(STDERR,"Failed to create the volume %s %u \n",aname,*anewid);
466 code = AFSVolSetInfo(aconn, tid, &tstatus);
468 fprintf(STDERR,"Could not change quota (error %d), continuing...\n", code);
471 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
473 fprintf(STDERR,"Could not bring the volume %s %u online \n",aname,*anewid);
477 if(verbose) fprintf(STDOUT,"Volume %s %u created and brought online\n",aname,*anewid);
478 /* set up the vldb entry for this volume */
479 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
481 entry.serverNumber[0] = aserver; /* this should have another
482 level of indirection later */
483 entry.serverPartition[0] = apart; /* this should also have
484 another indirection level */
485 entry.flags = RW_EXISTS;/* this records that rw volume exists */
486 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
487 entry.volumeId[RWVOL] = *anewid;
488 entry.volumeId[ROVOL] = *anewid + 1;/* rw,ro, bk id are related in the default case */
489 entry.volumeId[BACKVOL] = *anewid + 2;
491 /*map into right byte order, before passing to xdr, the stuff has to be in host
492 byte order. Xdr converts it into network order */
493 MapNetworkToHost(&entry,&storeEntry);
494 /* create the vldb entry */
495 vcode = VLDB_CreateEntry(&storeEntry);
497 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,*anewid);
498 /*destroy the created volume*/
500 fprintf(STDOUT,"Deleting the newly created volume %u\n",*anewid);
502 AFSVolDeleteVolume(aconn,tid);
506 if(verbose) fprintf(STDOUT,"Created the VLDB entry for the volume %s %u\n",aname,*anewid);
507 /* volume created, now terminate the transaction and release the connection*/
508 code = AFSVolEndTrans(aconn, tid, &rcode);/*if it crashes before this
509 the volume will come online anyway when transaction timesout , so if
510 vldb entry exists then the volume is guaranteed to exist too wrt create*/
513 fprintf(STDERR,"Failed to end the transaction on the volume %s %u\n",aname,*anewid);
521 code= AFSVolEndTrans(aconn, tid, &rcode);
523 fprintf(STDERR,"WARNING: could not end transaction\n");
525 if(aconn) rx_DestroyConnection(aconn);
526 PrintError("",error);
531 /* create a volume, given a server, partition number, volume name --> sends
532 * back new vol id in <anewid>*/
533 UV_AddVLDBEntry(aserver, apart, aname, aid)
534 afs_int32 apart, aserver;
538 register struct rx_connection *aconn;
541 struct nvldbentry entry,storeEntry;/*the new vldb entry */
543 aconn = (struct rx_connection *)0;
546 /* set up the vldb entry for this volume */
547 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
549 entry.serverNumber[0] = aserver; /* this should have another
550 level of indirection later */
551 entry.serverPartition[0] = apart; /* this should also have
552 another indirection level */
553 entry.flags = RW_EXISTS;/* this records that rw volume exists */
554 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
555 entry.volumeId[RWVOL] = aid;
557 entry.volumeId[ROVOL] = anewid + 1;/* rw,ro, bk id are related in the default case */
558 entry.volumeId[BACKVOL] = *anewid + 2;
560 entry.volumeId[ROVOL] = 0;
561 entry.volumeId[BACKVOL] = 0;
564 /*map into right byte order, before passing to xdr, the stuff has to be in host
565 byte order. Xdr converts it into network order */
566 MapNetworkToHost(&entry,&storeEntry);
567 /* create the vldb entry */
568 vcode = VLDB_CreateEntry(&storeEntry);
570 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,aid);
574 if(verbose) fprintf(STDOUT,"Created the VLDB entry for the volume %s %u\n",aname,aid);
577 if(aconn) rx_DestroyConnection(aconn);
578 PrintError("",error);
582 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
584 /* Delete the volume <volid>on <aserver> <apart>
585 * the physical entry gets removed from the vldb only if the ref count
588 UV_DeleteVolume(aserver, apart, avolid)
589 afs_int32 aserver, apart, avolid;
591 struct rx_connection *aconn = (struct rx_connection *)0;
593 afs_int32 code, rcode;
595 struct nvldbentry entry,storeEntry;
597 afs_int32 avoltype = -1, vtype;
598 int notondisk = 0, notinvldb = 0;
600 /* Find and read bhe VLDB entry for this volume */
601 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
603 if (code != VL_NOENT) {
604 fprintf(STDERR,"Could not lock VLDB entry for the volume %u\n", avolid);
611 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
613 fprintf(STDERR,"Could not fetch VLDB entry for volume %u\n",avolid);
616 MapHostToNetwork(&entry);
619 EnumerateEntry(&entry);
622 /* Whether volume is in the VLDB or not. Delete the volume on disk */
623 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
624 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
626 if (code == VNOVOL) {
629 fprintf(STDERR,"Transaction on volume %u failed\n", avolid);
635 fprintf(STDOUT,"Trying to delete the volume %u ...", avolid);
638 code = AFSVolDeleteVolume(aconn, ttid);
640 fprintf(STDERR,"Could not delete the volume %u \n", avolid);
643 code = AFSVolEndTrans(aconn, ttid, &rcode);
644 code = (code ? code : rcode);
647 fprintf(STDERR,"Could not end the transaction for the volume %u \n",avolid);
651 fprintf(STDOUT," done\n");
654 /* Now update the VLDB entry.
655 * But first, verify we have a VLDB entry.
656 * Whether volume is on disk or not. Delete the volume in VLDB.
661 if (avolid == entry.volumeId[BACKVOL]) {
662 /* Its a backup volume, modify the VLDB entry. Check that the
663 * backup volume is on the server/partition we asked to delete.
665 if ( !(entry.flags & BACK_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
666 notinvldb = 2; /* Not on this server and partition */
671 fprintf(STDOUT,"Marking the backup volume %u deleted in the VLDB\n", avolid);
673 entry.flags &= ~BACK_EXISTS;
677 else if (avolid == entry.volumeId[ROVOL]) {
678 /* Its a read-only volume, modify the VLDB entry. Check that the
679 * readonly volume is on the server/partition we asked to delete.
680 * If flags does not have RO_EIXSTS set, then this may mean the RO
681 * hasn't been released (and could exist in VLDB).
683 if (!Lp_ROMatch(aserver,apart,&entry)) {
684 notinvldb = 2; /* Not found on this server and partition */
689 fprintf(STDOUT,"Marking the readonly volume %u deleted in the VLDB\n", avolid);
691 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
693 if (!Lp_ROMatch(0,0,&entry))
694 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
698 else if (avolid == entry.volumeId[RWVOL]) {
699 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
700 * Check that the readwrite volumes is on the server/partition we
703 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
704 notinvldb = 2; /* Not found on this server and partition */
708 /* Delete backup if it exists */
709 code = AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart, ITOffline, &ttid);
712 fprintf(STDOUT,"Trying to delete the backup volume %u ...", entry.volumeId[BACKVOL]);
715 code = AFSVolDeleteVolume(aconn, ttid);
717 fprintf(STDERR,"Could not delete the volume %u \n", entry.volumeId[BACKVOL]);
720 code = AFSVolEndTrans(aconn, ttid, &rcode);
722 code = (code ? code : rcode);
724 fprintf(STDERR,"Could not end the transaction for the volume %u \n",
725 entry.volumeId[BACKVOL]);
729 fprintf(STDOUT," done\n");
733 fprintf(STDOUT,"Marking the readwrite volume %u%s deleted in the VLDB\n",
734 avolid, ((entry.flags & BACK_EXISTS)?", and its backup volume,":""));
736 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
738 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
741 if (entry.flags & RO_EXISTS)
742 fprintf(STDERR,"WARNING: ReadOnly copy(s) may still exist\n");
746 notinvldb = 2; /* Not found on this server and partition */
750 /* Either delete or replace the VLDB entry */
751 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
753 fprintf(STDOUT,"Last reference to the VLDB entry for %u - deleting entry\n", avolid);
754 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
756 fprintf(STDERR,"Could not delete the VLDB entry for the volume %u \n",avolid);
760 MapNetworkToHost(&entry, &storeEntry);
761 code = VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
762 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
764 fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n", avolid);
771 if (error) PrintError("", error);
773 if (notondisk && notinvldb) {
774 fprintf(STDERR,"Volume %u does not exist %s\n",
775 avolid, ((notinvldb == 2)?"on server and partition":""));
776 PrintError("", VOLSERNOVOL);
777 if (!error) error = VOLSERNOVOL;
779 else if (notondisk) {
780 fprintf(STDERR,"WARNING: Volume %u did not exist on the partition\n", avolid);
782 else if (notinvldb) {
783 fprintf(STDERR,"WARNING: Volume %u does not exist in VLDB %s\n",
784 avolid, ((notinvldb == 2)?"on server and partition":""));
788 code = AFSVolEndTrans(aconn, ttid, &rcode);
789 code = (code ? code : rcode);
791 fprintf(STDERR,"Could not end transaction on the volume %u\n", avolid);
792 PrintError("", code);
793 if (!error) error = code;
798 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, -1,
799 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
801 fprintf(STDERR,"Could not release the lock on the VLDB entry for the volume %u \n",
803 PrintError("", code);
804 if (!error) error = code;
808 if (aconn) rx_DestroyConnection(aconn);
812 /* add recovery to UV_MoveVolume */
814 #define TESTC 0 /* set to test recovery code, clear for production */
819 void sigint_handler(x)
825 "\nSIGINT handler: vos move operation in progress\n");
827 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
829 "enter second control-c to exit\n");
833 signal(SIGINT,sigint_handler);
838 #define ONERR(ec, es, ep) if (ec) { fprintf(STDERR, (es), (ep)); PrintError(" ",ec); error = (ec); goto mfail; }
840 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
841 * <atopart>. The operation is almost idempotent
844 UV_MoveVolume(afromvol, afromserver, afrompart, atoserver, atopart)
846 afs_int32 afromserver, atoserver;
847 afs_int32 afrompart, atopart;
849 struct rx_connection *toconn, *fromconn ;
850 afs_int32 fromtid, totid, clonetid;
853 char tmpName[VOLSER_MAXVOLNAME +1];
856 struct restoreCookie cookie;
857 register afs_int32 vcode, code;
858 afs_int32 newVol, volid, backupId;
859 struct volser_status tstatus;
860 struct destServer destination;
862 struct nvldbentry entry, storeEntry;
863 int i, islocked, pntg;
865 char in,lf; /* for test code */
868 #ifdef ENABLE_BUGFIX_1165
869 volEntries volumeInfo;
870 struct volintInfo *infop = 0;
874 fromconn = (struct rx_connection *)0;
875 toconn = (struct rx_connection *)0;
885 /* support control-c processing */
886 if (setjmp(env)) goto mfail;
887 (void) signal(SIGINT,sigint_handler);
892 "\nThere are three tests points - verifies all code paths through recovery.\n");
893 fprintf(STDOUT,"First test point - operation not started.\n");
894 fprintf(STDOUT,"...test here (y, n)? ");
896 fscanf(stdin,"%c",&in);
897 fscanf(stdin,"%c",&lf); /* toss away */
900 fprintf(STDOUT,"type control-c\n");
908 /* or drop through */
911 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
912 ONERR (vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
914 if (entry.volumeId[RWVOL] != afromvol)
916 fprintf(STDERR,"Only RW volume can be moved\n");
920 vcode = ubik_Call(VL_SetLock, cstruct, 0,afromvol, RWVOL, VLOP_MOVE);
921 ONERR (vcode, "Could not lock entry for volume %u \n", afromvol);
924 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
925 ONERR (vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
927 backupId = entry.volumeId[BACKVOL];
928 MapHostToNetwork(&entry);
930 if ( !Lp_Match(afromserver, afrompart, &entry) )
932 /* the from server and partition do not exist in the vldb entry corresponding to volid */
933 if ( !Lp_Match(atoserver, atopart, &entry) )
935 /* the to server and partition do not exist in the vldb entry corresponding to volid */
936 fprintf(STDERR,"The volume %u is not on the specified site. \n", afromvol);
937 fprintf(STDERR,"The current site is :");
938 for (i=0; i<entry.nServers; i++)
940 if (entry.serverFlags[i] == ITSRWVOL)
943 MapPartIdIntoName(entry.serverPartition[i],pname);
944 fprintf(STDERR," server %s partition %s \n",
945 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
948 vcode = ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
949 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
950 ONERR (vcode, " Could not release lock on the VLDB entry for the volume %u \n",
953 return VOLSERVOLMOVED;
956 /* delete the volume afromvol on src_server */
957 /* from-info does not exist but to-info does =>
958 * we have already done the move, but the volume
959 * may still be existing physically on from fileserver
961 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
965 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline, &fromtid);
967 { /* volume exists - delete it */
968 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
969 ONERR (code, "Failed to set flags on the volume %u\n", afromvol);
971 code = AFSVolDeleteVolume(fromconn,fromtid);
972 ONERR (code, "Failed to delete the volume %u\n", afromvol);
974 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
976 if (!code) code = rcode;
977 ONERR (code, "Could not end the transaction for the volume %u \n", afromvol);
980 /*delete the backup volume now */
982 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
984 { /* backup volume exists - delete it */
985 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
986 ONERR (code, "Failed to set flags on the backup volume %u\n", backupId);
988 code = AFSVolDeleteVolume(fromconn,fromtid);
989 ONERR (code, "Could not delete the backup volume %u\n", backupId);
991 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
993 if (!code) code = rcode;
994 ONERR (code,"Could not end the transaction for the backup volume %u \n",backupId);
1002 /* From-info matches the vldb info about volid,
1003 * its ok start the move operation, the backup volume
1004 * on the old site is deleted in the process
1006 if (afrompart == atopart)
1008 same = VLDB_IsSameAddrs (afromserver, atoserver, &error);
1011 fprintf(STDERR, "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1012 afromserver, error);
1015 if (same) ONERR (VOLSERVOLMOVED,
1016 "Warning: Moving volume %u to its home partition ignored!\n", afromvol);
1020 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1021 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1022 fromtid = totid = 0; /* initialize to uncreated */
1025 * clone the read/write volume locally.
1028 if (verbose) fprintf(STDOUT,"Starting transaction on source volume %u ...",afromvol);
1030 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1031 ONERR (code, "Failed to create transaction on the volume %u\n", afromvol);
1032 if (verbose) fprintf(STDOUT," done\n");
1034 /* Get a clone id */
1036 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1037 ONERR (vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1039 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1040 if (verbose) fprintf (STDOUT,"Cloning source volume %u ...", afromvol);
1042 strcpy(vname, "move-clone-temp");
1043 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &newVol);
1044 ONERR (code, "Failed to clone the source volume %u\n", afromvol);
1045 if (verbose) fprintf(STDOUT," done\n");
1047 /* lookup the name of the volume we just cloned */
1049 code = AFSVolGetName(fromconn, fromtid, &volName);
1050 ONERR (code, "Failed to get the name of the volume %u\n", newVol);
1052 if (verbose) fprintf (STDOUT,"Ending the transaction on the source volume %u ...", afromvol);
1055 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1057 if (!code) code = rcode;
1058 ONERR (code, "Failed to end the transaction on the source volume %u\n", afromvol);
1059 if (verbose) fprintf (STDOUT," done\n");
1062 * Create the destination volume
1065 if (verbose) fprintf(STDOUT, "Starting transaction on the cloned volume %u ...", newVol);
1067 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1068 ONERR (code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1069 if (verbose) fprintf(STDOUT," done\n");
1071 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1072 ONERR (code, "Could not set falgs on the cloned volume %u\n", newVol);
1074 /* remember time from which we've dumped the volume */
1075 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1076 ONERR (code, "Failed to get the status of the cloned volume %u\n", newVol);
1078 fromDate = tstatus.creationDate-CLOCKSKEW;
1080 #ifdef ENABLE_BUGFIX_1165
1082 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1083 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1084 * don't use this information...
1086 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
1087 volumeInfo.volEntries_len = 0;
1088 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1089 ONERR (code, "Failed to get the volint Info of the cloned volume %u\n", afromvol);
1091 infop = (volintInfo *) volumeInfo.volEntries_val;
1092 infop->maxquota = -1; /* Else it will replace the default quota */
1095 /* create a volume on the target machine */
1097 code = AFSVolTransCreate (toconn, volid, atopart, ITOffline, &totid);
1100 /* Delete the existing volume.
1101 * While we are deleting the volume in these steps, the transaction
1102 * we started against the cloned volume (clonetid above) will be
1103 * sitting idle. It will get cleaned up after 600 seconds
1105 if (verbose) fprintf(STDOUT,"Deleting pre-existing volume %u on destination ...",volid);
1108 code = AFSVolDeleteVolume(toconn, totid);
1109 ONERR (code, "Could not delete the pre-existing volume %u on destination\n", volid);
1111 code = AFSVolEndTrans(toconn, totid, &rcode);
1113 if (!code) code = rcode;
1114 ONERR (code, "Could not end the transaction on pre-existing volume %u on destination\n",
1117 if (verbose) fprintf(STDOUT," done\n");
1120 if (verbose) fprintf(STDOUT,"Creating the destination volume %u ...",volid);
1122 code = AFSVolCreateVolume (toconn, atopart, volName, volser_RW, volid, &volid, &totid);
1123 ONERR (code, "Failed to create the destination volume %u\n", volid);
1124 if (verbose) fprintf(STDOUT," done\n");
1126 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1128 volName = (char *) 0;
1130 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1131 ONERR(code, "Failed to set the flags on the destination volume %u\n", volid);
1134 * Now dump the clone to the new volume
1137 destination.destHost = ntohl(atoserver);
1138 destination.destPort = AFSCONF_VOLUMEPORT;
1139 destination.destSSID = 1;
1141 /* Copy the clone to the new volume */
1142 if (verbose) fprintf(STDOUT, "Dumping from clone %u on source to volume %u on destination ...",
1145 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1146 cookie.type = RWVOL;
1147 cookie.parent = entry.volumeId[RWVOL];
1149 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1150 ONERR (code, "Failed to move data for the volume %u\n", volid);
1151 if (verbose) fprintf(STDOUT," done\n");
1153 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1154 if (!code) code = rcode;
1156 ONERR (code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1159 * reattach to the main-line volume, and incrementally dump it.
1163 fprintf(STDOUT,"Doing the incremental dump from source to destination for volume %u ... ",
1167 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1168 ONERR (code, "Failed to create a transaction on the source volume %u\n", afromvol);
1170 /* now do the incremental */
1171 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1172 ONERR (code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n", 0);
1173 if (verbose)fprintf(STDOUT," done\n");
1175 /* now adjust the flags so that the new volume becomes official */
1176 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1177 ONERR (code, "Failed to set the flags to make old source volume offline\n", 0);
1179 code = AFSVolSetFlags(toconn, totid, 0);
1180 ONERR (code, "Failed to set the flags to make new source volume online\n", 0);
1182 #ifdef ENABLE_BUGFIX_1165
1183 code = AFSVolSetInfo(toconn, totid, infop);
1184 ONERR (code, "Failed to set volume status on the destination volume %u\n", volid);
1187 /* put new volume online */
1188 code = AFSVolEndTrans(toconn, totid, &rcode);
1190 if (!code) code = rcode;
1191 ONERR (code, "Failed to end the transaction on the volume %u on the new site\n", afromvol);
1193 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1194 MapNetworkToHost(&entry,&storeEntry);
1195 storeEntry.flags &= ~BACK_EXISTS;
1199 fprintf(STDOUT, "Second test point - operation in progress but not complete.\n");
1200 fprintf(STDOUT,"...test here (y, n)? ");
1202 fscanf(stdin,"%c",&in);
1203 fscanf(stdin,"%c",&lf); /* toss away */
1206 fprintf(STDOUT,"type control-c\n");
1209 fprintf(stdout,".");
1214 /* or drop through */
1217 vcode = VLDB_ReplaceEntry (afromvol, -1, &storeEntry,
1218 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1221 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %s %u \n",
1222 storeEntry.name,afromvol);
1230 fprintf(STDOUT, "Third test point - operation complete but no cleanup.\n");
1231 fprintf(STDOUT,"...test here (y, n)? ");
1233 fscanf(stdin,"%c",&in);
1234 fscanf(stdin,"%c",&lf); /* toss away */
1237 fprintf(STDOUT,"type control-c\n");
1240 fprintf(stdout,".");
1245 /* or drop through */
1249 /* This is tricky. File server is very stupid, and if you mark the volume
1250 * as VTOutOfService, it may mark the *good* instance (if you're moving
1251 * between partitions on the same machine) as out of service. Since
1252 * we're cleaning this code up in DEcorum, we're just going to kludge around
1253 * it for now by removing this call. */
1254 /* already out of service, just zap it now */
1255 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1258 fprintf(STDERR,"Failed to set the flags to make the old source volume offline\n");
1262 if (atoserver != afromserver)
1264 /* set forwarding pointer for moved volumes */
1265 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1266 ONERR (code, "Failed to set the forwarding pointer for the volume %u\n", afromvol);
1269 if (verbose) fprintf(STDOUT,"Deleting old volume %u on source ...", afromvol);
1272 code = AFSVolDeleteVolume(fromconn,fromtid); /* zap original volume */
1273 ONERR (code, "Failed to delete the old volume %u on source\n", afromvol);
1275 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1277 if (!code) code = rcode;
1278 ONERR (code, "Failed to end the transaction on the old volume %u on the source\n", afromvol);
1280 if (verbose) fprintf(STDOUT," done\n");
1282 /* Delete the backup volume on the original site */
1283 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1286 fprintf(STDOUT, "WARNING : Deleting the backup volume %u on the source ...",backupId);
1289 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1290 ONERR (code, "Failed to set the flags on the backup volume on source\n", 0);
1292 code = AFSVolDeleteVolume(fromconn,fromtid);
1293 ONERR (code, "Failed to delete the backup volume on source\n", 0);
1295 code = AFSVolEndTrans(fromconn,fromtid, &rcode);
1297 if (!code) code = rcode;
1298 ONERR (code, "Failed to end the transaction on the backup volume %u on source\n", 0);
1300 fprintf(STDOUT," done\n");
1302 else code = 0; /* no backup volume? that's okay */
1305 if (verbose) fprintf(STDOUT,"Starting transaction on the cloned volume %u ...",newVol);
1308 code = AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
1309 ONERR (code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1311 if (verbose) fprintf(STDOUT," done\n");
1313 /* now delete the clone */
1314 if (verbose) fprintf(STDOUT,"Deleting the clone %u ...", newVol);
1317 code = AFSVolDeleteVolume(fromconn, clonetid);
1318 ONERR (code, "Failed to delete the cloned volume %u\n", newVol);
1320 if (verbose) fprintf(STDOUT," done\n");
1322 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1323 if (!code) code = rcode;
1325 ONERR (code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1332 fprintf(STDOUT,"Fourth test point - operation complete.\n");
1333 fprintf(STDOUT,"...test here (y, n)? ");
1335 fscanf(stdin,"%c",&in);
1336 fscanf(stdin,"%c",&lf); /* toss away */
1339 fprintf(STDOUT,"type control-c\n");
1342 fprintf(stdout,".");
1347 /* or drop through */
1350 /* normal cleanup code */
1352 if (entry.flags & RO_EXISTS) fprintf(STDERR,"WARNING : readOnly copies still exist \n");
1356 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, -1,
1357 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1360 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %u \n",
1362 if (!error) error = vcode;
1368 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1371 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n", newVol);
1372 if (!error) error = (code ? code : rcode);
1378 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1381 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",newVol);
1382 if (!error) error = (code ? code : rcode);
1388 code = AFSVolEndTrans(toconn, totid, &rcode);
1391 fprintf(STDERR,"Could not end transaction on destination volume %u\n",afromvol);
1392 if (!error) error = (code ? code : rcode);
1395 if (volName) free(volName);
1396 #ifdef ENABLE_BUGFIX_1165
1397 if (infop) free(infop);
1399 if (fromconn) rx_DestroyConnection(fromconn);
1400 if (toconn) rx_DestroyConnection(toconn);
1401 PrintError("",error);
1404 /* come here only when the sky falls */
1409 fprintf(STDOUT,"vos move: operation interrupted, cleanup in progress...\n");
1410 fprintf(STDOUT,"clear transaction contexts\n");
1414 /* unlock VLDB entry */
1416 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1417 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1419 if (clonetid) AFSVolEndTrans(fromconn, clonetid, &rcode);
1420 if (totid) AFSVolEndTrans(toconn, totid, &rcode);
1422 { /* put it on-line */
1423 AFSVolSetFlags(fromconn,fromtid,0);
1424 AFSVolEndTrans(fromconn, fromtid, &rcode);
1428 { /* get current VLDB entry */
1429 fprintf(STDOUT,"access VLDB\n");
1432 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
1435 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
1439 MapHostToNetwork(&entry);
1441 /* Delete either the volume on the source location or the target location.
1442 * If the vldb entry still points to the source location, then we know the
1443 * volume move didn't finish so we remove the volume from the target
1444 * location. Otherwise, we remove the volume from the source location.
1446 if (Lp_Match(afromserver,afrompart,&entry)) { /* didn't move - delete target volume */
1449 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1453 if (volid && toconn) {
1454 code=AFSVolTransCreate(toconn,volid,atopart, ITOffline,&totid);
1456 AFSVolSetFlags(toconn,totid, VTDeleteOnSalvage | VTOutOfService);
1457 AFSVolDeleteVolume(toconn,totid);
1458 AFSVolEndTrans(toconn,totid,&rcode);
1462 /* put source volume on-line */
1464 code=AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1466 AFSVolSetFlags(fromconn,fromtid,0);
1467 AFSVolEndTrans(fromconn,fromtid,&rcode);
1471 else { /* yep, move complete */
1474 "move complete - attempt cleanup of source partition - no guarantee\n");
1478 /* delete backup volume */
1480 code=AFSVolTransCreate (fromconn,backupId,afrompart, ITOffline,&fromtid);
1482 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1483 AFSVolDeleteVolume(fromconn,fromtid);
1484 AFSVolEndTrans(fromconn,fromtid,&rcode);
1487 /* delete source volume */
1488 code=AFSVolTransCreate (fromconn, afromvol, afrompart, ITBusy, &fromtid);
1490 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1491 if (atoserver != afromserver)
1492 AFSVolSetForwarding(fromconn,fromtid,atoserver);
1493 AFSVolDeleteVolume(fromconn,fromtid);
1494 AFSVolEndTrans(fromconn,fromtid,&rcode);
1499 /* common cleanup - delete local clone */
1501 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1503 AFSVolDeleteVolume(fromconn,clonetid);
1504 AFSVolEndTrans(fromconn,clonetid,&rcode);
1508 /* unlock VLDB entry */
1509 ubik_Call (VL_ReleaseLock, cstruct, 0, afromvol, -1,
1510 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1512 done: /* routine cleanup */
1513 if (volName) free(volName);
1514 #ifdef ENABLE_BUGFIX_1165
1515 if (infop) free(infop);
1517 if (fromconn) rx_DestroyConnection(fromconn);
1518 if (toconn) rx_DestroyConnection(toconn);
1521 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
1527 /* Make a new backup of volume <avolid> on <aserver> and <apart>
1528 * if one already exists, update it
1531 UV_BackupVolume(aserver, apart, avolid)
1532 afs_int32 aserver, apart, avolid;
1534 struct rx_connection *aconn = (struct rx_connection *)0;
1535 afs_int32 ttid = 0, btid = 0;
1537 afs_int32 code = 0, rcode = 0;
1538 char vname[VOLSER_MAXVOLNAME +1];
1539 struct nvldbentry entry, storeEntry;
1540 afs_int32 error = 0;
1541 int vldblocked = 0, vldbmod = 0, backexists = 1;
1543 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
1545 /* the calls to VLDB will succeed only if avolid is a RW volume,
1546 * since we are following the RW hash chain for searching */
1547 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
1549 fprintf(STDERR, "Could not fetch the entry for the volume %u from the VLDB \n", avolid);
1550 error = code; goto bfail;
1552 MapHostToNetwork(&entry);
1554 /* These operations require the VLDB be locked since it means the VLDB
1555 * will change or the vldb is already locked.
1557 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
1558 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
1559 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
1561 code = ubik_Call(VL_SetLock,cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
1563 fprintf(STDERR,"Could not lock the VLDB entry for the volume %u\n",avolid);
1569 /* Reread the vldb entry */
1570 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
1572 fprintf(STDERR,"Could not fetch the entry for the volume %u from the VLDB \n",avolid);
1576 MapHostToNetwork(&entry);
1579 if (!ISNAMEVALID(entry.name)) {
1580 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n", entry.name);
1581 error = VOLSERBADNAME;
1585 backupID = entry.volumeId[BACKVOL];
1586 if (backupID == INVALID_BID) {
1587 /* Get a backup volume id from the VLDB and update the vldb
1590 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
1593 "Could not allocate ID for the backup volume of %u from the VLDB\n",
1598 entry.volumeId[BACKVOL] = backupID;
1602 /* Test to see if the backup volume exists by trying to create
1603 * a transaction on the backup volume. We've assumed the backup exists.
1605 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1607 if (code != VNOVOL) {
1608 fprintf(STDERR,"Could not reach the backup volume %u\n", backupID);
1612 backexists = 0; /* backup volume does not exist */
1615 code = AFSVolEndTrans(aconn, btid, &rcode);
1617 if (code || rcode) {
1619 "Could not end transaction on the previous backup volume %u\n",
1621 error = (code ? code : rcode);
1626 /* Now go ahead and try to clone the RW volume.
1627 * First start a transaction on the RW volume
1629 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
1631 fprintf(STDERR,"Could not start a transaction on the volume %u\n",avolid);
1636 /* Clone or reclone the volume, depending on whether the backup
1637 * volume exists or not
1641 fprintf(STDOUT,"Re-cloning backup volume %u ...", backupID);
1644 code = AFSVolReClone(aconn, ttid, backupID);
1646 fprintf(STDERR,"Could not re-clone backup volume %u\n", backupID);
1653 fprintf(STDOUT,"Creating a new backup clone %u ...", backupID);
1656 strcpy(vname, entry.name);
1657 strcat(vname,".backup");
1659 code = AFSVolClone(aconn, ttid, 0,backupVolume, vname, &backupID);
1661 fprintf(STDERR,"Failed to clone the volume %u\n",avolid);
1667 /* End the transaction on the RW volume */
1668 code = AFSVolEndTrans(aconn, ttid, &rcode);
1670 if (code || rcode) {
1671 fprintf(STDERR, "Failed to end the transaction on the rw volume %u\n", avolid);
1672 error = (code ? code : rcode);
1676 /* Mork vldb as backup exists */
1677 if (!(entry.flags & BACK_EXISTS)) {
1678 entry.flags |= BACK_EXISTS;
1682 /* Now go back to the backup volume and bring it on line */
1683 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1685 fprintf(STDERR,"Failed to start a transaction on the backup volume %u\n",backupID);
1690 code = AFSVolSetFlags(aconn, btid, 0);
1692 fprintf(STDERR,"Could not mark the backup volume %u on line \n",backupID);
1697 code = AFSVolEndTrans(aconn, btid, &rcode);
1699 if (code || rcode) {
1700 fprintf(STDERR, "Failed to end the transaction on the backup volume %u\n", backupID);
1701 error = (code ? code : rcode);
1706 fprintf(STDOUT,"done\n");
1708 /* Will update the vldb below */
1712 code = AFSVolEndTrans(aconn, ttid, &rcode);
1713 if (code || rcode) {
1714 fprintf(STDERR, "Could not end transaction on the volume %u\n", avolid);
1716 error = (code ? code : rcode);
1721 code = AFSVolEndTrans(aconn, btid, &rcode);
1722 if (code || rcode) {
1723 fprintf(STDERR,"Could not end transaction the backup volume %u\n",backupID);
1725 error = (code ? code : rcode);
1729 /* Now update the vldb - if modified */
1732 MapNetworkToHost(&entry,&storeEntry);
1733 code = VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
1734 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1736 fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n",avolid);
1742 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, RWVOL,
1743 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1745 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %u \n",avolid);
1753 rx_DestroyConnection(aconn);
1755 PrintError("",error);
1759 static int DelVol (conn, vid, part, flags)
1760 struct rx_connection *conn;
1761 afs_int32 vid, part, flags;
1763 afs_int32 acode, ccode, rcode, tid;
1764 ccode = rcode = tid = 0;
1766 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
1767 if (!acode) { /* It really was there */
1768 acode = AFSVolDeleteVolume(conn, tid);
1770 fprintf(STDERR, "Failed to delete volume %u.\n", vid);
1771 PrintError ("", acode);
1773 ccode = AFSVolEndTrans(conn, tid, &rcode);
1777 fprintf(STDERR, "Failed to end transaction on volume %u.\n", vid);
1778 PrintError ("", ccode);
1785 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
1786 #define ERROREXIT(ec) { error = (ec); goto rfail; }
1788 /* Get a "transaction" on this replica. Create the volume
1789 * if necessary. Return the time from which a dump should
1790 * be made (0 if it's a new volume)
1792 static int GetTrans (vldbEntryPtr, index, connPtr, transPtr, timePtr)
1793 struct nvldbentry *vldbEntryPtr;
1795 struct rx_connection **connPtr;
1796 afs_int32 *transPtr, *timePtr;
1799 struct volser_status tstatus;
1800 int code, rcode, tcode;
1802 *connPtr = (struct rx_connection *)0;
1806 /* get connection to the replication site */
1807 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
1808 if (!*connPtr) goto fail; /* server is down */
1810 volid = vldbEntryPtr->volumeId[ROVOL];
1812 code = AFSVolTransCreate(*connPtr, volid, vldbEntryPtr->serverPartition[index],
1813 ITOffline, transPtr);
1815 /* If the volume does not exist, create it */
1816 if (!volid || code) {
1819 if (volid && (code != VNOVOL)){
1820 PrintError("Failed to start a transaction on the RO volume.\n",
1825 strcpy(volname, vldbEntryPtr->name);
1826 strcat(volname, ".readonly");
1829 fprintf(STDOUT,"Creating new volume %u on replication site %s: ",
1830 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
1834 code = AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
1836 vldbEntryPtr->volumeId[RWVOL], &volid, transPtr);
1838 PrintError("Failed to create the ro volume: ",code);
1841 vldbEntryPtr->volumeId[ROVOL] = volid;
1843 if (verbose) fprintf(STDOUT,"done.\n");
1845 /* The following is a bit redundant, since create sets these flags by default */
1846 code = AFSVolSetFlags(*connPtr, *transPtr, VTDeleteOnSalvage | VTOutOfService);
1848 PrintError("Failed to set flags on the ro volume: ", code);
1853 /* Otherwise, the transaction did succeed, so get the creation date of the
1854 * latest RO volume on the replication site
1858 fprintf(STDOUT,"Updating existing ro volume %u on %s ...\n",
1859 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
1863 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
1865 PrintError("Failed to get status of volume on destination: ",code);
1868 *timePtr = tstatus.creationDate-CLOCKSKEW;
1875 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
1877 if (!tcode) tcode = rcode;
1878 if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode);
1884 static int SimulateForwardMultiple(fromconn, fromtid, fromdate, tr,
1885 flags, cookie, results)
1886 struct rx_connection *fromconn;
1887 afs_int32 fromtid, fromdate, flags;
1890 manyResults *results;
1894 for (i=0; i<tr->manyDests_len; i++) {
1895 results->manyResults_val[i] = AFSVolForward(fromconn, fromtid,
1896 fromdate, &(tr->manyDests_val[i].server),
1897 tr->manyDests_val[i].trans, cookie);
1903 static int rel_compar (r1, r2)
1904 struct release *r1, *r2;
1906 return (r1->time - r2->time);
1909 /* UV_ReleaseVolume()
1910 * Release volume <afromvol> on <afromserver> <afrompart> to all
1911 * its RO sites (full release). Unless the previous release was
1912 * incomplete: in which case we bring the remaining incomplete
1913 * volumes up to date with the volumes that were released
1915 * forceflag: Performs a full release.
1917 * Will create a clone from the RW, then dump the clone out to
1918 * the remaining replicas. If there is more than 1 RO sites,
1919 * ensure that the VLDB says at least one RO is available all
1920 * the time: Influences when we write back the VLDB entry.
1923 UV_ReleaseVolume(afromvol, afromserver, afrompart, forceflag)
1924 afs_int32 afromserver;
1925 afs_int32 afrompart;
1930 afs_int32 code, vcode, rcode, tcode;
1931 afs_int32 cloneVolId, roVolId;
1932 struct replica *replicas=0;
1933 struct nvldbentry entry,storeEntry;
1934 int i, volcount, m, fullrelease, vldbindex;
1936 struct restoreCookie cookie;
1937 struct rx_connection **toconns=0;
1938 struct release *times=0;
1940 struct rx_connection *fromconn = (struct rx_connection *)0;
1941 afs_int32 error = 0;
1943 afs_int32 clonetid=0, onlinetid;
1944 afs_int32 fromtid=0;
1945 afs_uint32 fromdate, thisdate;
1948 manyResults results;
1949 int rwindex, roindex, roclone, roexists;
1954 } remembertime[NMAXNSERVERS];
1955 int releasecount = 0;
1956 struct volser_status volstatus;
1958 memset((char *)remembertime, 0, sizeof(remembertime));
1959 memset((char *)&results, 0, sizeof(results));
1961 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
1962 if (vcode != VL_RERELEASE)
1963 ONERROR(vcode, afromvol, "Could not lock the VLDB entry for the volume %u.\n");
1966 /* Get the vldb entry in readable format */
1967 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
1968 ONERROR(vcode, afromvol, "Could not fetch the entry for the volume %u from the VLDB.\n");
1969 MapHostToNetwork(&entry);
1972 EnumerateEntry(&entry);
1974 if (!ISNAMEVALID(entry.name))
1975 ONERROR(VOLSERBADOP, entry.name,
1976 "Volume name %s is too long, rename before releasing.\n");
1977 if (entry.volumeId[RWVOL] != afromvol)
1978 ONERROR(VOLSERBADOP, afromvol,
1979 "The volume %u being released is not a read-write volume.\n");
1980 if (entry.nServers <= 1)
1981 ONERROR(VOLSERBADOP, afromvol,
1982 "Volume %u has no replicas - release operation is meaningless!\n");
1983 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
1984 ONERROR(VOLSERBADOP, entry.name,
1985 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
1987 /* roclone is true if one of the RO volumes is on the same
1988 * partition as the RW volume. In this case, we make the RO volume
1989 * on the same partition a clone instead of a complete copy.
1992 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
1993 roclone = ((roindex == -1) ? 0 : 1);
1994 rwindex = Lp_GetRwIndex(&entry);
1996 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
1998 /* Make sure we have a RO volume id to work with */
1999 if (entry.volumeId[ROVOL] == INVALID_BID) {
2000 /* need to get a new RO volume id */
2001 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
2002 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
2004 entry.volumeId[ROVOL] = roVolId;
2005 MapNetworkToHost(&entry, &storeEntry);
2006 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2007 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2010 /* Will we be completing a previously unfinished release. -force overrides */
2011 for (fullrelease=1, i=0; (fullrelease && (i<entry.nServers)); i++) {
2012 if (entry.serverFlags[i] & NEW_REPSITE)
2015 if (forceflag && !fullrelease)
2018 /* Determine which volume id to use and see if it exists */
2019 cloneVolId = ((fullrelease || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
2020 code = VolumeExists(afromserver, afrompart, cloneVolId);
2021 roexists = ((code == ENODEV) ? 0 : 1);
2022 if (!roexists && !fullrelease)
2023 fullrelease = 1; /* Do a full release if RO clone does not exist */
2027 fprintf(STDOUT,"This is a complete release of the volume %u\n", afromvol);
2029 fprintf(STDOUT,"This is a completion of the previous release\n");
2033 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2035 ONERROR(-1, afromserver, "Cannot establish connection with server 0x%x\n");
2038 /* If the RO clone exists, then if the clone is a temporary
2039 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2040 * (it was recently added), then also delete it. We do not
2041 * want to "reclone" a temporary RO clone.
2044 (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE)) ) {
2045 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2046 if (code && (code != VNOVOL))
2051 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2052 * write this entry out to the vlserver until after the first
2053 * RO volume is released (temp RO clones don't count).
2055 for (i=0; i<entry.nServers; i++) {
2056 entry.serverFlags[i] &= ~NEW_REPSITE;
2057 entry.serverFlags[i] |= RO_DONTUSE;
2059 entry.serverFlags[rwindex] |= NEW_REPSITE;
2060 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2062 /* Begin transaction on RW and mark it busy while we clone it */
2063 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &clonetid);
2064 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2066 /* Clone or reclone the volume */
2069 fprintf(STDERR, "Recloning RW volume ...\n");
2071 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2072 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2075 strcpy(vname, entry.name);
2076 strcat(vname, ".readonly");
2078 fprintf(STDERR, "Cloning RW volume ...\n");
2080 strcpy(vname, "readonly-clone-temp");
2082 fprintf(STDERR, "Cloning RW volume to temporary RO ...\n");
2084 code = AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, &cloneVolId);
2085 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
2088 /* Get the time the RW was created for future information */
2089 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
2090 ONERROR(code, cloneVolId, "Failed to get the status of the RW volume %u\n");
2091 rwcrdate = volstatus.creationDate;
2093 /* End the transaction on the RW volume */
2094 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2096 ONERROR((code?code:rcode), cloneVolId, "Failed to end cloning transaction on RW %u\n");
2098 /* Remember clone volume ID in case we fail or are interrupted */
2099 entry.cloneId = cloneVolId;
2102 /* Bring the RO clone online - though not if it's a temporary clone */
2103 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline, &onlinetid);
2104 ONERROR(code, cloneVolId, "Failed to start transaction on volume %u\n");
2106 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
2108 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
2109 ONERROR((code?code:rcode), cloneVolId, "Failed to end transaction on RO clone %u\n");
2111 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
2113 /* Sleep so that a client searching for an online volume won't
2114 * find the clone offline and then the next RO offline while the
2115 * release brings the clone online and the next RO offline (race).
2116 * There is a fix in the 3.4 client that does not need this sleep
2117 * anymore, but we don't know what clients we have.
2119 if (entry.nServers > 2)
2122 /* Mark the RO clone in the VLDB as a good site (already released)*/
2123 entry.serverFlags[roindex] |= NEW_REPSITE;
2124 entry.serverFlags[roindex] &= ~RO_DONTUSE;
2125 entry.flags |= RO_EXISTS;
2129 /* Write out the VLDB entry only if the clone is not a temporary
2130 * clone. If we did this to a temporary clone then we would end
2131 * up marking all the ROs as "old release" making the ROs
2132 * temporarily unavailable.
2134 MapNetworkToHost(&entry, &storeEntry);
2135 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2136 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2140 /* Now we will release from the clone to the remaining RO replicas.
2141 * The first 2 ROs (counting the non-temporary RO clone) are released
2142 * individually: releasecount. This is to reduce the race condition
2143 * of clients trying to find an on-line RO volume. The remaining ROs
2144 * are released in parallel but no more than half the number of ROs
2145 * (rounded up) at a time: nservers.
2148 strcpy(vname, entry.name);
2149 strcat(vname, ".readonly");
2150 memset(&cookie, 0, sizeof(cookie));
2151 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
2152 cookie.type = ROVOL;
2153 cookie.parent = entry.volumeId[RWVOL];
2156 nservers = entry.nServers/2; /* how many to do at once, excluding clone */
2157 replicas = (struct replica *) malloc (sizeof(struct replica)*nservers+1);
2158 times = (struct release *) malloc (sizeof(struct release)*nservers+1);
2159 toconns = (struct rx_connection **) malloc (sizeof(struct rx_connection *)*nservers+1);
2160 results.manyResults_val = (afs_int32 *) malloc (sizeof(afs_int32)*nservers+1);
2161 if ( !replicas || !times || !! !results.manyResults_val || !toconns )
2162 ONERROR(ENOMEM, 0, "Failed to create transaction on the release clone\n");
2164 memset(replicas, 0, (sizeof(struct replica)*nservers+1));
2165 memset(times, 0, (sizeof(struct release)*nservers+1));
2166 memset(toconns, 0, (sizeof(struct rx_connection *)*nservers+1));
2167 memset(results.manyResults_val, 0, (sizeof(afs_int32)*nservers+1));
2169 /* Create a transaction on the cloned volume */
2170 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
2171 if (!fullrelease && code)
2172 ONERROR(VOLSERNOVOL, afromvol,"Old clone is inaccessible. Try vos release -f %u.\n");
2173 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
2175 /* For each index in the VLDB */
2176 for (vldbindex=0; vldbindex<entry.nServers; ) {
2178 /* Get a transaction on the replicas. Pick replacas which have an old release. */
2179 for (volcount=0; ((volcount<nservers) && (vldbindex<entry.nServers)); vldbindex++) {
2180 /* The first two RO volumes will be released individually.
2181 * The rest are then released in parallel. This is a hack
2182 * for clients not recognizing right away when a RO volume
2183 * comes back on-line.
2185 if ((volcount == 1) && (releasecount < 2))
2188 if (vldbindex == roindex) continue; /* the clone */
2189 if ( (entry.serverFlags[vldbindex] & NEW_REPSITE) &&
2190 !(entry.serverFlags[vldbindex] & RO_DONTUSE) ) continue;
2191 if (!(entry.serverFlags[vldbindex] & ITSROVOL)) continue; /* not a RO vol */
2194 /* Get a Transaction on this replica. Get a new connection if
2195 * necessary. Create the volume if necessary. Return the
2196 * time from which the dump should be made (0 if it's a new
2197 * volume). Each volume might have a different time.
2199 replicas[volcount].server.destHost = ntohl(entry.serverNumber[vldbindex]);
2200 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
2201 replicas[volcount].server.destSSID = 1;
2202 times[volcount].vldbEntryIndex = vldbindex;
2204 code = GetTrans(&entry, vldbindex, &(toconns[volcount]),
2205 &(replicas[volcount].trans), &(times[volcount].time));
2208 /* Thisdate is the date from which we want to pick up all changes */
2209 if (forceflag || !fullrelease || (rwcrdate > times[volcount].time)) {
2210 /* If the forceflag is set, then we want to do a full dump.
2211 * If it's not a full release, we can't be sure that the creation
2212 * date is good (so we also do a full dump).
2213 * If the RW volume was replaced (its creation date is newer than
2214 * the last release), then we can't be sure what has changed (so
2215 * we do a full dump).
2218 } else if (remembertime[vldbindex].validtime) {
2219 /* Trans was prev ended. Use the time from the prev trans
2220 * because, prev trans may have created the volume. In which
2221 * case time[volcount].time would be now instead of 0.
2223 thisdate = (remembertime[vldbindex].time < times[volcount].time) ?
2224 remembertime[vldbindex].time : times[volcount].time;
2226 thisdate = times[volcount].time;
2228 remembertime[vldbindex].validtime = 1;
2229 remembertime[vldbindex].time = thisdate;
2231 if (volcount == 0) {
2232 fromdate = thisdate;
2234 /* Include this volume if it is within 15 minutes of the earliest */
2235 if (((fromdate>thisdate)?(fromdate-thisdate):(thisdate-fromdate)) > 900) {
2236 AFSVolEndTrans(toconns[volcount], replicas[volcount].trans, &rcode);
2237 replicas[volcount].trans = 0;
2240 if (thisdate < fromdate)
2241 fromdate = thisdate;
2245 if (!volcount) continue;
2248 fprintf(STDOUT,"Starting ForwardMulti from %u to %u on %s",
2249 cloneVolId, entry.volumeId[ROVOL],
2250 hostutil_GetNameByINet(entry.serverNumber[times[0].vldbEntryIndex]));
2252 for (s=1; s<volcount; s++) {
2253 fprintf(STDOUT," and %s",
2254 hostutil_GetNameByINet(entry.serverNumber[times[s].vldbEntryIndex]));
2258 fprintf(STDOUT," (full release)");
2259 fprintf(STDOUT,".\n");
2263 /* Release the ones we have collected */
2264 tr.manyDests_val = &(replicas[0]);
2265 tr.manyDests_len = results.manyResults_len = volcount;
2266 code = AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2267 if (code == RXGEN_OPCODE) { /* RPC Interface Mismatch */
2268 code = SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2273 PrintError("Release failed: ", code);
2275 for (m=0; m<volcount; m++) {
2276 if (results.manyResults_val[m]) {
2277 if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
2278 /* we retry timed out transaction. When it is
2279 * not the first volume and the transaction wasn't found
2280 * (assume it timed out and was garbage collected by volser).
2282 PrintError("Failed to dump volume from clone to a ro site: ",
2283 results.manyResults_val[m]);
2288 code = AFSVolSetIdsTypes(toconns[m], replicas[m].trans,
2289 vname, ROVOL, entry.volumeId[RWVOL], 0, 0);
2291 if ((m == 0) || (code != ENOENT)) {
2292 PrintError("Failed to set correct names and ids: ", code);
2297 /* have to clear dest. flags to ensure new vol goes online:
2298 * because the restore (forwarded) operation copied
2299 * the V_inService(=0) flag over to the destination.
2301 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
2303 if ((m == 0) || (code != ENOENT)) {
2304 PrintError("Failed to set flags on ro volume: ", code);
2309 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
2310 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
2311 entry.flags |= RO_EXISTS;
2316 /* End the transactions and destroy the connections */
2317 for (s=0; s<volcount; s++) {
2318 if (replicas[s].trans)
2319 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
2320 replicas[s].trans = 0;
2321 if (!code) code = rcode;
2323 if ((s == 0) || (code != ENOENT)) {
2324 PrintError("Could not end transaction on a ro volume: ", code);
2326 PrintError("Transaction timed out on a ro volume. Will retry.\n", 0);
2327 if (times[s].vldbEntryIndex < vldbindex)
2328 vldbindex = times[s].vldbEntryIndex;
2333 rx_DestroyConnection(toconns[s]);
2337 MapNetworkToHost(&entry, &storeEntry);
2338 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2339 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2340 } /* for each index in the vldb */
2342 /* End the transaction on the cloned volume */
2343 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2345 if (!code) code = rcode;
2347 PrintError("Failed to end transaction on rw volume: ", code);
2349 /* Figure out if any volume were not released and say so */
2350 for (failure=0, i=0; i<entry.nServers; i++) {
2351 if (!(entry.serverFlags[i] & NEW_REPSITE))
2356 fprintf(STDERR, "The volume %u could not be released to the following %d sites:\n",
2358 for (i=0; i<entry.nServers; i++) {
2359 if (!(entry.serverFlags[i] & NEW_REPSITE)) {
2360 MapPartIdIntoName(entry.serverPartition[i],pname);
2361 fprintf(STDERR,"\t%35s %s\n",
2362 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
2366 MapNetworkToHost(&entry,&storeEntry);
2367 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, LOCKREL_TIMESTAMP);
2368 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2370 ERROREXIT(VOLSERBADRELEASE);
2373 /* All the ROs were release successfully. Remove the temporary clone */
2376 fprintf(STDOUT,"Deleting the releaseClone %u ...", cloneVolId);
2379 code = DelVol (fromconn, cloneVolId, afrompart, ITOffline);
2380 ONERROR (code, cloneVolId, "Failed to delete volume %u.\n");
2382 fprintf(STDOUT," done\n");
2386 for (i=0; i<entry.nServers; i++)
2387 entry.serverFlags[i] &= ~NEW_REPSITE;
2389 /* Update the VLDB */
2391 fprintf(STDOUT,"updating VLDB ...");
2394 MapNetworkToHost(&entry, &storeEntry);
2395 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
2396 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2397 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2399 fprintf(STDOUT," done\n");
2403 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2406 fprintf (STDERR,"Failed to end cloning transaction on the RW volume %u\n", afromvol);
2407 if (!error) error = code;
2411 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2414 fprintf (STDERR,"Failed to end transaction on the release clone %u\n", cloneVolId);
2415 if (!error) error = code;
2418 for (i=0; i<nservers; i++) {
2419 if (replicas && replicas[i].trans) {
2420 code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
2421 replicas[i].trans = 0;
2423 fprintf(STDERR,"Failed to end transaction on ro volume %u at server 0x%x\n",
2424 entry.volumeId[ROVOL],
2425 hostutil_GetNameByINet(htonl(replicas[i].server.destHost)));
2426 if (!error) error = code;
2429 if (toconns && toconns[i]) {
2430 rx_DestroyConnection(toconns[i]);
2435 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, RWVOL,
2436 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2438 fprintf(STDERR,"Could not release lock on the VLDB entry for volume %u\n", afromvol);
2439 if (!error) error = vcode;
2443 PrintError("", error);
2445 if (fromconn) rx_DestroyConnection(fromconn);
2446 if (results.manyResults_val) free (results.manyResults_val);
2447 if (replicas) free (replicas);
2448 if (toconns) free (toconns);
2449 if (times) free (times);
2454 void dump_sig_handler(x)
2456 fprintf(STDERR,"\nSignal handler: vos dump operation\n");
2460 /* Dump the volume <afromvol> on <afromserver> and
2461 * <afrompart> to <afilename> starting from <fromdate>.
2462 * DumpFunction does the real work behind the scenes after
2463 * extracting parameters from the rock
2465 UV_DumpVolume(afromvol, afromserver, afrompart, fromdate, DumpFunction, rock)
2466 afs_int32 afromserver;
2467 afs_int32 afrompart;
2470 afs_int32 (*DumpFunction)();
2473 struct rx_connection *fromconn = (struct rx_connection *)0;
2474 struct rx_call *fromcall = (struct rx_call *)0;
2475 afs_int32 fromtid=0, rxError=0, rcode=0;
2476 afs_int32 code, error = 0;
2478 if (setjmp(env)) ERROR_EXIT(EPIPE);
2479 #ifndef AFS_NT40_ENV
2480 (void) signal(SIGPIPE, dump_sig_handler);
2482 (void) signal(SIGINT, dump_sig_handler);
2484 /* get connections to the servers */
2485 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2486 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2488 fprintf(STDERR,"Could not start transaction on the volume %u to be dumped\n", afromvol);
2494 fprintf(STDERR,"Full Dump ...");
2496 fprintf(STDERR,"Incremental Dump (as of %.24s) ...",
2497 ctime((time_t *)&fromdate));
2501 fromcall = rx_NewCall(fromconn);
2502 code = StartAFSVolDump(fromcall, fromtid, fromdate);
2504 fprintf(STDERR,"Could not start the dump process \n");
2507 if (code = DumpFunction(fromcall, rock)) {
2508 fprintf(STDERR,"Error while dumping volume \n");
2513 fprintf(STDERR,"completed\n");
2517 code = rx_EndCall(fromcall, rxError);
2519 fprintf(STDERR,"Error in rx_EndCall\n");
2520 if (!error) error = code;
2524 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2525 if (code || rcode) {
2526 fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol);
2527 if (!error) error = (code?code:rcode);
2531 rx_DestroyConnection(fromconn);
2533 PrintError("", error);
2539 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
2540 * the dump file <afilename>. WriteData does all the real work
2541 * after extracting params from the rock
2543 UV_RestoreVolume(toserver, topart, tovolid, tovolname, flags, WriteData, rock)
2544 afs_int32 toserver, topart, tovolid;
2547 afs_int32 (*WriteData)();
2550 struct rx_connection *toconn,*tempconn;
2551 struct rx_call *tocall;
2552 afs_int32 totid, code, rcode, vcode,terror = 0;
2553 afs_int32 rxError = 0;
2554 struct volser_status tstatus;
2559 struct nvldbentry entry,storeEntry;
2562 struct restoreCookie cookie;
2564 afs_int32 newDate, volflag, voltype, volsertype;
2565 int index, same, errcode;
2569 memset(&cookie, 0, sizeof(cookie));
2574 tocall = (struct rx_call *)0;
2575 toconn = (struct rx_connection *)0;
2576 tempconn = (struct rx_connection *)0;
2580 if (flags & RV_RDONLY) {
2582 volsertype = volser_RO;
2585 volsertype = volser_RW;
2589 toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
2590 if(pvolid == 0) {/*alot a new id if needed */
2591 vcode = VLDB_GetEntryByName(tovolname, &entry);
2592 if(vcode == VL_NOENT) {
2593 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 1, &pvolid);
2595 fprintf(STDERR,"Could not get an Id for the volume %s\n",tovolname);
2600 } else if (flags & RV_RDONLY) {
2601 if (entry.flags & RW_EXISTS) {
2602 fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
2603 error = VOLSERBADOP;
2606 if (!entry.volumeId[ROVOL]) {
2607 fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
2608 error = VOLSERBADOP;
2611 pvolid = entry.volumeId[ROVOL];
2613 pvolid = entry.volumeId[RWVOL];
2615 }/* at this point we have a volume id to use/reuse for the volume to be restored */
2617 if(strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
2618 fprintf(STDERR,"The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",tovolname);
2619 error = VOLSERBADOP;
2622 MapPartIdIntoName(topart, partName);
2623 fprintf(STDOUT,"Restoring volume %s Id %u on server %s partition %s ..", tovolname,
2624 pvolid, hostutil_GetNameByINet(toserver), partName);
2626 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
2628 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
2630 fprintf(STDOUT,"Deleting the previous volume %u ...",pvolid);
2633 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2635 fprintf(STDERR,"Failed to start transaction on %u\n",pvolid);
2639 code = AFSVolSetFlags(toconn, totid, VTDeleteOnSalvage | VTOutOfService);
2641 fprintf(STDERR,"Could not set flags on volume %u \n",pvolid);
2645 code = AFSVolDeleteVolume(toconn,totid);
2647 fprintf(STDERR,"Could not delete volume %u\n",pvolid);
2651 code = AFSVolEndTrans(toconn, totid, &rcode);
2653 if (!code) code = rcode;
2655 fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
2659 if (verbose) fprintf(STDOUT," done\n");
2660 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
2662 fprintf(STDERR,"Could not create new volume %u\n",pvolid);
2668 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2670 fprintf(STDERR,"Failed to start transaction on %u\n",pvolid);
2676 cookie.parent = pvolid;
2677 cookie.type = voltype;
2679 strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
2681 tocall = rx_NewCall(toconn);
2682 terror = StartAFSVolRestore(tocall,totid, 1,&cookie);
2684 fprintf(STDERR,"Volume restore Failed \n");
2688 code = WriteData(tocall, rock);
2690 fprintf(STDERR,"Could not transmit data\n");
2694 terror = rx_EndCall(tocall,rxError);
2695 tocall = (struct rx_call *) 0;
2697 fprintf(STDERR,"rx_EndCall Failed \n");
2701 code = AFSVolGetStatus(toconn,totid, &tstatus);
2703 fprintf(STDERR,"Could not get status information about the volume %u\n",pvolid);
2707 code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
2709 fprintf(STDERR,"Could not set the right type and ID on %u\n",pvolid);
2714 code = AFSVolSetDate(toconn,totid, newDate);
2716 fprintf(STDERR,"Could not set the date on %u\n",pvolid);
2721 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
2722 code = AFSVolSetFlags(toconn, totid, volflag);
2724 fprintf(STDERR,"Could not mark %u online\n",pvolid );
2729 /* It isn't handled right in refail */
2730 code = AFSVolEndTrans(toconn, totid, &rcode);
2732 if(!code) code = rcode;
2734 fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
2740 fprintf(STDOUT," done\n");
2742 if (success && (!reuseID || (flags & RV_FULLRST))) {
2743 /* Volume was restored on the file server, update the
2744 * VLDB to reflect the change.
2746 vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
2747 if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
2748 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",pvolid);
2752 if (!vcode) MapHostToNetwork(&entry);
2753 if(vcode == VL_NOENT) { /* it doesnot exist already */
2754 /*make the vldb return this indication specifically*/
2755 if (verbose) fprintf(STDOUT,"------- Creating a new VLDB entry ------- \n");
2756 strcpy(entry.name, tovolname);
2758 entry.serverNumber[0] = toserver;/*should be indirect */
2759 entry.serverPartition[0] = topart;
2760 entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2761 entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2762 if (flags & RV_RDONLY)
2763 entry.volumeId[ROVOL] = pvolid;
2764 else if(tstatus.cloneID != 0){
2765 entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
2768 entry.volumeId[ROVOL] = INVALID_BID;
2769 entry.volumeId[RWVOL] = pvolid;
2771 if(tstatus.backupID != 0){
2772 entry.volumeId[BACKVOL] = tstatus.backupID;
2773 /*this should come from status info on the volume if non zero */
2776 entry.volumeId[BACKVOL] = INVALID_BID;
2777 MapNetworkToHost(&entry,&storeEntry);
2778 vcode = VLDB_CreateEntry(&storeEntry);
2780 fprintf(STDERR,"Could not create the VLDB entry for volume number %u \n",pvolid);
2785 if (verbose) EnumerateEntry(&entry);
2787 else { /*update the existing entry */
2789 fprintf(STDOUT,"Updating the existing VLDB entry\n");
2790 fprintf(STDOUT,"------- Old entry -------\n");
2791 EnumerateEntry(&entry);
2792 fprintf(STDOUT,"------- New entry -------\n");
2794 vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
2796 fprintf(STDERR,"Could not lock the entry for volume number %u \n",pvolid);
2801 strcpy(entry.name, tovolname);
2803 /* Update the vlentry with the new information */
2804 if (flags & RV_RDONLY)
2805 index = Lp_ROMatch(toserver, topart, &entry) - 1;
2807 index = Lp_GetRwIndex(&entry);
2809 /* Add the new site for the volume being restored */
2810 entry.serverNumber[entry.nServers] = toserver;
2811 entry.serverPartition[entry.nServers] = topart;
2812 entry.serverFlags[entry.nServers] =
2813 (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2816 /* This volume should be deleted on the old site
2817 * if its different from new site.
2819 same = VLDB_IsSameAddrs(toserver, entry.serverNumber[index], &errcode);
2821 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
2824 if ( (!errcode && !same) || (entry.serverPartition[index] != topart) ) {
2825 tempconn = UV_Bind(entry.serverNumber[index], AFSCONF_VOLUMEPORT);
2827 MapPartIdIntoName(entry.serverPartition[index], apartName);
2828 fprintf(STDOUT,"Deleting the previous volume %u on server %s, partition %s ...",
2830 hostutil_GetNameByINet(entry.serverNumber[index]), apartName);
2833 code = AFSVolTransCreate(tempconn, pvolid, entry.serverPartition[index], ITOffline, &temptid);
2835 code = AFSVolSetFlags(tempconn, temptid, VTDeleteOnSalvage | VTOutOfService);
2837 fprintf(STDERR,"Could not set flags on volume %u on the older site\n",pvolid);
2841 code = AFSVolDeleteVolume(tempconn,temptid);
2843 fprintf(STDERR,"Could not delete volume %u on the older site\n",pvolid);
2847 code = AFSVolEndTrans(tempconn, temptid, &rcode);
2849 if(!code) code = rcode;
2851 fprintf(STDERR,"Could not end transaction on volume %u on the older site\n",pvolid);
2855 if(verbose) fprintf(STDOUT," done\n");
2856 MapPartIdIntoName(entry.serverPartition[index],partName);
2859 entry.serverNumber[index] = toserver;
2860 entry.serverPartition[index] = topart;
2863 entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2864 MapNetworkToHost(&entry,&storeEntry);
2865 vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
2867 fprintf(STDERR,"Could not update the entry for volume number %u \n",pvolid);
2872 if(verbose) EnumerateEntry(&entry);
2879 code = rx_EndCall(tocall, rxError);
2880 if (!error) error = code;
2883 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2885 fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %u\n",pvolid);
2886 if(!error) error = vcode;
2890 code = AFSVolEndTrans(toconn, totid, &rcode);
2891 if(!code) code = rcode;
2893 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
2894 if(!error) error = code;
2898 code = AFSVolEndTrans(toconn, temptid, &rcode);
2899 if(!code) code = rcode;
2901 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
2902 if(!error) error = code;
2905 if(tempconn) rx_DestroyConnection(tempconn);
2906 if(toconn) rx_DestroyConnection(toconn);
2907 PrintError("",error);
2912 /*unlocks the vldb entry associated with <volid> */
2913 UV_LockRelease(volid)
2920 if (verbose) fprintf(STDERR,"Binding to the VLDB server\n");
2921 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,volid,-1,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
2923 fprintf(STDERR,"Could not unlock the entry for volume number %u in VLDB \n",volid);
2924 PrintError("",vcode);
2927 if (verbose) fprintf(STDERR,"VLDB updated\n");
2932 /*adds <server> and <part> as a readonly replication site for <volid>
2934 UV_AddSite(server, part, volid)
2935 afs_int32 server, part, volid;
2937 int j, nro=0, islocked=0;
2938 struct nvldbentry entry,storeEntry;
2939 afs_int32 vcode, error=0;
2942 error = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
2944 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n", volid);
2949 error = VLDB_GetEntryByID(volid,RWVOL, &entry);
2951 fprintf(STDERR,"Could not fetch the VLDB entry for volume number %u \n",volid);
2955 if (!ISNAMEVALID(entry.name)){
2956 fprintf(STDERR,"Volume name %s is too long, rename before adding site\n", entry.name);
2957 error = VOLSERBADOP;
2960 MapHostToNetwork(&entry);
2962 /* See if it's too many entries */
2963 if (entry.nServers >= NMAXNSERVERS){
2964 fprintf(STDERR,"Total number of entries will exceed %u\n", NMAXNSERVERS);
2965 error = VOLSERBADOP;
2969 /* See if it's on the same server */
2970 for (j=0; j < entry.nServers; j++) {
2971 if (entry.serverFlags[j] & ITSROVOL) {
2973 if (VLDB_IsSameAddrs(server, entry.serverNumber[j], &error)) {
2975 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
2978 MapPartIdIntoName(entry.serverPartition[j], apartName);
2979 fprintf(STDERR,"RO already exists on partition %s. Multiple ROs on a single server aren't allowed\n", apartName);
2980 error = VOLSERBADOP;
2987 /* See if it's too many RO sites - leave one for the RW */
2988 if (nro >= NMAXNSERVERS-1){
2989 fprintf(STDERR,"Total number of sites will exceed %u\n", NMAXNSERVERS-1);
2990 error = VOLSERBADOP;
2994 if (verbose) fprintf(STDOUT,"Adding a new site ...");
2996 entry.serverNumber[entry.nServers] = server;
2997 entry.serverPartition[entry.nServers] = part;
2998 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
3001 MapNetworkToHost(&entry,&storeEntry);
3002 error = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3004 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3008 if (verbose) fprintf(STDOUT," done\n");
3012 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3014 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3015 PrintError("", vcode);
3019 PrintError("", error);
3023 /*removes <server> <part> as read only site for <volid> from the vldb */
3024 UV_RemoveSite(server, part, volid)
3025 afs_int32 server, part, volid;
3028 struct nvldbentry entry,storeEntry;
3031 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3033 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3034 PrintError("",vcode);
3038 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3040 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3041 PrintError("",vcode);
3044 MapHostToNetwork(&entry);
3045 if(!Lp_ROMatch(server, part, &entry)){
3046 /*this site doesnot exist */
3047 fprintf(STDERR,"This site is not a replication site \n");
3048 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3050 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3051 PrintError("",vcode);
3052 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3057 else { /*remove the rep site */
3058 Lp_SetROValue(&entry, server, part, 0, 0);
3060 if((entry.nServers == 1) && (entry.flags & RW_EXISTS))
3061 entry.flags &= ~RO_EXISTS;
3062 if(entry.nServers < 1) { /*this is the last ref */
3063 if(verbose) fprintf(STDOUT,"Deleting the VLDB entry for %u ...",volid);
3065 vcode = ubik_Call(VL_DeleteEntry,cstruct, 0,volid, ROVOL);
3067 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",volid);
3068 PrintError("",vcode);
3071 if (verbose) fprintf(STDOUT," done\n");
3073 MapNetworkToHost(&entry,&storeEntry);
3074 fprintf(STDOUT,"Deleting the replication site for volume %u ...",volid);
3076 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3078 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3079 PrintError("",vcode);
3080 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3083 if(verbose) fprintf(STDOUT," done\n");
3088 /*sets <server> <part> as read/write site for <volid> in the vldb */
3089 UV_ChangeLocation(server, part, volid)
3090 afs_int32 server, part, volid;
3093 struct nvldbentry entry,storeEntry;
3096 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3098 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3099 PrintError("",vcode);
3102 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3104 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3105 PrintError("",vcode);
3108 MapHostToNetwork(&entry);
3109 index = Lp_GetRwIndex(&entry);
3111 /* no RW site exists */
3112 fprintf(STDERR,"No existing RW site for volume %u", volid);
3113 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3115 fprintf(STDERR,"Could not release lock on entry for volume %u \n",volid);
3116 PrintError("",vcode);
3121 else { /* change the RW site */
3122 entry.serverNumber[index] = server;
3123 entry.serverPartition[index] = part;
3124 MapNetworkToHost(&entry,&storeEntry);
3125 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3127 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3128 PrintError("",vcode);
3129 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3132 if(verbose) fprintf(STDOUT," done\n");
3137 /*list all the partitions on <aserver> */
3138 UV_ListPartitions(aserver, ptrPartList, cntp)
3140 struct partList *ptrPartList;
3143 struct rx_connection *aconn;
3144 struct pIDs partIds;
3145 struct partEntries partEnts;
3146 register int i, j=0, code;
3149 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3151 partEnts.partEntries_len = 0;
3152 partEnts.partEntries_val = (afs_int32 *)0;
3153 code = AFSVolXListPartitions(aconn, &partEnts); /* this is available only on new servers */
3154 if (code == RXGEN_OPCODE)
3156 for(i = 0; i < 26; i++) /* try old interface */
3157 partIds.partIds[i] = -1;
3158 code = AFSVolListPartitions(aconn, &partIds);
3160 for (i = 0;i < 26; i++) {
3161 if((partIds.partIds[i]) != -1) {
3162 ptrPartList->partId[j] = partIds.partIds[i];
3163 ptrPartList->partFlags[j] = PARTVALID;
3166 ptrPartList->partFlags[i] = 0;
3173 *cntp = partEnts.partEntries_len;
3174 if (*cntp > VOLMAXPARTS) {
3175 fprintf(STDERR,"Warning: number of partitions on the server too high %d (process only %d)\n",
3176 *cntp, VOLMAXPARTS);
3177 *cntp = VOLMAXPARTS;
3179 for (i = 0;i < *cntp; i++) {
3180 ptrPartList->partId[i] = partEnts.partEntries_val[i];
3181 ptrPartList->partFlags[i] = PARTVALID;
3183 free(partEnts.partEntries_val);
3187 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
3188 PrintError("",code);
3189 if(aconn) rx_DestroyConnection(aconn);
3194 /*zap the list of volumes specified by volPtrArray (the volCloneId field).
3195 This is used by the backup system */
3196 UV_ZapVolumeClones(aserver,apart,volPtr,arraySize)
3197 afs_int32 aserver, apart;
3198 afs_int32 arraySize;
3199 struct volDescription *volPtr;
3201 struct rx_connection *aconn;
3202 struct volDescription *curPtr;
3205 afs_int32 rcode = 0;
3206 afs_int32 success = 1;
3209 aconn = (struct rx_connection *)0;
3210 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3212 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3213 if(curPtr->volFlags & CLONEVALID) {
3214 curPtr->volFlags &= ~CLONEZAPPED;
3216 code = AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline, &tid);
3217 if(code) success = 0;
3219 code = AFSVolDeleteVolume(aconn, tid);
3220 if(code) success = 0;
3221 code = AFSVolEndTrans(aconn, tid, &rcode);
3222 if(code || rcode) success = 0;
3224 if(success) curPtr->volFlags |= CLONEZAPPED;
3225 if(!success) fprintf(STDERR,"Could not zap volume %u\n",curPtr->volCloneId);
3226 if(success && verbose) fprintf(STDOUT,"Clone of %s %u deleted\n", curPtr->volName,curPtr->volCloneId);
3231 if(aconn)rx_DestroyConnection(aconn);
3235 /*return a list of clones of the volumes specified by volPtrArray. Used by the
3237 UV_GenerateVolumeClones(aserver,apart,volPtr,arraySize)
3238 afs_int32 aserver, apart;
3239 afs_int32 arraySize;
3240 struct volDescription *volPtr;
3242 struct rx_connection *aconn;
3243 struct volDescription *curPtr;
3246 afs_int32 rcode = 0;
3248 int reuseCloneId = 0;
3249 afs_int32 curCloneId = 0;
3250 char cloneName[256];/*max vol name */
3252 aconn = (struct rx_connection *)0;
3253 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3255 if((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
3257 else { /*get a bunch of id's from vldb */
3258 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, arraySize, &curCloneId);
3260 fprintf(STDERR,"Could not get ID's for the clone from VLDB\n");
3261 PrintError("",code);
3266 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3267 if(curPtr->volFlags & ENTRYVALID) {
3269 curPtr->volFlags |= CLONEVALID;
3270 /*make a clone of curParentId and record as curPtr->volCloneId */
3271 code = AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline, &tid);
3272 if(verbose && code) fprintf(STDERR,"Clone for volume %s %u failed \n",curPtr->volName,curPtr->volId);
3274 curPtr->volFlags &= ~CLONEVALID; /*cant clone */
3278 if(strlen(curPtr->volName) < (VOLSER_OLDMAXVOLNAME - 9) ){
3279 strcpy(cloneName, curPtr->volName);
3280 strcat(cloneName,"-tmpClone-");
3282 else strcpy(cloneName,"-tmpClone");
3284 curPtr->volCloneId = curCloneId;
3288 code = AFSVolClone(aconn, tid, 0, readonlyVolume, cloneName,&(curPtr->volCloneId));
3290 curPtr->volFlags &= ~CLONEVALID;
3292 fprintf(STDERR,"Could not clone %s due to error %u\n", curPtr->volName,code);
3293 code=AFSVolEndTrans(aconn, tid, &rcode);
3295 fprintf(STDERR,"WARNING: could not end transaction\n");
3298 if(verbose) fprintf(STDOUT,"********** Cloned %s temporary %u\n",cloneName,curPtr->volCloneId);
3299 code = AFSVolEndTrans(aconn, tid, &rcode);
3301 curPtr->volFlags &= ~CLONEVALID;
3309 if (aconn) rx_DestroyConnection(aconn);
3314 /*list all the volumes on <aserver> and <apart>. If all = 1, then all the
3315 * relevant fields of the volume are also returned. This is a heavy weight operation.*/
3316 UV_ListVolumes(aserver,apart,all,resultPtr,size)
3317 afs_int32 aserver, apart;
3319 struct volintInfo **resultPtr;
3322 struct rx_connection *aconn;
3324 volEntries volumeInfo;
3328 *resultPtr = (volintInfo *)0;
3329 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3330 volumeInfo.volEntries_len = 0;
3332 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3333 code = AFSVolListVolumes(aconn, apart, all, &volumeInfo);
3335 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
3338 *resultPtr = volumeInfo.volEntries_val;
3339 *size = volumeInfo.volEntries_len;
3342 if(aconn) rx_DestroyConnection(aconn);
3343 PrintError("",code);
3347 /*------------------------------------------------------------------------
3348 * EXPORTED UV_XListVolumes
3351 * List the extended information for all the volumes on a particular
3352 * File Server and partition. We may either return the volume's ID
3353 * or all of its extended information.
3356 * a_serverID : Address of the File Server for which we want
3357 * extended volume info.
3358 * a_partID : Partition for which we want the extended
3360 * a_all : If non-zero, fetch ALL the volume info,
3361 * otherwise just the volume ID.
3362 * a_resultPP : Ptr to the address of the area containing
3363 * the returned volume info.
3364 * a_numEntsInResultP : Ptr for the value we set for the number of
3369 * Otherise, the return value of AFSVolXListVolumes.
3372 * This routine is closely related to UV_ListVolumes, which returns
3373 * only the standard level of detail on AFS volumes. It is a
3374 * heavyweight operation, zipping through all the volume entries for
3375 * a given server/partition.
3379 *------------------------------------------------------------------------*/
3381 UV_XListVolumes(a_serverID, a_partID, a_all, a_resultPP, a_numEntsInResultP)
3382 afs_int32 a_serverID;
3385 struct volintXInfo **a_resultPP;
3386 afs_int32 *a_numEntsInResultP;
3388 { /*UV_XListVolumes*/
3390 struct rx_connection *rxConnP; /*Ptr to the Rx connection involved*/
3391 afs_int32 code; /*Error code to return*/
3392 volXEntries volumeXInfo; /*Area for returned extended vol info*/
3395 * Set up our error code and the area for returned extended volume info.
3396 * We set the val field to a null pointer as a hint for the stub to
3400 *a_numEntsInResultP = 0;
3401 *a_resultPP = (volintXInfo *)0;
3402 volumeXInfo.volXEntries_val = (volintXInfo *)0;
3403 volumeXInfo.volXEntries_len = 0;
3406 * Bind to the Volume Server port on the File Server machine in question,
3409 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
3410 code = AFSVolXListVolumes(rxConnP, a_partID, a_all, &volumeXInfo);
3413 "[UV_XListVolumes] Couldn't fetch volume list\n");
3416 * We got the info; pull out the pointer to where the results lie
3417 * and how many entries are there.
3419 *a_resultPP = volumeXInfo.volXEntries_val;
3420 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
3424 * If we got an Rx connection, throw it away.
3427 rx_DestroyConnection(rxConnP);
3429 PrintError("", code);
3431 } /*UV_XListVolumes*/
3433 /* get all the information about volume <volid> on <aserver> and <apart> */
3434 UV_ListOneVolume(aserver,apart,volid,resultPtr)
3435 afs_int32 aserver, apart;
3437 struct volintInfo **resultPtr;
3439 struct rx_connection *aconn;
3441 volEntries volumeInfo;
3445 *resultPtr = (volintInfo *)0;
3446 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3447 volumeInfo.volEntries_len = 0;
3449 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3450 code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
3452 fprintf(STDERR,"Could not fetch the information about volume %u from the server\n",volid);
3455 *resultPtr = volumeInfo.volEntries_val;
3459 if(aconn) rx_DestroyConnection(aconn);
3460 PrintError("",code);
3464 /*------------------------------------------------------------------------
3465 * EXPORTED UV_XListOneVolume
3468 * List the extended information for a volume on a particular File
3469 * Server and partition.
3472 * a_serverID : Address of the File Server for which we want
3473 * extended volume info.
3474 * a_partID : Partition for which we want the extended
3476 * a_volID : Volume ID for which we want the info.
3477 * a_resultPP : Ptr to the address of the area containing
3478 * the returned volume info.
3482 * Otherise, the return value of AFSVolXListOneVolume.
3485 * This routine is closely related to UV_ListOneVolume, which returns
3486 * only the standard level of detail on the chosen AFS volume.
3490 *------------------------------------------------------------------------*/
3492 UV_XListOneVolume(a_serverID, a_partID, a_volID, a_resultPP)
3493 afs_int32 a_serverID;
3496 struct volintXInfo **a_resultPP;
3498 { /*UV_XListOneVolume*/
3499 struct rx_connection *rxConnP; /*Rx connection to Volume Server*/
3500 afs_int32 code; /*Error code*/
3501 volXEntries volumeXInfo; /*Area for returned info*/
3504 * Set up our error code, and the area we're in which we are returning
3505 * the info. Setting the val field to a null pointer tells the stub
3506 * to allocate space for us.
3509 *a_resultPP = (volintXInfo *)0;
3510 volumeXInfo.volXEntries_val = (volintXInfo *)0;
3511 volumeXInfo.volXEntries_len = 0;
3514 * Bind to the Volume Server port on the File Server machine in question,
3517 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
3518 code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
3521 "[UV_XListOneVolume] Couldn't fetch the volume information\n");
3524 * We got the info; pull out the pointer to where the results lie.
3526 *a_resultPP = volumeXInfo.volXEntries_val;
3529 * If we got an Rx connection, throw it away.
3532 rx_DestroyConnection(rxConnP);
3534 PrintError("",code);
3536 } /*UV_XListOneVolume*/
3539 * Given a volume we read from a partition, check if it is
3540 * represented in the VLDB correctly.
3542 * The VLDB is looked up by the RW volume id (not its name).
3543 * The RW contains the true name of the volume (BK and RO set
3544 * the name in the VLDB only on creation of the VLDB entry).
3545 * We want rules strict enough that when we check all volumes
3546 * on one partition, it does not need to be done again. IE:
3547 * two volumes on different partitions won't constantly
3548 * change a VLDB entry away from what the other set.
3549 * For RW and BK volumes, we will always check the VLDB to see
3550 * if the two exist on the server/partition. May seem redundant,
3551 * but this is an easy check of the VLDB. IE: if the VLDB entry
3552 * says the BK exists but no BK volume is there, we will detect
3553 * this when we check the RW volume.
3554 * VLDB entries are locked only when a change needs to be done.
3555 * Output changed to look a lot like the "vos syncserv" otuput.
3557 static afs_int32 CheckVolume(volumeinfo, aserver, apart, modentry, maxvolid)
3558 volintInfo *volumeinfo;
3559 afs_int32 aserver, apart;
3560 afs_int32 *modentry;
3561 afs_uint32 *maxvolid;
3564 afs_int32 code, error = 0;
3565 struct nvldbentry entry, storeEntry;
3567 int pass=0, islocked=0, createentry, addvolume, modified, mod;
3570 if (modentry) *modentry = 0;
3571 rwvolid = ((volumeinfo->type == RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
3574 /* Check to see if the VLDB is ok without locking it (pass 1).
3575 * If it will change, then lock the VLDB entry, read it again,
3576 * then make the changes to it (pass 2).
3579 code = ubik_Call(VL_SetLock, cstruct, 0, rwvolid, RWVOL, VLOP_DELETE);
3581 fprintf(STDERR, "Could not lock VLDB entry for %u\n", rwvolid);
3587 createentry = 0; /* Do we need to create a VLDB entry */
3588 addvolume = 0; /* Add this volume to the VLDB entry */
3589 modified = 0; /* The VLDB entry was modified */
3591 /* Read the entry from VLDB by its RW volume id */
3592 code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
3594 if (code != VL_NOENT) {
3595 fprintf(STDOUT,"Could not retreive the VLDB entry for volume %u \n", rwvolid);
3599 memset(&entry, 0, sizeof(entry));
3600 vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
3604 MapHostToNetwork(&entry);
3607 if (verbose && (pass == 1)) {
3608 fprintf(STDOUT,"_______________________________\n");
3609 fprintf(STDOUT,"\n-- status before -- \n");
3611 fprintf(STDOUT,"\n**does not exist**\n");
3613 if ((entry.flags & RW_EXISTS) ||
3614 (entry.flags & RO_EXISTS) ||
3615 (entry.flags & BACK_EXISTS))
3616 EnumerateEntry(&entry);
3618 fprintf(STDOUT,"\n");
3621 if (volumeinfo->type == RWVOL) { /* RW volume exists */
3627 /* Check existence of RW and BK volumes */
3628 code = CheckVldbRWBK(&entry, &mod);
3629 if (code) ERROR_EXIT(code);
3630 if (mod) modified++;
3632 idx = Lp_GetRwIndex(&entry);
3633 if (idx == -1) { /* RW index not found in the VLDB entry */
3634 idx = entry.nServers; /* put it into next index */
3637 } else { /* RW index found in the VLDB entry. */
3638 /* Verify if this volume's location matches where the VLDB says it is */
3639 if (!Lp_Match(aserver, apart, &entry)) {
3640 if (entry.flags & RW_EXISTS) {
3641 /* The RW volume exists elsewhere - report this one a duplicate */
3643 MapPartIdIntoName(apart, pname);
3644 fprintf(STDERR,"*** Warning: Orphaned RW volume %u exists on %s %s\n",
3645 rwvolid, hostutil_GetNameByINet(aserver), pname);
3646 MapPartIdIntoName(entry.serverPartition[idx], pname);
3647 fprintf(STDERR," VLDB reports RW volume %u exists on %s %s\n",
3649 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
3652 /* The RW volume does not exist - have VLDB point to this one */
3655 /* Check for orphaned BK volume on old partition */
3656 if (entry.flags & BACK_EXISTS) {
3658 MapPartIdIntoName(entry.serverPartition[idx], pname);
3659 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3660 entry.volumeId[BACKVOL],
3661 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
3662 MapPartIdIntoName(apart, pname);
3663 fprintf(STDERR," VLDB reports its RW volume %u exists on %s %s\n",
3664 rwvolid, hostutil_GetNameByINet(aserver), pname);
3669 /* Volume location matches the VLDB location */
3670 if ( (volumeinfo->backupID && !entry.volumeId[BACKVOL]) ||
3671 (volumeinfo->cloneID && !entry.volumeId[ROVOL]) ||
3672 (strncmp(entry.name,volumeinfo->name,VOLSER_OLDMAXVOLNAME) != 0) ) {
3680 entry.flags |= RW_EXISTS;
3681 entry.volumeId[RWVOL] = rwvolid;
3682 if (!entry.volumeId[BACKVOL])
3683 entry.volumeId[BACKVOL] = volumeinfo->backupID;
3684 if (!entry.volumeId[ROVOL])
3685 entry.volumeId[ROVOL] = volumeinfo->cloneID;
3687 entry.serverFlags[idx] = ITSRWVOL;
3688 entry.serverNumber[idx] = aserver;
3689 entry.serverPartition[idx] = apart;
3690 strncpy(entry.name, volumeinfo->name, VOLSER_OLDMAXVOLNAME);
3694 /* One last check - to update BK if need to */
3695 code = CheckVldbRWBK(&entry, &mod);
3696 if (code) ERROR_EXIT(code);
3697 if (mod) modified++;
3701 else if (volumeinfo->type == BACKVOL) { /* A BK volume */
3707 /* Check existence of RW and BK volumes */
3708 code = CheckVldbRWBK(&entry, &mod);
3709 if (code) ERROR_EXIT(code);
3710 if (mod) modified++;
3712 idx = Lp_GetRwIndex(&entry);
3713 if (idx == -1) { /* RW index not found in the VLDB entry */
3714 idx = entry.nServers; /* Put it into next index */
3717 } else { /* RW index found in the VLDB entry */
3718 /* Verify if this volume's location matches where the VLDB says it is */
3719 if (!Lp_Match(aserver, apart, &entry)) {
3720 /* VLDB says RW and/or BK is elsewhere - report this BK volume orphaned */
3722 MapPartIdIntoName(apart, pname);
3723 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3724 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
3725 MapPartIdIntoName(entry.serverPartition[idx], pname);
3726 fprintf(STDERR," VLDB reports its RW/BK volume %u exists on %s %s\n",
3728 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
3731 if (volumeinfo->volid != entry.volumeId[BACKVOL]) {
3732 if (!(entry.flags & BACK_EXISTS)) {
3735 else if (volumeinfo->volid > entry.volumeId[BACKVOL]) {
3739 MapPartIdIntoName(entry.serverPartition[idx], pname);
3740 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3741 entry.volumeId[BACKVOL], hostutil_GetNameByINet(aserver), pname);
3742 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
3747 MapPartIdIntoName(entry.serverPartition[idx], pname);
3748 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3749 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
3750 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
3751 entry.volumeId[BACKVOL]);
3755 else if (!entry.volumeId[BACKVOL]) {
3762 entry.flags |= BACK_EXISTS;
3763 entry.volumeId[RWVOL] = rwvolid;
3764 entry.volumeId[BACKVOL] = volumeinfo->volid;
3766 entry.serverNumber[idx] = aserver;
3767 entry.serverPartition[idx] = apart;
3768 entry.serverFlags[idx] = ITSRWVOL;
3774 else if (volumeinfo->type == ROVOL) { /* A RO volume */
3775 if (volumeinfo->volid == entry.volumeId[ROVOL]) {
3776 /* This is a quick check to see if the RO entry exists in the
3777 * VLDB so we avoid the CheckVldbRO() call (which checks if each
3778 * RO volume listed in the VLDB exists).
3780 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
3782 idx = entry.nServers;
3786 if (!(entry.flags & RO_EXISTS)) {
3791 /* Before we correct the VLDB entry, make sure all the
3792 * ROs listed in the VLDB exist.
3794 code = CheckVldbRO(&entry, &mod);
3795 if (code) ERROR_EXIT(code);
3796 if (mod) modified++;
3798 if (!(entry.flags & RO_EXISTS)) {
3799 /* No RO exists in the VLDB entry - add this one */
3800 idx = entry.nServers;
3804 else if (volumeinfo->volid > entry.volumeId[ROVOL]) {
3805 /* The volume headers's RO ID does not match that in the VLDB entry,
3806 * and the vol hdr's ID is greater (implies more recent). So delete
3807 * all the RO volumes listed in VLDB entry and add this volume.
3809 for (j=0; j<entry.nServers; j++) {
3810 if (entry.serverFlags[j] & ITSROVOL) {
3811 /* Verify this volume exists and print message we are orphaning it */
3813 MapPartIdIntoName(apart, entry.serverPartition[j]);
3814 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
3815 entry.volumeId[ROVOL],
3816 hostutil_GetNameByINet(entry.serverNumber[j]), pname);
3817 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
3821 Lp_SetRWValue(entry, entry.serverNumber[idx],
3822 entry.serverPartition[idx], 0L, 0L);
3829 idx = entry.nServers;
3833 else if (volumeinfo->volid < entry.volumeId[ROVOL]) {
3834 /* The volume headers's RO ID does not match that in the VLDB entry,
3835 * and the vol hdr's ID is lower (implies its older). So orphan it.
3838 MapPartIdIntoName(apart, pname);
3839 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
3840 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
3841 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
3842 entry.volumeId[ROVOL]);
3846 /* The RO volume ID in the volume header match that in the VLDB entry,
3847 * and there exist RO volumes in the VLDB entry. See if any of them
3848 * are this one. If not, then we add it.
3850 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
3852 idx = entry.nServers;
3860 entry.flags |= RO_EXISTS;
3861 entry.volumeId[RWVOL] = rwvolid;
3862 entry.volumeId[ROVOL] = volumeinfo->volid;
3864 entry.serverNumber[idx] = aserver;
3865 entry.serverPartition[idx] = apart;
3866 entry.serverFlags[idx] = ITSROVOL;
3872 /* Remember largest volume id */
3873 if (entry.volumeId[ROVOL] > *maxvolid) *maxvolid = entry.volumeId[ROVOL];
3874 if (entry.volumeId[BACKVOL] > *maxvolid) *maxvolid = entry.volumeId[BACKVOL];
3875 if (entry.volumeId[RWVOL] > *maxvolid) *maxvolid = entry.volumeId[RWVOL];
3878 MapNetworkToHost(&entry, &storeEntry);
3881 code = VLDB_CreateEntry(&storeEntry);
3883 fprintf(STDOUT,"Could not create a VLDB entry for the volume %u\n", rwvolid);
3888 if (pass == 1) goto retry;
3889 code = VLDB_ReplaceEntry(rwvolid, RWVOL, &storeEntry,
3890 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3892 fprintf(STDERR,"Could not update entry for %u\n", rwvolid);
3896 if (modentry) *modentry = modified;
3897 } else if (pass == 2) {
3898 code = ubik_Call(VL_ReleaseLock,cstruct, 0, rwvolid, RWVOL,
3899 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3901 PrintError("Could not unlock VLDB entry ", code);
3906 fprintf(STDOUT,"-- status after --\n");
3908 EnumerateEntry(&entry);
3910 fprintf(STDOUT,"\n**no change**\n");
3915 fprintf(STDOUT,"\n_______________________________\n");
3920 int sortVolumes(v1, v2)
3921 volintInfo *v1, *v2;
3923 afs_int32 rwvolid1, rwvolid2;
3925 rwvolid1 = ((v1->type == RWVOL) ? v1->volid : v1->parentID);
3926 rwvolid2 = ((v2->type == RWVOL) ? v2->volid : v2->parentID);
3928 if (rwvolid1 > rwvolid2) return -1; /* lower RW id goes first */
3929 if (rwvolid1 < rwvolid2) return 1;
3931 if (v1->type == RWVOL) return -1; /* RW vols go first */
3932 if (v2->type == RWVOL) return 1;
3934 if ((v1->type == BACKVOL) && (v2->type == ROVOL )) return -1; /* BK vols next */
3935 if ((v1->type == ROVOL ) && (v2->type == BACKVOL)) return 1;
3937 if (v1->volid < v2->volid) return 1; /* larger volids first */
3938 if (v1->volid > v2->volid) return -1;
3943 * Synchronise <aserver> <apart>(if flags = 1) <avolid>.
3944 * Synchronize an individual volume against a sever and partition.
3945 * Checks the VLDB entry (similar to syncserv) as well as checks
3946 * if the volume exists on specified servers (similar to syncvldb).
3948 UV_SyncVolume(aserver, apart, avolname, flags)
3949 afs_int32 aserver, apart;
3953 struct rx_connection *aconn = 0;
3954 afs_int32 j, k, code, vcode, error = 0;
3955 afs_int32 tverbose, mod, modified = 0;
3956 struct nvldbentry vldbentry;
3957 afs_int32 volumeid = 0;
3958 volEntries volumeInfo;
3959 struct partList PartList;
3961 afs_int32 maxvolid = 0;
3963 volumeInfo.volEntries_val = (volintInfo *)0;
3964 volumeInfo.volEntries_len = 0;
3966 if (!aserver && flags) {
3967 /* fprintf(STDERR,"Partition option requires a server option\n"); */
3971 /* Turn verbose logging off and do our own verbose logging */
3975 /* Read the VLDB entry */
3976 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
3977 if (vcode && (vcode != VL_NOENT)) {
3978 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
3980 } else if (!vcode) {
3981 MapHostToNetwork(&vldbentry);
3985 fprintf(STDOUT,"Processing VLDB entry %s ...\n", avolname);
3986 fprintf(STDOUT,"_______________________________\n");
3987 fprintf(STDOUT,"\n-- status before -- \n");
3989 fprintf(STDOUT,"\n**does not exist**\n");
3991 if ((vldbentry.flags & RW_EXISTS) ||
3992 (vldbentry.flags & RO_EXISTS) ||
3993 (vldbentry.flags & BACK_EXISTS))
3994 EnumerateEntry(&vldbentry);
3996 fprintf(STDOUT,"\n");
3999 /* Verify that all of the VLDB entries exist on the repective servers
4000 * and partitions (this does not require that avolname be a volume ID).
4001 * Equivalent to a syncserv.
4004 code = CheckVldb(&vldbentry, &mod);
4006 fprintf(STDERR,"Could not process VLDB entry for volume %s\n", vldbentry.name);
4009 if (mod) modified++;
4012 /* If aserver is given, we will search for the desired volume on it */
4014 /* Generate array of partitions on the server that we will check */
4016 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4018 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4022 PartList.partId[0] = apart;
4026 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4028 /* If a volume ID were given, search for it on each partition */
4029 if (volumeid = atol(avolname)) {
4030 for (j=0; j<pcnt; j++) {
4031 code = AFSVolListOneVolume(aconn, PartList.partId[j], volumeid, &volumeInfo);
4033 if (code != ENODEV) {
4034 fprintf(STDERR,"Could not query server\n");
4038 /* Found one, sync it with VLDB entry */
4039 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4040 PartList.partId[j], &mod, &maxvolid);
4041 if (code) ERROR_EXIT(code);
4042 if (mod) modified++;
4045 if (volumeInfo.volEntries_val)
4046 free(volumeInfo.volEntries_val);
4047 volumeInfo.volEntries_val = (volintInfo *)0;
4048 volumeInfo.volEntries_len = 0;
4052 /* Check to see if the RW, BK, and RO IDs exist on any
4053 * partitions. We get the volume IDs from the VLDB.
4055 rv = 1; /* Read the VLDB entry ? */
4056 for (j=0; j<MAXTYPES; j++) { /* for RW, RO, and BK IDs */
4058 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
4060 if (vcode == VL_NOENT) break;
4061 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4067 if (vldbentry.volumeId[j] == 0) continue;
4069 for (k=0; k<pcnt; k++) { /* For each partition */
4070 volumeInfo.volEntries_val = (volintInfo *)0;
4071 volumeInfo.volEntries_len = 0;
4072 code = AFSVolListOneVolume(aconn, PartList.partId[k],
4073 vldbentry.volumeId[j], &volumeInfo);
4075 if (code != ENODEV) {
4076 fprintf(STDERR,"Could not query server\n");
4080 /* Found one, sync it with VLDB entry */
4081 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4082 PartList.partId[k], &mod, &maxvolid);
4083 if (code) ERROR_EXIT(code);
4084 if (mod) modified++, rv++;
4087 if (volumeInfo.volEntries_val)
4088 free(volumeInfo.volEntries_val);
4089 volumeInfo.volEntries_val = (volintInfo *)0;
4090 volumeInfo.volEntries_len = 0;
4093 } /* if (aserver) */
4095 /* If verbose output, print a summary of what changed */
4097 fprintf(STDOUT,"-- status after --\n");
4098 code = VLDB_GetEntryByName(avolname, &vldbentry);
4099 if (code && (code != VL_NOENT)) {
4100 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4103 if (modified && (code == VL_NOENT)) {
4104 fprintf(STDOUT,"\n**entry deleted**\n");
4105 } else if (modified) {
4106 EnumerateEntry(vldbentry);
4108 fprintf(STDOUT,"\n**no change**\n");
4110 fprintf(STDOUT,"\n_______________________________\n");
4114 /* Now check if the maxvolid is larger than that stored in the VLDB */
4116 afs_int32 maxvldbid = 0;
4117 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4119 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4120 if (!error) error = code;
4121 } else if (maxvolid > maxvldbid) {
4123 id = maxvolid - maxvldbid + 1;
4124 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4126 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4127 if (!error) error = code;
4134 if (error) fprintf(STDOUT,"...error encountered");
4135 else fprintf(STDOUT,"...done entry\n");
4137 if (aconn) rx_DestroyConnection(aconn);
4138 if (volumeInfo.volEntries_val) free(volumeInfo.volEntries_val);
4140 PrintError("",error);
4145 * Synchronise vldb with the file server <aserver> and,
4146 * optionally, <apart>.
4148 UV_SyncVldb(aserver, apart, flags, force)
4149 afs_int32 aserver, apart;
4152 struct rx_connection *aconn;
4153 afs_int32 code, error=0;
4155 volEntries volumeInfo;
4156 struct partList PartList;
4160 afs_int32 failures = 0, modifications = 0, tentries = 0;
4162 afs_uint32 maxvolid = 0;
4164 volumeInfo.volEntries_val = (volintInfo *)0;
4165 volumeInfo.volEntries_len = 0;
4167 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4169 /* Generate array of partitions to check */
4171 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4173 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4177 PartList.partId[0] = apart;
4182 fprintf(STDOUT,"Processing volume entries ...\n");
4186 /* Step through the array of partitions */
4187 for (i = 0; i < pcnt; i++) {
4188 apart = PartList.partId[i];
4189 MapPartIdIntoName(apart, pname);
4191 volumeInfo.volEntries_val = (volintInfo *)0;
4192 volumeInfo.volEntries_len = 0;
4193 code = AFSVolListVolumes(aconn, apart, 1, &volumeInfo);
4195 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
4199 /* May want to sort the entries: RW, BK (high to low), RO (high to low) */
4200 qsort((char *)volumeInfo.volEntries_val, volumeInfo.volEntries_len,
4201 sizeof(volintInfo), sortVolumes);
4204 for (vi=volumeInfo.volEntries_val, j=0; j < volumeInfo.volEntries_len; j++, vi++) {
4211 fprintf(STDOUT,"Processing volume entry %d: %s (%u) on server %s %s...\n",
4212 j+1, vi->name, vi->volid,
4213 hostutil_GetNameByINet(aserver), pname);
4217 code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
4219 PrintError("",code);
4223 else if (modified) {
4229 fprintf(STDOUT,"...error encountered\n\n");
4231 fprintf(STDOUT,"...done entry %d\n\n", j+1);
4237 fprintf(STDERR,"Could not process entries on server %s partition %s\n",
4238 hostutil_GetNameByINet(aserver), pname);
4240 if (volumeInfo.volEntries_val) {
4241 free(volumeInfo.volEntries_val);
4242 volumeInfo.volEntries_val = 0;
4245 }/* thru all partitions */
4248 fprintf(STDOUT, "Total entries: %u, Failed to process %d, Changed %d\n",
4249 tentries, failures, modifications);
4253 /* Now check if the maxvolid is larger than that stored in the VLDB */
4255 afs_uint32 maxvldbid = 0;
4256 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4258 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4259 if (!error) error = code;
4260 } else if (maxvolid > maxvldbid) {
4262 id = maxvolid - maxvldbid + 1;
4263 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4265 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4266 if (!error) error = code;
4271 if (aconn) rx_DestroyConnection(aconn);
4272 if (volumeInfo.volEntries_val)
4273 free(volumeInfo.volEntries_val);
4274 PrintError("",error);
4279 * Determine if a volume exists on a server and partition.
4280 * Try creating a transaction on the volume. If we can,
4281 * the volume exists, if not, then return the error code.
4282 * Some error codes mean the volume is unavailable but
4283 * still exists - so we catch these error codes.
4285 afs_int32 VolumeExists(server, partition, volumeid)
4286 afs_int32 server, partition, volumeid;
4288 struct rx_connection *conn=(struct rx_connection *)0;
4289 afs_int32 code = -1;
4290 volEntries volumeInfo;
4292 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4294 volumeInfo.volEntries_val = (volintInfo *)0;
4295 volumeInfo.volEntries_len = 0;
4296 code = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
4297 if (volumeInfo.volEntries_val)
4298 free(volumeInfo.volEntries_val);
4299 if (code == VOLSERILLEGAL_PARTITION)
4301 rx_DestroyConnection(conn);
4309 afs_int32 CheckVldbRWBK(entry, modified)
4310 struct nvldbentry *entry;
4311 afs_int32 *modified;
4315 afs_int32 code, error = 0;
4318 if (modified) *modified = 0;
4319 idx = Lp_GetRwIndex(entry);
4321 /* Check to see if the RW volume exists and set the RW_EXISTS
4324 if (idx == -1) { /* Did not find a RW entry */
4325 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4326 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4330 code = VolumeExists(entry->serverNumber[idx],
4331 entry->serverPartition[idx],
4332 entry->volumeId[RWVOL]);
4333 if (code == 0) { /* RW volume exists */
4334 if (!(entry->flags & RW_EXISTS)) { /* ... yet entry says RW does not exist */
4335 entry->flags |= RW_EXISTS; /* ... so say RW does exist */
4339 else if (code == ENODEV) { /* RW volume does not exist */
4340 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4341 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4346 /* If VLDB says it didn't exist, then ignore error */
4347 if (entry->flags & RW_EXISTS) {
4348 MapPartIdIntoName(entry->serverPartition[idx], pname);
4349 fprintf(STDERR,"Transaction call failed for RW volume %u on server %s %s\n",
4350 entry->volumeId[RWVOL],
4351 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4357 /* Check to see if the BK volume exists and set the BACK_EXISTS
4358 * flag accordingly. idx already ponts to the RW entry.
4360 if (idx == -1) { /* Did not find a RW entry */
4361 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
4362 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
4366 else { /* Found a RW entry */
4367 code = VolumeExists(entry->serverNumber[idx],
4368 entry->serverPartition[idx],
4369 entry->volumeId[BACKVOL]);
4370 if (code == 0) { /* BK volume exists */
4371 if (!(entry->flags & BACK_EXISTS)) { /* ... yet entry says BK does not exist */
4372 entry->flags |= BACK_EXISTS; /* ... so say BK does exist */
4376 else if (code == ENODEV) { /* BK volume does not exist */
4377 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
4378 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
4383 /* If VLDB says it didn't exist, then ignore error */
4384 if (entry->flags & BACK_EXISTS) {
4385 MapPartIdIntoName(entry->serverPartition[idx], pname);
4386 fprintf(STDERR,"Transaction call failed for BK volume %u on server %s %s\n",
4387 entry->volumeId[BACKVOL],
4388 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4394 /* If there is an idx but the BK and RW volumes no
4395 * longer exist, then remove the RW entry.
4397 if ((idx != -1) && !(entry->flags & RW_EXISTS) &&
4398 !(entry->flags & BACK_EXISTS)) {
4399 Lp_SetRWValue(entry, entry->serverNumber[idx],
4400 entry->serverPartition[idx], 0L, 0L);
4406 if (modified) *modified = modentry;
4410 CheckVldbRO(entry, modified)
4411 struct nvldbentry *entry;
4412 afs_int32 *modified;
4415 int foundro = 0, modentry = 0;
4416 afs_int32 code, error = 0;
4419 if (modified) *modified = 0;
4421 /* Check to see if the RO volumes exist and set the RO_EXISTS
4424 for (idx=0; idx < entry->nServers; idx++) {
4425 if (!(entry->serverFlags[idx] & ITSROVOL)) {
4426 continue; /* not a RO */
4429 code = VolumeExists(entry->serverNumber[idx],
4430 entry->serverPartition[idx],
4431 entry->volumeId[ROVOL]);
4432 if (code == 0) { /* RO volume exists */
4435 else if (code == ENODEV) { /* RW volume does not exist */
4436 Lp_SetROValue(entry, entry->serverNumber[idx],
4437 entry->serverPartition[idx], 0L, 0L);
4443 MapPartIdIntoName(entry->serverPartition[idx], pname);
4444 fprintf(STDERR,"Transaction call failed for RO %u on server %s %s\n",
4445 entry->volumeId[ROVOL],
4446 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4451 if (foundro) { /* A RO volume exists */
4452 if (!(entry->flags & RO_EXISTS)) { /* ... yet entry says RW does not exist */
4453 entry->flags |= RO_EXISTS; /* ... so say RW does exist */
4456 } else { /* A RO volume does not exist */
4457 if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
4458 entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
4464 if (modified) *modified = modentry;
4469 * Ensure that <entry> matches with the info on file servers
4471 afs_int32 CheckVldb(entry, modified)
4472 struct nvldbentry *entry;
4473 afs_int32 *modified;
4475 afs_int32 code, error=0;
4476 struct nvldbentry storeEntry;
4477 int islocked=0, mod, modentry, delentry=0;
4480 if (modified) *modified = 0;
4482 fprintf(STDOUT,"_______________________________\n");
4483 fprintf(STDOUT,"\n-- status before -- \n");
4484 if ((entry->flags & RW_EXISTS) ||
4485 (entry->flags & RO_EXISTS) ||
4486 (entry->flags & BACK_EXISTS))
4487 EnumerateEntry(entry);
4488 fprintf(STDOUT,"\n");
4491 if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
4492 fprintf(STDERR,"Volume name %s exceeds limit of %d characters\n",
4493 entry->name, VOLSER_OLDMAXVOLNAME-10);
4497 /* Check to see if the VLDB is ok without locking it (pass 1).
4498 * If it will change, then lock the VLDB entry, read it again,
4499 * then make the changes to it (pass 2).
4502 code = ubik_Call(VL_SetLock,cstruct, 0, entry->volumeId[RWVOL], RWVOL, VLOP_DELETE);
4504 fprintf(STDERR, "Could not lock VLDB entry for %u \n",entry->volumeId[RWVOL] );
4509 code = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, entry);
4511 fprintf(STDERR,"Could not read VLDB entry for volume %s\n", entry->name);
4515 MapHostToNetwork(entry);
4521 /* Check if the RW and BK entries are ok */
4522 code = CheckVldbRWBK(entry, &mod);
4523 if (code) ERROR_EXIT(code);
4524 if (mod && (pass == 1)) goto retry;
4525 if (mod) modentry++;
4527 /* Check if the RO volumes entries are ok */
4528 code = CheckVldbRO(entry, &mod);
4529 if (code) ERROR_EXIT(code);
4530 if (mod && (pass == 1)) goto retry;
4531 if (mod) modentry++;
4533 /* The VLDB entry has been updated. If it as been modified, then
4534 * write the entry back out the the VLDB.
4537 if (pass == 1) goto retry;
4539 if (!(entry->flags & RW_EXISTS) &&
4540 !(entry->flags & BACK_EXISTS) &&
4541 !(entry->flags & RO_EXISTS)) {
4542 /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
4543 code = ubik_Call(VL_DeleteEntry, cstruct, 0, entry->volumeId[RWVOL], RWVOL);
4545 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",
4546 entry->volumeId[RWVOL]);
4552 /* Replace old entry with our new one */
4553 MapNetworkToHost(entry,&storeEntry);
4554 code = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry,
4555 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
4557 fprintf(STDERR,"Could not update VLDB entry for volume %u\n",
4558 entry->volumeId[RWVOL] );
4562 if (modified) *modified = 1;
4567 fprintf(STDOUT,"-- status after --\n");
4569 fprintf(STDOUT,"\n**entry deleted**\n");
4571 EnumerateEntry(entry);
4573 fprintf(STDOUT,"\n**no change**\n");
4578 fprintf(STDOUT,"\n_______________________________\n");
4582 code = ubik_Call(VL_ReleaseLock, cstruct, 0, entry->volumeId[RWVOL], RWVOL,
4583 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
4585 fprintf(STDERR,"Could not release lock on VLDB entry for volume %u\n",
4586 entry->volumeId[RWVOL]);
4587 if (!error) error = code;
4594 * Synchronise <aserver> <apart>(if flags = 1) with the VLDB.
4596 UV_SyncServer(aserver, apart, flags, force)
4597 afs_int32 aserver, apart;
4600 struct rx_connection *aconn;
4601 afs_int32 code, error = 0;
4602 afs_int32 nentries, tentries=0;
4603 struct VldbListByAttributes attributes;
4604 nbulkentries arrayEntries;
4605 afs_int32 failures=0, modified, modifications=0;
4606 struct nvldbentry *vlentry;
4607 afs_int32 si, nsi, j;
4609 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4611 /* Set up attributes to search VLDB */
4612 attributes.server = ntohl(aserver);
4613 attributes.Mask = VLLIST_SERVER;
4615 attributes.partition = apart;
4616 attributes.Mask |= VLLIST_PARTITION;
4620 fprintf(STDOUT,"Processing VLDB entries ...\n");
4624 /* While we need to collect more VLDB entries */
4625 for (si=0; si != -1; si=nsi) {
4626 memset(&arrayEntries, 0, sizeof(arrayEntries));
4628 /* Collect set of VLDB entries */
4629 code = VLDB_ListAttributesN2(&attributes, 0, si,
4630 &nentries, &arrayEntries, &nsi);
4631 if (code == RXGEN_OPCODE) {
4632 code = VLDB_ListAttributes(&attributes, &nentries, &arrayEntries);
4636 fprintf(STDERR,"Could not access the VLDB for attributes\n");
4639 tentries += nentries;
4641 for (j=0; j<nentries; j++) {
4642 vlentry = &arrayEntries.nbulkentries_val[j];
4643 MapHostToNetwork(vlentry);
4646 fprintf(STDOUT,"Processing VLDB entry %d ...\n", j+1);
4650 code = CheckVldb(vlentry, &modified);
4652 PrintError("",code);
4653 fprintf(STDERR,"Could not process VLDB entry for volume %s\n",
4656 } else if (modified) {
4662 fprintf(STDOUT,"...error encountered\n\n");
4664 fprintf(STDOUT,"...done entry %d\n\n", j+1);
4669 if (arrayEntries.nbulkentries_val) {
4670 free(arrayEntries.nbulkentries_val);
4671 arrayEntries.nbulkentries_val = 0;
4676 fprintf(STDOUT,"Total entries: %u, Failed to process %d, Changed %d\n",
4677 tentries, failures, modifications);
4682 rx_DestroyConnection(aconn);
4683 if (arrayEntries.nbulkentries_val)
4684 free(arrayEntries.nbulkentries_val);
4687 error = VOLSERFAILEDOP;
4691 /*rename volume <oldname> to <newname>, changing the names of the related
4692 *readonly and backup volumes. This operation is also idempotent.
4693 *salvager is capable of recovering from rename operation stopping halfway.
4694 *to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
4695 UV_RenameVolume(entry,oldname,newname)
4696 struct nvldbentry *entry;
4697 char oldname[],newname[];
4699 struct nvldbentry storeEntry;
4700 afs_int32 vcode,code,rcode,error;
4702 char nameBuffer[256];
4704 struct rx_connection *aconn;
4708 aconn = (struct rx_connection *)0;
4712 vcode = ubik_Call(VL_SetLock,cstruct, 0,entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE);/*last param is dummy*/
4714 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n",entry->volumeId[RWVOL] );
4719 strncpy(entry->name,newname,VOLSER_OLDMAXVOLNAME);
4720 MapNetworkToHost(entry,&storeEntry);
4721 vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL],RWVOL, &storeEntry,0 );
4723 fprintf(STDERR,"Could not update VLDB entry for %u\n",entry->volumeId[RWVOL]);
4727 if(verbose) fprintf(STDOUT,"Recorded the new name %s in VLDB\n",newname);
4728 /*at this stage the intent to rename is recorded in the vldb, as far as the vldb
4729 is concerned, oldname is lost */
4730 if(entry->flags & RW_EXISTS) {
4731 index = Lp_GetRwIndex(entry);
4732 if(index == -1){ /* there is a serious discrepancy */
4733 fprintf(STDERR,"There is a serious discrepancy in VLDB entry for volume %u\n",entry->volumeId[RWVOL]);
4734 fprintf(STDERR,"try building VLDB from scratch\n");
4735 error = VOLSERVLDB_ERROR;
4738 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
4739 code = AFSVolTransCreate(aconn,entry->volumeId[RWVOL],entry->serverPartition[index], ITOffline, &tid);
4740 if(code) { /*volume doesnot exist */
4741 fprintf(STDERR,"Could not start transaction on the rw volume %u\n",entry->volumeId[RWVOL]);
4745 else {/*volume exists, process it */
4747 code = AFSVolSetIdsTypes(aconn, tid, newname,RWVOL, entry->volumeId[RWVOL],entry->volumeId[ROVOL],entry->volumeId[BACKVOL]);
4749 if(verbose) printf("Renamed rw volume %s to %s\n",oldname,newname);
4750 code = AFSVolEndTrans(aconn, tid, &rcode);
4753 fprintf(STDERR,"Could not end transaction on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
4759 fprintf(STDERR,"Could not set parameters on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
4764 if(aconn) rx_DestroyConnection(aconn);
4765 aconn = (struct rx_connection *)0;
4766 } /*end rw volume processing */
4768 if(entry->flags & BACK_EXISTS) {/*process the backup volume */
4769 index = Lp_GetRwIndex(entry);
4770 if(index == -1){ /* there is a serious discrepancy */
4771 fprintf(STDERR,"There is a serious discrepancy in the VLDB entry for the backup volume %u\n",entry->volumeId[BACKVOL]);
4772 fprintf(STDERR,"try building VLDB from scratch\n");
4773 error = VOLSERVLDB_ERROR;
4776 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
4777 code = AFSVolTransCreate(aconn,entry->volumeId[BACKVOL],entry->serverPartition[index], ITOffline, &tid);
4778 if(code) { /*volume doesnot exist */
4779 fprintf(STDERR,"Could not start transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
4783 else {/*volume exists, process it */
4784 if(strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)){
4785 fprintf(STDERR,"Volume name %s.backup exceeds the limit of %u characters\n",newname,VOLSER_OLDMAXVOLNAME);
4789 strcpy(nameBuffer,newname);
4790 strcat(nameBuffer,".backup");
4792 code = AFSVolSetIdsTypes(aconn, tid,nameBuffer ,BACKVOL, entry->volumeId[RWVOL],0,0);
4794 if(verbose) fprintf(STDOUT,"Renamed backup volume to %s \n",nameBuffer);
4795 code = AFSVolEndTrans(aconn, tid, &rcode);
4798 fprintf(STDERR,"Could not end transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
4804 fprintf(STDERR,"Could not set parameters on the backup volume %u\n",entry->volumeId[BACKVOL]);
4809 } /* end backup processing */
4810 if(aconn) rx_DestroyConnection(aconn);
4811 aconn = (struct rx_connection *)0;
4812 if(entry->flags & RO_EXISTS){ /*process the ro volumes */
4813 for(i = 0; i < entry->nServers; i++){
4814 if(entry->serverFlags[i] & ITSROVOL) {
4815 aconn = UV_Bind(entry->serverNumber[i],AFSCONF_VOLUMEPORT);
4816 code = AFSVolTransCreate(aconn,entry->volumeId[ROVOL],entry->serverPartition[i], ITOffline, &tid);
4817 if(code) { /*volume doesnot exist */
4818 fprintf(STDERR,"Could not start transaction on the ro volume %u\n",entry->volumeId[ROVOL]);
4822 else {/*volume exists, process it */
4823 strcpy(nameBuffer,newname);
4824 strcat(nameBuffer,".readonly");
4825 if(strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)){
4826 fprintf(STDERR,"Volume name %s exceeds the limit of %u characters\n",nameBuffer,VOLSER_OLDMAXVOLNAME);
4830 code = AFSVolSetIdsTypes(aconn, tid, nameBuffer,ROVOL, entry->volumeId[RWVOL],0,0);
4832 if(verbose) fprintf(STDOUT,"Renamed RO volume %s on host %s\n",
4834 hostutil_GetNameByINet(entry->serverNumber[i]));
4835 code = AFSVolEndTrans(aconn, tid, &rcode);
4838 fprintf(STDERR,"Could not end transaction on volume %u\n",entry->volumeId[ROVOL]);
4844 fprintf(STDERR,"Could not set parameters on the ro volume %u\n",entry->volumeId[ROVOL]);
4849 if(aconn) rx_DestroyConnection(aconn);
4850 aconn = (struct rx_connection *)0;
4856 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,entry->volumeId[RWVOL] , RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4858 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
4859 if(!error) error = vcode;
4863 code = AFSVolEndTrans(aconn, tid, &rcode);
4864 if(!code) code = rcode;
4866 fprintf(STDERR,"Failed to end transaction on a volume \n");
4867 if(!error) error = code;
4870 if(aconn) rx_DestroyConnection(aconn);
4871 PrintError("",error);
4876 /*report on all the active transactions on volser */
4877 UV_VolserStatus(server,rpntr,rcount)
4879 transDebugInfo **rpntr;
4882 struct rx_connection *aconn;
4883 transDebugEntries transInfo;
4886 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4887 transInfo.transDebugEntries_val = (transDebugInfo *) 0;
4888 transInfo.transDebugEntries_len = 0;
4889 code = AFSVolMonitor(aconn,&transInfo);
4891 fprintf(STDERR,"Could not access status information about the server\n");
4892 PrintError("",code);
4893 if (transInfo.transDebugEntries_val) free(transInfo.transDebugEntries_val);
4894 if(aconn) rx_DestroyConnection(aconn);
4898 *rcount = transInfo.transDebugEntries_len;
4899 *rpntr = transInfo.transDebugEntries_val;
4900 if(aconn) rx_DestroyConnection(aconn);
4906 /*delete the volume without interacting with the vldb */
4907 UV_VolumeZap(server,part,volid)
4908 afs_int32 volid,server,part;
4911 afs_int32 rcode,ttid,error,code;
4912 struct rx_connection *aconn;
4918 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4919 code = AFSVolTransCreate(aconn, volid, part, ITOffline, &ttid);
4921 fprintf(STDERR,"Could not start transaction on volume %u\n",volid);
4925 code = AFSVolDeleteVolume(aconn, ttid);
4927 fprintf(STDERR,"Could not delete volume %u\n",volid);
4931 code = AFSVolEndTrans(aconn, ttid, &rcode);
4933 if(!code) code = rcode;
4935 fprintf(STDERR,"Could not end transaction on volume %u\n",volid);
4941 code = AFSVolEndTrans(aconn,ttid,&rcode);
4942 if(!code) code = rcode;
4943 if(!error) error = code;
4945 PrintError("",error);
4946 if(aconn) rx_DestroyConnection(aconn);
4950 UV_SetVolume(server, partition, volid, transflag, setflag, sleeptime)
4951 afs_int32 server, partition, volid, transflag, setflag;
4953 struct rx_connection *conn = 0;
4955 afs_int32 code, error=0, rcode;
4957 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4959 fprintf(STDERR, "SetVolumeStatus: Bind Failed");
4963 code = AFSVolTransCreate(conn, volid, partition, transflag, &tid);
4965 fprintf(STDERR, "SetVolumeStatus: TransCreate Failed\n");
4969 code = AFSVolSetFlags(conn, tid, setflag);
4971 fprintf(STDERR, "SetVolumeStatus: SetFlags Failed\n");
4976 #ifdef AFS_PTHREAD_ENV
4979 IOMGR_Sleep(sleeptime);
4986 code = AFSVolEndTrans(conn, tid, &rcode);
4987 if (code || rcode) {
4988 fprintf(STDERR, "SetVolumeStatus: EndTrans Failed\n");
4989 if (!error) error = (code ? code : rcode);
4993 if (conn) rx_DestroyConnection(conn);
4997 UV_SetVolumeInfo(server, partition, volid, infop)
4998 afs_int32 server, partition, volid;
5001 struct rx_connection *conn = 0;
5003 afs_int32 code, error=0, rcode;
5005 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5007 fprintf(STDERR, "SetVolumeInfo: Bind Failed");
5011 code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
5013 fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
5017 code = AFSVolSetInfo(conn, tid, infop);
5019 fprintf(STDERR, "SetVolumeInfo: SetInfo Failed\n");
5026 code = AFSVolEndTrans(conn, tid, &rcode);
5027 if (code || rcode) {
5028 fprintf(STDERR, "SetVolumeInfo: EndTrans Failed\n");
5029 if (!error) error = (code ? code : rcode);
5033 if (conn) rx_DestroyConnection(conn);
5037 /*maps the host addresses in <old > (present in network byte order) to
5038 that in< new> (present in host byte order )*/
5040 MapNetworkToHost(old, new)
5041 struct nvldbentry *old, *new;
5045 /*copy all the fields */
5046 strcpy(new->name,old->name);
5047 /* new->volumeType = old->volumeType;*/
5048 new->nServers = old->nServers;
5049 count = old->nServers;
5050 if(count < NMAXNSERVERS) count++;
5051 for(i = 0; i < count; i++) {
5052 new->serverNumber[i] = ntohl(old->serverNumber[i]);
5053 new->serverPartition[i] = old->serverPartition[i];
5054 new->serverFlags[i] = old->serverFlags[i];
5056 new->volumeId[RWVOL]= old->volumeId[RWVOL];
5057 new->volumeId[ROVOL] = old->volumeId[ROVOL];
5058 new->volumeId[BACKVOL] = old->volumeId[BACKVOL];
5059 new->cloneId = old->cloneId;
5060 new->flags = old->flags;
5063 /*maps the host entries in <entry> which are present in host byte order to network byte order */
5065 MapHostToNetwork(entry)
5066 struct nvldbentry *entry;
5070 count = entry->nServers;
5071 if(count < NMAXNSERVERS) count++;
5072 for(i = 0; i < count; i++) {
5073 entry->serverNumber[i] = htonl(entry->serverNumber[i]);