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: %-10lu", (unsigned long) entry->cloneId);
431 fprintf(STDOUT,"\n");
433 fprintf(STDOUT," number of sites -> %lu\n",
434 (unsigned long) entry->nServers);
435 for(i = 0; i < entry->nServers; i++) {
436 if(entry->serverFlags[i] & NEW_REPSITE)
439 for(i = 0; i < entry->nServers; i++) {
440 MapPartIdIntoName(entry->serverPartition[i],pname);
441 fprintf(STDOUT," server %s partition %s ",
442 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
443 if(entry->serverFlags[i] & ITSRWVOL) fprintf(STDOUT,"RW Site ") ; else fprintf(STDOUT,"RO Site ");
445 if (entry->serverFlags[i] & NEW_REPSITE)
446 fprintf(STDOUT," -- New release");
448 fprintf(STDOUT," -- Old release");
450 if (entry->serverFlags[i] & RO_DONTUSE)
451 fprintf(STDOUT," -- Not released");
453 fprintf(STDOUT,"\n");
460 /*enumerate the vldb entry corresponding to <entry> */
461 void EnumerateEntry(struct nvldbentry *entry)
464 fprintf(STDOUT,"\n");
465 fprintf(STDOUT,"%s \n",entry->name);
466 SubEnumerateEntry(entry);
470 /* forcibly remove a volume. Very dangerous call */
471 int UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
473 register struct rx_connection *tconn;
474 register afs_int32 code;
476 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
478 code = AFSVolNukeVolume(tconn, partid, volid);
479 rx_DestroyConnection(tconn);
485 /* like df. Return usage of <pname> on <server> in <partition> */
486 int UV_PartitionInfo(afs_int32 server, char *pname, struct diskPartition *partition)
488 register struct rx_connection *aconn;
492 aconn = (struct rx_connection *)0;
493 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
494 code = AFSVolPartitionInfo(aconn,pname,partition);
496 fprintf(STDERR,"Could not get information on partition %s\n",pname);
499 if(aconn) rx_DestroyConnection(aconn);
503 /* old interface to create volume */
504 int UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 *anewid)
507 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
511 /* create a volume, given a server, partition number, volume name --> sends
512 * back new vol id in <anewid>*/
513 int UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aquota,
514 afs_int32 aspare1, afs_int32 aspare2, afs_int32 aspare3, afs_int32 aspare4, afs_int32 *anewid)
517 register struct rx_connection *aconn;
519 register afs_int32 code;
521 afs_int32 rcode,vcode;
522 struct nvldbentry entry,storeEntry;/*the new vldb entry */
523 struct volintInfo tstatus;
526 aconn = (struct rx_connection *)0;
528 memset(&tstatus, 0, sizeof(struct volintInfo));
530 tstatus.maxquota = aquota;
532 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
533 /* next the next 3 available ids from the VLDB */
534 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 3, anewid);
535 EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n",aname);
537 code = AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
538 EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n",aname,*anewid);
540 code = AFSVolSetInfo(aconn, tid, &tstatus);
542 EPRINT(code, "Could not change quota (error %d), continuing...\n");
544 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
545 EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n",aname,*anewid);
547 VPRINT2("Volume %s %u created and brought online\n",aname,*anewid);
549 /* set up the vldb entry for this volume */
550 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
552 entry.serverNumber[0] = aserver; /* this should have another
553 level of indirection later */
554 entry.serverPartition[0] = apart; /* this should also have
555 another indirection level */
556 entry.flags = RW_EXISTS;/* this records that rw volume exists */
557 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
558 entry.volumeId[RWVOL] = *anewid;
559 entry.volumeId[ROVOL] = *anewid + 1;/* rw,ro, bk id are related in the default case */
560 entry.volumeId[BACKVOL] = *anewid + 2;
562 /*map into right byte order, before passing to xdr, the stuff has to be in host
563 byte order. Xdr converts it into network order */
564 MapNetworkToHost(&entry,&storeEntry);
565 /* create the vldb entry */
566 vcode = VLDB_CreateEntry(&storeEntry);
568 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %lu\n",
569 aname, (unsigned long) *anewid);
570 /*destroy the created volume*/
571 VPRINT1("Deleting the newly created volume %u\n",*anewid);
572 AFSVolDeleteVolume(aconn,tid);
576 VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,*anewid);
577 /* volume created, now terminate the transaction and release the connection*/
578 code = AFSVolEndTrans(aconn, tid, &rcode);/*if it crashes before this
579 the volume will come online anyway when transaction timesout , so if
580 vldb entry exists then the volume is guaranteed to exist too wrt create*/
583 fprintf(STDERR,"Failed to end the transaction on the volume %s %lu\n",
584 aname, (unsigned long) *anewid);
592 code= AFSVolEndTrans(aconn, tid, &rcode);
594 fprintf(STDERR,"WARNING: could not end transaction\n");
596 if(aconn) rx_DestroyConnection(aconn);
597 PrintError("",error);
602 /* create a volume, given a server, partition number, volume name --> sends
603 * back new vol id in <anewid>*/
604 int UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aid)
606 register struct rx_connection *aconn;
609 struct nvldbentry entry,storeEntry;/*the new vldb entry */
611 aconn = (struct rx_connection *)0;
614 /* set up the vldb entry for this volume */
615 strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
617 entry.serverNumber[0] = aserver; /* this should have another
618 level of indirection later */
619 entry.serverPartition[0] = apart; /* this should also have
620 another indirection level */
621 entry.flags = RW_EXISTS;/* this records that rw volume exists */
622 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
623 entry.volumeId[RWVOL] = aid;
625 entry.volumeId[ROVOL] = anewid + 1;/* rw,ro, bk id are related in the default case */
626 entry.volumeId[BACKVOL] = *anewid + 2;
628 entry.volumeId[ROVOL] = 0;
629 entry.volumeId[BACKVOL] = 0;
632 /*map into right byte order, before passing to xdr, the stuff has to be in host
633 byte order. Xdr converts it into network order */
634 MapNetworkToHost(&entry,&storeEntry);
635 /* create the vldb entry */
636 vcode = VLDB_CreateEntry(&storeEntry);
638 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %lu\n",
639 aname, (unsigned long) aid);
643 VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,aid);
646 if(aconn) rx_DestroyConnection(aconn);
647 PrintError("",error);
651 /* Delete the volume <volid>on <aserver> <apart>
652 * the physical entry gets removed from the vldb only if the ref count
655 int UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
657 struct rx_connection *aconn = (struct rx_connection *)0;
659 afs_int32 code, rcode;
661 struct nvldbentry entry,storeEntry;
663 afs_int32 avoltype = -1, vtype;
664 int notondisk = 0, notinvldb = 0;
666 /* Find and read bhe VLDB entry for this volume */
667 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
669 if (code != VL_NOENT) {
670 EGOTO1(error_exit, code, "Could not lock VLDB entry for the volume %u\n", avolid);
676 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
677 EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",avolid);
678 MapHostToNetwork(&entry);
681 EnumerateEntry(&entry);
684 /* Whether volume is in the VLDB or not. Delete the volume on disk */
685 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
686 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
688 if (code == VNOVOL) {
691 EGOTO1(error_exit, code, "Transaction on volume %u failed\n", avolid);
695 VPRINT1("Trying to delete the volume %u ...", avolid);
697 code = AFSVolDeleteVolume(aconn, ttid);
698 EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
700 code = AFSVolEndTrans(aconn, ttid, &rcode);
701 code = (code ? code : rcode);
703 EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",avolid);
707 /* Now update the VLDB entry.
708 * But first, verify we have a VLDB entry.
709 * Whether volume is on disk or not. Delete the volume in VLDB.
714 if (avolid == entry.volumeId[BACKVOL]) {
715 /* Its a backup volume, modify the VLDB entry. Check that the
716 * backup volume is on the server/partition we asked to delete.
718 if ( !(entry.flags & BACK_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
719 notinvldb = 2; /* Not on this server and partition */
723 VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
725 entry.flags &= ~BACK_EXISTS;
729 else if (avolid == entry.volumeId[ROVOL]) {
730 /* Its a read-only volume, modify the VLDB entry. Check that the
731 * readonly volume is on the server/partition we asked to delete.
732 * If flags does not have RO_EIXSTS set, then this may mean the RO
733 * hasn't been released (and could exist in VLDB).
735 if (!Lp_ROMatch(aserver,apart,&entry)) {
736 notinvldb = 2; /* Not found on this server and partition */
741 fprintf(STDOUT,"Marking the readonly volume %lu deleted in the VLDB\n",
742 (unsigned long) avolid);
744 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
746 if (!Lp_ROMatch(0,0,&entry))
747 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
751 else if (avolid == entry.volumeId[RWVOL]) {
752 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
753 * Check that the readwrite volumes is on the server/partition we
756 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
757 notinvldb = 2; /* Not found on this server and partition */
761 /* Delete backup if it exists */
762 code = AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart, ITOffline, &ttid);
765 fprintf(STDOUT,"Trying to delete the backup volume %u ...", entry.volumeId[BACKVOL]);
768 code = AFSVolDeleteVolume(aconn, ttid);
769 EGOTO1(error_exit, code, "Could not delete the volume %u \n", entry.volumeId[BACKVOL]);
771 code = AFSVolEndTrans(aconn, ttid, &rcode);
773 code = (code ? code : rcode);
774 EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",
775 entry.volumeId[BACKVOL]);
777 fprintf(STDOUT," done\n");
781 fprintf(STDOUT,"Marking the readwrite volume %lu%s deleted in the VLDB\n",
782 (unsigned long) avolid, ((entry.flags & BACK_EXISTS)?", and its backup volume,":""));
784 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
786 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
789 if (entry.flags & RO_EXISTS)
790 fprintf(STDERR,"WARNING: ReadOnly copy(s) may still exist\n");
794 notinvldb = 2; /* Not found on this server and partition */
798 /* Either delete or replace the VLDB entry */
799 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
801 fprintf(STDOUT,"Last reference to the VLDB entry for %lu - deleting entry\n",
802 (unsigned long) avolid);
803 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
804 EGOTO1(error_exit, code, "Could not delete the VLDB entry for the volume %u \n",avolid);
806 MapNetworkToHost(&entry, &storeEntry);
807 code = VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
808 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
809 EGOTO1(error_exit, code, "Could not update the VLDB entry for the volume %u \n", avolid);
814 if (error) EPRINT(error, "\n");
816 if (notondisk && notinvldb) {
817 EPRINT2(VOLSERNOVOL,"Volume %u does not exist %s\n",
818 avolid, ((notinvldb == 2)?"on server and partition":""));
819 if (!error) error = VOLSERNOVOL;
821 else if (notondisk) {
822 fprintf(STDERR,"WARNING: Volume %lu did not exist on the partition\n",
823 (unsigned long) avolid);
825 else if (notinvldb) {
826 fprintf(STDERR,"WARNING: Volume %lu does not exist in VLDB %s\n",
827 (unsigned long) avolid,
828 ((notinvldb == 2)?"on server and partition":""));
832 code = AFSVolEndTrans(aconn, ttid, &rcode);
833 code = (code ? code : rcode);
835 fprintf(STDERR,"Could not end transaction on the volume %lu\n",
836 (unsigned long) avolid);
837 PrintError("", code);
838 if (!error) error = code;
843 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, -1,
844 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
846 EPRINT1(code, "Could not release the lock on the VLDB entry for the volume %u \n",
848 if (!error) error = code;
852 if (aconn) rx_DestroyConnection(aconn);
856 /* add recovery to UV_MoveVolume */
858 #define TESTC 0 /* set to test recovery code, clear for production */
863 void sigint_handler(int x)
869 "\nSIGINT handler: vos move operation in progress\n");
871 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
873 "enter second control-c to exit\n");
877 (void) signal(SIGINT,sigint_handler);
882 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
883 * <atopart>. The operation is almost idempotent
886 int UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver,
887 afs_int32 afrompart, afs_int32 atoserver, afs_int32 atopart)
889 struct rx_connection *toconn, *fromconn ;
890 afs_int32 fromtid, totid, clonetid;
893 char tmpName[VOLSER_MAXVOLNAME +1];
896 struct restoreCookie cookie;
897 register afs_int32 vcode, code;
898 afs_int32 newVol, volid, backupId;
899 struct volser_status tstatus;
900 struct destServer destination;
902 struct nvldbentry entry, storeEntry;
903 int i, islocked, pntg;
905 char in,lf; /* for test code */
908 #ifdef ENABLE_BUGFIX_1165
909 volEntries volumeInfo;
910 struct volintInfo *infop = 0;
914 fromconn = (struct rx_connection *)0;
915 toconn = (struct rx_connection *)0;
925 /* support control-c processing */
926 if (setjmp(env)) goto mfail;
927 (void) signal(SIGINT,sigint_handler);
932 "\nThere are three tests points - verifies all code paths through recovery.\n");
933 fprintf(STDOUT,"First test point - operation not started.\n");
934 fprintf(STDOUT,"...test here (y, n)? ");
936 fscanf(stdin,"%c",&in);
937 fscanf(stdin,"%c",&lf); /* toss away */
940 fprintf(STDOUT,"type control-c\n");
948 /* or drop through */
951 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
952 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
954 if (entry.volumeId[RWVOL] != afromvol)
956 fprintf(STDERR,"Only RW volume can be moved\n");
960 vcode = ubik_Call(VL_SetLock, cstruct, 0,afromvol, RWVOL, VLOP_MOVE);
961 EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
964 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
965 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
967 backupId = entry.volumeId[BACKVOL];
968 MapHostToNetwork(&entry);
970 if ( !Lp_Match(afromserver, afrompart, &entry) )
972 /* the from server and partition do not exist in the vldb entry corresponding to volid */
973 if ( !Lp_Match(atoserver, atopart, &entry) )
975 /* the to server and partition do not exist in the vldb entry corresponding to volid */
976 fprintf(STDERR,"The volume %lu is not on the specified site. \n",
977 (unsigned long) afromvol);
978 fprintf(STDERR,"The current site is :");
979 for (i=0; i<entry.nServers; i++)
981 if (entry.serverFlags[i] == ITSRWVOL)
984 MapPartIdIntoName(entry.serverPartition[i],pname);
985 fprintf(STDERR," server %s partition %s \n",
986 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
989 vcode = ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
990 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
991 EGOTO1(mfail, vcode, " Could not release lock on the VLDB entry for the volume %u \n",
994 return VOLSERVOLMOVED;
997 /* delete the volume afromvol on src_server */
998 /* from-info does not exist but to-info does =>
999 * we have already done the move, but the volume
1000 * may still be existing physically on from fileserver
1002 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1006 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline, &fromtid);
1008 { /* volume exists - delete it */
1009 VPRINT1("Setting flags on leftover source volume %u ...", afromvol);
1010 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1011 EGOTO1(mfail, code, "Failed to set flags on the leftover source volume %u\n", afromvol);
1014 VPRINT1("Deleting leftover source volume %u ...", afromvol);
1015 code = AFSVolDeleteVolume(fromconn,fromtid);
1016 EGOTO1(mfail, code, "Failed to delete the leftover source volume %u\n", afromvol);
1019 VPRINT1("Ending transaction on leftover source volume %u ...", afromvol);
1020 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1022 if (!code) code = rcode;
1023 EGOTO1(mfail, code, "Could not end the transaction for the leftover source volume %u \n", afromvol);
1027 /*delete the backup volume now */
1029 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1031 { /* backup volume exists - delete it */
1032 VPRINT1("Setting flags on leftover backup volume %u ...", backupId);
1033 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1034 EGOTO1(mfail, code, "Failed to set flags on the backup volume %u\n", backupId);
1037 VPRINT1("Deleting leftover backup volume %u ...", backupId);
1038 code = AFSVolDeleteVolume(fromconn,fromtid);
1039 EGOTO1(mfail, code, "Could not delete the leftover backup volume %u\n", backupId);
1042 VPRINT1("Ending transaction on leftover backup volume %u ...", backupId);
1043 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1045 if (!code) code = rcode;
1046 EGOTO1(mfail, code,"Could not end the transaction for the leftover backup volume %u\n",backupId);
1055 /* From-info matches the vldb info about volid,
1056 * its ok start the move operation, the backup volume
1057 * on the old site is deleted in the process
1059 if (afrompart == atopart)
1061 same = VLDB_IsSameAddrs (afromserver, atoserver, &error);
1062 EGOTO2(mfail, error, "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1063 afromserver, error);
1067 EGOTO1(mfail, VOLSERVOLMOVED, "Warning: Moving volume %u to its home partition ignored!\n", afromvol);
1072 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1073 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1074 fromtid = totid = 0; /* initialize to uncreated */
1077 * clone the read/write volume locally.
1080 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1081 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1082 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1085 /* Get a clone id */
1086 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1088 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1089 EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1092 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1093 VPRINT1("Cloning source volume %u ...", afromvol);
1094 strcpy(vname, "move-clone-temp");
1095 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &newVol);
1096 EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1099 /* lookup the name of the volume we just cloned */
1101 code = AFSVolGetName(fromconn, fromtid, &volName);
1102 EGOTO1(mfail, code, "Failed to get the name of the volume %u\n", newVol);
1104 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1106 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1108 if (!code) code = rcode;
1109 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1113 * Create the destination volume
1116 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1117 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1118 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1121 VPRINT1("Setting flags on cloned volume %u ...", newVol);
1122 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1123 EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", newVol);
1126 /* remember time from which we've dumped the volume */
1127 VPRINT1("Getting status of cloned volume %u ...", newVol);
1128 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1129 EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", newVol);
1132 fromDate = tstatus.creationDate-CLOCKSKEW;
1134 #ifdef ENABLE_BUGFIX_1165
1136 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1137 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1138 * don't use this information...
1140 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
1141 volumeInfo.volEntries_len = 0;
1142 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1143 EGOTO1(mfail, code, "Failed to get the volint Info of the cloned volume %u\n", afromvol);
1145 infop = (volintInfo *) volumeInfo.volEntries_val;
1146 infop->maxquota = -1; /* Else it will replace the default quota */
1149 /* create a volume on the target machine */
1151 code = AFSVolTransCreate (toconn, volid, atopart, ITOffline, &totid);
1154 /* Delete the existing volume.
1155 * While we are deleting the volume in these steps, the transaction
1156 * we started against the cloned volume (clonetid above) will be
1157 * sitting idle. It will get cleaned up after 600 seconds
1159 VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1160 code = AFSVolDeleteVolume(toconn, totid);
1161 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", volid);
1164 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", volid);
1165 code = AFSVolEndTrans(toconn, totid, &rcode);
1167 if (!code) code = rcode;
1168 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1173 VPRINT1("Creating the destination volume %u ...", volid);
1174 code = AFSVolCreateVolume (toconn, atopart, volName, volser_RW, volid, &volid, &totid);
1175 EGOTO1(mfail, code, "Failed to create the destination volume %u\n", volid);
1178 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1182 VPRINT1("Setting volume flags on destination volume %u ...", volid);
1183 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1184 EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", volid);
1188 * Now dump the clone to the new volume
1191 destination.destHost = ntohl(atoserver);
1192 destination.destPort = AFSCONF_VOLUMEPORT;
1193 destination.destSSID = 1;
1195 /* Copy the clone to the new volume */
1196 VPRINT2("Dumping from clone %u on source to volume %u on destination ...", newVol, afromvol);
1197 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1198 cookie.type = RWVOL;
1199 cookie.parent = entry.volumeId[RWVOL];
1201 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1202 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1205 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1206 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1207 if (!code) code = rcode;
1209 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1213 * reattach to the main-line volume, and incrementally dump it.
1216 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1217 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1218 EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1221 /* now do the incremental */
1222 VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1223 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1224 EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1227 /* now adjust the flags so that the new volume becomes official */
1228 VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1229 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1230 EGOTO(mfail, code, "Failed to set the flags to make old source volume offline\n");
1233 VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1234 code = AFSVolSetFlags(toconn, totid, 0);
1235 EGOTO(mfail, code, "Failed to set the flags to make new source volume online\n");
1238 #ifdef ENABLE_BUGFIX_1165
1239 VPRINT1("Setting volume status on destination volume %u ...", volid);
1240 code = AFSVolSetInfo(toconn, totid, infop);
1241 EGOTO1(mfail, code, "Failed to set volume status on the destination volume %u\n", volid);
1245 /* put new volume online */
1246 VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1247 code = AFSVolEndTrans(toconn, totid, &rcode);
1249 if (!code) code = rcode;
1250 EGOTO1(mfail, code, "Failed to end the transaction on the volume %u on the new site\n", afromvol);
1253 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1254 MapNetworkToHost(&entry,&storeEntry);
1255 storeEntry.flags &= ~BACK_EXISTS;
1259 fprintf(STDOUT, "Second test point - operation in progress but not complete.\n");
1260 fprintf(STDOUT,"...test here (y, n)? ");
1262 fscanf(stdin,"%c",&in);
1263 fscanf(stdin,"%c",&lf); /* toss away */
1266 fprintf(STDOUT,"type control-c\n");
1269 fprintf(stdout,".");
1274 /* or drop through */
1277 VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1278 vcode = VLDB_ReplaceEntry (afromvol, -1, &storeEntry,
1279 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1282 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %s %lu \n",
1283 storeEntry.name, (unsigned long) afromvol);
1292 fprintf(STDOUT, "Third test point - operation complete but no cleanup.\n");
1293 fprintf(STDOUT,"...test here (y, n)? ");
1295 fscanf(stdin,"%c",&in);
1296 fscanf(stdin,"%c",&lf); /* toss away */
1299 fprintf(STDOUT,"type control-c\n");
1302 fprintf(stdout,".");
1307 /* or drop through */
1311 /* This is tricky. File server is very stupid, and if you mark the volume
1312 * as VTOutOfService, it may mark the *good* instance (if you're moving
1313 * between partitions on the same machine) as out of service. Since
1314 * we're cleaning this code up in DEcorum, we're just going to kludge around
1315 * it for now by removing this call. */
1316 /* already out of service, just zap it now */
1317 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1320 fprintf(STDERR,"Failed to set the flags to make the old source volume offline\n");
1324 if (atoserver != afromserver)
1326 /* set forwarding pointer for moved volumes */
1327 VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1328 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1329 EGOTO1(mfail, code, "Failed to set the forwarding pointer for the volume %u\n", afromvol);
1333 VPRINT1("Deleting old volume %u on source ...", afromvol);
1334 code = AFSVolDeleteVolume(fromconn,fromtid); /* zap original volume */
1335 EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n", afromvol);
1338 VPRINT1("Ending transaction on old volume %u on the source ...", afromvol);
1339 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1341 if (!code) code = rcode;
1342 EGOTO1(mfail, code, "Failed to end the transaction on the old volume %u on the source\n", afromvol);
1345 /* Delete the backup volume on the original site */
1346 VPRINT1("Creating transaction for backup volume %u on source ...", backupId);
1347 code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1351 VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1352 code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1353 EGOTO1(mfail, code, "Failed to set the flags on the backup volume %u on the source\n", backupId);
1356 VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1357 code = AFSVolDeleteVolume(fromconn,fromtid);
1358 EGOTO1(mfail, code, "Failed to delete the backup volume %u on the source\n", backupId);
1361 VPRINT1("Ending transaction on backup volume %u on source ...", backupId);
1362 code = AFSVolEndTrans(fromconn,fromtid, &rcode);
1364 if (!code) code = rcode;
1365 EGOTO1(mfail, code, "Failed to end the transaction on the backup volume %u on the source\n", backupId);
1368 else code = 0; /* no backup volume? that's okay */
1371 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1372 code = AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
1373 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1376 /* now delete the clone */
1377 VPRINT1("Deleting the cloned volume %u ...", newVol);
1378 code = AFSVolDeleteVolume(fromconn, clonetid);
1379 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", newVol);
1382 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1383 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1384 if (!code) code = rcode;
1386 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1394 fprintf(STDOUT,"Fourth test point - operation complete.\n");
1395 fprintf(STDOUT,"...test here (y, n)? ");
1397 fscanf(stdin,"%c",&in);
1398 fscanf(stdin,"%c",&lf); /* toss away */
1401 fprintf(STDOUT,"type control-c\n");
1404 fprintf(stdout,".");
1409 /* or drop through */
1412 /* normal cleanup code */
1414 if (entry.flags & RO_EXISTS) fprintf(STDERR,"WARNING : readOnly copies still exist \n");
1418 VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1419 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, -1,
1420 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1424 fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %lu \n",
1425 (unsigned long) afromvol);
1426 if (!error) error = vcode;
1433 VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1434 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1438 fprintf(STDERR,"Could not end transaction on the source's clone volume %lu\n",
1439 (unsigned long) newVol);
1440 if (!error) error = (code ? code : rcode);
1447 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1448 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1452 fprintf(STDERR,"Could not end transaction on the source's clone volume %lu\n",
1453 (unsigned long) newVol);
1454 if (!error) error = (code ? code : rcode);
1461 VPRINT1("Cleanup: Ending transaction on destination volume %u ...", afromvol);
1462 code = AFSVolEndTrans(toconn, totid, &rcode);
1466 fprintf(STDERR,"Could not end transaction on destination volume %lu\n",
1467 (unsigned long) afromvol);
1468 if (!error) error = (code ? code : rcode);
1472 if (volName) free(volName);
1473 #ifdef ENABLE_BUGFIX_1165
1474 if (infop) free(infop);
1476 if (fromconn) rx_DestroyConnection(fromconn);
1477 if (toconn) rx_DestroyConnection(toconn);
1478 PrintError("",error);
1481 /* come here only when the sky falls */
1486 fprintf(STDOUT,"vos move: operation interrupted, cleanup in progress...\n");
1487 fprintf(STDOUT,"clear transaction contexts\n");
1491 /* unlock VLDB entry */
1494 VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1495 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1496 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1502 VPRINT("Recovery: Ending transaction on clone volume ...");
1503 AFSVolEndTrans(fromconn, clonetid, &rcode);
1508 VPRINT("Recovery: Ending transaction on destination volume ...");
1509 AFSVolEndTrans(toconn, totid, &rcode);
1513 { /* put it on-line */
1514 VPRINT("Recovery: Setting volume flags on source volume ...");
1515 AFSVolSetFlags(fromconn,fromtid,0);
1518 VPRINT("Recovery: Ending transaction on source volume ...");
1519 AFSVolEndTrans(fromconn, fromtid, &rcode);
1523 VPRINT("Recovery: Accessing VLDB.\n");
1524 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
1527 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
1531 MapHostToNetwork(&entry);
1533 /* Delete either the volume on the source location or the target location.
1534 * If the vldb entry still points to the source location, then we know the
1535 * volume move didn't finish so we remove the volume from the target
1536 * location. Otherwise, we remove the volume from the source location.
1538 if (Lp_Match(afromserver,afrompart,&entry)) { /* didn't move - delete target volume */
1541 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1545 if (volid && toconn) {
1546 VPRINT1("Recovery: Creating transaction for destination volume %u ...", volid);
1547 code=AFSVolTransCreate(toconn,volid,atopart, ITOffline,&totid);
1552 VPRINT1("Recovery: Setting flags on destination volume %u ...", volid);
1553 AFSVolSetFlags(toconn,totid, VTDeleteOnSalvage | VTOutOfService);
1556 VPRINT1("Recovery: Deleting destination volume %u ...", volid);
1557 AFSVolDeleteVolume(toconn,totid);
1560 VPRINT1("Recovery: Ending transaction on destination volume %u ...", volid);
1561 AFSVolEndTrans(toconn,totid,&rcode);
1566 VPRINT1("\nRecovery: Unable to start transaction on destination volume %u.\n", afromvol);
1570 /* put source volume on-line */
1572 VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1573 code=AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1577 VPRINT1("Recovery: Setting flags on source volume %u ...", afromvol);
1578 AFSVolSetFlags(fromconn,fromtid,0);
1581 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1582 AFSVolEndTrans(fromconn,fromtid,&rcode);
1587 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1591 else { /* yep, move complete */
1594 "move complete - attempt cleanup of source partition - no guarantee\n");
1598 /* delete backup volume */
1600 VPRINT1("Recovery: Creating transaction on backup volume %u ...", backupId);
1601 code=AFSVolTransCreate (fromconn,backupId,afrompart, ITOffline,&fromtid);
1605 VPRINT1("Recovery: Setting flags on backup volume %u ...", backupId);
1606 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1609 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1610 AFSVolDeleteVolume(fromconn,fromtid);
1613 VPRINT1("Recovery: Ending transaction on backup volume %u ...", backupId);
1614 AFSVolEndTrans(fromconn,fromtid,&rcode);
1619 VPRINT1("\nRecovery: Unable to start transaction on backup volume %u.\n", backupId);
1622 /* delete source volume */
1623 VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1624 code=AFSVolTransCreate (fromconn, afromvol, afrompart, ITBusy, &fromtid);
1628 VPRINT1("Recovery: Setting flags on backup volume %u ...", afromvol);
1629 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1632 if (atoserver != afromserver)
1634 VPRINT("Recovery: Setting volume forwarding pointer ...");
1635 AFSVolSetForwarding(fromconn,fromtid,atoserver);
1639 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1640 AFSVolDeleteVolume(fromconn,fromtid);
1643 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1644 AFSVolEndTrans(fromconn,fromtid,&rcode);
1649 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1654 /* common cleanup - delete local clone */
1656 VPRINT1("Recovery: Creating transaction on clone volume %u ...", newVol);
1657 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1661 VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1662 AFSVolDeleteVolume(fromconn,clonetid);
1665 VPRINT1("Recovery: Ending transaction on clone volume %u ...", newVol);
1666 AFSVolEndTrans(fromconn,clonetid,&rcode);
1671 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1675 /* unlock VLDB entry */
1676 VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...", afromvol);
1677 ubik_Call (VL_ReleaseLock, cstruct, 0, afromvol, -1,
1678 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1681 done: /* routine cleanup */
1682 if (volName) free(volName);
1683 #ifdef ENABLE_BUGFIX_1165
1684 if (infop) free(infop);
1686 if (fromconn) rx_DestroyConnection(fromconn);
1687 if (toconn) rx_DestroyConnection(toconn);
1690 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
1697 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1698 * <atopart>. The operation is almost idempotent
1701 int UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver,
1702 afs_int32 afrompart, char *atovolname, afs_int32 atoserver, afs_int32 atopart)
1704 struct rx_connection *toconn, *fromconn ;
1705 afs_int32 fromtid, totid, clonetid;
1707 char tmpName[VOLSER_MAXVOLNAME +1];
1710 struct restoreCookie cookie;
1711 register afs_int32 vcode, code;
1712 afs_int32 cloneVol, newVol;
1713 struct volser_status tstatus;
1714 struct destServer destination;
1716 struct nvldbentry entry, newentry, storeEntry;
1717 int i, islocked, pntg;
1719 char in,lf; /* for test code */
1724 fromconn = (struct rx_connection *)0;
1725 toconn = (struct rx_connection *)0;
1733 /* support control-c processing */
1734 if (setjmp(env)) goto mfail;
1735 (void) signal(SIGINT,sigint_handler);
1737 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1738 EGOTO1(mfail, vcode, "Could not fetch the entry for the volume %u from the VLDB \n", afromvol);
1739 MapHostToNetwork(&entry);
1742 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1743 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1744 fromtid = totid = 0; /* initialize to uncreated */
1747 /* check if we can shortcut and use a local clone instead of a full copy */
1748 if ( afromserver == atoserver && afrompart == atopart )
1754 * clone the read/write volume locally.
1757 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1758 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1759 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1762 /* Get a clone id */
1763 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1765 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &cloneVol);
1766 EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1769 /* Get a new volume id */
1770 VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
1772 vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1773 EGOTO1(mfail, vcode, "Could not get an ID for the copy of volume %u from the VLDB\n", afromvol);
1776 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1777 VPRINT1("Cloning source volume %u ...", afromvol);
1778 strcpy(vname, "copy-clone-temp");
1779 code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &cloneVol);
1780 EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1783 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1785 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1787 if (!code) code = rcode;
1788 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1792 * Create the destination volume
1795 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1796 code = AFSVolTransCreate (fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1797 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1800 VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
1801 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1802 EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", cloneVol);
1805 /* remember time from which we've dumped the volume */
1806 VPRINT1("Getting status of cloned volume %u ...", cloneVol);
1807 code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1808 EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", cloneVol);
1811 fromDate = tstatus.creationDate-CLOCKSKEW;
1813 /* create a volume on the target machine */
1814 code = AFSVolTransCreate (toconn, newVol, atopart, ITOffline, &totid);
1817 /* Delete the existing volume.
1818 * While we are deleting the volume in these steps, the transaction
1819 * we started against the cloned volume (clonetid above) will be
1820 * sitting idle. It will get cleaned up after 600 seconds
1822 VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
1823 code = AFSVolDeleteVolume(toconn, totid);
1824 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", newVol);
1827 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", newVol);
1828 code = AFSVolEndTrans(toconn, totid, &rcode);
1830 if (!code) code = rcode;
1831 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1836 VPRINT1("Creating the destination volume %u ...", newVol);
1837 code = AFSVolCreateVolume (toconn, atopart, atovolname, volser_RW, newVol, &newVol, &totid);
1838 EGOTO1(mfail, code, "Failed to create the destination volume %u\n", newVol);
1841 strncpy(tmpName, atovolname, VOLSER_OLDMAXVOLNAME);
1843 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1844 code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1845 EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", newVol);
1849 * Now dump the clone to the new volume
1852 destination.destHost = ntohl(atoserver);
1853 destination.destPort = AFSCONF_VOLUMEPORT;
1854 destination.destSSID = 1;
1857 /* probably should have some code here that checks to see if we are copying to same server
1858 and partition - if so, just use a clone to save disk space */
1860 /* Copy the clone to the new volume */
1861 VPRINT2("Dumping from clone %u on source to volume %u on destination ...", cloneVol, newVol);
1862 strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1863 cookie.type = RWVOL;
1866 code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1867 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", newVol);
1870 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1871 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1872 if (!code) code = rcode;
1874 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1878 * reattach to the main-line volume, and incrementally dump it.
1881 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1882 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1883 EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1886 /* now do the incremental */
1887 VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1888 code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1889 EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1892 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1893 code = AFSVolSetFlags(toconn, totid, 0);
1894 EGOTO(mfail, code, "Failed to set the flags to make destination volume online\n");
1897 /* put new volume online */
1898 VPRINT1("Ending transaction on destination volume %u ...", newVol);
1899 code = AFSVolEndTrans(toconn, totid, &rcode);
1901 if (!code) code = rcode;
1902 EGOTO1(mfail, code, "Failed to end the transaction on the destination volume %u\n", newVol);
1905 VPRINT1("Ending transaction on source volume %u ...", afromvol);
1906 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1908 if (!code) code = rcode;
1909 EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1913 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1914 code = AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1915 EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1918 /* now delete the clone */
1919 VPRINT1("Deleting the cloned volume %u ...", cloneVol);
1920 code = AFSVolDeleteVolume(fromconn, clonetid);
1921 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", cloneVol);
1924 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1925 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1926 if (!code) code = rcode;
1928 EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1931 /* create the vldb entry for the copied volume */
1932 strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
1933 newentry.nServers = 1;
1934 newentry.serverNumber[0] = atoserver;
1935 newentry.serverPartition[0] = atopart;
1936 newentry.flags = RW_EXISTS;/* this records that rw volume exists */
1937 newentry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
1938 newentry.volumeId[RWVOL] = newVol;
1939 newentry.volumeId[ROVOL] = 0;
1940 newentry.volumeId[BACKVOL] = 0;
1941 newentry.cloneId = 0;
1942 /*map into right byte order, before passing to xdr, the stuff has to be in host
1943 byte order. Xdr converts it into network order */
1944 MapNetworkToHost(&newentry,&storeEntry);
1945 /* create the vldb entry */
1946 vcode = VLDB_CreateEntry(&storeEntry);
1948 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %lu\n",
1949 atovolname, (unsigned long) newVol);
1950 /*destroy the created volume*/
1951 VPRINT1("Deleting the newly created volume %u\n",newVol);
1952 AFSVolDeleteVolume(toconn,totid);
1956 VPRINT2("Created the VLDB entry for the volume %s %u\n",atovolname,newVol);
1958 /* normal cleanup code */
1962 VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1963 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1967 fprintf(STDERR,"Could not end transaction on the source volume %lu\n",
1968 (unsigned long) afromvol);
1969 if (!error) error = (code ? code : rcode);
1976 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", cloneVol);
1977 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1981 fprintf(STDERR,"Could not end transaction on the source's clone volume %lu\n",
1982 (unsigned long) cloneVol);
1983 if (!error) error = (code ? code : rcode);
1990 VPRINT1("Cleanup: Ending transaction on destination volume %u ...", newVol);
1991 code = AFSVolEndTrans(toconn, totid, &rcode);
1995 fprintf(STDERR,"Could not end transaction on destination volume %lu\n",
1996 (unsigned long) newVol);
1997 if (!error) error = (code ? code : rcode);
2001 if (fromconn) rx_DestroyConnection(fromconn);
2002 if (toconn) rx_DestroyConnection(toconn);
2003 PrintError("",error);
2006 /* come here only when the sky falls */
2011 fprintf(STDOUT,"vos copy: operation interrupted, cleanup in progress...\n");
2012 fprintf(STDOUT,"clear transaction contexts\n");
2018 VPRINT("Recovery: Ending transaction on clone volume ...");
2019 AFSVolEndTrans(fromconn, clonetid, &rcode);
2024 VPRINT("Recovery: Ending transaction on destination volume ...");
2025 AFSVolEndTrans(toconn, totid, &rcode);
2029 { /* put it on-line */
2030 VPRINT("Recovery: Ending transaction on source volume ...");
2031 AFSVolEndTrans(fromconn, fromtid, &rcode);
2035 VPRINT("Recovery: Accessing VLDB.\n");
2036 vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
2039 fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
2043 MapHostToNetwork(&entry);
2045 /* common cleanup - delete local clone */
2047 VPRINT1("Recovery: Creating transaction on clone volume %u ...", cloneVol);
2048 code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
2052 VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2053 AFSVolDeleteVolume(fromconn,clonetid);
2056 VPRINT1("Recovery: Ending transaction on clone volume %u ...", cloneVol);
2057 AFSVolEndTrans(fromconn,clonetid,&rcode);
2062 VPRINT1("\nRecovery: Unable to start transaction on clone volume %u.\n", cloneVol);
2066 done: /* routine cleanup */
2067 if (fromconn) rx_DestroyConnection(fromconn);
2068 if (toconn) rx_DestroyConnection(toconn);
2071 fprintf(STDOUT,"cleanup complete - user verify desired result\n");
2081 /* Make a new backup of volume <avolid> on <aserver> and <apart>
2082 * if one already exists, update it
2085 int UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2087 struct rx_connection *aconn = (struct rx_connection *)0;
2088 afs_int32 ttid = 0, btid = 0;
2090 afs_int32 code = 0, rcode = 0;
2091 char vname[VOLSER_MAXVOLNAME +1];
2092 struct nvldbentry entry, storeEntry;
2093 afs_int32 error = 0;
2094 int vldblocked = 0, vldbmod = 0, backexists = 1;
2096 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2098 /* the calls to VLDB will succeed only if avolid is a RW volume,
2099 * since we are following the RW hash chain for searching */
2100 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2102 fprintf(STDERR, "Could not fetch the entry for the volume %lu from the VLDB \n",
2103 (unsigned long) avolid);
2104 error = code; goto bfail;
2106 MapHostToNetwork(&entry);
2108 /* These operations require the VLDB be locked since it means the VLDB
2109 * will change or the vldb is already locked.
2111 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
2112 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
2113 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
2115 code = ubik_Call(VL_SetLock,cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2117 fprintf(STDERR,"Could not lock the VLDB entry for the volume %lu\n",
2118 (unsigned long) avolid);
2124 /* Reread the vldb entry */
2125 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2127 fprintf(STDERR,"Could not fetch the entry for the volume %lu from the VLDB \n",
2128 (unsigned long) avolid);
2132 MapHostToNetwork(&entry);
2135 if (!ISNAMEVALID(entry.name)) {
2136 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n", entry.name);
2137 error = VOLSERBADNAME;
2141 backupID = entry.volumeId[BACKVOL];
2142 if (backupID == INVALID_BID) {
2143 /* Get a backup volume id from the VLDB and update the vldb
2146 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
2149 "Could not allocate ID for the backup volume of %lu from the VLDB\n",
2150 (unsigned long) avolid);
2154 entry.volumeId[BACKVOL] = backupID;
2158 /* Test to see if the backup volume exists by trying to create
2159 * a transaction on the backup volume. We've assumed the backup exists.
2161 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2163 if (code != VNOVOL) {
2164 fprintf(STDERR,"Could not reach the backup volume %lu\n",
2165 (unsigned long) backupID);
2169 backexists = 0; /* backup volume does not exist */
2172 code = AFSVolEndTrans(aconn, btid, &rcode);
2174 if (code || rcode) {
2176 "Could not end transaction on the previous backup volume %lu\n",
2177 (unsigned long) backupID);
2178 error = (code ? code : rcode);
2183 /* Now go ahead and try to clone the RW volume.
2184 * First start a transaction on the RW volume
2186 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2188 fprintf(STDERR,"Could not start a transaction on the volume %lu\n",
2189 (unsigned long) avolid);
2194 /* Clone or reclone the volume, depending on whether the backup
2195 * volume exists or not
2198 VPRINT1("Re-cloning backup volume %u ...", backupID);
2200 code = AFSVolReClone(aconn, ttid, backupID);
2202 fprintf(STDERR,"Could not re-clone backup volume %lu\n",
2203 (unsigned long) backupID);
2209 VPRINT1("Creating a new backup clone %u ...", backupID);
2211 strcpy(vname, entry.name);
2212 strcat(vname,".backup");
2214 code = AFSVolClone(aconn, ttid, 0,backupVolume, vname, &backupID);
2216 fprintf(STDERR,"Failed to clone the volume %lu\n",
2217 (unsigned long) avolid);
2223 /* End the transaction on the RW volume */
2224 code = AFSVolEndTrans(aconn, ttid, &rcode);
2226 if (code || rcode) {
2227 fprintf(STDERR, "Failed to end the transaction on the rw volume %lu\n",
2228 (unsigned long) avolid);
2229 error = (code ? code : rcode);
2233 /* Mork vldb as backup exists */
2234 if (!(entry.flags & BACK_EXISTS)) {
2235 entry.flags |= BACK_EXISTS;
2239 /* Now go back to the backup volume and bring it on line */
2240 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2242 fprintf(STDERR,"Failed to start a transaction on the backup volume %lu\n",
2243 (unsigned long) backupID);
2248 code = AFSVolSetFlags(aconn, btid, 0);
2250 fprintf(STDERR,"Could not mark the backup volume %lu on line \n",
2251 (unsigned long) backupID);
2256 code = AFSVolEndTrans(aconn, btid, &rcode);
2258 if (code || rcode) {
2259 fprintf(STDERR, "Failed to end the transaction on the backup volume %lu\n",
2260 (unsigned long) backupID);
2261 error = (code ? code : rcode);
2267 /* Will update the vldb below */
2271 code = AFSVolEndTrans(aconn, ttid, &rcode);
2272 if (code || rcode) {
2273 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2274 (unsigned long) avolid);
2276 error = (code ? code : rcode);
2281 code = AFSVolEndTrans(aconn, btid, &rcode);
2282 if (code || rcode) {
2283 fprintf(STDERR,"Could not end transaction the backup volume %lu\n",
2284 (unsigned long) backupID);
2286 error = (code ? code : rcode);
2290 /* Now update the vldb - if modified */
2293 MapNetworkToHost(&entry,&storeEntry);
2294 code = VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2295 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2297 fprintf(STDERR,"Could not update the VLDB entry for the volume %lu \n",
2298 (unsigned long) avolid);
2304 code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, RWVOL,
2305 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2307 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %lu \n",
2308 (unsigned long) avolid);
2316 rx_DestroyConnection(aconn);
2318 PrintError("",error);
2322 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags)
2324 afs_int32 acode, ccode, rcode, tid;
2325 ccode = rcode = tid = 0;
2327 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2328 if (!acode) { /* It really was there */
2329 acode = AFSVolDeleteVolume(conn, tid);
2331 fprintf(STDERR, "Failed to delete volume %lu.\n", (unsigned long) vid);
2332 PrintError ("", acode);
2334 ccode = AFSVolEndTrans(conn, tid, &rcode);
2338 fprintf(STDERR, "Failed to end transaction on volume %lu.\n",
2339 (unsigned long) vid);
2340 PrintError ("", ccode);
2347 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
2348 #define ERROREXIT(ec) { error = (ec); goto rfail; }
2350 /* Get a "transaction" on this replica. Create the volume
2351 * if necessary. Return the time from which a dump should
2352 * be made (0 if it's a new volume)
2354 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr,
2355 afs_int32 *transPtr, afs_int32 *timePtr)
2358 struct volser_status tstatus;
2359 int code, rcode, tcode;
2361 *connPtr = (struct rx_connection *)0;
2365 /* get connection to the replication site */
2366 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
2367 if (!*connPtr) goto fail; /* server is down */
2369 volid = vldbEntryPtr->volumeId[ROVOL];
2371 code = AFSVolTransCreate(*connPtr, volid, vldbEntryPtr->serverPartition[index],
2372 ITOffline, transPtr);
2374 /* If the volume does not exist, create it */
2375 if (!volid || code) {
2378 if (volid && (code != VNOVOL)){
2379 PrintError("Failed to start a transaction on the RO volume.\n",
2384 strcpy(volname, vldbEntryPtr->name);
2385 strcat(volname, ".readonly");
2388 fprintf(STDOUT,"Creating new volume %lu on replication site %s: ",
2389 (unsigned long) volid,
2390 hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2394 code = AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
2396 vldbEntryPtr->volumeId[RWVOL], &volid, transPtr);
2398 PrintError("Failed to create the ro volume: ",code);
2401 vldbEntryPtr->volumeId[ROVOL] = volid;
2405 /* The following is a bit redundant, since create sets these flags by default */
2406 code = AFSVolSetFlags(*connPtr, *transPtr, VTDeleteOnSalvage | VTOutOfService);
2408 PrintError("Failed to set flags on the ro volume: ", code);
2413 /* Otherwise, the transaction did succeed, so get the creation date of the
2414 * latest RO volume on the replication site
2417 VPRINT2("Updating existing ro volume %u on %s ...\n",
2418 volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2420 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
2422 PrintError("Failed to get status of volume on destination: ",code);
2425 *timePtr = tstatus.creationDate-CLOCKSKEW;
2432 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
2434 if (!tcode) tcode = rcode;
2435 if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode);
2441 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
2442 afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results)
2446 for (i=0; i<tr->manyDests_len; i++) {
2447 results->manyResults_val[i] = AFSVolForward(fromconn, fromtid,
2448 fromdate, &(tr->manyDests_val[i].server),
2449 tr->manyDests_val[i].trans, cookie);
2455 static int rel_compar (struct release *r1, struct release *r2)
2457 return (r1->time - r2->time);
2460 /* UV_ReleaseVolume()
2461 * Release volume <afromvol> on <afromserver> <afrompart> to all
2462 * its RO sites (full release). Unless the previous release was
2463 * incomplete: in which case we bring the remaining incomplete
2464 * volumes up to date with the volumes that were released
2466 * forceflag: Performs a full release.
2468 * Will create a clone from the RW, then dump the clone out to
2469 * the remaining replicas. If there is more than 1 RO sites,
2470 * ensure that the VLDB says at least one RO is available all
2471 * the time: Influences when we write back the VLDB entry.
2474 int UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, int forceflag)
2477 afs_int32 code, vcode, rcode, tcode;
2478 afs_int32 cloneVolId, roVolId;
2479 struct replica *replicas=0;
2480 struct nvldbentry entry,storeEntry;
2481 int i, volcount, m, fullrelease, vldbindex;
2483 struct restoreCookie cookie;
2484 struct rx_connection **toconns=0;
2485 struct release *times=0;
2487 struct rx_connection *fromconn = (struct rx_connection *)0;
2488 afs_int32 error = 0;
2490 afs_int32 clonetid=0, onlinetid;
2491 afs_int32 fromtid=0;
2492 afs_uint32 fromdate, thisdate;
2495 manyResults results;
2496 int rwindex, roindex, roclone, roexists;
2501 } remembertime[NMAXNSERVERS];
2502 int releasecount = 0;
2503 struct volser_status volstatus;
2505 memset((char *)remembertime, 0, sizeof(remembertime));
2506 memset((char *)&results, 0, sizeof(results));
2508 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
2509 if (vcode != VL_RERELEASE)
2510 ONERROR(vcode, afromvol, "Could not lock the VLDB entry for the volume %u.\n");
2513 /* Get the vldb entry in readable format */
2514 vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
2515 ONERROR(vcode, afromvol, "Could not fetch the entry for the volume %u from the VLDB.\n");
2516 MapHostToNetwork(&entry);
2519 EnumerateEntry(&entry);
2521 if (!ISNAMEVALID(entry.name))
2522 ONERROR(VOLSERBADOP, entry.name,
2523 "Volume name %s is too long, rename before releasing.\n");
2524 if (entry.volumeId[RWVOL] != afromvol)
2525 ONERROR(VOLSERBADOP, afromvol,
2526 "The volume %u being released is not a read-write volume.\n");
2527 if (entry.nServers <= 1)
2528 ONERROR(VOLSERBADOP, afromvol,
2529 "Volume %u has no replicas - release operation is meaningless!\n");
2530 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
2531 ONERROR(VOLSERBADOP, entry.name,
2532 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
2534 /* roclone is true if one of the RO volumes is on the same
2535 * partition as the RW volume. In this case, we make the RO volume
2536 * on the same partition a clone instead of a complete copy.
2539 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
2540 roclone = ((roindex == -1) ? 0 : 1);
2541 rwindex = Lp_GetRwIndex(&entry);
2543 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
2545 /* Make sure we have a RO volume id to work with */
2546 if (entry.volumeId[ROVOL] == INVALID_BID) {
2547 /* need to get a new RO volume id */
2548 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
2549 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
2551 entry.volumeId[ROVOL] = roVolId;
2552 MapNetworkToHost(&entry, &storeEntry);
2553 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2554 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2557 /* Will we be completing a previously unfinished release. -force overrides */
2558 for (fullrelease=1, i=0; (fullrelease && (i<entry.nServers)); i++) {
2559 if (entry.serverFlags[i] & NEW_REPSITE)
2562 if (forceflag && !fullrelease)
2565 /* Determine which volume id to use and see if it exists */
2566 cloneVolId = ((fullrelease || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
2567 code = VolumeExists(afromserver, afrompart, cloneVolId);
2568 roexists = ((code == ENODEV) ? 0 : 1);
2569 if (!roexists && !fullrelease)
2570 fullrelease = 1; /* Do a full release if RO clone does not exist */
2574 fprintf(STDOUT,"This is a complete release of the volume %lu\n",
2575 (unsigned long) afromvol);
2577 fprintf(STDOUT,"This is a completion of the previous release\n");
2581 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2583 ONERROR(-1, afromserver, "Cannot establish connection with server 0x%x\n");
2586 /* If the RO clone exists, then if the clone is a temporary
2587 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2588 * (it was recently added), then also delete it. We do not
2589 * want to "reclone" a temporary RO clone.
2592 (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE)) ) {
2593 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2594 if (code && (code != VNOVOL))
2599 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2600 * write this entry out to the vlserver until after the first
2601 * RO volume is released (temp RO clones don't count).
2603 for (i=0; i<entry.nServers; i++) {
2604 entry.serverFlags[i] &= ~NEW_REPSITE;
2605 entry.serverFlags[i] |= RO_DONTUSE;
2607 entry.serverFlags[rwindex] |= NEW_REPSITE;
2608 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2610 /* Begin transaction on RW and mark it busy while we clone it */
2611 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &clonetid);
2612 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2614 /* Clone or reclone the volume */
2616 VPRINT1("Recloning RW volume %u...", cloneVolId);
2617 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2618 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2622 strcpy(vname, entry.name);
2623 strcat(vname, ".readonly");
2624 VPRINT("Cloning RW volume %u to permanent RO...");
2626 strcpy(vname, "readonly-clone-temp");
2627 VPRINT("Cloning RW volume %u to temporary RO...");
2629 code = AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, &cloneVolId);
2630 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
2634 /* Get the time the RW was created for future information */
2635 VPRINT1("Getting status of RW volume %u...", cloneVolId);
2636 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
2637 ONERROR(code, cloneVolId, "Failed to get the status of the RW volume %u\n");
2639 rwcrdate = volstatus.creationDate;
2641 /* End the transaction on the RW volume */
2642 VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
2643 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2645 ONERROR((code?code:rcode), cloneVolId, "Failed to end cloning transaction on RW %u\n");
2648 /* Remember clone volume ID in case we fail or are interrupted */
2649 entry.cloneId = cloneVolId;
2652 /* Bring the RO clone online - though not if it's a temporary clone */
2653 VPRINT1("Starting transaction on RO clone volume %u...", cloneVolId);
2654 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline, &onlinetid);
2655 ONERROR(code, cloneVolId, "Failed to start transaction on volume %u\n");
2658 VPRINT1("Setting volume flags for volume %u...", cloneVolId);
2659 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
2662 VPRINT1("Ending transaction on volume %u...", cloneVolId);
2663 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
2664 ONERROR((code?code:rcode), cloneVolId, "Failed to end transaction on RO clone %u\n");
2667 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
2669 /* Sleep so that a client searching for an online volume won't
2670 * find the clone offline and then the next RO offline while the
2671 * release brings the clone online and the next RO offline (race).
2672 * There is a fix in the 3.4 client that does not need this sleep
2673 * anymore, but we don't know what clients we have.
2675 if (entry.nServers > 2)
2678 /* Mark the RO clone in the VLDB as a good site (already released)*/
2679 entry.serverFlags[roindex] |= NEW_REPSITE;
2680 entry.serverFlags[roindex] &= ~RO_DONTUSE;
2681 entry.flags |= RO_EXISTS;
2685 /* Write out the VLDB entry only if the clone is not a temporary
2686 * clone. If we did this to a temporary clone then we would end
2687 * up marking all the ROs as "old release" making the ROs
2688 * temporarily unavailable.
2690 MapNetworkToHost(&entry, &storeEntry);
2691 VPRINT1("Replacing VLDB entry for %s...", entry.name);
2692 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2693 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2698 /* Now we will release from the clone to the remaining RO replicas.
2699 * The first 2 ROs (counting the non-temporary RO clone) are released
2700 * individually: releasecount. This is to reduce the race condition
2701 * of clients trying to find an on-line RO volume. The remaining ROs
2702 * are released in parallel but no more than half the number of ROs
2703 * (rounded up) at a time: nservers.
2706 strcpy(vname, entry.name);
2707 strcat(vname, ".readonly");
2708 memset(&cookie, 0, sizeof(cookie));
2709 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
2710 cookie.type = ROVOL;
2711 cookie.parent = entry.volumeId[RWVOL];
2714 nservers = entry.nServers/2; /* how many to do at once, excluding clone */
2715 replicas = (struct replica *) malloc (sizeof(struct replica)*nservers+1);
2716 times = (struct release *) malloc (sizeof(struct release)*nservers+1);
2717 toconns = (struct rx_connection **) malloc (sizeof(struct rx_connection *)*nservers+1);
2718 results.manyResults_val = (afs_int32 *) malloc (sizeof(afs_int32)*nservers+1);
2719 if ( !replicas || !times || !! !results.manyResults_val || !toconns )
2720 ONERROR(ENOMEM, 0, "Failed to create transaction on the release clone\n");
2722 memset(replicas, 0, (sizeof(struct replica)*nservers+1));
2723 memset(times, 0, (sizeof(struct release)*nservers+1));
2724 memset(toconns, 0, (sizeof(struct rx_connection *)*nservers+1));
2725 memset(results.manyResults_val, 0, (sizeof(afs_int32)*nservers+1));
2727 /* Create a transaction on the cloned volume */
2728 VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
2729 code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
2730 if (!fullrelease && code)
2731 ONERROR(VOLSERNOVOL, afromvol,"Old clone is inaccessible. Try vos release -f %u.\n");
2732 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
2735 /* For each index in the VLDB */
2736 for (vldbindex=0; vldbindex<entry.nServers; ) {
2738 /* Get a transaction on the replicas. Pick replacas which have an old release. */
2739 for (volcount=0; ((volcount<nservers) && (vldbindex<entry.nServers)); vldbindex++) {
2740 /* The first two RO volumes will be released individually.
2741 * The rest are then released in parallel. This is a hack
2742 * for clients not recognizing right away when a RO volume
2743 * comes back on-line.
2745 if ((volcount == 1) && (releasecount < 2))
2748 if (vldbindex == roindex) continue; /* the clone */
2749 if ( (entry.serverFlags[vldbindex] & NEW_REPSITE) &&
2750 !(entry.serverFlags[vldbindex] & RO_DONTUSE) ) continue;
2751 if (!(entry.serverFlags[vldbindex] & ITSROVOL)) continue; /* not a RO vol */
2754 /* Get a Transaction on this replica. Get a new connection if
2755 * necessary. Create the volume if necessary. Return the
2756 * time from which the dump should be made (0 if it's a new
2757 * volume). Each volume might have a different time.
2759 replicas[volcount].server.destHost = ntohl(entry.serverNumber[vldbindex]);
2760 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
2761 replicas[volcount].server.destSSID = 1;
2762 times[volcount].vldbEntryIndex = vldbindex;
2764 code = GetTrans(&entry, vldbindex, &(toconns[volcount]),
2765 &(replicas[volcount].trans), &(times[volcount].time));
2768 /* Thisdate is the date from which we want to pick up all changes */
2769 if (forceflag || !fullrelease || (rwcrdate > times[volcount].time)) {
2770 /* If the forceflag is set, then we want to do a full dump.
2771 * If it's not a full release, we can't be sure that the creation
2772 * date is good (so we also do a full dump).
2773 * If the RW volume was replaced (its creation date is newer than
2774 * the last release), then we can't be sure what has changed (so
2775 * we do a full dump).
2778 } else if (remembertime[vldbindex].validtime) {
2779 /* Trans was prev ended. Use the time from the prev trans
2780 * because, prev trans may have created the volume. In which
2781 * case time[volcount].time would be now instead of 0.
2783 thisdate = (remembertime[vldbindex].time < times[volcount].time) ?
2784 remembertime[vldbindex].time : times[volcount].time;
2786 thisdate = times[volcount].time;
2788 remembertime[vldbindex].validtime = 1;
2789 remembertime[vldbindex].time = thisdate;
2791 if (volcount == 0) {
2792 fromdate = thisdate;
2794 /* Include this volume if it is within 15 minutes of the earliest */
2795 if (((fromdate>thisdate)?(fromdate-thisdate):(thisdate-fromdate)) > 900) {
2796 AFSVolEndTrans(toconns[volcount], replicas[volcount].trans, &rcode);
2797 replicas[volcount].trans = 0;
2800 if (thisdate < fromdate)
2801 fromdate = thisdate;
2805 if (!volcount) continue;
2808 fprintf(STDOUT,"Starting ForwardMulti from %lu to %u on %s",
2809 (unsigned long) cloneVolId, entry.volumeId[ROVOL],
2810 hostutil_GetNameByINet(entry.serverNumber[times[0].vldbEntryIndex]));
2812 for (s=1; s<volcount; s++) {
2813 fprintf(STDOUT," and %s",
2814 hostutil_GetNameByINet(entry.serverNumber[times[s].vldbEntryIndex]));
2818 fprintf(STDOUT," (full release)");
2819 fprintf(STDOUT,".\n");
2823 /* Release the ones we have collected */
2824 tr.manyDests_val = &(replicas[0]);
2825 tr.manyDests_len = results.manyResults_len = volcount;
2826 code = AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2827 if (code == RXGEN_OPCODE) { /* RPC Interface Mismatch */
2828 code = SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2833 PrintError("Release failed: ", code);
2835 for (m=0; m<volcount; m++) {
2836 if (results.manyResults_val[m]) {
2837 if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
2838 /* we retry timed out transaction. When it is
2839 * not the first volume and the transaction wasn't found
2840 * (assume it timed out and was garbage collected by volser).
2842 PrintError("Failed to dump volume from clone to a ro site: ",
2843 results.manyResults_val[m]);
2848 code = AFSVolSetIdsTypes(toconns[m], replicas[m].trans,
2849 vname, ROVOL, entry.volumeId[RWVOL], 0, 0);
2851 if ((m == 0) || (code != ENOENT)) {
2852 PrintError("Failed to set correct names and ids: ", code);
2857 /* have to clear dest. flags to ensure new vol goes online:
2858 * because the restore (forwarded) operation copied
2859 * the V_inService(=0) flag over to the destination.
2861 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
2863 if ((m == 0) || (code != ENOENT)) {
2864 PrintError("Failed to set flags on ro volume: ", code);
2869 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
2870 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
2871 entry.flags |= RO_EXISTS;
2876 /* End the transactions and destroy the connections */
2877 for (s=0; s<volcount; s++) {
2878 if (replicas[s].trans)
2879 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
2880 replicas[s].trans = 0;
2881 if (!code) code = rcode;
2883 if ((s == 0) || (code != ENOENT)) {
2884 PrintError("Could not end transaction on a ro volume: ", code);
2886 PrintError("Transaction timed out on a ro volume. Will retry.\n", 0);
2887 if (times[s].vldbEntryIndex < vldbindex)
2888 vldbindex = times[s].vldbEntryIndex;
2893 rx_DestroyConnection(toconns[s]);
2897 MapNetworkToHost(&entry, &storeEntry);
2898 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2899 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2900 } /* for each index in the vldb */
2902 /* End the transaction on the cloned volume */
2903 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2905 if (!code) code = rcode;
2907 PrintError("Failed to end transaction on rw volume: ", code);
2909 /* Figure out if any volume were not released and say so */
2910 for (failure=0, i=0; i<entry.nServers; i++) {
2911 if (!(entry.serverFlags[i] & NEW_REPSITE))
2916 fprintf(STDERR, "The volume %lu could not be released to the following %d sites:\n",
2917 (unsigned long) afromvol, failure);
2918 for (i=0; i<entry.nServers; i++) {
2919 if (!(entry.serverFlags[i] & NEW_REPSITE)) {
2920 MapPartIdIntoName(entry.serverPartition[i],pname);
2921 fprintf(STDERR,"\t%35s %s\n",
2922 hostutil_GetNameByINet(entry.serverNumber[i]), pname);
2926 MapNetworkToHost(&entry,&storeEntry);
2927 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, LOCKREL_TIMESTAMP);
2928 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2930 ERROREXIT(VOLSERBADRELEASE);
2933 /* All the ROs were release successfully. Remove the temporary clone */
2936 fprintf(STDOUT,"Deleting the releaseClone %lu ...",
2937 (unsigned long) cloneVolId);
2940 code = DelVol (fromconn, cloneVolId, afrompart, ITOffline);
2941 ONERROR (code, cloneVolId, "Failed to delete volume %u.\n");
2946 for (i=0; i<entry.nServers; i++)
2947 entry.serverFlags[i] &= ~NEW_REPSITE;
2949 /* Update the VLDB */
2950 VPRINT("updating VLDB ...");
2952 MapNetworkToHost(&entry, &storeEntry);
2953 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
2954 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2955 ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2960 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2963 fprintf (STDERR,"Failed to end cloning transaction on the RW volume %lu\n",
2964 (unsigned long) afromvol);
2965 if (!error) error = code;
2969 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2972 fprintf (STDERR,"Failed to end transaction on the release clone %lu\n",
2973 (unsigned long) cloneVolId);
2974 if (!error) error = code;
2977 for (i=0; i<nservers; i++) {
2978 if (replicas && replicas[i].trans) {
2979 code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
2980 replicas[i].trans = 0;
2982 fprintf(STDERR,"Failed to end transaction on ro volume %u at server 0x%x\n",
2983 entry.volumeId[ROVOL],
2984 hostutil_GetNameByINet(htonl(replicas[i].server.destHost)));
2985 if (!error) error = code;
2988 if (toconns && toconns[i]) {
2989 rx_DestroyConnection(toconns[i]);
2994 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, RWVOL,
2995 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2997 fprintf(STDERR,"Could not release lock on the VLDB entry for volume %lu\n",
2998 (unsigned long) afromvol);
2999 if (!error) error = vcode;
3003 PrintError("", error);
3005 if (fromconn) rx_DestroyConnection(fromconn);
3006 if (results.manyResults_val) free (results.manyResults_val);
3007 if (replicas) free (replicas);
3008 if (toconns) free (toconns);
3009 if (times) free (times);
3014 void dump_sig_handler(int x)
3016 fprintf(STDERR,"\nSignal handler: vos dump operation\n");
3020 /* Dump the volume <afromvol> on <afromserver> and
3021 * <afrompart> to <afilename> starting from <fromdate>.
3022 * DumpFunction does the real work behind the scenes after
3023 * extracting parameters from the rock
3025 int UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
3026 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
3028 struct rx_connection *fromconn = (struct rx_connection *)0;
3029 struct rx_call *fromcall = (struct rx_call *)0;
3030 afs_int32 fromtid=0, rxError=0, rcode=0;
3031 afs_int32 code, error = 0;
3033 if (setjmp(env)) ERROR_EXIT(EPIPE);
3034 #ifndef AFS_NT40_ENV
3035 (void) signal(SIGPIPE, dump_sig_handler);
3037 (void) signal(SIGINT, dump_sig_handler);
3041 VPRINT("Full Dump ...\n");
3045 VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
3048 /* get connections to the servers */
3049 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3051 VPRINT1("Starting transaction on volume %u...", afromvol);
3052 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3053 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3056 fromcall = rx_NewCall(fromconn);
3058 VPRINT1("Starting volume dump on volume %u...", afromvol);
3059 code = StartAFSVolDump(fromcall, fromtid, fromdate);
3060 EGOTO(error_exit, code, "Could not start the dump process \n");
3063 VPRINT1("Dumping volume %u...", afromvol);
3064 code = DumpFunction(fromcall, rock);
3065 EGOTO(error_exit, code, "Error while dumping volume \n");
3070 code = rx_EndCall(fromcall, rxError);
3072 fprintf(STDERR,"Error in rx_EndCall\n");
3073 if (!error) error = code;
3077 VPRINT1("Ending transaction on volume %u...", afromvol);
3078 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3079 if (code || rcode) {
3080 fprintf(STDERR,"Could not end transaction on the volume %lu\n",
3081 (unsigned long) afromvol);
3082 if (!error) error = (code?code:rcode);
3087 rx_DestroyConnection(fromconn);
3089 PrintError("", error);
3093 /* Clone the volume <afromvol> on <afromserver> and
3094 * <afrompart>, and then dump the clone volume to
3095 * <afilename> starting from <fromdate>.
3096 * DumpFunction does the real work behind the scenes after
3097 * extracting parameters from the rock
3099 int UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
3100 afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
3102 struct rx_connection *fromconn = (struct rx_connection *)0;
3103 struct rx_call *fromcall = (struct rx_call *)0;
3104 afs_int32 fromtid=0, rxError=0, rcode=0;
3105 afs_int32 clonetid=0;
3106 afs_int32 code=0, vcode=0, error = 0;
3107 afs_int32 clonevol=0;
3110 if (setjmp(env)) ERROR_EXIT(EPIPE);
3111 #ifndef AFS_NT40_ENV
3112 (void) signal(SIGPIPE, dump_sig_handler);
3114 (void) signal(SIGINT, dump_sig_handler);
3118 VPRINT("Full Dump ...\n");
3122 VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
3125 /* get connections to the servers */
3126 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3128 VPRINT1("Starting transaction on volume %u...", afromvol);
3129 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3130 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3133 /* Get a clone id */
3134 VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
3135 code = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &clonevol);
3136 EGOTO1(error_exit, code, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
3139 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
3140 VPRINT2("Cloning source volume %u to clone volume %u...", afromvol, clonevol);
3141 strcpy(vname, "dump-clone-temp");
3142 code = AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
3143 EGOTO1(error_exit, code, "Failed to clone the source volume %u\n", afromvol);
3146 VPRINT1("Ending the transaction on the volume %u ...", afromvol);
3148 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3150 if (!code) code = rcode;
3151 EGOTO1(error_exit, code, "Failed to end the transaction on the volume %u\n", afromvol);
3155 VPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
3156 code = AFSVolTransCreate (fromconn, clonevol, afrompart, ITOffline, &clonetid);
3157 EGOTO1(error_exit, code, "Failed to start a transaction on the cloned volume%u\n", clonevol);
3160 VPRINT1("Setting flags on cloned volume %u ...", clonevol);
3161 code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
3162 EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n", clonevol);
3166 fromcall = rx_NewCall(fromconn);
3168 VPRINT1("Starting volume dump from cloned volume %u...", clonevol);
3169 code = StartAFSVolDump(fromcall, clonetid, fromdate);
3170 EGOTO(error_exit, code, "Could not start the dump process \n");
3173 VPRINT1("Dumping volume %u...", afromvol);
3174 code = DumpFunction(fromcall, rock);
3175 EGOTO(error_exit, code, "Error while dumping volume \n");
3179 /* now delete the clone */
3180 VPRINT1("Deleting the cloned volume %u ...", clonevol);
3181 code = AFSVolDeleteVolume(fromconn, clonetid);
3184 fprintf(STDERR,"Failed to delete the cloned volume %lu\n",
3185 (unsigned long) clonevol);
3193 code = rx_EndCall(fromcall, rxError);
3195 fprintf(STDERR,"Error in rx_EndCall\n");
3196 if (!error) error = code;
3200 VPRINT1("Ending transaction on cloned volume %u...", clonevol);
3201 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3202 if (code || rcode) {
3203 fprintf(STDERR,"Could not end transaction on the cloned volume %lu\n",
3204 (unsigned long) clonevol);
3205 if (!error) error = (code?code:rcode);
3210 rx_DestroyConnection(fromconn);
3212 PrintError("", error);
3219 * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
3220 * the dump file <afilename>. WriteData does all the real work
3221 * after extracting params from the rock
3223 int UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
3224 char tovolname[], int flags, afs_int32 (*WriteData)(), char *rock)
3226 struct rx_connection *toconn,*tempconn;
3227 struct rx_call *tocall;
3228 afs_int32 totid, code, rcode, vcode,terror = 0;
3229 afs_int32 rxError = 0;
3230 struct volser_status tstatus;
3235 struct nvldbentry entry,storeEntry;
3238 struct restoreCookie cookie;
3240 afs_int32 newDate, volflag, voltype, volsertype;
3241 int index, same, errcode;
3245 memset(&cookie, 0, sizeof(cookie));
3250 tocall = (struct rx_call *)0;
3251 toconn = (struct rx_connection *)0;
3252 tempconn = (struct rx_connection *)0;
3256 if (flags & RV_RDONLY) {
3258 volsertype = volser_RO;
3261 volsertype = volser_RW;
3265 toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
3266 if(pvolid == 0) {/*alot a new id if needed */
3267 vcode = VLDB_GetEntryByName(tovolname, &entry);
3268 if(vcode == VL_NOENT) {
3269 vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 1, &pvolid);
3271 fprintf(STDERR,"Could not get an Id for the volume %s\n",tovolname);
3276 } else if (flags & RV_RDONLY) {
3277 if (entry.flags & RW_EXISTS) {
3278 fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
3279 error = VOLSERBADOP;
3282 if (!entry.volumeId[ROVOL]) {
3283 fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
3284 error = VOLSERBADOP;
3287 pvolid = entry.volumeId[ROVOL];
3289 pvolid = entry.volumeId[RWVOL];
3291 }/* at this point we have a volume id to use/reuse for the volume to be restored */
3293 if(strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
3294 EGOTO1(refail, VOLSERBADOP, "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",tovolname);
3296 MapPartIdIntoName(topart, partName);
3297 fprintf(STDOUT,"Restoring volume %s Id %lu on server %s partition %s ..",
3299 (unsigned long) pvolid,
3300 hostutil_GetNameByINet(toserver), partName);
3302 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3304 if (flags & RV_FULLRST) { /* full restore: delete then create anew */
3305 VPRINT1("Deleting the previous volume %u ...",pvolid);
3307 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3308 EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3310 code = AFSVolSetFlags(toconn, totid, VTDeleteOnSalvage | VTOutOfService);
3311 EGOTO1(refail, code, "Could not set flags on volume %u \n",pvolid);
3313 code = AFSVolDeleteVolume(toconn,totid);
3314 EGOTO1(refail, code, "Could not delete volume %u\n",pvolid);
3316 code = AFSVolEndTrans(toconn, totid, &rcode);
3318 if (!code) code = rcode;
3319 EGOTO1(refail, code, "Could not end transaction on %u\n",pvolid);
3323 code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3324 EGOTO1(refail, code, "Could not create new volume %u\n",pvolid);
3327 code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3328 EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3331 cookie.parent = pvolid;
3332 cookie.type = voltype;
3334 strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
3336 tocall = rx_NewCall(toconn);
3337 terror = StartAFSVolRestore(tocall,totid, 1,&cookie);
3339 fprintf(STDERR,"Volume restore Failed \n");
3343 code = WriteData(tocall, rock);
3345 fprintf(STDERR,"Could not transmit data\n");
3349 terror = rx_EndCall(tocall,rxError);
3350 tocall = (struct rx_call *) 0;
3352 fprintf(STDERR,"rx_EndCall Failed \n");
3356 code = AFSVolGetStatus(toconn,totid, &tstatus);
3358 fprintf(STDERR,"Could not get status information about the volume %lu\n",
3359 (unsigned long) pvolid);
3363 code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
3365 fprintf(STDERR,"Could not set the right type and ID on %lu\n",
3366 (unsigned long) pvolid);
3371 code = AFSVolSetDate(toconn,totid, newDate);
3373 fprintf(STDERR,"Could not set the date on %lu\n",
3374 (unsigned long) pvolid);
3379 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
3380 code = AFSVolSetFlags(toconn, totid, volflag);
3382 fprintf(STDERR,"Could not mark %lu online\n", (unsigned long) pvolid );
3387 /* It isn't handled right in refail */
3388 code = AFSVolEndTrans(toconn, totid, &rcode);
3390 if(!code) code = rcode;
3392 fprintf(STDERR,"Could not end transaction on %lu\n",
3393 (unsigned long) pvolid);
3399 fprintf(STDOUT," done\n");
3401 if (success && (!reuseID || (flags & RV_FULLRST))) {
3402 /* Volume was restored on the file server, update the
3403 * VLDB to reflect the change.
3405 vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
3406 if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
3407 fprintf(STDERR,"Could not fetch the entry for volume number %lu from VLDB \n",
3408 (unsigned long) pvolid);
3412 if (!vcode) MapHostToNetwork(&entry);
3413 if(vcode == VL_NOENT) { /* it doesnot exist already */
3414 /*make the vldb return this indication specifically*/
3415 VPRINT("------- Creating a new VLDB entry ------- \n");
3416 strcpy(entry.name, tovolname);
3418 entry.serverNumber[0] = toserver;/*should be indirect */
3419 entry.serverPartition[0] = topart;
3420 entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3421 entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3422 if (flags & RV_RDONLY)
3423 entry.volumeId[ROVOL] = pvolid;
3424 else if(tstatus.cloneID != 0){
3425 entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
3428 entry.volumeId[ROVOL] = INVALID_BID;
3429 entry.volumeId[RWVOL] = pvolid;
3431 if(tstatus.backupID != 0){
3432 entry.volumeId[BACKVOL] = tstatus.backupID;
3433 /*this should come from status info on the volume if non zero */
3436 entry.volumeId[BACKVOL] = INVALID_BID;
3437 MapNetworkToHost(&entry,&storeEntry);
3438 vcode = VLDB_CreateEntry(&storeEntry);
3440 fprintf(STDERR,"Could not create the VLDB entry for volume number %lu \n",
3441 (unsigned long) pvolid);
3446 if (verbose) EnumerateEntry(&entry);
3448 else { /*update the existing entry */
3450 fprintf(STDOUT,"Updating the existing VLDB entry\n");
3451 fprintf(STDOUT,"------- Old entry -------\n");
3452 EnumerateEntry(&entry);
3453 fprintf(STDOUT,"------- New entry -------\n");
3455 vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
3457 fprintf(STDERR,"Could not lock the entry for volume number %lu \n",
3458 (unsigned long) pvolid);
3463 strcpy(entry.name, tovolname);
3465 /* Update the vlentry with the new information */
3466 if (flags & RV_RDONLY)
3467 index = Lp_ROMatch(toserver, topart, &entry) - 1;
3469 index = Lp_GetRwIndex(&entry);
3471 /* Add the new site for the volume being restored */
3472 entry.serverNumber[entry.nServers] = toserver;
3473 entry.serverPartition[entry.nServers] = topart;
3474 entry.serverFlags[entry.nServers] =
3475 (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3478 /* This volume should be deleted on the old site
3479 * if its different from new site.
3481 same = VLDB_IsSameAddrs(toserver, entry.serverNumber[index], &errcode);
3482 EPRINT2(errcode, "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
3484 if ( (!errcode && !same) || (entry.serverPartition[index] != topart) ) {
3485 tempconn = UV_Bind(entry.serverNumber[index], AFSCONF_VOLUMEPORT);
3487 MapPartIdIntoName(entry.serverPartition[index], apartName);
3488 VPRINT3("Deleting the previous volume %u on server %s, partition %s ...",
3490 hostutil_GetNameByINet(entry.serverNumber[index]), apartName);
3491 code = AFSVolTransCreate(tempconn, pvolid, entry.serverPartition[index], ITOffline, &temptid);
3493 code = AFSVolSetFlags(tempconn, temptid, VTDeleteOnSalvage | VTOutOfService);
3495 fprintf(STDERR,"Could not set flags on volume %lu on the older site\n",
3496 (unsigned long) pvolid);
3500 code = AFSVolDeleteVolume(tempconn,temptid);
3502 fprintf(STDERR,"Could not delete volume %lu on the older site\n",
3503 (unsigned long) pvolid);
3507 code = AFSVolEndTrans(tempconn, temptid, &rcode);
3509 if(!code) code = rcode;
3511 fprintf(STDERR,"Could not end transaction on volume %lu on the older site\n",
3512 (unsigned long) pvolid);
3517 MapPartIdIntoName(entry.serverPartition[index],partName);
3520 entry.serverNumber[index] = toserver;
3521 entry.serverPartition[index] = topart;
3524 entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3525 MapNetworkToHost(&entry,&storeEntry);
3526 vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3528 fprintf(STDERR,"Could not update the entry for volume number %lu \n",
3529 (unsigned long) pvolid);
3534 if(verbose) EnumerateEntry(&entry);
3541 code = rx_EndCall(tocall, rxError);
3542 if (!error) error = code;
3545 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3547 fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %lu\n",
3548 (unsigned long) pvolid);
3549 if(!error) error = vcode;
3553 code = AFSVolEndTrans(toconn, totid, &rcode);
3554 if(!code) code = rcode;
3556 fprintf(STDERR,"Could not end transaction on the volume %lu \n",
3557 (unsigned long) pvolid);
3558 if(!error) error = code;
3562 code = AFSVolEndTrans(toconn, temptid, &rcode);
3563 if(!code) code = rcode;
3565 fprintf(STDERR,"Could not end transaction on the volume %lu \n",
3566 (unsigned long) pvolid);
3567 if(!error) error = code;
3570 if(tempconn) rx_DestroyConnection(tempconn);
3571 if(toconn) rx_DestroyConnection(toconn);
3572 PrintError("",error);
3577 /*unlocks the vldb entry associated with <volid> */
3578 int UV_LockRelease(afs_int32 volid)
3584 VPRINT("Binding to the VLDB server\n");
3585 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,volid,-1,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3587 fprintf(STDERR,"Could not unlock the entry for volume number %lu in VLDB \n",
3588 (unsigned long) volid);
3589 PrintError("",vcode);
3592 VPRINT("VLDB updated\n");
3597 /*adds <server> and <part> as a readonly replication site for <volid>
3599 int UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3601 int j, nro=0, islocked=0;
3602 struct nvldbentry entry,storeEntry;
3603 afs_int32 vcode, error=0;
3606 error = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3608 fprintf(STDERR," Could not lock the VLDB entry for the volume %lu \n",
3609 (unsigned long) volid);
3614 error = VLDB_GetEntryByID(volid,RWVOL, &entry);
3616 fprintf(STDERR,"Could not fetch the VLDB entry for volume number %lu \n",
3617 (unsigned long) volid);
3621 if (!ISNAMEVALID(entry.name)){
3622 fprintf(STDERR,"Volume name %s is too long, rename before adding site\n", entry.name);
3623 error = VOLSERBADOP;
3626 MapHostToNetwork(&entry);
3628 /* See if it's too many entries */
3629 if (entry.nServers >= NMAXNSERVERS){
3630 fprintf(STDERR,"Total number of entries will exceed %u\n", NMAXNSERVERS);
3631 error = VOLSERBADOP;
3635 /* See if it's on the same server */
3636 for (j=0; j < entry.nServers; j++) {
3637 if (entry.serverFlags[j] & ITSROVOL) {
3639 if (VLDB_IsSameAddrs(server, entry.serverNumber[j], &error)) {
3641 fprintf(STDERR,"Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
3644 MapPartIdIntoName(entry.serverPartition[j], apartName);
3645 fprintf(STDERR,"RO already exists on partition %s. Multiple ROs on a single server aren't allowed\n", apartName);
3646 error = VOLSERBADOP;
3653 /* See if it's too many RO sites - leave one for the RW */
3654 if (nro >= NMAXNSERVERS-1){
3655 fprintf(STDERR,"Total number of sites will exceed %u\n", NMAXNSERVERS-1);
3656 error = VOLSERBADOP;
3660 VPRINT("Adding a new site ...");
3661 entry.serverNumber[entry.nServers] = server;
3662 entry.serverPartition[entry.nServers] = part;
3663 entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
3666 MapNetworkToHost(&entry,&storeEntry);
3667 error = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3669 fprintf(STDERR,"Could not update entry for volume %lu \n",
3670 (unsigned long) volid);
3678 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3680 fprintf(STDERR,"Could not release lock on volume entry for %lu \n",
3681 (unsigned long) volid);
3682 PrintError("", vcode);
3686 PrintError("", error);
3690 /*removes <server> <part> as read only site for <volid> from the vldb */
3691 int UV_RemoveSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3694 struct nvldbentry entry,storeEntry;
3697 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3699 fprintf(STDERR," Could not lock the VLDB entry for volume %lu \n",
3700 (unsigned long) volid);
3701 PrintError("",vcode);
3705 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3707 fprintf(STDERR,"Could not fetch the entry for volume number %lu from VLDB \n",
3708 (unsigned long) volid);
3709 PrintError("",vcode);
3712 MapHostToNetwork(&entry);
3713 if(!Lp_ROMatch(server, part, &entry)){
3714 /*this site doesnot exist */
3715 fprintf(STDERR,"This site is not a replication site \n");
3716 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3718 fprintf(STDERR,"Could not update entry for volume %lu \n",
3719 (unsigned long) volid);
3720 PrintError("",vcode);
3721 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3726 else { /*remove the rep site */
3727 Lp_SetROValue(&entry, server, part, 0, 0);
3729 if((entry.nServers == 1) && (entry.flags & RW_EXISTS))
3730 entry.flags &= ~RO_EXISTS;
3731 if(entry.nServers < 1) { /*this is the last ref */
3732 VPRINT1("Deleting the VLDB entry for %u ...",volid);
3734 vcode = ubik_Call(VL_DeleteEntry,cstruct, 0,volid, ROVOL);
3736 fprintf(STDERR,"Could not delete VLDB entry for volume %lu \n",
3737 (unsigned long) volid);
3738 PrintError("",vcode);
3743 MapNetworkToHost(&entry,&storeEntry);
3744 fprintf(STDOUT,"Deleting the replication site for volume %lu ...",
3745 (unsigned long) volid);
3747 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3749 fprintf(STDERR,"Could not release lock on volume entry for %lu \n",
3750 (unsigned long) volid);
3751 PrintError("",vcode);
3752 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3760 /*sets <server> <part> as read/write site for <volid> in the vldb */
3761 int UV_ChangeLocation(afs_int32 server, afs_int32 part, afs_int32 volid)
3764 struct nvldbentry entry,storeEntry;
3767 vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3769 fprintf(STDERR," Could not lock the VLDB entry for volume %lu \n",
3770 (unsigned long) volid);
3771 PrintError("",vcode);
3774 vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
3776 fprintf(STDERR,"Could not fetch the entry for volume number %lu from VLDB \n",
3777 (unsigned long) volid);
3778 PrintError("",vcode);
3781 MapHostToNetwork(&entry);
3782 index = Lp_GetRwIndex(&entry);
3784 /* no RW site exists */
3785 fprintf(STDERR,"No existing RW site for volume %lu",
3786 (unsigned long) volid);
3787 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3789 fprintf(STDERR,"Could not release lock on entry for volume %lu \n",
3790 (unsigned long) volid);
3791 PrintError("",vcode);
3796 else { /* change the RW site */
3797 entry.serverNumber[index] = server;
3798 entry.serverPartition[index] = part;
3799 MapNetworkToHost(&entry,&storeEntry);
3800 vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3802 fprintf(STDERR,"Could not update entry for volume %lu \n",
3803 (unsigned long) volid);
3804 PrintError("",vcode);
3805 ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3813 /*list all the partitions on <aserver> */
3814 int UV_ListPartitions(afs_int32 aserver, struct partList *ptrPartList, afs_int32 *cntp)
3816 struct rx_connection *aconn;
3817 struct pIDs partIds;
3818 struct partEntries partEnts;
3819 register int i, j=0, code;
3822 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3824 partEnts.partEntries_len = 0;
3825 partEnts.partEntries_val = NULL;
3826 code = AFSVolXListPartitions(aconn, &partEnts); /* this is available only on new servers */
3827 if (code == RXGEN_OPCODE)
3829 for(i = 0; i < 26; i++) /* try old interface */
3830 partIds.partIds[i] = -1;
3831 code = AFSVolListPartitions(aconn, &partIds);
3833 for (i = 0;i < 26; i++) {
3834 if((partIds.partIds[i]) != -1) {
3835 ptrPartList->partId[j] = partIds.partIds[i];
3836 ptrPartList->partFlags[j] = PARTVALID;
3839 ptrPartList->partFlags[i] = 0;
3846 *cntp = partEnts.partEntries_len;
3847 if (*cntp > VOLMAXPARTS) {
3848 fprintf(STDERR,"Warning: number of partitions on the server too high %d (process only %d)\n",
3849 *cntp, VOLMAXPARTS);
3850 *cntp = VOLMAXPARTS;
3852 for (i = 0;i < *cntp; i++) {
3853 ptrPartList->partId[i] = partEnts.partEntries_val[i];
3854 ptrPartList->partFlags[i] = PARTVALID;
3856 free(partEnts.partEntries_val);
3860 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
3861 PrintError("",code);
3862 if(aconn) rx_DestroyConnection(aconn);
3867 /*zap the list of volumes specified by volPtrArray (the volCloneId field).
3868 This is used by the backup system */
3869 int UV_ZapVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3871 struct rx_connection *aconn;
3872 struct volDescription *curPtr;
3875 afs_int32 rcode = 0;
3876 afs_int32 success = 1;
3879 aconn = (struct rx_connection *)0;
3880 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3882 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3883 if(curPtr->volFlags & CLONEVALID) {
3884 curPtr->volFlags &= ~CLONEZAPPED;
3886 code = AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline, &tid);
3887 if(code) success = 0;
3889 code = AFSVolDeleteVolume(aconn, tid);
3890 if(code) success = 0;
3891 code = AFSVolEndTrans(aconn, tid, &rcode);
3892 if(code || rcode) success = 0;
3894 if(success) curPtr->volFlags |= CLONEZAPPED;
3895 if(!success) fprintf(STDERR,"Could not zap volume %lu\n",
3896 (unsigned long) curPtr->volCloneId);
3897 if(success) VPRINT2("Clone of %s %u deleted\n", curPtr->volName,curPtr->volCloneId);
3902 if(aconn)rx_DestroyConnection(aconn);
3906 /*return a list of clones of the volumes specified by volPtrArray. Used by the
3908 int UV_GenerateVolumeClones(afs_int32 aserver, afs_int32 apart, struct volDescription *volPtr, afs_int32 arraySize)
3910 struct rx_connection *aconn;
3911 struct volDescription *curPtr;
3914 afs_int32 rcode = 0;
3916 int reuseCloneId = 0;
3917 afs_int32 curCloneId = 0;
3918 char cloneName[256];/*max vol name */
3920 aconn = (struct rx_connection *)0;
3921 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3923 if((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
3925 else { /*get a bunch of id's from vldb */
3926 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, arraySize, &curCloneId);
3928 fprintf(STDERR,"Could not get ID's for the clone from VLDB\n");
3929 PrintError("",code);
3934 for(curPtr = volPtr; curPos < arraySize; curPtr++) {
3935 if(curPtr->volFlags & ENTRYVALID) {
3937 curPtr->volFlags |= CLONEVALID;
3938 /*make a clone of curParentId and record as curPtr->volCloneId */
3939 code = AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline, &tid);
3940 if(code) VPRINT2("Clone for volume %s %u failed \n",curPtr->volName,curPtr->volId);
3942 curPtr->volFlags &= ~CLONEVALID; /*cant clone */
3946 if(strlen(curPtr->volName) < (VOLSER_OLDMAXVOLNAME - 9) ){
3947 strcpy(cloneName, curPtr->volName);
3948 strcat(cloneName,"-tmpClone-");
3950 else strcpy(cloneName,"-tmpClone");
3952 curPtr->volCloneId = curCloneId;
3956 code = AFSVolClone(aconn, tid, 0, readonlyVolume, cloneName,&(curPtr->volCloneId));
3958 curPtr->volFlags &= ~CLONEVALID;
3960 fprintf(STDERR,"Could not clone %s due to error %lu\n", curPtr->volName,
3961 (unsigned long) code);
3962 code=AFSVolEndTrans(aconn, tid, &rcode);
3964 fprintf(STDERR,"WARNING: could not end transaction\n");
3967 VPRINT2("********** Cloned %s temporary %u\n",cloneName,curPtr->volCloneId);
3968 code = AFSVolEndTrans(aconn, tid, &rcode);
3970 curPtr->volFlags &= ~CLONEVALID;
3978 if (aconn) rx_DestroyConnection(aconn);
3983 /*list all the volumes on <aserver> and <apart>. If all = 1, then all the
3984 * relevant fields of the volume are also returned. This is a heavy weight operation.*/
3985 int UV_ListVolumes(afs_int32 aserver, afs_int32 apart, int all, struct volintInfo **resultPtr, afs_int32 *size)
3987 struct rx_connection *aconn;
3989 volEntries volumeInfo;
3993 *resultPtr = (volintInfo *)0;
3994 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
3995 volumeInfo.volEntries_len = 0;
3997 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
3998 code = AFSVolListVolumes(aconn, apart, all, &volumeInfo);
4000 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
4003 *resultPtr = volumeInfo.volEntries_val;
4004 *size = volumeInfo.volEntries_len;
4007 if(aconn) rx_DestroyConnection(aconn);
4008 PrintError("",code);
4012 /*------------------------------------------------------------------------
4013 * EXPORTED UV_XListVolumes
4016 * List the extended information for all the volumes on a particular
4017 * File Server and partition. We may either return the volume's ID
4018 * or all of its extended information.
4021 * a_serverID : Address of the File Server for which we want
4022 * extended volume info.
4023 * a_partID : Partition for which we want the extended
4025 * a_all : If non-zero, fetch ALL the volume info,
4026 * otherwise just the volume ID.
4027 * a_resultPP : Ptr to the address of the area containing
4028 * the returned volume info.
4029 * a_numEntsInResultP : Ptr for the value we set for the number of
4034 * Otherise, the return value of AFSVolXListVolumes.
4037 * This routine is closely related to UV_ListVolumes, which returns
4038 * only the standard level of detail on AFS volumes. It is a
4039 * heavyweight operation, zipping through all the volume entries for
4040 * a given server/partition.
4044 *------------------------------------------------------------------------*/
4046 int UV_XListVolumes(afs_int32 a_serverID, afs_int32 a_partID, int a_all,
4047 struct volintXInfo **a_resultPP, afs_int32 *a_numEntsInResultP)
4049 struct rx_connection *rxConnP; /*Ptr to the Rx connection involved*/
4050 afs_int32 code; /*Error code to return*/
4051 volXEntries volumeXInfo; /*Area for returned extended vol info*/
4054 * Set up our error code and the area for returned extended volume info.
4055 * We set the val field to a null pointer as a hint for the stub to
4059 *a_numEntsInResultP = 0;
4060 *a_resultPP = (volintXInfo *)0;
4061 volumeXInfo.volXEntries_val = (volintXInfo *)0;
4062 volumeXInfo.volXEntries_len = 0;
4065 * Bind to the Volume Server port on the File Server machine in question,
4068 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
4069 code = AFSVolXListVolumes(rxConnP, a_partID, a_all, &volumeXInfo);
4072 "[UV_XListVolumes] Couldn't fetch volume list\n");
4075 * We got the info; pull out the pointer to where the results lie
4076 * and how many entries are there.
4078 *a_resultPP = volumeXInfo.volXEntries_val;
4079 *a_numEntsInResultP = volumeXInfo.volXEntries_len;
4083 * If we got an Rx connection, throw it away.
4086 rx_DestroyConnection(rxConnP);
4088 PrintError("", code);
4090 } /*UV_XListVolumes*/
4092 /* get all the information about volume <volid> on <aserver> and <apart> */
4093 int UV_ListOneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 volid, struct volintInfo **resultPtr)
4095 struct rx_connection *aconn;
4097 volEntries volumeInfo;
4101 *resultPtr = (volintInfo *)0;
4102 volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
4103 volumeInfo.volEntries_len = 0;
4105 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4106 code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
4108 fprintf(STDERR,"Could not fetch the information about volume %lu from the server\n",
4109 (unsigned long) volid);
4112 *resultPtr = volumeInfo.volEntries_val;
4116 if(aconn) rx_DestroyConnection(aconn);
4117 PrintError("",code);
4121 /*------------------------------------------------------------------------
4122 * EXPORTED UV_XListOneVolume
4125 * List the extended information for a volume on a particular File
4126 * Server and partition.
4129 * a_serverID : Address of the File Server for which we want
4130 * extended volume info.
4131 * a_partID : Partition for which we want the extended
4133 * a_volID : Volume ID for which we want the info.
4134 * a_resultPP : Ptr to the address of the area containing
4135 * the returned volume info.
4139 * Otherise, the return value of AFSVolXListOneVolume.
4142 * This routine is closely related to UV_ListOneVolume, which returns
4143 * only the standard level of detail on the chosen AFS volume.
4147 *------------------------------------------------------------------------*/
4149 int UV_XListOneVolume(afs_int32 a_serverID, afs_int32 a_partID,
4150 afs_int32 a_volID, struct volintXInfo **a_resultPP)
4152 struct rx_connection *rxConnP; /*Rx connection to Volume Server*/
4153 afs_int32 code; /*Error code*/
4154 volXEntries volumeXInfo; /*Area for returned info*/
4157 * Set up our error code, and the area we're in which we are returning
4158 * the info. Setting the val field to a null pointer tells the stub
4159 * to allocate space for us.
4162 *a_resultPP = (volintXInfo *)0;
4163 volumeXInfo.volXEntries_val = (volintXInfo *)0;
4164 volumeXInfo.volXEntries_len = 0;
4167 * Bind to the Volume Server port on the File Server machine in question,
4170 rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
4171 code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
4174 "[UV_XListOneVolume] Couldn't fetch the volume information\n");
4177 * We got the info; pull out the pointer to where the results lie.
4179 *a_resultPP = volumeXInfo.volXEntries_val;
4182 * If we got an Rx connection, throw it away.
4185 rx_DestroyConnection(rxConnP);
4187 PrintError("",code);
4192 * Given a volume we read from a partition, check if it is
4193 * represented in the VLDB correctly.
4195 * The VLDB is looked up by the RW volume id (not its name).
4196 * The RW contains the true name of the volume (BK and RO set
4197 * the name in the VLDB only on creation of the VLDB entry).
4198 * We want rules strict enough that when we check all volumes
4199 * on one partition, it does not need to be done again. IE:
4200 * two volumes on different partitions won't constantly
4201 * change a VLDB entry away from what the other set.
4202 * For RW and BK volumes, we will always check the VLDB to see
4203 * if the two exist on the server/partition. May seem redundant,
4204 * but this is an easy check of the VLDB. IE: if the VLDB entry
4205 * says the BK exists but no BK volume is there, we will detect
4206 * this when we check the RW volume.
4207 * VLDB entries are locked only when a change needs to be done.
4208 * Output changed to look a lot like the "vos syncserv" otuput.
4210 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart,
4211 afs_int32 *modentry, afs_uint32 *maxvolid)
4214 afs_int32 code, error = 0;
4215 struct nvldbentry entry, storeEntry;
4217 int pass=0, islocked=0, createentry, addvolume, modified, mod;
4220 if (modentry) *modentry = 0;
4221 rwvolid = ((volumeinfo->type == RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
4224 /* Check to see if the VLDB is ok without locking it (pass 1).
4225 * If it will change, then lock the VLDB entry, read it again,
4226 * then make the changes to it (pass 2).
4229 code = ubik_Call(VL_SetLock, cstruct, 0, rwvolid, RWVOL, VLOP_DELETE);
4231 fprintf(STDERR, "Could not lock VLDB entry for %lu\n",
4232 (unsigned long) rwvolid);
4238 createentry = 0; /* Do we need to create a VLDB entry */
4239 addvolume = 0; /* Add this volume to the VLDB entry */
4240 modified = 0; /* The VLDB entry was modified */
4242 /* Read the entry from VLDB by its RW volume id */
4243 code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
4245 if (code != VL_NOENT) {
4246 fprintf(STDOUT,"Could not retreive the VLDB entry for volume %lu \n",
4247 (unsigned long) rwvolid);
4251 memset(&entry, 0, sizeof(entry));
4252 vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
4256 MapHostToNetwork(&entry);
4259 if (verbose && (pass == 1)) {
4260 fprintf(STDOUT,"_______________________________\n");
4261 fprintf(STDOUT,"\n-- status before -- \n");
4263 fprintf(STDOUT,"\n**does not exist**\n");
4265 if ((entry.flags & RW_EXISTS) ||
4266 (entry.flags & RO_EXISTS) ||
4267 (entry.flags & BACK_EXISTS))
4268 EnumerateEntry(&entry);
4270 fprintf(STDOUT,"\n");
4273 if (volumeinfo->type == RWVOL) { /* RW volume exists */
4279 /* Check existence of RW and BK volumes */
4280 code = CheckVldbRWBK(&entry, &mod);
4281 if (code) ERROR_EXIT(code);
4282 if (mod) modified++;
4284 idx = Lp_GetRwIndex(&entry);
4285 if (idx == -1) { /* RW index not found in the VLDB entry */
4286 idx = entry.nServers; /* put it into next index */
4289 } else { /* RW index found in the VLDB entry. */
4290 /* Verify if this volume's location matches where the VLDB says it is */
4291 if (!Lp_Match(aserver, apart, &entry)) {
4292 if (entry.flags & RW_EXISTS) {
4293 /* The RW volume exists elsewhere - report this one a duplicate */
4295 MapPartIdIntoName(apart, pname);
4296 fprintf(STDERR,"*** Warning: Orphaned RW volume %lu exists on %s %s\n",
4297 (unsigned long) rwvolid,
4298 hostutil_GetNameByINet(aserver), pname);
4299 MapPartIdIntoName(entry.serverPartition[idx], pname);
4300 fprintf(STDERR," VLDB reports RW volume %lu exists on %s %s\n",
4301 (unsigned long) rwvolid,
4302 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
4305 /* The RW volume does not exist - have VLDB point to this one */
4308 /* Check for orphaned BK volume on old partition */
4309 if (entry.flags & BACK_EXISTS) {
4311 MapPartIdIntoName(entry.serverPartition[idx], pname);
4312 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
4313 entry.volumeId[BACKVOL],
4314 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
4315 MapPartIdIntoName(apart, pname);
4316 fprintf(STDERR," VLDB reports its RW volume %lu exists on %s %s\n",
4317 (unsigned long) rwvolid,
4318 hostutil_GetNameByINet(aserver), pname);
4323 /* Volume location matches the VLDB location */
4324 if ( (volumeinfo->backupID && !entry.volumeId[BACKVOL]) ||
4325 (volumeinfo->cloneID && !entry.volumeId[ROVOL]) ||
4326 (strncmp(entry.name,volumeinfo->name,VOLSER_OLDMAXVOLNAME) != 0) ) {
4334 entry.flags |= RW_EXISTS;
4335 entry.volumeId[RWVOL] = rwvolid;
4336 if (!entry.volumeId[BACKVOL])
4337 entry.volumeId[BACKVOL] = volumeinfo->backupID;
4338 if (!entry.volumeId[ROVOL])
4339 entry.volumeId[ROVOL] = volumeinfo->cloneID;
4341 entry.serverFlags[idx] = ITSRWVOL;
4342 entry.serverNumber[idx] = aserver;
4343 entry.serverPartition[idx] = apart;
4344 strncpy(entry.name, volumeinfo->name, VOLSER_OLDMAXVOLNAME);
4348 /* One last check - to update BK if need to */
4349 code = CheckVldbRWBK(&entry, &mod);
4350 if (code) ERROR_EXIT(code);
4351 if (mod) modified++;
4355 else if (volumeinfo->type == BACKVOL) { /* A BK volume */
4361 /* Check existence of RW and BK volumes */
4362 code = CheckVldbRWBK(&entry, &mod);
4363 if (code) ERROR_EXIT(code);
4364 if (mod) modified++;
4366 idx = Lp_GetRwIndex(&entry);
4367 if (idx == -1) { /* RW index not found in the VLDB entry */
4368 idx = entry.nServers; /* Put it into next index */
4371 } else { /* RW index found in the VLDB entry */
4372 /* Verify if this volume's location matches where the VLDB says it is */
4373 if (!Lp_Match(aserver, apart, &entry)) {
4374 /* VLDB says RW and/or BK is elsewhere - report this BK volume orphaned */
4376 MapPartIdIntoName(apart, pname);
4377 fprintf(STDERR,"*** Warning: Orphaned BK volume %lu exists on %s %s\n",
4378 (unsigned long) volumeinfo->volid,
4379 hostutil_GetNameByINet(aserver), pname);
4380 MapPartIdIntoName(entry.serverPartition[idx], pname);
4381 fprintf(STDERR," VLDB reports its RW/BK volume %lu exists on %s %s\n",
4382 (unsigned long) rwvolid,
4383 hostutil_GetNameByINet(entry.serverNumber[idx]), pname);
4386 if (volumeinfo->volid != entry.volumeId[BACKVOL]) {
4387 if (!(entry.flags & BACK_EXISTS)) {
4390 else if (volumeinfo->volid > entry.volumeId[BACKVOL]) {
4394 MapPartIdIntoName(entry.serverPartition[idx], pname);
4395 fprintf(STDERR,"*** Warning: Orphaned BK volume %u exists on %s %s\n",
4396 entry.volumeId[BACKVOL], hostutil_GetNameByINet(aserver), pname);
4397 fprintf(STDERR," VLDB reports its BK volume ID is %lu\n",
4398 (unsigned long) volumeinfo->volid);
4402 MapPartIdIntoName(entry.serverPartition[idx], pname);
4403 fprintf(STDERR,"*** Warning: Orphaned BK volume %lu exists on %s %s\n",
4404 (unsigned long) volumeinfo->volid,
4405 hostutil_GetNameByINet(aserver), pname);
4406 fprintf(STDERR," VLDB reports its BK volume ID is %u\n",
4407 entry.volumeId[BACKVOL]);
4411 else if (!entry.volumeId[BACKVOL]) {
4418 entry.flags |= BACK_EXISTS;
4419 entry.volumeId[RWVOL] = rwvolid;
4420 entry.volumeId[BACKVOL] = volumeinfo->volid;
4422 entry.serverNumber[idx] = aserver;
4423 entry.serverPartition[idx] = apart;
4424 entry.serverFlags[idx] = ITSRWVOL;
4430 else if (volumeinfo->type == ROVOL) { /* A RO volume */
4431 if (volumeinfo->volid == entry.volumeId[ROVOL]) {
4432 /* This is a quick check to see if the RO entry exists in the
4433 * VLDB so we avoid the CheckVldbRO() call (which checks if each
4434 * RO volume listed in the VLDB exists).
4436 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
4438 idx = entry.nServers;
4442 if (!(entry.flags & RO_EXISTS)) {
4447 /* Before we correct the VLDB entry, make sure all the
4448 * ROs listed in the VLDB exist.
4450 code = CheckVldbRO(&entry, &mod);
4451 if (code) ERROR_EXIT(code);
4452 if (mod) modified++;
4454 if (!(entry.flags & RO_EXISTS)) {
4455 /* No RO exists in the VLDB entry - add this one */
4456 idx = entry.nServers;
4460 else if (volumeinfo->volid > entry.volumeId[ROVOL]) {
4461 /* The volume headers's RO ID does not match that in the VLDB entry,
4462 * and the vol hdr's ID is greater (implies more recent). So delete
4463 * all the RO volumes listed in VLDB entry and add this volume.
4465 for (j=0; j<entry.nServers; j++) {
4466 if (entry.serverFlags[j] & ITSROVOL) {
4467 /* Verify this volume exists and print message we are orphaning it */
4469 MapPartIdIntoName(apart, pname);
4470 fprintf(STDERR,"*** Warning: Orphaned RO volume %u exists on %s %s\n",
4471 entry.volumeId[ROVOL],
4472 hostutil_GetNameByINet(entry.serverNumber[j]), pname);
4473 fprintf(STDERR," VLDB reports its RO volume ID is %lu\n",
4474 (unsigned long) volumeinfo->volid);
4477 Lp_SetRWValue(entry, entry.serverNumber[idx],
4478 entry.serverPartition[idx], 0L, 0L);
4485 idx = entry.nServers;
4489 else if (volumeinfo->volid < entry.volumeId[ROVOL]) {
4490 /* The volume headers's RO ID does not match that in the VLDB entry,
4491 * and the vol hdr's ID is lower (implies its older). So orphan it.
4494 MapPartIdIntoName(apart, pname);
4495 fprintf(STDERR,"*** Warning: Orphaned RO volume %lu exists on %s %s\n",
4496 (unsigned long) volumeinfo->volid,
4497 hostutil_GetNameByINet(aserver), pname);
4498 fprintf(STDERR," VLDB reports its RO volume ID is %u\n",
4499 entry.volumeId[ROVOL]);
4503 /* The RO volume ID in the volume header match that in the VLDB entry,
4504 * and there exist RO volumes in the VLDB entry. See if any of them
4505 * are this one. If not, then we add it.
4507 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
4509 idx = entry.nServers;
4517 entry.flags |= RO_EXISTS;
4518 entry.volumeId[RWVOL] = rwvolid;
4519 entry.volumeId[ROVOL] = volumeinfo->volid;
4521 entry.serverNumber[idx] = aserver;
4522 entry.serverPartition[idx] = apart;
4523 entry.serverFlags[idx] = ITSROVOL;
4529 /* Remember largest volume id */
4530 if (entry.volumeId[ROVOL] > *maxvolid) *maxvolid = entry.volumeId[ROVOL];
4531 if (entry.volumeId[BACKVOL] > *maxvolid) *maxvolid = entry.volumeId[BACKVOL];
4532 if (entry.volumeId[RWVOL] > *maxvolid) *maxvolid = entry.volumeId[RWVOL];
4535 MapNetworkToHost(&entry, &storeEntry);
4538 code = VLDB_CreateEntry(&storeEntry);
4540 fprintf(STDOUT,"Could not create a VLDB entry for the volume %lu\n",
4541 (unsigned long) rwvolid);
4546 if (pass == 1) goto retry;
4547 code = VLDB_ReplaceEntry(rwvolid, RWVOL, &storeEntry,
4548 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4550 fprintf(STDERR,"Could not update entry for %lu\n",
4551 (unsigned long) rwvolid);
4555 if (modentry) *modentry = modified;
4556 } else if (pass == 2) {
4557 code = ubik_Call(VL_ReleaseLock,cstruct, 0, rwvolid, RWVOL,
4558 LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4560 PrintError("Could not unlock VLDB entry ", code);
4565 fprintf(STDOUT,"-- status after --\n");
4567 EnumerateEntry(&entry);
4569 fprintf(STDOUT,"\n**no change**\n");
4573 VPRINT("\n_______________________________\n");
4577 int sortVolumes(const void *a, const void *b)
4579 volintInfo *v1 = (volintInfo *)a;
4580 volintInfo *v2 = (volintInfo *)b;
4581 afs_int32 rwvolid1, rwvolid2;
4583 rwvolid1 = ((v1->type == RWVOL) ? v1->volid : v1->parentID);
4584 rwvolid2 = ((v2->type == RWVOL) ? v2->volid : v2->parentID);
4586 if (rwvolid1 > rwvolid2) return -1; /* lower RW id goes first */
4587 if (rwvolid1 < rwvolid2) return 1;
4589 if (v1->type == RWVOL) return -1; /* RW vols go first */
4590 if (v2->type == RWVOL) return 1;
4592 if ((v1->type == BACKVOL) && (v2->type == ROVOL )) return -1; /* BK vols next */
4593 if ((v1->type == ROVOL ) && (v2->type == BACKVOL)) return 1;
4595 if (v1->volid < v2->volid) return 1; /* larger volids first */
4596 if (v1->volid > v2->volid) return -1;
4601 * Synchronise <aserver> <apart>(if flags = 1) <avolid>.
4602 * Synchronize an individual volume against a sever and partition.
4603 * Checks the VLDB entry (similar to syncserv) as well as checks
4604 * if the volume exists on specified servers (similar to syncvldb).
4606 int UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
4608 struct rx_connection *aconn = 0;
4609 afs_int32 j, k, code, vcode, error = 0;
4610 afs_int32 tverbose, mod, modified = 0;
4611 struct nvldbentry vldbentry;
4612 afs_int32 volumeid = 0;
4613 volEntries volumeInfo;
4614 struct partList PartList;
4616 afs_int32 maxvolid = 0;
4618 volumeInfo.volEntries_val = (volintInfo *)0;
4619 volumeInfo.volEntries_len = 0;
4621 if (!aserver && flags) {
4622 /* fprintf(STDERR,"Partition option requires a server option\n"); */
4626 /* Turn verbose logging off and do our own verbose logging */
4630 /* Read the VLDB entry */
4631 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
4632 if (vcode && (vcode != VL_NOENT)) {
4633 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4635 } else if (!vcode) {
4636 MapHostToNetwork(&vldbentry);
4640 fprintf(STDOUT,"Processing VLDB entry %s ...\n", avolname);
4641 fprintf(STDOUT,"_______________________________\n");
4642 fprintf(STDOUT,"\n-- status before -- \n");
4644 fprintf(STDOUT,"\n**does not exist**\n");
4646 if ((vldbentry.flags & RW_EXISTS) ||
4647 (vldbentry.flags & RO_EXISTS) ||
4648 (vldbentry.flags & BACK_EXISTS))
4649 EnumerateEntry(&vldbentry);
4651 fprintf(STDOUT,"\n");
4654 /* Verify that all of the VLDB entries exist on the repective servers
4655 * and partitions (this does not require that avolname be a volume ID).
4656 * Equivalent to a syncserv.
4659 code = CheckVldb(&vldbentry, &mod);
4661 fprintf(STDERR,"Could not process VLDB entry for volume %s\n", vldbentry.name);
4664 if (mod) modified++;
4667 /* If aserver is given, we will search for the desired volume on it */
4669 /* Generate array of partitions on the server that we will check */
4671 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4673 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4677 PartList.partId[0] = apart;
4681 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
4683 /* If a volume ID were given, search for it on each partition */
4684 if ((volumeid = atol(avolname))) {
4685 for (j=0; j<pcnt; j++) {
4686 code = AFSVolListOneVolume(aconn, PartList.partId[j], volumeid, &volumeInfo);
4688 if (code != ENODEV) {
4689 fprintf(STDERR,"Could not query server\n");
4693 /* Found one, sync it with VLDB entry */
4694 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4695 PartList.partId[j], &mod, &maxvolid);
4696 if (code) ERROR_EXIT(code);
4697 if (mod) modified++;
4700 if (volumeInfo.volEntries_val)
4701 free(volumeInfo.volEntries_val);
4702 volumeInfo.volEntries_val = (volintInfo *)0;
4703 volumeInfo.volEntries_len = 0;
4707 /* Check to see if the RW, BK, and RO IDs exist on any
4708 * partitions. We get the volume IDs from the VLDB.
4710 rv = 1; /* Read the VLDB entry ? */
4711 for (j=0; j<MAXTYPES; j++) { /* for RW, RO, and BK IDs */
4713 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
4715 if (vcode == VL_NOENT) break;
4716 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4722 if (vldbentry.volumeId[j] == 0) continue;
4724 for (k=0; k<pcnt; k++) { /* For each partition */
4725 volumeInfo.volEntries_val = (volintInfo *)0;
4726 volumeInfo.volEntries_len = 0;
4727 code = AFSVolListOneVolume(aconn, PartList.partId[k],
4728 vldbentry.volumeId[j], &volumeInfo);
4730 if (code != ENODEV) {
4731 fprintf(STDERR,"Could not query server\n");
4735 /* Found one, sync it with VLDB entry */
4736 code = CheckVolume(volumeInfo.volEntries_val, aserver,
4737 PartList.partId[k], &mod, &maxvolid);
4738 if (code) ERROR_EXIT(code);
4739 if (mod) modified++, rv++;
4742 if (volumeInfo.volEntries_val)
4743 free(volumeInfo.volEntries_val);
4744 volumeInfo.volEntries_val = (volintInfo *)0;
4745 volumeInfo.volEntries_len = 0;
4748 } /* if (aserver) */
4750 /* If verbose output, print a summary of what changed */
4752 fprintf(STDOUT,"-- status after --\n");
4753 code = VLDB_GetEntryByName(avolname, &vldbentry);
4754 if (code && (code != VL_NOENT)) {
4755 fprintf(STDERR,"Could not access the VLDB for volume %s\n", avolname);
4758 if (modified && (code == VL_NOENT)) {
4759 fprintf(STDOUT,"\n**entry deleted**\n");
4760 } else if (modified) {
4761 EnumerateEntry(&vldbentry);
4763 fprintf(STDOUT,"\n**no change**\n");
4765 fprintf(STDOUT,"\n_______________________________\n");
4769 /* Now check if the maxvolid is larger than that stored in the VLDB */
4771 afs_int32 maxvldbid = 0;
4772 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4774 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4775 if (!error) error = code;
4776 } else if (maxvolid > maxvldbid) {
4778 id = maxvolid - maxvldbid + 1;
4779 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4781 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4782 if (!error) error = code;
4789 if (error) fprintf(STDOUT,"...error encountered");
4790 else fprintf(STDOUT,"...done entry\n");
4792 if (aconn) rx_DestroyConnection(aconn);
4793 if (volumeInfo.volEntries_val) free(volumeInfo.volEntries_val);
4795 PrintError("",error);
4800 * Synchronise vldb with the file server <aserver> and,
4801 * optionally, <apart>.
4803 int UV_SyncVldb(afs_int32 aserver, afs_int32 apart, int flags, int force)
4805 struct rx_connection *aconn;
4806 afs_int32 code, error=0;
4808 volEntries volumeInfo;
4809 struct partList PartList;
4813 afs_int32 failures = 0, modifications = 0, tentries = 0;
4815 afs_uint32 maxvolid = 0;
4817 volumeInfo.volEntries_val = (volintInfo *)0;
4818 volumeInfo.volEntries_len = 0;
4820 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4822 /* Generate array of partitions to check */
4824 code = UV_ListPartitions(aserver, &PartList, &pcnt);
4826 fprintf(STDERR,"Could not fetch the list of partitions from the server\n");
4830 PartList.partId[0] = apart;
4834 VPRINT("Processing volume entries ...\n");
4836 /* Step through the array of partitions */
4837 for (i = 0; i < pcnt; i++) {
4838 apart = PartList.partId[i];
4839 MapPartIdIntoName(apart, pname);
4841 volumeInfo.volEntries_val = (volintInfo *)0;
4842 volumeInfo.volEntries_len = 0;
4843 code = AFSVolListVolumes(aconn, apart, 1, &volumeInfo);
4845 fprintf(STDERR,"Could not fetch the list of volumes from the server\n");
4849 /* May want to sort the entries: RW, BK (high to low), RO (high to low) */
4850 qsort((char *)volumeInfo.volEntries_val, volumeInfo.volEntries_len,
4851 sizeof(volintInfo), sortVolumes);
4854 for (vi=volumeInfo.volEntries_val, j=0; j < volumeInfo.volEntries_len; j++, vi++) {
4861 fprintf(STDOUT,"Processing volume entry %d: %s (%lu) on server %s %s...\n",
4862 j+1, vi->name, (unsigned long) vi->volid,
4863 hostutil_GetNameByINet(aserver), pname);
4867 code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
4869 PrintError("",code);
4873 else if (modified) {
4879 fprintf(STDOUT,"...error encountered\n\n");
4881 fprintf(STDOUT,"...done entry %d\n\n", j+1);
4887 fprintf(STDERR,"Could not process entries on server %s partition %s\n",
4888 hostutil_GetNameByINet(aserver), pname);
4890 if (volumeInfo.volEntries_val) {
4891 free(volumeInfo.volEntries_val);
4892 volumeInfo.volEntries_val = 0;
4895 }/* thru all partitions */
4897 VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n",
4898 tentries, failures, modifications);
4901 /* Now check if the maxvolid is larger than that stored in the VLDB */
4903 afs_uint32 maxvldbid = 0;
4904 code = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 0, &maxvldbid);
4906 fprintf(STDERR, "Could not get the highest allocated volume id from the VLDB\n");
4907 if (!error) error = code;
4908 } else if (maxvolid > maxvldbid) {
4910 id = maxvolid - maxvldbid + 1;
4911 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, id, &nid);
4913 fprintf(STDERR,"Error in increasing highest allocated volume id in VLDB\n");
4914 if (!error) error = code;
4919 if (aconn) rx_DestroyConnection(aconn);
4920 if (volumeInfo.volEntries_val)
4921 free(volumeInfo.volEntries_val);
4922 PrintError("",error);
4927 * Determine if a volume exists on a server and partition.
4928 * Try creating a transaction on the volume. If we can,
4929 * the volume exists, if not, then return the error code.
4930 * Some error codes mean the volume is unavailable but
4931 * still exists - so we catch these error codes.
4933 afs_int32 VolumeExists(afs_int32 server, afs_int32 partition, afs_int32 volumeid)
4935 struct rx_connection *conn=(struct rx_connection *)0;
4936 afs_int32 code = -1;
4937 volEntries volumeInfo;
4939 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
4941 volumeInfo.volEntries_val = (volintInfo *)0;
4942 volumeInfo.volEntries_len = 0;
4943 code = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
4944 if (volumeInfo.volEntries_val)
4945 free(volumeInfo.volEntries_val);
4946 if (code == VOLSERILLEGAL_PARTITION)
4948 rx_DestroyConnection(conn);
4956 afs_int32 CheckVldbRWBK(struct nvldbentry *entry, afs_int32 *modified)
4960 afs_int32 code, error = 0;
4963 if (modified) *modified = 0;
4964 idx = Lp_GetRwIndex(entry);
4966 /* Check to see if the RW volume exists and set the RW_EXISTS
4969 if (idx == -1) { /* Did not find a RW entry */
4970 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4971 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4975 code = VolumeExists(entry->serverNumber[idx],
4976 entry->serverPartition[idx],
4977 entry->volumeId[RWVOL]);
4978 if (code == 0) { /* RW volume exists */
4979 if (!(entry->flags & RW_EXISTS)) { /* ... yet entry says RW does not exist */
4980 entry->flags |= RW_EXISTS; /* ... so say RW does exist */
4984 else if (code == ENODEV) { /* RW volume does not exist */
4985 if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
4986 entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
4991 /* If VLDB says it didn't exist, then ignore error */
4992 if (entry->flags & RW_EXISTS) {
4993 MapPartIdIntoName(entry->serverPartition[idx], pname);
4994 fprintf(STDERR,"Transaction call failed for RW volume %u on server %s %s\n",
4995 entry->volumeId[RWVOL],
4996 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
5002 /* Check to see if the BK volume exists and set the BACK_EXISTS
5003 * flag accordingly. idx already ponts to the RW entry.
5005 if (idx == -1) { /* Did not find a RW entry */
5006 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
5007 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
5011 else { /* Found a RW entry */
5012 code = VolumeExists(entry->serverNumber[idx],
5013 entry->serverPartition[idx],
5014 entry->volumeId[BACKVOL]);
5015 if (code == 0) { /* BK volume exists */
5016 if (!(entry->flags & BACK_EXISTS)) { /* ... yet entry says BK does not exist */
5017 entry->flags |= BACK_EXISTS; /* ... so say BK does exist */
5021 else if (code == ENODEV) { /* BK volume does not exist */
5022 if (entry->flags & BACK_EXISTS) { /* ... yet entry says BK exists */
5023 entry->flags &= ~BACK_EXISTS; /* ... so say BK does not exist */
5028 /* If VLDB says it didn't exist, then ignore error */
5029 if (entry->flags & BACK_EXISTS) {
5030 MapPartIdIntoName(entry->serverPartition[idx], pname);
5031 fprintf(STDERR,"Transaction call failed for BK volume %u on server %s %s\n",
5032 entry->volumeId[BACKVOL],
5033 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
5039 /* If there is an idx but the BK and RW volumes no
5040 * longer exist, then remove the RW entry.
5042 if ((idx != -1) && !(entry->flags & RW_EXISTS) &&
5043 !(entry->flags & BACK_EXISTS)) {
5044 Lp_SetRWValue(entry, entry->serverNumber[idx],
5045 entry->serverPartition[idx], 0L, 0L);
5051 if (modified) *modified = modentry;
5055 int CheckVldbRO(struct nvldbentry *entry, afs_int32 *modified)
5058 int foundro = 0, modentry = 0;
5059 afs_int32 code, error = 0;
5062 if (modified) *modified = 0;
5064 /* Check to see if the RO volumes exist and set the RO_EXISTS
5067 for (idx=0; idx < entry->nServers; idx++) {
5068 if (!(entry->serverFlags[idx] & ITSROVOL)) {
5069 continue; /* not a RO */
5072 code = VolumeExists(entry->serverNumber[idx],
5073 entry->serverPartition[idx],
5074 entry->volumeId[ROVOL]);
5075 if (code == 0) { /* RO volume exists */
5078 else if (code == ENODEV) { /* RW volume does not exist */
5079 Lp_SetROValue(entry, entry->serverNumber[idx],
5080 entry->serverPartition[idx], 0L, 0L);
5086 MapPartIdIntoName(entry->serverPartition[idx], pname);
5087 fprintf(STDERR,"Transaction call failed for RO %u on server %s %s\n",
5088 entry->volumeId[ROVOL],
5089 hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
5094 if (foundro) { /* A RO volume exists */
5095 if (!(entry->flags & RO_EXISTS)) { /* ... yet entry says RW does not exist */
5096 entry->flags |= RO_EXISTS; /* ... so say RW does exist */
5099 } else { /* A RO volume does not exist */
5100 if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
5101 entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
5107 if (modified) *modified = modentry;
5112 * Ensure that <entry> matches with the info on file servers
5114 afs_int32 CheckVldb(struct nvldbentry *entry, afs_int32 *modified)
5116 afs_int32 code, error=0;
5117 struct nvldbentry storeEntry;
5118 int islocked=0, mod, modentry, delentry=0;
5121 if (modified) *modified = 0;
5123 fprintf(STDOUT,"_______________________________\n");
5124 fprintf(STDOUT,"\n-- status before -- \n");
5125 if ((entry->flags & RW_EXISTS) ||
5126 (entry->flags & RO_EXISTS) ||
5127 (entry->flags & BACK_EXISTS))
5128 EnumerateEntry(entry);
5129 fprintf(STDOUT,"\n");
5132 if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
5133 fprintf(STDERR,"Volume name %s exceeds limit of %d characters\n",
5134 entry->name, VOLSER_OLDMAXVOLNAME-10);
5138 /* Check to see if the VLDB is ok without locking it (pass 1).
5139 * If it will change, then lock the VLDB entry, read it again,
5140 * then make the changes to it (pass 2).
5143 code = ubik_Call(VL_SetLock,cstruct, 0, entry->volumeId[RWVOL], RWVOL, VLOP_DELETE);
5145 fprintf(STDERR, "Could not lock VLDB entry for %u \n",entry->volumeId[RWVOL] );
5150 code = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, entry);
5152 fprintf(STDERR,"Could not read VLDB entry for volume %s\n", entry->name);
5156 MapHostToNetwork(entry);
5162 /* Check if the RW and BK entries are ok */
5163 code = CheckVldbRWBK(entry, &mod);
5164 if (code) ERROR_EXIT(code);
5165 if (mod && (pass == 1)) goto retry;
5166 if (mod) modentry++;
5168 /* Check if the RO volumes entries are ok */
5169 code = CheckVldbRO(entry, &mod);
5170 if (code) ERROR_EXIT(code);
5171 if (mod && (pass == 1)) goto retry;
5172 if (mod) modentry++;
5174 /* The VLDB entry has been updated. If it as been modified, then
5175 * write the entry back out the the VLDB.
5178 if (pass == 1) goto retry;
5180 if (!(entry->flags & RW_EXISTS) &&
5181 !(entry->flags & BACK_EXISTS) &&
5182 !(entry->flags & RO_EXISTS)) {
5183 /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
5184 code = ubik_Call(VL_DeleteEntry, cstruct, 0, entry->volumeId[RWVOL], RWVOL);
5186 fprintf(STDERR,"Could not delete VLDB entry for volume %u \n",
5187 entry->volumeId[RWVOL]);
5193 /* Replace old entry with our new one */
5194 MapNetworkToHost(entry,&storeEntry);
5195 code = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry,
5196 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
5198 fprintf(STDERR,"Could not update VLDB entry for volume %u\n",
5199 entry->volumeId[RWVOL] );
5203 if (modified) *modified = 1;
5208 fprintf(STDOUT,"-- status after --\n");
5210 fprintf(STDOUT,"\n**entry deleted**\n");
5212 EnumerateEntry(entry);
5214 fprintf(STDOUT,"\n**no change**\n");
5218 VPRINT("\n_______________________________\n");
5221 code = ubik_Call(VL_ReleaseLock, cstruct, 0, entry->volumeId[RWVOL], RWVOL,
5222 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
5224 fprintf(STDERR,"Could not release lock on VLDB entry for volume %u\n",
5225 entry->volumeId[RWVOL]);
5226 if (!error) error = code;
5233 * Synchronise <aserver> <apart>(if flags = 1) with the VLDB.
5235 int UV_SyncServer(afs_int32 aserver, afs_int32 apart, int flags, int force)
5237 struct rx_connection *aconn;
5238 afs_int32 code, error = 0;
5239 afs_int32 nentries, tentries=0;
5240 struct VldbListByAttributes attributes;
5241 nbulkentries arrayEntries;
5242 afs_int32 failures=0, modified, modifications=0;
5243 struct nvldbentry *vlentry;
5244 afs_int32 si, nsi, j;
5246 aconn = UV_Bind(aserver,AFSCONF_VOLUMEPORT);
5248 /* Set up attributes to search VLDB */
5249 attributes.server = ntohl(aserver);
5250 attributes.Mask = VLLIST_SERVER;
5252 attributes.partition = apart;
5253 attributes.Mask |= VLLIST_PARTITION;
5256 VPRINT("Processing VLDB entries ...\n");
5258 /* While we need to collect more VLDB entries */
5259 for (si=0; si != -1; si=nsi) {
5260 memset(&arrayEntries, 0, sizeof(arrayEntries));
5262 /* Collect set of VLDB entries */
5263 code = VLDB_ListAttributesN2(&attributes, 0, si,
5264 &nentries, &arrayEntries, &nsi);
5265 if (code == RXGEN_OPCODE) {
5266 code = VLDB_ListAttributes(&attributes, &nentries, &arrayEntries);
5270 fprintf(STDERR,"Could not access the VLDB for attributes\n");
5273 tentries += nentries;
5275 for (j=0; j<nentries; j++) {
5276 vlentry = &arrayEntries.nbulkentries_val[j];
5277 MapHostToNetwork(vlentry);
5279 VPRINT1("Processing VLDB entry %d ...\n", j+1);
5281 code = CheckVldb(vlentry, &modified);
5283 PrintError("",code);
5284 fprintf(STDERR,"Could not process VLDB entry for volume %s\n",
5287 } else if (modified) {
5293 fprintf(STDOUT,"...error encountered\n\n");
5295 fprintf(STDOUT,"...done entry %d\n\n", j+1);
5300 if (arrayEntries.nbulkentries_val) {
5301 free(arrayEntries.nbulkentries_val);
5302 arrayEntries.nbulkentries_val = 0;
5306 VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n",
5307 tentries, failures, modifications);
5311 rx_DestroyConnection(aconn);
5312 if (arrayEntries.nbulkentries_val)
5313 free(arrayEntries.nbulkentries_val);
5316 error = VOLSERFAILEDOP;
5320 /*rename volume <oldname> to <newname>, changing the names of the related
5321 *readonly and backup volumes. This operation is also idempotent.
5322 *salvager is capable of recovering from rename operation stopping halfway.
5323 *to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
5324 int UV_RenameVolume(struct nvldbentry *entry, char oldname[], char newname[])
5326 struct nvldbentry storeEntry;
5327 afs_int32 vcode,code,rcode,error;
5329 char nameBuffer[256];
5331 struct rx_connection *aconn;
5335 aconn = (struct rx_connection *)0;
5339 vcode = ubik_Call(VL_SetLock,cstruct, 0,entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE);/*last param is dummy*/
5341 fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n",entry->volumeId[RWVOL] );
5346 strncpy(entry->name,newname,VOLSER_OLDMAXVOLNAME);
5347 MapNetworkToHost(entry,&storeEntry);
5348 vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL],RWVOL, &storeEntry,0 );
5350 fprintf(STDERR,"Could not update VLDB entry for %u\n",entry->volumeId[RWVOL]);
5354 VPRINT1("Recorded the new name %s in VLDB\n",newname);
5355 /*at this stage the intent to rename is recorded in the vldb, as far as the vldb
5356 is concerned, oldname is lost */
5357 if(entry->flags & RW_EXISTS) {
5358 index = Lp_GetRwIndex(entry);
5359 if(index == -1){ /* there is a serious discrepancy */
5360 fprintf(STDERR,"There is a serious discrepancy in VLDB entry for volume %u\n",entry->volumeId[RWVOL]);
5361 fprintf(STDERR,"try building VLDB from scratch\n");
5362 error = VOLSERVLDB_ERROR;
5365 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
5366 code = AFSVolTransCreate(aconn,entry->volumeId[RWVOL],entry->serverPartition[index], ITOffline, &tid);
5367 if(code) { /*volume doesnot exist */
5368 fprintf(STDERR,"Could not start transaction on the rw volume %u\n",entry->volumeId[RWVOL]);
5372 else {/*volume exists, process it */
5374 code = AFSVolSetIdsTypes(aconn, tid, newname,RWVOL, entry->volumeId[RWVOL],entry->volumeId[ROVOL],entry->volumeId[BACKVOL]);
5376 VPRINT2("Renamed rw volume %s to %s\n",oldname,newname);
5377 code = AFSVolEndTrans(aconn, tid, &rcode);
5380 fprintf(STDERR,"Could not end transaction on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
5386 fprintf(STDERR,"Could not set parameters on volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
5391 if(aconn) rx_DestroyConnection(aconn);
5392 aconn = (struct rx_connection *)0;
5393 } /*end rw volume processing */
5395 if(entry->flags & BACK_EXISTS) {/*process the backup volume */
5396 index = Lp_GetRwIndex(entry);
5397 if(index == -1){ /* there is a serious discrepancy */
5398 fprintf(STDERR,"There is a serious discrepancy in the VLDB entry for the backup volume %u\n",entry->volumeId[BACKVOL]);
5399 fprintf(STDERR,"try building VLDB from scratch\n");
5400 error = VOLSERVLDB_ERROR;
5403 aconn = UV_Bind(entry->serverNumber[index],AFSCONF_VOLUMEPORT);
5404 code = AFSVolTransCreate(aconn,entry->volumeId[BACKVOL],entry->serverPartition[index], ITOffline, &tid);
5405 if(code) { /*volume doesnot exist */
5406 fprintf(STDERR,"Could not start transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
5410 else {/*volume exists, process it */
5411 if(strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)){
5412 fprintf(STDERR,"Volume name %s.backup exceeds the limit of %u characters\n",newname,VOLSER_OLDMAXVOLNAME);
5416 strcpy(nameBuffer,newname);
5417 strcat(nameBuffer,".backup");
5419 code = AFSVolSetIdsTypes(aconn, tid,nameBuffer ,BACKVOL, entry->volumeId[RWVOL],0,0);
5421 VPRINT1("Renamed backup volume to %s \n",nameBuffer);
5422 code = AFSVolEndTrans(aconn, tid, &rcode);
5425 fprintf(STDERR,"Could not end transaction on the backup volume %u\n",entry->volumeId[BACKVOL]);
5431 fprintf(STDERR,"Could not set parameters on the backup volume %u\n",entry->volumeId[BACKVOL]);
5436 } /* end backup processing */
5437 if(aconn) rx_DestroyConnection(aconn);
5438 aconn = (struct rx_connection *)0;
5439 if(entry->flags & RO_EXISTS){ /*process the ro volumes */
5440 for(i = 0; i < entry->nServers; i++){
5441 if(entry->serverFlags[i] & ITSROVOL) {
5442 aconn = UV_Bind(entry->serverNumber[i],AFSCONF_VOLUMEPORT);
5443 code = AFSVolTransCreate(aconn,entry->volumeId[ROVOL],entry->serverPartition[i], ITOffline, &tid);
5444 if(code) { /*volume doesnot exist */
5445 fprintf(STDERR,"Could not start transaction on the ro volume %u\n",entry->volumeId[ROVOL]);
5449 else {/*volume exists, process it */
5450 strcpy(nameBuffer,newname);
5451 strcat(nameBuffer,".readonly");
5452 if(strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)){
5453 fprintf(STDERR,"Volume name %s exceeds the limit of %u characters\n",nameBuffer,VOLSER_OLDMAXVOLNAME);
5457 code = AFSVolSetIdsTypes(aconn, tid, nameBuffer,ROVOL, entry->volumeId[RWVOL],0,0);
5459 VPRINT2("Renamed RO volume %s on host %s\n",
5461 hostutil_GetNameByINet(entry->serverNumber[i]));
5462 code = AFSVolEndTrans(aconn, tid, &rcode);
5465 fprintf(STDERR,"Could not end transaction on volume %u\n",entry->volumeId[ROVOL]);
5471 fprintf(STDERR,"Could not set parameters on the ro volume %u\n",entry->volumeId[ROVOL]);
5476 if(aconn) rx_DestroyConnection(aconn);
5477 aconn = (struct rx_connection *)0;
5483 vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,entry->volumeId[RWVOL] , RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
5485 fprintf(STDERR,"Could not unlock the VLDB entry for the volume %s %u\n",entry->name,entry->volumeId[RWVOL]);
5486 if(!error) error = vcode;
5490 code = AFSVolEndTrans(aconn, tid, &rcode);
5491 if(!code) code = rcode;
5493 fprintf(STDERR,"Failed to end transaction on a volume \n");
5494 if(!error) error = code;
5497 if(aconn) rx_DestroyConnection(aconn);
5498 PrintError("",error);
5503 /*report on all the active transactions on volser */
5504 int UV_VolserStatus(afs_int32 server, transDebugInfo **rpntr, afs_int32 *rcount)
5506 struct rx_connection *aconn;
5507 transDebugEntries transInfo;
5510 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5511 transInfo.transDebugEntries_val = (transDebugInfo *) 0;
5512 transInfo.transDebugEntries_len = 0;
5513 code = AFSVolMonitor(aconn,&transInfo);
5515 fprintf(STDERR,"Could not access status information about the server\n");
5516 PrintError("",code);
5517 if (transInfo.transDebugEntries_val) free(transInfo.transDebugEntries_val);
5518 if(aconn) rx_DestroyConnection(aconn);
5522 *rcount = transInfo.transDebugEntries_len;
5523 *rpntr = transInfo.transDebugEntries_val;
5524 if(aconn) rx_DestroyConnection(aconn);
5531 /*delete the volume without interacting with the vldb */
5532 int UV_VolumeZap(afs_int32 server, afs_int32 part, afs_int32 volid)
5534 afs_int32 rcode,ttid,error,code;
5535 struct rx_connection *aconn;
5541 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5542 code = AFSVolTransCreate(aconn, volid, part, ITOffline, &ttid);
5544 fprintf(STDERR,"Could not start transaction on volume %lu\n",
5545 (unsigned long) volid);
5549 code = AFSVolDeleteVolume(aconn, ttid);
5551 fprintf(STDERR,"Could not delete volume %lu\n",
5552 (unsigned long) volid);
5556 code = AFSVolEndTrans(aconn, ttid, &rcode);
5558 if(!code) code = rcode;
5560 fprintf(STDERR,"Could not end transaction on volume %lu\n",
5561 (unsigned long) volid);
5567 code = AFSVolEndTrans(aconn,ttid,&rcode);
5568 if(!code) code = rcode;
5569 if(!error) error = code;
5571 PrintError("",error);
5572 if(aconn) rx_DestroyConnection(aconn);
5576 int UV_SetVolume(afs_int32 server, afs_int32 partition, afs_int32 volid, afs_int32 transflag, afs_int32 setflag, int sleeptime)
5578 struct rx_connection *conn = 0;
5580 afs_int32 code, error=0, rcode;
5582 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5584 fprintf(STDERR, "SetVolumeStatus: Bind Failed");
5588 code = AFSVolTransCreate(conn, volid, partition, transflag, &tid);
5590 fprintf(STDERR, "SetVolumeStatus: TransCreate Failed\n");
5594 code = AFSVolSetFlags(conn, tid, setflag);
5596 fprintf(STDERR, "SetVolumeStatus: SetFlags Failed\n");
5601 #ifdef AFS_PTHREAD_ENV
5604 IOMGR_Sleep(sleeptime);
5611 code = AFSVolEndTrans(conn, tid, &rcode);
5612 if (code || rcode) {
5613 fprintf(STDERR, "SetVolumeStatus: EndTrans Failed\n");
5614 if (!error) error = (code ? code : rcode);
5618 if (conn) rx_DestroyConnection(conn);
5622 int UV_SetVolumeInfo(afs_int32 server, afs_int32 partition, afs_int32 volid, volintInfo *infop)
5624 struct rx_connection *conn = 0;
5626 afs_int32 code, error=0, rcode;
5628 conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
5630 fprintf(STDERR, "SetVolumeInfo: Bind Failed");
5634 code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
5636 fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
5640 code = AFSVolSetInfo(conn, tid, infop);
5642 fprintf(STDERR, "SetVolumeInfo: SetInfo Failed\n");
5649 code = AFSVolEndTrans(conn, tid, &rcode);
5650 if (code || rcode) {
5651 fprintf(STDERR, "SetVolumeInfo: EndTrans Failed\n");
5652 if (!error) error = (code ? code : rcode);
5656 if (conn) rx_DestroyConnection(conn);
5660 int UV_GetSize(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
5661 afs_int32 fromdate, struct volintSize *vol_size)
5663 struct rx_connection *aconn = (struct rx_connection *)0;
5664 afs_int32 tid=0, rcode=0;
5665 afs_int32 code, error = 0;
5668 /* get connections to the servers */
5669 aconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
5671 VPRINT1("Starting transaction on volume %u...", afromvol);
5672 code = AFSVolTransCreate(aconn, afromvol, afrompart, ITBusy, &tid);
5673 EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be measured\n", afromvol);
5676 VPRINT1("Getting size of volume on volume %u...", afromvol);
5677 code = AFSVolGetSize(aconn, tid, fromdate, vol_size);
5678 EGOTO(error_exit, code, "Could not start the measurement process \n");
5683 VPRINT1("Ending transaction on volume %u...", afromvol);
5684 code = AFSVolEndTrans(aconn, tid, &rcode);
5685 if (code || rcode) {
5686 fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol);
5687 fprintf(STDERR,"error codes: %d and %d\n", code, rcode);
5688 if (!error) error = (code?code:rcode);
5693 rx_DestroyConnection(aconn);
5695 PrintError("", error);
5699 /*maps the host addresses in <old > (present in network byte order) to
5700 that in< new> (present in host byte order )*/
5701 void MapNetworkToHost(struct nvldbentry *old, struct nvldbentry *new)
5705 /*copy all the fields */
5706 strcpy(new->name,old->name);
5707 /* new->volumeType = old->volumeType;*/
5708 new->nServers = old->nServers;
5709 count = old->nServers;
5710 if(count < NMAXNSERVERS) count++;
5711 for(i = 0; i < count; i++) {
5712 new->serverNumber[i] = ntohl(old->serverNumber[i]);
5713 new->serverPartition[i] = old->serverPartition[i];
5714 new->serverFlags[i] = old->serverFlags[i];
5716 new->volumeId[RWVOL]= old->volumeId[RWVOL];
5717 new->volumeId[ROVOL] = old->volumeId[ROVOL];
5718 new->volumeId[BACKVOL] = old->volumeId[BACKVOL];
5719 new->cloneId = old->cloneId;
5720 new->flags = old->flags;
5723 /*maps the host entries in <entry> which are present in host byte order to network byte order */
5724 void MapHostToNetwork(struct nvldbentry *entry)
5728 count = entry->nServers;
5729 if(count < NMAXNSERVERS) count++;
5730 for(i = 0; i < count; i++) {
5731 entry->serverNumber[i] = htonl(entry->serverNumber[i]);