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>
38 #include <afs/voldefs.h>
41 #include <afs/vlserver.h>
44 #include <afs/cellconfig.h>
47 #include <afs/afsint.h>
51 #include <afs/com_err.h>
53 #include <afs/kautils.h>
56 #define ERRCODE_RANGE 8 /* from error_table.h */
57 #define CLOCKSKEW 2 /* not really skew, but resolution */
59 /* for UV_MoveVolume() recovery */
61 #include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
64 afs_int32 VolumeExists(), CheckVldbRWBK(), CheckVldb();
66 struct ubik_client *cstruct;
68 extern int VL_GetNewVolumeId();
69 extern int VL_SetLock();
70 extern int VL_ReleaseLock();
71 extern int VL_DeleteEntry();
73 void MapNetworkToHost();
74 void MapHostToNetwork();
78 afs_int32 vldbEntryIndex;
81 /*map the partition <partId> into partition name <partName>*/
82 void MapPartIdIntoName(afs_int32 partId, char *partName)
84 if(partId < 26) {/* what if partId > = 26 ? */
85 strcpy(partName,"/vicep");
86 partName[6] = partId + 'a';
89 } else if (partId < VOLMAXPARTS) {
90 strcpy(partName,"/vicep");
92 partName[6] = 'a' + (partId/26);
93 partName[7] = 'a' + (partId%26);
99 int yesprompt(char *str)
104 fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
105 response = c = getchar();
106 while (!(c==EOF || c=='\n')) c=getchar(); /*skip to end of line*/
107 code = (response=='y'||response=='Y');
112 int PrintError(char *msg, afs_int32 errcode)
115 /*replace by a big switch statement*/
119 case -1 : fprintf(STDERR,"Possible communication failure\n");
121 case VSALVAGE: fprintf(STDERR,"Volume needs to be salvaged\n");
123 case VNOVNODE: fprintf(STDERR,"Bad vnode number quoted\n");
125 case VNOVOL: fprintf(STDERR,"Volume not attached, does not exist, or not on line\n");
127 case VVOLEXISTS:fprintf(STDERR,"Volume already exists\n");
129 case VNOSERVICE:fprintf(STDERR,"Volume is not in service\n");
131 case VOFFLINE: fprintf(STDERR,"Volume is off line\n");
133 case VONLINE: fprintf(STDERR,"Volume is already on line\n");
135 case VDISKFULL: fprintf(STDERR,"Partition is full\n");
137 case VOVERQUOTA:fprintf(STDERR,"Volume max quota exceeded\n");
139 case VBUSY: fprintf(STDERR,"Volume temporarily unavailable\n");
141 case VMOVED:fprintf(STDERR,"Volume has moved to another server\n");
143 case VL_IDEXIST : fprintf(STDERR,"VLDB: volume Id exists in the vldb\n");
145 case VL_IO: fprintf(STDERR,"VLDB: a read terminated too early\n");
147 case VL_NAMEEXIST: fprintf(STDERR,"VLDB: volume entry exists in the vldb\n");
149 case VL_CREATEFAIL: fprintf(STDERR,"VLDB: internal creation failure\n");
151 case VL_NOENT: fprintf(STDERR,"VLDB: no such entry\n");
153 case VL_EMPTY: fprintf(STDERR,"VLDB: vldb database is empty\n");
155 case VL_ENTDELETED: fprintf(STDERR,"VLDB: entry is deleted (soft delete)\n");
157 case VL_BADNAME: fprintf(STDERR,"VLDB: volume name is illegal\n");
159 case VL_BADINDEX: fprintf(STDERR,"VLDB: index was out of range\n");
161 case VL_BADVOLTYPE: fprintf(STDERR,"VLDB: bad volume type\n");
163 case VL_BADSERVER: fprintf(STDERR,"VLDB: illegal server number (not within limits)\n");
165 case VL_BADPARTITION: fprintf(STDERR,"VLDB: bad partition number\n");
167 case VL_REPSFULL: fprintf(STDERR,"VLDB: run out of space for replication sites\n");
169 case VL_NOREPSERVER: fprintf(STDERR,"VLDB: no such repsite server exists\n");
171 case VL_DUPREPSERVER: fprintf(STDERR,"VLDB: replication site server already exists\n");
173 case VL_RWNOTFOUND: fprintf(STDERR,"VLDB: parent r/w entry not found\n");
175 case VL_BADREFCOUNT: fprintf(STDERR,"VLDB: illegal reference count number\n");
177 case VL_SIZEEXCEEDED: fprintf(STDERR,"VLDB: vldb size for attributes exceeded\n");
179 case VL_BADENTRY: fprintf(STDERR,"VLDB: bad incoming vldb entry\n");
181 case VL_BADVOLIDBUMP: fprintf(STDERR,"VLDB: illegal max volid increment\n");
183 case VL_IDALREADYHASHED: fprintf(STDERR,"VLDB: (RO/BACK) Id already hashed\n");
185 case VL_ENTRYLOCKED: fprintf(STDERR,"VLDB: vldb entry is already locked\n");
187 case VL_BADVOLOPER: fprintf(STDERR,"VLDB: bad volume operation code\n");
189 case VL_BADRELLOCKTYPE: fprintf(STDERR,"VLDB: bad release lock type\n");
191 case VL_RERELEASE: fprintf(STDERR,"VLDB: status report: last release was aborted\n");
193 case VL_BADSERVERFLAG: fprintf(STDERR,"VLDB: invalid replication site server flag\n");
195 case VL_PERM: fprintf(STDERR,"VLDB: no permission access for call\n");
197 case VOLSERREAD_DUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in reading the dump file !\n");
199 case VOLSERDUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in doing the dump !\n");
201 case VOLSERATTACH_ERROR: fprintf(STDERR,"VOLSER: Could not attach the volume\n");
203 case VOLSERDETACH_ERROR: fprintf(STDERR,"VOLSER: Could not detach the volume\n");
205 case VOLSERILLEGAL_PARTITION: fprintf(STDERR,"VOLSER: encountered illegal partition number\n");
207 case VOLSERBAD_ACCESS: fprintf(STDERR,"VOLSER: permission denied, not a super user\n");
209 case VOLSERVLDB_ERROR: fprintf(STDERR,"VOLSER: error detected in the VLDB\n");
211 case VOLSERBADNAME: fprintf(STDERR,"VOLSER: error in volume name\n");
213 case VOLSERVOLMOVED: fprintf(STDERR,"VOLSER: volume has moved\n");
215 case VOLSERBADOP: fprintf(STDERR,"VOLSER: illegal operation\n");
217 case VOLSERBADRELEASE: fprintf(STDERR,"VOLSER: release could not be completed\n");
219 case VOLSERVOLBUSY: fprintf(STDERR,"VOLSER: volume is busy\n");
221 case VOLSERNO_MEMORY: fprintf(STDERR,"VOLSER: volume server is out of memory\n");
223 case VOLSERNOVOL:fprintf(STDERR,"VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
225 case VOLSERMULTIRWVOL: fprintf(STDERR,"VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
227 case VOLSERFAILEDOP: fprintf(STDERR,"VOLSER: not all entries were successfully processed\n");
234 initialize_KA_error_table();
235 initialize_RXK_error_table();
236 initialize_KTC_error_table();
237 initialize_ACFG_error_table();
238 initialize_CMD_error_table();
239 initialize_VL_error_table();
241 offset = errcode & ((1<<ERRCODE_RANGE)-1);
242 fprintf(STDERR,"%s: %s\n",error_table_name (errcode), error_message (errcode));
250 static struct rx_securityClass *uvclass=0;
251 static int uvindex = -1;
252 /* called by VLDBClient_Init to set the security module to be used in the RPC */
253 int UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
259 /* bind to volser on <port> <aserver> */
260 /* takes server address in network order, port in host order. dumb */
261 struct rx_connection *UV_Bind(afs_int32 aserver, afs_int32 port)
263 register struct rx_connection *tc;
265 tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass, uvindex);
269 /* if <okvol> is allright(indicated by beibg able to
270 * start a transaction, delete the <delvol> */
271 static afs_int32 CheckAndDeleteVolume(aconn,apart,okvol,delvol)
272 struct rx_connection *aconn;
273 afs_int32 apart,okvol,delvol;
275 afs_int32 error,code,tid,rcode;
281 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
282 if(!error && code) error = code;
283 code = AFSVolDeleteVolume(aconn,tid);
284 if(!error && code) error = code;
285 code = AFSVolEndTrans(aconn,tid, &rcode);
286 if(!code) code = rcode;
287 if(!error && code) error = code;
291 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline,&tid);
293 code = AFSVolEndTrans(aconn,tid, &rcode);
294 if(!code) code = rcode;
295 if(!error && code) error = code;
296 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
297 if(!error && code) error = code;
298 code = AFSVolDeleteVolume(aconn,tid);
299 if(!error && code) error = code;
300 code = AFSVolEndTrans(aconn,tid, &rcode);
301 if(!code) code = rcode;
302 if(!error && code) error = code;
310 /* called by EmuerateEntry, show vldb entry in a reasonable format */
311 void SubEnumerateEntry(struct nvldbentry *entry)
318 fprintf(STDOUT," readWriteID %-10u ",entry->volumeId[RWVOL]);
319 if(entry->flags & RW_EXISTS) fprintf(STDOUT," valid \n");else fprintf(STDOUT," invalid \n");
320 fprintf(STDOUT," readOnlyID %-10u ",entry->volumeId[ROVOL]);
321 if(entry->flags & RO_EXISTS) fprintf(STDOUT," valid \n") ;else fprintf(STDOUT," invalid \n");
322 fprintf(STDOUT," backUpID %-10u ",entry->volumeId[BACKVOL]);
323 if(entry->flags & BACK_EXISTS) fprintf(STDOUT," valid \n"); else fprintf(STDOUT," invalid \n");
324 if((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
325 fprintf(STDOUT," releaseClone %-10u \n",entry->cloneId);
327 if (entry->flags & RW_EXISTS)
328 fprintf(STDOUT," RWrite: %-10u",entry->volumeId[RWVOL]);
329 if (entry->flags & RO_EXISTS)
330 fprintf(STDOUT," ROnly: %-10u",entry->volumeId[ROVOL]);
331 if (entry->flags & BACK_EXISTS)
332 fprintf(STDOUT," Backup: %-10u",entry->volumeId[BACKVOL]);
333 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
334 fprintf(STDOUT," RClone: %-10u",entry->cloneId);
335 fprintf(STDOUT,"\n");
337 fprintf(STDOUT," number of sites -> %u\n",entry->nServers);
338 for(i = 0; i < entry->nServers; i++) {
339 if(entry->serverFlags[i] & NEW_REPSITE)
342 for(i = 0; i < entry->nServers; i++) {
343 MapPartIdIntoName(entry->serverPartition[i],pname);
344 fprintf(STDOUT," server %s partition %s ",
345 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
346 if(entry->serverFlags[i] & ITSRWVOL) fprintf(STDOUT,"RW Site ") ; else fprintf(STDOUT,"RO Site ");
348 if (entry->serverFlags[i] & NEW_REPSITE)
349 fprintf(STDOUT," -- New release");
351 fprintf(STDOUT," -- Old release");
353 if (entry->serverFlags[i] & RO_DONTUSE)
354 fprintf(STDOUT," -- Not released");
356 fprintf(STDOUT,"\n");
363 /*enumerate the vldb entry corresponding to <entry> */
364 void EnumerateEntry(struct nvldbentry *entry)
367 fprintf(STDOUT,"\n");
368 fprintf(STDOUT,"%s \n",entry->name);
369 SubEnumerateEntry(entry);
373 /* forcibly remove a volume. Very dangerous call */
374 int UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
376 register struct rx_connection *tconn;
377 register afs_int32 code;
379 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
381 code = AFSVolNukeVolume(tconn, partid, volid);
382 rx_DestroyConnection(tconn);
388 /* like df. Return usage of <pname> on <server> in <partition> */
389 int UV_PartitionInfo(afs_int32 server, char *pname, struct diskPartition *partition)
391 register struct rx_connection *aconn;
395 aconn = (struct rx_connection *)0;
396 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
397 code = AFSVolPartitionInfo(aconn,pname,partition);
399 fprintf(STDERR,"Could not get information on partition %s\n",pname);
402 if(aconn) rx_DestroyConnection(aconn);
406 /* old interface to create volume */
407 int UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 *anewid)
410 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
414 /* create a volume, given a server, partition number, volume name --> sends
415 * back new vol id in <anewid>*/
416 int UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aquota,
417 afs_int32 aspare1, afs_int32 aspare2, afs_int32 aspare3, afs_int32 aspare4, afs_int32 *anewid)
420 register struct rx_connection *aconn;
422 register afs_int32 code;
424 afs_int32 rcode,vcode;
425 struct nvldbentry entry,storeEntry;/*the new vldb entry */
426 struct volintInfo tstatus;
429 aconn = (struct rx_connection *)0;
431 memset(&tstatus, 0, sizeof(struct volintInfo));
433 tstatus.maxquota = aquota;
435 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
436 /* next the next 3 available ids from the VLDB */
437 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 3, anewid);
439 fprintf(STDERR,"Could not get an Id for volume %s\n",aname);
443 code = AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
445 fprintf(STDERR,"Failed to create the volume %s %u \n",aname,*anewid);
450 code = AFSVolSetInfo(aconn, tid, &tstatus);
452 fprintf(STDERR,"Could not change quota (error %d), continuing...\n", code);
455 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
457 fprintf(STDERR,"Could not bring the volume %s %u online \n",aname,*anewid);
461 if(verbose) fprintf(STDOUT,"Volume %s %u created and brought online\n",aname,*anewid);
462 /* set up the vldb entry for this volume */
463 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
465 entry.serverNumber[0] = aserver; /* this should have another
466 level of indirection later */
467 entry.serverPartition[0] = apart; /* this should also have
468 another indirection level */
469 entry.flags = RW_EXISTS;/* this records that rw volume exists */
470 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
471 entry.volumeId[RWVOL] = *anewid;
472 entry.volumeId[ROVOL] = *anewid + 1;/* rw,ro, bk id are related in the default case */
473 entry.volumeId[BACKVOL] = *anewid + 2;
475 /*map into right byte order, before passing to xdr, the stuff has to be in host
476 byte order. Xdr converts it into network order */
477 MapNetworkToHost(&entry,&storeEntry);
478 /* create the vldb entry */
479 vcode = VLDB_CreateEntry(&storeEntry);
481 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,*anewid);
482 /*destroy the created volume*/
484 fprintf(STDOUT,"Deleting the newly created volume %u\n",*anewid);
486 AFSVolDeleteVolume(aconn,tid);
490 if(verbose) fprintf(STDOUT,"Created the VLDB entry for the volume %s %u\n",aname,*anewid);
491 /* volume created, now terminate the transaction and release the connection*/
492 code = AFSVolEndTrans(aconn, tid, &rcode);/*if it crashes before this
493 the volume will come online anyway when transaction timesout , so if
494 vldb entry exists then the volume is guaranteed to exist too wrt create*/
497 fprintf(STDERR,"Failed to end the transaction on the volume %s %u\n",aname,*anewid);
505 code= AFSVolEndTrans(aconn, tid, &rcode);
507 fprintf(STDERR,"WARNING: could not end transaction\n");
509 if(aconn) rx_DestroyConnection(aconn);
510 PrintError("",error);
515 /* create a volume, given a server, partition number, volume name --> sends
516 * back new vol id in <anewid>*/
517 int UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aid)
519 register struct rx_connection *aconn;
522 struct nvldbentry entry,storeEntry;/*the new vldb entry */
524 aconn = (struct rx_connection *)0;
527 /* set up the vldb entry for this volume */
528 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
530 entry.serverNumber[0] = aserver; /* this should have another
531 level of indirection later */
532 entry.serverPartition[0] = apart; /* this should also have
533 another indirection level */
534 entry.flags = RW_EXISTS;/* this records that rw volume exists */
535 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
536 entry.volumeId[RWVOL] = aid;
538 entry.volumeId[ROVOL] = anewid + 1;/* rw,ro, bk id are related in the default case */
539 entry.volumeId[BACKVOL] = *anewid + 2;
541 entry.volumeId[ROVOL] = 0;
542 entry.volumeId[BACKVOL] = 0;
545 /*map into right byte order, before passing to xdr, the stuff has to be in host
546 byte order. Xdr converts it into network order */
547 MapNetworkToHost(&entry,&storeEntry);
548 /* create the vldb entry */
549 vcode = VLDB_CreateEntry(&storeEntry);
551 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,aid);
555 if(verbose) fprintf(STDOUT,"Created the VLDB entry for the volume %s %u\n",aname,aid);
558 if(aconn) rx_DestroyConnection(aconn);
559 PrintError("",error);
563 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
565 /* Delete the volume <volid>on <aserver> <apart>
566 * the physical entry gets removed from the vldb only if the ref count
569 int UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
571 struct rx_connection *aconn = (struct rx_connection *)0;
573 afs_int32 code, rcode;
575 struct nvldbentry entry,storeEntry;
577 afs_int32 avoltype = -1, vtype;
578 int notondisk = 0, notinvldb = 0;
580 /* Find and read bhe VLDB entry for this volume */
581 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
583 if (code != VL_NOENT) {
584 fprintf(STDERR,"Could not lock VLDB entry for the volume %u\n", avolid);
591 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
593 fprintf(STDERR,"Could not fetch VLDB entry for volume %u\n",avolid);
596 MapHostToNetwork(&entry);
599 EnumerateEntry(&entry);
602 /* Whether volume is in the VLDB or not. Delete the volume on disk */
603 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
604 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
606 if (code == VNOVOL) {
609 fprintf(STDERR,"Transaction on volume %u failed\n", avolid);
615 fprintf(STDOUT,"Trying to delete the volume %u ...", avolid);
618 code = AFSVolDeleteVolume(aconn, ttid);
620 fprintf(STDERR,"Could not delete the volume %u \n", avolid);
623 code = AFSVolEndTrans(aconn, ttid, &rcode);
624 code = (code ? code : rcode);
627 fprintf(STDERR,"Could not end the transaction for the volume %u \n",avolid);
631 fprintf(STDOUT," done\n");
634 /* Now update the VLDB entry.
635 * But first, verify we have a VLDB entry.
636 * Whether volume is on disk or not. Delete the volume in VLDB.
641 if (avolid == entry.volumeId[BACKVOL]) {
642 /* Its a backup volume, modify the VLDB entry. Check that the
643 * backup volume is on the server/partition we asked to delete.
645 if ( !(entry.flags & BACK_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
646 notinvldb = 2; /* Not on this server and partition */
651 fprintf(STDOUT,"Marking the backup volume %u deleted in the VLDB\n", avolid);
653 entry.flags &= ~BACK_EXISTS;
657 else if (avolid == entry.volumeId[ROVOL]) {
658 /* Its a read-only volume, modify the VLDB entry. Check that the
659 * readonly volume is on the server/partition we asked to delete.
660 * If flags does not have RO_EIXSTS set, then this may mean the RO
661 * hasn't been released (and could exist in VLDB).
663 if (!Lp_ROMatch(aserver,apart,&entry)) {
664 notinvldb = 2; /* Not found on this server and partition */
669 fprintf(STDOUT,"Marking the readonly volume %u deleted in the VLDB\n", avolid);
671 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
673 if (!Lp_ROMatch(0,0,&entry))
674 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
678 else if (avolid == entry.volumeId[RWVOL]) {
679 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
680 * Check that the readwrite volumes is on the server/partition we
683 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
684 notinvldb = 2; /* Not found on this server and partition */
688 /* Delete backup if it exists */
689 code = AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart, ITOffline, &ttid);
692 fprintf(STDOUT,"Trying to delete the backup volume %u ...", entry.volumeId[BACKVOL]);
695 code = AFSVolDeleteVolume(aconn, ttid);
697 fprintf(STDERR,"Could not delete the volume %u \n", entry.volumeId[BACKVOL]);
700 code = AFSVolEndTrans(aconn, ttid, &rcode);
702 code = (code ? code : rcode);
704 fprintf(STDERR,"Could not end the transaction for the volume %u \n",
705 entry.volumeId[BACKVOL]);
709 fprintf(STDOUT," done\n");
713 fprintf(STDOUT,"Marking the readwrite volume %u%s deleted in the VLDB\n",
714 avolid, ((entry.flags & BACK_EXISTS)?", and its backup volume,":""));
716 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
718 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
721 if (entry.flags & RO_EXISTS)
722 fprintf(STDERR,"WARNING: ReadOnly copy(s) may still exist\n");
726 notinvldb = 2; /* Not found on this server and partition */
730 /* Either delete or replace the VLDB entry */
731 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
733 fprintf(STDOUT,"Last reference to the VLDB entry for %u - deleting entry\n", avolid);
734 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
736 fprintf(STDERR,"Could not delete the VLDB entry for the volume %u \n",avolid);
740 MapNetworkToHost(&entry, &storeEntry);
741 code = VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
742 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
744 fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n", avolid);
751 if (error) PrintError("", error);
753 if (notondisk && notinvldb) {
754 fprintf(STDERR,"Volume %u does not exist %s\n",
755 avolid, ((notinvldb == 2)?"on server and partition":""));
756 PrintError("", VOLSERNOVOL);
757 if (!error) error = VOLSERNOVOL;
759 else if (notondisk) {
760 fprintf(STDERR,"WARNING: Volume %u did not exist on the partition\n", avolid);
762 else if (notinvldb) {
763 fprintf(STDERR,"WARNING: Volume %u does not exist in VLDB %s\n",
764 avolid, ((notinvldb == 2)?"on server and partition":""));
768 code = AFSVolEndTrans(aconn, ttid, &rcode);
769 code = (code ? code : rcode);
771 fprintf(STDERR,"Could not end transaction on the volume %u\n", avolid);
772 PrintError("", code);
773 if (!error) error = code;
778 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, -1,
779 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
781 fprintf(STDERR,"Could not release the lock on the VLDB entry for the volume %u \n",
783 PrintError("", code);
784 if (!error) error = code;
788 if (aconn) rx_DestroyConnection(aconn);
792 /* add recovery to UV_MoveVolume */
794 #define TESTC 0 /* set to test recovery code, clear for production */
799 void sigint_handler(int x)
805 "\nSIGINT handler: vos move operation in progress\n");
807 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
809 "enter second control-c to exit\n");
813 signal(SIGINT,sigint_handler);
818 #define ONERR(ec, es, ep) if (ec) { fprintf(STDERR, (es), (ep)); PrintError(" ",ec); error = (ec); goto mfail; }
820 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
821 * <atopart>. The operation is almost idempotent
824 UV_MoveVolume(afromvol, afromserver, afrompart, atoserver, atopart)
826 afs_int32 afromserver, atoserver;
827 afs_int32 afrompart, atopart;
829 struct rx_connection *toconn, *fromconn ;
830 afs_int32 fromtid, totid, clonetid;
833 char tmpName[VOLSER_MAXVOLNAME +1];
836 struct restoreCookie cookie;
837 register afs_int32 vcode, code;
838 afs_int32 newVol, volid, backupId;
839 struct volser_status tstatus;
840 struct destServer destination;
842 struct nvldbentry entry, storeEntry;
843 int i, islocked, pntg;
845 char in,lf; /* for test code */
848 #ifdef ENABLE_BUGFIX_1165
849 volEntries volumeInfo;
850 struct volintInfo *infop = 0;
854 fromconn = (struct rx_connection *)0;
855 toconn = (struct rx_connection *)0;
865 /* support control-c processing */
866 if (setjmp(env)) goto mfail;
867 (void) signal(SIGINT,sigint_handler);
872 "\nThere are three tests points - verifies all code paths through recovery.\n");
873 fprintf(STDOUT,"First test point - operation not started.\n");
874 fprintf(STDOUT,"...test here (y, n)? ");
876 fscanf(stdin,"%c",&in);
877 fscanf(stdin,"%c",&lf); /* toss away */
880 fprintf(STDOUT,"type control-c\n");
888 /* or drop through */
891 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
892 ONERR (vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
894 if (entry.volumeId[RWVOL] != afromvol)
896 fprintf(STDERR,"Only RW volume can be moved\n");
900 vcode = ubik_Call(VL_SetLock, cstruct, 0,afromvol, RWVOL, VLOP_MOVE);
901 ONERR (vcode, "Could not lock entry for volume %u \n", afromvol);
904 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
905 ONERR (vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
907 backupId = entry.volumeId[BACKVOL];
908 MapHostToNetwork(&entry);
910 if ( !Lp_Match(afromserver, afrompart, &entry) )
912 /* the from server and partition do not exist in the vldb entry corresponding to volid */
913 if ( !Lp_Match(atoserver, atopart, &entry) )
915 /* the to server and partition do not exist in the vldb entry corresponding to volid */
916 fprintf(STDERR,"The volume %u is not on the specified site. \n", afromvol);
917 fprintf(STDERR,"The current site is :");
918 for (i=0; i<entry.nServers; i++)
920 if (entry.serverFlags[i] == ITSRWVOL)
923 MapPartIdIntoName(entry.serverPartition[i],pname);
924 fprintf(STDERR," server %s partition %s \n",
925 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
928 vcode = ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
929 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
930 ONERR (vcode, " Could not release lock on the VLDB entry for the volume %u \n",
933 return VOLSERVOLMOVED;
936 /* delete the volume afromvol on src_server */
937 /* from-info does not exist but to-info does =>
938 * we have already done the move, but the volume
939 * may still be existing physically on from fileserver
941 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
945 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline, &fromtid);
947 { /* volume exists - delete it */
948 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
949 ONERR (code, "Failed to set flags on the volume %u\n", afromvol);
951 code = AFSVolDeleteVolume(fromconn,fromtid);
952 ONERR (code, "Failed to delete the volume %u\n", afromvol);
954 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
956 if (!code) code = rcode;
957 ONERR (code, "Could not end the transaction for the volume %u \n", afromvol);
960 /*delete the backup volume now */
962 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
964 { /* backup volume exists - delete it */
965 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
966 ONERR (code, "Failed to set flags on the backup volume %u\n", backupId);
968 code = AFSVolDeleteVolume(fromconn,fromtid);
969 ONERR (code, "Could not delete the backup volume %u\n", backupId);
971 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
973 if (!code) code = rcode;
974 ONERR (code,"Could not end the transaction for the backup volume %u \n",backupId);
982 /* From-info matches the vldb info about volid,
983 * its ok start the move operation, the backup volume
984 * on the old site is deleted in the process
986 if (afrompart == atopart)
988 same = VLDB_IsSameAddrs (afromserver, atoserver, &error);
991 fprintf(STDERR, "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
995 if (same) ONERR (VOLSERVOLMOVED,
996 "Warning: Moving volume %u to its home partition ignored!\n", afromvol);
1000 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1001 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1002 fromtid = totid = 0; /* initialize to uncreated */
1005 * clone the read/write volume locally.
1008 if (verbose) fprintf(STDOUT,"Starting transaction on source volume %u ...",afromvol);
1010 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1011 ONERR (code, "Failed to create transaction on the volume %u\n", afromvol);
1012 if (verbose) fprintf(STDOUT," done\n");
1014 /* Get a clone id */
1016 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1017 ONERR (vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1019 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1020 if (verbose) fprintf (STDOUT,"Cloning source volume %u ...", afromvol);
1022 strcpy(vname, "move-clone-temp");
1023 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &newVol);
1024 ONERR (code, "Failed to clone the source volume %u\n", afromvol);
1025 if (verbose) fprintf(STDOUT," done\n");
1027 /* lookup the name of the volume we just cloned */
1029 code = AFSVolGetName(fromconn, fromtid, &volName);
1030 ONERR (code, "Failed to get the name of the volume %u\n", newVol);
1032 if (verbose) fprintf (STDOUT,"Ending the transaction on the source volume %u ...", afromvol);
1035 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1037 if (!code) code = rcode;
1038 ONERR (code, "Failed to end the transaction on the source volume %u\n", afromvol);
1039 if (verbose) fprintf (STDOUT," done\n");
1042 * Create the destination volume
1045 if (verbose) fprintf(STDOUT, "Starting transaction on the cloned volume %u ...", newVol);
1047 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1048 ONERR (code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1049 if (verbose) fprintf(STDOUT," done\n");
1051 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1052 ONERR (code, "Could not set falgs on the cloned volume %u\n", newVol);
1054 /* remember time from which we've dumped the volume */
1055 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1056 ONERR (code, "Failed to get the status of the cloned volume %u\n", newVol);
1058 fromDate = tstatus.creationDate-CLOCKSKEW;
1060 #ifdef ENABLE_BUGFIX_1165
1062 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1063 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1064 * don't use this information...
1066 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
1067 volumeInfo.volEntries_len = 0;
1068 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1069 ONERR (code, "Failed to get the volint Info of the cloned volume %u\n", afromvol);
1071 infop = (volintInfo *) volumeInfo.volEntries_val;
1072 infop->maxquota = -1; /* Else it will replace the default quota */
1075 /* create a volume on the target machine */
1077 code = AFSVolTransCreate (toconn, volid, atopart, ITOffline, &totid);
1080 /* Delete the existing volume.
1081 * While we are deleting the volume in these steps, the transaction
1082 * we started against the cloned volume (clonetid above) will be
1083 * sitting idle. It will get cleaned up after 600 seconds
1085 if (verbose) fprintf(STDOUT,"Deleting pre-existing volume %u on destination ...",volid);
1088 code = AFSVolDeleteVolume(toconn, totid);
1089 ONERR (code, "Could not delete the pre-existing volume %u on destination\n", volid);
1091 code = AFSVolEndTrans(toconn, totid, &rcode);
1093 if (!code) code = rcode;
1094 ONERR (code, "Could not end the transaction on pre-existing volume %u on destination\n",
1097 if (verbose) fprintf(STDOUT," done\n");
1100 if (verbose) fprintf(STDOUT,"Creating the destination volume %u ...",volid);
1102 code = AFSVolCreateVolume (toconn, atopart, volName, volser_RW, volid, &volid, &totid);
1103 ONERR (code, "Failed to create the destination volume %u\n", volid);
1104 if (verbose) fprintf(STDOUT," done\n");
1106 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1110 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1111 ONERR(code, "Failed to set the flags on the destination volume %u\n", volid);
1114 * Now dump the clone to the new volume
1117 destination.destHost = ntohl(atoserver);
1118 destination.destPort = AFSCONF_VOLUMEPORT;
1119 destination.destSSID = 1;
1121 /* Copy the clone to the new volume */
1122 if (verbose) fprintf(STDOUT, "Dumping from clone %u on source to volume %u on destination ...",
1125 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1126 cookie.type = RWVOL;
1127 cookie.parent = entry.volumeId[RWVOL];
1129 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1130 ONERR (code, "Failed to move data for the volume %u\n", volid);
1131 if (verbose) fprintf(STDOUT," done\n");
1133 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1134 if (!code) code = rcode;
1136 ONERR (code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1139 * reattach to the main-line volume, and incrementally dump it.
1143 fprintf(STDOUT,"Doing the incremental dump from source to destination for volume %u ... ",
1147 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1148 ONERR (code, "Failed to create a transaction on the source volume %u\n", afromvol);
1150 /* now do the incremental */
1151 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1152 ONERR (code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n", 0);
1153 if (verbose)fprintf(STDOUT," done\n");
1155 /* now adjust the flags so that the new volume becomes official */
1156 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1157 ONERR (code, "Failed to set the flags to make old source volume offline\n", 0);
1159 code = AFSVolSetFlags(toconn, totid, 0);
1160 ONERR (code, "Failed to set the flags to make new source volume online\n", 0);
1162 #ifdef ENABLE_BUGFIX_1165
1163 code = AFSVolSetInfo(toconn, totid, infop);
1164 ONERR (code, "Failed to set volume status on the destination volume %u\n", volid);
1167 /* put new volume online */
1168 code = AFSVolEndTrans(toconn, totid, &rcode);
1170 if (!code) code = rcode;
1171 ONERR (code, "Failed to end the transaction on the volume %u on the new site\n", afromvol);
1173 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1174 MapNetworkToHost(&entry,&storeEntry);
1175 storeEntry.flags &= ~BACK_EXISTS;
1179 fprintf(STDOUT, "Second test point - operation in progress but not complete.\n");
1180 fprintf(STDOUT,"...test here (y, n)? ");
1182 fscanf(stdin,"%c",&in);
1183 fscanf(stdin,"%c",&lf); /* toss away */
1186 fprintf(STDOUT,"type control-c\n");
1189 fprintf(stdout,".");
1194 /* or drop through */
1197 vcode = VLDB_ReplaceEntry (afromvol, -1, &storeEntry,
1198 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1201 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %s %u \n",
1202 storeEntry.name,afromvol);
1210 fprintf(STDOUT, "Third test point - operation complete but no cleanup.\n");
1211 fprintf(STDOUT,"...test here (y, n)? ");
1213 fscanf(stdin,"%c",&in);
1214 fscanf(stdin,"%c",&lf); /* toss away */
1217 fprintf(STDOUT,"type control-c\n");
1220 fprintf(stdout,".");
1225 /* or drop through */
1229 /* This is tricky. File server is very stupid, and if you mark the volume
1230 * as VTOutOfService, it may mark the *good* instance (if you're moving
1231 * between partitions on the same machine) as out of service. Since
1232 * we're cleaning this code up in DEcorum, we're just going to kludge around
1233 * it for now by removing this call. */
1234 /* already out of service, just zap it now */
1235 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1238 fprintf(STDERR,"Failed to set the flags to make the old source volume offline\n");
1242 if (atoserver != afromserver)
1244 /* set forwarding pointer for moved volumes */
1245 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1246 ONERR (code, "Failed to set the forwarding pointer for the volume %u\n", afromvol);
1249 if (verbose) fprintf(STDOUT,"Deleting old volume %u on source ...", afromvol);
1252 code = AFSVolDeleteVolume(fromconn,fromtid); /* zap original volume */
1253 ONERR (code, "Failed to delete the old volume %u on source\n", afromvol);
1255 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1257 if (!code) code = rcode;
1258 ONERR (code, "Failed to end the transaction on the old volume %u on the source\n", afromvol);
1260 if (verbose) fprintf(STDOUT," done\n");
1262 /* Delete the backup volume on the original site */
1263 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1266 fprintf(STDOUT, "WARNING : Deleting the backup volume %u on the source ...",backupId);
1269 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1270 ONERR (code, "Failed to set the flags on the backup volume on source\n", 0);
1272 code = AFSVolDeleteVolume(fromconn,fromtid);
1273 ONERR (code, "Failed to delete the backup volume on source\n", 0);
1275 code = AFSVolEndTrans(fromconn,fromtid, &rcode);
1277 if (!code) code = rcode;
1278 ONERR (code, "Failed to end the transaction on the backup volume %u on source\n", 0);
1280 fprintf(STDOUT," done\n");
1282 else code = 0; /* no backup volume? that's okay */
1285 if (verbose) fprintf(STDOUT,"Starting transaction on the cloned volume %u ...",newVol);
1288 code = AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
1289 ONERR (code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1291 if (verbose) fprintf(STDOUT," done\n");
1293 /* now delete the clone */
1294 if (verbose) fprintf(STDOUT,"Deleting the clone %u ...", newVol);
1297 code = AFSVolDeleteVolume(fromconn, clonetid);
1298 ONERR (code, "Failed to delete the cloned volume %u\n", newVol);
1300 if (verbose) fprintf(STDOUT," done\n");
1302 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1303 if (!code) code = rcode;
1305 ONERR (code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1312 fprintf(STDOUT,"Fourth test point - operation complete.\n");
1313 fprintf(STDOUT,"...test here (y, n)? ");
1315 fscanf(stdin,"%c",&in);
1316 fscanf(stdin,"%c",&lf); /* toss away */
1319 fprintf(STDOUT,"type control-c\n");
1322 fprintf(stdout,".");
1327 /* or drop through */
1330 /* normal cleanup code */
1332 if (entry.flags & RO_EXISTS) fprintf(STDERR,"WARNING : readOnly copies still exist \n");
1336 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, -1,
1337 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1340 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %u \n",
1342 if (!error) error = vcode;
1348 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1351 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n", newVol);
1352 if (!error) error = (code ? code : rcode);
1358 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1361 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",newVol);
1362 if (!error) error = (code ? code : rcode);
1368 code = AFSVolEndTrans(toconn, totid, &rcode);
1371 fprintf(STDERR,"Could not end transaction on destination volume %u\n",afromvol);
1372 if (!error) error = (code ? code : rcode);
1375 if (volName) free(volName);
1376 #ifdef ENABLE_BUGFIX_1165
1377 if (infop) free(infop);
1379 if (fromconn) rx_DestroyConnection(fromconn);
1380 if (toconn) rx_DestroyConnection(toconn);
1381 PrintError("",error);
1384 /* come here only when the sky falls */
1389 fprintf(STDOUT,"vos move: operation interrupted, cleanup in progress...\n");
1390 fprintf(STDOUT,"clear transaction contexts\n");
1394 /* unlock VLDB entry */
1396 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1397 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1399 if (clonetid) AFSVolEndTrans(fromconn, clonetid, &rcode);
1400 if (totid) AFSVolEndTrans(toconn, totid, &rcode);
1402 { /* put it on-line */
1403 AFSVolSetFlags(fromconn,fromtid,0);
1404 AFSVolEndTrans(fromconn, fromtid, &rcode);
1408 { /* get current VLDB entry */
1409 fprintf(STDOUT,"access VLDB\n");
1412 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
1415 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
1419 MapHostToNetwork(&entry);
1421 /* Delete either the volume on the source location or the target location.
1422 * If the vldb entry still points to the source location, then we know the
1423 * volume move didn't finish so we remove the volume from the target
1424 * location. Otherwise, we remove the volume from the source location.
1426 if (Lp_Match(afromserver,afrompart,&entry)) { /* didn't move - delete target volume */
1429 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1433 if (volid && toconn) {
1434 code=AFSVolTransCreate(toconn,volid,atopart, ITOffline,&totid);
1436 AFSVolSetFlags(toconn,totid, VTDeleteOnSalvage | VTOutOfService);
1437 AFSVolDeleteVolume(toconn,totid);
1438 AFSVolEndTrans(toconn,totid,&rcode);
1442 /* put source volume on-line */
1444 code=AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1446 AFSVolSetFlags(fromconn,fromtid,0);
1447 AFSVolEndTrans(fromconn,fromtid,&rcode);
1451 else { /* yep, move complete */
1454 "move complete - attempt cleanup of source partition - no guarantee\n");
1458 /* delete backup volume */
1460 code=AFSVolTransCreate (fromconn,backupId,afrompart, ITOffline,&fromtid);
1462 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1463 AFSVolDeleteVolume(fromconn,fromtid);
1464 AFSVolEndTrans(fromconn,fromtid,&rcode);
1467 /* delete source volume */
1468 code=AFSVolTransCreate (fromconn, afromvol, afrompart, ITBusy, &fromtid);
1470 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1471 if (atoserver != afromserver)
1472 AFSVolSetForwarding(fromconn,fromtid,atoserver);
1473 AFSVolDeleteVolume(fromconn,fromtid);
1474 AFSVolEndTrans(fromconn,fromtid,&rcode);
1479 /* common cleanup - delete local clone */
1481 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1483 AFSVolDeleteVolume(fromconn,clonetid);
1484 AFSVolEndTrans(fromconn,clonetid,&rcode);
1488 /* unlock VLDB entry */
1489 ubik_Call (VL_ReleaseLock, cstruct, 0, afromvol, -1,
1490 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1492 done: /* routine cleanup */
1493 if (volName) free(volName);
1494 #ifdef ENABLE_BUGFIX_1165
1495 if (infop) free(infop);
1497 if (fromconn) rx_DestroyConnection(fromconn);
1498 if (toconn) rx_DestroyConnection(toconn);
1501 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
1507 /* Make a new backup of volume <avolid> on <aserver> and <apart>
1508 * if one already exists, update it
1511 int UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
1513 struct rx_connection *aconn = (struct rx_connection *)0;
1514 afs_int32 ttid = 0, btid = 0;
1516 afs_int32 code = 0, rcode = 0;
1517 char vname[VOLSER_MAXVOLNAME +1];
1518 struct nvldbentry entry, storeEntry;
1519 afs_int32 error = 0;
1520 int vldblocked = 0, vldbmod = 0, backexists = 1;
1522 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
1524 /* the calls to VLDB will succeed only if avolid is a RW volume,
1525 * since we are following the RW hash chain for searching */
1526 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
1528 fprintf(STDERR, "Could not fetch the entry for the volume %u from the VLDB \n", avolid);
1529 error = code; goto bfail;
1531 MapHostToNetwork(&entry);
1533 /* These operations require the VLDB be locked since it means the VLDB
1534 * will change or the vldb is already locked.
1536 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
1537 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
1538 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
1540 code = ubik_Call(VL_SetLock,cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
1542 fprintf(STDERR,"Could not lock the VLDB entry for the volume %u\n",avolid);
1548 /* Reread the vldb entry */
1549 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
1551 fprintf(STDERR,"Could not fetch the entry for the volume %u from the VLDB \n",avolid);
1555 MapHostToNetwork(&entry);
1558 if (!ISNAMEVALID(entry.name)) {
1559 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n", entry.name);
1560 error = VOLSERBADNAME;
1564 backupID = entry.volumeId[BACKVOL];
1565 if (backupID == INVALID_BID) {
1566 /* Get a backup volume id from the VLDB and update the vldb
1569 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
1572 "Could not allocate ID for the backup volume of %u from the VLDB\n",
1577 entry.volumeId[BACKVOL] = backupID;
1581 /* Test to see if the backup volume exists by trying to create
1582 * a transaction on the backup volume. We've assumed the backup exists.
1584 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1586 if (code != VNOVOL) {
1587 fprintf(STDERR,"Could not reach the backup volume %u\n", backupID);
1591 backexists = 0; /* backup volume does not exist */
1594 code = AFSVolEndTrans(aconn, btid, &rcode);
1596 if (code || rcode) {
1598 "Could not end transaction on the previous backup volume %u\n",
1600 error = (code ? code : rcode);
1605 /* Now go ahead and try to clone the RW volume.
1606 * First start a transaction on the RW volume
1608 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
1610 fprintf(STDERR,"Could not start a transaction on the volume %u\n",avolid);
1615 /* Clone or reclone the volume, depending on whether the backup
1616 * volume exists or not
1620 fprintf(STDOUT,"Re-cloning backup volume %u ...", backupID);
1623 code = AFSVolReClone(aconn, ttid, backupID);
1625 fprintf(STDERR,"Could not re-clone backup volume %u\n", backupID);
1632 fprintf(STDOUT,"Creating a new backup clone %u ...", backupID);
1635 strcpy(vname, entry.name);
1636 strcat(vname,".backup");
1638 code = AFSVolClone(aconn, ttid, 0,backupVolume, vname, &backupID);
1640 fprintf(STDERR,"Failed to clone the volume %u\n",avolid);
1646 /* End the transaction on the RW volume */
1647 code = AFSVolEndTrans(aconn, ttid, &rcode);
1649 if (code || rcode) {
1650 fprintf(STDERR, "Failed to end the transaction on the rw volume %u\n", avolid);
1651 error = (code ? code : rcode);
1655 /* Mork vldb as backup exists */
1656 if (!(entry.flags & BACK_EXISTS)) {
1657 entry.flags |= BACK_EXISTS;
1661 /* Now go back to the backup volume and bring it on line */
1662 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
1664 fprintf(STDERR,"Failed to start a transaction on the backup volume %u\n",backupID);
1669 code = AFSVolSetFlags(aconn, btid, 0);
1671 fprintf(STDERR,"Could not mark the backup volume %u on line \n",backupID);
1676 code = AFSVolEndTrans(aconn, btid, &rcode);
1678 if (code || rcode) {
1679 fprintf(STDERR, "Failed to end the transaction on the backup volume %u\n", backupID);
1680 error = (code ? code : rcode);
1685 fprintf(STDOUT,"done\n");
1687 /* Will update the vldb below */
1691 code = AFSVolEndTrans(aconn, ttid, &rcode);
1692 if (code || rcode) {
1693 fprintf(STDERR, "Could not end transaction on the volume %u\n", avolid);
1695 error = (code ? code : rcode);
1700 code = AFSVolEndTrans(aconn, btid, &rcode);
1701 if (code || rcode) {
1702 fprintf(STDERR,"Could not end transaction the backup volume %u\n",backupID);
1704 error = (code ? code : rcode);
1708 /* Now update the vldb - if modified */
1711 MapNetworkToHost(&entry,&storeEntry);
1712 code = VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
1713 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1715 fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n",avolid);
1721 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, RWVOL,
1722 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1724 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %u \n",avolid);
1732 rx_DestroyConnection(aconn);
1734 PrintError("",error);
1738 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags)
1740 afs_int32 acode, ccode, rcode, tid;
1741 ccode = rcode = tid = 0;
1743 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
1744 if (!acode) { /* It really was there */
1745 acode = AFSVolDeleteVolume(conn, tid);
1747 fprintf(STDERR, "Failed to delete volume %u.\n", vid);
1748 PrintError ("", acode);
1750 ccode = AFSVolEndTrans(conn, tid, &rcode);
1754 fprintf(STDERR, "Failed to end transaction on volume %u.\n", vid);
1755 PrintError ("", ccode);
1762 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
1763 #define ERROREXIT(ec) { error = (ec); goto rfail; }
1765 /* Get a "transaction" on this replica. Create the volume
1766 * if necessary. Return the time from which a dump should
1767 * be made (0 if it's a new volume)
1769 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr,
1770 afs_int32 *transPtr, afs_int32 *timePtr)
1773 struct volser_status tstatus;
1774 int code, rcode, tcode;
1776 *connPtr = (struct rx_connection *)0;
1780 /* get connection to the replication site */
1781 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
1782 if (!*connPtr) goto fail; /* server is down */
1784 volid = vldbEntryPtr->volumeId[ROVOL];
1786 code = AFSVolTransCreate(*connPtr, volid, vldbEntryPtr->serverPartition[index],
1787 ITOffline, transPtr);
1789 /* If the volume does not exist, create it */
1790 if (!volid || code) {
1793 if (volid && (code != VNOVOL)){
1794 PrintError("Failed to start a transaction on the RO volume.\n",
1799 strcpy(volname, vldbEntryPtr->name);
1800 strcat(volname, ".readonly");
1803 fprintf(STDOUT,"Creating new volume %u on replication site %s: ",
1804 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
1808 code = AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
1810 vldbEntryPtr->volumeId[RWVOL], &volid, transPtr);
1812 PrintError("Failed to create the ro volume: ",code);
1815 vldbEntryPtr->volumeId[ROVOL] = volid;
1817 if (verbose) fprintf(STDOUT,"done.\n");
1819 /* The following is a bit redundant, since create sets these flags by default */
1820 code = AFSVolSetFlags(*connPtr, *transPtr, VTDeleteOnSalvage | VTOutOfService);
1822 PrintError("Failed to set flags on the ro volume: ", code);
1827 /* Otherwise, the transaction did succeed, so get the creation date of the
1828 * latest RO volume on the replication site
1832 fprintf(STDOUT,"Updating existing ro volume %u on %s ...\n",
1833 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
1837 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
1839 PrintError("Failed to get status of volume on destination: ",code);
1842 *timePtr = tstatus.creationDate-CLOCKSKEW;
1849 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
1851 if (!tcode) tcode = rcode;
1852 if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode);
1858 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
1859 afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results)
1863 for (i=0; i<tr->manyDests_len; i++) {
1864 results->manyResults_val[i] = AFSVolForward(fromconn, fromtid,
1865 fromdate, &(tr->manyDests_val[i].server),
1866 tr->manyDests_val[i].trans, cookie);
1872 static int rel_compar (struct release *r1, struct release *r2)
1874 return (r1->time - r2->time);
1877 /* UV_ReleaseVolume()
1878 * Release volume <afromvol> on <afromserver> <afrompart> to all
1879 * its RO sites (full release). Unless the previous release was
1880 * incomplete: in which case we bring the remaining incomplete
1881 * volumes up to date with the volumes that were released
1883 * forceflag: Performs a full release.
1885 * Will create a clone from the RW, then dump the clone out to
1886 * the remaining replicas. If there is more than 1 RO sites,
1887 * ensure that the VLDB says at least one RO is available all
1888 * the time: Influences when we write back the VLDB entry.
1891 int UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, int forceflag)
1894 afs_int32 code, vcode, rcode, tcode;
1895 afs_int32 cloneVolId, roVolId;
1896 struct replica *replicas=0;
1897 struct nvldbentry entry,storeEntry;
1898 int i, volcount, m, fullrelease, vldbindex;
1900 struct restoreCookie cookie;
1901 struct rx_connection **toconns=0;
1902 struct release *times=0;
1904 struct rx_connection *fromconn = (struct rx_connection *)0;
1905 afs_int32 error = 0;
1907 afs_int32 clonetid=0, onlinetid;
1908 afs_int32 fromtid=0;
1909 afs_uint32 fromdate, thisdate;
1912 manyResults results;
1913 int rwindex, roindex, roclone, roexists;
1918 } remembertime[NMAXNSERVERS];
1919 int releasecount = 0;
1920 struct volser_status volstatus;
1922 memset((char *)remembertime, 0, sizeof(remembertime));
1923 memset((char *)&results, 0, sizeof(results));
1925 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
1926 if (vcode != VL_RERELEASE)
1927 ONERROR(vcode, afromvol, "Could not lock the VLDB entry for the volume %u.\n");
1930 /* Get the vldb entry in readable format */
1931 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
1932 ONERROR(vcode, afromvol, "Could not fetch the entry for the volume %u from the VLDB.\n");
1933 MapHostToNetwork(&entry);
1936 EnumerateEntry(&entry);
1938 if (!ISNAMEVALID(entry.name))
1939 ONERROR(VOLSERBADOP, entry.name,
1940 "Volume name %s is too long, rename before releasing.\n");
1941 if (entry.volumeId[RWVOL] != afromvol)
1942 ONERROR(VOLSERBADOP, afromvol,
1943 "The volume %u being released is not a read-write volume.\n");
1944 if (entry.nServers <= 1)
1945 ONERROR(VOLSERBADOP, afromvol,
1946 "Volume %u has no replicas - release operation is meaningless!\n");
1947 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
1948 ONERROR(VOLSERBADOP, entry.name,
1949 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
1951 /* roclone is true if one of the RO volumes is on the same
1952 * partition as the RW volume. In this case, we make the RO volume
1953 * on the same partition a clone instead of a complete copy.
1956 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
1957 roclone = ((roindex == -1) ? 0 : 1);
1958 rwindex = Lp_GetRwIndex(&entry);
1960 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
1962 /* Make sure we have a RO volume id to work with */
1963 if (entry.volumeId[ROVOL] == INVALID_BID) {
1964 /* need to get a new RO volume id */
1965 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
1966 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
1968 entry.volumeId[ROVOL] = roVolId;
1969 MapNetworkToHost(&entry, &storeEntry);
1970 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
1971 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
1974 /* Will we be completing a previously unfinished release. -force overrides */
1975 for (fullrelease=1, i=0; (fullrelease && (i<entry.nServers)); i++) {
1976 if (entry.serverFlags[i] & NEW_REPSITE)
1979 if (forceflag && !fullrelease)
1982 /* Determine which volume id to use and see if it exists */
1983 cloneVolId = ((fullrelease || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
1984 code = VolumeExists(afromserver, afrompart, cloneVolId);
1985 roexists = ((code == ENODEV) ? 0 : 1);
1986 if (!roexists && !fullrelease)
1987 fullrelease = 1; /* Do a full release if RO clone does not exist */
1991 fprintf(STDOUT,"This is a complete release of the volume %u\n", afromvol);
1993 fprintf(STDOUT,"This is a completion of the previous release\n");
1997 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1999 ONERROR(-1, afromserver, "Cannot establish connection with server 0x%x\n");
2002 /* If the RO clone exists, then if the clone is a temporary
2003 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2004 * (it was recently added), then also delete it. We do not
2005 * want to "reclone" a temporary RO clone.
2008 (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE)) ) {
2009 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2010 if (code && (code != VNOVOL))
2015 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2016 * write this entry out to the vlserver until after the first
2017 * RO volume is released (temp RO clones don't count).
2019 for (i=0; i<entry.nServers; i++) {
2020 entry.serverFlags[i] &= ~NEW_REPSITE;
2021 entry.serverFlags[i] |= RO_DONTUSE;
2023 entry.serverFlags[rwindex] |= NEW_REPSITE;
2024 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2026 /* Begin transaction on RW and mark it busy while we clone it */
2027 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &clonetid);
2028 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2030 /* Clone or reclone the volume */
2033 fprintf(STDERR, "Recloning RW volume ...\n");
2035 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2036 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2039 strcpy(vname, entry.name);
2040 strcat(vname, ".readonly");
2042 fprintf(STDERR, "Cloning RW volume ...\n");
2044 strcpy(vname, "readonly-clone-temp");
2046 fprintf(STDERR, "Cloning RW volume to temporary RO ...\n");
2048 code = AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, &cloneVolId);
2049 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
2052 /* Get the time the RW was created for future information */
2053 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
2054 ONERROR(code, cloneVolId, "Failed to get the status of the RW volume %u\n");
2055 rwcrdate = volstatus.creationDate;
2057 /* End the transaction on the RW volume */
2058 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2060 ONERROR((code?code:rcode), cloneVolId, "Failed to end cloning transaction on RW %u\n");
2062 /* Remember clone volume ID in case we fail or are interrupted */
2063 entry.cloneId = cloneVolId;
2066 /* Bring the RO clone online - though not if it's a temporary clone */
2067 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline, &onlinetid);
2068 ONERROR(code, cloneVolId, "Failed to start transaction on volume %u\n");
2070 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
2072 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
2073 ONERROR((code?code:rcode), cloneVolId, "Failed to end transaction on RO clone %u\n");
2075 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
2077 /* Sleep so that a client searching for an online volume won't
2078 * find the clone offline and then the next RO offline while the
2079 * release brings the clone online and the next RO offline (race).
2080 * There is a fix in the 3.4 client that does not need this sleep
2081 * anymore, but we don't know what clients we have.
2083 if (entry.nServers > 2)
2086 /* Mark the RO clone in the VLDB as a good site (already released)*/
2087 entry.serverFlags[roindex] |= NEW_REPSITE;
2088 entry.serverFlags[roindex] &= ~RO_DONTUSE;
2089 entry.flags |= RO_EXISTS;
2093 /* Write out the VLDB entry only if the clone is not a temporary
2094 * clone. If we did this to a temporary clone then we would end
2095 * up marking all the ROs as "old release" making the ROs
2096 * temporarily unavailable.
2098 MapNetworkToHost(&entry, &storeEntry);
2099 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2100 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2104 /* Now we will release from the clone to the remaining RO replicas.
2105 * The first 2 ROs (counting the non-temporary RO clone) are released
2106 * individually: releasecount. This is to reduce the race condition
2107 * of clients trying to find an on-line RO volume. The remaining ROs
2108 * are released in parallel but no more than half the number of ROs
2109 * (rounded up) at a time: nservers.
2112 strcpy(vname, entry.name);
2113 strcat(vname, ".readonly");
2114 memset(&cookie, 0, sizeof(cookie));
2115 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
2116 cookie.type = ROVOL;
2117 cookie.parent = entry.volumeId[RWVOL];
2120 nservers = entry.nServers/2; /* how many to do at once, excluding clone */
2121 replicas = (struct replica *) malloc (sizeof(struct replica)*nservers+1);
2122 times = (struct release *) malloc (sizeof(struct release)*nservers+1);
2123 toconns = (struct rx_connection **) malloc (sizeof(struct rx_connection *)*nservers+1);
2124 results.manyResults_val = (afs_int32 *) malloc (sizeof(afs_int32)*nservers+1);
2125 if ( !replicas || !times || !! !results.manyResults_val || !toconns )
2126 ONERROR(ENOMEM, 0, "Failed to create transaction on the release clone\n");
2128 memset(replicas, 0, (sizeof(struct replica)*nservers+1));
2129 memset(times, 0, (sizeof(struct release)*nservers+1));
2130 memset(toconns, 0, (sizeof(struct rx_connection *)*nservers+1));
2131 memset(results.manyResults_val, 0, (sizeof(afs_int32)*nservers+1));
2133 /* Create a transaction on the cloned volume */
2134 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
2135 if (!fullrelease && code)
2136 ONERROR(VOLSERNOVOL, afromvol,"Old clone is inaccessible. Try vos release -f %u.\n");
2137 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
2139 /* For each index in the VLDB */
2140 for (vldbindex=0; vldbindex<entry.nServers; ) {
2142 /* Get a transaction on the replicas. Pick replacas which have an old release. */
2143 for (volcount=0; ((volcount<nservers) && (vldbindex<entry.nServers)); vldbindex++) {
2144 /* The first two RO volumes will be released individually.
2145 * The rest are then released in parallel. This is a hack
2146 * for clients not recognizing right away when a RO volume
2147 * comes back on-line.
2149 if ((volcount == 1) && (releasecount < 2))
2152 if (vldbindex == roindex) continue; /* the clone */
2153 if ( (entry.serverFlags[vldbindex] & NEW_REPSITE) &&
2154 !(entry.serverFlags[vldbindex] & RO_DONTUSE) ) continue;
2155 if (!(entry.serverFlags[vldbindex] & ITSROVOL)) continue; /* not a RO vol */
2158 /* Get a Transaction on this replica. Get a new connection if
2159 * necessary. Create the volume if necessary. Return the
2160 * time from which the dump should be made (0 if it's a new
2161 * volume). Each volume might have a different time.
2163 replicas[volcount].server.destHost = ntohl(entry.serverNumber[vldbindex]);
2164 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
2165 replicas[volcount].server.destSSID = 1;
2166 times[volcount].vldbEntryIndex = vldbindex;
2168 code = GetTrans(&entry, vldbindex, &(toconns[volcount]),
2169 &(replicas[volcount].trans), &(times[volcount].time));
2172 /* Thisdate is the date from which we want to pick up all changes */
2173 if (forceflag || !fullrelease || (rwcrdate > times[volcount].time)) {
2174 /* If the forceflag is set, then we want to do a full dump.
2175 * If it's not a full release, we can't be sure that the creation
2176 * date is good (so we also do a full dump).
2177 * If the RW volume was replaced (its creation date is newer than
2178 * the last release), then we can't be sure what has changed (so
2179 * we do a full dump).
2182 } else if (remembertime[vldbindex].validtime) {
2183 /* Trans was prev ended. Use the time from the prev trans
2184 * because, prev trans may have created the volume. In which
2185 * case time[volcount].time would be now instead of 0.
2187 thisdate = (remembertime[vldbindex].time < times[volcount].time) ?
2188 remembertime[vldbindex].time : times[volcount].time;
2190 thisdate = times[volcount].time;
2192 remembertime[vldbindex].validtime = 1;
2193 remembertime[vldbindex].time = thisdate;
2195 if (volcount == 0) {
2196 fromdate = thisdate;
2198 /* Include this volume if it is within 15 minutes of the earliest */
2199 if (((fromdate>thisdate)?(fromdate-thisdate):(thisdate-fromdate)) > 900) {
2200 AFSVolEndTrans(toconns[volcount], replicas[volcount].trans, &rcode);
2201 replicas[volcount].trans = 0;
2204 if (thisdate < fromdate)
2205 fromdate = thisdate;
2209 if (!volcount) continue;
2212 fprintf(STDOUT,"Starting ForwardMulti from %u to %u on %s",
2213 cloneVolId, entry.volumeId[ROVOL],
2214 hostutil_GetNameByINet(entry.serverNumber[times[0].vldbEntryIndex]));
2216 for (s=1; s<volcount; s++) {
2217 fprintf(STDOUT," and %s",
2218 hostutil_GetNameByINet(entry.serverNumber[times[s].vldbEntryIndex]));
2222 fprintf(STDOUT," (full release)");
2223 fprintf(STDOUT,".\n");
2227 /* Release the ones we have collected */
2228 tr.manyDests_val = &(replicas[0]);
2229 tr.manyDests_len = results.manyResults_len = volcount;
2230 code = AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2231 if (code == RXGEN_OPCODE) { /* RPC Interface Mismatch */
2232 code = SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2237 PrintError("Release failed: ", code);
2239 for (m=0; m<volcount; m++) {
2240 if (results.manyResults_val[m]) {
2241 if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
2242 /* we retry timed out transaction. When it is
2243 * not the first volume and the transaction wasn't found
2244 * (assume it timed out and was garbage collected by volser).
2246 PrintError("Failed to dump volume from clone to a ro site: ",
2247 results.manyResults_val[m]);
2252 code = AFSVolSetIdsTypes(toconns[m], replicas[m].trans,
2253 vname, ROVOL, entry.volumeId[RWVOL], 0, 0);
2255 if ((m == 0) || (code != ENOENT)) {
2256 PrintError("Failed to set correct names and ids: ", code);
2261 /* have to clear dest. flags to ensure new vol goes online:
2262 * because the restore (forwarded) operation copied
2263 * the V_inService(=0) flag over to the destination.
2265 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
2267 if ((m == 0) || (code != ENOENT)) {
2268 PrintError("Failed to set flags on ro volume: ", code);
2273 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
2274 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
2275 entry.flags |= RO_EXISTS;
2280 /* End the transactions and destroy the connections */
2281 for (s=0; s<volcount; s++) {
2282 if (replicas[s].trans)
2283 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
2284 replicas[s].trans = 0;
2285 if (!code) code = rcode;
2287 if ((s == 0) || (code != ENOENT)) {
2288 PrintError("Could not end transaction on a ro volume: ", code);
2290 PrintError("Transaction timed out on a ro volume. Will retry.\n", 0);
2291 if (times[s].vldbEntryIndex < vldbindex)
2292 vldbindex = times[s].vldbEntryIndex;
2297 rx_DestroyConnection(toconns[s]);
2301 MapNetworkToHost(&entry, &storeEntry);
2302 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2303 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2304 } /* for each index in the vldb */
2306 /* End the transaction on the cloned volume */
2307 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2309 if (!code) code = rcode;
2311 PrintError("Failed to end transaction on rw volume: ", code);
2313 /* Figure out if any volume were not released and say so */
2314 for (failure=0, i=0; i<entry.nServers; i++) {
2315 if (!(entry.serverFlags[i] & NEW_REPSITE))
2320 fprintf(STDERR, "The volume %u could not be released to the following %d sites:\n",
2322 for (i=0; i<entry.nServers; i++) {
2323 if (!(entry.serverFlags[i] & NEW_REPSITE)) {
2324 MapPartIdIntoName(entry.serverPartition[i],pname);
2325 fprintf(STDERR,"\t%35s %s\n",
2326 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
2330 MapNetworkToHost(&entry,&storeEntry);
2331 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, LOCKREL_TIMESTAMP);
2332 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2334 ERROREXIT(VOLSERBADRELEASE);
2337 /* All the ROs were release successfully. Remove the temporary clone */
2340 fprintf(STDOUT,"Deleting the releaseClone %u ...", cloneVolId);
2343 code = DelVol (fromconn, cloneVolId, afrompart, ITOffline);
2344 ONERROR (code, cloneVolId, "Failed to delete volume %u.\n");
2346 fprintf(STDOUT," done\n");
2350 for (i=0; i<entry.nServers; i++)
2351 entry.serverFlags[i] &= ~NEW_REPSITE;
2353 /* Update the VLDB */
2355 fprintf(STDOUT,"updating VLDB ...");
2358 MapNetworkToHost(&entry, &storeEntry);
2359 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
2360 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2361 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2363 fprintf(STDOUT," done\n");
2367 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2370 fprintf (STDERR,"Failed to end cloning transaction on the RW volume %u\n", afromvol);
2371 if (!error) error = code;
2375 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2378 fprintf (STDERR,"Failed to end transaction on the release clone %u\n", cloneVolId);
2379 if (!error) error = code;
2382 for (i=0; i<nservers; i++) {
2383 if (replicas && replicas[i].trans) {
2384 code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
2385 replicas[i].trans = 0;
2387 fprintf(STDERR,"Failed to end transaction on ro volume %u at server 0x%x\n",
2388 entry.volumeId[ROVOL],
2389 hostutil_GetNameByINet(htonl(replicas[i].server.destHost)));
2390 if (!error) error = code;
2393 if (toconns && toconns[i]) {
2394 rx_DestroyConnection(toconns[i]);
2399 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, RWVOL,
2400 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2402 fprintf(STDERR,"Could not release lock on the VLDB entry for volume %u\n", afromvol);
2403 if (!error) error = vcode;
2407 PrintError("", error);
2409 if (fromconn) rx_DestroyConnection(fromconn);
2410 if (results.manyResults_val) free (results.manyResults_val);
2411 if (replicas) free (replicas);
2412 if (toconns) free (toconns);
2413 if (times) free (times);
2418 void dump_sig_handler(x)
2420 fprintf(STDERR,"\nSignal handler: vos dump operation\n");
2424 /* Dump the volume <afromvol> on <afromserver> and
2425 * <afrompart> to <afilename> starting from <fromdate>.
2426 * DumpFunction does the real work behind the scenes after
2427 * extracting parameters from the rock
2429 int UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2430 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
2432 struct rx_connection *fromconn = (struct rx_connection *)0;
2433 struct rx_call *fromcall = (struct rx_call *)0;
2434 afs_int32 fromtid=0, rxError=0, rcode=0;
2435 afs_int32 code, error = 0;
2437 if (setjmp(env)) ERROR_EXIT(EPIPE);
2438 #ifndef AFS_NT40_ENV
2439 (void) signal(SIGPIPE, dump_sig_handler);
2441 (void) signal(SIGINT, dump_sig_handler);
2443 /* get connections to the servers */
2444 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2445 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2447 fprintf(STDERR,"Could not start transaction on the volume %u to be dumped\n", afromvol);
2453 fprintf(STDERR,"Full Dump ...");
2455 fprintf(STDERR,"Incremental Dump (as of %.24s) ...",
2456 ctime((time_t *)&fromdate));
2460 fromcall = rx_NewCall(fromconn);
2461 code = StartAFSVolDump(fromcall, fromtid, fromdate);
2463 fprintf(STDERR,"Could not start the dump process \n");
2466 if (code = DumpFunction(fromcall, rock)) {
2467 fprintf(STDERR,"Error while dumping volume \n");
2472 fprintf(STDERR,"completed\n");
2476 code = rx_EndCall(fromcall, rxError);
2478 fprintf(STDERR,"Error in rx_EndCall\n");
2479 if (!error) error = code;
2483 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2484 if (code || rcode) {
2485 fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol);
2486 if (!error) error = (code?code:rcode);
2490 rx_DestroyConnection(fromconn);
2492 PrintError("", error);
2498 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
2499 * the dump file <afilename>. WriteData does all the real work
2500 * after extracting params from the rock
2502 int UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
2503 char tovolname[], int flags, afs_int32 (*WriteData)(), char *rock)
2505 struct rx_connection *toconn,*tempconn;
2506 struct rx_call *tocall;
2507 afs_int32 totid, code, rcode, vcode,terror = 0;
2508 afs_int32 rxError = 0;
2509 struct volser_status tstatus;
2514 struct nvldbentry entry,storeEntry;
2517 struct restoreCookie cookie;
2519 afs_int32 newDate, volflag, voltype, volsertype;
2520 int index, same, errcode;
2524 memset(&cookie, 0, sizeof(cookie));
2529 tocall = (struct rx_call *)0;
2530 toconn = (struct rx_connection *)0;
2531 tempconn = (struct rx_connection *)0;
2535 if (flags & RV_RDONLY) {
2537 volsertype = volser_RO;
2540 volsertype = volser_RW;
2544 toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
2545 if(pvolid == 0) {/*alot a new id if needed */
2546 vcode = VLDB_GetEntryByName(tovolname, &entry);
2547 if(vcode == VL_NOENT) {
2548 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 1, &pvolid);
2550 fprintf(STDERR,"Could not get an Id for the volume %s\n",tovolname);
2555 } else if (flags & RV_RDONLY) {
2556 if (entry.flags & RW_EXISTS) {
2557 fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
2558 error = VOLSERBADOP;
2561 if (!entry.volumeId[ROVOL]) {
2562 fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
2563 error = VOLSERBADOP;
2566 pvolid = entry.volumeId[ROVOL];
2568 pvolid = entry.volumeId[RWVOL];
2570 }/* at this point we have a volume id to use/reuse for the volume to be restored */
2572 if(strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
2573 fprintf(STDERR,"The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",tovolname);
2574 error = VOLSERBADOP;
2577 MapPartIdIntoName(topart, partName);
2578 fprintf(STDOUT,"Restoring volume %s Id %u on server %s partition %s ..", tovolname,
2579 pvolid, hostutil_GetNameByINet(toserver), partName);
2581 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
2583 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
2585 fprintf(STDOUT,"Deleting the previous volume %u ...",pvolid);
2588 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2590 fprintf(STDERR,"Failed to start transaction on %u\n",pvolid);
2594 code = AFSVolSetFlags(toconn, totid, VTDeleteOnSalvage | VTOutOfService);
2596 fprintf(STDERR,"Could not set flags on volume %u \n",pvolid);
2600 code = AFSVolDeleteVolume(toconn,totid);
2602 fprintf(STDERR,"Could not delete volume %u\n",pvolid);
2606 code = AFSVolEndTrans(toconn, totid, &rcode);
2608 if (!code) code = rcode;
2610 fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
2614 if (verbose) fprintf(STDOUT," done\n");
2615 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
2617 fprintf(STDERR,"Could not create new volume %u\n",pvolid);
2623 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
2625 fprintf(STDERR,"Failed to start transaction on %u\n",pvolid);
2631 cookie.parent = pvolid;
2632 cookie.type = voltype;
2634 strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
2636 tocall = rx_NewCall(toconn);
2637 terror = StartAFSVolRestore(tocall,totid, 1,&cookie);
2639 fprintf(STDERR,"Volume restore Failed \n");
2643 code = WriteData(tocall, rock);
2645 fprintf(STDERR,"Could not transmit data\n");
2649 terror = rx_EndCall(tocall,rxError);
2650 tocall = (struct rx_call *) 0;
2652 fprintf(STDERR,"rx_EndCall Failed \n");
2656 code = AFSVolGetStatus(toconn,totid, &tstatus);
2658 fprintf(STDERR,"Could not get status information about the volume %u\n",pvolid);
2662 code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
2664 fprintf(STDERR,"Could not set the right type and ID on %u\n",pvolid);
2669 code = AFSVolSetDate(toconn,totid, newDate);
2671 fprintf(STDERR,"Could not set the date on %u\n",pvolid);
2676 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
2677 code = AFSVolSetFlags(toconn, totid, volflag);
2679 fprintf(STDERR,"Could not mark %u online\n",pvolid );
2684 /* It isn't handled right in refail */
2685 code = AFSVolEndTrans(toconn, totid, &rcode);
2687 if(!code) code = rcode;
2689 fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
2695 fprintf(STDOUT," done\n");
2697 if (success && (!reuseID || (flags & RV_FULLRST))) {
2698 /* Volume was restored on the file server, update the
2699 * VLDB to reflect the change.
2701 vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
2702 if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
2703 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",pvolid);
2707 if (!vcode) MapHostToNetwork(&entry);
2708 if(vcode == VL_NOENT) { /* it doesnot exist already */
2709 /*make the vldb return this indication specifically*/
2710 if (verbose) fprintf(STDOUT,"------- Creating a new VLDB entry ------- \n");
2711 strcpy(entry.name, tovolname);
2713 entry.serverNumber[0] = toserver;/*should be indirect */
2714 entry.serverPartition[0] = topart;
2715 entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2716 entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2717 if (flags & RV_RDONLY)
2718 entry.volumeId[ROVOL] = pvolid;
2719 else if(tstatus.cloneID != 0){
2720 entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
2723 entry.volumeId[ROVOL] = INVALID_BID;
2724 entry.volumeId[RWVOL] = pvolid;
2726 if(tstatus.backupID != 0){
2727 entry.volumeId[BACKVOL] = tstatus.backupID;
2728 /*this should come from status info on the volume if non zero */
2731 entry.volumeId[BACKVOL] = INVALID_BID;
2732 MapNetworkToHost(&entry,&storeEntry);
2733 vcode = VLDB_CreateEntry(&storeEntry);
2735 fprintf(STDERR,"Could not create the VLDB entry for volume number %u \n",pvolid);
2740 if (verbose) EnumerateEntry(&entry);
2742 else { /*update the existing entry */
2744 fprintf(STDOUT,"Updating the existing VLDB entry\n");
2745 fprintf(STDOUT,"------- Old entry -------\n");
2746 EnumerateEntry(&entry);
2747 fprintf(STDOUT,"------- New entry -------\n");
2749 vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
2751 fprintf(STDERR,"Could not lock the entry for volume number %u \n",pvolid);
2756 strcpy(entry.name, tovolname);
2758 /* Update the vlentry with the new information */
2759 if (flags & RV_RDONLY)
2760 index = Lp_ROMatch(toserver, topart, &entry) - 1;
2762 index = Lp_GetRwIndex(&entry);
2764 /* Add the new site for the volume being restored */
2765 entry.serverNumber[entry.nServers] = toserver;
2766 entry.serverPartition[entry.nServers] = topart;
2767 entry.serverFlags[entry.nServers] =
2768 (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2771 /* This volume should be deleted on the old site
2772 * if its different from new site.
2774 same = VLDB_IsSameAddrs(toserver, entry.serverNumber[index], &errcode);
2776 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
2779 if ( (!errcode && !same) || (entry.serverPartition[index] != topart) ) {
2780 tempconn = UV_Bind(entry.serverNumber[index], AFSCONF_VOLUMEPORT);
2782 MapPartIdIntoName(entry.serverPartition[index], apartName);
2783 fprintf(STDOUT,"Deleting the previous volume %u on server %s, partition %s ...",
2785 hostutil_GetNameByINet(entry.serverNumber[index]), apartName);
2788 code = AFSVolTransCreate(tempconn, pvolid, entry.serverPartition[index], ITOffline, &temptid);
2790 code = AFSVolSetFlags(tempconn, temptid, VTDeleteOnSalvage | VTOutOfService);
2792 fprintf(STDERR,"Could not set flags on volume %u on the older site\n",pvolid);
2796 code = AFSVolDeleteVolume(tempconn,temptid);
2798 fprintf(STDERR,"Could not delete volume %u on the older site\n",pvolid);
2802 code = AFSVolEndTrans(tempconn, temptid, &rcode);
2804 if(!code) code = rcode;
2806 fprintf(STDERR,"Could not end transaction on volume %u on the older site\n",pvolid);
2810 if(verbose) fprintf(STDOUT," done\n");
2811 MapPartIdIntoName(entry.serverPartition[index],partName);
2814 entry.serverNumber[index] = toserver;
2815 entry.serverPartition[index] = topart;
2818 entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2819 MapNetworkToHost(&entry,&storeEntry);
2820 vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
2822 fprintf(STDERR,"Could not update the entry for volume number %u \n",pvolid);
2827 if(verbose) EnumerateEntry(&entry);
2834 code = rx_EndCall(tocall, rxError);
2835 if (!error) error = code;
2838 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2840 fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %u\n",pvolid);
2841 if(!error) error = vcode;
2845 code = AFSVolEndTrans(toconn, totid, &rcode);
2846 if(!code) code = rcode;
2848 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
2849 if(!error) error = code;
2853 code = AFSVolEndTrans(toconn, temptid, &rcode);
2854 if(!code) code = rcode;
2856 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
2857 if(!error) error = code;
2860 if(tempconn) rx_DestroyConnection(tempconn);
2861 if(toconn) rx_DestroyConnection(toconn);
2862 PrintError("",error);
2867 /*unlocks the vldb entry associated with <volid> */
2868 int UV_LockRelease(afs_int32 volid)
2874 if (verbose) fprintf(STDERR,"Binding to the VLDB server\n");
2875 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,volid,-1,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
2877 fprintf(STDERR,"Could not unlock the entry for volume number %u in VLDB \n",volid);
2878 PrintError("",vcode);
2881 if (verbose) fprintf(STDERR,"VLDB updated\n");
2886 /*adds <server> and <part> as a readonly replication site for <volid>
2888 int UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
2890 int j, nro=0, islocked=0;
2891 struct nvldbentry entry,storeEntry;
2892 afs_int32 vcode, error=0;
2895 error = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
2897 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n", volid);
2902 error = VLDB_GetEntryByID(volid,RWVOL, &entry);
2904 fprintf(STDERR,"Could not fetch the VLDB entry for volume number %u \n",volid);
2908 if (!ISNAMEVALID(entry.name)){
2909 fprintf(STDERR,"Volume name %s is too long, rename before adding site\n", entry.name);
2910 error = VOLSERBADOP;
2913 MapHostToNetwork(&entry);
2915 /* See if it's too many entries */
2916 if (entry.nServers >= NMAXNSERVERS){
2917 fprintf(STDERR,"Total number of entries will exceed %u\n", NMAXNSERVERS);
2918 error = VOLSERBADOP;
2922 /* See if it's on the same server */
2923 for (j=0; j < entry.nServers; j++) {
2924 if (entry.serverFlags[j] & ITSROVOL) {
2926 if (VLDB_IsSameAddrs(server, entry.serverNumber[j], &error)) {
2928 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
2931 MapPartIdIntoName(entry.serverPartition[j], apartName);
2932 fprintf(STDERR,"RO already exists on partition %s. Multiple ROs on a single server aren't allowed\n", apartName);
2933 error = VOLSERBADOP;
2940 /* See if it's too many RO sites - leave one for the RW */
2941 if (nro >= NMAXNSERVERS-1){
2942 fprintf(STDERR,"Total number of sites will exceed %u\n", NMAXNSERVERS-1);
2943 error = VOLSERBADOP;
2947 if (verbose) fprintf(STDOUT,"Adding a new site ...");
2949 entry.serverNumber[entry.nServers] = server;
2950 entry.serverPartition[entry.nServers] = part;
2951 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
2954 MapNetworkToHost(&entry,&storeEntry);
2955 error = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2957 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
2961 if (verbose) fprintf(STDOUT," done\n");
2965 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2967 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
2968 PrintError("", vcode);
2972 PrintError("", error);
2976 /*removes <server> <part> as read only site for <volid> from the vldb */
2977 int UV_RemoveSite(afs_int32 server, afs_int32 part, afs_int32 volid)
2980 struct nvldbentry entry,storeEntry;
2983 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
2985 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
2986 PrintError("",vcode);
2990 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
2992 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
2993 PrintError("",vcode);
2996 MapHostToNetwork(&entry);
2997 if(!Lp_ROMatch(server, part, &entry)){
2998 /*this site doesnot exist */
2999 fprintf(STDERR,"This site is not a replication site \n");
3000 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3002 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3003 PrintError("",vcode);
3004 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3009 else { /*remove the rep site */
3010 Lp_SetROValue(&entry, server, part, 0, 0);
3012 if((entry.nServers == 1) && (entry.flags & RW_EXISTS))
3013 entry.flags &= ~RO_EXISTS;
3014 if(entry.nServers < 1) { /*this is the last ref */
3015 if(verbose) fprintf(STDOUT,"Deleting the VLDB entry for %u ...",volid);
3017 vcode = ubik_Call(VL_DeleteEntry,cstruct, 0,volid, ROVOL);
3019 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",volid);
3020 PrintError("",vcode);
3023 if (verbose) fprintf(STDOUT," done\n");
3025 MapNetworkToHost(&entry,&storeEntry);
3026 fprintf(STDOUT,"Deleting the replication site for volume %u ...",volid);
3028 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3030 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3031 PrintError("",vcode);
3032 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3035 if(verbose) fprintf(STDOUT," done\n");
3040 /*sets <server> <part> as read/write site for <volid> in the vldb */
3041 int UV_ChangeLocation(afs_int32 server, afs_int32 part, afs_int32 volid)
3044 struct nvldbentry entry,storeEntry;
3047 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3049 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3050 PrintError("",vcode);
3053 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3055 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3056 PrintError("",vcode);
3059 MapHostToNetwork(&entry);
3060 index = Lp_GetRwIndex(&entry);
3062 /* no RW site exists */
3063 fprintf(STDERR,"No existing RW site for volume %u", volid);
3064 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3066 fprintf(STDERR,"Could not release lock on entry for volume %u \n",volid);
3067 PrintError("",vcode);
3072 else { /* change the RW site */
3073 entry.serverNumber[index] = server;
3074 entry.serverPartition[index] = part;
3075 MapNetworkToHost(&entry,&storeEntry);
3076 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3078 fprintf(STDERR,"Could not update entry for volume %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 /*list all the partitions on <aserver> */
3089 int UV_ListPartitions(afs_int32 aserver, struct partList *ptrPartList, afs_int32 *cntp)
3091 struct rx_connection *aconn;
3092 struct pIDs partIds;
3093 struct partEntries partEnts;
3094 register int i, j=0, code;
3097 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3099 partEnts.partEntries_len = 0;
3100 partEnts.partEntries_val = NULL;
3101 code = AFSVolXListPartitions(aconn, &partEnts); /* this is available only on new servers */
3102 if (code == RXGEN_OPCODE)
3104 for(i = 0; i < 26; i++) /* try old interface */
3105 partIds.partIds[i] = -1;
3106 code = AFSVolListPartitions(aconn, &partIds);
3108 for (i = 0;i < 26; i++) {
3109 if((partIds.partIds[i]) != -1) {
3110 ptrPartList->partId[j] = partIds.partIds[i];
3111 ptrPartList->partFlags[j] = PARTVALID;
3114 ptrPartList->partFlags[i] = 0;
3121 *cntp = partEnts.partEntries_len;
3122 if (*cntp > VOLMAXPARTS) {
3123 fprintf(STDERR,"Warning: number of partitions on the server too high %d (process only %d)\n",
3124 *cntp, VOLMAXPARTS);
3125 *cntp = VOLMAXPARTS;
3127 for (i = 0;i < *cntp; i++) {
3128 ptrPartList->partId[i] = partEnts.partEntries_val[i];
3129 ptrPartList->partFlags[i] = PARTVALID;
3131 free(partEnts.partEntries_val);
3135 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
3136 PrintError("",code);
3137 if(aconn) rx_DestroyConnection(aconn);
3142 /*zap the list of volumes specified by volPtrArray (the volCloneId field).
3143 This is used by the backup system */
3144 int UV_ZapVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3146 struct rx_connection *aconn;
3147 struct volDescription *curPtr;
3150 afs_int32 rcode = 0;
3151 afs_int32 success = 1;
3154 aconn = (struct rx_connection *)0;
3155 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3157 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3158 if(curPtr->volFlags & CLONEVALID) {
3159 curPtr->volFlags &= ~CLONEZAPPED;
3161 code = AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline, &tid);
3162 if(code) success = 0;
3164 code = AFSVolDeleteVolume(aconn, tid);
3165 if(code) success = 0;
3166 code = AFSVolEndTrans(aconn, tid, &rcode);
3167 if(code || rcode) success = 0;
3169 if(success) curPtr->volFlags |= CLONEZAPPED;
3170 if(!success) fprintf(STDERR,"Could not zap volume %u\n",curPtr->volCloneId);
3171 if(success && verbose) fprintf(STDOUT,"Clone of %s %u deleted\n", curPtr->volName,curPtr->volCloneId);
3176 if(aconn)rx_DestroyConnection(aconn);
3180 /*return a list of clones of the volumes specified by volPtrArray. Used by the
3182 int UV_GenerateVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3184 struct rx_connection *aconn;
3185 struct volDescription *curPtr;
3188 afs_int32 rcode = 0;
3190 int reuseCloneId = 0;
3191 afs_int32 curCloneId = 0;
3192 char cloneName[256];/*max vol name */
3194 aconn = (struct rx_connection *)0;
3195 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3197 if((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
3199 else { /*get a bunch of id's from vldb */
3200 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, arraySize, &curCloneId);
3202 fprintf(STDERR,"Could not get ID's for the clone from VLDB\n");
3203 PrintError("",code);
3208 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3209 if(curPtr->volFlags & ENTRYVALID) {
3211 curPtr->volFlags |= CLONEVALID;
3212 /*make a clone of curParentId and record as curPtr->volCloneId */
3213 code = AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline, &tid);
3214 if(verbose && code) fprintf(STDERR,"Clone for volume %s %u failed \n",curPtr->volName,curPtr->volId);
3216 curPtr->volFlags &= ~CLONEVALID; /*cant clone */
3220 if(strlen(curPtr->volName) < (VOLSER_OLDMAXVOLNAME - 9) ){
3221 strcpy(cloneName, curPtr->volName);
3222 strcat(cloneName,"-tmpClone-");
3224 else strcpy(cloneName,"-tmpClone");
3226 curPtr->volCloneId = curCloneId;
3230 code = AFSVolClone(aconn, tid, 0, readonlyVolume, cloneName,&(curPtr->volCloneId));
3232 curPtr->volFlags &= ~CLONEVALID;
3234 fprintf(STDERR,"Could not clone %s due to error %u\n", curPtr->volName,code);
3235 code=AFSVolEndTrans(aconn, tid, &rcode);
3237 fprintf(STDERR,"WARNING: could not end transaction\n");
3240 if(verbose) fprintf(STDOUT,"********** Cloned %s temporary %u\n",cloneName,curPtr->volCloneId);
3241 code = AFSVolEndTrans(aconn, tid, &rcode);
3243 curPtr->volFlags &= ~CLONEVALID;
3251 if (aconn) rx_DestroyConnection(aconn);
3256 /*list all the volumes on <aserver> and <apart>. If all = 1, then all the
3257 * relevant fields of the volume are also returned. This is a heavy weight operation.*/
3258 int UV_ListVolumes(afs_int32 aserver, afs_int32 apart, int all, struct volintInfo **resultPtr, afs_int32 *size)
3260 struct rx_connection *aconn;
3262 volEntries volumeInfo;
3266 *resultPtr = (volintInfo *)0;
3267 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3268 volumeInfo.volEntries_len = 0;
3270 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3271 code = AFSVolListVolumes(aconn, apart, all, &volumeInfo);
3273 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
3276 *resultPtr = volumeInfo.volEntries_val;
3277 *size = volumeInfo.volEntries_len;
3280 if(aconn) rx_DestroyConnection(aconn);
3281 PrintError("",code);
3285 /*------------------------------------------------------------------------
3286 * EXPORTED UV_XListVolumes
3289 * List the extended information for all the volumes on a particular
3290 * File Server and partition. We may either return the volume's ID
3291 * or all of its extended information.
3294 * a_serverID : Address of the File Server for which we want
3295 * extended volume info.
3296 * a_partID : Partition for which we want the extended
3298 * a_all : If non-zero, fetch ALL the volume info,
3299 * otherwise just the volume ID.
3300 * a_resultPP : Ptr to the address of the area containing
3301 * the returned volume info.
3302 * a_numEntsInResultP : Ptr for the value we set for the number of
3307 * Otherise, the return value of AFSVolXListVolumes.
3310 * This routine is closely related to UV_ListVolumes, which returns
3311 * only the standard level of detail on AFS volumes. It is a
3312 * heavyweight operation, zipping through all the volume entries for
3313 * a given server/partition.
3317 *------------------------------------------------------------------------*/
3319 int UV_XListVolumes(afs_int32 a_serverID, afs_int32 a_partID, int a_all,
3320 struct volintXInfo **a_resultPP, afs_int32 *a_numEntsInResultP)
3322 struct rx_connection *rxConnP; /*Ptr to the Rx connection involved*/
3323 afs_int32 code; /*Error code to return*/
3324 volXEntries volumeXInfo; /*Area for returned extended vol info*/
3327 * Set up our error code and the area for returned extended volume info.
3328 * We set the val field to a null pointer as a hint for the stub to
3332 *a_numEntsInResultP = 0;
3333 *a_resultPP = (volintXInfo *)0;
3334 volumeXInfo.volXEntries_val = (volintXInfo *)0;
3335 volumeXInfo.volXEntries_len = 0;
3338 * Bind to the Volume Server port on the File Server machine in question,
3341 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
3342 code = AFSVolXListVolumes(rxConnP, a_partID, a_all, &volumeXInfo);
3345 "[UV_XListVolumes] Couldn't fetch volume list\n");
3348 * We got the info; pull out the pointer to where the results lie
3349 * and how many entries are there.
3351 *a_resultPP = volumeXInfo.volXEntries_val;
3352 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
3356 * If we got an Rx connection, throw it away.
3359 rx_DestroyConnection(rxConnP);
3361 PrintError("", code);
3363 } /*UV_XListVolumes*/
3365 /* get all the information about volume <volid> on <aserver> and <apart> */
3366 int UV_ListOneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 volid, struct volintInfo **resultPtr)
3368 struct rx_connection *aconn;
3370 volEntries volumeInfo;
3374 *resultPtr = (volintInfo *)0;
3375 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3376 volumeInfo.volEntries_len = 0;
3378 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3379 code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
3381 fprintf(STDERR,"Could not fetch the information about volume %u from the server\n",volid);
3384 *resultPtr = volumeInfo.volEntries_val;
3388 if(aconn) rx_DestroyConnection(aconn);
3389 PrintError("",code);
3393 /*------------------------------------------------------------------------
3394 * EXPORTED UV_XListOneVolume
3397 * List the extended information for a volume on a particular File
3398 * Server and partition.
3401 * a_serverID : Address of the File Server for which we want
3402 * extended volume info.
3403 * a_partID : Partition for which we want the extended
3405 * a_volID : Volume ID for which we want the info.
3406 * a_resultPP : Ptr to the address of the area containing
3407 * the returned volume info.
3411 * Otherise, the return value of AFSVolXListOneVolume.
3414 * This routine is closely related to UV_ListOneVolume, which returns
3415 * only the standard level of detail on the chosen AFS volume.
3419 *------------------------------------------------------------------------*/
3421 int UV_XListOneVolume(afs_int32 a_serverID, afs_int32 a_partID,
3422 afs_int32 a_volID, struct volintXInfo **a_resultPP)
3424 struct rx_connection *rxConnP; /*Rx connection to Volume Server*/
3425 afs_int32 code; /*Error code*/
3426 volXEntries volumeXInfo; /*Area for returned info*/
3429 * Set up our error code, and the area we're in which we are returning
3430 * the info. Setting the val field to a null pointer tells the stub
3431 * to allocate space for us.
3434 *a_resultPP = (volintXInfo *)0;
3435 volumeXInfo.volXEntries_val = (volintXInfo *)0;
3436 volumeXInfo.volXEntries_len = 0;
3439 * Bind to the Volume Server port on the File Server machine in question,
3442 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
3443 code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
3446 "[UV_XListOneVolume] Couldn't fetch the volume information\n");
3449 * We got the info; pull out the pointer to where the results lie.
3451 *a_resultPP = volumeXInfo.volXEntries_val;
3454 * If we got an Rx connection, throw it away.
3457 rx_DestroyConnection(rxConnP);
3459 PrintError("",code);
3464 * Given a volume we read from a partition, check if it is
3465 * represented in the VLDB correctly.
3467 * The VLDB is looked up by the RW volume id (not its name).
3468 * The RW contains the true name of the volume (BK and RO set
3469 * the name in the VLDB only on creation of the VLDB entry).
3470 * We want rules strict enough that when we check all volumes
3471 * on one partition, it does not need to be done again. IE:
3472 * two volumes on different partitions won't constantly
3473 * change a VLDB entry away from what the other set.
3474 * For RW and BK volumes, we will always check the VLDB to see
3475 * if the two exist on the server/partition. May seem redundant,
3476 * but this is an easy check of the VLDB. IE: if the VLDB entry
3477 * says the BK exists but no BK volume is there, we will detect
3478 * this when we check the RW volume.
3479 * VLDB entries are locked only when a change needs to be done.
3480 * Output changed to look a lot like the "vos syncserv" otuput.
3482 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart,
3483 afs_int32 *modentry, afs_uint32 *maxvolid)
3486 afs_int32 code, error = 0;
3487 struct nvldbentry entry, storeEntry;
3489 int pass=0, islocked=0, createentry, addvolume, modified, mod;
3492 if (modentry) *modentry = 0;
3493 rwvolid = ((volumeinfo->type == RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
3496 /* Check to see if the VLDB is ok without locking it (pass 1).
3497 * If it will change, then lock the VLDB entry, read it again,
3498 * then make the changes to it (pass 2).
3501 code = ubik_Call(VL_SetLock, cstruct, 0, rwvolid, RWVOL, VLOP_DELETE);
3503 fprintf(STDERR, "Could not lock VLDB entry for %u\n", rwvolid);
3509 createentry = 0; /* Do we need to create a VLDB entry */
3510 addvolume = 0; /* Add this volume to the VLDB entry */
3511 modified = 0; /* The VLDB entry was modified */
3513 /* Read the entry from VLDB by its RW volume id */
3514 code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
3516 if (code != VL_NOENT) {
3517 fprintf(STDOUT,"Could not retreive the VLDB entry for volume %u \n", rwvolid);
3521 memset(&entry, 0, sizeof(entry));
3522 vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
3526 MapHostToNetwork(&entry);
3529 if (verbose && (pass == 1)) {
3530 fprintf(STDOUT,"_______________________________\n");
3531 fprintf(STDOUT,"\n-- status before -- \n");
3533 fprintf(STDOUT,"\n**does not exist**\n");
3535 if ((entry.flags & RW_EXISTS) ||
3536 (entry.flags & RO_EXISTS) ||
3537 (entry.flags & BACK_EXISTS))
3538 EnumerateEntry(&entry);
3540 fprintf(STDOUT,"\n");
3543 if (volumeinfo->type == RWVOL) { /* RW volume exists */
3549 /* Check existence of RW and BK volumes */
3550 code = CheckVldbRWBK(&entry, &mod);
3551 if (code) ERROR_EXIT(code);
3552 if (mod) modified++;
3554 idx = Lp_GetRwIndex(&entry);
3555 if (idx == -1) { /* RW index not found in the VLDB entry */
3556 idx = entry.nServers; /* put it into next index */
3559 } else { /* RW index found in the VLDB entry. */
3560 /* Verify if this volume's location matches where the VLDB says it is */
3561 if (!Lp_Match(aserver, apart, &entry)) {
3562 if (entry.flags & RW_EXISTS) {
3563 /* The RW volume exists elsewhere - report this one a duplicate */
3565 MapPartIdIntoName(apart, pname);
3566 fprintf(STDERR,"*** Warning: Orphaned RW volume %u exists on %s %s\n",
3567 rwvolid, hostutil_GetNameByINet(aserver), pname);
3568 MapPartIdIntoName(entry.serverPartition[idx], pname);
3569 fprintf(STDERR," VLDB reports RW volume %u exists on %s %s\n",
3571 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
3574 /* The RW volume does not exist - have VLDB point to this one */
3577 /* Check for orphaned BK volume on old partition */
3578 if (entry.flags & BACK_EXISTS) {
3580 MapPartIdIntoName(entry.serverPartition[idx], pname);
3581 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3582 entry.volumeId[BACKVOL],
3583 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
3584 MapPartIdIntoName(apart, pname);
3585 fprintf(STDERR," VLDB reports its RW volume %u exists on %s %s\n",
3586 rwvolid, hostutil_GetNameByINet(aserver), pname);
3591 /* Volume location matches the VLDB location */
3592 if ( (volumeinfo->backupID && !entry.volumeId[BACKVOL]) ||
3593 (volumeinfo->cloneID && !entry.volumeId[ROVOL]) ||
3594 (strncmp(entry.name,volumeinfo->name,VOLSER_OLDMAXVOLNAME) != 0) ) {
3602 entry.flags |= RW_EXISTS;
3603 entry.volumeId[RWVOL] = rwvolid;
3604 if (!entry.volumeId[BACKVOL])
3605 entry.volumeId[BACKVOL] = volumeinfo->backupID;
3606 if (!entry.volumeId[ROVOL])
3607 entry.volumeId[ROVOL] = volumeinfo->cloneID;
3609 entry.serverFlags[idx] = ITSRWVOL;
3610 entry.serverNumber[idx] = aserver;
3611 entry.serverPartition[idx] = apart;
3612 strncpy(entry.name, volumeinfo->name, VOLSER_OLDMAXVOLNAME);
3616 /* One last check - to update BK if need to */
3617 code = CheckVldbRWBK(&entry, &mod);
3618 if (code) ERROR_EXIT(code);
3619 if (mod) modified++;
3623 else if (volumeinfo->type == BACKVOL) { /* A BK volume */
3629 /* Check existence of RW and BK volumes */
3630 code = CheckVldbRWBK(&entry, &mod);
3631 if (code) ERROR_EXIT(code);
3632 if (mod) modified++;
3634 idx = Lp_GetRwIndex(&entry);
3635 if (idx == -1) { /* RW index not found in the VLDB entry */
3636 idx = entry.nServers; /* Put it into next index */
3639 } else { /* RW index found in the VLDB entry */
3640 /* Verify if this volume's location matches where the VLDB says it is */
3641 if (!Lp_Match(aserver, apart, &entry)) {
3642 /* VLDB says RW and/or BK is elsewhere - report this BK volume orphaned */
3644 MapPartIdIntoName(apart, pname);
3645 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3646 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
3647 MapPartIdIntoName(entry.serverPartition[idx], pname);
3648 fprintf(STDERR," VLDB reports its RW/BK volume %u exists on %s %s\n",
3650 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
3653 if (volumeinfo->volid != entry.volumeId[BACKVOL]) {
3654 if (!(entry.flags & BACK_EXISTS)) {
3657 else if (volumeinfo->volid > entry.volumeId[BACKVOL]) {
3661 MapPartIdIntoName(entry.serverPartition[idx], pname);
3662 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3663 entry.volumeId[BACKVOL], hostutil_GetNameByINet(aserver), pname);
3664 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
3669 MapPartIdIntoName(entry.serverPartition[idx], pname);
3670 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
3671 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
3672 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
3673 entry.volumeId[BACKVOL]);
3677 else if (!entry.volumeId[BACKVOL]) {
3684 entry.flags |= BACK_EXISTS;
3685 entry.volumeId[RWVOL] = rwvolid;
3686 entry.volumeId[BACKVOL] = volumeinfo->volid;
3688 entry.serverNumber[idx] = aserver;
3689 entry.serverPartition[idx] = apart;
3690 entry.serverFlags[idx] = ITSRWVOL;
3696 else if (volumeinfo->type == ROVOL) { /* A RO volume */
3697 if (volumeinfo->volid == entry.volumeId[ROVOL]) {
3698 /* This is a quick check to see if the RO entry exists in the
3699 * VLDB so we avoid the CheckVldbRO() call (which checks if each
3700 * RO volume listed in the VLDB exists).
3702 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
3704 idx = entry.nServers;
3708 if (!(entry.flags & RO_EXISTS)) {
3713 /* Before we correct the VLDB entry, make sure all the
3714 * ROs listed in the VLDB exist.
3716 code = CheckVldbRO(&entry, &mod);
3717 if (code) ERROR_EXIT(code);
3718 if (mod) modified++;
3720 if (!(entry.flags & RO_EXISTS)) {
3721 /* No RO exists in the VLDB entry - add this one */
3722 idx = entry.nServers;
3726 else if (volumeinfo->volid > entry.volumeId[ROVOL]) {
3727 /* The volume headers's RO ID does not match that in the VLDB entry,
3728 * and the vol hdr's ID is greater (implies more recent). So delete
3729 * all the RO volumes listed in VLDB entry and add this volume.
3731 for (j=0; j<entry.nServers; j++) {
3732 if (entry.serverFlags[j] & ITSROVOL) {
3733 /* Verify this volume exists and print message we are orphaning it */
3735 MapPartIdIntoName(apart, pname);
3736 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
3737 entry.volumeId[ROVOL],
3738 hostutil_GetNameByINet(entry.serverNumber[j]), pname);
3739 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
3743 Lp_SetRWValue(entry, entry.serverNumber[idx],
3744 entry.serverPartition[idx], 0L, 0L);
3751 idx = entry.nServers;
3755 else if (volumeinfo->volid < entry.volumeId[ROVOL]) {
3756 /* The volume headers's RO ID does not match that in the VLDB entry,
3757 * and the vol hdr's ID is lower (implies its older). So orphan it.
3760 MapPartIdIntoName(apart, pname);
3761 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
3762 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
3763 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
3764 entry.volumeId[ROVOL]);
3768 /* The RO volume ID in the volume header match that in the VLDB entry,
3769 * and there exist RO volumes in the VLDB entry. See if any of them
3770 * are this one. If not, then we add it.
3772 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
3774 idx = entry.nServers;
3782 entry.flags |= RO_EXISTS;
3783 entry.volumeId[RWVOL] = rwvolid;
3784 entry.volumeId[ROVOL] = volumeinfo->volid;
3786 entry.serverNumber[idx] = aserver;
3787 entry.serverPartition[idx] = apart;
3788 entry.serverFlags[idx] = ITSROVOL;
3794 /* Remember largest volume id */
3795 if (entry.volumeId[ROVOL] > *maxvolid) *maxvolid = entry.volumeId[ROVOL];
3796 if (entry.volumeId[BACKVOL] > *maxvolid) *maxvolid = entry.volumeId[BACKVOL];
3797 if (entry.volumeId[RWVOL] > *maxvolid) *maxvolid = entry.volumeId[RWVOL];
3800 MapNetworkToHost(&entry, &storeEntry);
3803 code = VLDB_CreateEntry(&storeEntry);
3805 fprintf(STDOUT,"Could not create a VLDB entry for the volume %u\n", rwvolid);
3810 if (pass == 1) goto retry;
3811 code = VLDB_ReplaceEntry(rwvolid, RWVOL, &storeEntry,
3812 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3814 fprintf(STDERR,"Could not update entry for %u\n", rwvolid);
3818 if (modentry) *modentry = modified;
3819 } else if (pass == 2) {
3820 code = ubik_Call(VL_ReleaseLock,cstruct, 0, rwvolid, RWVOL,
3821 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3823 PrintError("Could not unlock VLDB entry ", code);
3828 fprintf(STDOUT,"-- status after --\n");
3830 EnumerateEntry(&entry);
3832 fprintf(STDOUT,"\n**no change**\n");
3837 fprintf(STDOUT,"\n_______________________________\n");
3842 int sortVolumes(const void *a, const void *b)
3844 volintInfo *v1 = (volintInfo *)a;
3845 volintInfo *v2 = (volintInfo *)b;
3846 afs_int32 rwvolid1, rwvolid2;
3848 rwvolid1 = ((v1->type == RWVOL) ? v1->volid : v1->parentID);
3849 rwvolid2 = ((v2->type == RWVOL) ? v2->volid : v2->parentID);
3851 if (rwvolid1 > rwvolid2) return -1; /* lower RW id goes first */
3852 if (rwvolid1 < rwvolid2) return 1;
3854 if (v1->type == RWVOL) return -1; /* RW vols go first */
3855 if (v2->type == RWVOL) return 1;
3857 if ((v1->type == BACKVOL) && (v2->type == ROVOL )) return -1; /* BK vols next */
3858 if ((v1->type == ROVOL ) && (v2->type == BACKVOL)) return 1;
3860 if (v1->volid < v2->volid) return 1; /* larger volids first */
3861 if (v1->volid > v2->volid) return -1;
3866 * Synchronise <aserver> <apart>(if flags = 1) <avolid>.
3867 * Synchronize an individual volume against a sever and partition.
3868 * Checks the VLDB entry (similar to syncserv) as well as checks
3869 * if the volume exists on specified servers (similar to syncvldb).
3871 int UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
3873 struct rx_connection *aconn = 0;
3874 afs_int32 j, k, code, vcode, error = 0;
3875 afs_int32 tverbose, mod, modified = 0;
3876 struct nvldbentry vldbentry;
3877 afs_int32 volumeid = 0;
3878 volEntries volumeInfo;
3879 struct partList PartList;
3881 afs_int32 maxvolid = 0;
3883 volumeInfo.volEntries_val = (volintInfo *)0;
3884 volumeInfo.volEntries_len = 0;
3886 if (!aserver && flags) {
3887 /* fprintf(STDERR,"Partition option requires a server option\n"); */
3891 /* Turn verbose logging off and do our own verbose logging */
3895 /* Read the VLDB entry */
3896 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
3897 if (vcode && (vcode != VL_NOENT)) {
3898 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
3900 } else if (!vcode) {
3901 MapHostToNetwork(&vldbentry);
3905 fprintf(STDOUT,"Processing VLDB entry %s ...\n", avolname);
3906 fprintf(STDOUT,"_______________________________\n");
3907 fprintf(STDOUT,"\n-- status before -- \n");
3909 fprintf(STDOUT,"\n**does not exist**\n");
3911 if ((vldbentry.flags & RW_EXISTS) ||
3912 (vldbentry.flags & RO_EXISTS) ||
3913 (vldbentry.flags & BACK_EXISTS))
3914 EnumerateEntry(&vldbentry);
3916 fprintf(STDOUT,"\n");
3919 /* Verify that all of the VLDB entries exist on the repective servers
3920 * and partitions (this does not require that avolname be a volume ID).
3921 * Equivalent to a syncserv.
3924 code = CheckVldb(&vldbentry, &mod);
3926 fprintf(STDERR,"Could not process VLDB entry for volume %s\n", vldbentry.name);
3929 if (mod) modified++;
3932 /* If aserver is given, we will search for the desired volume on it */
3934 /* Generate array of partitions on the server that we will check */
3936 code = UV_ListPartitions(aserver, &PartList, &pcnt);
3938 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
3942 PartList.partId[0] = apart;
3946 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3948 /* If a volume ID were given, search for it on each partition */
3949 if (volumeid = atol(avolname)) {
3950 for (j=0; j<pcnt; j++) {
3951 code = AFSVolListOneVolume(aconn, PartList.partId[j], volumeid, &volumeInfo);
3953 if (code != ENODEV) {
3954 fprintf(STDERR,"Could not query server\n");
3958 /* Found one, sync it with VLDB entry */
3959 code = CheckVolume(volumeInfo.volEntries_val, aserver,
3960 PartList.partId[j], &mod, &maxvolid);
3961 if (code) ERROR_EXIT(code);
3962 if (mod) modified++;
3965 if (volumeInfo.volEntries_val)
3966 free(volumeInfo.volEntries_val);
3967 volumeInfo.volEntries_val = (volintInfo *)0;
3968 volumeInfo.volEntries_len = 0;
3972 /* Check to see if the RW, BK, and RO IDs exist on any
3973 * partitions. We get the volume IDs from the VLDB.
3975 rv = 1; /* Read the VLDB entry ? */
3976 for (j=0; j<MAXTYPES; j++) { /* for RW, RO, and BK IDs */
3978 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
3980 if (vcode == VL_NOENT) break;
3981 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
3987 if (vldbentry.volumeId[j] == 0) continue;
3989 for (k=0; k<pcnt; k++) { /* For each partition */
3990 volumeInfo.volEntries_val = (volintInfo *)0;
3991 volumeInfo.volEntries_len = 0;
3992 code = AFSVolListOneVolume(aconn, PartList.partId[k],
3993 vldbentry.volumeId[j], &volumeInfo);
3995 if (code != ENODEV) {
3996 fprintf(STDERR,"Could not query server\n");
4000 /* Found one, sync it with VLDB entry */
4001 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4002 PartList.partId[k], &mod, &maxvolid);
4003 if (code) ERROR_EXIT(code);
4004 if (mod) modified++, rv++;
4007 if (volumeInfo.volEntries_val)
4008 free(volumeInfo.volEntries_val);
4009 volumeInfo.volEntries_val = (volintInfo *)0;
4010 volumeInfo.volEntries_len = 0;
4013 } /* if (aserver) */
4015 /* If verbose output, print a summary of what changed */
4017 fprintf(STDOUT,"-- status after --\n");
4018 code = VLDB_GetEntryByName(avolname, &vldbentry);
4019 if (code && (code != VL_NOENT)) {
4020 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4023 if (modified && (code == VL_NOENT)) {
4024 fprintf(STDOUT,"\n**entry deleted**\n");
4025 } else if (modified) {
4026 EnumerateEntry(&vldbentry);
4028 fprintf(STDOUT,"\n**no change**\n");
4030 fprintf(STDOUT,"\n_______________________________\n");
4034 /* Now check if the maxvolid is larger than that stored in the VLDB */
4036 afs_int32 maxvldbid = 0;
4037 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4039 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4040 if (!error) error = code;
4041 } else if (maxvolid > maxvldbid) {
4043 id = maxvolid - maxvldbid + 1;
4044 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4046 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4047 if (!error) error = code;
4054 if (error) fprintf(STDOUT,"...error encountered");
4055 else fprintf(STDOUT,"...done entry\n");
4057 if (aconn) rx_DestroyConnection(aconn);
4058 if (volumeInfo.volEntries_val) free(volumeInfo.volEntries_val);
4060 PrintError("",error);
4065 * Synchronise vldb with the file server <aserver> and,
4066 * optionally, <apart>.
4068 int UV_SyncVldb(afs_int32 aserver, afs_int32 apart, int flags, int force)
4070 struct rx_connection *aconn;
4071 afs_int32 code, error=0;
4073 volEntries volumeInfo;
4074 struct partList PartList;
4078 afs_int32 failures = 0, modifications = 0, tentries = 0;
4080 afs_uint32 maxvolid = 0;
4082 volumeInfo.volEntries_val = (volintInfo *)0;
4083 volumeInfo.volEntries_len = 0;
4085 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4087 /* Generate array of partitions to check */
4089 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4091 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4095 PartList.partId[0] = apart;
4100 fprintf(STDOUT,"Processing volume entries ...\n");
4104 /* Step through the array of partitions */
4105 for (i = 0; i < pcnt; i++) {
4106 apart = PartList.partId[i];
4107 MapPartIdIntoName(apart, pname);
4109 volumeInfo.volEntries_val = (volintInfo *)0;
4110 volumeInfo.volEntries_len = 0;
4111 code = AFSVolListVolumes(aconn, apart, 1, &volumeInfo);
4113 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
4117 /* May want to sort the entries: RW, BK (high to low), RO (high to low) */
4118 qsort((char *)volumeInfo.volEntries_val, volumeInfo.volEntries_len,
4119 sizeof(volintInfo), sortVolumes);
4122 for (vi=volumeInfo.volEntries_val, j=0; j < volumeInfo.volEntries_len; j++, vi++) {
4129 fprintf(STDOUT,"Processing volume entry %d: %s (%u) on server %s %s...\n",
4130 j+1, vi->name, vi->volid,
4131 hostutil_GetNameByINet(aserver), pname);
4135 code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
4137 PrintError("",code);
4141 else if (modified) {
4147 fprintf(STDOUT,"...error encountered\n\n");
4149 fprintf(STDOUT,"...done entry %d\n\n", j+1);
4155 fprintf(STDERR,"Could not process entries on server %s partition %s\n",
4156 hostutil_GetNameByINet(aserver), pname);
4158 if (volumeInfo.volEntries_val) {
4159 free(volumeInfo.volEntries_val);
4160 volumeInfo.volEntries_val = 0;
4163 }/* thru all partitions */
4166 fprintf(STDOUT, "Total entries: %u, Failed to process %d, Changed %d\n",
4167 tentries, failures, modifications);
4171 /* Now check if the maxvolid is larger than that stored in the VLDB */
4173 afs_uint32 maxvldbid = 0;
4174 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4176 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4177 if (!error) error = code;
4178 } else if (maxvolid > maxvldbid) {
4180 id = maxvolid - maxvldbid + 1;
4181 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4183 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4184 if (!error) error = code;
4189 if (aconn) rx_DestroyConnection(aconn);
4190 if (volumeInfo.volEntries_val)
4191 free(volumeInfo.volEntries_val);
4192 PrintError("",error);
4197 * Determine if a volume exists on a server and partition.
4198 * Try creating a transaction on the volume. If we can,
4199 * the volume exists, if not, then return the error code.
4200 * Some error codes mean the volume is unavailable but
4201 * still exists - so we catch these error codes.
4203 afs_int32 VolumeExists(afs_int32 server, afs_int32 partition, afs_int32 volumeid)
4205 struct rx_connection *conn=(struct rx_connection *)0;
4206 afs_int32 code = -1;
4207 volEntries volumeInfo;
4209 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4211 volumeInfo.volEntries_val = (volintInfo *)0;
4212 volumeInfo.volEntries_len = 0;
4213 code = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
4214 if (volumeInfo.volEntries_val)
4215 free(volumeInfo.volEntries_val);
4216 if (code == VOLSERILLEGAL_PARTITION)
4218 rx_DestroyConnection(conn);
4226 afs_int32 CheckVldbRWBK(struct nvldbentry *entry, afs_int32 *modified)
4230 afs_int32 code, error = 0;
4233 if (modified) *modified = 0;
4234 idx = Lp_GetRwIndex(entry);
4236 /* Check to see if the RW volume exists and set the RW_EXISTS
4239 if (idx == -1) { /* Did not find a RW entry */
4240 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4241 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4245 code = VolumeExists(entry->serverNumber[idx],
4246 entry->serverPartition[idx],
4247 entry->volumeId[RWVOL]);
4248 if (code == 0) { /* RW volume exists */
4249 if (!(entry->flags & RW_EXISTS)) { /* ... yet entry says RW does not exist */
4250 entry->flags |= RW_EXISTS; /* ... so say RW does exist */
4254 else if (code == ENODEV) { /* RW volume does not exist */
4255 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4256 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4261 /* If VLDB says it didn't exist, then ignore error */
4262 if (entry->flags & RW_EXISTS) {
4263 MapPartIdIntoName(entry->serverPartition[idx], pname);
4264 fprintf(STDERR,"Transaction call failed for RW volume %u on server %s %s\n",
4265 entry->volumeId[RWVOL],
4266 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4272 /* Check to see if the BK volume exists and set the BACK_EXISTS
4273 * flag accordingly. idx already ponts to the RW entry.
4275 if (idx == -1) { /* Did not find a RW entry */
4276 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
4277 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
4281 else { /* Found a RW entry */
4282 code = VolumeExists(entry->serverNumber[idx],
4283 entry->serverPartition[idx],
4284 entry->volumeId[BACKVOL]);
4285 if (code == 0) { /* BK volume exists */
4286 if (!(entry->flags & BACK_EXISTS)) { /* ... yet entry says BK does not exist */
4287 entry->flags |= BACK_EXISTS; /* ... so say BK does exist */
4291 else if (code == ENODEV) { /* BK volume does not exist */
4292 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
4293 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
4298 /* If VLDB says it didn't exist, then ignore error */
4299 if (entry->flags & BACK_EXISTS) {
4300 MapPartIdIntoName(entry->serverPartition[idx], pname);
4301 fprintf(STDERR,"Transaction call failed for BK volume %u on server %s %s\n",
4302 entry->volumeId[BACKVOL],
4303 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4309 /* If there is an idx but the BK and RW volumes no
4310 * longer exist, then remove the RW entry.
4312 if ((idx != -1) && !(entry->flags & RW_EXISTS) &&
4313 !(entry->flags & BACK_EXISTS)) {
4314 Lp_SetRWValue(entry, entry->serverNumber[idx],
4315 entry->serverPartition[idx], 0L, 0L);
4321 if (modified) *modified = modentry;
4325 int CheckVldbRO(struct nvldbentry *entry, afs_int32 *modified)
4328 int foundro = 0, modentry = 0;
4329 afs_int32 code, error = 0;
4332 if (modified) *modified = 0;
4334 /* Check to see if the RO volumes exist and set the RO_EXISTS
4337 for (idx=0; idx < entry->nServers; idx++) {
4338 if (!(entry->serverFlags[idx] & ITSROVOL)) {
4339 continue; /* not a RO */
4342 code = VolumeExists(entry->serverNumber[idx],
4343 entry->serverPartition[idx],
4344 entry->volumeId[ROVOL]);
4345 if (code == 0) { /* RO volume exists */
4348 else if (code == ENODEV) { /* RW volume does not exist */
4349 Lp_SetROValue(entry, entry->serverNumber[idx],
4350 entry->serverPartition[idx], 0L, 0L);
4356 MapPartIdIntoName(entry->serverPartition[idx], pname);
4357 fprintf(STDERR,"Transaction call failed for RO %u on server %s %s\n",
4358 entry->volumeId[ROVOL],
4359 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4364 if (foundro) { /* A RO volume exists */
4365 if (!(entry->flags & RO_EXISTS)) { /* ... yet entry says RW does not exist */
4366 entry->flags |= RO_EXISTS; /* ... so say RW does exist */
4369 } else { /* A RO volume does not exist */
4370 if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
4371 entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
4377 if (modified) *modified = modentry;
4382 * Ensure that <entry> matches with the info on file servers
4384 afs_int32 CheckVldb(struct nvldbentry *entry, afs_int32 *modified)
4386 afs_int32 code, error=0;
4387 struct nvldbentry storeEntry;
4388 int islocked=0, mod, modentry, delentry=0;
4391 if (modified) *modified = 0;
4393 fprintf(STDOUT,"_______________________________\n");
4394 fprintf(STDOUT,"\n-- status before -- \n");
4395 if ((entry->flags & RW_EXISTS) ||
4396 (entry->flags & RO_EXISTS) ||
4397 (entry->flags & BACK_EXISTS))
4398 EnumerateEntry(entry);
4399 fprintf(STDOUT,"\n");
4402 if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
4403 fprintf(STDERR,"Volume name %s exceeds limit of %d characters\n",
4404 entry->name, VOLSER_OLDMAXVOLNAME-10);
4408 /* Check to see if the VLDB is ok without locking it (pass 1).
4409 * If it will change, then lock the VLDB entry, read it again,
4410 * then make the changes to it (pass 2).
4413 code = ubik_Call(VL_SetLock,cstruct, 0, entry->volumeId[RWVOL], RWVOL, VLOP_DELETE);
4415 fprintf(STDERR, "Could not lock VLDB entry for %u \n",entry->volumeId[RWVOL] );
4420 code = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, entry);
4422 fprintf(STDERR,"Could not read VLDB entry for volume %s\n", entry->name);
4426 MapHostToNetwork(entry);
4432 /* Check if the RW and BK entries are ok */
4433 code = CheckVldbRWBK(entry, &mod);
4434 if (code) ERROR_EXIT(code);
4435 if (mod && (pass == 1)) goto retry;
4436 if (mod) modentry++;
4438 /* Check if the RO volumes entries are ok */
4439 code = CheckVldbRO(entry, &mod);
4440 if (code) ERROR_EXIT(code);
4441 if (mod && (pass == 1)) goto retry;
4442 if (mod) modentry++;
4444 /* The VLDB entry has been updated. If it as been modified, then
4445 * write the entry back out the the VLDB.
4448 if (pass == 1) goto retry;
4450 if (!(entry->flags & RW_EXISTS) &&
4451 !(entry->flags & BACK_EXISTS) &&
4452 !(entry->flags & RO_EXISTS)) {
4453 /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
4454 code = ubik_Call(VL_DeleteEntry, cstruct, 0, entry->volumeId[RWVOL], RWVOL);
4456 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",
4457 entry->volumeId[RWVOL]);
4463 /* Replace old entry with our new one */
4464 MapNetworkToHost(entry,&storeEntry);
4465 code = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry,
4466 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
4468 fprintf(STDERR,"Could not update VLDB entry for volume %u\n",
4469 entry->volumeId[RWVOL] );
4473 if (modified) *modified = 1;
4478 fprintf(STDOUT,"-- status after --\n");
4480 fprintf(STDOUT,"\n**entry deleted**\n");
4482 EnumerateEntry(entry);
4484 fprintf(STDOUT,"\n**no change**\n");
4489 fprintf(STDOUT,"\n_______________________________\n");
4493 code = ubik_Call(VL_ReleaseLock, cstruct, 0, entry->volumeId[RWVOL], RWVOL,
4494 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
4496 fprintf(STDERR,"Could not release lock on VLDB entry for volume %u\n",
4497 entry->volumeId[RWVOL]);
4498 if (!error) error = code;
4505 * Synchronise <aserver> <apart>(if flags = 1) with the VLDB.
4507 int UV_SyncServer(afs_int32 aserver, afs_int32 apart, int flags, int force)
4509 struct rx_connection *aconn;
4510 afs_int32 code, error = 0;
4511 afs_int32 nentries, tentries=0;
4512 struct VldbListByAttributes attributes;
4513 nbulkentries arrayEntries;
4514 afs_int32 failures=0, modified, modifications=0;
4515 struct nvldbentry *vlentry;
4516 afs_int32 si, nsi, j;
4518 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4520 /* Set up attributes to search VLDB */
4521 attributes.server = ntohl(aserver);
4522 attributes.Mask = VLLIST_SERVER;
4524 attributes.partition = apart;
4525 attributes.Mask |= VLLIST_PARTITION;
4529 fprintf(STDOUT,"Processing VLDB entries ...\n");
4533 /* While we need to collect more VLDB entries */
4534 for (si=0; si != -1; si=nsi) {
4535 memset(&arrayEntries, 0, sizeof(arrayEntries));
4537 /* Collect set of VLDB entries */
4538 code = VLDB_ListAttributesN2(&attributes, 0, si,
4539 &nentries, &arrayEntries, &nsi);
4540 if (code == RXGEN_OPCODE) {
4541 code = VLDB_ListAttributes(&attributes, &nentries, &arrayEntries);
4545 fprintf(STDERR,"Could not access the VLDB for attributes\n");
4548 tentries += nentries;
4550 for (j=0; j<nentries; j++) {
4551 vlentry = &arrayEntries.nbulkentries_val[j];
4552 MapHostToNetwork(vlentry);
4555 fprintf(STDOUT,"Processing VLDB entry %d ...\n", j+1);
4559 code = CheckVldb(vlentry, &modified);
4561 PrintError("",code);
4562 fprintf(STDERR,"Could not process VLDB entry for volume %s\n",
4565 } else if (modified) {
4571 fprintf(STDOUT,"...error encountered\n\n");
4573 fprintf(STDOUT,"...done entry %d\n\n", j+1);
4578 if (arrayEntries.nbulkentries_val) {
4579 free(arrayEntries.nbulkentries_val);
4580 arrayEntries.nbulkentries_val = 0;
4585 fprintf(STDOUT,"Total entries: %u, Failed to process %d, Changed %d\n",
4586 tentries, failures, modifications);
4591 rx_DestroyConnection(aconn);
4592 if (arrayEntries.nbulkentries_val)
4593 free(arrayEntries.nbulkentries_val);
4596 error = VOLSERFAILEDOP;
4600 /*rename volume <oldname> to <newname>, changing the names of the related
4601 *readonly and backup volumes. This operation is also idempotent.
4602 *salvager is capable of recovering from rename operation stopping halfway.
4603 *to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
4604 int UV_RenameVolume(struct nvldbentry *entry, char oldname[], char newname[])
4606 struct nvldbentry storeEntry;
4607 afs_int32 vcode,code,rcode,error;
4609 char nameBuffer[256];
4611 struct rx_connection *aconn;
4615 aconn = (struct rx_connection *)0;
4619 vcode = ubik_Call(VL_SetLock,cstruct, 0,entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE);/*last param is dummy*/
4621 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n",entry->volumeId[RWVOL] );
4626 strncpy(entry->name,newname,VOLSER_OLDMAXVOLNAME);
4627 MapNetworkToHost(entry,&storeEntry);
4628 vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL],RWVOL, &storeEntry,0 );
4630 fprintf(STDERR,"Could not update VLDB entry for %u\n",entry->volumeId[RWVOL]);
4634 if(verbose) fprintf(STDOUT,"Recorded the new name %s in VLDB\n",newname);
4635 /*at this stage the intent to rename is recorded in the vldb, as far as the vldb
4636 is concerned, oldname is lost */
4637 if(entry->flags & RW_EXISTS) {
4638 index = Lp_GetRwIndex(entry);
4639 if(index == -1){ /* there is a serious discrepancy */
4640 fprintf(STDERR,"There is a serious discrepancy in VLDB entry for volume %u\n",entry->volumeId[RWVOL]);
4641 fprintf(STDERR,"try building VLDB from scratch\n");
4642 error = VOLSERVLDB_ERROR;
4645 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
4646 code = AFSVolTransCreate(aconn,entry->volumeId[RWVOL],entry->serverPartition[index], ITOffline, &tid);
4647 if(code) { /*volume doesnot exist */
4648 fprintf(STDERR,"Could not start transaction on the rw volume %u\n",entry->volumeId[RWVOL]);
4652 else {/*volume exists, process it */
4654 code = AFSVolSetIdsTypes(aconn, tid, newname,RWVOL, entry->volumeId[RWVOL],entry->volumeId[ROVOL],entry->volumeId[BACKVOL]);
4656 if(verbose) printf("Renamed rw volume %s to %s\n",oldname,newname);
4657 code = AFSVolEndTrans(aconn, tid, &rcode);
4660 fprintf(STDERR,"Could not end transaction on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
4666 fprintf(STDERR,"Could not set parameters on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
4671 if(aconn) rx_DestroyConnection(aconn);
4672 aconn = (struct rx_connection *)0;
4673 } /*end rw volume processing */
4675 if(entry->flags & BACK_EXISTS) {/*process the backup volume */
4676 index = Lp_GetRwIndex(entry);
4677 if(index == -1){ /* there is a serious discrepancy */
4678 fprintf(STDERR,"There is a serious discrepancy in the VLDB entry for the backup volume %u\n",entry->volumeId[BACKVOL]);
4679 fprintf(STDERR,"try building VLDB from scratch\n");
4680 error = VOLSERVLDB_ERROR;
4683 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
4684 code = AFSVolTransCreate(aconn,entry->volumeId[BACKVOL],entry->serverPartition[index], ITOffline, &tid);
4685 if(code) { /*volume doesnot exist */
4686 fprintf(STDERR,"Could not start transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
4690 else {/*volume exists, process it */
4691 if(strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)){
4692 fprintf(STDERR,"Volume name %s.backup exceeds the limit of %u characters\n",newname,VOLSER_OLDMAXVOLNAME);
4696 strcpy(nameBuffer,newname);
4697 strcat(nameBuffer,".backup");
4699 code = AFSVolSetIdsTypes(aconn, tid,nameBuffer ,BACKVOL, entry->volumeId[RWVOL],0,0);
4701 if(verbose) fprintf(STDOUT,"Renamed backup volume to %s \n",nameBuffer);
4702 code = AFSVolEndTrans(aconn, tid, &rcode);
4705 fprintf(STDERR,"Could not end transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
4711 fprintf(STDERR,"Could not set parameters on the backup volume %u\n",entry->volumeId[BACKVOL]);
4716 } /* end backup processing */
4717 if(aconn) rx_DestroyConnection(aconn);
4718 aconn = (struct rx_connection *)0;
4719 if(entry->flags & RO_EXISTS){ /*process the ro volumes */
4720 for(i = 0; i < entry->nServers; i++){
4721 if(entry->serverFlags[i] & ITSROVOL) {
4722 aconn = UV_Bind(entry->serverNumber[i],AFSCONF_VOLUMEPORT);
4723 code = AFSVolTransCreate(aconn,entry->volumeId[ROVOL],entry->serverPartition[i], ITOffline, &tid);
4724 if(code) { /*volume doesnot exist */
4725 fprintf(STDERR,"Could not start transaction on the ro volume %u\n",entry->volumeId[ROVOL]);
4729 else {/*volume exists, process it */
4730 strcpy(nameBuffer,newname);
4731 strcat(nameBuffer,".readonly");
4732 if(strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)){
4733 fprintf(STDERR,"Volume name %s exceeds the limit of %u characters\n",nameBuffer,VOLSER_OLDMAXVOLNAME);
4737 code = AFSVolSetIdsTypes(aconn, tid, nameBuffer,ROVOL, entry->volumeId[RWVOL],0,0);
4739 if(verbose) fprintf(STDOUT,"Renamed RO volume %s on host %s\n",
4741 hostutil_GetNameByINet(entry->serverNumber[i]));
4742 code = AFSVolEndTrans(aconn, tid, &rcode);
4745 fprintf(STDERR,"Could not end transaction on volume %u\n",entry->volumeId[ROVOL]);
4751 fprintf(STDERR,"Could not set parameters on the ro volume %u\n",entry->volumeId[ROVOL]);
4756 if(aconn) rx_DestroyConnection(aconn);
4757 aconn = (struct rx_connection *)0;
4763 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,entry->volumeId[RWVOL] , RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4765 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
4766 if(!error) error = vcode;
4770 code = AFSVolEndTrans(aconn, tid, &rcode);
4771 if(!code) code = rcode;
4773 fprintf(STDERR,"Failed to end transaction on a volume \n");
4774 if(!error) error = code;
4777 if(aconn) rx_DestroyConnection(aconn);
4778 PrintError("",error);
4783 /*report on all the active transactions on volser */
4784 int UV_VolserStatus(afs_int32 server, transDebugInfo **rpntr, afs_int32 *rcount)
4786 struct rx_connection *aconn;
4787 transDebugEntries transInfo;
4790 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4791 transInfo.transDebugEntries_val = (transDebugInfo *) 0;
4792 transInfo.transDebugEntries_len = 0;
4793 code = AFSVolMonitor(aconn,&transInfo);
4795 fprintf(STDERR,"Could not access status information about the server\n");
4796 PrintError("",code);
4797 if (transInfo.transDebugEntries_val) free(transInfo.transDebugEntries_val);
4798 if(aconn) rx_DestroyConnection(aconn);
4802 *rcount = transInfo.transDebugEntries_len;
4803 *rpntr = transInfo.transDebugEntries_val;
4804 if(aconn) rx_DestroyConnection(aconn);
4811 /*delete the volume without interacting with the vldb */
4812 int UV_VolumeZap(afs_int32 server, afs_int32 part, afs_int32 volid)
4814 afs_int32 rcode,ttid,error,code;
4815 struct rx_connection *aconn;
4821 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4822 code = AFSVolTransCreate(aconn, volid, part, ITOffline, &ttid);
4824 fprintf(STDERR,"Could not start transaction on volume %u\n",volid);
4828 code = AFSVolDeleteVolume(aconn, ttid);
4830 fprintf(STDERR,"Could not delete volume %u\n",volid);
4834 code = AFSVolEndTrans(aconn, ttid, &rcode);
4836 if(!code) code = rcode;
4838 fprintf(STDERR,"Could not end transaction on volume %u\n",volid);
4844 code = AFSVolEndTrans(aconn,ttid,&rcode);
4845 if(!code) code = rcode;
4846 if(!error) error = code;
4848 PrintError("",error);
4849 if(aconn) rx_DestroyConnection(aconn);
4853 int UV_SetVolume(afs_int32 server, afs_int32 partition, afs_int32 volid, afs_int32 transflag, afs_int32 setflag, int sleeptime)
4855 struct rx_connection *conn = 0;
4857 afs_int32 code, error=0, rcode;
4859 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4861 fprintf(STDERR, "SetVolumeStatus: Bind Failed");
4865 code = AFSVolTransCreate(conn, volid, partition, transflag, &tid);
4867 fprintf(STDERR, "SetVolumeStatus: TransCreate Failed\n");
4871 code = AFSVolSetFlags(conn, tid, setflag);
4873 fprintf(STDERR, "SetVolumeStatus: SetFlags Failed\n");
4878 #ifdef AFS_PTHREAD_ENV
4881 IOMGR_Sleep(sleeptime);
4888 code = AFSVolEndTrans(conn, tid, &rcode);
4889 if (code || rcode) {
4890 fprintf(STDERR, "SetVolumeStatus: EndTrans Failed\n");
4891 if (!error) error = (code ? code : rcode);
4895 if (conn) rx_DestroyConnection(conn);
4899 int UV_SetVolumeInfo(afs_int32 server, afs_int32 partition, afs_int32 volid, volintInfo *infop)
4901 struct rx_connection *conn = 0;
4903 afs_int32 code, error=0, rcode;
4905 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4907 fprintf(STDERR, "SetVolumeInfo: Bind Failed");
4911 code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
4913 fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
4917 code = AFSVolSetInfo(conn, tid, infop);
4919 fprintf(STDERR, "SetVolumeInfo: SetInfo Failed\n");
4926 code = AFSVolEndTrans(conn, tid, &rcode);
4927 if (code || rcode) {
4928 fprintf(STDERR, "SetVolumeInfo: EndTrans Failed\n");
4929 if (!error) error = (code ? code : rcode);
4933 if (conn) rx_DestroyConnection(conn);
4937 /*maps the host addresses in <old > (present in network byte order) to
4938 that in< new> (present in host byte order )*/
4939 void MapNetworkToHost(struct nvldbentry *old, struct nvldbentry *new)
4943 /*copy all the fields */
4944 strcpy(new->name,old->name);
4945 /* new->volumeType = old->volumeType;*/
4946 new->nServers = old->nServers;
4947 count = old->nServers;
4948 if(count < NMAXNSERVERS) count++;
4949 for(i = 0; i < count; i++) {
4950 new->serverNumber[i] = ntohl(old->serverNumber[i]);
4951 new->serverPartition[i] = old->serverPartition[i];
4952 new->serverFlags[i] = old->serverFlags[i];
4954 new->volumeId[RWVOL]= old->volumeId[RWVOL];
4955 new->volumeId[ROVOL] = old->volumeId[ROVOL];
4956 new->volumeId[BACKVOL] = old->volumeId[BACKVOL];
4957 new->cloneId = old->cloneId;
4958 new->flags = old->flags;
4961 /*maps the host entries in <entry> which are present in host byte order to network byte order */
4962 void MapHostToNetwork(struct nvldbentry *entry)
4966 count = entry->nServers;
4967 if(count < NMAXNSERVERS) count++;
4968 for(i = 0; i < count; i++) {
4969 entry->serverNumber[i] = htonl(entry->serverNumber[i]);