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) \
86 fprintf(STDERR, "\n"); \
87 fprintf(STDERR, (es)); \
91 #define EPRINT1(ec, es, ep1) \
93 fprintf(STDERR, "\n"); \
94 fprintf(STDERR, (es), (ep1)); \
98 #define EPRINT2(ec, es, ep1, ep2) \
100 fprintf(STDERR, "\n"); \
101 fprintf(STDERR, (es), (ep1), (ep2)); \
102 PrintError(" ",ec); \
105 #define EPRINT3(ec, es, ep1, ep2, ep3) \
107 fprintf(STDERR, "\n"); \
108 fprintf(STDERR, (es), (ep1), (ep2), (ep3)); \
109 PrintError(" ",ec); \
112 #define EGOTO(where, ec, es) \
121 #define EGOTO1(where, ec, es, ep1) \
124 EPRINT1((ec),(es),(ep1)); \
130 #define EGOTO2(where, ec, es, ep1, ep2) \
133 EPRINT2((ec),(es),(ep1),(ep2)); \
139 #define EGOTO3(where, ec, es, ep1, ep2, ep3) \
142 EPRINT3((ec),(es),(ep1),(ep2),(ep3)); \
149 { if (verbose) { fprintf(STDOUT, (es)); fflush(STDOUT); } }
150 #define VPRINT1(es, p) \
151 { if (verbose) { fprintf(STDOUT, (es), (p)); fflush(STDOUT); } }
152 #define VPRINT2(es, p1, p2) \
153 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2)); fflush(STDOUT); } }
154 #define VPRINT3(es, p1, p2, p3) \
155 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
157 { if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
161 /* getting rid of this */
162 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
165 /* Protos for static routines */
166 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
167 afs_int32 apart, afs_int32 okvol, afs_int32 delvol);
168 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags);
169 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr,
170 afs_int32 *transPtr, afs_int32 *timePtr);
171 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
172 afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results);
173 static int rel_compar (struct release *r1, struct release *r2);
174 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart,
175 afs_int32 *modentry, afs_uint32 *maxvolid);
178 /*map the partition <partId> into partition name <partName>*/
179 void MapPartIdIntoName(afs_int32 partId, char *partName)
181 if(partId < 26) {/* what if partId > = 26 ? */
182 strcpy(partName,"/vicep");
183 partName[6] = partId + 'a';
186 } else if (partId < VOLMAXPARTS) {
187 strcpy(partName,"/vicep");
189 partName[6] = 'a' + (partId/26);
190 partName[7] = 'a' + (partId%26);
196 int yesprompt(char *str)
201 fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
202 response = c = getchar();
203 while (!(c==EOF || c=='\n')) c=getchar(); /*skip to end of line*/
204 code = (response=='y'||response=='Y');
209 int PrintError(char *msg, afs_int32 errcode)
212 /*replace by a big switch statement*/
216 case -1 : fprintf(STDERR,"Possible communication failure\n");
218 case VSALVAGE: fprintf(STDERR,"Volume needs to be salvaged\n");
220 case VNOVNODE: fprintf(STDERR,"Bad vnode number quoted\n");
222 case VNOVOL: fprintf(STDERR,"Volume not attached, does not exist, or not on line\n");
224 case VVOLEXISTS:fprintf(STDERR,"Volume already exists\n");
226 case VNOSERVICE:fprintf(STDERR,"Volume is not in service\n");
228 case VOFFLINE: fprintf(STDERR,"Volume is off line\n");
230 case VONLINE: fprintf(STDERR,"Volume is already on line\n");
232 case VDISKFULL: fprintf(STDERR,"Partition is full\n");
234 case VOVERQUOTA:fprintf(STDERR,"Volume max quota exceeded\n");
236 case VBUSY: fprintf(STDERR,"Volume temporarily unavailable\n");
238 case VMOVED:fprintf(STDERR,"Volume has moved to another server\n");
240 case VL_IDEXIST : fprintf(STDERR,"VLDB: volume Id exists in the vldb\n");
242 case VL_IO: fprintf(STDERR,"VLDB: a read terminated too early\n");
244 case VL_NAMEEXIST: fprintf(STDERR,"VLDB: volume entry exists in the vldb\n");
246 case VL_CREATEFAIL: fprintf(STDERR,"VLDB: internal creation failure\n");
248 case VL_NOENT: fprintf(STDERR,"VLDB: no such entry\n");
250 case VL_EMPTY: fprintf(STDERR,"VLDB: vldb database is empty\n");
252 case VL_ENTDELETED: fprintf(STDERR,"VLDB: entry is deleted (soft delete)\n");
254 case VL_BADNAME: fprintf(STDERR,"VLDB: volume name is illegal\n");
256 case VL_BADINDEX: fprintf(STDERR,"VLDB: index was out of range\n");
258 case VL_BADVOLTYPE: fprintf(STDERR,"VLDB: bad volume type\n");
260 case VL_BADSERVER: fprintf(STDERR,"VLDB: illegal server number (not within limits)\n");
262 case VL_BADPARTITION: fprintf(STDERR,"VLDB: bad partition number\n");
264 case VL_REPSFULL: fprintf(STDERR,"VLDB: run out of space for replication sites\n");
266 case VL_NOREPSERVER: fprintf(STDERR,"VLDB: no such repsite server exists\n");
268 case VL_DUPREPSERVER: fprintf(STDERR,"VLDB: replication site server already exists\n");
270 case VL_RWNOTFOUND: fprintf(STDERR,"VLDB: parent r/w entry not found\n");
272 case VL_BADREFCOUNT: fprintf(STDERR,"VLDB: illegal reference count number\n");
274 case VL_SIZEEXCEEDED: fprintf(STDERR,"VLDB: vldb size for attributes exceeded\n");
276 case VL_BADENTRY: fprintf(STDERR,"VLDB: bad incoming vldb entry\n");
278 case VL_BADVOLIDBUMP: fprintf(STDERR,"VLDB: illegal max volid increment\n");
280 case VL_IDALREADYHASHED: fprintf(STDERR,"VLDB: (RO/BACK) Id already hashed\n");
282 case VL_ENTRYLOCKED: fprintf(STDERR,"VLDB: vldb entry is already locked\n");
284 case VL_BADVOLOPER: fprintf(STDERR,"VLDB: bad volume operation code\n");
286 case VL_BADRELLOCKTYPE: fprintf(STDERR,"VLDB: bad release lock type\n");
288 case VL_RERELEASE: fprintf(STDERR,"VLDB: status report: last release was aborted\n");
290 case VL_BADSERVERFLAG: fprintf(STDERR,"VLDB: invalid replication site server flag\n");
292 case VL_PERM: fprintf(STDERR,"VLDB: no permission access for call\n");
294 case VOLSERREAD_DUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in reading the dump file !\n");
296 case VOLSERDUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in doing the dump !\n");
298 case VOLSERATTACH_ERROR: fprintf(STDERR,"VOLSER: Could not attach the volume\n");
300 case VOLSERDETACH_ERROR: fprintf(STDERR,"VOLSER: Could not detach the volume\n");
302 case VOLSERILLEGAL_PARTITION: fprintf(STDERR,"VOLSER: encountered illegal partition number\n");
304 case VOLSERBAD_ACCESS: fprintf(STDERR,"VOLSER: permission denied, not a super user\n");
306 case VOLSERVLDB_ERROR: fprintf(STDERR,"VOLSER: error detected in the VLDB\n");
308 case VOLSERBADNAME: fprintf(STDERR,"VOLSER: error in volume name\n");
310 case VOLSERVOLMOVED: fprintf(STDERR,"VOLSER: volume has moved\n");
312 case VOLSERBADOP: fprintf(STDERR,"VOLSER: illegal operation\n");
314 case VOLSERBADRELEASE: fprintf(STDERR,"VOLSER: release could not be completed\n");
316 case VOLSERVOLBUSY: fprintf(STDERR,"VOLSER: volume is busy\n");
318 case VOLSERNO_MEMORY: fprintf(STDERR,"VOLSER: volume server is out of memory\n");
320 case VOLSERNOVOL:fprintf(STDERR,"VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
322 case VOLSERMULTIRWVOL: fprintf(STDERR,"VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
324 case VOLSERFAILEDOP: fprintf(STDERR,"VOLSER: not all entries were successfully processed\n");
331 initialize_KA_error_table();
332 initialize_RXK_error_table();
333 initialize_KTC_error_table();
334 initialize_ACFG_error_table();
335 initialize_CMD_error_table();
336 initialize_VL_error_table();
338 offset = errcode & ((1<<ERRCODE_RANGE)-1);
339 fprintf(STDERR,"%s: %s\n",error_table_name (errcode), error_message (errcode));
347 static struct rx_securityClass *uvclass=0;
348 static int uvindex = -1;
349 /* called by VLDBClient_Init to set the security module to be used in the RPC */
350 int UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
356 /* bind to volser on <port> <aserver> */
357 /* takes server address in network order, port in host order. dumb */
358 struct rx_connection *UV_Bind(afs_int32 aserver, afs_int32 port)
360 register struct rx_connection *tc;
362 tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass, uvindex);
366 /* if <okvol> is allright(indicated by beibg able to
367 * start a transaction, delete the <delvol> */
368 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
369 afs_int32 apart, afs_int32 okvol, afs_int32 delvol)
371 afs_int32 error,code,tid,rcode;
377 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
378 if(!error && code) error = code;
379 code = AFSVolDeleteVolume(aconn,tid);
380 if(!error && code) error = code;
381 code = AFSVolEndTrans(aconn,tid, &rcode);
382 if(!code) code = rcode;
383 if(!error && code) error = code;
387 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline,&tid);
389 code = AFSVolEndTrans(aconn,tid, &rcode);
390 if(!code) code = rcode;
391 if(!error && code) error = code;
392 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
393 if(!error && code) error = code;
394 code = AFSVolDeleteVolume(aconn,tid);
395 if(!error && code) error = code;
396 code = AFSVolEndTrans(aconn,tid, &rcode);
397 if(!code) code = rcode;
398 if(!error && code) error = code;
406 /* called by EmuerateEntry, show vldb entry in a reasonable format */
407 void SubEnumerateEntry(struct nvldbentry *entry)
414 fprintf(STDOUT," readWriteID %-10u ",entry->volumeId[RWVOL]);
415 if(entry->flags & RW_EXISTS) fprintf(STDOUT," valid \n");else fprintf(STDOUT," invalid \n");
416 fprintf(STDOUT," readOnlyID %-10u ",entry->volumeId[ROVOL]);
417 if(entry->flags & RO_EXISTS) fprintf(STDOUT," valid \n") ;else fprintf(STDOUT," invalid \n");
418 fprintf(STDOUT," backUpID %-10u ",entry->volumeId[BACKVOL]);
419 if(entry->flags & BACK_EXISTS) fprintf(STDOUT," valid \n"); else fprintf(STDOUT," invalid \n");
420 if((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
421 fprintf(STDOUT," releaseClone %-10u \n",entry->cloneId);
423 if (entry->flags & RW_EXISTS)
424 fprintf(STDOUT," RWrite: %-10u",entry->volumeId[RWVOL]);
425 if (entry->flags & RO_EXISTS)
426 fprintf(STDOUT," ROnly: %-10u",entry->volumeId[ROVOL]);
427 if (entry->flags & BACK_EXISTS)
428 fprintf(STDOUT," Backup: %-10u",entry->volumeId[BACKVOL]);
429 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
430 fprintf(STDOUT," RClone: %-10u",entry->cloneId);
431 fprintf(STDOUT,"\n");
433 fprintf(STDOUT," number of sites -> %u\n",entry->nServers);
434 for(i = 0; i < entry->nServers; i++) {
435 if(entry->serverFlags[i] & NEW_REPSITE)
438 for(i = 0; i < entry->nServers; i++) {
439 MapPartIdIntoName(entry->serverPartition[i],pname);
440 fprintf(STDOUT," server %s partition %s ",
441 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
442 if(entry->serverFlags[i] & ITSRWVOL) fprintf(STDOUT,"RW Site ") ; else fprintf(STDOUT,"RO Site ");
444 if (entry->serverFlags[i] & NEW_REPSITE)
445 fprintf(STDOUT," -- New release");
447 fprintf(STDOUT," -- Old release");
449 if (entry->serverFlags[i] & RO_DONTUSE)
450 fprintf(STDOUT," -- Not released");
452 fprintf(STDOUT,"\n");
459 /*enumerate the vldb entry corresponding to <entry> */
460 void EnumerateEntry(struct nvldbentry *entry)
463 fprintf(STDOUT,"\n");
464 fprintf(STDOUT,"%s \n",entry->name);
465 SubEnumerateEntry(entry);
469 /* forcibly remove a volume. Very dangerous call */
470 int UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
472 register struct rx_connection *tconn;
473 register afs_int32 code;
475 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
477 code = AFSVolNukeVolume(tconn, partid, volid);
478 rx_DestroyConnection(tconn);
484 /* like df. Return usage of <pname> on <server> in <partition> */
485 int UV_PartitionInfo(afs_int32 server, char *pname, struct diskPartition *partition)
487 register struct rx_connection *aconn;
491 aconn = (struct rx_connection *)0;
492 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
493 code = AFSVolPartitionInfo(aconn,pname,partition);
495 fprintf(STDERR,"Could not get information on partition %s\n",pname);
498 if(aconn) rx_DestroyConnection(aconn);
502 /* old interface to create volume */
503 int UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 *anewid)
506 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
510 /* create a volume, given a server, partition number, volume name --> sends
511 * back new vol id in <anewid>*/
512 int UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aquota,
513 afs_int32 aspare1, afs_int32 aspare2, afs_int32 aspare3, afs_int32 aspare4, afs_int32 *anewid)
516 register struct rx_connection *aconn;
518 register afs_int32 code;
520 afs_int32 rcode,vcode;
521 struct nvldbentry entry,storeEntry;/*the new vldb entry */
522 struct volintInfo tstatus;
525 aconn = (struct rx_connection *)0;
527 memset(&tstatus, 0, sizeof(struct volintInfo));
529 tstatus.maxquota = aquota;
531 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
532 /* next the next 3 available ids from the VLDB */
533 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 3, anewid);
534 EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n",aname);
536 code = AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
537 EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n",aname,*anewid);
539 code = AFSVolSetInfo(aconn, tid, &tstatus);
541 EPRINT(code, "Could not change quota (error %d), continuing...\n");
543 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
544 EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n",aname,*anewid);
546 VPRINT2("Volume %s %u created and brought online\n",aname,*anewid);
548 /* set up the vldb entry for this volume */
549 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
551 entry.serverNumber[0] = aserver; /* this should have another
552 level of indirection later */
553 entry.serverPartition[0] = apart; /* this should also have
554 another indirection level */
555 entry.flags = RW_EXISTS;/* this records that rw volume exists */
556 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
557 entry.volumeId[RWVOL] = *anewid;
558 entry.volumeId[ROVOL] = *anewid + 1;/* rw,ro, bk id are related in the default case */
559 entry.volumeId[BACKVOL] = *anewid + 2;
561 /*map into right byte order, before passing to xdr, the stuff has to be in host
562 byte order. Xdr converts it into network order */
563 MapNetworkToHost(&entry,&storeEntry);
564 /* create the vldb entry */
565 vcode = VLDB_CreateEntry(&storeEntry);
567 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,*anewid);
568 /*destroy the created volume*/
569 VPRINT1("Deleting the newly created volume %u\n",*anewid);
570 AFSVolDeleteVolume(aconn,tid);
574 VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,*anewid);
575 /* volume created, now terminate the transaction and release the connection*/
576 code = AFSVolEndTrans(aconn, tid, &rcode);/*if it crashes before this
577 the volume will come online anyway when transaction timesout , so if
578 vldb entry exists then the volume is guaranteed to exist too wrt create*/
581 fprintf(STDERR,"Failed to end the transaction on the volume %s %u\n",aname,*anewid);
589 code= AFSVolEndTrans(aconn, tid, &rcode);
591 fprintf(STDERR,"WARNING: could not end transaction\n");
593 if(aconn) rx_DestroyConnection(aconn);
594 PrintError("",error);
599 /* create a volume, given a server, partition number, volume name --> sends
600 * back new vol id in <anewid>*/
601 int UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aid)
603 register struct rx_connection *aconn;
606 struct nvldbentry entry,storeEntry;/*the new vldb entry */
608 aconn = (struct rx_connection *)0;
611 /* set up the vldb entry for this volume */
612 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
614 entry.serverNumber[0] = aserver; /* this should have another
615 level of indirection later */
616 entry.serverPartition[0] = apart; /* this should also have
617 another indirection level */
618 entry.flags = RW_EXISTS;/* this records that rw volume exists */
619 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
620 entry.volumeId[RWVOL] = aid;
622 entry.volumeId[ROVOL] = anewid + 1;/* rw,ro, bk id are related in the default case */
623 entry.volumeId[BACKVOL] = *anewid + 2;
625 entry.volumeId[ROVOL] = 0;
626 entry.volumeId[BACKVOL] = 0;
629 /*map into right byte order, before passing to xdr, the stuff has to be in host
630 byte order. Xdr converts it into network order */
631 MapNetworkToHost(&entry,&storeEntry);
632 /* create the vldb entry */
633 vcode = VLDB_CreateEntry(&storeEntry);
635 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,aid);
639 VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,aid);
642 if(aconn) rx_DestroyConnection(aconn);
643 PrintError("",error);
647 /* Delete the volume <volid>on <aserver> <apart>
648 * the physical entry gets removed from the vldb only if the ref count
651 int UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
653 struct rx_connection *aconn = (struct rx_connection *)0;
655 afs_int32 code, rcode;
657 struct nvldbentry entry,storeEntry;
659 afs_int32 avoltype = -1, vtype;
660 int notondisk = 0, notinvldb = 0;
662 /* Find and read bhe VLDB entry for this volume */
663 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
665 if (code != VL_NOENT) {
666 EGOTO1(error_exit, code, "Could not lock VLDB entry for the volume %u\n", avolid);
672 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
673 EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",avolid);
674 MapHostToNetwork(&entry);
677 EnumerateEntry(&entry);
680 /* Whether volume is in the VLDB or not. Delete the volume on disk */
681 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
682 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
684 if (code == VNOVOL) {
687 EGOTO1(error_exit, code, "Transaction on volume %u failed\n", avolid);
691 VPRINT1("Trying to delete the volume %u ...", avolid);
693 code = AFSVolDeleteVolume(aconn, ttid);
694 EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
696 code = AFSVolEndTrans(aconn, ttid, &rcode);
697 code = (code ? code : rcode);
699 EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",avolid);
703 /* Now update the VLDB entry.
704 * But first, verify we have a VLDB entry.
705 * Whether volume is on disk or not. Delete the volume in VLDB.
710 if (avolid == entry.volumeId[BACKVOL]) {
711 /* Its a backup volume, modify the VLDB entry. Check that the
712 * backup volume is on the server/partition we asked to delete.
714 if ( !(entry.flags & BACK_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
715 notinvldb = 2; /* Not on this server and partition */
719 VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
721 entry.flags &= ~BACK_EXISTS;
725 else if (avolid == entry.volumeId[ROVOL]) {
726 /* Its a read-only volume, modify the VLDB entry. Check that the
727 * readonly volume is on the server/partition we asked to delete.
728 * If flags does not have RO_EIXSTS set, then this may mean the RO
729 * hasn't been released (and could exist in VLDB).
731 if (!Lp_ROMatch(aserver,apart,&entry)) {
732 notinvldb = 2; /* Not found on this server and partition */
737 fprintf(STDOUT,"Marking the readonly volume %u deleted in the VLDB\n", avolid);
739 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
741 if (!Lp_ROMatch(0,0,&entry))
742 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
746 else if (avolid == entry.volumeId[RWVOL]) {
747 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
748 * Check that the readwrite volumes is on the server/partition we
751 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
752 notinvldb = 2; /* Not found on this server and partition */
756 /* Delete backup if it exists */
757 code = AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart, ITOffline, &ttid);
760 fprintf(STDOUT,"Trying to delete the backup volume %u ...", entry.volumeId[BACKVOL]);
763 code = AFSVolDeleteVolume(aconn, ttid);
764 EGOTO1(error_exit, code, "Could not delete the volume %u \n", entry.volumeId[BACKVOL]);
766 code = AFSVolEndTrans(aconn, ttid, &rcode);
768 code = (code ? code : rcode);
769 EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",
770 entry.volumeId[BACKVOL]);
772 fprintf(STDOUT," done\n");
776 fprintf(STDOUT,"Marking the readwrite volume %u%s deleted in the VLDB\n",
777 avolid, ((entry.flags & BACK_EXISTS)?", and its backup volume,":""));
779 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
781 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
784 if (entry.flags & RO_EXISTS)
785 fprintf(STDERR,"WARNING: ReadOnly copy(s) may still exist\n");
789 notinvldb = 2; /* Not found on this server and partition */
793 /* Either delete or replace the VLDB entry */
794 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
796 fprintf(STDOUT,"Last reference to the VLDB entry for %u - deleting entry\n", avolid);
797 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
798 EGOTO1(error_exit, code, "Could not delete the VLDB entry for the volume %u \n",avolid);
800 MapNetworkToHost(&entry, &storeEntry);
801 code = VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
802 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
803 EGOTO1(error_exit, code, "Could not update the VLDB entry for the volume %u \n", avolid);
808 if (error) EPRINT(error, "\n");
810 if (notondisk && notinvldb) {
811 EPRINT2(VOLSERNOVOL,"Volume %u does not exist %s\n",
812 avolid, ((notinvldb == 2)?"on server and partition":""));
813 if (!error) error = VOLSERNOVOL;
815 else if (notondisk) {
816 fprintf(STDERR,"WARNING: Volume %u did not exist on the partition\n", avolid);
818 else if (notinvldb) {
819 fprintf(STDERR,"WARNING: Volume %u does not exist in VLDB %s\n",
820 avolid, ((notinvldb == 2)?"on server and partition":""));
824 code = AFSVolEndTrans(aconn, ttid, &rcode);
825 code = (code ? code : rcode);
827 fprintf(STDERR,"Could not end transaction on the volume %u\n", avolid);
828 PrintError("", code);
829 if (!error) error = code;
834 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, -1,
835 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
837 EPRINT1(code, "Could not release the lock on the VLDB entry for the volume %u \n",
839 if (!error) error = code;
843 if (aconn) rx_DestroyConnection(aconn);
847 /* add recovery to UV_MoveVolume */
849 #define TESTC 0 /* set to test recovery code, clear for production */
854 void sigint_handler(int x)
860 "\nSIGINT handler: vos move operation in progress\n");
862 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
864 "enter second control-c to exit\n");
868 signal(SIGINT,sigint_handler);
873 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
874 * <atopart>. The operation is almost idempotent
877 int UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver,
878 afs_int32 afrompart, afs_int32 atoserver, afs_int32 atopart)
880 struct rx_connection *toconn, *fromconn ;
881 afs_int32 fromtid, totid, clonetid;
884 char tmpName[VOLSER_MAXVOLNAME +1];
887 struct restoreCookie cookie;
888 register afs_int32 vcode, code;
889 afs_int32 newVol, volid, backupId;
890 struct volser_status tstatus;
891 struct destServer destination;
893 struct nvldbentry entry, storeEntry;
894 int i, islocked, pntg;
896 char in,lf; /* for test code */
899 #ifdef ENABLE_BUGFIX_1165
900 volEntries volumeInfo;
901 struct volintInfo *infop = 0;
905 fromconn = (struct rx_connection *)0;
906 toconn = (struct rx_connection *)0;
916 /* support control-c processing */
917 if (setjmp(env)) goto mfail;
918 (void) signal(SIGINT,sigint_handler);
923 "\nThere are three tests points - verifies all code paths through recovery.\n");
924 fprintf(STDOUT,"First test point - operation not started.\n");
925 fprintf(STDOUT,"...test here (y, n)? ");
927 fscanf(stdin,"%c",&in);
928 fscanf(stdin,"%c",&lf); /* toss away */
931 fprintf(STDOUT,"type control-c\n");
939 /* or drop through */
942 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
943 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
945 if (entry.volumeId[RWVOL] != afromvol)
947 fprintf(STDERR,"Only RW volume can be moved\n");
951 vcode = ubik_Call(VL_SetLock, cstruct, 0,afromvol, RWVOL, VLOP_MOVE);
952 EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
955 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
956 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
958 backupId = entry.volumeId[BACKVOL];
959 MapHostToNetwork(&entry);
961 if ( !Lp_Match(afromserver, afrompart, &entry) )
963 /* the from server and partition do not exist in the vldb entry corresponding to volid */
964 if ( !Lp_Match(atoserver, atopart, &entry) )
966 /* the to server and partition do not exist in the vldb entry corresponding to volid */
967 fprintf(STDERR,"The volume %u is not on the specified site. \n", afromvol);
968 fprintf(STDERR,"The current site is :");
969 for (i=0; i<entry.nServers; i++)
971 if (entry.serverFlags[i] == ITSRWVOL)
974 MapPartIdIntoName(entry.serverPartition[i],pname);
975 fprintf(STDERR," server %s partition %s \n",
976 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
979 vcode = ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
980 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
981 EGOTO1(mfail, vcode, " Could not release lock on the VLDB entry for the volume %u \n",
984 return VOLSERVOLMOVED;
987 /* delete the volume afromvol on src_server */
988 /* from-info does not exist but to-info does =>
989 * we have already done the move, but the volume
990 * may still be existing physically on from fileserver
992 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
996 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline, &fromtid);
998 { /* volume exists - delete it */
999 VPRINT1("Setting flags on leftover source volume %u ...", afromvol);
1000 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1001 EGOTO1(mfail, code, "Failed to set flags on the leftover source volume %u\n", afromvol);
1004 VPRINT1("Deleting leftover source volume %u ...", afromvol);
1005 code = AFSVolDeleteVolume(fromconn,fromtid);
1006 EGOTO1(mfail, code, "Failed to delete the leftover source volume %u\n", afromvol);
1009 VPRINT1("Ending transaction on leftover source volume %u ...", afromvol);
1010 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1012 if (!code) code = rcode;
1013 EGOTO1(mfail, code, "Could not end the transaction for the leftover source volume %u \n", afromvol);
1017 /*delete the backup volume now */
1019 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1021 { /* backup volume exists - delete it */
1022 VPRINT1("Setting flags on leftover backup volume %u ...", backupId);
1023 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1024 EGOTO1(mfail, code, "Failed to set flags on the backup volume %u\n", backupId);
1027 VPRINT1("Deleting leftover backup volume %u ...", backupId);
1028 code = AFSVolDeleteVolume(fromconn,fromtid);
1029 EGOTO1(mfail, code, "Could not delete the leftover backup volume %u\n", backupId);
1032 VPRINT1("Ending transaction on leftover backup volume %u ...", backupId);
1033 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1035 if (!code) code = rcode;
1036 EGOTO1(mfail, code,"Could not end the transaction for the leftover backup volume %u\n",backupId);
1045 /* From-info matches the vldb info about volid,
1046 * its ok start the move operation, the backup volume
1047 * on the old site is deleted in the process
1049 if (afrompart == atopart)
1051 same = VLDB_IsSameAddrs (afromserver, atoserver, &error);
1052 EGOTO2(mfail, error, "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1053 afromserver, error);
1057 EGOTO1(mfail, VOLSERVOLMOVED, "Warning: Moving volume %u to its home partition ignored!\n", afromvol);
1062 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1063 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1064 fromtid = totid = 0; /* initialize to uncreated */
1067 * clone the read/write volume locally.
1070 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1071 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1072 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1075 /* Get a clone id */
1076 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1078 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1079 EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1082 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1083 VPRINT1("Cloning source volume %u ...", afromvol);
1084 strcpy(vname, "move-clone-temp");
1085 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &newVol);
1086 EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1089 /* lookup the name of the volume we just cloned */
1091 code = AFSVolGetName(fromconn, fromtid, &volName);
1092 EGOTO1(mfail, code, "Failed to get the name of the volume %u\n", newVol);
1094 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1096 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1098 if (!code) code = rcode;
1099 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1103 * Create the destination volume
1106 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1107 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1108 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1111 VPRINT1("Setting flags on cloned volume %u ...", newVol);
1112 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1113 EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", newVol);
1116 /* remember time from which we've dumped the volume */
1117 VPRINT1("Getting status of cloned volume %u ...", newVol);
1118 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1119 EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", newVol);
1122 fromDate = tstatus.creationDate-CLOCKSKEW;
1124 #ifdef ENABLE_BUGFIX_1165
1126 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1127 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1128 * don't use this information...
1130 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
1131 volumeInfo.volEntries_len = 0;
1132 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1133 EGOTO1(mfail, code, "Failed to get the volint Info of the cloned volume %u\n", afromvol);
1135 infop = (volintInfo *) volumeInfo.volEntries_val;
1136 infop->maxquota = -1; /* Else it will replace the default quota */
1139 /* create a volume on the target machine */
1141 code = AFSVolTransCreate (toconn, volid, atopart, ITOffline, &totid);
1144 /* Delete the existing volume.
1145 * While we are deleting the volume in these steps, the transaction
1146 * we started against the cloned volume (clonetid above) will be
1147 * sitting idle. It will get cleaned up after 600 seconds
1149 VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1150 code = AFSVolDeleteVolume(toconn, totid);
1151 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", volid);
1154 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", volid);
1155 code = AFSVolEndTrans(toconn, totid, &rcode);
1157 if (!code) code = rcode;
1158 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1163 VPRINT1("Creating the destination volume %u ...", volid);
1164 code = AFSVolCreateVolume (toconn, atopart, volName, volser_RW, volid, &volid, &totid);
1165 EGOTO1(mfail, code, "Failed to create the destination volume %u\n", volid);
1168 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1172 VPRINT1("Setting volume flags on destination volume %u ...", volid);
1173 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1174 EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", volid);
1178 * Now dump the clone to the new volume
1181 destination.destHost = ntohl(atoserver);
1182 destination.destPort = AFSCONF_VOLUMEPORT;
1183 destination.destSSID = 1;
1185 /* Copy the clone to the new volume */
1186 VPRINT2("Dumping from clone %u on source to volume %u on destination ...", newVol, afromvol);
1187 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1188 cookie.type = RWVOL;
1189 cookie.parent = entry.volumeId[RWVOL];
1191 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1192 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1195 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1196 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1197 if (!code) code = rcode;
1199 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1203 * reattach to the main-line volume, and incrementally dump it.
1206 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1207 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1208 EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1211 /* now do the incremental */
1212 VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1213 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1214 EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1217 /* now adjust the flags so that the new volume becomes official */
1218 VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1219 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1220 EGOTO(mfail, code, "Failed to set the flags to make old source volume offline\n");
1223 VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1224 code = AFSVolSetFlags(toconn, totid, 0);
1225 EGOTO(mfail, code, "Failed to set the flags to make new source volume online\n");
1228 #ifdef ENABLE_BUGFIX_1165
1229 VPRINT1("Setting volume status on destination volume %u ...", volid);
1230 code = AFSVolSetInfo(toconn, totid, infop);
1231 EGOTO1(mfail, code, "Failed to set volume status on the destination volume %u\n", volid);
1235 /* put new volume online */
1236 VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1237 code = AFSVolEndTrans(toconn, totid, &rcode);
1239 if (!code) code = rcode;
1240 EGOTO1(mfail, code, "Failed to end the transaction on the volume %u on the new site\n", afromvol);
1243 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1244 MapNetworkToHost(&entry,&storeEntry);
1245 storeEntry.flags &= ~BACK_EXISTS;
1249 fprintf(STDOUT, "Second test point - operation in progress but not complete.\n");
1250 fprintf(STDOUT,"...test here (y, n)? ");
1252 fscanf(stdin,"%c",&in);
1253 fscanf(stdin,"%c",&lf); /* toss away */
1256 fprintf(STDOUT,"type control-c\n");
1259 fprintf(stdout,".");
1264 /* or drop through */
1267 VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1268 vcode = VLDB_ReplaceEntry (afromvol, -1, &storeEntry,
1269 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1272 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %s %u \n",
1273 storeEntry.name,afromvol);
1282 fprintf(STDOUT, "Third test point - operation complete but no cleanup.\n");
1283 fprintf(STDOUT,"...test here (y, n)? ");
1285 fscanf(stdin,"%c",&in);
1286 fscanf(stdin,"%c",&lf); /* toss away */
1289 fprintf(STDOUT,"type control-c\n");
1292 fprintf(stdout,".");
1297 /* or drop through */
1301 /* This is tricky. File server is very stupid, and if you mark the volume
1302 * as VTOutOfService, it may mark the *good* instance (if you're moving
1303 * between partitions on the same machine) as out of service. Since
1304 * we're cleaning this code up in DEcorum, we're just going to kludge around
1305 * it for now by removing this call. */
1306 /* already out of service, just zap it now */
1307 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1310 fprintf(STDERR,"Failed to set the flags to make the old source volume offline\n");
1314 if (atoserver != afromserver)
1316 /* set forwarding pointer for moved volumes */
1317 VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1318 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1319 EGOTO1(mfail, code, "Failed to set the forwarding pointer for the volume %u\n", afromvol);
1323 VPRINT1("Deleting old volume %u on source ...", afromvol);
1324 code = AFSVolDeleteVolume(fromconn,fromtid); /* zap original volume */
1325 EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n", afromvol);
1328 VPRINT1("Ending transaction on old volume %u on the source ...", afromvol);
1329 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1331 if (!code) code = rcode;
1332 EGOTO1(mfail, code, "Failed to end the transaction on the old volume %u on the source\n", afromvol);
1335 /* Delete the backup volume on the original site */
1336 VPRINT1("Creating transaction for backup volume %u on source ...", backupId);
1337 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1341 VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1342 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1343 EGOTO1(mfail, code, "Failed to set the flags on the backup volume %u on the source\n", backupId);
1346 VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1347 code = AFSVolDeleteVolume(fromconn,fromtid);
1348 EGOTO1(mfail, code, "Failed to delete the backup volume %u on the source\n", backupId);
1351 VPRINT1("Ending transaction on backup volume %u on source ...", backupId);
1352 code = AFSVolEndTrans(fromconn,fromtid, &rcode);
1354 if (!code) code = rcode;
1355 EGOTO1(mfail, code, "Failed to end the transaction on the backup volume %u on the source\n", backupId);
1358 else code = 0; /* no backup volume? that's okay */
1361 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1362 code = AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
1363 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1366 /* now delete the clone */
1367 VPRINT1("Deleting the cloned volume %u ...", newVol);
1368 code = AFSVolDeleteVolume(fromconn, clonetid);
1369 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", newVol);
1372 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1373 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1374 if (!code) code = rcode;
1376 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1384 fprintf(STDOUT,"Fourth test point - operation complete.\n");
1385 fprintf(STDOUT,"...test here (y, n)? ");
1387 fscanf(stdin,"%c",&in);
1388 fscanf(stdin,"%c",&lf); /* toss away */
1391 fprintf(STDOUT,"type control-c\n");
1394 fprintf(stdout,".");
1399 /* or drop through */
1402 /* normal cleanup code */
1404 if (entry.flags & RO_EXISTS) fprintf(STDERR,"WARNING : readOnly copies still exist \n");
1408 VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1409 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, -1,
1410 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1414 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %u \n",
1416 if (!error) error = vcode;
1423 VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1424 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1428 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n", newVol);
1429 if (!error) error = (code ? code : rcode);
1436 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1437 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1441 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",newVol);
1442 if (!error) error = (code ? code : rcode);
1449 VPRINT1("Cleanup: Ending transaction on destination volume %u ...", afromvol);
1450 code = AFSVolEndTrans(toconn, totid, &rcode);
1454 fprintf(STDERR,"Could not end transaction on destination volume %u\n",afromvol);
1455 if (!error) error = (code ? code : rcode);
1459 if (volName) free(volName);
1460 #ifdef ENABLE_BUGFIX_1165
1461 if (infop) free(infop);
1463 if (fromconn) rx_DestroyConnection(fromconn);
1464 if (toconn) rx_DestroyConnection(toconn);
1465 PrintError("",error);
1468 /* come here only when the sky falls */
1473 fprintf(STDOUT,"vos move: operation interrupted, cleanup in progress...\n");
1474 fprintf(STDOUT,"clear transaction contexts\n");
1478 /* unlock VLDB entry */
1481 VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1482 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1483 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1489 VPRINT("Recovery: Ending transaction on clone volume ...");
1490 AFSVolEndTrans(fromconn, clonetid, &rcode);
1495 VPRINT("Recovery: Ending transaction on destination volume ...");
1496 AFSVolEndTrans(toconn, totid, &rcode);
1500 { /* put it on-line */
1501 VPRINT("Recovery: Setting volume flags on source volume ...");
1502 AFSVolSetFlags(fromconn,fromtid,0);
1505 VPRINT("Recovery: Ending transaction on source volume ...");
1506 AFSVolEndTrans(fromconn, fromtid, &rcode);
1510 VPRINT("Recovery: Accessing VLDB.\n");
1511 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
1514 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
1518 MapHostToNetwork(&entry);
1520 /* Delete either the volume on the source location or the target location.
1521 * If the vldb entry still points to the source location, then we know the
1522 * volume move didn't finish so we remove the volume from the target
1523 * location. Otherwise, we remove the volume from the source location.
1525 if (Lp_Match(afromserver,afrompart,&entry)) { /* didn't move - delete target volume */
1528 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1532 if (volid && toconn) {
1533 VPRINT1("Recovery: Creating transaction for destination volume %u ...", volid);
1534 code=AFSVolTransCreate(toconn,volid,atopart, ITOffline,&totid);
1539 VPRINT1("Recovery: Setting flags on destination volume %u ...", volid);
1540 AFSVolSetFlags(toconn,totid, VTDeleteOnSalvage | VTOutOfService);
1543 VPRINT1("Recovery: Deleting destination volume %u ...", volid);
1544 AFSVolDeleteVolume(toconn,totid);
1547 VPRINT1("Recovery: Ending transaction on destination volume %u ...", volid);
1548 AFSVolEndTrans(toconn,totid,&rcode);
1553 VPRINT1("\nRecovery: Unable to start transaction on destination volume %u.\n", afromvol);
1557 /* put source volume on-line */
1559 VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1560 code=AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1564 VPRINT1("Recovery: Setting flags on source volume %u ...", afromvol);
1565 AFSVolSetFlags(fromconn,fromtid,0);
1568 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1569 AFSVolEndTrans(fromconn,fromtid,&rcode);
1574 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1578 else { /* yep, move complete */
1581 "move complete - attempt cleanup of source partition - no guarantee\n");
1585 /* delete backup volume */
1587 VPRINT1("Recovery: Creating transaction on backup volume %u ...", backupId);
1588 code=AFSVolTransCreate (fromconn,backupId,afrompart, ITOffline,&fromtid);
1592 VPRINT1("Recovery: Setting flags on backup volume %u ...", backupId);
1593 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1596 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1597 AFSVolDeleteVolume(fromconn,fromtid);
1600 VPRINT1("Recovery: Ending transaction on backup volume %u ...", backupId);
1601 AFSVolEndTrans(fromconn,fromtid,&rcode);
1606 VPRINT1("\nRecovery: Unable to start transaction on backup volume %u.\n", backupId);
1609 /* delete source volume */
1610 VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1611 code=AFSVolTransCreate (fromconn, afromvol, afrompart, ITBusy, &fromtid);
1615 VPRINT1("Recovery: Setting flags on backup volume %u ...", afromvol);
1616 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1619 if (atoserver != afromserver)
1621 VPRINT("Recovery: Setting volume forwarding pointer ...");
1622 AFSVolSetForwarding(fromconn,fromtid,atoserver);
1626 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1627 AFSVolDeleteVolume(fromconn,fromtid);
1630 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1631 AFSVolEndTrans(fromconn,fromtid,&rcode);
1636 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1641 /* common cleanup - delete local clone */
1643 VPRINT1("Recovery: Creating transaction on clone volume %u ...", newVol);
1644 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1648 VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1649 AFSVolDeleteVolume(fromconn,clonetid);
1652 VPRINT1("Recovery: Ending transaction on clone volume %u ...", newVol);
1653 AFSVolEndTrans(fromconn,clonetid,&rcode);
1658 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1662 /* unlock VLDB entry */
1663 VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...", afromvol);
1664 ubik_Call (VL_ReleaseLock, cstruct, 0, afromvol, -1,
1665 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1668 done: /* routine cleanup */
1669 if (volName) free(volName);
1670 #ifdef ENABLE_BUGFIX_1165
1671 if (infop) free(infop);
1673 if (fromconn) rx_DestroyConnection(fromconn);
1674 if (toconn) rx_DestroyConnection(toconn);
1677 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
1684 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1685 * <atopart>. The operation is almost idempotent
1688 int UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver,
1689 afs_int32 afrompart, char *atovolname, afs_int32 atoserver, afs_int32 atopart)
1691 struct rx_connection *toconn, *fromconn ;
1692 afs_int32 fromtid, totid, clonetid;
1694 char tmpName[VOLSER_MAXVOLNAME +1];
1697 struct restoreCookie cookie;
1698 register afs_int32 vcode, code;
1699 afs_int32 cloneVol, newVol;
1700 struct volser_status tstatus;
1701 struct destServer destination;
1703 struct nvldbentry entry, newentry, storeEntry;
1704 int i, islocked, pntg;
1706 char in,lf; /* for test code */
1711 fromconn = (struct rx_connection *)0;
1712 toconn = (struct rx_connection *)0;
1720 /* support control-c processing */
1721 if (setjmp(env)) goto mfail;
1722 (void) signal(SIGINT,sigint_handler);
1724 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1725 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
1726 MapHostToNetwork(&entry);
1729 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1730 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1731 fromtid = totid = 0; /* initialize to uncreated */
1734 /* check if we can shortcut and use a local clone instead of a full copy */
1735 if ( afromserver == atoserver && afrompart == atopart )
1741 * clone the read/write volume locally.
1744 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1745 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1746 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1749 /* Get a clone id */
1750 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1752 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &cloneVol);
1753 EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1756 /* Get a new volume id */
1757 VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
1759 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1760 EGOTO1(mfail, vcode, "Could not get an ID for the copy of volume %u from the VLDB\n", afromvol);
1763 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1764 VPRINT1("Cloning source volume %u ...", afromvol);
1765 strcpy(vname, "copy-clone-temp");
1766 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &cloneVol);
1767 EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1770 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1772 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1774 if (!code) code = rcode;
1775 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1779 * Create the destination volume
1782 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1783 code = AFSVolTransCreate (fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1784 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1787 VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
1788 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1789 EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", cloneVol);
1792 /* remember time from which we've dumped the volume */
1793 VPRINT1("Getting status of cloned volume %u ...", cloneVol);
1794 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1795 EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", cloneVol);
1798 fromDate = tstatus.creationDate-CLOCKSKEW;
1800 /* create a volume on the target machine */
1801 code = AFSVolTransCreate (toconn, newVol, atopart, ITOffline, &totid);
1804 /* Delete the existing volume.
1805 * While we are deleting the volume in these steps, the transaction
1806 * we started against the cloned volume (clonetid above) will be
1807 * sitting idle. It will get cleaned up after 600 seconds
1809 VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
1810 code = AFSVolDeleteVolume(toconn, totid);
1811 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", newVol);
1814 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", newVol);
1815 code = AFSVolEndTrans(toconn, totid, &rcode);
1817 if (!code) code = rcode;
1818 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1823 VPRINT1("Creating the destination volume %u ...", newVol);
1824 code = AFSVolCreateVolume (toconn, atopart, atovolname, volser_RW, newVol, &newVol, &totid);
1825 EGOTO1(mfail, code, "Failed to create the destination volume %u\n", newVol);
1828 strncpy(tmpName, atovolname, VOLSER_OLDMAXVOLNAME);
1830 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1831 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1832 EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", newVol);
1836 * Now dump the clone to the new volume
1839 destination.destHost = ntohl(atoserver);
1840 destination.destPort = AFSCONF_VOLUMEPORT;
1841 destination.destSSID = 1;
1844 /* probably should have some code here that checks to see if we are copying to same server
1845 and partition - if so, just use a clone to save disk space */
1847 /* Copy the clone to the new volume */
1848 VPRINT2("Dumping from clone %u on source to volume %u on destination ...", cloneVol, newVol);
1849 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1850 cookie.type = RWVOL;
1853 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1854 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", newVol);
1857 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1858 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1859 if (!code) code = rcode;
1861 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1865 * reattach to the main-line volume, and incrementally dump it.
1868 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1869 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1870 EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1873 /* now do the incremental */
1874 VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1875 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1876 EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1879 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1880 code = AFSVolSetFlags(toconn, totid, 0);
1881 EGOTO(mfail, code, "Failed to set the flags to make destination volume online\n");
1884 /* put new volume online */
1885 VPRINT1("Ending transaction on destination volume %u ...", newVol);
1886 code = AFSVolEndTrans(toconn, totid, &rcode);
1888 if (!code) code = rcode;
1889 EGOTO1(mfail, code, "Failed to end the transaction on the destination volume %u\n", newVol);
1892 VPRINT1("Ending transaction on source volume %u ...", afromvol);
1893 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1895 if (!code) code = rcode;
1896 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1900 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1901 code = AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1902 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1905 /* now delete the clone */
1906 VPRINT1("Deleting the cloned volume %u ...", cloneVol);
1907 code = AFSVolDeleteVolume(fromconn, clonetid);
1908 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", cloneVol);
1911 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1912 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1913 if (!code) code = rcode;
1915 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1918 /* create the vldb entry for the copied volume */
1919 strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
1920 newentry.nServers = 1;
1921 newentry.serverNumber[0] = atoserver;
1922 newentry.serverPartition[0] = atopart;
1923 newentry.flags = RW_EXISTS;/* this records that rw volume exists */
1924 newentry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
1925 newentry.volumeId[RWVOL] = newVol;
1926 newentry.volumeId[ROVOL] = 0;
1927 newentry.volumeId[BACKVOL] = 0;
1928 newentry.cloneId = 0;
1929 /*map into right byte order, before passing to xdr, the stuff has to be in host
1930 byte order. Xdr converts it into network order */
1931 MapNetworkToHost(&newentry,&storeEntry);
1932 /* create the vldb entry */
1933 vcode = VLDB_CreateEntry(&storeEntry);
1935 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", atovolname,newVol);
1936 /*destroy the created volume*/
1937 VPRINT1("Deleting the newly created volume %u\n",newVol);
1938 AFSVolDeleteVolume(toconn,totid);
1942 VPRINT2("Created the VLDB entry for the volume %s %u\n",atovolname,newVol);
1944 /* normal cleanup code */
1948 VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1949 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1953 fprintf(STDERR,"Could not end transaction on the source volume %u\n", afromvol);
1954 if (!error) error = (code ? code : rcode);
1961 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", cloneVol);
1962 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1966 fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",cloneVol);
1967 if (!error) error = (code ? code : rcode);
1974 VPRINT1("Cleanup: Ending transaction on destination volume %u ...", newVol);
1975 code = AFSVolEndTrans(toconn, totid, &rcode);
1979 fprintf(STDERR,"Could not end transaction on destination volume %u\n", newVol);
1980 if (!error) error = (code ? code : rcode);
1984 if (fromconn) rx_DestroyConnection(fromconn);
1985 if (toconn) rx_DestroyConnection(toconn);
1986 PrintError("",error);
1989 /* come here only when the sky falls */
1994 fprintf(STDOUT,"vos copy: operation interrupted, cleanup in progress...\n");
1995 fprintf(STDOUT,"clear transaction contexts\n");
2001 VPRINT("Recovery: Ending transaction on clone volume ...");
2002 AFSVolEndTrans(fromconn, clonetid, &rcode);
2007 VPRINT("Recovery: Ending transaction on destination volume ...");
2008 AFSVolEndTrans(toconn, totid, &rcode);
2012 { /* put it on-line */
2013 VPRINT("Recovery: Ending transaction on source volume ...");
2014 AFSVolEndTrans(fromconn, fromtid, &rcode);
2018 VPRINT("Recovery: Accessing VLDB.\n");
2019 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
2022 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
2026 MapHostToNetwork(&entry);
2028 /* common cleanup - delete local clone */
2030 VPRINT1("Recovery: Creating transaction on clone volume %u ...", cloneVol);
2031 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
2035 VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2036 AFSVolDeleteVolume(fromconn,clonetid);
2039 VPRINT1("Recovery: Ending transaction on clone volume %u ...", cloneVol);
2040 AFSVolEndTrans(fromconn,clonetid,&rcode);
2045 VPRINT1("\nRecovery: Unable to start transaction on clone volume %u.\n", cloneVol);
2049 done: /* routine cleanup */
2050 if (fromconn) rx_DestroyConnection(fromconn);
2051 if (toconn) rx_DestroyConnection(toconn);
2054 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
2064 /* Make a new backup of volume <avolid> on <aserver> and <apart>
2065 * if one already exists, update it
2068 int UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2070 struct rx_connection *aconn = (struct rx_connection *)0;
2071 afs_int32 ttid = 0, btid = 0;
2073 afs_int32 code = 0, rcode = 0;
2074 char vname[VOLSER_MAXVOLNAME +1];
2075 struct nvldbentry entry, storeEntry;
2076 afs_int32 error = 0;
2077 int vldblocked = 0, vldbmod = 0, backexists = 1;
2079 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2081 /* the calls to VLDB will succeed only if avolid is a RW volume,
2082 * since we are following the RW hash chain for searching */
2083 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2085 fprintf(STDERR, "Could not fetch the entry for the volume %u from the VLDB \n", avolid);
2086 error = code; goto bfail;
2088 MapHostToNetwork(&entry);
2090 /* These operations require the VLDB be locked since it means the VLDB
2091 * will change or the vldb is already locked.
2093 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
2094 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
2095 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
2097 code = ubik_Call(VL_SetLock,cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2099 fprintf(STDERR,"Could not lock the VLDB entry for the volume %u\n",avolid);
2105 /* Reread the vldb entry */
2106 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2108 fprintf(STDERR,"Could not fetch the entry for the volume %u from the VLDB \n",avolid);
2112 MapHostToNetwork(&entry);
2115 if (!ISNAMEVALID(entry.name)) {
2116 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n", entry.name);
2117 error = VOLSERBADNAME;
2121 backupID = entry.volumeId[BACKVOL];
2122 if (backupID == INVALID_BID) {
2123 /* Get a backup volume id from the VLDB and update the vldb
2126 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
2129 "Could not allocate ID for the backup volume of %u from the VLDB\n",
2134 entry.volumeId[BACKVOL] = backupID;
2138 /* Test to see if the backup volume exists by trying to create
2139 * a transaction on the backup volume. We've assumed the backup exists.
2141 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2143 if (code != VNOVOL) {
2144 fprintf(STDERR,"Could not reach the backup volume %u\n", backupID);
2148 backexists = 0; /* backup volume does not exist */
2151 code = AFSVolEndTrans(aconn, btid, &rcode);
2153 if (code || rcode) {
2155 "Could not end transaction on the previous backup volume %u\n",
2157 error = (code ? code : rcode);
2162 /* Now go ahead and try to clone the RW volume.
2163 * First start a transaction on the RW volume
2165 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2167 fprintf(STDERR,"Could not start a transaction on the volume %u\n",avolid);
2172 /* Clone or reclone the volume, depending on whether the backup
2173 * volume exists or not
2176 VPRINT1("Re-cloning backup volume %u ...", backupID);
2178 code = AFSVolReClone(aconn, ttid, backupID);
2180 fprintf(STDERR,"Could not re-clone backup volume %u\n", backupID);
2186 VPRINT1("Creating a new backup clone %u ...", backupID);
2188 strcpy(vname, entry.name);
2189 strcat(vname,".backup");
2191 code = AFSVolClone(aconn, ttid, 0,backupVolume, vname, &backupID);
2193 fprintf(STDERR,"Failed to clone the volume %u\n",avolid);
2199 /* End the transaction on the RW volume */
2200 code = AFSVolEndTrans(aconn, ttid, &rcode);
2202 if (code || rcode) {
2203 fprintf(STDERR, "Failed to end the transaction on the rw volume %u\n", avolid);
2204 error = (code ? code : rcode);
2208 /* Mork vldb as backup exists */
2209 if (!(entry.flags & BACK_EXISTS)) {
2210 entry.flags |= BACK_EXISTS;
2214 /* Now go back to the backup volume and bring it on line */
2215 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2217 fprintf(STDERR,"Failed to start a transaction on the backup volume %u\n",backupID);
2222 code = AFSVolSetFlags(aconn, btid, 0);
2224 fprintf(STDERR,"Could not mark the backup volume %u on line \n",backupID);
2229 code = AFSVolEndTrans(aconn, btid, &rcode);
2231 if (code || rcode) {
2232 fprintf(STDERR, "Failed to end the transaction on the backup volume %u\n", backupID);
2233 error = (code ? code : rcode);
2239 /* Will update the vldb below */
2243 code = AFSVolEndTrans(aconn, ttid, &rcode);
2244 if (code || rcode) {
2245 fprintf(STDERR, "Could not end transaction on the volume %u\n", avolid);
2247 error = (code ? code : rcode);
2252 code = AFSVolEndTrans(aconn, btid, &rcode);
2253 if (code || rcode) {
2254 fprintf(STDERR,"Could not end transaction the backup volume %u\n",backupID);
2256 error = (code ? code : rcode);
2260 /* Now update the vldb - if modified */
2263 MapNetworkToHost(&entry,&storeEntry);
2264 code = VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2265 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2267 fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n",avolid);
2273 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, RWVOL,
2274 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2276 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %u \n",avolid);
2284 rx_DestroyConnection(aconn);
2286 PrintError("",error);
2290 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags)
2292 afs_int32 acode, ccode, rcode, tid;
2293 ccode = rcode = tid = 0;
2295 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2296 if (!acode) { /* It really was there */
2297 acode = AFSVolDeleteVolume(conn, tid);
2299 fprintf(STDERR, "Failed to delete volume %u.\n", vid);
2300 PrintError ("", acode);
2302 ccode = AFSVolEndTrans(conn, tid, &rcode);
2306 fprintf(STDERR, "Failed to end transaction on volume %u.\n", vid);
2307 PrintError ("", ccode);
2314 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
2315 #define ERROREXIT(ec) { error = (ec); goto rfail; }
2317 /* Get a "transaction" on this replica. Create the volume
2318 * if necessary. Return the time from which a dump should
2319 * be made (0 if it's a new volume)
2321 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr,
2322 afs_int32 *transPtr, afs_int32 *timePtr)
2325 struct volser_status tstatus;
2326 int code, rcode, tcode;
2328 *connPtr = (struct rx_connection *)0;
2332 /* get connection to the replication site */
2333 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
2334 if (!*connPtr) goto fail; /* server is down */
2336 volid = vldbEntryPtr->volumeId[ROVOL];
2338 code = AFSVolTransCreate(*connPtr, volid, vldbEntryPtr->serverPartition[index],
2339 ITOffline, transPtr);
2341 /* If the volume does not exist, create it */
2342 if (!volid || code) {
2345 if (volid && (code != VNOVOL)){
2346 PrintError("Failed to start a transaction on the RO volume.\n",
2351 strcpy(volname, vldbEntryPtr->name);
2352 strcat(volname, ".readonly");
2355 fprintf(STDOUT,"Creating new volume %u on replication site %s: ",
2356 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2360 code = AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
2362 vldbEntryPtr->volumeId[RWVOL], &volid, transPtr);
2364 PrintError("Failed to create the ro volume: ",code);
2367 vldbEntryPtr->volumeId[ROVOL] = volid;
2371 /* The following is a bit redundant, since create sets these flags by default */
2372 code = AFSVolSetFlags(*connPtr, *transPtr, VTDeleteOnSalvage | VTOutOfService);
2374 PrintError("Failed to set flags on the ro volume: ", code);
2379 /* Otherwise, the transaction did succeed, so get the creation date of the
2380 * latest RO volume on the replication site
2383 VPRINT2("Updating existing ro volume %u on %s ...\n",
2384 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2386 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
2388 PrintError("Failed to get status of volume on destination: ",code);
2391 *timePtr = tstatus.creationDate-CLOCKSKEW;
2398 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
2400 if (!tcode) tcode = rcode;
2401 if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode);
2407 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
2408 afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results)
2412 for (i=0; i<tr->manyDests_len; i++) {
2413 results->manyResults_val[i] = AFSVolForward(fromconn, fromtid,
2414 fromdate, &(tr->manyDests_val[i].server),
2415 tr->manyDests_val[i].trans, cookie);
2421 static int rel_compar (struct release *r1, struct release *r2)
2423 return (r1->time - r2->time);
2426 /* UV_ReleaseVolume()
2427 * Release volume <afromvol> on <afromserver> <afrompart> to all
2428 * its RO sites (full release). Unless the previous release was
2429 * incomplete: in which case we bring the remaining incomplete
2430 * volumes up to date with the volumes that were released
2432 * forceflag: Performs a full release.
2434 * Will create a clone from the RW, then dump the clone out to
2435 * the remaining replicas. If there is more than 1 RO sites,
2436 * ensure that the VLDB says at least one RO is available all
2437 * the time: Influences when we write back the VLDB entry.
2440 int UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, int forceflag)
2443 afs_int32 code, vcode, rcode, tcode;
2444 afs_int32 cloneVolId, roVolId;
2445 struct replica *replicas=0;
2446 struct nvldbentry entry,storeEntry;
2447 int i, volcount, m, fullrelease, vldbindex;
2449 struct restoreCookie cookie;
2450 struct rx_connection **toconns=0;
2451 struct release *times=0;
2453 struct rx_connection *fromconn = (struct rx_connection *)0;
2454 afs_int32 error = 0;
2456 afs_int32 clonetid=0, onlinetid;
2457 afs_int32 fromtid=0;
2458 afs_uint32 fromdate, thisdate;
2461 manyResults results;
2462 int rwindex, roindex, roclone, roexists;
2467 } remembertime[NMAXNSERVERS];
2468 int releasecount = 0;
2469 struct volser_status volstatus;
2471 memset((char *)remembertime, 0, sizeof(remembertime));
2472 memset((char *)&results, 0, sizeof(results));
2474 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
2475 if (vcode != VL_RERELEASE)
2476 ONERROR(vcode, afromvol, "Could not lock the VLDB entry for the volume %u.\n");
2479 /* Get the vldb entry in readable format */
2480 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
2481 ONERROR(vcode, afromvol, "Could not fetch the entry for the volume %u from the VLDB.\n");
2482 MapHostToNetwork(&entry);
2485 EnumerateEntry(&entry);
2487 if (!ISNAMEVALID(entry.name))
2488 ONERROR(VOLSERBADOP, entry.name,
2489 "Volume name %s is too long, rename before releasing.\n");
2490 if (entry.volumeId[RWVOL] != afromvol)
2491 ONERROR(VOLSERBADOP, afromvol,
2492 "The volume %u being released is not a read-write volume.\n");
2493 if (entry.nServers <= 1)
2494 ONERROR(VOLSERBADOP, afromvol,
2495 "Volume %u has no replicas - release operation is meaningless!\n");
2496 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
2497 ONERROR(VOLSERBADOP, entry.name,
2498 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
2500 /* roclone is true if one of the RO volumes is on the same
2501 * partition as the RW volume. In this case, we make the RO volume
2502 * on the same partition a clone instead of a complete copy.
2505 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
2506 roclone = ((roindex == -1) ? 0 : 1);
2507 rwindex = Lp_GetRwIndex(&entry);
2509 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
2511 /* Make sure we have a RO volume id to work with */
2512 if (entry.volumeId[ROVOL] == INVALID_BID) {
2513 /* need to get a new RO volume id */
2514 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
2515 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
2517 entry.volumeId[ROVOL] = roVolId;
2518 MapNetworkToHost(&entry, &storeEntry);
2519 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2520 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2523 /* Will we be completing a previously unfinished release. -force overrides */
2524 for (fullrelease=1, i=0; (fullrelease && (i<entry.nServers)); i++) {
2525 if (entry.serverFlags[i] & NEW_REPSITE)
2528 if (forceflag && !fullrelease)
2531 /* Determine which volume id to use and see if it exists */
2532 cloneVolId = ((fullrelease || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
2533 code = VolumeExists(afromserver, afrompart, cloneVolId);
2534 roexists = ((code == ENODEV) ? 0 : 1);
2535 if (!roexists && !fullrelease)
2536 fullrelease = 1; /* Do a full release if RO clone does not exist */
2540 fprintf(STDOUT,"This is a complete release of the volume %u\n", afromvol);
2542 fprintf(STDOUT,"This is a completion of the previous release\n");
2546 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2548 ONERROR(-1, afromserver, "Cannot establish connection with server 0x%x\n");
2551 /* If the RO clone exists, then if the clone is a temporary
2552 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2553 * (it was recently added), then also delete it. We do not
2554 * want to "reclone" a temporary RO clone.
2557 (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE)) ) {
2558 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2559 if (code && (code != VNOVOL))
2564 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2565 * write this entry out to the vlserver until after the first
2566 * RO volume is released (temp RO clones don't count).
2568 for (i=0; i<entry.nServers; i++) {
2569 entry.serverFlags[i] &= ~NEW_REPSITE;
2570 entry.serverFlags[i] |= RO_DONTUSE;
2572 entry.serverFlags[rwindex] |= NEW_REPSITE;
2573 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2575 /* Begin transaction on RW and mark it busy while we clone it */
2576 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &clonetid);
2577 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2579 /* Clone or reclone the volume */
2581 VPRINT1("Recloning RW volume %u...", cloneVolId);
2582 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2583 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2587 strcpy(vname, entry.name);
2588 strcat(vname, ".readonly");
2589 VPRINT("Cloning RW volume %u to permanent RO...");
2591 strcpy(vname, "readonly-clone-temp");
2592 VPRINT("Cloning RW volume %u to temporary RO...");
2594 code = AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, &cloneVolId);
2595 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
2599 /* Get the time the RW was created for future information */
2600 VPRINT1("Getting status of RW volume %u...", cloneVolId);
2601 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
2602 ONERROR(code, cloneVolId, "Failed to get the status of the RW volume %u\n");
2604 rwcrdate = volstatus.creationDate;
2606 /* End the transaction on the RW volume */
2607 VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
2608 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2610 ONERROR((code?code:rcode), cloneVolId, "Failed to end cloning transaction on RW %u\n");
2613 /* Remember clone volume ID in case we fail or are interrupted */
2614 entry.cloneId = cloneVolId;
2617 /* Bring the RO clone online - though not if it's a temporary clone */
2618 VPRINT1("Starting transaction on RO clone volume %u...", cloneVolId);
2619 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline, &onlinetid);
2620 ONERROR(code, cloneVolId, "Failed to start transaction on volume %u\n");
2623 VPRINT1("Setting volume flags for volume %u...", cloneVolId);
2624 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
2627 VPRINT1("Ending transaction on volume %u...", cloneVolId);
2628 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
2629 ONERROR((code?code:rcode), cloneVolId, "Failed to end transaction on RO clone %u\n");
2632 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
2634 /* Sleep so that a client searching for an online volume won't
2635 * find the clone offline and then the next RO offline while the
2636 * release brings the clone online and the next RO offline (race).
2637 * There is a fix in the 3.4 client that does not need this sleep
2638 * anymore, but we don't know what clients we have.
2640 if (entry.nServers > 2)
2643 /* Mark the RO clone in the VLDB as a good site (already released)*/
2644 entry.serverFlags[roindex] |= NEW_REPSITE;
2645 entry.serverFlags[roindex] &= ~RO_DONTUSE;
2646 entry.flags |= RO_EXISTS;
2650 /* Write out the VLDB entry only if the clone is not a temporary
2651 * clone. If we did this to a temporary clone then we would end
2652 * up marking all the ROs as "old release" making the ROs
2653 * temporarily unavailable.
2655 MapNetworkToHost(&entry, &storeEntry);
2656 VPRINT1("Replacing VLDB entry for %s...", entry.name);
2657 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2658 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2663 /* Now we will release from the clone to the remaining RO replicas.
2664 * The first 2 ROs (counting the non-temporary RO clone) are released
2665 * individually: releasecount. This is to reduce the race condition
2666 * of clients trying to find an on-line RO volume. The remaining ROs
2667 * are released in parallel but no more than half the number of ROs
2668 * (rounded up) at a time: nservers.
2671 strcpy(vname, entry.name);
2672 strcat(vname, ".readonly");
2673 memset(&cookie, 0, sizeof(cookie));
2674 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
2675 cookie.type = ROVOL;
2676 cookie.parent = entry.volumeId[RWVOL];
2679 nservers = entry.nServers/2; /* how many to do at once, excluding clone */
2680 replicas = (struct replica *) malloc (sizeof(struct replica)*nservers+1);
2681 times = (struct release *) malloc (sizeof(struct release)*nservers+1);
2682 toconns = (struct rx_connection **) malloc (sizeof(struct rx_connection *)*nservers+1);
2683 results.manyResults_val = (afs_int32 *) malloc (sizeof(afs_int32)*nservers+1);
2684 if ( !replicas || !times || !! !results.manyResults_val || !toconns )
2685 ONERROR(ENOMEM, 0, "Failed to create transaction on the release clone\n");
2687 memset(replicas, 0, (sizeof(struct replica)*nservers+1));
2688 memset(times, 0, (sizeof(struct release)*nservers+1));
2689 memset(toconns, 0, (sizeof(struct rx_connection *)*nservers+1));
2690 memset(results.manyResults_val, 0, (sizeof(afs_int32)*nservers+1));
2692 /* Create a transaction on the cloned volume */
2693 VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
2694 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
2695 if (!fullrelease && code)
2696 ONERROR(VOLSERNOVOL, afromvol,"Old clone is inaccessible. Try vos release -f %u.\n");
2697 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
2700 /* For each index in the VLDB */
2701 for (vldbindex=0; vldbindex<entry.nServers; ) {
2703 /* Get a transaction on the replicas. Pick replacas which have an old release. */
2704 for (volcount=0; ((volcount<nservers) && (vldbindex<entry.nServers)); vldbindex++) {
2705 /* The first two RO volumes will be released individually.
2706 * The rest are then released in parallel. This is a hack
2707 * for clients not recognizing right away when a RO volume
2708 * comes back on-line.
2710 if ((volcount == 1) && (releasecount < 2))
2713 if (vldbindex == roindex) continue; /* the clone */
2714 if ( (entry.serverFlags[vldbindex] & NEW_REPSITE) &&
2715 !(entry.serverFlags[vldbindex] & RO_DONTUSE) ) continue;
2716 if (!(entry.serverFlags[vldbindex] & ITSROVOL)) continue; /* not a RO vol */
2719 /* Get a Transaction on this replica. Get a new connection if
2720 * necessary. Create the volume if necessary. Return the
2721 * time from which the dump should be made (0 if it's a new
2722 * volume). Each volume might have a different time.
2724 replicas[volcount].server.destHost = ntohl(entry.serverNumber[vldbindex]);
2725 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
2726 replicas[volcount].server.destSSID = 1;
2727 times[volcount].vldbEntryIndex = vldbindex;
2729 code = GetTrans(&entry, vldbindex, &(toconns[volcount]),
2730 &(replicas[volcount].trans), &(times[volcount].time));
2733 /* Thisdate is the date from which we want to pick up all changes */
2734 if (forceflag || !fullrelease || (rwcrdate > times[volcount].time)) {
2735 /* If the forceflag is set, then we want to do a full dump.
2736 * If it's not a full release, we can't be sure that the creation
2737 * date is good (so we also do a full dump).
2738 * If the RW volume was replaced (its creation date is newer than
2739 * the last release), then we can't be sure what has changed (so
2740 * we do a full dump).
2743 } else if (remembertime[vldbindex].validtime) {
2744 /* Trans was prev ended. Use the time from the prev trans
2745 * because, prev trans may have created the volume. In which
2746 * case time[volcount].time would be now instead of 0.
2748 thisdate = (remembertime[vldbindex].time < times[volcount].time) ?
2749 remembertime[vldbindex].time : times[volcount].time;
2751 thisdate = times[volcount].time;
2753 remembertime[vldbindex].validtime = 1;
2754 remembertime[vldbindex].time = thisdate;
2756 if (volcount == 0) {
2757 fromdate = thisdate;
2759 /* Include this volume if it is within 15 minutes of the earliest */
2760 if (((fromdate>thisdate)?(fromdate-thisdate):(thisdate-fromdate)) > 900) {
2761 AFSVolEndTrans(toconns[volcount], replicas[volcount].trans, &rcode);
2762 replicas[volcount].trans = 0;
2765 if (thisdate < fromdate)
2766 fromdate = thisdate;
2770 if (!volcount) continue;
2773 fprintf(STDOUT,"Starting ForwardMulti from %u to %u on %s",
2774 cloneVolId, entry.volumeId[ROVOL],
2775 hostutil_GetNameByINet(entry.serverNumber[times[0].vldbEntryIndex]));
2777 for (s=1; s<volcount; s++) {
2778 fprintf(STDOUT," and %s",
2779 hostutil_GetNameByINet(entry.serverNumber[times[s].vldbEntryIndex]));
2783 fprintf(STDOUT," (full release)");
2784 fprintf(STDOUT,".\n");
2788 /* Release the ones we have collected */
2789 tr.manyDests_val = &(replicas[0]);
2790 tr.manyDests_len = results.manyResults_len = volcount;
2791 code = AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2792 if (code == RXGEN_OPCODE) { /* RPC Interface Mismatch */
2793 code = SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2798 PrintError("Release failed: ", code);
2800 for (m=0; m<volcount; m++) {
2801 if (results.manyResults_val[m]) {
2802 if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
2803 /* we retry timed out transaction. When it is
2804 * not the first volume and the transaction wasn't found
2805 * (assume it timed out and was garbage collected by volser).
2807 PrintError("Failed to dump volume from clone to a ro site: ",
2808 results.manyResults_val[m]);
2813 code = AFSVolSetIdsTypes(toconns[m], replicas[m].trans,
2814 vname, ROVOL, entry.volumeId[RWVOL], 0, 0);
2816 if ((m == 0) || (code != ENOENT)) {
2817 PrintError("Failed to set correct names and ids: ", code);
2822 /* have to clear dest. flags to ensure new vol goes online:
2823 * because the restore (forwarded) operation copied
2824 * the V_inService(=0) flag over to the destination.
2826 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
2828 if ((m == 0) || (code != ENOENT)) {
2829 PrintError("Failed to set flags on ro volume: ", code);
2834 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
2835 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
2836 entry.flags |= RO_EXISTS;
2841 /* End the transactions and destroy the connections */
2842 for (s=0; s<volcount; s++) {
2843 if (replicas[s].trans)
2844 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
2845 replicas[s].trans = 0;
2846 if (!code) code = rcode;
2848 if ((s == 0) || (code != ENOENT)) {
2849 PrintError("Could not end transaction on a ro volume: ", code);
2851 PrintError("Transaction timed out on a ro volume. Will retry.\n", 0);
2852 if (times[s].vldbEntryIndex < vldbindex)
2853 vldbindex = times[s].vldbEntryIndex;
2858 rx_DestroyConnection(toconns[s]);
2862 MapNetworkToHost(&entry, &storeEntry);
2863 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2864 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2865 } /* for each index in the vldb */
2867 /* End the transaction on the cloned volume */
2868 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2870 if (!code) code = rcode;
2872 PrintError("Failed to end transaction on rw volume: ", code);
2874 /* Figure out if any volume were not released and say so */
2875 for (failure=0, i=0; i<entry.nServers; i++) {
2876 if (!(entry.serverFlags[i] & NEW_REPSITE))
2881 fprintf(STDERR, "The volume %u could not be released to the following %d sites:\n",
2883 for (i=0; i<entry.nServers; i++) {
2884 if (!(entry.serverFlags[i] & NEW_REPSITE)) {
2885 MapPartIdIntoName(entry.serverPartition[i],pname);
2886 fprintf(STDERR,"\t%35s %s\n",
2887 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
2891 MapNetworkToHost(&entry,&storeEntry);
2892 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, LOCKREL_TIMESTAMP);
2893 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2895 ERROREXIT(VOLSERBADRELEASE);
2898 /* All the ROs were release successfully. Remove the temporary clone */
2901 fprintf(STDOUT,"Deleting the releaseClone %u ...", cloneVolId);
2904 code = DelVol (fromconn, cloneVolId, afrompart, ITOffline);
2905 ONERROR (code, cloneVolId, "Failed to delete volume %u.\n");
2910 for (i=0; i<entry.nServers; i++)
2911 entry.serverFlags[i] &= ~NEW_REPSITE;
2913 /* Update the VLDB */
2914 VPRINT("updating VLDB ...");
2916 MapNetworkToHost(&entry, &storeEntry);
2917 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
2918 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2919 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2924 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2927 fprintf (STDERR,"Failed to end cloning transaction on the RW volume %u\n", afromvol);
2928 if (!error) error = code;
2932 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2935 fprintf (STDERR,"Failed to end transaction on the release clone %u\n", cloneVolId);
2936 if (!error) error = code;
2939 for (i=0; i<nservers; i++) {
2940 if (replicas && replicas[i].trans) {
2941 code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
2942 replicas[i].trans = 0;
2944 fprintf(STDERR,"Failed to end transaction on ro volume %u at server 0x%x\n",
2945 entry.volumeId[ROVOL],
2946 hostutil_GetNameByINet(htonl(replicas[i].server.destHost)));
2947 if (!error) error = code;
2950 if (toconns && toconns[i]) {
2951 rx_DestroyConnection(toconns[i]);
2956 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, RWVOL,
2957 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2959 fprintf(STDERR,"Could not release lock on the VLDB entry for volume %u\n", afromvol);
2960 if (!error) error = vcode;
2964 PrintError("", error);
2966 if (fromconn) rx_DestroyConnection(fromconn);
2967 if (results.manyResults_val) free (results.manyResults_val);
2968 if (replicas) free (replicas);
2969 if (toconns) free (toconns);
2970 if (times) free (times);
2975 void dump_sig_handler(int x)
2977 fprintf(STDERR,"\nSignal handler: vos dump operation\n");
2981 /* Dump the volume <afromvol> on <afromserver> and
2982 * <afrompart> to <afilename> starting from <fromdate>.
2983 * DumpFunction does the real work behind the scenes after
2984 * extracting parameters from the rock
2986 int UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2987 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
2989 struct rx_connection *fromconn = (struct rx_connection *)0;
2990 struct rx_call *fromcall = (struct rx_call *)0;
2991 afs_int32 fromtid=0, rxError=0, rcode=0;
2992 afs_int32 code, error = 0;
2994 if (setjmp(env)) ERROR_EXIT(EPIPE);
2995 #ifndef AFS_NT40_ENV
2996 (void) signal(SIGPIPE, dump_sig_handler);
2998 (void) signal(SIGINT, dump_sig_handler);
3002 VPRINT("Full Dump ...\n");
3006 VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
3009 /* get connections to the servers */
3010 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3012 VPRINT1("Starting transaction on volume %u...", afromvol);
3013 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3014 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3017 fromcall = rx_NewCall(fromconn);
3019 VPRINT1("Starting volume dump on volume %u...", afromvol);
3020 code = StartAFSVolDump(fromcall, fromtid, fromdate);
3021 EGOTO(error_exit, code, "Could not start the dump process \n");
3024 VPRINT1("Dumping volume %u...", afromvol);
3025 code = DumpFunction(fromcall, rock);
3026 EGOTO(error_exit, code, "Error while dumping volume \n");
3031 code = rx_EndCall(fromcall, rxError);
3033 fprintf(STDERR,"Error in rx_EndCall\n");
3034 if (!error) error = code;
3038 VPRINT1("Ending transaction on volume %u...", afromvol);
3039 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3040 if (code || rcode) {
3041 fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol);
3042 if (!error) error = (code?code:rcode);
3047 rx_DestroyConnection(fromconn);
3049 PrintError("", error);
3053 /* Clone the volume <afromvol> on <afromserver> and
3054 * <afrompart>, and then dump the clone volume to
3055 * <afilename> starting from <fromdate>.
3056 * DumpFunction does the real work behind the scenes after
3057 * extracting parameters from the rock
3059 int UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
3060 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
3062 struct rx_connection *fromconn = (struct rx_connection *)0;
3063 struct rx_call *fromcall = (struct rx_call *)0;
3064 afs_int32 fromtid=0, rxError=0, rcode=0;
3065 afs_int32 clonetid=0;
3066 afs_int32 code=0, vcode=0, error = 0;
3067 afs_int32 clonevol=0;
3070 if (setjmp(env)) ERROR_EXIT(EPIPE);
3071 #ifndef AFS_NT40_ENV
3072 (void) signal(SIGPIPE, dump_sig_handler);
3074 (void) signal(SIGINT, dump_sig_handler);
3078 VPRINT("Full Dump ...\n");
3082 VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
3085 /* get connections to the servers */
3086 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3088 VPRINT1("Starting transaction on volume %u...", afromvol);
3089 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3090 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3093 /* Get a clone id */
3094 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
3095 code = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &clonevol);
3096 EGOTO1(error_exit, code, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
3099 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
3100 VPRINT2("Cloning source volume %u to clone volume %u...", afromvol, clonevol);
3101 strcpy(vname, "dump-clone-temp");
3102 code = AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
3103 EGOTO1(error_exit, code, "Failed to clone the source volume %u\n", afromvol);
3106 VPRINT1("Ending the transaction on the volume %u ...", afromvol);
3108 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3110 if (!code) code = rcode;
3111 EGOTO1(error_exit, code, "Failed to end the transaction on the volume %u\n", afromvol);
3115 VPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
3116 code = AFSVolTransCreate (fromconn, clonevol, afrompart, ITOffline, &clonetid);
3117 EGOTO1(error_exit, code, "Failed to start a transaction on the cloned volume%u\n", clonevol);
3120 VPRINT1("Setting flags on cloned volume %u ...", clonevol);
3121 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
3122 EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n", clonevol);
3126 fromcall = rx_NewCall(fromconn);
3128 VPRINT1("Starting volume dump from cloned volume %u...", clonevol);
3129 code = StartAFSVolDump(fromcall, clonetid, fromdate);
3130 EGOTO(error_exit, code, "Could not start the dump process \n");
3133 VPRINT1("Dumping volume %u...", afromvol);
3134 code = DumpFunction(fromcall, rock);
3135 EGOTO(error_exit, code, "Error while dumping volume \n");
3139 /* now delete the clone */
3140 VPRINT1("Deleting the cloned volume %u ...", clonevol);
3141 code = AFSVolDeleteVolume(fromconn, clonetid);
3144 fprintf(STDERR,"Failed to delete the cloned volume %u\n", clonevol);
3152 code = rx_EndCall(fromcall, rxError);
3154 fprintf(STDERR,"Error in rx_EndCall\n");
3155 if (!error) error = code;
3159 VPRINT1("Ending transaction on cloned volume %u...", clonevol);
3160 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3161 if (code || rcode) {
3162 fprintf(STDERR,"Could not end transaction on the cloned volume %u\n", clonevol);
3163 if (!error) error = (code?code:rcode);
3168 rx_DestroyConnection(fromconn);
3170 PrintError("", error);
3177 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
3178 * the dump file <afilename>. WriteData does all the real work
3179 * after extracting params from the rock
3181 int UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
3182 char tovolname[], int flags, afs_int32 (*WriteData)(), char *rock)
3184 struct rx_connection *toconn,*tempconn;
3185 struct rx_call *tocall;
3186 afs_int32 totid, code, rcode, vcode,terror = 0;
3187 afs_int32 rxError = 0;
3188 struct volser_status tstatus;
3193 struct nvldbentry entry,storeEntry;
3196 struct restoreCookie cookie;
3198 afs_int32 newDate, volflag, voltype, volsertype;
3199 int index, same, errcode;
3203 memset(&cookie, 0, sizeof(cookie));
3208 tocall = (struct rx_call *)0;
3209 toconn = (struct rx_connection *)0;
3210 tempconn = (struct rx_connection *)0;
3214 if (flags & RV_RDONLY) {
3216 volsertype = volser_RO;
3219 volsertype = volser_RW;
3223 toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
3224 if(pvolid == 0) {/*alot a new id if needed */
3225 vcode = VLDB_GetEntryByName(tovolname, &entry);
3226 if(vcode == VL_NOENT) {
3227 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 1, &pvolid);
3229 fprintf(STDERR,"Could not get an Id for the volume %s\n",tovolname);
3234 } else if (flags & RV_RDONLY) {
3235 if (entry.flags & RW_EXISTS) {
3236 fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
3237 error = VOLSERBADOP;
3240 if (!entry.volumeId[ROVOL]) {
3241 fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
3242 error = VOLSERBADOP;
3245 pvolid = entry.volumeId[ROVOL];
3247 pvolid = entry.volumeId[RWVOL];
3249 }/* at this point we have a volume id to use/reuse for the volume to be restored */
3251 if(strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
3252 EGOTO1(refail, VOLSERBADOP, "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",tovolname);
3254 MapPartIdIntoName(topart, partName);
3255 fprintf(STDOUT,"Restoring volume %s Id %u on server %s partition %s ..", tovolname,
3256 pvolid, hostutil_GetNameByINet(toserver), partName);
3258 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3260 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
3261 VPRINT1("Deleting the previous volume %u ...",pvolid);
3263 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3264 EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3266 code = AFSVolSetFlags(toconn, totid, VTDeleteOnSalvage | VTOutOfService);
3267 EGOTO1(refail, code, "Could not set flags on volume %u \n",pvolid);
3269 code = AFSVolDeleteVolume(toconn,totid);
3270 EGOTO1(refail, code, "Could not delete volume %u\n",pvolid);
3272 code = AFSVolEndTrans(toconn, totid, &rcode);
3274 if (!code) code = rcode;
3275 EGOTO1(refail, code, "Could not end transaction on %u\n",pvolid);
3279 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3280 EGOTO1(refail, code, "Could not create new volume %u\n",pvolid);
3283 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3284 EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3287 cookie.parent = pvolid;
3288 cookie.type = voltype;
3290 strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
3292 tocall = rx_NewCall(toconn);
3293 terror = StartAFSVolRestore(tocall,totid, 1,&cookie);
3295 fprintf(STDERR,"Volume restore Failed \n");
3299 code = WriteData(tocall, rock);
3301 fprintf(STDERR,"Could not transmit data\n");
3305 terror = rx_EndCall(tocall,rxError);
3306 tocall = (struct rx_call *) 0;
3308 fprintf(STDERR,"rx_EndCall Failed \n");
3312 code = AFSVolGetStatus(toconn,totid, &tstatus);
3314 fprintf(STDERR,"Could not get status information about the volume %u\n",pvolid);
3318 code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
3320 fprintf(STDERR,"Could not set the right type and ID on %u\n",pvolid);
3325 code = AFSVolSetDate(toconn,totid, newDate);
3327 fprintf(STDERR,"Could not set the date on %u\n",pvolid);
3332 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
3333 code = AFSVolSetFlags(toconn, totid, volflag);
3335 fprintf(STDERR,"Could not mark %u online\n",pvolid );
3340 /* It isn't handled right in refail */
3341 code = AFSVolEndTrans(toconn, totid, &rcode);
3343 if(!code) code = rcode;
3345 fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
3351 fprintf(STDOUT," done\n");
3353 if (success && (!reuseID || (flags & RV_FULLRST))) {
3354 /* Volume was restored on the file server, update the
3355 * VLDB to reflect the change.
3357 vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
3358 if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
3359 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",pvolid);
3363 if (!vcode) MapHostToNetwork(&entry);
3364 if(vcode == VL_NOENT) { /* it doesnot exist already */
3365 /*make the vldb return this indication specifically*/
3366 VPRINT("------- Creating a new VLDB entry ------- \n");
3367 strcpy(entry.name, tovolname);
3369 entry.serverNumber[0] = toserver;/*should be indirect */
3370 entry.serverPartition[0] = topart;
3371 entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3372 entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3373 if (flags & RV_RDONLY)
3374 entry.volumeId[ROVOL] = pvolid;
3375 else if(tstatus.cloneID != 0){
3376 entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
3379 entry.volumeId[ROVOL] = INVALID_BID;
3380 entry.volumeId[RWVOL] = pvolid;
3382 if(tstatus.backupID != 0){
3383 entry.volumeId[BACKVOL] = tstatus.backupID;
3384 /*this should come from status info on the volume if non zero */
3387 entry.volumeId[BACKVOL] = INVALID_BID;
3388 MapNetworkToHost(&entry,&storeEntry);
3389 vcode = VLDB_CreateEntry(&storeEntry);
3391 fprintf(STDERR,"Could not create the VLDB entry for volume number %u \n",pvolid);
3396 if (verbose) EnumerateEntry(&entry);
3398 else { /*update the existing entry */
3400 fprintf(STDOUT,"Updating the existing VLDB entry\n");
3401 fprintf(STDOUT,"------- Old entry -------\n");
3402 EnumerateEntry(&entry);
3403 fprintf(STDOUT,"------- New entry -------\n");
3405 vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
3407 fprintf(STDERR,"Could not lock the entry for volume number %u \n",pvolid);
3412 strcpy(entry.name, tovolname);
3414 /* Update the vlentry with the new information */
3415 if (flags & RV_RDONLY)
3416 index = Lp_ROMatch(toserver, topart, &entry) - 1;
3418 index = Lp_GetRwIndex(&entry);
3420 /* Add the new site for the volume being restored */
3421 entry.serverNumber[entry.nServers] = toserver;
3422 entry.serverPartition[entry.nServers] = topart;
3423 entry.serverFlags[entry.nServers] =
3424 (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3427 /* This volume should be deleted on the old site
3428 * if its different from new site.
3430 same = VLDB_IsSameAddrs(toserver, entry.serverNumber[index], &errcode);
3431 EPRINT2(errcode, "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
3433 if ( (!errcode && !same) || (entry.serverPartition[index] != topart) ) {
3434 tempconn = UV_Bind(entry.serverNumber[index], AFSCONF_VOLUMEPORT);
3436 MapPartIdIntoName(entry.serverPartition[index], apartName);
3437 VPRINT3("Deleting the previous volume %u on server %s, partition %s ...",
3439 hostutil_GetNameByINet(entry.serverNumber[index]), apartName);
3440 code = AFSVolTransCreate(tempconn, pvolid, entry.serverPartition[index], ITOffline, &temptid);
3442 code = AFSVolSetFlags(tempconn, temptid, VTDeleteOnSalvage | VTOutOfService);
3444 fprintf(STDERR,"Could not set flags on volume %u on the older site\n",pvolid);
3448 code = AFSVolDeleteVolume(tempconn,temptid);
3450 fprintf(STDERR,"Could not delete volume %u on the older site\n",pvolid);
3454 code = AFSVolEndTrans(tempconn, temptid, &rcode);
3456 if(!code) code = rcode;
3458 fprintf(STDERR,"Could not end transaction on volume %u on the older site\n",pvolid);
3463 MapPartIdIntoName(entry.serverPartition[index],partName);
3466 entry.serverNumber[index] = toserver;
3467 entry.serverPartition[index] = topart;
3470 entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3471 MapNetworkToHost(&entry,&storeEntry);
3472 vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3474 fprintf(STDERR,"Could not update the entry for volume number %u \n",pvolid);
3479 if(verbose) EnumerateEntry(&entry);
3486 code = rx_EndCall(tocall, rxError);
3487 if (!error) error = code;
3490 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3492 fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %u\n",pvolid);
3493 if(!error) error = vcode;
3497 code = AFSVolEndTrans(toconn, totid, &rcode);
3498 if(!code) code = rcode;
3500 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
3501 if(!error) error = code;
3505 code = AFSVolEndTrans(toconn, temptid, &rcode);
3506 if(!code) code = rcode;
3508 fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
3509 if(!error) error = code;
3512 if(tempconn) rx_DestroyConnection(tempconn);
3513 if(toconn) rx_DestroyConnection(toconn);
3514 PrintError("",error);
3519 /*unlocks the vldb entry associated with <volid> */
3520 int UV_LockRelease(afs_int32 volid)
3526 VPRINT("Binding to the VLDB server\n");
3527 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,volid,-1,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3529 fprintf(STDERR,"Could not unlock the entry for volume number %u in VLDB \n",volid);
3530 PrintError("",vcode);
3533 VPRINT("VLDB updated\n");
3538 /*adds <server> and <part> as a readonly replication site for <volid>
3540 int UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3542 int j, nro=0, islocked=0;
3543 struct nvldbentry entry,storeEntry;
3544 afs_int32 vcode, error=0;
3547 error = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3549 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n", volid);
3554 error = VLDB_GetEntryByID(volid,RWVOL, &entry);
3556 fprintf(STDERR,"Could not fetch the VLDB entry for volume number %u \n",volid);
3560 if (!ISNAMEVALID(entry.name)){
3561 fprintf(STDERR,"Volume name %s is too long, rename before adding site\n", entry.name);
3562 error = VOLSERBADOP;
3565 MapHostToNetwork(&entry);
3567 /* See if it's too many entries */
3568 if (entry.nServers >= NMAXNSERVERS){
3569 fprintf(STDERR,"Total number of entries will exceed %u\n", NMAXNSERVERS);
3570 error = VOLSERBADOP;
3574 /* See if it's on the same server */
3575 for (j=0; j < entry.nServers; j++) {
3576 if (entry.serverFlags[j] & ITSROVOL) {
3578 if (VLDB_IsSameAddrs(server, entry.serverNumber[j], &error)) {
3580 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
3583 MapPartIdIntoName(entry.serverPartition[j], apartName);
3584 fprintf(STDERR,"RO already exists on partition %s. Multiple ROs on a single server aren't allowed\n", apartName);
3585 error = VOLSERBADOP;
3592 /* See if it's too many RO sites - leave one for the RW */
3593 if (nro >= NMAXNSERVERS-1){
3594 fprintf(STDERR,"Total number of sites will exceed %u\n", NMAXNSERVERS-1);
3595 error = VOLSERBADOP;
3599 VPRINT("Adding a new site ...");
3600 entry.serverNumber[entry.nServers] = server;
3601 entry.serverPartition[entry.nServers] = part;
3602 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
3605 MapNetworkToHost(&entry,&storeEntry);
3606 error = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3608 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3616 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3618 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3619 PrintError("", vcode);
3623 PrintError("", error);
3627 /*removes <server> <part> as read only site for <volid> from the vldb */
3628 int UV_RemoveSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3631 struct nvldbentry entry,storeEntry;
3634 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3636 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3637 PrintError("",vcode);
3641 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3643 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3644 PrintError("",vcode);
3647 MapHostToNetwork(&entry);
3648 if(!Lp_ROMatch(server, part, &entry)){
3649 /*this site doesnot exist */
3650 fprintf(STDERR,"This site is not a replication site \n");
3651 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3653 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3654 PrintError("",vcode);
3655 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3660 else { /*remove the rep site */
3661 Lp_SetROValue(&entry, server, part, 0, 0);
3663 if((entry.nServers == 1) && (entry.flags & RW_EXISTS))
3664 entry.flags &= ~RO_EXISTS;
3665 if(entry.nServers < 1) { /*this is the last ref */
3666 VPRINT1("Deleting the VLDB entry for %u ...",volid);
3668 vcode = ubik_Call(VL_DeleteEntry,cstruct, 0,volid, ROVOL);
3670 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",volid);
3671 PrintError("",vcode);
3676 MapNetworkToHost(&entry,&storeEntry);
3677 fprintf(STDOUT,"Deleting the replication site for volume %u ...",volid);
3679 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3681 fprintf(STDERR,"Could not release lock on volume entry for %u \n",volid);
3682 PrintError("",vcode);
3683 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3691 /*sets <server> <part> as read/write site for <volid> in the vldb */
3692 int UV_ChangeLocation(afs_int32 server, afs_int32 part, afs_int32 volid)
3695 struct nvldbentry entry,storeEntry;
3698 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3700 fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
3701 PrintError("",vcode);
3704 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3706 fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
3707 PrintError("",vcode);
3710 MapHostToNetwork(&entry);
3711 index = Lp_GetRwIndex(&entry);
3713 /* no RW site exists */
3714 fprintf(STDERR,"No existing RW site for volume %u", volid);
3715 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3717 fprintf(STDERR,"Could not release lock on entry for volume %u \n",volid);
3718 PrintError("",vcode);
3723 else { /* change the RW site */
3724 entry.serverNumber[index] = server;
3725 entry.serverPartition[index] = part;
3726 MapNetworkToHost(&entry,&storeEntry);
3727 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3729 fprintf(STDERR,"Could not update entry for volume %u \n",volid);
3730 PrintError("",vcode);
3731 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3739 /*list all the partitions on <aserver> */
3740 int UV_ListPartitions(afs_int32 aserver, struct partList *ptrPartList, afs_int32 *cntp)
3742 struct rx_connection *aconn;
3743 struct pIDs partIds;
3744 struct partEntries partEnts;
3745 register int i, j=0, code;
3748 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3750 partEnts.partEntries_len = 0;
3751 partEnts.partEntries_val = NULL;
3752 code = AFSVolXListPartitions(aconn, &partEnts); /* this is available only on new servers */
3753 if (code == RXGEN_OPCODE)
3755 for(i = 0; i < 26; i++) /* try old interface */
3756 partIds.partIds[i] = -1;
3757 code = AFSVolListPartitions(aconn, &partIds);
3759 for (i = 0;i < 26; i++) {
3760 if((partIds.partIds[i]) != -1) {
3761 ptrPartList->partId[j] = partIds.partIds[i];
3762 ptrPartList->partFlags[j] = PARTVALID;
3765 ptrPartList->partFlags[i] = 0;
3772 *cntp = partEnts.partEntries_len;
3773 if (*cntp > VOLMAXPARTS) {
3774 fprintf(STDERR,"Warning: number of partitions on the server too high %d (process only %d)\n",
3775 *cntp, VOLMAXPARTS);
3776 *cntp = VOLMAXPARTS;
3778 for (i = 0;i < *cntp; i++) {
3779 ptrPartList->partId[i] = partEnts.partEntries_val[i];
3780 ptrPartList->partFlags[i] = PARTVALID;
3782 free(partEnts.partEntries_val);
3786 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
3787 PrintError("",code);
3788 if(aconn) rx_DestroyConnection(aconn);
3793 /*zap the list of volumes specified by volPtrArray (the volCloneId field).
3794 This is used by the backup system */
3795 int UV_ZapVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3797 struct rx_connection *aconn;
3798 struct volDescription *curPtr;
3801 afs_int32 rcode = 0;
3802 afs_int32 success = 1;
3805 aconn = (struct rx_connection *)0;
3806 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3808 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3809 if(curPtr->volFlags & CLONEVALID) {
3810 curPtr->volFlags &= ~CLONEZAPPED;
3812 code = AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline, &tid);
3813 if(code) success = 0;
3815 code = AFSVolDeleteVolume(aconn, tid);
3816 if(code) success = 0;
3817 code = AFSVolEndTrans(aconn, tid, &rcode);
3818 if(code || rcode) success = 0;
3820 if(success) curPtr->volFlags |= CLONEZAPPED;
3821 if(!success) fprintf(STDERR,"Could not zap volume %u\n",curPtr->volCloneId);
3822 if(success) VPRINT2("Clone of %s %u deleted\n", curPtr->volName,curPtr->volCloneId);
3827 if(aconn)rx_DestroyConnection(aconn);
3831 /*return a list of clones of the volumes specified by volPtrArray. Used by the
3833 int UV_GenerateVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3835 struct rx_connection *aconn;
3836 struct volDescription *curPtr;
3839 afs_int32 rcode = 0;
3841 int reuseCloneId = 0;
3842 afs_int32 curCloneId = 0;
3843 char cloneName[256];/*max vol name */
3845 aconn = (struct rx_connection *)0;
3846 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3848 if((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
3850 else { /*get a bunch of id's from vldb */
3851 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, arraySize, &curCloneId);
3853 fprintf(STDERR,"Could not get ID's for the clone from VLDB\n");
3854 PrintError("",code);
3859 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3860 if(curPtr->volFlags & ENTRYVALID) {
3862 curPtr->volFlags |= CLONEVALID;
3863 /*make a clone of curParentId and record as curPtr->volCloneId */
3864 code = AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline, &tid);
3865 if(code) VPRINT2("Clone for volume %s %u failed \n",curPtr->volName,curPtr->volId);
3867 curPtr->volFlags &= ~CLONEVALID; /*cant clone */
3871 if(strlen(curPtr->volName) < (VOLSER_OLDMAXVOLNAME - 9) ){
3872 strcpy(cloneName, curPtr->volName);
3873 strcat(cloneName,"-tmpClone-");
3875 else strcpy(cloneName,"-tmpClone");
3877 curPtr->volCloneId = curCloneId;
3881 code = AFSVolClone(aconn, tid, 0, readonlyVolume, cloneName,&(curPtr->volCloneId));
3883 curPtr->volFlags &= ~CLONEVALID;
3885 fprintf(STDERR,"Could not clone %s due to error %u\n", curPtr->volName,code);
3886 code=AFSVolEndTrans(aconn, tid, &rcode);
3888 fprintf(STDERR,"WARNING: could not end transaction\n");
3891 VPRINT2("********** Cloned %s temporary %u\n",cloneName,curPtr->volCloneId);
3892 code = AFSVolEndTrans(aconn, tid, &rcode);
3894 curPtr->volFlags &= ~CLONEVALID;
3902 if (aconn) rx_DestroyConnection(aconn);
3907 /*list all the volumes on <aserver> and <apart>. If all = 1, then all the
3908 * relevant fields of the volume are also returned. This is a heavy weight operation.*/
3909 int UV_ListVolumes(afs_int32 aserver, afs_int32 apart, int all, struct volintInfo **resultPtr, afs_int32 *size)
3911 struct rx_connection *aconn;
3913 volEntries volumeInfo;
3917 *resultPtr = (volintInfo *)0;
3918 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3919 volumeInfo.volEntries_len = 0;
3921 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3922 code = AFSVolListVolumes(aconn, apart, all, &volumeInfo);
3924 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
3927 *resultPtr = volumeInfo.volEntries_val;
3928 *size = volumeInfo.volEntries_len;
3931 if(aconn) rx_DestroyConnection(aconn);
3932 PrintError("",code);
3936 /*------------------------------------------------------------------------
3937 * EXPORTED UV_XListVolumes
3940 * List the extended information for all the volumes on a particular
3941 * File Server and partition. We may either return the volume's ID
3942 * or all of its extended information.
3945 * a_serverID : Address of the File Server for which we want
3946 * extended volume info.
3947 * a_partID : Partition for which we want the extended
3949 * a_all : If non-zero, fetch ALL the volume info,
3950 * otherwise just the volume ID.
3951 * a_resultPP : Ptr to the address of the area containing
3952 * the returned volume info.
3953 * a_numEntsInResultP : Ptr for the value we set for the number of
3958 * Otherise, the return value of AFSVolXListVolumes.
3961 * This routine is closely related to UV_ListVolumes, which returns
3962 * only the standard level of detail on AFS volumes. It is a
3963 * heavyweight operation, zipping through all the volume entries for
3964 * a given server/partition.
3968 *------------------------------------------------------------------------*/
3970 int UV_XListVolumes(afs_int32 a_serverID, afs_int32 a_partID, int a_all,
3971 struct volintXInfo **a_resultPP, afs_int32 *a_numEntsInResultP)
3973 struct rx_connection *rxConnP; /*Ptr to the Rx connection involved*/
3974 afs_int32 code; /*Error code to return*/
3975 volXEntries volumeXInfo; /*Area for returned extended vol info*/
3978 * Set up our error code and the area for returned extended volume info.
3979 * We set the val field to a null pointer as a hint for the stub to
3983 *a_numEntsInResultP = 0;
3984 *a_resultPP = (volintXInfo *)0;
3985 volumeXInfo.volXEntries_val = (volintXInfo *)0;
3986 volumeXInfo.volXEntries_len = 0;
3989 * Bind to the Volume Server port on the File Server machine in question,
3992 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
3993 code = AFSVolXListVolumes(rxConnP, a_partID, a_all, &volumeXInfo);
3996 "[UV_XListVolumes] Couldn't fetch volume list\n");
3999 * We got the info; pull out the pointer to where the results lie
4000 * and how many entries are there.
4002 *a_resultPP = volumeXInfo.volXEntries_val;
4003 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
4007 * If we got an Rx connection, throw it away.
4010 rx_DestroyConnection(rxConnP);
4012 PrintError("", code);
4014 } /*UV_XListVolumes*/
4016 /* get all the information about volume <volid> on <aserver> and <apart> */
4017 int UV_ListOneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 volid, struct volintInfo **resultPtr)
4019 struct rx_connection *aconn;
4021 volEntries volumeInfo;
4025 *resultPtr = (volintInfo *)0;
4026 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
4027 volumeInfo.volEntries_len = 0;
4029 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4030 code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
4032 fprintf(STDERR,"Could not fetch the information about volume %u from the server\n",volid);
4035 *resultPtr = volumeInfo.volEntries_val;
4039 if(aconn) rx_DestroyConnection(aconn);
4040 PrintError("",code);
4044 /*------------------------------------------------------------------------
4045 * EXPORTED UV_XListOneVolume
4048 * List the extended information for a volume on a particular File
4049 * Server and partition.
4052 * a_serverID : Address of the File Server for which we want
4053 * extended volume info.
4054 * a_partID : Partition for which we want the extended
4056 * a_volID : Volume ID for which we want the info.
4057 * a_resultPP : Ptr to the address of the area containing
4058 * the returned volume info.
4062 * Otherise, the return value of AFSVolXListOneVolume.
4065 * This routine is closely related to UV_ListOneVolume, which returns
4066 * only the standard level of detail on the chosen AFS volume.
4070 *------------------------------------------------------------------------*/
4072 int UV_XListOneVolume(afs_int32 a_serverID, afs_int32 a_partID,
4073 afs_int32 a_volID, struct volintXInfo **a_resultPP)
4075 struct rx_connection *rxConnP; /*Rx connection to Volume Server*/
4076 afs_int32 code; /*Error code*/
4077 volXEntries volumeXInfo; /*Area for returned info*/
4080 * Set up our error code, and the area we're in which we are returning
4081 * the info. Setting the val field to a null pointer tells the stub
4082 * to allocate space for us.
4085 *a_resultPP = (volintXInfo *)0;
4086 volumeXInfo.volXEntries_val = (volintXInfo *)0;
4087 volumeXInfo.volXEntries_len = 0;
4090 * Bind to the Volume Server port on the File Server machine in question,
4093 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
4094 code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
4097 "[UV_XListOneVolume] Couldn't fetch the volume information\n");
4100 * We got the info; pull out the pointer to where the results lie.
4102 *a_resultPP = volumeXInfo.volXEntries_val;
4105 * If we got an Rx connection, throw it away.
4108 rx_DestroyConnection(rxConnP);
4110 PrintError("",code);
4115 * Given a volume we read from a partition, check if it is
4116 * represented in the VLDB correctly.
4118 * The VLDB is looked up by the RW volume id (not its name).
4119 * The RW contains the true name of the volume (BK and RO set
4120 * the name in the VLDB only on creation of the VLDB entry).
4121 * We want rules strict enough that when we check all volumes
4122 * on one partition, it does not need to be done again. IE:
4123 * two volumes on different partitions won't constantly
4124 * change a VLDB entry away from what the other set.
4125 * For RW and BK volumes, we will always check the VLDB to see
4126 * if the two exist on the server/partition. May seem redundant,
4127 * but this is an easy check of the VLDB. IE: if the VLDB entry
4128 * says the BK exists but no BK volume is there, we will detect
4129 * this when we check the RW volume.
4130 * VLDB entries are locked only when a change needs to be done.
4131 * Output changed to look a lot like the "vos syncserv" otuput.
4133 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart,
4134 afs_int32 *modentry, afs_uint32 *maxvolid)
4137 afs_int32 code, error = 0;
4138 struct nvldbentry entry, storeEntry;
4140 int pass=0, islocked=0, createentry, addvolume, modified, mod;
4143 if (modentry) *modentry = 0;
4144 rwvolid = ((volumeinfo->type == RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
4147 /* Check to see if the VLDB is ok without locking it (pass 1).
4148 * If it will change, then lock the VLDB entry, read it again,
4149 * then make the changes to it (pass 2).
4152 code = ubik_Call(VL_SetLock, cstruct, 0, rwvolid, RWVOL, VLOP_DELETE);
4154 fprintf(STDERR, "Could not lock VLDB entry for %u\n", rwvolid);
4160 createentry = 0; /* Do we need to create a VLDB entry */
4161 addvolume = 0; /* Add this volume to the VLDB entry */
4162 modified = 0; /* The VLDB entry was modified */
4164 /* Read the entry from VLDB by its RW volume id */
4165 code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
4167 if (code != VL_NOENT) {
4168 fprintf(STDOUT,"Could not retreive the VLDB entry for volume %u \n", rwvolid);
4172 memset(&entry, 0, sizeof(entry));
4173 vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
4177 MapHostToNetwork(&entry);
4180 if (verbose && (pass == 1)) {
4181 fprintf(STDOUT,"_______________________________\n");
4182 fprintf(STDOUT,"\n-- status before -- \n");
4184 fprintf(STDOUT,"\n**does not exist**\n");