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 #include <volser_prototypes.h>
66 afs_int32 VolumeExists(), CheckVldbRWBK(), CheckVldb();
68 struct ubik_client *cstruct;
70 extern int VL_GetNewVolumeId();
71 extern int VL_SetLock();
72 extern int VL_ReleaseLock();
73 extern int VL_DeleteEntry();
75 void MapNetworkToHost();
76 void MapHostToNetwork();
80 afs_int32 vldbEntryIndex;
83 /* Utility macros used by rest of this source file */
84 #define EPRINT(ec, es) \
85 fprintf(STDERR, "\n"); \
86 fprintf(STDERR, (es)); \
89 #define EPRINT1(ec, es, ep1) \
90 fprintf(STDERR, "\n"); \
91 fprintf(STDERR, (es), (ep1)); \
94 #define EPRINT2(ec, es, ep1, ep2) \
95 fprintf(STDERR, "\n"); \
96 fprintf(STDERR, (es), (ep1), (ep2)); \
99 #define EPRINT3(ec, es, ep1, ep2, ep3) \
100 fprintf(STDERR, "\n"); \
101 fprintf(STDERR, (es), (ep1), (ep2), (ep3)); \
104 #define EGOTO(where, ec, es) \
111 #define EGOTO1(where, ec, es, ep1) \
113 EPRINT1((ec),(es),(ep1)); \
118 #define EGOTO2(where, ec, es, ep1, ep2) \
120 EPRINT2((ec),(es),(ep1),(ep2)); \
125 #define EGOTO3(where, ec, es, ep1, ep2, ep3) \
127 EPRINT3((ec),(es),(ep1),(ep2),(ep3)); \
133 { if (verbose) { fprintf(STDOUT, (es)); fflush(STDOUT); } }
134 #define VPRINT1(es, p) \
135 { if (verbose) { fprintf(STDOUT, (es), (p)); fflush(STDOUT); } }
136 #define VPRINT2(es, p1, p2) \
137 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2)); fflush(STDOUT); } }
138 #define VPRINT3(es, p1, p2, p3) \
139 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
141 { if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
145 /* getting rid of this */
146 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
149 /* Protos for static routines */
150 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
151 afs_int32 apart, afs_int32 okvol, afs_int32 delvol);
152 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags);
153 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr,
154 afs_int32 *transPtr, afs_int32 *timePtr);
155 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
156 afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results);
157 static int rel_compar (struct release *r1, struct release *r2);
158 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart,
159 afs_int32 *modentry, afs_uint32 *maxvolid);
162 /*map the partition <partId> into partition name <partName>*/
163 void MapPartIdIntoName(afs_int32 partId, char *partName)
165 if(partId < 26) {/* what if partId > = 26 ? */
166 strcpy(partName,"/vicep");
167 partName[6] = partId + 'a';
170 } else if (partId < VOLMAXPARTS) {
171 strcpy(partName,"/vicep");
173 partName[6] = 'a' + (partId/26);
174 partName[7] = 'a' + (partId%26);
180 int yesprompt(char *str)
185 fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
186 response = c = getchar();
187 while (!(c==EOF || c=='\n')) c=getchar(); /*skip to end of line*/
188 code = (response=='y'||response=='Y');
193 int PrintError(char *msg, afs_int32 errcode)
196 /*replace by a big switch statement*/
200 case -1 : fprintf(STDERR,"Possible communication failure\n");
202 case VSALVAGE: fprintf(STDERR,"Volume needs to be salvaged\n");
204 case VNOVNODE: fprintf(STDERR,"Bad vnode number quoted\n");
206 case VNOVOL: fprintf(STDERR,"Volume not attached, does not exist, or not on line\n");
208 case VVOLEXISTS:fprintf(STDERR,"Volume already exists\n");
210 case VNOSERVICE:fprintf(STDERR,"Volume is not in service\n");
212 case VOFFLINE: fprintf(STDERR,"Volume is off line\n");
214 case VONLINE: fprintf(STDERR,"Volume is already on line\n");
216 case VDISKFULL: fprintf(STDERR,"Partition is full\n");
218 case VOVERQUOTA:fprintf(STDERR,"Volume max quota exceeded\n");
220 case VBUSY: fprintf(STDERR,"Volume temporarily unavailable\n");
222 case VMOVED:fprintf(STDERR,"Volume has moved to another server\n");
224 case VL_IDEXIST : fprintf(STDERR,"VLDB: volume Id exists in the vldb\n");
226 case VL_IO: fprintf(STDERR,"VLDB: a read terminated too early\n");
228 case VL_NAMEEXIST: fprintf(STDERR,"VLDB: volume entry exists in the vldb\n");
230 case VL_CREATEFAIL: fprintf(STDERR,"VLDB: internal creation failure\n");
232 case VL_NOENT: fprintf(STDERR,"VLDB: no such entry\n");
234 case VL_EMPTY: fprintf(STDERR,"VLDB: vldb database is empty\n");
236 case VL_ENTDELETED: fprintf(STDERR,"VLDB: entry is deleted (soft delete)\n");
238 case VL_BADNAME: fprintf(STDERR,"VLDB: volume name is illegal\n");
240 case VL_BADINDEX: fprintf(STDERR,"VLDB: index was out of range\n");
242 case VL_BADVOLTYPE: fprintf(STDERR,"VLDB: bad volume type\n");
244 case VL_BADSERVER: fprintf(STDERR,"VLDB: illegal server number (not within limits)\n");
246 case VL_BADPARTITION: fprintf(STDERR,"VLDB: bad partition number\n");
248 case VL_REPSFULL: fprintf(STDERR,"VLDB: run out of space for replication sites\n");
250 case VL_NOREPSERVER: fprintf(STDERR,"VLDB: no such repsite server exists\n");
252 case VL_DUPREPSERVER: fprintf(STDERR,"VLDB: replication site server already exists\n");
254 case VL_RWNOTFOUND: fprintf(STDERR,"VLDB: parent r/w entry not found\n");
256 case VL_BADREFCOUNT: fprintf(STDERR,"VLDB: illegal reference count number\n");
258 case VL_SIZEEXCEEDED: fprintf(STDERR,"VLDB: vldb size for attributes exceeded\n");
260 case VL_BADENTRY: fprintf(STDERR,"VLDB: bad incoming vldb entry\n");
262 case VL_BADVOLIDBUMP: fprintf(STDERR,"VLDB: illegal max volid increment\n");
264 case VL_IDALREADYHASHED: fprintf(STDERR,"VLDB: (RO/BACK) Id already hashed\n");
266 case VL_ENTRYLOCKED: fprintf(STDERR,"VLDB: vldb entry is already locked\n");
268 case VL_BADVOLOPER: fprintf(STDERR,"VLDB: bad volume operation code\n");
270 case VL_BADRELLOCKTYPE: fprintf(STDERR,"VLDB: bad release lock type\n");
272 case VL_RERELEASE: fprintf(STDERR,"VLDB: status report: last release was aborted\n");
274 case VL_BADSERVERFLAG: fprintf(STDERR,"VLDB: invalid replication site server flag\n");
276 case VL_PERM: fprintf(STDERR,"VLDB: no permission access for call\n");
278 case VOLSERREAD_DUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in reading the dump file !\n");
280 case VOLSERDUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in doing the dump !\n");
282 case VOLSERATTACH_ERROR: fprintf(STDERR,"VOLSER: Could not attach the volume\n");
284 case VOLSERDETACH_ERROR: fprintf(STDERR,"VOLSER: Could not detach the volume\n");
286 case VOLSERILLEGAL_PARTITION: fprintf(STDERR,"VOLSER: encountered illegal partition number\n");
288 case VOLSERBAD_ACCESS: fprintf(STDERR,"VOLSER: permission denied, not a super user\n");
290 case VOLSERVLDB_ERROR: fprintf(STDERR,"VOLSER: error detected in the VLDB\n");
292 case VOLSERBADNAME: fprintf(STDERR,"VOLSER: error in volume name\n");
294 case VOLSERVOLMOVED: fprintf(STDERR,"VOLSER: volume has moved\n");
296 case VOLSERBADOP: fprintf(STDERR,"VOLSER: illegal operation\n");
298 case VOLSERBADRELEASE: fprintf(STDERR,"VOLSER: release could not be completed\n");
300 case VOLSERVOLBUSY: fprintf(STDERR,"VOLSER: volume is busy\n");
302 case VOLSERNO_MEMORY: fprintf(STDERR,"VOLSER: volume server is out of memory\n");
304 case VOLSERNOVOL:fprintf(STDERR,"VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
306 case VOLSERMULTIRWVOL: fprintf(STDERR,"VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
308 case VOLSERFAILEDOP: fprintf(STDERR,"VOLSER: not all entries were successfully processed\n");
315 initialize_KA_error_table();
316 initialize_RXK_error_table();
317 initialize_KTC_error_table();
318 initialize_ACFG_error_table();
319 initialize_CMD_error_table();
320 initialize_VL_error_table();
322 offset = errcode & ((1<<ERRCODE_RANGE)-1);
323 fprintf(STDERR,"%s: %s\n",error_table_name (errcode), error_message (errcode));
331 static struct rx_securityClass *uvclass=0;
332 static int uvindex = -1;
333 /* called by VLDBClient_Init to set the security module to be used in the RPC */
334 int UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
340 /* bind to volser on <port> <aserver> */
341 /* takes server address in network order, port in host order. dumb */
342 struct rx_connection *UV_Bind(afs_int32 aserver, afs_int32 port)
344 register struct rx_connection *tc;
346 tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass, uvindex);
350 /* if <okvol> is allright(indicated by beibg able to
351 * start a transaction, delete the <delvol> */
352 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
353 afs_int32 apart, afs_int32 okvol, afs_int32 delvol)
355 afs_int32 error,code,tid,rcode;
361 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
362 if(!error && code) error = code;
363 code = AFSVolDeleteVolume(aconn,tid);
364 if(!error && code) error = code;
365 code = AFSVolEndTrans(aconn,tid, &rcode);
366 if(!code) code = rcode;
367 if(!error && code) error = code;
371 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline,&tid);
373 code = AFSVolEndTrans(aconn,tid, &rcode);
374 if(!code) code = rcode;
375 if(!error && code) error = code;
376 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
377 if(!error && code) error = code;
378 code = AFSVolDeleteVolume(aconn,tid);
379 if(!error && code) error = code;
380 code = AFSVolEndTrans(aconn,tid, &rcode);
381 if(!code) code = rcode;
382 if(!error && code) error = code;
390 /* called by EmuerateEntry, show vldb entry in a reasonable format */
391 void SubEnumerateEntry(struct nvldbentry *entry)
398 fprintf(STDOUT," readWriteID %-10u ",entry->volumeId[RWVOL]);
399 if(entry->flags & RW_EXISTS) fprintf(STDOUT," valid \n");else fprintf(STDOUT," invalid \n");
400 fprintf(STDOUT," readOnlyID %-10u ",entry->volumeId[ROVOL]);
401 if(entry->flags & RO_EXISTS) fprintf(STDOUT," valid \n") ;else fprintf(STDOUT," invalid \n");
402 fprintf(STDOUT," backUpID %-10u ",entry->volumeId[BACKVOL]);
403 if(entry->flags & BACK_EXISTS) fprintf(STDOUT," valid \n"); else fprintf(STDOUT," invalid \n");
404 if((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
405 fprintf(STDOUT," releaseClone %-10u \n",entry->cloneId);
407 if (entry->flags & RW_EXISTS)
408 fprintf(STDOUT," RWrite: %-10u",entry->volumeId[RWVOL]);
409 if (entry->flags & RO_EXISTS)
410 fprintf(STDOUT," ROnly: %-10u",entry->volumeId[ROVOL]);
411 if (entry->flags & BACK_EXISTS)
412 fprintf(STDOUT," Backup: %-10u",entry->volumeId[BACKVOL]);
413 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
414 fprintf(STDOUT," RClone: %-10u",entry->cloneId);
415 fprintf(STDOUT,"\n");
417 fprintf(STDOUT," number of sites -> %u\n",entry->nServers);
418 for(i = 0; i < entry->nServers; i++) {
419 if(entry->serverFlags[i] & NEW_REPSITE)
422 for(i = 0; i < entry->nServers; i++) {
423 MapPartIdIntoName(entry->serverPartition[i],pname);
424 fprintf(STDOUT," server %s partition %s ",
425 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
426 if(entry->serverFlags[i] & ITSRWVOL) fprintf(STDOUT,"RW Site ") ; else fprintf(STDOUT,"RO Site ");
428 if (entry->serverFlags[i] & NEW_REPSITE)
429 fprintf(STDOUT," -- New release");
431 fprintf(STDOUT," -- Old release");
433 if (entry->serverFlags[i] & RO_DONTUSE)
434 fprintf(STDOUT," -- Not released");
436 fprintf(STDOUT,"\n");
443 /*enumerate the vldb entry corresponding to <entry> */
444 void EnumerateEntry(struct nvldbentry *entry)
447 fprintf(STDOUT,"\n");
448 fprintf(STDOUT,"%s \n",entry->name);
449 SubEnumerateEntry(entry);
453 /* forcibly remove a volume. Very dangerous call */
454 int UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
456 register struct rx_connection *tconn;
457 register afs_int32 code;
459 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
461 code = AFSVolNukeVolume(tconn, partid, volid);
462 rx_DestroyConnection(tconn);
468 /* like df. Return usage of <pname> on <server> in <partition> */
469 int UV_PartitionInfo(afs_int32 server, char *pname, struct diskPartition *partition)
471 register struct rx_connection *aconn;
475 aconn = (struct rx_connection *)0;
476 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
477 code = AFSVolPartitionInfo(aconn,pname,partition);
479 fprintf(STDERR,"Could not get information on partition %s\n",pname);
482 if(aconn) rx_DestroyConnection(aconn);
486 /* old interface to create volume */
487 int UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 *anewid)
490 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
494 /* create a volume, given a server, partition number, volume name --> sends
495 * back new vol id in <anewid>*/
496 int UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aquota,
497 afs_int32 aspare1, afs_int32 aspare2, afs_int32 aspare3, afs_int32 aspare4, afs_int32 *anewid)
500 register struct rx_connection *aconn;
502 register afs_int32 code;
504 afs_int32 rcode,vcode;
505 struct nvldbentry entry,storeEntry;/*the new vldb entry */
506 struct volintInfo tstatus;
509 aconn = (struct rx_connection *)0;
511 memset(&tstatus, 0, sizeof(struct volintInfo));
513 tstatus.maxquota = aquota;
515 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
516 /* next the next 3 available ids from the VLDB */
517 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 3, anewid);
518 EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n",aname);
520 code = AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
521 EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n",aname,*anewid);
523 code = AFSVolSetInfo(aconn, tid, &tstatus);
524 EPRINT1(code, "Could not change quota (error %d), continuing...\n", code);
526 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
527 EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n",aname,*anewid);
529 VPRINT2("Volume %s %u created and brought online\n",aname,*anewid);
531 /* set up the vldb entry for this volume */
532 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
534 entry.serverNumber[0] = aserver; /* this should have another
535 level of indirection later */
536 entry.serverPartition[0] = apart; /* this should also have
537 another indirection level */
538 entry.flags = RW_EXISTS;/* this records that rw volume exists */
539 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
540 entry.volumeId[RWVOL] = *anewid;
541 entry.volumeId[ROVOL] = *anewid + 1;/* rw,ro, bk id are related in the default case */
542 entry.volumeId[BACKVOL] = *anewid + 2;
544 /*map into right byte order, before passing to xdr, the stuff has to be in host
545 byte order. Xdr converts it into network order */
546 MapNetworkToHost(&entry,&storeEntry);
547 /* create the vldb entry */
548 vcode = VLDB_CreateEntry(&storeEntry);
550 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,*anewid);
551 /*destroy the created volume*/
552 VPRINT1("Deleting the newly created volume %u\n",*anewid);
553 AFSVolDeleteVolume(aconn,tid);
557 VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,*anewid);
558 /* volume created, now terminate the transaction and release the connection*/
559 code = AFSVolEndTrans(aconn, tid, &rcode);/*if it crashes before this
560 the volume will come online anyway when transaction timesout , so if
561 vldb entry exists then the volume is guaranteed to exist too wrt create*/
564 fprintf(STDERR,"Failed to end the transaction on the volume %s %u\n",aname,*anewid);
572 code= AFSVolEndTrans(aconn, tid, &rcode);
574 fprintf(STDERR,"WARNING: could not end transaction\n");
576 if(aconn) rx_DestroyConnection(aconn);
577 PrintError("",error);
582 /* create a volume, given a server, partition number, volume name --> sends
583 * back new vol id in <anewid>*/
584 int UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aid)
586 register struct rx_connection *aconn;
589 struct nvldbentry entry,storeEntry;/*the new vldb entry */
591 aconn = (struct rx_connection *)0;
594 /* set up the vldb entry for this volume */
595 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
597 entry.serverNumber[0] = aserver; /* this should have another
598 level of indirection later */
599 entry.serverPartition[0] = apart; /* this should also have
600 another indirection level */
601 entry.flags = RW_EXISTS;/* this records that rw volume exists */
602 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
603 entry.volumeId[RWVOL] = aid;
605 entry.volumeId[ROVOL] = anewid + 1;/* rw,ro, bk id are related in the default case */
606 entry.volumeId[BACKVOL] = *anewid + 2;
608 entry.volumeId[ROVOL] = 0;
609 entry.volumeId[BACKVOL] = 0;
612 /*map into right byte order, before passing to xdr, the stuff has to be in host
613 byte order. Xdr converts it into network order */
614 MapNetworkToHost(&entry,&storeEntry);
615 /* create the vldb entry */
616 vcode = VLDB_CreateEntry(&storeEntry);
618 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,aid);
622 VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,aid);
625 if(aconn) rx_DestroyConnection(aconn);
626 PrintError("",error);
630 /* Delete the volume <volid>on <aserver> <apart>
631 * the physical entry gets removed from the vldb only if the ref count
634 int UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
636 struct rx_connection *aconn = (struct rx_connection *)0;
638 afs_int32 code, rcode;
640 struct nvldbentry entry,storeEntry;
642 afs_int32 avoltype = -1, vtype;
643 int notondisk = 0, notinvldb = 0;
645 /* Find and read bhe VLDB entry for this volume */
646 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
648 if (code != VL_NOENT) {
649 EGOTO1(error_exit, code, "Could not lock VLDB entry for the volume %u\n", avolid);
655 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
656 EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",avolid);
657 MapHostToNetwork(&entry);
660 EnumerateEntry(&entry);
663 /* Whether volume is in the VLDB or not. Delete the volume on disk */
664 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
665 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
667 if (code == VNOVOL) {
670 EGOTO1(error_exit, code, "Transaction on volume %u failed\n", avolid);
674 VPRINT1("Trying to delete the volume %u ...", avolid);
676 code = AFSVolDeleteVolume(aconn, ttid);
677 EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
679 code = AFSVolEndTrans(aconn, ttid, &rcode);
680 code = (code ? code : rcode);
682 EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",avolid);
686 /* Now update the VLDB entry.
687 * But first, verify we have a VLDB entry.
688 * Whether volume is on disk or not. Delete the volume in VLDB.
693 if (avolid == entry.volumeId[BACKVOL]) {
694 /* Its a backup volume, modify the VLDB entry. Check that the
695 * backup volume is on the server/partition we asked to delete.
697 if ( !(entry.flags & BACK_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
698 notinvldb = 2; /* Not on this server and partition */
702 VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
704 entry.flags &= ~BACK_EXISTS;
708 else if (avolid == entry.volumeId[ROVOL]) {
709 /* Its a read-only volume, modify the VLDB entry. Check that the
710 * readonly volume is on the server/partition we asked to delete.
711 * If flags does not have RO_EIXSTS set, then this may mean the RO
712 * hasn't been released (and could exist in VLDB).
714 if (!Lp_ROMatch(aserver,apart,&entry)) {
715 notinvldb = 2; /* Not found on this server and partition */
720 fprintf(STDOUT,"Marking the readonly volume %u deleted in the VLDB\n", avolid);
722 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
724 if (!Lp_ROMatch(0,0,&entry))
725 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
729 else if (avolid == entry.volumeId[RWVOL]) {
730 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
731 * Check that the readwrite volumes is on the server/partition we
734 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
735 notinvldb = 2; /* Not found on this server and partition */
739 /* Delete backup if it exists */
740 code = AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart, ITOffline, &ttid);
743 fprintf(STDOUT,"Trying to delete the backup volume %u ...", entry.volumeId[BACKVOL]);
746 code = AFSVolDeleteVolume(aconn, ttid);
747 EGOTO1(error_exit, code, "Could not delete the volume %u \n", entry.volumeId[BACKVOL]);
749 code = AFSVolEndTrans(aconn, ttid, &rcode);
751 code = (code ? code : rcode);
752 EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",
753 entry.volumeId[BACKVOL]);
755 fprintf(STDOUT," done\n");
759 fprintf(STDOUT,"Marking the readwrite volume %u%s deleted in the VLDB\n",
760 avolid, ((entry.flags & BACK_EXISTS)?", and its backup volume,":""));
762 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
764 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
767 if (entry.flags & RO_EXISTS)
768 fprintf(STDERR,"WARNING: ReadOnly copy(s) may still exist\n");
772 notinvldb = 2; /* Not found on this server and partition */
776 /* Either delete or replace the VLDB entry */
777 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
779 fprintf(STDOUT,"Last reference to the VLDB entry for %u - deleting entry\n", avolid);
780 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
781 EGOTO1(error_exit, code, "Could not delete the VLDB entry for the volume %u \n",avolid);
783 MapNetworkToHost(&entry, &storeEntry);
784 code = VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
785 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
786 EGOTO1(error_exit, code, "Could not update the VLDB entry for the volume %u \n", avolid);
791 if (error) EPRINT(error, "\n");
793 if (notondisk && notinvldb) {
794 EPRINT2(VOLSERNOVOL,"Volume %u does not exist %s\n",
795 avolid, ((notinvldb == 2)?"on server and partition":""));
796 if (!error) error = VOLSERNOVOL;
798 else if (notondisk) {
799 fprintf(STDERR,"WARNING: Volume %u did not exist on the partition\n", avolid);
801 else if (notinvldb) {
802 fprintf(STDERR,"WARNING: Volume %u does not exist in VLDB %s\n",
803 avolid, ((notinvldb == 2)?"on server and partition":""));
807 code = AFSVolEndTrans(aconn, ttid, &rcode);
808 code = (code ? code : rcode);
810 fprintf(STDERR,"Could not end transaction on the volume %u\n", avolid);
811 PrintError("", code);
812 if (!error) error = code;
817 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, -1,
818 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
820 EPRINT1(code, "Could not release the lock on the VLDB entry for the volume %u \n",
822 if (!error) error = code;
826 if (aconn) rx_DestroyConnection(aconn);
830 /* add recovery to UV_MoveVolume */
832 #define TESTC 0 /* set to test recovery code, clear for production */
837 void sigint_handler(int x)
843 "\nSIGINT handler: vos move operation in progress\n");
845 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
847 "enter second control-c to exit\n");
851 signal(SIGINT,sigint_handler);
856 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
857 * <atopart>. The operation is almost idempotent
860 int UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver,
861 afs_int32 afrompart, afs_int32 atoserver, afs_int32 atopart)
863 struct rx_connection *toconn, *fromconn ;
864 afs_int32 fromtid, totid, clonetid;
867 char tmpName[VOLSER_MAXVOLNAME +1];
870 struct restoreCookie cookie;
871 register afs_int32 vcode, code;
872 afs_int32 newVol, volid, backupId;
873 struct volser_status tstatus;
874 struct destServer destination;
876 struct nvldbentry entry, storeEntry;
877 int i, islocked, pntg;
879 char in,lf; /* for test code */
882 #ifdef ENABLE_BUGFIX_1165
883 volEntries volumeInfo;
884 struct volintInfo *infop = 0;
888 fromconn = (struct rx_connection *)0;
889 toconn = (struct rx_connection *)0;
899 /* support control-c processing */
900 if (setjmp(env)) goto mfail;
901 (void) signal(SIGINT,sigint_handler);
906 "\nThere are three tests points - verifies all code paths through recovery.\n");
907 fprintf(STDOUT,"First test point - operation not started.\n");
908 fprintf(STDOUT,"...test here (y, n)? ");
910 fscanf(stdin,"%c",&in);
911 fscanf(stdin,"%c",&lf); /* toss away */
914 fprintf(STDOUT,"type control-c\n");
922 /* or drop through */
925 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
926 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
928 if (entry.volumeId[RWVOL] != afromvol)
930 fprintf(STDERR,"Only RW volume can be moved\n");
934 vcode = ubik_Call(VL_SetLock, cstruct, 0,afromvol, RWVOL, VLOP_MOVE);
935 EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
938 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
939 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
941 backupId = entry.volumeId[BACKVOL];
942 MapHostToNetwork(&entry);
944 if ( !Lp_Match(afromserver, afrompart, &entry) )
946 /* the from server and partition do not exist in the vldb entry corresponding to volid */
947 if ( !Lp_Match(atoserver, atopart, &entry) )
949 /* the to server and partition do not exist in the vldb entry corresponding to volid */
950 fprintf(STDERR,"The volume %u is not on the specified site. \n", afromvol);
951 fprintf(STDERR,"The current site is :");
952 for (i=0; i<entry.nServers; i++)
954 if (entry.serverFlags[i] == ITSRWVOL)
957 MapPartIdIntoName(entry.serverPartition[i],pname);
958 fprintf(STDERR," server %s partition %s \n",
959 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
962 vcode = ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
963 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
964 EGOTO1(mfail, vcode, " Could not release lock on the VLDB entry for the volume %u \n",
967 return VOLSERVOLMOVED;
970 /* delete the volume afromvol on src_server */
971 /* from-info does not exist but to-info does =>
972 * we have already done the move, but the volume
973 * may still be existing physically on from fileserver
975 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
979 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline, &fromtid);
981 { /* volume exists - delete it */
982 VPRINT1("Setting flags on leftover source volume %u ...", afromvol);
983 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
984 EGOTO1(mfail, code, "Failed to set flags on the leftover source volume %u\n", afromvol);
987 VPRINT1("Deleting leftover source volume %u ...", afromvol);
988 code = AFSVolDeleteVolume(fromconn,fromtid);
989 EGOTO1(mfail, code, "Failed to delete the leftover source volume %u\n", afromvol);
992 VPRINT1("Ending transaction on leftover source volume %u ...", afromvol);
993 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
995 if (!code) code = rcode;
996 EGOTO1(mfail, code, "Could not end the transaction for the leftover source volume %u \n", afromvol);
1000 /*delete the backup volume now */
1002 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1004 { /* backup volume exists - delete it */
1005 VPRINT1("Setting flags on leftover backup volume %u ...", backupId);
1006 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1007 EGOTO1(mfail, code, "Failed to set flags on the backup volume %u\n", backupId);
1010 VPRINT1("Deleting leftover backup volume %u ...", backupId);
1011 code = AFSVolDeleteVolume(fromconn,fromtid);
1012 EGOTO1(mfail, code, "Could not delete the leftover backup volume %u\n", backupId);
1015 VPRINT1("Ending transaction on leftover backup volume %u ...", backupId);
1016 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1018 if (!code) code = rcode;
1019 EGOTO1(mfail, code,"Could not end the transaction for the leftover backup volume %u\n",backupId);
1028 /* From-info matches the vldb info about volid,
1029 * its ok start the move operation, the backup volume
1030 * on the old site is deleted in the process
1032 if (afrompart == atopart)
1034 same = VLDB_IsSameAddrs (afromserver, atoserver, &error);
1035 EGOTO2(mfail, error, "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1036 afromserver, error);
1040 EGOTO1(mfail, VOLSERVOLMOVED, "Warning: Moving volume %u to its home partition ignored!\n", afromvol);
1045 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1046 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1047 fromtid = totid = 0; /* initialize to uncreated */
1050 * clone the read/write volume locally.
1053 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1054 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1055 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1058 /* Get a clone id */
1059 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1061 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1062 EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1065 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1066 VPRINT1("Cloning source volume %u ...", afromvol);
1067 strcpy(vname, "move-clone-temp");
1068 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &newVol);
1069 EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1072 /* lookup the name of the volume we just cloned */
1074 code = AFSVolGetName(fromconn, fromtid, &volName);
1075 EGOTO1(mfail, code, "Failed to get the name of the volume %u\n", newVol);
1077 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1079 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1081 if (!code) code = rcode;
1082 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1086 * Create the destination volume
1089 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1090 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1091 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1094 VPRINT1("Setting flags on cloned volume %u ...", newVol);
1095 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1096 EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", newVol);
1099 /* remember time from which we've dumped the volume */
1100 VPRINT1("Getting status of cloned volume %u ...", newVol);
1101 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1102 EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", newVol);
1105 fromDate = tstatus.creationDate-CLOCKSKEW;
1107 #ifdef ENABLE_BUGFIX_1165
1109 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1110 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1111 * don't use this information...
1113 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
1114 volumeInfo.volEntries_len = 0;
1115 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1116 EGOTO1(mfail, code, "Failed to get the volint Info of the cloned volume %u\n", afromvol);
1118 infop = (volintInfo *) volumeInfo.volEntries_val;
1119 infop->maxquota = -1; /* Else it will replace the default quota */
1122 /* create a volume on the target machine */
1124 code = AFSVolTransCreate (toconn, volid, atopart, ITOffline, &totid);
1127 /* Delete the existing volume.
1128 * While we are deleting the volume in these steps, the transaction
1129 * we started against the cloned volume (clonetid above) will be
1130 * sitting idle. It will get cleaned up after 600 seconds
1132 VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1133 code = AFSVolDeleteVolume(toconn, totid);
1134 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", volid);
1137 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", volid);
1138 code = AFSVolEndTrans(toconn, totid, &rcode);
1140 if (!code) code = rcode;
1141 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1146 VPRINT1("Creating the destination volume %u ...", volid);
1147 code = AFSVolCreateVolume (toconn, atopart, volName, volser_RW, volid, &volid, &totid);
1148 EGOTO1(mfail, code, "Failed to create the destination volume %u\n", volid);
1151 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1155 VPRINT1("Setting volume flags on destination volume %u ...", volid);
1156 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1157 EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", volid);
1161 * Now dump the clone to the new volume
1164 destination.destHost = ntohl(atoserver);
1165 destination.destPort = AFSCONF_VOLUMEPORT;
1166 destination.destSSID = 1;
1168 /* Copy the clone to the new volume */
1169 VPRINT2("Dumping from clone %u on source to volume %u on destination ...", newVol, afromvol);
1170 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1171 cookie.type = RWVOL;
1172 cookie.parent = entry.volumeId[RWVOL];
1174 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1175 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1178 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1179 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1180 if (!code) code = rcode;
1182 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1186 * reattach to the main-line volume, and incrementally dump it.
1189 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1190 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1191 EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1194 /* now do the incremental */
1195 VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1196 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1197 EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1200 /* now adjust the flags so that the new volume becomes official */
1201 VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1202 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1203 EGOTO(mfail, code, "Failed to set the flags to make old source volume offline\n");
1206 VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1207 code = AFSVolSetFlags(toconn, totid, 0);
1208 EGOTO(mfail, code, "Failed to set the flags to make new source volume online\n");
1211 #ifdef ENABLE_BUGFIX_1165
1212 VPRINT1("Setting volume status on destination volume %u ...", volid);
1213 code = AFSVolSetInfo(toconn, totid, infop);
1214 EGOTO1(mfail, code, "Failed to set volume status on the destination volume %u\n", volid);
1218 /* put new volume online */
1219 VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1220 code = AFSVolEndTrans(toconn, totid, &rcode);
1222 if (!code) code = rcode;
1223 EGOTO1(mfail, code, "Failed to end the transaction on the volume %u on the new site\n", afromvol);
1226 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1227 MapNetworkToHost(&entry,&storeEntry);
1228 storeEntry.flags &= ~BACK_EXISTS;
1232 fprintf(STDOUT, "Second test point - operation in progress but not complete.\n");
1233 fprintf(STDOUT,"...test here (y, n)? ");
1235 fscanf(stdin,"%c",&in);
1236 fscanf(stdin,"%c",&lf); /* toss away */
1239 fprintf(STDOUT,"type control-c\n");
1242 fprintf(stdout,".");
1247 /* or drop through */
1250 VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1251 vcode = VLDB_ReplaceEntry (afromvol, -1, &storeEntry,
1252 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1255 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %s %u \n",
1256 storeEntry.name,afromvol);
1265 fprintf(STDOUT, "Third test point - operation complete but no cleanup.\n");
1266 fprintf(STDOUT,"...test here (y, n)? ");
1268 fscanf(stdin,"%c",&in);
1269 fscanf(stdin,"%c",&lf); /* toss away */
1272 fprintf(STDOUT,"type control-c\n");
1275 fprintf(stdout,".");
1280 /* or drop through */
1284 /* This is tricky. File server is very stupid, and if you mark the volume
1285 * as VTOutOfService, it may mark the *good* instance (if you're moving
1286 * between partitions on the same machine) as out of service. Since
1287 * we're cleaning this code up in DEcorum, we're just going to kludge around
1288 * it for now by removing this call. */
1289 /* already out of service, just zap it now */
1290 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1293 fprintf(STDERR,"Failed to set the flags to make the old source volume offline\n");
1297 if (atoserver != afromserver)
1299 /* set forwarding pointer for moved volumes */
1300 VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1301 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1302 EGOTO1(mfail, code, "Failed to set the forwarding pointer for the volume %u\n", afromvol);
1306 VPRINT1("Deleting old volume %u on source ...", afromvol);
1307 code = AFSVolDeleteVolume(fromconn,fromtid); /* zap original volume */
1308 EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n", afromvol);
1311 VPRINT1("Ending transaction on old volume %u on the source ...", afromvol);
1312 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1314 if (!code) code = rcode;
1315 EGOTO1(mfail, code, "Failed to end the transaction on the old volume %u on the source\n", afromvol);
1318 /* Delete the backup volume on the original site */
1319 VPRINT1("Creating transaction for backup volume %u on source ...", backupId);
1320 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1324 VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1325 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1326 EGOTO1(mfail, code, "Failed to set the flags on the backup volume %u on the source\n", backupId);
1329 VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1330 code = AFSVolDeleteVolume(fromconn,fromtid);
1331 EGOTO1(mfail, code, "Failed to delete the backup volume %u on the source\n", backupId);
1334 VPRINT1("Ending transaction on backup volume %u on source ...", backupId);
1335 code = AFSVolEndTrans(fromconn,fromtid, &rcode);
1337 if (!code) code = rcode;
1338 EGOTO1(mfail, code, "Failed to end the transaction on the backup volume %u on the source\n", backupId);
1341 else code = 0; /* no backup volume? that's okay */
1344 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1345 code = AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
1346 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1349 /* now delete the clone */
1350 VPRINT1("Deleting the cloned volume %u ...", newVol);
1351 code = AFSVolDeleteVolume(fromconn, clonetid);
1352 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", newVol);
1355 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1356 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1357 if (!code) code = rcode;
1359 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1367 fprintf(STDOUT,"Fourth test point - operation complete.\n");
1368 fprintf(STDOUT,"...test here (y, n)? ");
1370 fscanf(stdin,"%c",&in);
1371 fscanf(stdin,"%c",&lf); /* toss away */
1374 fprintf(STDOUT,"type control-c\n");
1377 fprintf(stdout,".");
1382 /* or drop through */
1385 /* normal cleanup code */
1387 if (entry.flags & RO_EXISTS) fprintf(STDERR,"WARNING : readOnly copies still exist \n");
1391 VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1392 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, -1,
1393 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1397 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %u \n",
1399 if (!error) error = vcode;
1406 VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1407 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1411 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n", newVol);
1412 if (!error) error = (code ? code : rcode);
1419 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1420 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1424 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",newVol);
1425 if (!error) error = (code ? code : rcode);
1432 VPRINT1("Cleanup: Ending transaction on destination volume %u ...", afromvol);
1433 code = AFSVolEndTrans(toconn, totid, &rcode);
1437 fprintf(STDERR,"Could not end transaction on destination volume %u\n",afromvol);
1438 if (!error) error = (code ? code : rcode);
1442 if (volName) free(volName);
1443 #ifdef ENABLE_BUGFIX_1165
1444 if (infop) free(infop);
1446 if (fromconn) rx_DestroyConnection(fromconn);
1447 if (toconn) rx_DestroyConnection(toconn);
1448 PrintError("",error);
1451 /* come here only when the sky falls */
1456 fprintf(STDOUT,"vos move: operation interrupted, cleanup in progress...\n");
1457 fprintf(STDOUT,"clear transaction contexts\n");
1461 /* unlock VLDB entry */
1464 VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1465 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1466 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1472 VPRINT("Recovery: Ending transaction on clone volume ...");
1473 AFSVolEndTrans(fromconn, clonetid, &rcode);
1478 VPRINT("Recovery: Ending transaction on destination volume ...");
1479 AFSVolEndTrans(toconn, totid, &rcode);
1483 { /* put it on-line */
1484 VPRINT("Recovery: Setting volume flags on source volume ...");
1485 AFSVolSetFlags(fromconn,fromtid,0);
1488 VPRINT("Recovery: Ending transaction on source volume ...");
1489 AFSVolEndTrans(fromconn, fromtid, &rcode);
1493 VPRINT("Recovery: Accessing VLDB.\n");
1494 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
1497 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
1501 MapHostToNetwork(&entry);
1503 /* Delete either the volume on the source location or the target location.
1504 * If the vldb entry still points to the source location, then we know the
1505 * volume move didn't finish so we remove the volume from the target
1506 * location. Otherwise, we remove the volume from the source location.
1508 if (Lp_Match(afromserver,afrompart,&entry)) { /* didn't move - delete target volume */
1511 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1515 if (volid && toconn) {
1516 VPRINT1("Recovery: Creating transaction for destination volume %u ...", volid);
1517 code=AFSVolTransCreate(toconn,volid,atopart, ITOffline,&totid);
1522 VPRINT1("Recovery: Setting flags on destination volume %u ...", volid);
1523 AFSVolSetFlags(toconn,totid, VTDeleteOnSalvage | VTOutOfService);
1526 VPRINT1("Recovery: Deleting destination volume %u ...", volid);
1527 AFSVolDeleteVolume(toconn,totid);
1530 VPRINT1("Recovery: Ending transaction on destination volume %u ...", volid);
1531 AFSVolEndTrans(toconn,totid,&rcode);
1536 VPRINT1("\nRecovery: Unable to start transaction on destination volume %u.\n", afromvol);
1540 /* put source volume on-line */
1542 VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1543 code=AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1547 VPRINT1("Recovery: Setting flags on source volume %u ...", afromvol);
1548 AFSVolSetFlags(fromconn,fromtid,0);
1551 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1552 AFSVolEndTrans(fromconn,fromtid,&rcode);
1557 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1561 else { /* yep, move complete */
1564 "move complete - attempt cleanup of source partition - no guarantee\n");
1568 /* delete backup volume */
1570 VPRINT1("Recovery: Creating transaction on backup volume %u ...", backupId);
1571 code=AFSVolTransCreate (fromconn,backupId,afrompart, ITOffline,&fromtid);
1575 VPRINT1("Recovery: Setting flags on backup volume %u ...", backupId);
1576 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1579 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1580 AFSVolDeleteVolume(fromconn,fromtid);
1583 VPRINT1("Recovery: Ending transaction on backup volume %u ...", backupId);
1584 AFSVolEndTrans(fromconn,fromtid,&rcode);
1589 VPRINT1("\nRecovery: Unable to start transaction on backup volume %u.\n", backupId);
1592 /* delete source volume */
1593 VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1594 code=AFSVolTransCreate (fromconn, afromvol, afrompart, ITBusy, &fromtid);
1598 VPRINT1("Recovery: Setting flags on backup volume %u ...", afromvol);
1599 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1602 if (atoserver != afromserver)
1604 VPRINT("Recovery: Setting volume forwarding pointer ...");
1605 AFSVolSetForwarding(fromconn,fromtid,atoserver);
1609 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1610 AFSVolDeleteVolume(fromconn,fromtid);
1613 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1614 AFSVolEndTrans(fromconn,fromtid,&rcode);
1619 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1624 /* common cleanup - delete local clone */
1626 VPRINT1("Recovery: Creating transaction on clone volume %u ...", newVol);
1627 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1631 VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1632 AFSVolDeleteVolume(fromconn,clonetid);
1635 VPRINT1("Recovery: Ending transaction on clone volume %u ...", newVol);
1636 AFSVolEndTrans(fromconn,clonetid,&rcode);
1641 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1645 /* unlock VLDB entry */
1646 VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...", afromvol);
1647 ubik_Call (VL_ReleaseLock, cstruct, 0, afromvol, -1,
1648 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1651 done: /* routine cleanup */
1652 if (volName) free(volName);
1653 #ifdef ENABLE_BUGFIX_1165
1654 if (infop) free(infop);
1656 if (fromconn) rx_DestroyConnection(fromconn);
1657 if (toconn) rx_DestroyConnection(toconn);
1660 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
1667 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1668 * <atopart>. The operation is almost idempotent
1671 int UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver,
1672 afs_int32 afrompart, char *atovolname, afs_int32 atoserver, afs_int32 atopart)
1674 struct rx_connection *toconn, *fromconn ;
1675 afs_int32 fromtid, totid, clonetid;
1677 char tmpName[VOLSER_MAXVOLNAME +1];
1680 struct restoreCookie cookie;
1681 register afs_int32 vcode, code;
1682 afs_int32 cloneVol, newVol;
1683 struct volser_status tstatus;
1684 struct destServer destination;
1686 struct nvldbentry entry, newentry, storeEntry;
1687 int i, islocked, pntg;
1689 char in,lf; /* for test code */
1694 fromconn = (struct rx_connection *)0;
1695 toconn = (struct rx_connection *)0;
1703 /* support control-c processing */
1704 if (setjmp(env)) goto mfail;
1705 (void) signal(SIGINT,sigint_handler);
1707 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1708 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
1709 MapHostToNetwork(&entry);
1712 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1713 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1714 fromtid = totid = 0; /* initialize to uncreated */
1717 /* check if we can shortcut and use a local clone instead of a full copy */
1718 if ( afromserver == atoserver && afrompart == atopart )
1724 * clone the read/write volume locally.
1727 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1728 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1729 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1732 /* Get a clone id */
1733 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1735 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &cloneVol);
1736 EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1739 /* Get a new volume id */
1740 VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
1742 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1743 EGOTO1(mfail, vcode, "Could not get an ID for the copy of volume %u from the VLDB\n", afromvol);
1746 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1747 VPRINT1("Cloning source volume %u ...", afromvol);
1748 strcpy(vname, "copy-clone-temp");
1749 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &cloneVol);
1750 EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1753 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1755 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1757 if (!code) code = rcode;
1758 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1762 * Create the destination volume
1765 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1766 code = AFSVolTransCreate (fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1767 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1770 VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
1771 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1772 EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", cloneVol);
1775 /* remember time from which we've dumped the volume */
1776 VPRINT1("Getting status of cloned volume %u ...", cloneVol);
1777 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1778 EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", cloneVol);
1781 fromDate = tstatus.creationDate-CLOCKSKEW;
1783 /* create a volume on the target machine */
1784 code = AFSVolTransCreate (toconn, newVol, atopart, ITOffline, &totid);
1787 /* Delete the existing volume.
1788 * While we are deleting the volume in these steps, the transaction
1789 * we started against the cloned volume (clonetid above) will be
1790 * sitting idle. It will get cleaned up after 600 seconds
1792 VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
1793 code = AFSVolDeleteVolume(toconn, totid);
1794 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", newVol);
1797 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", newVol);
1798 code = AFSVolEndTrans(toconn, totid, &rcode);
1800 if (!code) code = rcode;
1801 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1806 VPRINT1("Creating the destination volume %u ...", newVol);
1807 code = AFSVolCreateVolume (toconn, atopart, atovolname, volser_RW, newVol, &newVol, &totid);
1808 EGOTO1(mfail, code, "Failed to create the destination volume %u\n", newVol);
1811 strncpy(tmpName, atovolname, VOLSER_OLDMAXVOLNAME);
1813 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1814 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1815 EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", newVol);
1819 * Now dump the clone to the new volume
1822 destination.destHost = ntohl(atoserver);
1823 destination.destPort = AFSCONF_VOLUMEPORT;
1824 destination.destSSID = 1;
1827 /* probably should have some code here that checks to see if we are copying to same server
1828 and partition - if so, just use a clone to save disk space */
1830 /* Copy the clone to the new volume */
1831 VPRINT2("Dumping from clone %u on source to volume %u on destination ...", cloneVol, newVol);
1832 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1833 cookie.type = RWVOL;
1836 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1837 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", newVol);
1840 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1841 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1842 if (!code) code = rcode;
1844 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1848 * reattach to the main-line volume, and incrementally dump it.
1851 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1852 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1853 EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1856 /* now do the incremental */
1857 VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1858 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1859 EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1862 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1863 code = AFSVolSetFlags(toconn, totid, 0);
1864 EGOTO(mfail, code, "Failed to set the flags to make destination volume online\n");
1867 /* put new volume online */
1868 VPRINT1("Ending transaction on destination volume %u ...", newVol);
1869 code = AFSVolEndTrans(toconn, totid, &rcode);
1871 if (!code) code = rcode;
1872 EGOTO1(mfail, code, "Failed to end the transaction on the destination volume %u\n", newVol);
1875 VPRINT1("Ending transaction on source volume %u ...", afromvol);
1876 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1878 if (!code) code = rcode;
1879 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1883 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1884 code = AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1885 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1888 /* now delete the clone */
1889 VPRINT1("Deleting the cloned volume %u ...", cloneVol);
1890 code = AFSVolDeleteVolume(fromconn, clonetid);
1891 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", cloneVol);
1894 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1895 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1896 if (!code) code = rcode;
1898 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1901 /* create the vldb entry for the copied volume */
1902 strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
1903 newentry.nServers = 1;
1904 newentry.serverNumber[0] = atoserver;
1905 newentry.serverPartition[0] = atopart;
1906 newentry.flags = RW_EXISTS;/* this records that rw volume exists */
1907 newentry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
1908 newentry.volumeId[RWVOL] = newVol;
1909 newentry.volumeId[ROVOL] = 0;
1910 newentry.volumeId[BACKVOL] = 0;
1911 newentry.cloneId = 0;
1912 /*map into right byte order, before passing to xdr, the stuff has to be in host
1913 byte order. Xdr converts it into network order */
1914 MapNetworkToHost(&newentry,&storeEntry);
1915 /* create the vldb entry */
1916 vcode = VLDB_CreateEntry(&storeEntry);
1918 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", atovolname,newVol);
1919 /*destroy the created volume*/
1920 VPRINT1("Deleting the newly created volume %u\n",newVol);
1921 AFSVolDeleteVolume(toconn,totid);
1925 VPRINT2("Created the VLDB entry for the volume %s %u\n",atovolname,newVol);
1927 /* normal cleanup code */
1931 VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1932 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1936 fprintf(STDERR,"Could not end transaction on the source volume %u\n", afromvol);
1937 if (!error) error = (code ? code : rcode);
1944 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", cloneVol);
1945 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1949 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",cloneVol);
1950 if (!error) error = (code ? code : rcode);
1957 VPRINT1("Cleanup: Ending transaction on destination volume %u ...", newVol);
1958 code = AFSVolEndTrans(toconn, totid, &rcode);
1962 fprintf(STDERR,"Could not end transaction on destination volume %u\n", newVol);
1963 if (!error) error = (code ? code : rcode);
1967 if (fromconn) rx_DestroyConnection(fromconn);
1968 if (toconn) rx_DestroyConnection(toconn);
1969 PrintError("",error);
1972 /* come here only when the sky falls */
1977 fprintf(STDOUT,"vos copy: operation interrupted, cleanup in progress...\n");
1978 fprintf(STDOUT,"clear transaction contexts\n");
1984 VPRINT("Recovery: Ending transaction on clone volume ...");
1985 AFSVolEndTrans(fromconn, clonetid, &rcode);
1990 VPRINT("Recovery: Ending transaction on destination volume ...");
1991 AFSVolEndTrans(toconn, totid, &rcode);
1995 { /* put it on-line */
1996 VPRINT("Recovery: Ending transaction on source volume ...");
1997 AFSVolEndTrans(fromconn, fromtid, &rcode);
2001 VPRINT("Recovery: Accessing VLDB.\n");
2002 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
2005 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
2009 MapHostToNetwork(&entry);
2011 /* common cleanup - delete local clone */
2013 VPRINT1("Recovery: Creating transaction on clone volume %u ...", cloneVol);
2014 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
2018 VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2019 AFSVolDeleteVolume(fromconn,clonetid);
2022 VPRINT1("Recovery: Ending transaction on clone volume %u ...", cloneVol);
2023 AFSVolEndTrans(fromconn,clonetid,&rcode);
2028 VPRINT1("\nRecovery: Unable to start transaction on clone volume %u.\n", cloneVol);
2032 done: /* routine cleanup */
2033 if (fromconn) rx_DestroyConnection(fromconn);
2034 if (toconn) rx_DestroyConnection(toconn);
2037 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
2047 /* Make a new backup of volume <avolid> on <aserver> and <apart>
2048 * if one already exists, update it
2051 int UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2053 struct rx_connection *aconn = (struct rx_connection *)0;
2054 afs_int32 ttid = 0, btid = 0;
2056 afs_int32 code = 0, rcode = 0;
2057 char vname[VOLSER_MAXVOLNAME +1];
2058 struct nvldbentry entry, storeEntry;
2059 afs_int32 error = 0;
2060 int vldblocked = 0, vldbmod = 0, backexists = 1;
2062 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2064 /* the calls to VLDB will succeed only if avolid is a RW volume,
2065 * since we are following the RW hash chain for searching */
2066 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2068 fprintf(STDERR, "Could not fetch the entry for the volume %u from the VLDB \n", avolid);
2069 error = code; goto bfail;
2071 MapHostToNetwork(&entry);
2073 /* These operations require the VLDB be locked since it means the VLDB
2074 * will change or the vldb is already locked.
2076 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
2077 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
2078 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
2080 code = ubik_Call(VL_SetLock,cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2082 fprintf(STDERR,"Could not lock the VLDB entry for the volume %u\n",avolid);
2088 /* Reread the vldb entry */
2089 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2091 fprintf(STDERR,"Could not fetch the entry for the volume %u from the VLDB \n",avolid);
2095 MapHostToNetwork(&entry);
2098 if (!ISNAMEVALID(entry.name)) {
2099 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n", entry.name);
2100 error = VOLSERBADNAME;
2104 backupID = entry.volumeId[BACKVOL];
2105 if (backupID == INVALID_BID) {
2106 /* Get a backup volume id from the VLDB and update the vldb
2109 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
2112 "Could not allocate ID for the backup volume of %u from the VLDB\n",
2117 entry.volumeId[BACKVOL] = backupID;
2121 /* Test to see if the backup volume exists by trying to create
2122 * a transaction on the backup volume. We've assumed the backup exists.
2124 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2126 if (code != VNOVOL) {
2127 fprintf(STDERR,"Could not reach the backup volume %u\n", backupID);
2131 backexists = 0; /* backup volume does not exist */
2134 code = AFSVolEndTrans(aconn, btid, &rcode);
2136 if (code || rcode) {
2138 "Could not end transaction on the previous backup volume %u\n",
2140 error = (code ? code : rcode);
2145 /* Now go ahead and try to clone the RW volume.
2146 * First start a transaction on the RW volume
2148 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2150 fprintf(STDERR,"Could not start a transaction on the volume %u\n",avolid);
2155 /* Clone or reclone the volume, depending on whether the backup
2156 * volume exists or not
2159 VPRINT1("Re-cloning backup volume %u ...", backupID);
2161 code = AFSVolReClone(aconn, ttid, backupID);
2163 fprintf(STDERR,"Could not re-clone backup volume %u\n", backupID);
2169 VPRINT1("Creating a new backup clone %u ...", backupID);
2171 strcpy(vname, entry.name);
2172 strcat(vname,".backup");
2174 code = AFSVolClone(aconn, ttid, 0,backupVolume, vname, &backupID);
2176 fprintf(STDERR,"Failed to clone the volume %u\n",avolid);
2182 /* End the transaction on the RW volume */
2183 code = AFSVolEndTrans(aconn, ttid, &rcode);
2185 if (code || rcode) {
2186 fprintf(STDERR, "Failed to end the transaction on the rw volume %u\n", avolid);
2187 error = (code ? code : rcode);
2191 /* Mork vldb as backup exists */
2192 if (!(entry.flags & BACK_EXISTS)) {
2193 entry.flags |= BACK_EXISTS;
2197 /* Now go back to the backup volume and bring it on line */
2198 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2200 fprintf(STDERR,"Failed to start a transaction on the backup volume %u\n",backupID);
2205 code = AFSVolSetFlags(aconn, btid, 0);
2207 fprintf(STDERR,"Could not mark the backup volume %u on line \n",backupID);
2212 code = AFSVolEndTrans(aconn, btid, &rcode);
2214 if (code || rcode) {
2215 fprintf(STDERR, "Failed to end the transaction on the backup volume %u\n", backupID);
2216 error = (code ? code : rcode);
2222 /* Will update the vldb below */
2226 code = AFSVolEndTrans(aconn, ttid, &rcode);
2227 if (code || rcode) {
2228 fprintf(STDERR, "Could not end transaction on the volume %u\n", avolid);
2230 error = (code ? code : rcode);
2235 code = AFSVolEndTrans(aconn, btid, &rcode);
2236 if (code || rcode) {
2237 fprintf(STDERR,"Could not end transaction the backup volume %u\n",backupID);
2239 error = (code ? code : rcode);
2243 /* Now update the vldb - if modified */
2246 MapNetworkToHost(&entry,&storeEntry);
2247 code = VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2248 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2250 fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n",avolid);
2256 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, RWVOL,
2257 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2259 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %u \n",avolid);
2267 rx_DestroyConnection(aconn);
2269 PrintError("",error);
2273 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags)
2275 afs_int32 acode, ccode, rcode, tid;
2276 ccode = rcode = tid = 0;
2278 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2279 if (!acode) { /* It really was there */
2280 acode = AFSVolDeleteVolume(conn, tid);
2282 fprintf(STDERR, "Failed to delete volume %u.\n", vid);
2283 PrintError ("", acode);
2285 ccode = AFSVolEndTrans(conn, tid, &rcode);
2289 fprintf(STDERR, "Failed to end transaction on volume %u.\n", vid);
2290 PrintError ("", ccode);
2297 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
2298 #define ERROREXIT(ec) { error = (ec); goto rfail; }
2300 /* Get a "transaction" on this replica. Create the volume
2301 * if necessary. Return the time from which a dump should
2302 * be made (0 if it's a new volume)
2304 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr,
2305 afs_int32 *transPtr, afs_int32 *timePtr)
2308 struct volser_status tstatus;
2309 int code, rcode, tcode;
2311 *connPtr = (struct rx_connection *)0;
2315 /* get connection to the replication site */
2316 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
2317 if (!*connPtr) goto fail; /* server is down */
2319 volid = vldbEntryPtr->volumeId[ROVOL];
2321 code = AFSVolTransCreate(*connPtr, volid, vldbEntryPtr->serverPartition[index],
2322 ITOffline, transPtr);
2324 /* If the volume does not exist, create it */
2325 if (!volid || code) {
2328 if (volid && (code != VNOVOL)){
2329 PrintError("Failed to start a transaction on the RO volume.\n",
2334 strcpy(volname, vldbEntryPtr->name);
2335 strcat(volname, ".readonly");
2338 fprintf(STDOUT,"Creating new volume %u on replication site %s: ",
2339 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2343 code = AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
2345 vldbEntryPtr->volumeId[RWVOL], &volid, transPtr);
2347 PrintError("Failed to create the ro volume: ",code);
2350 vldbEntryPtr->volumeId[ROVOL] = volid;
2354 /* The following is a bit redundant, since create sets these flags by default */
2355 code = AFSVolSetFlags(*connPtr, *transPtr, VTDeleteOnSalvage | VTOutOfService);
2357 PrintError("Failed to set flags on the ro volume: ", code);
2362 /* Otherwise, the transaction did succeed, so get the creation date of the
2363 * latest RO volume on the replication site
2366 VPRINT2("Updating existing ro volume %u on %s ...\n",
2367 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2369 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
2371 PrintError("Failed to get status of volume on destination: ",code);
2374 *timePtr = tstatus.creationDate-CLOCKSKEW;
2381 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
2383 if (!tcode) tcode = rcode;
2384 if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode);
2390 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
2391 afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results)
2395 for (i=0; i<tr->manyDests_len; i++) {
2396 results->manyResults_val[i] = AFSVolForward(fromconn, fromtid,
2397 fromdate, &(tr->manyDests_val[i].server),
2398 tr->manyDests_val[i].trans, cookie);
2404 static int rel_compar (struct release *r1, struct release *r2)
2406 return (r1->time - r2->time);
2409 /* UV_ReleaseVolume()
2410 * Release volume <afromvol> on <afromserver> <afrompart> to all
2411 * its RO sites (full release). Unless the previous release was
2412 * incomplete: in which case we bring the remaining incomplete
2413 * volumes up to date with the volumes that were released
2415 * forceflag: Performs a full release.
2417 * Will create a clone from the RW, then dump the clone out to
2418 * the remaining replicas. If there is more than 1 RO sites,
2419 * ensure that the VLDB says at least one RO is available all
2420 * the time: Influences when we write back the VLDB entry.
2423 int UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, int forceflag)
2426 afs_int32 code, vcode, rcode, tcode;
2427 afs_int32 cloneVolId, roVolId;
2428 struct replica *replicas=0;
2429 struct nvldbentry entry,storeEntry;
2430 int i, volcount, m, fullrelease, vldbindex;
2432 struct restoreCookie cookie;
2433 struct rx_connection **toconns=0;
2434 struct release *times=0;
2436 struct rx_connection *fromconn = (struct rx_connection *)0;
2437 afs_int32 error = 0;
2439 afs_int32 clonetid=0, onlinetid;
2440 afs_int32 fromtid=0;
2441 afs_uint32 fromdate, thisdate;
2444 manyResults results;
2445 int rwindex, roindex, roclone, roexists;
2450 } remembertime[NMAXNSERVERS];
2451 int releasecount = 0;
2452 struct volser_status volstatus;
2454 memset((char *)remembertime, 0, sizeof(remembertime));
2455 memset((char *)&results, 0, sizeof(results));
2457 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
2458 if (vcode != VL_RERELEASE)
2459 ONERROR(vcode, afromvol, "Could not lock the VLDB entry for the volume %u.\n");
2462 /* Get the vldb entry in readable format */
2463 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
2464 ONERROR(vcode, afromvol, "Could not fetch the entry for the volume %u from the VLDB.\n");
2465 MapHostToNetwork(&entry);
2468 EnumerateEntry(&entry);
2470 if (!ISNAMEVALID(entry.name))
2471 ONERROR(VOLSERBADOP, entry.name,
2472 "Volume name %s is too long, rename before releasing.\n");
2473 if (entry.volumeId[RWVOL] != afromvol)
2474 ONERROR(VOLSERBADOP, afromvol,
2475 "The volume %u being released is not a read-write volume.\n");
2476 if (entry.nServers <= 1)
2477 ONERROR(VOLSERBADOP, afromvol,
2478 "Volume %u has no replicas - release operation is meaningless!\n");
2479 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
2480 ONERROR(VOLSERBADOP, entry.name,
2481 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
2483 /* roclone is true if one of the RO volumes is on the same
2484 * partition as the RW volume. In this case, we make the RO volume
2485 * on the same partition a clone instead of a complete copy.
2488 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
2489 roclone = ((roindex == -1) ? 0 : 1);
2490 rwindex = Lp_GetRwIndex(&entry);
2492 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
2494 /* Make sure we have a RO volume id to work with */
2495 if (entry.volumeId[ROVOL] == INVALID_BID) {
2496 /* need to get a new RO volume id */
2497 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
2498 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
2500 entry.volumeId[ROVOL] = roVolId;
2501 MapNetworkToHost(&entry, &storeEntry);
2502 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2503 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2506 /* Will we be completing a previously unfinished release. -force overrides */
2507 for (fullrelease=1, i=0; (fullrelease && (i<entry.nServers)); i++) {
2508 if (entry.serverFlags[i] & NEW_REPSITE)
2511 if (forceflag && !fullrelease)
2514 /* Determine which volume id to use and see if it exists */
2515 cloneVolId = ((fullrelease || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
2516 code = VolumeExists(afromserver, afrompart, cloneVolId);
2517 roexists = ((code == ENODEV) ? 0 : 1);
2518 if (!roexists && !fullrelease)
2519 fullrelease = 1; /* Do a full release if RO clone does not exist */
2523 fprintf(STDOUT,"This is a complete release of the volume %u\n", afromvol);
2525 fprintf(STDOUT,"This is a completion of the previous release\n");
2529 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2531 ONERROR(-1, afromserver, "Cannot establish connection with server 0x%x\n");
2534 /* If the RO clone exists, then if the clone is a temporary
2535 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2536 * (it was recently added), then also delete it. We do not
2537 * want to "reclone" a temporary RO clone.
2540 (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE)) ) {
2541 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2542 if (code && (code != VNOVOL))
2547 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2548 * write this entry out to the vlserver until after the first
2549 * RO volume is released (temp RO clones don't count).
2551 for (i=0; i<entry.nServers; i++) {
2552 entry.serverFlags[i] &= ~NEW_REPSITE;
2553 entry.serverFlags[i] |= RO_DONTUSE;
2555 entry.serverFlags[rwindex] |= NEW_REPSITE;
2556 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2558 /* Begin transaction on RW and mark it busy while we clone it */
2559 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &clonetid);
2560 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2562 /* Clone or reclone the volume */
2564 VPRINT1("Recloning RW volume %u...", cloneVolId);
2565 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2566 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2570 strcpy(vname, entry.name);
2571 strcat(vname, ".readonly");
2572 VPRINT("Cloning RW volume %u to permanent RO...");
2574 strcpy(vname, "readonly-clone-temp");
2575 VPRINT("Cloning RW volume %u to temporary RO...");
2577 code = AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, &cloneVolId);
2578 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
2582 /* Get the time the RW was created for future information */
2583 VPRINT1("Getting status of RW volume %u...", cloneVolId);
2584 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
2585 ONERROR(code, cloneVolId, "Failed to get the status of the RW volume %u\n");
2587 rwcrdate = volstatus.creationDate;
2589 /* End the transaction on the RW volume */
2590 VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
2591 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2593 ONERROR((code?code:rcode), cloneVolId, "Failed to end cloning transaction on RW %u\n");
2596 /* Remember clone volume ID in case we fail or are interrupted */
2597 entry.cloneId = cloneVolId;
2600 /* Bring the RO clone online - though not if it's a temporary clone */
2601 VPRINT1("Starting transaction on RO clone volume %u...", cloneVolId);
2602 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline, &onlinetid);
2603 ONERROR(code, cloneVolId, "Failed to start transaction on volume %u\n");
2606 VPRINT1("Setting volume flags for volume %u...", cloneVolId);
2607 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
2610 VPRINT1("Ending transaction on volume %u...", cloneVolId);
2611 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
2612 ONERROR((code?code:rcode), cloneVolId, "Failed to end transaction on RO clone %u\n");
2615 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
2617 /* Sleep so that a client searching for an online volume won't
2618 * find the clone offline and then the next RO offline while the
2619 * release brings the clone online and the next RO offline (race).
2620 * There is a fix in the 3.4 client that does not need this sleep
2621 * anymore, but we don't know what clients we have.
2623 if (entry.nServers > 2)
2626 /* Mark the RO clone in the VLDB as a good site (already released)*/
2627 entry.serverFlags[roindex] |= NEW_REPSITE;
2628 entry.serverFlags[roindex] &= ~RO_DONTUSE;
2629 entry.flags |= RO_EXISTS;
2633 /* Write out the VLDB entry only if the clone is not a temporary
2634 * clone. If we did this to a temporary clone then we would end
2635 * up marking all the ROs as "old release" making the ROs
2636 * temporarily unavailable.
2638 MapNetworkToHost(&entry, &storeEntry);
2639 VPRINT1("Replacing VLDB entry for %s...", entry.name);
2640 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2641 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2646 /* Now we will release from the clone to the remaining RO replicas.
2647 * The first 2 ROs (counting the non-temporary RO clone) are released
2648 * individually: releasecount. This is to reduce the race condition
2649 * of clients trying to find an on-line RO volume. The remaining ROs
2650 * are released in parallel but no more than half the number of ROs
2651 * (rounded up) at a time: nservers.
2654 strcpy(vname, entry.name);
2655 strcat(vname, ".readonly");
2656 memset(&cookie, 0, sizeof(cookie));
2657 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
2658 cookie.type = ROVOL;
2659 cookie.parent = entry.volumeId[RWVOL];
2662 nservers = entry.nServers/2; /* how many to do at once, excluding clone */
2663 replicas = (struct replica *) malloc (sizeof(struct replica)*nservers+1);
2664 times = (struct release *) malloc (sizeof(struct release)*nservers+1);
2665 toconns = (struct rx_connection **) malloc (sizeof(struct rx_connection *)*nservers+1);
2666 results.manyResults_val = (afs_int32 *) malloc (sizeof(afs_int32)*nservers+1);
2667 if ( !replicas || !times || !! !results.manyResults_val || !toconns )
2668 ONERROR(ENOMEM, 0, "Failed to create transaction on the release clone\n");
2670 memset(replicas, 0, (sizeof(struct replica)*nservers+1));
2671 memset(times, 0, (sizeof(struct release)*nservers+1));
2672 memset(toconns, 0, (sizeof(struct rx_connection *)*nservers+1));
2673 memset(results.manyResults_val, 0, (sizeof(afs_int32)*nservers+1));
2675 /* Create a transaction on the cloned volume */
2676 VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
2677 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
2678 if (!fullrelease && code)
2679 ONERROR(VOLSERNOVOL, afromvol,"Old clone is inaccessible. Try vos release -f %u.\n");
2680 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
2683 /* For each index in the VLDB */
2684 for (vldbindex=0; vldbindex<entry.nServers; ) {
2686 /* Get a transaction on the replicas. Pick replacas which have an old release. */
2687 for (volcount=0; ((volcount<nservers) && (vldbindex<entry.nServers)); vldbindex++) {
2688 /* The first two RO volumes will be released individually.
2689 * The rest are then released in parallel. This is a hack
2690 * for clients not recognizing right away when a RO volume
2691 * comes back on-line.
2693 if ((volcount == 1) && (releasecount < 2))
2696 if (vldbindex == roindex) continue; /* the clone */
2697 if ( (entry.serverFlags[vldbindex] & NEW_REPSITE) &&
2698 !(entry.serverFlags[vldbindex] & RO_DONTUSE) ) continue;
2699 if (!(entry.serverFlags[vldbindex] & ITSROVOL)) continue; /* not a RO vol */
2702 /* Get a Transaction on this replica. Get a new connection if
2703 * necessary. Create the volume if necessary. Return the
2704 * time from which the dump should be made (0 if it's a new
2705 * volume). Each volume might have a different time.
2707 replicas[volcount].server.destHost = ntohl(entry.serverNumber[vldbindex]);
2708 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
2709 replicas[volcount].server.destSSID = 1;
2710 times[volcount].vldbEntryIndex = vldbindex;
2712 code = GetTrans(&entry, vldbindex, &(toconns[volcount]),
2713 &(replicas[volcount].trans), &(times[volcount].time));
2716 /* Thisdate is the date from which we want to pick up all changes */
2717 if (forceflag || !fullrelease || (rwcrdate > times[volcount].time)) {
2718 /* If the forceflag is set, then we want to do a full dump.
2719 * If it's not a full release, we can't be sure that the creation
2720 * date is good (so we also do a full dump).
2721 * If the RW volume was replaced (its creation date is newer than
2722 * the last release), then we can't be sure what has changed (so
2723 * we do a full dump).
2726 } else if (remembertime[vldbindex].validtime) {
2727 /* Trans was prev ended. Use the time from the prev trans
2728 * because, prev trans may have created the volume. In which
2729 * case time[volcount].time would be now instead of 0.
2731 thisdate = (remembertime[vldbindex].time < times[volcount].time) ?
2732 remembertime[vldbindex].time : times[volcount].time;
2734 thisdate = times[volcount].time;
2736 remembertime[vldbindex].validtime = 1;
2737 remembertime[vldbindex].time = thisdate;
2739 if (volcount == 0) {
2740 fromdate = thisdate;
2742 /* Include this volume if it is within 15 minutes of the earliest */
2743 if (((fromdate>thisdate)?(fromdate-thisdate):(thisdate-fromdate)) > 900) {
2744 AFSVolEndTrans(toconns[volcount], replicas[volcount].trans, &rcode);
2745 replicas[volcount].trans = 0;
2748 if (thisdate < fromdate)
2749 fromdate = thisdate;
2753 if (!volcount) continue;
2756 fprintf(STDOUT,"Starting ForwardMulti from %u to %u on %s",
2757 cloneVolId, entry.volumeId[ROVOL],
2758 hostutil_GetNameByINet(entry.serverNumber[times[0].vldbEntryIndex]));
2760 for (s=1; s<volcount; s++) {
2761 fprintf(STDOUT," and %s",
2762 hostutil_GetNameByINet(entry.serverNumber[times[s].vldbEntryIndex]));
2766 fprintf(STDOUT," (full release)");
2767 fprintf(STDOUT,".\n");
2771 /* Release the ones we have collected */
2772 tr.manyDests_val = &(replicas[0]);
2773 tr.manyDests_len = results.manyResults_len = volcount;
2774 code = AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2775 if (code == RXGEN_OPCODE) { /* RPC Interface Mismatch */
2776 code = SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2781 PrintError("Release failed: ", code);
2783 for (m=0; m<volcount; m++) {
2784 if (results.manyResults_val[m]) {
2785 if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
2786 /* we retry timed out transaction. When it is
2787 * not the first volume and the transaction wasn't found
2788 * (assume it timed out and was garbage collected by volser).
2790 PrintError("Failed to dump volume from clone to a ro site: ",
2791 results.manyResults_val[m]);
2796 code = AFSVolSetIdsTypes(toconns[m], replicas[m].trans,
2797 vname, ROVOL, entry.volumeId[RWVOL], 0, 0);
2799 if ((m == 0) || (code != ENOENT)) {
2800 PrintError("Failed to set correct names and ids: ", code);
2805 /* have to clear dest. flags to ensure new vol goes online:
2806 * because the restore (forwarded) operation copied
2807 * the V_inService(=0) flag over to the destination.
2809 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
2811 if ((m == 0) || (code != ENOENT)) {
2812 PrintError("Failed to set flags on ro volume: ", code);
2817 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
2818 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
2819 entry.flags |= RO_EXISTS;
2824 /* End the transactions and destroy the connections */
2825 for (s=0; s<volcount; s++) {
2826 if (replicas[s].trans)
2827 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
2828 replicas[s].trans = 0;
2829 if (!code) code = rcode;
2831 if ((s == 0) || (code != ENOENT)) {
2832 PrintError("Could not end transaction on a ro volume: ", code);
2834 PrintError("Transaction timed out on a ro volume. Will retry.\n", 0);
2835 if (times[s].vldbEntryIndex < vldbindex)
2836 vldbindex = times[s].vldbEntryIndex;
2841 rx_DestroyConnection(toconns[s]);
2845 MapNetworkToHost(&entry, &storeEntry);
2846 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2847 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2848 } /* for each index in the vldb */
2850 /* End the transaction on the cloned volume */
2851 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2853 if (!code) code = rcode;
2855 PrintError("Failed to end transaction on rw volume: ", code);
2857 /* Figure out if any volume were not released and say so */
2858 for (failure=0, i=0; i<entry.nServers; i++) {
2859 if (!(entry.serverFlags[i] & NEW_REPSITE))
2864 fprintf(STDERR, "The volume %u could not be released to the following %d sites:\n",
2866 for (i=0; i<entry.nServers; i++) {
2867 if (!(entry.serverFlags[i] & NEW_REPSITE)) {
2868 MapPartIdIntoName(entry.serverPartition[i],pname);
2869 fprintf(STDERR,"\t%35s %s\n",
2870 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
2874 MapNetworkToHost(&entry,&storeEntry);
2875 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, LOCKREL_TIMESTAMP);
2876 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2878 ERROREXIT(VOLSERBADRELEASE);
2881 /* All the ROs were release successfully. Remove the temporary clone */
2884 fprintf(STDOUT,"Deleting the releaseClone %u ...", cloneVolId);
2887 code = DelVol (fromconn, cloneVolId, afrompart, ITOffline);
2888 ONERROR (code, cloneVolId, "Failed to delete volume %u.\n");
2893 for (i=0; i<entry.nServers; i++)
2894 entry.serverFlags[i] &= ~NEW_REPSITE;
2896 /* Update the VLDB */
2897 VPRINT("updating VLDB ...");
2899 MapNetworkToHost(&entry, &storeEntry);
2900 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
2901 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2902 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2907 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2910 fprintf (STDERR,"Failed to end cloning transaction on the RW volume %u\n", afromvol);
2911 if (!error) error = code;
2915 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2918 fprintf (STDERR,"Failed to end transaction on the release clone %u\n", cloneVolId);
2919 if (!error) error = code;
2922 for (i=0; i<nservers; i++) {
2923 if (replicas && replicas[i].trans) {
2924 code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
2925 replicas[i].trans = 0;
2927 fprintf(STDERR,"Failed to end transaction on ro volume %u at server 0x%x\n",
2928 entry.volumeId[ROVOL],
2929 hostutil_GetNameByINet(htonl(replicas[i].server.destHost)));
2930 if (!error) error = code;
2933 if (toconns && toconns[i]) {
2934 rx_DestroyConnection(toconns[i]);
2939 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, RWVOL,
2940 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2942 fprintf(STDERR,"Could not release lock on the VLDB entry for volume %u\n", afromvol);
2943 if (!error) error = vcode;
2947 PrintError("", error);
2949 if (fromconn) rx_DestroyConnection(fromconn);
2950 if (results.manyResults_val) free (results.manyResults_val);
2951 if (replicas) free (replicas);
2952 if (toconns) free (toconns);
2953 if (times) free (times);
2958 void dump_sig_handler(int x)
2960 fprintf(STDERR,"\nSignal handler: vos dump operation\n");
2964 /* Dump the volume <afromvol> on <afromserver> and
2965 * <afrompart> to <afilename> starting from <fromdate>.
2966 * DumpFunction does the real work behind the scenes after
2967 * extracting parameters from the rock
2969 int UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2970 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
2972 struct rx_connection *fromconn = (struct rx_connection *)0;
2973 struct rx_call *fromcall = (struct rx_call *)0;
2974 afs_int32 fromtid=0, rxError=0, rcode=0;
2975 afs_int32 code, error = 0;
2977 if (setjmp(env)) ERROR_EXIT(EPIPE);
2978 #ifndef AFS_NT40_ENV
2979 (void) signal(SIGPIPE, dump_sig_handler);
2981 (void) signal(SIGINT, dump_sig_handler);
2985 VPRINT("Full Dump ...\n");
2989 VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
2992 /* get connections to the servers */
2993 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2995 VPRINT1("Starting transaction on volume %u...", afromvol);
2996 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2997 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3000 fromcall = rx_NewCall(fromconn);
3002 VPRINT1("Starting volume dump on volume %u...", afromvol);
3003 code = StartAFSVolDump(fromcall, fromtid, fromdate);
3004 EGOTO(error_exit, code, "Could not start the dump process \n");
3007 VPRINT1("Dumping volume %u...", afromvol);
3008 code = DumpFunction(fromcall, rock);
3009 EGOTO(error_exit, code, "Error while dumping volume \n");
3014 code = rx_EndCall(fromcall, rxError);
3016 fprintf(STDERR,"Error in rx_EndCall\n");
3017 if (!error) error = code;
3021 VPRINT1("Ending transaction on volume %u...", afromvol);
3022 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3023 if (code || rcode) {
3024 fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol);
3025 if (!error) error = (code?code:rcode);
3030 rx_DestroyConnection(fromconn);
3032 PrintError("", error);
3036 /* Clone the volume <afromvol> on <afromserver> and
3037 * <afrompart>, and then dump the clone volume to
3038 * <afilename> starting from <fromdate>.
3039 * DumpFunction does the real work behind the scenes after
3040 * extracting parameters from the rock
3042 int UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
3043 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
3045 struct rx_connection *fromconn = (struct rx_connection *)0;
3046 struct rx_call *fromcall = (struct rx_call *)0;
3047 afs_int32 fromtid=0, rxError=0, rcode=0;
3048 afs_int32 clonetid=0;
3049 afs_int32 code=0, vcode=0, error = 0;
3050 afs_int32 clonevol=0;
3053 if (setjmp(env)) ERROR_EXIT(EPIPE);
3054 #ifndef AFS_NT40_ENV
3055 (void) signal(SIGPIPE, dump_sig_handler);
3057 (void) signal(SIGINT, dump_sig_handler);
3061 VPRINT("Full Dump ...\n");
3065 VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
3068 /* get connections to the servers */
3069 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3071 VPRINT1("Starting transaction on volume %u...", afromvol);
3072 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3073 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3076 /* Get a clone id */
3077 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
3078 code = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &clonevol);
3079 EGOTO1(error_exit, code, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
3082 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
3083 VPRINT2("Cloning source volume %u to clone volume %u...", afromvol, clonevol);
3084 strcpy(vname, "dump-clone-temp");
3085 code = AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
3086 EGOTO1(error_exit, code, "Failed to clone the source volume %u\n", afromvol);
3089 VPRINT1("Ending the transaction on the volume %u ...", afromvol);
3091 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3093 if (!code) code = rcode;
3094 EGOTO1(error_exit, code, "Failed to end the transaction on the volume %u\n", afromvol);
3098 VPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
3099 code = AFSVolTransCreate (fromconn, clonevol, afrompart, ITOffline, &clonetid);
3100 EGOTO1(error_exit, code, "Failed to start a transaction on the cloned volume%u\n", clonevol);
3103 VPRINT1("Setting flags on cloned volume %u ...", clonevol);
3104 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
3105 EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n", clonevol);
3109 fromcall = rx_NewCall(fromconn);
3111 VPRINT1("Starting volume dump from cloned volume %u...", clonevol);
3112 code = StartAFSVolDump(fromcall, clonetid, fromdate);
3113 EGOTO(error_exit, code, "Could not start the dump process \n");
3116 VPRINT1("Dumping volume %u...", afromvol);
3117 code = DumpFunction(fromcall, rock);
3118 EGOTO(error_exit, code, "Error while dumping volume \n");
3122 /* now delete the clone */
3123 VPRINT1("Deleting the cloned volume %u ...", clonevol);
3124 code = AFSVolDeleteVolume(fromconn, clonetid);
3127 fprintf(STDERR,"Failed to delete the cloned volume %u\n", clonevol);
3135 code = rx_EndCall(fromcall, rxError);
3137 fprintf(STDERR,"Error in rx_EndCall\n");
3138 if (!error) error = code;
3142 VPRINT1("Ending transaction on cloned volume %u...", clonevol);
3143 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3144 if (code || rcode) {
3145 fprintf(STDERR,"Could not end transaction on the cloned volume %u\n", clonevol);
3146 if (!error) error = (code?code:rcode);
3151 rx_DestroyConnection(fromconn);
3153 PrintError("", error);
3160 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
3161 * the dump file <afilename>. WriteData does all the real work
3162 * after extracting params from the rock
3164 int UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
3165 char tovolname[], int flags, afs_int32 (*WriteData)(), char *rock)
3167 struct rx_connection *toconn,*tempconn;
3168 struct rx_call *tocall;
3169 afs_int32 totid, code, rcode, vcode,terror = 0;
3170 afs_int32 rxError = 0;
3171 struct volser_status tstatus;
3176 struct nvldbentry entry,storeEntry;
3179 struct restoreCookie cookie;
3181 afs_int32 newDate, volflag, voltype, volsertype;
3182 int index, same, errcode;
3186 memset(&cookie, 0, sizeof(cookie));
3191 tocall = (struct rx_call *)0;
3192 toconn = (struct rx_connection *)0;
3193 tempconn = (struct rx_connection *)0;
3197 if (flags & RV_RDONLY) {
3199 volsertype = volser_RO;
3202 volsertype = volser_RW;
3206 toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
3207 if(pvolid == 0) {/*alot a new id if needed */
3208 vcode = VLDB_GetEntryByName(tovolname, &entry);
3209 if(vcode == VL_NOENT) {
3210 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 1, &pvolid);
3212 fprintf(STDERR,"Could not get an Id for the volume %s\n",tovolname);
3217 } else if (flags & RV_RDONLY) {
3218 if (entry.flags & RW_EXISTS) {
3219 fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
3220 error = VOLSERBADOP;
3223 if (!entry.volumeId[ROVOL]) {
3224 fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
3225 error = VOLSERBADOP;
3228 pvolid = entry.volumeId[ROVOL];
3230 pvolid = entry.volumeId[RWVOL];
3232 }/* at this point we have a volume id to use/reuse for the volume to be restored */
3234 if(strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
3235 EGOTO1(refail, VOLSERBADOP, "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",tovolname);
3237 MapPartIdIntoName(topart, partName);
3238 fprintf(STDOUT,"Restoring volume %s Id %u on server %s partition %s ..", tovolname,
3239 pvolid, hostutil_GetNameByINet(toserver), partName);
3241 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3243 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
3244 VPRINT1("Deleting the previous volume %u ...",pvolid);
3246 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3247 EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3249 code = AFSVolSetFlags(toconn, totid, VTDeleteOnSalvage | VTOutOfService);
3250 EGOTO1(refail, code, "Could not set flags on volume %u \n",pvolid);
3252 code = AFSVolDeleteVolume(toconn,totid);
3253 EGOTO1(refail, code, "Could not delete volume %u\n",pvolid);
3255 code = AFSVolEndTrans(toconn, totid, &rcode);
3257 if (!code) code = rcode;
3258 EGOTO1(refail, code, "Could not end transaction on %u\n",pvolid);
3262 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3263 EGOTO1(refail, code, "Could not create new volume %u\n",pvolid);
3266 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3267 EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3270 cookie.parent = pvolid;
3271 cookie.type = voltype;
3273 strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
3275 tocall = rx_NewCall(toconn);
3276 terror = StartAFSVolRestore(tocall,totid, 1,&cookie);
3278 fprintf(STDERR,"Volume restore Failed \n");
3282 code = WriteData(tocall, rock);
3284 fprintf(STDERR,"Could not transmit data\n");
3288 terror = rx_EndCall(tocall,rxError);
3289 tocall = (struct rx_call *) 0;
3291 fprintf(STDERR,"rx_EndCall Failed \n");
3295 code = AFSVolGetStatus(toconn,totid, &tstatus);
3297 fprintf(STDERR,"Could not get status information about the volume %u\n",pvolid);
3301 code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
3303 fprintf(STDERR,"Could not set the right type and ID on %u\n",pvolid);
3308 code = AFSVolSetDate(toconn,totid, newDate);
3310 fprintf(STDERR,"Could not set the date on %u\n",pvolid);
3315 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
3316 code = AFSVolSetFlags(toconn, totid, volflag);
3318 fprintf(STDERR,"Could not mark %u online\n",pvolid );
3323 /* It isn't handled right in refail */
3324 code = AFSVolEndTrans(toconn, totid, &rcode);
3326 if(!code) code = rcode;
3328 fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
3334 fprintf(STDOUT," done\n");
3336 if (success && (!reuseID || (flags & RV_FULLRST))) {
3337 /* Volume was restored on the file server, update the
3338 * VLDB to reflect the change.
3340 vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
3341 if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
3342 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",pvolid);
3346 if (!vcode) MapHostToNetwork(&entry);
3347 if(vcode == VL_NOENT) { /* it doesnot exist already */
3348 /*make the vldb return this indication specifically*/
3349 VPRINT("------- Creating a new VLDB entry ------- \n");
3350 strcpy(entry.name, tovolname);
3352 entry.serverNumber[0] = toserver;/*should be indirect */
3353 entry.serverPartition[0] = topart;
3354 entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3355 entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3356 if (flags & RV_RDONLY)
3357 entry.volumeId[ROVOL] = pvolid;
3358 else if(tstatus.cloneID != 0){
3359 entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
3362 entry.volumeId[ROVOL] = INVALID_BID;
3363 entry.volumeId[RWVOL] = pvolid;
3365 if(tstatus.backupID != 0){
3366 entry.volumeId[BACKVOL] = tstatus.backupID;
3367 /*this should come from status info on the volume if non zero */
3370 entry.volumeId[BACKVOL] = INVALID_BID;
3371 MapNetworkToHost(&entry,&storeEntry);
3372 vcode = VLDB_CreateEntry(&storeEntry);
3374 fprintf(STDERR,"Could not create the VLDB entry for volume number %u \n",pvolid);
3379 if (verbose) EnumerateEntry(&entry);
3381 else { /*update the existing entry */
3383 fprintf(STDOUT,"Updating the existing VLDB entry\n");
3384 fprintf(STDOUT,"------- Old entry -------\n");
3385 EnumerateEntry(&entry);
3386 fprintf(STDOUT,"------- New entry -------\n");
3388 vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
3390 fprintf(STDERR,"Could not lock the entry for volume number %u \n",pvolid);
3395 strcpy(entry.name, tovolname);
3397 /* Update the vlentry with the new information */
3398 if (flags & RV_RDONLY)
3399 index = Lp_ROMatch(toserver, topart, &entry) - 1;
3401 index = Lp_GetRwIndex(&entry);
3403 /* Add the new site for the volume being restored */
3404 entry.serverNumber[entry.nServers] = toserver;
3405 entry.serverPartition[entry.nServers] = topart;
3406 entry.serverFlags[entry.nServers] =
3407 (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3410 /* This volume should be deleted on the old site
3411 * if its different from new site.
3413 same = VLDB_IsSameAddrs(toserver, entry.serverNumber[index], &errcode);
3414 EPRINT2(errcode, "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
3416 if ( (!errcode && !same) || (entry.serverPartition[index] != topart) ) {
3417 tempconn = UV_Bind(entry.serverNumber[index], AFSCONF_VOLUMEPORT);
3419 MapPartIdIntoName(entry.serverPartition[index], apartName);
3420 VPRINT3("Deleting the previous volume %u on server %s, partition %s ...",
3422 hostutil_GetNameByINet(entry.serverNumber[index]), apartName);
3423 code = AFSVolTransCreate(tempconn, pvolid, entry.serverPartition[index], ITOffline, &temptid);
3425 code = AFSVolSetFlags(tempconn, temptid, VTDeleteOnSalvage | VTOutOfService);
3427 fprintf(STDERR,"Could not set flags on volume %u on the older site\n",pvolid);
3431 code = AFSVolDeleteVolume(tempconn,temptid);
3433 fprintf(STDERR,"Could not delete volume %u on the older site\n",pvolid);
3437 code = AFSVolEndTrans(tempconn, temptid, &rcode);
3439 if(!code) code = rcode;
3441 fprintf(STDERR,"Could not end transaction on volume %u on the older site\n",pvolid);
3446 MapPartIdIntoName(entry.serverPartition[index],partName);
3449 entry.serverNumber[index] = toserver;
3450 entry.serverPartition[index] = topart;
3453 entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3454 MapNetworkToHost(&entry,&storeEntry);
3455 vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3457 fprintf(STDERR,"Could not update the entry for volume number %u \n",pvolid);
3462 if(verbose) EnumerateEntry(&entry);
3469 code = rx_EndCall(tocall, rxError);
3470 if (!error) error = code;
3473 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3475 fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %u\n",pvolid);
3476 if(!error) error = vcode;
3480 code = AFSVolEndTrans(toconn, totid, &rcode);
3481 if(!code) code = rcode;
3483 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
3484 if(!error) error = code;
3488 code = AFSVolEndTrans(toconn, temptid, &rcode);
3489 if(!code) code = rcode;
3491 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
3492 if(!error) error = code;
3495 if(tempconn) rx_DestroyConnection(tempconn);
3496 if(toconn) rx_DestroyConnection(toconn);
3497 PrintError("",error);
3502 /*unlocks the vldb entry associated with <volid> */
3503 int UV_LockRelease(afs_int32 volid)
3509 VPRINT("Binding to the VLDB server\n");
3510 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,volid,-1,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3512 fprintf(STDERR,"Could not unlock the entry for volume number %u in VLDB \n",volid);
3513 PrintError("",vcode);
3516 VPRINT("VLDB updated\n");
3521 /*adds <server> and <part> as a readonly replication site for <volid>
3523 int UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3525 int j, nro=0, islocked=0;
3526 struct nvldbentry entry,storeEntry;
3527 afs_int32 vcode, error=0;
3530 error = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3532 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n", volid);
3537 error = VLDB_GetEntryByID(volid,RWVOL, &entry);
3539 fprintf(STDERR,"Could not fetch the VLDB entry for volume number %u \n",volid);
3543 if (!ISNAMEVALID(entry.name)){
3544 fprintf(STDERR,"Volume name %s is too long, rename before adding site\n", entry.name);
3545 error = VOLSERBADOP;
3548 MapHostToNetwork(&entry);
3550 /* See if it's too many entries */
3551 if (entry.nServers >= NMAXNSERVERS){
3552 fprintf(STDERR,"Total number of entries will exceed %u\n", NMAXNSERVERS);
3553 error = VOLSERBADOP;
3557 /* See if it's on the same server */
3558 for (j=0; j < entry.nServers; j++) {
3559 if (entry.serverFlags[j] & ITSROVOL) {
3561 if (VLDB_IsSameAddrs(server, entry.serverNumber[j], &error)) {
3563 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
3566 MapPartIdIntoName(entry.serverPartition[j], apartName);
3567 fprintf(STDERR,"RO already exists on partition %s. Multiple ROs on a single server aren't allowed\n", apartName);
3568 error = VOLSERBADOP;
3575 /* See if it's too many RO sites - leave one for the RW */
3576 if (nro >= NMAXNSERVERS-1){
3577 fprintf(STDERR,"Total number of sites will exceed %u\n", NMAXNSERVERS-1);
3578 error = VOLSERBADOP;
3582 VPRINT("Adding a new site ...");
3583 entry.serverNumber[entry.nServers] = server;
3584 entry.serverPartition[entry.nServers] = part;
3585 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
3588 MapNetworkToHost(&entry,&storeEntry);
3589 error = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3591 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3599 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3601 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3602 PrintError("", vcode);
3606 PrintError("", error);
3610 /*removes <server> <part> as read only site for <volid> from the vldb */
3611 int UV_RemoveSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3614 struct nvldbentry entry,storeEntry;
3617 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3619 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3620 PrintError("",vcode);
3624 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3626 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3627 PrintError("",vcode);
3630 MapHostToNetwork(&entry);
3631 if(!Lp_ROMatch(server, part, &entry)){
3632 /*this site doesnot exist */
3633 fprintf(STDERR,"This site is not a replication site \n");
3634 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3636 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3637 PrintError("",vcode);
3638 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3643 else { /*remove the rep site */
3644 Lp_SetROValue(&entry, server, part, 0, 0);
3646 if((entry.nServers == 1) && (entry.flags & RW_EXISTS))
3647 entry.flags &= ~RO_EXISTS;
3648 if(entry.nServers < 1) { /*this is the last ref */
3649 VPRINT1("Deleting the VLDB entry for %u ...",volid);
3651 vcode = ubik_Call(VL_DeleteEntry,cstruct, 0,volid, ROVOL);
3653 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",volid);
3654 PrintError("",vcode);
3659 MapNetworkToHost(&entry,&storeEntry);
3660 fprintf(STDOUT,"Deleting the replication site for volume %u ...",volid);
3662 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3664 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3665 PrintError("",vcode);
3666 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3674 /*sets <server> <part> as read/write site for <volid> in the vldb */
3675 int UV_ChangeLocation(afs_int32 server, afs_int32 part, afs_int32 volid)
3678 struct nvldbentry entry,storeEntry;
3681 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3683 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3684 PrintError("",vcode);
3687 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3689 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3690 PrintError("",vcode);
3693 MapHostToNetwork(&entry);
3694 index = Lp_GetRwIndex(&entry);
3696 /* no RW site exists */
3697 fprintf(STDERR,"No existing RW site for volume %u", volid);
3698 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3700 fprintf(STDERR,"Could not release lock on entry for volume %u \n",volid);
3701 PrintError("",vcode);
3706 else { /* change the RW site */
3707 entry.serverNumber[index] = server;
3708 entry.serverPartition[index] = part;
3709 MapNetworkToHost(&entry,&storeEntry);
3710 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3712 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3713 PrintError("",vcode);
3714 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3722 /*list all the partitions on <aserver> */
3723 int UV_ListPartitions(afs_int32 aserver, struct partList *ptrPartList, afs_int32 *cntp)
3725 struct rx_connection *aconn;
3726 struct pIDs partIds;
3727 struct partEntries partEnts;
3728 register int i, j=0, code;
3731 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3733 partEnts.partEntries_len = 0;
3734 partEnts.partEntries_val = NULL;
3735 code = AFSVolXListPartitions(aconn, &partEnts); /* this is available only on new servers */
3736 if (code == RXGEN_OPCODE)
3738 for(i = 0; i < 26; i++) /* try old interface */
3739 partIds.partIds[i] = -1;
3740 code = AFSVolListPartitions(aconn, &partIds);
3742 for (i = 0;i < 26; i++) {
3743 if((partIds.partIds[i]) != -1) {
3744 ptrPartList->partId[j] = partIds.partIds[i];
3745 ptrPartList->partFlags[j] = PARTVALID;
3748 ptrPartList->partFlags[i] = 0;
3755 *cntp = partEnts.partEntries_len;
3756 if (*cntp > VOLMAXPARTS) {
3757 fprintf(STDERR,"Warning: number of partitions on the server too high %d (process only %d)\n",
3758 *cntp, VOLMAXPARTS);
3759 *cntp = VOLMAXPARTS;
3761 for (i = 0;i < *cntp; i++) {
3762 ptrPartList->partId[i] = partEnts.partEntries_val[i];
3763 ptrPartList->partFlags[i] = PARTVALID;
3765 free(partEnts.partEntries_val);
3769 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
3770 PrintError("",code);
3771 if(aconn) rx_DestroyConnection(aconn);
3776 /*zap the list of volumes specified by volPtrArray (the volCloneId field).
3777 This is used by the backup system */
3778 int UV_ZapVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3780 struct rx_connection *aconn;
3781 struct volDescription *curPtr;
3784 afs_int32 rcode = 0;
3785 afs_int32 success = 1;
3788 aconn = (struct rx_connection *)0;
3789 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3791 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3792 if(curPtr->volFlags & CLONEVALID) {
3793 curPtr->volFlags &= ~CLONEZAPPED;
3795 code = AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline, &tid);
3796 if(code) success = 0;
3798 code = AFSVolDeleteVolume(aconn, tid);
3799 if(code) success = 0;
3800 code = AFSVolEndTrans(aconn, tid, &rcode);
3801 if(code || rcode) success = 0;
3803 if(success) curPtr->volFlags |= CLONEZAPPED;
3804 if(!success) fprintf(STDERR,"Could not zap volume %u\n",curPtr->volCloneId);
3805 if(success) VPRINT2("Clone of %s %u deleted\n", curPtr->volName,curPtr->volCloneId);
3810 if(aconn)rx_DestroyConnection(aconn);
3814 /*return a list of clones of the volumes specified by volPtrArray. Used by the
3816 int UV_GenerateVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3818 struct rx_connection *aconn;
3819 struct volDescription *curPtr;
3822 afs_int32 rcode = 0;
3824 int reuseCloneId = 0;
3825 afs_int32 curCloneId = 0;
3826 char cloneName[256];/*max vol name */
3828 aconn = (struct rx_connection *)0;
3829 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3831 if((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
3833 else { /*get a bunch of id's from vldb */
3834 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, arraySize, &curCloneId);
3836 fprintf(STDERR,"Could not get ID's for the clone from VLDB\n");
3837 PrintError("",code);
3842 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3843 if(curPtr->volFlags & ENTRYVALID) {
3845 curPtr->volFlags |= CLONEVALID;
3846 /*make a clone of curParentId and record as curPtr->volCloneId */
3847 code = AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline, &tid);
3848 if(code) VPRINT2("Clone for volume %s %u failed \n",curPtr->volName,curPtr->volId);
3850 curPtr->volFlags &= ~CLONEVALID; /*cant clone */
3854 if(strlen(curPtr->volName) < (VOLSER_OLDMAXVOLNAME - 9) ){
3855 strcpy(cloneName, curPtr->volName);
3856 strcat(cloneName,"-tmpClone-");
3858 else strcpy(cloneName,"-tmpClone");
3860 curPtr->volCloneId = curCloneId;
3864 code = AFSVolClone(aconn, tid, 0, readonlyVolume, cloneName,&(curPtr->volCloneId));
3866 curPtr->volFlags &= ~CLONEVALID;
3868 fprintf(STDERR,"Could not clone %s due to error %u\n", curPtr->volName,code);
3869 code=AFSVolEndTrans(aconn, tid, &rcode);
3871 fprintf(STDERR,"WARNING: could not end transaction\n");
3874 VPRINT2("********** Cloned %s temporary %u\n",cloneName,curPtr->volCloneId);
3875 code = AFSVolEndTrans(aconn, tid, &rcode);
3877 curPtr->volFlags &= ~CLONEVALID;
3885 if (aconn) rx_DestroyConnection(aconn);
3890 /*list all the volumes on <aserver> and <apart>. If all = 1, then all the
3891 * relevant fields of the volume are also returned. This is a heavy weight operation.*/
3892 int UV_ListVolumes(afs_int32 aserver, afs_int32 apart, int all, struct volintInfo **resultPtr, afs_int32 *size)
3894 struct rx_connection *aconn;
3896 volEntries volumeInfo;
3900 *resultPtr = (volintInfo *)0;
3901 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3902 volumeInfo.volEntries_len = 0;
3904 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3905 code = AFSVolListVolumes(aconn, apart, all, &volumeInfo);
3907 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
3910 *resultPtr = volumeInfo.volEntries_val;
3911 *size = volumeInfo.volEntries_len;
3914 if(aconn) rx_DestroyConnection(aconn);
3915 PrintError("",code);
3919 /*------------------------------------------------------------------------
3920 * EXPORTED UV_XListVolumes
3923 * List the extended information for all the volumes on a particular
3924 * File Server and partition. We may either return the volume's ID
3925 * or all of its extended information.
3928 * a_serverID : Address of the File Server for which we want
3929 * extended volume info.
3930 * a_partID : Partition for which we want the extended
3932 * a_all : If non-zero, fetch ALL the volume info,
3933 * otherwise just the volume ID.
3934 * a_resultPP : Ptr to the address of the area containing
3935 * the returned volume info.
3936 * a_numEntsInResultP : Ptr for the value we set for the number of
3941 * Otherise, the return value of AFSVolXListVolumes.
3944 * This routine is closely related to UV_ListVolumes, which returns
3945 * only the standard level of detail on AFS volumes. It is a
3946 * heavyweight operation, zipping through all the volume entries for
3947 * a given server/partition.
3951 *------------------------------------------------------------------------*/
3953 int UV_XListVolumes(afs_int32 a_serverID, afs_int32 a_partID, int a_all,
3954 struct volintXInfo **a_resultPP, afs_int32 *a_numEntsInResultP)
3956 struct rx_connection *rxConnP; /*Ptr to the Rx connection involved*/
3957 afs_int32 code; /*Error code to return*/
3958 volXEntries volumeXInfo; /*Area for returned extended vol info*/
3961 * Set up our error code and the area for returned extended volume info.
3962 * We set the val field to a null pointer as a hint for the stub to
3966 *a_numEntsInResultP = 0;
3967 *a_resultPP = (volintXInfo *)0;
3968 volumeXInfo.volXEntries_val = (volintXInfo *)0;
3969 volumeXInfo.volXEntries_len = 0;
3972 * Bind to the Volume Server port on the File Server machine in question,
3975 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
3976 code = AFSVolXListVolumes(rxConnP, a_partID, a_all, &volumeXInfo);
3979 "[UV_XListVolumes] Couldn't fetch volume list\n");
3982 * We got the info; pull out the pointer to where the results lie
3983 * and how many entries are there.
3985 *a_resultPP = volumeXInfo.volXEntries_val;
3986 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
3990 * If we got an Rx connection, throw it away.
3993 rx_DestroyConnection(rxConnP);
3995 PrintError("", code);
3997 } /*UV_XListVolumes*/
3999 /* get all the information about volume <volid> on <aserver> and <apart> */
4000 int UV_ListOneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 volid, struct volintInfo **resultPtr)
4002 struct rx_connection *aconn;
4004 volEntries volumeInfo;
4008 *resultPtr = (volintInfo *)0;
4009 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
4010 volumeInfo.volEntries_len = 0;
4012 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4013 code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
4015 fprintf(STDERR,"Could not fetch the information about volume %u from the server\n",volid);
4018 *resultPtr = volumeInfo.volEntries_val;
4022 if(aconn) rx_DestroyConnection(aconn);
4023 PrintError("",code);
4027 /*------------------------------------------------------------------------
4028 * EXPORTED UV_XListOneVolume
4031 * List the extended information for a volume on a particular File
4032 * Server and partition.
4035 * a_serverID : Address of the File Server for which we want
4036 * extended volume info.
4037 * a_partID : Partition for which we want the extended
4039 * a_volID : Volume ID for which we want the info.
4040 * a_resultPP : Ptr to the address of the area containing
4041 * the returned volume info.
4045 * Otherise, the return value of AFSVolXListOneVolume.
4048 * This routine is closely related to UV_ListOneVolume, which returns
4049 * only the standard level of detail on the chosen AFS volume.
4053 *------------------------------------------------------------------------*/
4055 int UV_XListOneVolume(afs_int32 a_serverID, afs_int32 a_partID,
4056 afs_int32 a_volID, struct volintXInfo **a_resultPP)
4058 struct rx_connection *rxConnP; /*Rx connection to Volume Server*/
4059 afs_int32 code; /*Error code*/
4060 volXEntries volumeXInfo; /*Area for returned info*/
4063 * Set up our error code, and the area we're in which we are returning
4064 * the info. Setting the val field to a null pointer tells the stub
4065 * to allocate space for us.
4068 *a_resultPP = (volintXInfo *)0;
4069 volumeXInfo.volXEntries_val = (volintXInfo *)0;
4070 volumeXInfo.volXEntries_len = 0;
4073 * Bind to the Volume Server port on the File Server machine in question,
4076 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
4077 code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
4080 "[UV_XListOneVolume] Couldn't fetch the volume information\n");
4083 * We got the info; pull out the pointer to where the results lie.
4085 *a_resultPP = volumeXInfo.volXEntries_val;
4088 * If we got an Rx connection, throw it away.
4091 rx_DestroyConnection(rxConnP);
4093 PrintError("",code);
4098 * Given a volume we read from a partition, check if it is
4099 * represented in the VLDB correctly.
4101 * The VLDB is looked up by the RW volume id (not its name).
4102 * The RW contains the true name of the volume (BK and RO set
4103 * the name in the VLDB only on creation of the VLDB entry).
4104 * We want rules strict enough that when we check all volumes
4105 * on one partition, it does not need to be done again. IE:
4106 * two volumes on different partitions won't constantly
4107 * change a VLDB entry away from what the other set.
4108 * For RW and BK volumes, we will always check the VLDB to see
4109 * if the two exist on the server/partition. May seem redundant,
4110 * but this is an easy check of the VLDB. IE: if the VLDB entry
4111 * says the BK exists but no BK volume is there, we will detect
4112 * this when we check the RW volume.
4113 * VLDB entries are locked only when a change needs to be done.
4114 * Output changed to look a lot like the "vos syncserv" otuput.
4116 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart,
4117 afs_int32 *modentry, afs_uint32 *maxvolid)
4120 afs_int32 code, error = 0;
4121 struct nvldbentry entry, storeEntry;
4123 int pass=0, islocked=0, createentry, addvolume, modified, mod;
4126 if (modentry) *modentry = 0;
4127 rwvolid = ((volumeinfo->type == RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
4130 /* Check to see if the VLDB is ok without locking it (pass 1).
4131 * If it will change, then lock the VLDB entry, read it again,
4132 * then make the changes to it (pass 2).
4135 code = ubik_Call(VL_SetLock, cstruct, 0, rwvolid, RWVOL, VLOP_DELETE);
4137 fprintf(STDERR, "Could not lock VLDB entry for %u\n", rwvolid);
4143 createentry = 0; /* Do we need to create a VLDB entry */
4144 addvolume = 0; /* Add this volume to the VLDB entry */
4145 modified = 0; /* The VLDB entry was modified */
4147 /* Read the entry from VLDB by its RW volume id */
4148 code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
4150 if (code != VL_NOENT) {
4151 fprintf(STDOUT,"Could not retreive the VLDB entry for volume %u \n", rwvolid);
4155 memset(&entry, 0, sizeof(entry));
4156 vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
4160 MapHostToNetwork(&entry);
4163 if (verbose && (pass == 1)) {
4164 fprintf(STDOUT,"_______________________________\n");
4165 fprintf(STDOUT,"\n-- status before -- \n");
4167 fprintf(STDOUT,"\n**does not exist**\n");
4169 if ((entry.flags & RW_EXISTS) ||
4170 (entry.flags & RO_EXISTS) ||
4171 (entry.flags & BACK_EXISTS))
4172 EnumerateEntry(&entry);
4174 fprintf(STDOUT,"\n");
4177 if (volumeinfo->type == RWVOL) { /* RW volume exists */
4183 /* Check existence of RW and BK volumes */
4184 code = CheckVldbRWBK(&entry, &mod);
4185 if (code) ERROR_EXIT(code);
4186 if (mod) modified++;
4188 idx = Lp_GetRwIndex(&entry);
4189 if (idx == -1) { /* RW index not found in the VLDB entry */
4190 idx = entry.nServers; /* put it into next index */
4193 } else { /* RW index found in the VLDB entry. */
4194 /* Verify if this volume's location matches where the VLDB says it is */
4195 if (!Lp_Match(aserver, apart, &entry)) {
4196 if (entry.flags & RW_EXISTS) {
4197 /* The RW volume exists elsewhere - report this one a duplicate */
4199 MapPartIdIntoName(apart, pname);
4200 fprintf(STDERR,"*** Warning: Orphaned RW volume %u exists on %s %s\n",
4201 rwvolid, hostutil_GetNameByINet(aserver), pname);
4202 MapPartIdIntoName(entry.serverPartition[idx], pname);
4203 fprintf(STDERR," VLDB reports RW volume %u exists on %s %s\n",
4205 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
4208 /* The RW volume does not exist - have VLDB point to this one */
4211 /* Check for orphaned BK volume on old partition */
4212 if (entry.flags & BACK_EXISTS) {
4214 MapPartIdIntoName(entry.serverPartition[idx], pname);
4215 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
4216 entry.volumeId[BACKVOL],
4217 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
4218 MapPartIdIntoName(apart, pname);
4219 fprintf(STDERR," VLDB reports its RW volume %u exists on %s %s\n",
4220 rwvolid, hostutil_GetNameByINet(aserver), pname);
4225 /* Volume location matches the VLDB location */
4226 if ( (volumeinfo->backupID && !entry.volumeId[BACKVOL]) ||
4227 (volumeinfo->cloneID && !entry.volumeId[ROVOL]) ||
4228 (strncmp(entry.name,volumeinfo->name,VOLSER_OLDMAXVOLNAME) != 0) ) {
4236 entry.flags |= RW_EXISTS;
4237 entry.volumeId[RWVOL] = rwvolid;
4238 if (!entry.volumeId[BACKVOL])
4239 entry.volumeId[BACKVOL] = volumeinfo->backupID;
4240 if (!entry.volumeId[ROVOL])
4241 entry.volumeId[ROVOL] = volumeinfo->cloneID;
4243 entry.serverFlags[idx] = ITSRWVOL;
4244 entry.serverNumber[idx] = aserver;
4245 entry.serverPartition[idx] = apart;
4246 strncpy(entry.name, volumeinfo->name, VOLSER_OLDMAXVOLNAME);
4250 /* One last check - to update BK if need to */
4251 code = CheckVldbRWBK(&entry, &mod);
4252 if (code) ERROR_EXIT(code);
4253 if (mod) modified++;
4257 else if (volumeinfo->type == BACKVOL) { /* A BK volume */
4263 /* Check existence of RW and BK volumes */
4264 code = CheckVldbRWBK(&entry, &mod);
4265 if (code) ERROR_EXIT(code);
4266 if (mod) modified++;
4268 idx = Lp_GetRwIndex(&entry);
4269 if (idx == -1) { /* RW index not found in the VLDB entry */
4270 idx = entry.nServers; /* Put it into next index */
4273 } else { /* RW index found in the VLDB entry */
4274 /* Verify if this volume's location matches where the VLDB says it is */
4275 if (!Lp_Match(aserver, apart, &entry)) {
4276 /* VLDB says RW and/or BK is elsewhere - report this BK volume orphaned */
4278 MapPartIdIntoName(apart, pname);
4279 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
4280 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
4281 MapPartIdIntoName(entry.serverPartition[idx], pname);
4282 fprintf(STDERR," VLDB reports its RW/BK volume %u exists on %s %s\n",
4284 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
4287 if (volumeinfo->volid != entry.volumeId[BACKVOL]) {
4288 if (!(entry.flags & BACK_EXISTS)) {
4291 else if (volumeinfo->volid > entry.volumeId[BACKVOL]) {
4295 MapPartIdIntoName(entry.serverPartition[idx], pname);
4296 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
4297 entry.volumeId[BACKVOL], hostutil_GetNameByINet(aserver), pname);
4298 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
4303 MapPartIdIntoName(entry.serverPartition[idx], pname);
4304 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
4305 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
4306 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
4307 entry.volumeId[BACKVOL]);
4311 else if (!entry.volumeId[BACKVOL]) {
4318 entry.flags |= BACK_EXISTS;
4319 entry.volumeId[RWVOL] = rwvolid;
4320 entry.volumeId[BACKVOL] = volumeinfo->volid;
4322 entry.serverNumber[idx] = aserver;
4323 entry.serverPartition[idx] = apart;
4324 entry.serverFlags[idx] = ITSRWVOL;
4330 else if (volumeinfo->type == ROVOL) { /* A RO volume */
4331 if (volumeinfo->volid == entry.volumeId[ROVOL]) {
4332 /* This is a quick check to see if the RO entry exists in the
4333 * VLDB so we avoid the CheckVldbRO() call (which checks if each
4334 * RO volume listed in the VLDB exists).
4336 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
4338 idx = entry.nServers;
4342 if (!(entry.flags & RO_EXISTS)) {
4347 /* Before we correct the VLDB entry, make sure all the
4348 * ROs listed in the VLDB exist.
4350 code = CheckVldbRO(&entry, &mod);
4351 if (code) ERROR_EXIT(code);
4352 if (mod) modified++;
4354 if (!(entry.flags & RO_EXISTS)) {
4355 /* No RO exists in the VLDB entry - add this one */
4356 idx = entry.nServers;
4360 else if (volumeinfo->volid > entry.volumeId[ROVOL]) {
4361 /* The volume headers's RO ID does not match that in the VLDB entry,
4362 * and the vol hdr's ID is greater (implies more recent). So delete
4363 * all the RO volumes listed in VLDB entry and add this volume.
4365 for (j=0; j<entry.nServers; j++) {
4366 if (entry.serverFlags[j] & ITSROVOL) {
4367 /* Verify this volume exists and print message we are orphaning it */
4369 MapPartIdIntoName(apart, pname);
4370 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
4371 entry.volumeId[ROVOL],
4372 hostutil_GetNameByINet(entry.serverNumber[j]), pname);
4373 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
4377 Lp_SetRWValue(entry, entry.serverNumber[idx],
4378 entry.serverPartition[idx], 0L, 0L);
4385 idx = entry.nServers;
4389 else if (volumeinfo->volid < entry.volumeId[ROVOL]) {
4390 /* The volume headers's RO ID does not match that in the VLDB entry,
4391 * and the vol hdr's ID is lower (implies its older). So orphan it.
4394 MapPartIdIntoName(apart, pname);
4395 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
4396 volumeinfo->volid, hostutil_GetNameByINet(aserver), pname);
4397 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
4398 entry.volumeId[ROVOL]);
4402 /* The RO volume ID in the volume header match that in the VLDB entry,
4403 * and there exist RO volumes in the VLDB entry. See if any of them
4404 * are this one. If not, then we add it.
4406 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
4408 idx = entry.nServers;
4416 entry.flags |= RO_EXISTS;
4417 entry.volumeId[RWVOL] = rwvolid;
4418 entry.volumeId[ROVOL] = volumeinfo->volid;
4420 entry.serverNumber[idx] = aserver;
4421 entry.serverPartition[idx] = apart;
4422 entry.serverFlags[idx] = ITSROVOL;
4428 /* Remember largest volume id */
4429 if (entry.volumeId[ROVOL] > *maxvolid) *maxvolid = entry.volumeId[ROVOL];
4430 if (entry.volumeId[BACKVOL] > *maxvolid) *maxvolid = entry.volumeId[BACKVOL];
4431 if (entry.volumeId[RWVOL] > *maxvolid) *maxvolid = entry.volumeId[RWVOL];
4434 MapNetworkToHost(&entry, &storeEntry);
4437 code = VLDB_CreateEntry(&storeEntry);
4439 fprintf(STDOUT,"Could not create a VLDB entry for the volume %u\n", rwvolid);
4444 if (pass == 1) goto retry;
4445 code = VLDB_ReplaceEntry(rwvolid, RWVOL, &storeEntry,
4446 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4448 fprintf(STDERR,"Could not update entry for %u\n", rwvolid);
4452 if (modentry) *modentry = modified;
4453 } else if (pass == 2) {
4454 code = ubik_Call(VL_ReleaseLock,cstruct, 0, rwvolid, RWVOL,
4455 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4457 PrintError("Could not unlock VLDB entry ", code);
4462 fprintf(STDOUT,"-- status after --\n");
4464 EnumerateEntry(&entry);
4466 fprintf(STDOUT,"\n**no change**\n");
4470 VPRINT("\n_______________________________\n");
4474 int sortVolumes(const void *a, const void *b)
4476 volintInfo *v1 = (volintInfo *)a;
4477 volintInfo *v2 = (volintInfo *)b;
4478 afs_int32 rwvolid1, rwvolid2;
4480 rwvolid1 = ((v1->type == RWVOL) ? v1->volid : v1->parentID);
4481 rwvolid2 = ((v2->type == RWVOL) ? v2->volid : v2->parentID);
4483 if (rwvolid1 > rwvolid2) return -1; /* lower RW id goes first */
4484 if (rwvolid1 < rwvolid2) return 1;
4486 if (v1->type == RWVOL) return -1; /* RW vols go first */
4487 if (v2->type == RWVOL) return 1;
4489 if ((v1->type == BACKVOL) && (v2->type == ROVOL )) return -1; /* BK vols next */
4490 if ((v1->type == ROVOL ) && (v2->type == BACKVOL)) return 1;
4492 if (v1->volid < v2->volid) return 1; /* larger volids first */
4493 if (v1->volid > v2->volid) return -1;
4498 * Synchronise <aserver> <apart>(if flags = 1) <avolid>.
4499 * Synchronize an individual volume against a sever and partition.
4500 * Checks the VLDB entry (similar to syncserv) as well as checks
4501 * if the volume exists on specified servers (similar to syncvldb).
4503 int UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
4505 struct rx_connection *aconn = 0;
4506 afs_int32 j, k, code, vcode, error = 0;
4507 afs_int32 tverbose, mod, modified = 0;
4508 struct nvldbentry vldbentry;
4509 afs_int32 volumeid = 0;
4510 volEntries volumeInfo;
4511 struct partList PartList;
4513 afs_int32 maxvolid = 0;
4515 volumeInfo.volEntries_val = (volintInfo *)0;
4516 volumeInfo.volEntries_len = 0;
4518 if (!aserver && flags) {
4519 /* fprintf(STDERR,"Partition option requires a server option\n"); */
4523 /* Turn verbose logging off and do our own verbose logging */
4527 /* Read the VLDB entry */
4528 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
4529 if (vcode && (vcode != VL_NOENT)) {
4530 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4532 } else if (!vcode) {
4533 MapHostToNetwork(&vldbentry);
4537 fprintf(STDOUT,"Processing VLDB entry %s ...\n", avolname);
4538 fprintf(STDOUT,"_______________________________\n");
4539 fprintf(STDOUT,"\n-- status before -- \n");
4541 fprintf(STDOUT,"\n**does not exist**\n");
4543 if ((vldbentry.flags & RW_EXISTS) ||
4544 (vldbentry.flags & RO_EXISTS) ||
4545 (vldbentry.flags & BACK_EXISTS))
4546 EnumerateEntry(&vldbentry);
4548 fprintf(STDOUT,"\n");
4551 /* Verify that all of the VLDB entries exist on the repective servers
4552 * and partitions (this does not require that avolname be a volume ID).
4553 * Equivalent to a syncserv.
4556 code = CheckVldb(&vldbentry, &mod);
4558 fprintf(STDERR,"Could not process VLDB entry for volume %s\n", vldbentry.name);
4561 if (mod) modified++;
4564 /* If aserver is given, we will search for the desired volume on it */
4566 /* Generate array of partitions on the server that we will check */
4568 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4570 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4574 PartList.partId[0] = apart;
4578 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4580 /* If a volume ID were given, search for it on each partition */
4581 if ((volumeid = atol(avolname))) {
4582 for (j=0; j<pcnt; j++) {
4583 code = AFSVolListOneVolume(aconn, PartList.partId[j], volumeid, &volumeInfo);
4585 if (code != ENODEV) {
4586 fprintf(STDERR,"Could not query server\n");
4590 /* Found one, sync it with VLDB entry */
4591 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4592 PartList.partId[j], &mod, &maxvolid);
4593 if (code) ERROR_EXIT(code);
4594 if (mod) modified++;
4597 if (volumeInfo.volEntries_val)
4598 free(volumeInfo.volEntries_val);
4599 volumeInfo.volEntries_val = (volintInfo *)0;
4600 volumeInfo.volEntries_len = 0;
4604 /* Check to see if the RW, BK, and RO IDs exist on any
4605 * partitions. We get the volume IDs from the VLDB.
4607 rv = 1; /* Read the VLDB entry ? */
4608 for (j=0; j<MAXTYPES; j++) { /* for RW, RO, and BK IDs */
4610 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
4612 if (vcode == VL_NOENT) break;
4613 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4619 if (vldbentry.volumeId[j] == 0) continue;
4621 for (k=0; k<pcnt; k++) { /* For each partition */
4622 volumeInfo.volEntries_val = (volintInfo *)0;
4623 volumeInfo.volEntries_len = 0;
4624 code = AFSVolListOneVolume(aconn, PartList.partId[k],
4625 vldbentry.volumeId[j], &volumeInfo);
4627 if (code != ENODEV) {
4628 fprintf(STDERR,"Could not query server\n");
4632 /* Found one, sync it with VLDB entry */
4633 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4634 PartList.partId[k], &mod, &maxvolid);
4635 if (code) ERROR_EXIT(code);
4636 if (mod) modified++, rv++;
4639 if (volumeInfo.volEntries_val)
4640 free(volumeInfo.volEntries_val);
4641 volumeInfo.volEntries_val = (volintInfo *)0;
4642 volumeInfo.volEntries_len = 0;
4645 } /* if (aserver) */
4647 /* If verbose output, print a summary of what changed */
4649 fprintf(STDOUT,"-- status after --\n");
4650 code = VLDB_GetEntryByName(avolname, &vldbentry);
4651 if (code && (code != VL_NOENT)) {
4652 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4655 if (modified && (code == VL_NOENT)) {
4656 fprintf(STDOUT,"\n**entry deleted**\n");
4657 } else if (modified) {
4658 EnumerateEntry(&vldbentry);
4660 fprintf(STDOUT,"\n**no change**\n");
4662 fprintf(STDOUT,"\n_______________________________\n");
4666 /* Now check if the maxvolid is larger than that stored in the VLDB */
4668 afs_int32 maxvldbid = 0;
4669 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4671 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4672 if (!error) error = code;
4673 } else if (maxvolid > maxvldbid) {
4675 id = maxvolid - maxvldbid + 1;
4676 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4678 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4679 if (!error) error = code;
4686 if (error) fprintf(STDOUT,"...error encountered");
4687 else fprintf(STDOUT,"...done entry\n");
4689 if (aconn) rx_DestroyConnection(aconn);
4690 if (volumeInfo.volEntries_val) free(volumeInfo.volEntries_val);
4692 PrintError("",error);
4697 * Synchronise vldb with the file server <aserver> and,
4698 * optionally, <apart>.
4700 int UV_SyncVldb(afs_int32 aserver, afs_int32 apart, int flags, int force)
4702 struct rx_connection *aconn;
4703 afs_int32 code, error=0;
4705 volEntries volumeInfo;
4706 struct partList PartList;
4710 afs_int32 failures = 0, modifications = 0, tentries = 0;
4712 afs_uint32 maxvolid = 0;
4714 volumeInfo.volEntries_val = (volintInfo *)0;
4715 volumeInfo.volEntries_len = 0;
4717 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4719 /* Generate array of partitions to check */
4721 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4723 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4727 PartList.partId[0] = apart;
4731 VPRINT("Processing volume entries ...\n");
4733 /* Step through the array of partitions */
4734 for (i = 0; i < pcnt; i++) {
4735 apart = PartList.partId[i];
4736 MapPartIdIntoName(apart, pname);
4738 volumeInfo.volEntries_val = (volintInfo *)0;
4739 volumeInfo.volEntries_len = 0;
4740 code = AFSVolListVolumes(aconn, apart, 1, &volumeInfo);
4742 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
4746 /* May want to sort the entries: RW, BK (high to low), RO (high to low) */
4747 qsort((char *)volumeInfo.volEntries_val, volumeInfo.volEntries_len,
4748 sizeof(volintInfo), sortVolumes);
4751 for (vi=volumeInfo.volEntries_val, j=0; j < volumeInfo.volEntries_len; j++, vi++) {
4758 fprintf(STDOUT,"Processing volume entry %d: %s (%u) on server %s %s...\n",
4759 j+1, vi->name, vi->volid,
4760 hostutil_GetNameByINet(aserver), pname);
4764 code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
4766 PrintError("",code);
4770 else if (modified) {
4776 fprintf(STDOUT,"...error encountered\n\n");
4778 fprintf(STDOUT,"...done entry %d\n\n", j+1);
4784 fprintf(STDERR,"Could not process entries on server %s partition %s\n",
4785 hostutil_GetNameByINet(aserver), pname);
4787 if (volumeInfo.volEntries_val) {
4788 free(volumeInfo.volEntries_val);
4789 volumeInfo.volEntries_val = 0;
4792 }/* thru all partitions */
4794 VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n",
4795 tentries, failures, modifications);
4798 /* Now check if the maxvolid is larger than that stored in the VLDB */
4800 afs_uint32 maxvldbid = 0;
4801 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4803 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4804 if (!error) error = code;
4805 } else if (maxvolid > maxvldbid) {
4807 id = maxvolid - maxvldbid + 1;
4808 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4810 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4811 if (!error) error = code;
4816 if (aconn) rx_DestroyConnection(aconn);
4817 if (volumeInfo.volEntries_val)
4818 free(volumeInfo.volEntries_val);
4819 PrintError("",error);
4824 * Determine if a volume exists on a server and partition.
4825 * Try creating a transaction on the volume. If we can,
4826 * the volume exists, if not, then return the error code.
4827 * Some error codes mean the volume is unavailable but
4828 * still exists - so we catch these error codes.
4830 afs_int32 VolumeExists(afs_int32 server, afs_int32 partition, afs_int32 volumeid)
4832 struct rx_connection *conn=(struct rx_connection *)0;
4833 afs_int32 code = -1;
4834 volEntries volumeInfo;
4836 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4838 volumeInfo.volEntries_val = (volintInfo *)0;
4839 volumeInfo.volEntries_len = 0;
4840 code = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
4841 if (volumeInfo.volEntries_val)
4842 free(volumeInfo.volEntries_val);
4843 if (code == VOLSERILLEGAL_PARTITION)
4845 rx_DestroyConnection(conn);
4853 afs_int32 CheckVldbRWBK(struct nvldbentry *entry, afs_int32 *modified)
4857 afs_int32 code, error = 0;
4860 if (modified) *modified = 0;
4861 idx = Lp_GetRwIndex(entry);
4863 /* Check to see if the RW volume exists and set the RW_EXISTS
4866 if (idx == -1) { /* Did not find a RW entry */
4867 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4868 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4872 code = VolumeExists(entry->serverNumber[idx],
4873 entry->serverPartition[idx],
4874 entry->volumeId[RWVOL]);
4875 if (code == 0) { /* RW volume exists */
4876 if (!(entry->flags & RW_EXISTS)) { /* ... yet entry says RW does not exist */
4877 entry->flags |= RW_EXISTS; /* ... so say RW does exist */
4881 else if (code == ENODEV) { /* RW volume does not exist */
4882 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4883 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4888 /* If VLDB says it didn't exist, then ignore error */
4889 if (entry->flags & RW_EXISTS) {
4890 MapPartIdIntoName(entry->serverPartition[idx], pname);
4891 fprintf(STDERR,"Transaction call failed for RW volume %u on server %s %s\n",
4892 entry->volumeId[RWVOL],
4893 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4899 /* Check to see if the BK volume exists and set the BACK_EXISTS
4900 * flag accordingly. idx already ponts to the RW entry.
4902 if (idx == -1) { /* Did not find a RW entry */
4903 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
4904 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
4908 else { /* Found a RW entry */
4909 code = VolumeExists(entry->serverNumber[idx],
4910 entry->serverPartition[idx],
4911 entry->volumeId[BACKVOL]);
4912 if (code == 0) { /* BK volume exists */
4913 if (!(entry->flags & BACK_EXISTS)) { /* ... yet entry says BK does not exist */
4914 entry->flags |= BACK_EXISTS; /* ... so say BK does exist */
4918 else if (code == ENODEV) { /* BK volume does not exist */
4919 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
4920 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
4925 /* If VLDB says it didn't exist, then ignore error */
4926 if (entry->flags & BACK_EXISTS) {
4927 MapPartIdIntoName(entry->serverPartition[idx], pname);
4928 fprintf(STDERR,"Transaction call failed for BK volume %u on server %s %s\n",
4929 entry->volumeId[BACKVOL],
4930 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4936 /* If there is an idx but the BK and RW volumes no
4937 * longer exist, then remove the RW entry.
4939 if ((idx != -1) && !(entry->flags & RW_EXISTS) &&
4940 !(entry->flags & BACK_EXISTS)) {
4941 Lp_SetRWValue(entry, entry->serverNumber[idx],
4942 entry->serverPartition[idx], 0L, 0L);
4948 if (modified) *modified = modentry;
4952 int CheckVldbRO(struct nvldbentry *entry, afs_int32 *modified)
4955 int foundro = 0, modentry = 0;
4956 afs_int32 code, error = 0;
4959 if (modified) *modified = 0;
4961 /* Check to see if the RO volumes exist and set the RO_EXISTS
4964 for (idx=0; idx < entry->nServers; idx++) {
4965 if (!(entry->serverFlags[idx] & ITSROVOL)) {
4966 continue; /* not a RO */
4969 code = VolumeExists(entry->serverNumber[idx],
4970 entry->serverPartition[idx],
4971 entry->volumeId[ROVOL]);
4972 if (code == 0) { /* RO volume exists */
4975 else if (code == ENODEV) { /* RW volume does not exist */
4976 Lp_SetROValue(entry, entry->serverNumber[idx],
4977 entry->serverPartition[idx], 0L, 0L);
4983 MapPartIdIntoName(entry->serverPartition[idx], pname);
4984 fprintf(STDERR,"Transaction call failed for RO %u on server %s %s\n",
4985 entry->volumeId[ROVOL],
4986 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
4991 if (foundro) { /* A RO volume exists */
4992 if (!(entry->flags & RO_EXISTS)) { /* ... yet entry says RW does not exist */
4993 entry->flags |= RO_EXISTS; /* ... so say RW does exist */
4996 } else { /* A RO volume does not exist */
4997 if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
4998 entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
5004 if (modified) *modified = modentry;
5009 * Ensure that <entry> matches with the info on file servers
5011 afs_int32 CheckVldb(struct nvldbentry *entry, afs_int32 *modified)
5013 afs_int32 code, error=0;
5014 struct nvldbentry storeEntry;
5015 int islocked=0, mod, modentry, delentry=0;
5018 if (modified) *modified = 0;
5020 fprintf(STDOUT,"_______________________________\n");
5021 fprintf(STDOUT,"\n-- status before -- \n");
5022 if ((entry->flags & RW_EXISTS) ||
5023 (entry->flags & RO_EXISTS) ||
5024 (entry->flags & BACK_EXISTS))
5025 EnumerateEntry(entry);
5026 fprintf(STDOUT,"\n");
5029 if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
5030 fprintf(STDERR,"Volume name %s exceeds limit of %d characters\n",
5031 entry->name, VOLSER_OLDMAXVOLNAME-10);
5035 /* Check to see if the VLDB is ok without locking it (pass 1).
5036 * If it will change, then lock the VLDB entry, read it again,
5037 * then make the changes to it (pass 2).
5040 code = ubik_Call(VL_SetLock,cstruct, 0, entry->volumeId[RWVOL], RWVOL, VLOP_DELETE);
5042 fprintf(STDERR, "Could not lock VLDB entry for %u \n",entry->volumeId[RWVOL] );
5047 code = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, entry);
5049 fprintf(STDERR,"Could not read VLDB entry for volume %s\n", entry->name);
5053 MapHostToNetwork(entry);
5059 /* Check if the RW and BK entries are ok */
5060 code = CheckVldbRWBK(entry, &mod);
5061 if (code) ERROR_EXIT(code);
5062 if (mod && (pass == 1)) goto retry;
5063 if (mod) modentry++;
5065 /* Check if the RO volumes entries are ok */
5066 code = CheckVldbRO(entry, &mod);
5067 if (code) ERROR_EXIT(code);
5068 if (mod && (pass == 1)) goto retry;
5069 if (mod) modentry++;
5071 /* The VLDB entry has been updated. If it as been modified, then
5072 * write the entry back out the the VLDB.
5075 if (pass == 1) goto retry;
5077 if (!(entry->flags & RW_EXISTS) &&
5078 !(entry->flags & BACK_EXISTS) &&
5079 !(entry->flags & RO_EXISTS)) {
5080 /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
5081 code = ubik_Call(VL_DeleteEntry, cstruct, 0, entry->volumeId[RWVOL], RWVOL);
5083 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",
5084 entry->volumeId[RWVOL]);
5090 /* Replace old entry with our new one */
5091 MapNetworkToHost(entry,&storeEntry);
5092 code = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry,
5093 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
5095 fprintf(STDERR,"Could not update VLDB entry for volume %u\n",
5096 entry->volumeId[RWVOL] );
5100 if (modified) *modified = 1;
5105 fprintf(STDOUT,"-- status after --\n");
5107 fprintf(STDOUT,"\n**entry deleted**\n");
5109 EnumerateEntry(entry);
5111 fprintf(STDOUT,"\n**no change**\n");
5115 VPRINT("\n_______________________________\n");
5118 code = ubik_Call(VL_ReleaseLock, cstruct, 0, entry->volumeId[RWVOL], RWVOL,
5119 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
5121 fprintf(STDERR,"Could not release lock on VLDB entry for volume %u\n",
5122 entry->volumeId[RWVOL]);
5123 if (!error) error = code;
5130 * Synchronise <aserver> <apart>(if flags = 1) with the VLDB.
5132 int UV_SyncServer(afs_int32 aserver, afs_int32 apart, int flags, int force)
5134 struct rx_connection *aconn;
5135 afs_int32 code, error = 0;
5136 afs_int32 nentries, tentries=0;
5137 struct VldbListByAttributes attributes;
5138 nbulkentries arrayEntries;
5139 afs_int32 failures=0, modified, modifications=0;
5140 struct nvldbentry *vlentry;
5141 afs_int32 si, nsi, j;
5143 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
5145 /* Set up attributes to search VLDB */
5146 attributes.server = ntohl(aserver);
5147 attributes.Mask = VLLIST_SERVER;
5149 attributes.partition = apart;
5150 attributes.Mask |= VLLIST_PARTITION;
5153 VPRINT("Processing VLDB entries ...\n");
5155 /* While we need to collect more VLDB entries */
5156 for (si=0; si != -1; si=nsi) {
5157 memset(&arrayEntries, 0, sizeof(arrayEntries));
5159 /* Collect set of VLDB entries */
5160 code = VLDB_ListAttributesN2(&attributes, 0, si,
5161 &nentries, &arrayEntries, &nsi);
5162 if (code == RXGEN_OPCODE) {
5163 code = VLDB_ListAttributes(&attributes, &nentries, &arrayEntries);
5167 fprintf(STDERR,"Could not access the VLDB for attributes\n");
5170 tentries += nentries;
5172 for (j=0; j<nentries; j++) {
5173 vlentry = &arrayEntries.nbulkentries_val[j];
5174 MapHostToNetwork(vlentry);
5176 VPRINT1("Processing VLDB entry %d ...\n", j+1);
5178 code = CheckVldb(vlentry, &modified);
5180 PrintError("",code);
5181 fprintf(STDERR,"Could not process VLDB entry for volume %s\n",
5184 } else if (modified) {
5190 fprintf(STDOUT,"...error encountered\n\n");
5192 fprintf(STDOUT,"...done entry %d\n\n", j+1);
5197 if (arrayEntries.nbulkentries_val) {
5198 free(arrayEntries.nbulkentries_val);
5199 arrayEntries.nbulkentries_val = 0;
5203 VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n",
5204 tentries, failures, modifications);
5208 rx_DestroyConnection(aconn);
5209 if (arrayEntries.nbulkentries_val)
5210 free(arrayEntries.nbulkentries_val);
5213 error = VOLSERFAILEDOP;
5217 /*rename volume <oldname> to <newname>, changing the names of the related
5218 *readonly and backup volumes. This operation is also idempotent.
5219 *salvager is capable of recovering from rename operation stopping halfway.
5220 *to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
5221 int UV_RenameVolume(struct nvldbentry *entry, char oldname[], char newname[])
5223 struct nvldbentry storeEntry;
5224 afs_int32 vcode,code,rcode,error;
5226 char nameBuffer[256];
5228 struct rx_connection *aconn;
5232 aconn = (struct rx_connection *)0;
5236 vcode = ubik_Call(VL_SetLock,cstruct, 0,entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE);/*last param is dummy*/
5238 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n",entry->volumeId[RWVOL] );
5243 strncpy(entry->name,newname,VOLSER_OLDMAXVOLNAME);
5244 MapNetworkToHost(entry,&storeEntry);
5245 vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL],RWVOL, &storeEntry,0 );
5247 fprintf(STDERR,"Could not update VLDB entry for %u\n",entry->volumeId[RWVOL]);
5251 VPRINT1("Recorded the new name %s in VLDB\n",newname);
5252 /*at this stage the intent to rename is recorded in the vldb, as far as the vldb
5253 is concerned, oldname is lost */
5254 if(entry->flags & RW_EXISTS) {
5255 index = Lp_GetRwIndex(entry);
5256 if(index == -1){ /* there is a serious discrepancy */
5257 fprintf(STDERR,"There is a serious discrepancy in VLDB entry for volume %u\n",entry->volumeId[RWVOL]);
5258 fprintf(STDERR,"try building VLDB from scratch\n");
5259 error = VOLSERVLDB_ERROR;
5262 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
5263 code = AFSVolTransCreate(aconn,entry->volumeId[RWVOL],entry->serverPartition[index], ITOffline, &tid);
5264 if(code) { /*volume doesnot exist */
5265 fprintf(STDERR,"Could not start transaction on the rw volume %u\n",entry->volumeId[RWVOL]);
5269 else {/*volume exists, process it */
5271 code = AFSVolSetIdsTypes(aconn, tid, newname,RWVOL, entry->volumeId[RWVOL],entry->volumeId[ROVOL],entry->volumeId[BACKVOL]);
5273 VPRINT2("Renamed rw volume %s to %s\n",oldname,newname);
5274 code = AFSVolEndTrans(aconn, tid, &rcode);
5277 fprintf(STDERR,"Could not end transaction on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
5283 fprintf(STDERR,"Could not set parameters on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
5288 if(aconn) rx_DestroyConnection(aconn);
5289 aconn = (struct rx_connection *)0;
5290 } /*end rw volume processing */
5292 if(entry->flags & BACK_EXISTS) {/*process the backup volume */
5293 index = Lp_GetRwIndex(entry);
5294 if(index == -1){ /* there is a serious discrepancy */
5295 fprintf(STDERR,"There is a serious discrepancy in the VLDB entry for the backup volume %u\n",entry->volumeId[BACKVOL]);
5296 fprintf(STDERR,"try building VLDB from scratch\n");
5297 error = VOLSERVLDB_ERROR;
5300 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
5301 code = AFSVolTransCreate(aconn,entry->volumeId[BACKVOL],entry->serverPartition[index], ITOffline, &tid);
5302 if(code) { /*volume doesnot exist */
5303 fprintf(STDERR,"Could not start transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
5307 else {/*volume exists, process it */
5308 if(strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)){
5309 fprintf(STDERR,"Volume name %s.backup exceeds the limit of %u characters\n",newname,VOLSER_OLDMAXVOLNAME);
5313 strcpy(nameBuffer,newname);
5314 strcat(nameBuffer,".backup");
5316 code = AFSVolSetIdsTypes(aconn, tid,nameBuffer ,BACKVOL, entry->volumeId[RWVOL],0,0);
5318 VPRINT1("Renamed backup volume to %s \n",nameBuffer);
5319 code = AFSVolEndTrans(aconn, tid, &rcode);
5322 fprintf(STDERR,"Could not end transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
5328 fprintf(STDERR,"Could not set parameters on the backup volume %u\n",entry->volumeId[BACKVOL]);
5333 } /* end backup processing */
5334 if(aconn) rx_DestroyConnection(aconn);
5335 aconn = (struct rx_connection *)0;
5336 if(entry->flags & RO_EXISTS){ /*process the ro volumes */
5337 for(i = 0; i < entry->nServers; i++){
5338 if(entry->serverFlags[i] & ITSROVOL) {
5339 aconn = UV_Bind(entry->serverNumber[i],AFSCONF_VOLUMEPORT);
5340 code = AFSVolTransCreate(aconn,entry->volumeId[ROVOL],entry->serverPartition[i], ITOffline, &tid);
5341 if(code) { /*volume doesnot exist */
5342 fprintf(STDERR,"Could not start transaction on the ro volume %u\n",entry->volumeId[ROVOL]);
5346 else {/*volume exists, process it */
5347 strcpy(nameBuffer,newname);
5348 strcat(nameBuffer,".readonly");
5349 if(strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)){
5350 fprintf(STDERR,"Volume name %s exceeds the limit of %u characters\n",nameBuffer,VOLSER_OLDMAXVOLNAME);
5354 code = AFSVolSetIdsTypes(aconn, tid, nameBuffer,ROVOL, entry->volumeId[RWVOL],0,0);
5356 VPRINT2("Renamed RO volume %s on host %s\n",
5358 hostutil_GetNameByINet(entry->serverNumber[i]));
5359 code = AFSVolEndTrans(aconn, tid, &rcode);
5362 fprintf(STDERR,"Could not end transaction on volume %u\n",entry->volumeId[ROVOL]);
5368 fprintf(STDERR,"Could not set parameters on the ro volume %u\n",entry->volumeId[ROVOL]);
5373 if(aconn) rx_DestroyConnection(aconn);
5374 aconn = (struct rx_connection *)0;
5380 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,entry->volumeId[RWVOL] , RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
5382 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
5383 if(!error) error = vcode;
5387 code = AFSVolEndTrans(aconn, tid, &rcode);
5388 if(!code) code = rcode;
5390 fprintf(STDERR,"Failed to end transaction on a volume \n");
5391 if(!error) error = code;
5394 if(aconn) rx_DestroyConnection(aconn);
5395 PrintError("",error);
5400 /*report on all the active transactions on volser */
5401 int UV_VolserStatus(afs_int32 server, transDebugInfo **rpntr, afs_int32 *rcount)
5403 struct rx_connection *aconn;
5404 transDebugEntries transInfo;
5407 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5408 transInfo.transDebugEntries_val = (transDebugInfo *) 0;
5409 transInfo.transDebugEntries_len = 0;
5410 code = AFSVolMonitor(aconn,&transInfo);
5412 fprintf(STDERR,"Could not access status information about the server\n");
5413 PrintError("",code);
5414 if (transInfo.transDebugEntries_val) free(transInfo.transDebugEntries_val);
5415 if(aconn) rx_DestroyConnection(aconn);
5419 *rcount = transInfo.transDebugEntries_len;
5420 *rpntr = transInfo.transDebugEntries_val;
5421 if(aconn) rx_DestroyConnection(aconn);
5428 /*delete the volume without interacting with the vldb */
5429 int UV_VolumeZap(afs_int32 server, afs_int32 part, afs_int32 volid)
5431 afs_int32 rcode,ttid,error,code;
5432 struct rx_connection *aconn;
5438 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5439 code = AFSVolTransCreate(aconn, volid, part, ITOffline, &ttid);
5441 fprintf(STDERR,"Could not start transaction on volume %u\n",volid);
5445 code = AFSVolDeleteVolume(aconn, ttid);
5447 fprintf(STDERR,"Could not delete volume %u\n",volid);
5451 code = AFSVolEndTrans(aconn, ttid, &rcode);
5453 if(!code) code = rcode;
5455 fprintf(STDERR,"Could not end transaction on volume %u\n",volid);
5461 code = AFSVolEndTrans(aconn,ttid,&rcode);
5462 if(!code) code = rcode;
5463 if(!error) error = code;
5465 PrintError("",error);
5466 if(aconn) rx_DestroyConnection(aconn);
5470 int UV_SetVolume(afs_int32 server, afs_int32 partition, afs_int32 volid, afs_int32 transflag, afs_int32 setflag, int sleeptime)
5472 struct rx_connection *conn = 0;
5474 afs_int32 code, error=0, rcode;
5476 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5478 fprintf(STDERR, "SetVolumeStatus: Bind Failed");
5482 code = AFSVolTransCreate(conn, volid, partition, transflag, &tid);
5484 fprintf(STDERR, "SetVolumeStatus: TransCreate Failed\n");
5488 code = AFSVolSetFlags(conn, tid, setflag);
5490 fprintf(STDERR, "SetVolumeStatus: SetFlags Failed\n");
5495 #ifdef AFS_PTHREAD_ENV
5498 IOMGR_Sleep(sleeptime);
5505 code = AFSVolEndTrans(conn, tid, &rcode);
5506 if (code || rcode) {
5507 fprintf(STDERR, "SetVolumeStatus: EndTrans Failed\n");
5508 if (!error) error = (code ? code : rcode);
5512 if (conn) rx_DestroyConnection(conn);
5516 int UV_SetVolumeInfo(afs_int32 server, afs_int32 partition, afs_int32 volid, volintInfo *infop)
5518 struct rx_connection *conn = 0;
5520 afs_int32 code, error=0, rcode;
5522 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5524 fprintf(STDERR, "SetVolumeInfo: Bind Failed");
5528 code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
5530 fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
5534 code = AFSVolSetInfo(conn, tid, infop);
5536 fprintf(STDERR, "SetVolumeInfo: SetInfo Failed\n");
5543 code = AFSVolEndTrans(conn, tid, &rcode);
5544 if (code || rcode) {
5545 fprintf(STDERR, "SetVolumeInfo: EndTrans Failed\n");
5546 if (!error) error = (code ? code : rcode);
5550 if (conn) rx_DestroyConnection(conn);
5554 /*maps the host addresses in <old > (present in network byte order) to
5555 that in< new> (present in host byte order )*/
5556 void MapNetworkToHost(struct nvldbentry *old, struct nvldbentry *new)
5560 /*copy all the fields */
5561 strcpy(new->name,old->name);
5562 /* new->volumeType = old->volumeType;*/
5563 new->nServers = old->nServers;
5564 count = old->nServers;
5565 if(count < NMAXNSERVERS) count++;
5566 for(i = 0; i < count; i++) {
5567 new->serverNumber[i] = ntohl(old->serverNumber[i]);
5568 new->serverPartition[i] = old->serverPartition[i];
5569 new->serverFlags[i] = old->serverFlags[i];
5571 new->volumeId[RWVOL]= old->volumeId[RWVOL];
5572 new->volumeId[ROVOL] = old->volumeId[ROVOL];
5573 new->volumeId[BACKVOL] = old->volumeId[BACKVOL];
5574 new->cloneId = old->cloneId;
5575 new->flags = old->flags;
5578 /*maps the host entries in <entry> which are present in host byte order to network byte order */
5579 void MapHostToNetwork(struct nvldbentry *entry)
5583 count = entry->nServers;
5584 if(count < NMAXNSERVERS) count++;
5585 for(i = 0; i < count; i++) {
5586 entry->serverNumber[i] = htonl(entry->serverNumber[i]);