vos-dump-clone-and-vos-copy-support-20021026
[openafs.git] / src / volser / vsprocs.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID("$Header$");
14
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #ifdef  AFS_AIX_ENV
19 #include <sys/statfs.h>
20 #endif
21 #ifdef AFS_NT40_ENV
22 #include <fcntl.h>
23 #include <winsock2.h>
24 #else
25 #include <sys/file.h>
26 #include <netinet/in.h>
27 #endif
28
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #else
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #endif
35 #endif
36
37 #include <lock.h>
38 #include <afs/voldefs.h>
39 #include <rx/xdr.h>
40 #include <rx/rx.h>
41 #include <afs/vlserver.h>
42 #include <afs/nfs.h>
43 #include <afs/auth.h>
44 #include <afs/cellconfig.h>
45 #include <afs/keys.h>
46 #include <ubik.h>
47 #include <afs/afsint.h>
48 #include "volser.h" 
49 #include "volint.h"
50 #include "lockdata.h"
51 #include <afs/com_err.h>
52 #include <rx/rxkad.h>
53 #include <afs/kautils.h>
54 #include <afs/cmd.h>
55 #include <errno.h>
56 #define ERRCODE_RANGE 8                 /* from error_table.h */
57 #define CLOCKSKEW   2                   /* not really skew, but resolution */
58
59 /* for UV_MoveVolume() recovery */
60
61 #include <afs/procmgmt.h>   /* signal(), kill(), wait(), etc. */
62 #include <setjmp.h>
63
64 #include <volser_prototypes.h>
65
66 afs_int32 VolumeExists(), CheckVldbRWBK(), CheckVldb();
67
68 struct ubik_client *cstruct;
69 int verbose = 0;
70 extern int VL_GetNewVolumeId();
71 extern int VL_SetLock();
72 extern int VL_ReleaseLock();
73 extern int VL_DeleteEntry();
74
75 void MapNetworkToHost();
76 void MapHostToNetwork();
77
78 struct release {
79   afs_int32 time;
80   afs_int32 vldbEntryIndex;
81 };
82
83 /* Utility macros used by rest of this source file */
84 #define EPRINT(ec, es) \
85         fprintf(STDERR, "\n"); \
86         fprintf(STDERR, (es)); \
87         PrintError("   ",ec);
88
89 #define EPRINT1(ec, es, ep1) \
90         fprintf(STDERR, "\n"); \
91         fprintf(STDERR, (es), (ep1)); \
92         PrintError("   ",ec);
93
94 #define EPRINT2(ec, es, ep1, ep2) \
95         fprintf(STDERR, "\n"); \
96         fprintf(STDERR, (es), (ep1), (ep2)); \
97         PrintError("   ",ec);
98
99 #define EPRINT3(ec, es, ep1, ep2, ep3) \
100         fprintf(STDERR, "\n"); \
101         fprintf(STDERR, (es), (ep1), (ep2), (ep3)); \
102         PrintError("   ",ec); 
103
104 #define EGOTO(where, ec, es) \
105         if (ec) { \
106                 EPRINT((ec),(es)); \
107                 error = (ec); \
108                 goto where; \
109         }
110
111 #define EGOTO1(where, ec, es, ep1) \
112         if (ec) { \
113                 EPRINT1((ec),(es),(ep1)); \
114                 error = (ec); \
115                 goto where; \
116         }
117
118 #define EGOTO2(where, ec, es, ep1, ep2) \
119         if (ec) { \
120                 EPRINT2((ec),(es),(ep1),(ep2)); \
121                 error = (ec); \
122                 goto where; \
123         }
124
125 #define EGOTO3(where, ec, es, ep1, ep2, ep3) \
126         if (ec) { \
127                 EPRINT3((ec),(es),(ep1),(ep2),(ep3)); \
128                 error = (ec); \
129                 goto where; \
130         }
131
132 #define VPRINT(es) \
133         { if (verbose) { fprintf(STDOUT, (es)); fflush(STDOUT); } }
134 #define VPRINT1(es, p) \
135         { if (verbose) { fprintf(STDOUT, (es), (p)); fflush(STDOUT); } }
136 #define VPRINT2(es, p1, p2) \
137         { if (verbose) { fprintf(STDOUT, (es), (p1), (p2)); fflush(STDOUT); } }
138 #define VPRINT3(es, p1, p2, p3) \
139         { if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
140 #define VDONE \
141         { if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
142
143
144
145 /* getting rid of this */
146 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
147
148
149 /* Protos for static routines */
150 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn, 
151         afs_int32 apart, afs_int32 okvol, afs_int32 delvol);
152 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags);
153 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr, 
154         afs_int32 *transPtr, afs_int32 *timePtr);
155 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid, 
156         afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results);
157 static int rel_compar (struct release *r1, struct release *r2);
158 static afs_int32 CheckVolume(volintInfo *volumeinfo, afs_int32 aserver, afs_int32 apart, 
159         afs_int32 *modentry, afs_uint32 *maxvolid);
160
161
162 /*map the partition <partId> into partition name <partName>*/
163 void MapPartIdIntoName(afs_int32 partId, char *partName)
164 {
165     if(partId < 26) {/* what if partId > = 26 ? */
166         strcpy(partName,"/vicep");
167         partName[6] = partId + 'a';
168         partName[7] = '\0';
169         return;
170     } else if (partId < VOLMAXPARTS) {
171         strcpy(partName,"/vicep");
172         partId -= 26;
173         partName[6] = 'a' + (partId/26);
174         partName[7] = 'a' + (partId%26);
175         partName[8] = '\0';
176         return;
177     }
178 }
179
180 int yesprompt(char *str)
181 {
182     int response, c;
183     int code;
184
185     fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
186     response = c = getchar();
187     while (!(c==EOF || c=='\n')) c=getchar(); /*skip to end of line*/
188     code = (response=='y'||response=='Y');      
189     return code;
190 }
191
192
193 int PrintError(char *msg, afs_int32 errcode)
194 {
195         fprintf(STDERR,msg);
196         /*replace by a big switch statement*/
197         switch(errcode) {
198             case 0 :    
199                 break;
200             case -1     :   fprintf(STDERR,"Possible communication failure\n");
201                 break;
202             case VSALVAGE: fprintf(STDERR,"Volume needs to be salvaged\n");
203                 break;
204             case VNOVNODE:  fprintf(STDERR,"Bad vnode number quoted\n");
205                 break;
206             case VNOVOL:    fprintf(STDERR,"Volume not attached, does not exist, or not on line\n");
207                 break;
208             case VVOLEXISTS:fprintf(STDERR,"Volume already exists\n");
209                 break;
210             case VNOSERVICE:fprintf(STDERR,"Volume is not in service\n");
211                 break;
212             case VOFFLINE:  fprintf(STDERR,"Volume is off line\n");
213                 break;
214             case VONLINE:   fprintf(STDERR,"Volume is already on line\n");
215                 break;
216             case VDISKFULL: fprintf(STDERR,"Partition is full\n");
217                 break;
218             case VOVERQUOTA:fprintf(STDERR,"Volume max quota exceeded\n");
219                 break;
220             case VBUSY: fprintf(STDERR,"Volume temporarily unavailable\n");
221                 break;
222             case VMOVED:fprintf(STDERR,"Volume has moved to another server\n");
223                 break;
224             case VL_IDEXIST :  fprintf(STDERR,"VLDB: volume Id exists in the vldb\n");
225                 break;
226             case VL_IO:   fprintf(STDERR,"VLDB: a read terminated too early\n");
227                 break;
228             case VL_NAMEEXIST:   fprintf(STDERR,"VLDB: volume entry exists in the vldb\n");
229                 break;
230             case VL_CREATEFAIL:   fprintf(STDERR,"VLDB: internal creation failure\n");
231                 break;
232             case VL_NOENT:   fprintf(STDERR,"VLDB: no such entry\n");
233                 break;
234             case VL_EMPTY:   fprintf(STDERR,"VLDB: vldb database is empty\n");
235                 break;
236             case VL_ENTDELETED:   fprintf(STDERR,"VLDB: entry is deleted (soft delete)\n");
237                 break;
238             case VL_BADNAME:   fprintf(STDERR,"VLDB: volume name is illegal\n");
239                 break;
240             case VL_BADINDEX:   fprintf(STDERR,"VLDB: index was out of range\n");
241                 break;
242             case VL_BADVOLTYPE:   fprintf(STDERR,"VLDB: bad volume type\n");
243                 break;
244             case VL_BADSERVER:   fprintf(STDERR,"VLDB: illegal server number (not within limits)\n");
245                 break;
246             case VL_BADPARTITION:   fprintf(STDERR,"VLDB: bad partition number\n");
247                 break;
248             case VL_REPSFULL:   fprintf(STDERR,"VLDB: run out of space for replication sites\n");
249                 break;
250             case VL_NOREPSERVER:   fprintf(STDERR,"VLDB: no such repsite server exists\n");
251                 break;
252             case VL_DUPREPSERVER:   fprintf(STDERR,"VLDB: replication site server already exists\n");
253                 break;
254             case VL_RWNOTFOUND:   fprintf(STDERR,"VLDB: parent r/w entry not found\n");
255                 break;
256             case VL_BADREFCOUNT:   fprintf(STDERR,"VLDB: illegal reference count number\n");
257                 break;
258             case VL_SIZEEXCEEDED:   fprintf(STDERR,"VLDB: vldb size for attributes exceeded\n");
259                 break;
260             case VL_BADENTRY:   fprintf(STDERR,"VLDB: bad incoming vldb entry\n");
261                 break;
262             case VL_BADVOLIDBUMP:   fprintf(STDERR,"VLDB: illegal max volid increment\n");
263                 break;
264             case VL_IDALREADYHASHED:   fprintf(STDERR,"VLDB: (RO/BACK) Id already hashed\n");
265                 break;
266             case VL_ENTRYLOCKED:   fprintf(STDERR,"VLDB: vldb entry is already locked\n");
267                 break;
268             case VL_BADVOLOPER:   fprintf(STDERR,"VLDB: bad volume operation code\n");
269                 break;
270             case VL_BADRELLOCKTYPE:   fprintf(STDERR,"VLDB: bad release lock type\n");
271                 break;
272             case VL_RERELEASE:   fprintf(STDERR,"VLDB: status report: last release was aborted\n");
273                 break;
274             case VL_BADSERVERFLAG:      fprintf(STDERR,"VLDB: invalid replication site server flag\n");
275                 break;
276             case VL_PERM:       fprintf(STDERR,"VLDB: no permission access for call\n");
277                 break;
278             case VOLSERREAD_DUMPERROR:fprintf(STDERR,"VOLSER:  Problems encountered in reading the dump file !\n");
279                 break;
280             case VOLSERDUMPERROR:fprintf(STDERR,"VOLSER: Problems encountered in doing the dump !\n");
281                 break;
282             case VOLSERATTACH_ERROR: fprintf(STDERR,"VOLSER: Could not attach the volume\n");
283                 break;
284             case VOLSERDETACH_ERROR: fprintf(STDERR,"VOLSER: Could not detach the volume\n");
285                 break;
286             case VOLSERILLEGAL_PARTITION: fprintf(STDERR,"VOLSER: encountered illegal partition number\n");
287                 break;
288             case VOLSERBAD_ACCESS: fprintf(STDERR,"VOLSER: permission denied, not a super user\n");
289                 break;
290             case VOLSERVLDB_ERROR: fprintf(STDERR,"VOLSER: error detected in the VLDB\n");
291                 break;
292             case VOLSERBADNAME: fprintf(STDERR,"VOLSER: error in volume name\n");
293                 break;
294             case VOLSERVOLMOVED: fprintf(STDERR,"VOLSER: volume has moved\n");
295                 break;
296             case VOLSERBADOP: fprintf(STDERR,"VOLSER: illegal operation\n");
297                 break;
298             case VOLSERBADRELEASE: fprintf(STDERR,"VOLSER: release could not be completed\n");
299                 break;
300             case VOLSERVOLBUSY: fprintf(STDERR,"VOLSER: volume is busy\n");
301                 break;
302               case VOLSERNO_MEMORY: fprintf(STDERR,"VOLSER: volume server is out of memory\n");
303                 break;
304               case VOLSERNOVOL:fprintf(STDERR,"VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
305                 break;
306               case VOLSERMULTIRWVOL: fprintf(STDERR,"VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
307                 break;
308               case VOLSERFAILEDOP: fprintf(STDERR,"VOLSER: not all entries were successfully processed\n");
309                 break;
310             default: 
311                 {
312
313                 afs_int32 offset;
314
315                 initialize_KA_error_table();
316                 initialize_RXK_error_table();
317                 initialize_KTC_error_table();
318                 initialize_ACFG_error_table();
319                 initialize_CMD_error_table();
320                 initialize_VL_error_table();
321                 
322                 offset = errcode & ((1<<ERRCODE_RANGE)-1);
323                 fprintf(STDERR,"%s: %s\n",error_table_name (errcode), error_message (errcode));
324                 break;
325                 }
326         }
327         return 0;
328 }
329
330
331 static struct rx_securityClass *uvclass=0;
332 static int uvindex = -1;
333 /* called by VLDBClient_Init to set the security module to be used in the RPC */
334 int UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
335 {
336     uvindex = aindex;
337     uvclass = as;
338 }
339
340 /* bind to volser on <port> <aserver> */
341 /* takes server address in network order, port in host order.  dumb */
342 struct rx_connection *UV_Bind(afs_int32 aserver, afs_int32 port)
343 {
344     register struct rx_connection *tc;
345     
346     tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass, uvindex);
347     return tc;
348 }
349
350 /* if <okvol> is allright(indicated by beibg able to
351  * start a transaction, delete the <delvol> */
352 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn, 
353         afs_int32 apart, afs_int32 okvol, afs_int32 delvol)
354 {
355     afs_int32 error,code,tid,rcode;
356
357     error = 0;
358     code = 0;
359
360     if(okvol == 0) {
361         code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
362         if(!error && code) error = code;
363         code = AFSVolDeleteVolume(aconn,tid);
364         if(!error && code) error = code;
365         code = AFSVolEndTrans(aconn,tid, &rcode);
366         if(!code) code = rcode;
367         if(!error && code) error = code;
368         return error;
369     }
370     else {
371         code = AFSVolTransCreate(aconn, okvol, apart, ITOffline,&tid);
372         if(!code) {
373             code = AFSVolEndTrans(aconn,tid, &rcode);
374             if(!code) code = rcode;
375             if(!error && code) error = code;
376             code = AFSVolTransCreate(aconn, delvol, apart, ITOffline,&tid);
377             if(!error && code) error = code;
378             code = AFSVolDeleteVolume(aconn,tid);
379             if(!error && code) error = code;
380             code = AFSVolEndTrans(aconn,tid, &rcode);
381             if(!code) code = rcode;
382             if(!error && code) error = code;
383         }
384         else 
385             error = code;
386         return error;
387     }
388 }
389
390 /* called by EmuerateEntry, show vldb entry in a reasonable format */
391 void SubEnumerateEntry(struct nvldbentry *entry)
392 {
393     int i;
394     char pname[10];
395     int isMixed = 0;
396
397 #ifdef notdef
398     fprintf(STDOUT,"    readWriteID %-10u ",entry->volumeId[RWVOL]);
399     if(entry->flags & RW_EXISTS) fprintf(STDOUT," valid \n");else fprintf(STDOUT," invalid \n");
400     fprintf(STDOUT,"    readOnlyID  %-10u ",entry->volumeId[ROVOL]);
401     if(entry->flags & RO_EXISTS) fprintf(STDOUT," valid \n") ;else fprintf(STDOUT," invalid \n");
402     fprintf(STDOUT,"    backUpID    %-10u ",entry->volumeId[BACKVOL]);
403     if(entry->flags & BACK_EXISTS) fprintf(STDOUT," valid \n"); else fprintf(STDOUT," invalid \n");
404     if((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
405         fprintf(STDOUT,"    releaseClone %-10u \n",entry->cloneId);
406 #else
407     if (entry->flags & RW_EXISTS)
408         fprintf(STDOUT,"    RWrite: %-10u",entry->volumeId[RWVOL]);
409     if (entry->flags & RO_EXISTS)
410         fprintf(STDOUT,"    ROnly: %-10u",entry->volumeId[ROVOL]);
411     if (entry->flags & BACK_EXISTS)
412         fprintf(STDOUT,"    Backup: %-10u",entry->volumeId[BACKVOL]);
413     if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
414         fprintf(STDOUT,"    RClone: %-10u",entry->cloneId);
415     fprintf(STDOUT,"\n");
416 #endif
417     fprintf(STDOUT,"    number of sites -> %u\n",entry->nServers);
418     for(i = 0; i < entry->nServers; i++) {
419         if(entry->serverFlags[i] & NEW_REPSITE)
420             isMixed = 1;
421     }
422     for(i = 0; i < entry->nServers; i++) {
423         MapPartIdIntoName(entry->serverPartition[i],pname);
424         fprintf(STDOUT,"       server %s partition %s ",
425                 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
426         if(entry->serverFlags[i] & ITSRWVOL) fprintf(STDOUT,"RW Site ") ; else fprintf(STDOUT,"RO Site ");
427         if (isMixed) {
428            if (entry->serverFlags[i] & NEW_REPSITE)
429               fprintf(STDOUT," -- New release");
430            else
431               fprintf(STDOUT," -- Old release");
432         } else {
433            if (entry->serverFlags[i] & RO_DONTUSE)
434               fprintf(STDOUT," -- Not released");
435         }
436         fprintf(STDOUT,"\n");
437     }
438     
439     return;
440     
441 }
442
443 /*enumerate the vldb entry corresponding to <entry> */
444 void EnumerateEntry(struct nvldbentry *entry)
445 {
446
447     fprintf(STDOUT,"\n");
448     fprintf(STDOUT,"%s \n",entry->name);
449     SubEnumerateEntry(entry);
450     return;
451 }
452
453 /* forcibly remove a volume.  Very dangerous call */
454 int UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
455 {
456     register struct rx_connection *tconn;
457     register afs_int32 code;
458
459     tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
460     if (tconn) {
461         code = AFSVolNukeVolume(tconn, partid, volid);
462         rx_DestroyConnection(tconn);
463     }
464     else code = 0;
465     return code;
466 }
467
468 /* like df. Return usage of <pname> on <server> in <partition> */
469 int UV_PartitionInfo(afs_int32 server, char *pname, struct diskPartition *partition)
470 {
471     register struct rx_connection *aconn;
472     afs_int32 code;
473
474     code = 0;
475     aconn = (struct rx_connection *)0;
476     aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
477     code = AFSVolPartitionInfo(aconn,pname,partition);
478     if(code){
479         fprintf(STDERR,"Could not get information on partition %s\n",pname);
480         PrintError("",code);
481     }
482     if(aconn) rx_DestroyConnection(aconn);
483     return code;
484 }
485
486 /* old interface to create volume */
487 int UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 *anewid)
488 {
489 afs_int32 code;
490 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
491 return code;
492 }
493
494 /* create a volume, given a server, partition number, volume name --> sends
495 * back new vol id in <anewid>*/
496 int UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aquota, 
497         afs_int32 aspare1, afs_int32 aspare2, afs_int32 aspare3, afs_int32 aspare4, afs_int32 *anewid)
498 {
499
500     register struct rx_connection *aconn;
501     afs_int32 tid;
502     register afs_int32 code;
503     afs_int32 error;
504     afs_int32 rcode,vcode;
505     struct nvldbentry entry,storeEntry;/*the new vldb entry */
506     struct volintInfo tstatus;
507
508     tid = 0;
509     aconn = (struct rx_connection *)0;
510     error = 0;
511     memset(&tstatus, 0, sizeof(struct volintInfo));
512     tstatus.dayUse = -1;
513     tstatus.maxquota = aquota;
514
515     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
516     /* next the next 3 available ids from the VLDB */
517     vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 3, anewid);
518     EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n",aname);
519
520     code = AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
521     EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n",aname,*anewid);
522     
523     code = AFSVolSetInfo(aconn, tid, &tstatus);
524     EPRINT1(code, "Could not change quota (error %d), continuing...\n", code);
525
526     code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
527     EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n",aname,*anewid);
528
529     VPRINT2("Volume %s %u created and brought online\n",aname,*anewid);
530
531     /* set up the vldb entry for this volume */
532     strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
533     entry.nServers = 1;
534     entry.serverNumber[0] = aserver;    /* this should have another 
535                                          level of indirection later */
536     entry.serverPartition[0] = apart;   /* this should also have 
537                                          another indirection level */
538     entry.flags = RW_EXISTS;/* this records that rw volume exists */
539     entry.serverFlags[0] = ITSRWVOL;    /*this rep site has rw  vol */
540     entry.volumeId[RWVOL] = *anewid;
541     entry.volumeId[ROVOL] = *anewid + 1;/* rw,ro, bk id are related in the default case */
542     entry.volumeId[BACKVOL] = *anewid + 2;
543     entry.cloneId = 0;
544     /*map into right byte order, before passing to xdr, the stuff has to be in host
545       byte order. Xdr converts it into network order */
546     MapNetworkToHost(&entry,&storeEntry);
547     /* create the vldb entry */
548     vcode = VLDB_CreateEntry(&storeEntry);
549     if(vcode) {
550         fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", aname,*anewid);
551         /*destroy the created volume*/
552         VPRINT1("Deleting the newly created volume %u\n",*anewid);
553         AFSVolDeleteVolume(aconn,tid);
554         error = vcode;
555         goto cfail;
556     }
557     VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,*anewid);
558     /* volume created, now terminate the transaction and release the connection*/
559     code = AFSVolEndTrans(aconn, tid, &rcode);/*if it crashes before this
560         the volume will come online anyway when transaction timesout , so if
561             vldb entry exists then the volume is guaranteed to exist too wrt create*/
562     tid = 0;
563     if(code){
564         fprintf(STDERR,"Failed to end the transaction on the volume %s %u\n",aname,*anewid); 
565         error = code;
566         goto cfail;
567     }
568
569     cfail:
570       if(tid)
571         {
572                 code= AFSVolEndTrans(aconn, tid, &rcode);
573                 if(code)
574                         fprintf(STDERR,"WARNING: could not end transaction\n");
575         }
576     if(aconn) rx_DestroyConnection(aconn);
577     PrintError("",error);
578     return error;
579     
580
581 }
582 /* create a volume, given a server, partition number, volume name --> sends
583 * back new vol id in <anewid>*/
584 int UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname, afs_int32 aid)
585 {
586     register struct rx_connection *aconn;
587     afs_int32 error;
588     afs_int32 vcode;
589     struct nvldbentry entry,storeEntry;/*the new vldb entry */
590
591     aconn = (struct rx_connection *)0;
592     error = 0;
593
594     /* set up the vldb entry for this volume */
595     strncpy(entry.name, aname,VOLSER_OLDMAXVOLNAME);
596     entry.nServers = 1;
597     entry.serverNumber[0] = aserver;    /* this should have another 
598                                          level of indirection later */
599     entry.serverPartition[0] = apart;   /* this should also have 
600                                          another indirection level */
601     entry.flags = RW_EXISTS;/* this records that rw volume exists */
602     entry.serverFlags[0] = ITSRWVOL;    /*this rep site has rw  vol */
603     entry.volumeId[RWVOL] = aid;
604 #ifdef notdef
605     entry.volumeId[ROVOL] = anewid + 1;/* rw,ro, bk id are related in the default case */
606     entry.volumeId[BACKVOL] = *anewid + 2;
607 #else
608     entry.volumeId[ROVOL] = 0;
609     entry.volumeId[BACKVOL] = 0;
610 #endif
611     entry.cloneId = 0;
612     /*map into right byte order, before passing to xdr, the stuff has to be in host
613       byte order. Xdr converts it into network order */
614     MapNetworkToHost(&entry,&storeEntry);
615     /* create the vldb entry */
616     vcode = VLDB_CreateEntry(&storeEntry);
617     if(vcode) {
618         fprintf(STDERR,"Could not create a VLDB entry for the  volume %s %u\n", aname,aid);
619         error = vcode;
620         goto cfail;
621     }
622     VPRINT2("Created the VLDB entry for the volume %s %u\n",aname,aid);
623
624   cfail:
625     if(aconn) rx_DestroyConnection(aconn);
626     PrintError("",error);
627     return error;
628 }
629
630 /* Delete the volume <volid>on <aserver> <apart>
631  * the physical entry gets removed from the vldb only if the ref count 
632  * becomes zero
633  */
634 int UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
635 {
636     struct rx_connection *aconn = (struct rx_connection *)0;
637     afs_int32 ttid = 0;
638     afs_int32 code, rcode;
639     afs_int32 error = 0;
640     struct nvldbentry entry,storeEntry;
641     int islocked = 0;
642     afs_int32 avoltype = -1, vtype;
643     int notondisk = 0, notinvldb = 0;
644
645     /* Find and read bhe VLDB entry for this volume */
646     code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
647     if (code) {
648         if (code != VL_NOENT) {
649            EGOTO1(error_exit, code, "Could not lock VLDB entry for the volume %u\n", avolid);
650         }
651         notinvldb = 1;
652     } else {
653        islocked = 1;
654
655        code = VLDB_GetEntryByID(avolid, avoltype, &entry);
656        EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",avolid);
657        MapHostToNetwork(&entry);
658
659        if (verbose)
660           EnumerateEntry(&entry);
661     }
662
663     /* Whether volume is in the VLDB or not. Delete the volume on disk */
664     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
665     code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
666     if (code) {
667        if (code == VNOVOL) {
668           notondisk = 1;
669        } else {
670            EGOTO1(error_exit, code, "Transaction on volume %u failed\n", avolid);
671        }
672     }
673     else {
674        VPRINT1("Trying to delete the volume %u ...", avolid);
675
676        code = AFSVolDeleteVolume(aconn, ttid);
677        EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
678
679        code = AFSVolEndTrans(aconn, ttid, &rcode);
680        code = (code ? code : rcode);
681        ttid = 0;
682        EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",avolid);
683        VDONE;
684     }
685
686     /* Now update the VLDB entry.
687      * But first, verify we have a VLDB entry.
688      * Whether volume is on disk or not. Delete the volume in VLDB.
689      */
690     if (notinvldb)
691        ERROR_EXIT(0);
692
693     if (avolid == entry.volumeId[BACKVOL]) {
694         /* Its a backup volume, modify the VLDB entry. Check that the
695          * backup volume is on the server/partition we asked to delete.
696          */
697         if ( !(entry.flags & BACK_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
698            notinvldb = 2;         /* Not on this server and partition */
699            ERROR_EXIT(0);
700         }
701
702         VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
703
704         entry.flags &= ~BACK_EXISTS;
705         vtype = BACKVOL;
706     }
707
708     else if (avolid == entry.volumeId[ROVOL]) {
709         /* Its a read-only volume, modify the VLDB entry. Check that the
710          * readonly volume is on the server/partition we asked to delete.
711          * If flags does not have RO_EIXSTS set, then this may mean the RO 
712          * hasn't been released (and could exist in VLDB).
713          */
714         if (!Lp_ROMatch(aserver,apart,&entry)) {
715            notinvldb = 2;            /* Not found on this server and partition */
716            ERROR_EXIT(0);
717         }
718         
719         if (verbose)
720            fprintf(STDOUT,"Marking the readonly volume %u deleted in the VLDB\n", avolid);
721
722         Lp_SetROValue(&entry, aserver, apart, 0, 0);  /* delete the site */
723         entry.nServers--;
724         if (!Lp_ROMatch(0,0,&entry))
725            entry.flags &= ~RO_EXISTS;    /* This was the last ro volume */
726         vtype = ROVOL;
727     }
728
729     else if (avolid == entry.volumeId[RWVOL]) {
730         /* It's a rw volume, delete the backup volume, modify the VLDB entry.
731          * Check that the readwrite volumes is on the server/partition we
732          * asked to delete.
733          */
734         if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver,apart,&entry)) {
735            notinvldb = 2;          /* Not found on this server and partition */
736            ERROR_EXIT(0);
737         }
738         
739         /* Delete backup if it exists */
740         code = AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart, ITOffline, &ttid);
741         if (!code) {
742            if (verbose) {
743               fprintf(STDOUT,"Trying to delete the backup volume %u ...", entry.volumeId[BACKVOL]);
744               fflush(STDOUT);
745            }
746            code = AFSVolDeleteVolume(aconn, ttid);
747            EGOTO1(error_exit, code, "Could not delete the volume %u \n", entry.volumeId[BACKVOL]);
748
749            code = AFSVolEndTrans(aconn, ttid, &rcode);
750            ttid = 0;
751            code = (code ? code : rcode);
752            EGOTO1(error_exit, code, "Could not end the transaction for the volume %u \n",
753                       entry.volumeId[BACKVOL]);
754            if (verbose)
755               fprintf(STDOUT," done\n");
756         }
757
758         if (verbose)
759            fprintf(STDOUT,"Marking the readwrite volume %u%s deleted in the VLDB\n", 
760                    avolid, ((entry.flags & BACK_EXISTS)?", and its backup volume,":""));
761
762         Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
763         entry.nServers--;
764         entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
765         vtype = RWVOL;
766
767         if (entry.flags & RO_EXISTS)
768            fprintf(STDERR,"WARNING: ReadOnly copy(s) may still exist\n");
769     }
770
771     else {
772        notinvldb = 2;         /* Not found on this server and partition */
773        ERROR_EXIT(0);
774     }
775
776     /* Either delete or replace the VLDB entry */
777     if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
778        if (verbose)
779           fprintf(STDOUT,"Last reference to the VLDB entry for %u - deleting entry\n", avolid);
780        code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
781        EGOTO1(error_exit, code, "Could not delete the VLDB entry for the volume %u \n",avolid);
782     } else {
783        MapNetworkToHost(&entry, &storeEntry);
784        code = VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
785                                 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
786        EGOTO1(error_exit, code, "Could not update the VLDB entry for the volume %u \n", avolid);
787     }
788     islocked = 0;
789
790   error_exit:
791     if (error) EPRINT(error, "\n");
792
793     if (notondisk && notinvldb) {
794        EPRINT2(VOLSERNOVOL,"Volume %u does not exist %s\n",
795                avolid, ((notinvldb == 2)?"on server and partition":""));
796        if (!error) error = VOLSERNOVOL;
797     }
798     else if (notondisk) {
799        fprintf(STDERR,"WARNING: Volume %u did not exist on the partition\n", avolid);
800     }
801     else if (notinvldb) {
802        fprintf(STDERR,"WARNING: Volume %u does not exist in VLDB %s\n",
803                avolid, ((notinvldb == 2)?"on server and partition":""));
804     }
805
806     if (ttid) {
807         code = AFSVolEndTrans(aconn, ttid, &rcode);
808         code = (code ? code : rcode);
809         if (code) {
810             fprintf(STDERR,"Could not end transaction on the volume %u\n", avolid);
811             PrintError("", code);
812             if (!error) error = code;
813         }
814     }
815
816     if (islocked) {
817         code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, -1, 
818                          (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
819         if (code) {
820             EPRINT1(code, "Could not release the lock on the VLDB entry for the volume %u \n", 
821                     avolid);
822             if (!error) error = code;
823         }
824     }
825
826     if (aconn) rx_DestroyConnection(aconn);
827     return error;
828 }
829
830 /* add recovery to UV_MoveVolume */
831
832 #define TESTC   0       /* set to test recovery code, clear for production */
833
834 jmp_buf env;
835 int interrupt=0;
836
837 void sigint_handler(int x)
838 {
839         if(interrupt)
840                 longjmp(env,0);
841
842         fprintf(STDOUT,
843                 "\nSIGINT handler: vos move operation in progress\n");
844         fprintf(STDOUT,
845                 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
846         fprintf(STDOUT,
847                 "enter second control-c to exit\n");
848         fflush(STDOUT);
849
850         interrupt=1;
851         signal(SIGINT,sigint_handler);
852
853         return;
854 }
855
856 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
857  * <atopart>. The operation is almost idempotent 
858  */
859
860 int UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver, 
861         afs_int32 afrompart, afs_int32 atoserver, afs_int32 atopart)
862 {
863     struct rx_connection *toconn, *fromconn ;
864     afs_int32                fromtid, totid, clonetid;
865     char                 vname[64];
866     char                 *volName = 0;
867     char                 tmpName[VOLSER_MAXVOLNAME +1];
868     afs_int32                rcode;
869     afs_int32                fromDate;
870     struct restoreCookie cookie;
871     register afs_int32       vcode, code;
872     afs_int32                newVol, volid, backupId;
873     struct volser_status tstatus;
874     struct destServer    destination;
875
876     struct nvldbentry    entry, storeEntry;
877     int                  i, islocked, pntg;
878     afs_int32                error;
879     char                 in,lf;                         /* for test code */
880     int                  same;
881
882 #ifdef  ENABLE_BUGFIX_1165
883     volEntries volumeInfo;
884     struct volintInfo *infop = 0;
885 #endif
886
887     islocked = 0;
888     fromconn = (struct rx_connection *)0;
889     toconn   = (struct rx_connection *)0;
890     fromtid  = 0;
891     totid    = 0;
892     clonetid = 0;
893     error    = 0;
894     volid    = 0;
895     pntg     = 0;
896     backupId = 0;
897     newVol   = 0;
898
899     /* support control-c processing */
900     if (setjmp(env)) goto mfail;
901     (void) signal(SIGINT,sigint_handler);
902  
903     if (TESTC)
904     {
905         fprintf(STDOUT,
906                 "\nThere are three tests points - verifies all code paths through recovery.\n");
907         fprintf(STDOUT,"First test point - operation not started.\n");
908         fprintf(STDOUT,"...test here (y, n)? ");
909         fflush(STDOUT);
910         fscanf(stdin,"%c",&in);
911         fscanf(stdin,"%c",&lf); /* toss away */
912         if (in=='y')
913         {
914             fprintf(STDOUT,"type control-c\n");
915             while(1)
916             {
917                 fprintf(stdout,".");
918                 fflush(stdout);
919                 sleep(1);
920             }
921         }
922         /* or drop through */
923     }
924
925     vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
926     EGOTO1(mfail, vcode, "Could not fetch the entry for the volume  %u from the VLDB \n", afromvol);
927
928     if (entry.volumeId[RWVOL] != afromvol)
929     {
930         fprintf(STDERR,"Only RW volume can be moved\n");
931         exit(1);
932     }
933
934     vcode = ubik_Call(VL_SetLock, cstruct, 0,afromvol, RWVOL, VLOP_MOVE);
935     EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
936     islocked = 1;
937
938     vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
939     EGOTO1(mfail, vcode, "Could not fetch the entry for the volume  %u from the VLDB \n", afromvol);
940
941     backupId = entry.volumeId[BACKVOL];
942     MapHostToNetwork(&entry);
943
944     if ( !Lp_Match(afromserver, afrompart, &entry) )
945     {
946         /* the from server and partition do not exist in the vldb entry corresponding to volid */
947         if ( !Lp_Match(atoserver, atopart, &entry) ) 
948         {
949             /* the to server and partition do not exist in the vldb entry corresponding to volid */
950             fprintf(STDERR,"The volume %u is not on the specified site. \n", afromvol);
951             fprintf(STDERR,"The current site is :");
952             for (i=0; i<entry.nServers; i++)
953             {
954                 if (entry.serverFlags[i] == ITSRWVOL)
955                 {
956                     char pname[10];
957                     MapPartIdIntoName(entry.serverPartition[i],pname);
958                     fprintf(STDERR," server %s partition %s \n",
959                             hostutil_GetNameByINet(entry.serverNumber[i]), pname);
960                 }
961             }
962             vcode = ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
963                               (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
964             EGOTO1(mfail, vcode, " Could not release lock on the VLDB entry for the volume %u \n",
965                    afromvol);
966
967             return VOLSERVOLMOVED;
968         }
969
970         /* delete the volume afromvol on src_server */
971         /* from-info does not exist but to-info does =>
972          * we have already done the move, but the volume
973          * may still be existing physically on from fileserver
974          */
975         fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
976         fromtid = 0;
977         pntg = 1;
978
979         code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline, &fromtid);
980         if (!code) 
981         {   /* volume exists - delete it */
982             VPRINT1("Setting flags on leftover source volume %u ...", afromvol);
983             code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
984             EGOTO1(mfail, code, "Failed to set flags on the leftover source volume %u\n", afromvol);
985             VDONE;
986
987             VPRINT1("Deleting leftover source volume %u ...", afromvol);
988             code = AFSVolDeleteVolume(fromconn,fromtid);
989             EGOTO1(mfail, code, "Failed to delete the leftover source volume %u\n", afromvol);
990             VDONE;
991             
992             VPRINT1("Ending transaction on leftover source volume %u ...", afromvol);
993             code = AFSVolEndTrans(fromconn, fromtid, &rcode);
994             fromtid = 0;
995             if (!code) code = rcode;
996             EGOTO1(mfail, code, "Could not end the transaction for the leftover source volume %u \n", afromvol);
997             VDONE;
998         }
999
1000         /*delete the backup volume now */
1001         fromtid = 0;
1002         code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1003         if (!code) 
1004         {   /* backup volume exists - delete it */
1005             VPRINT1("Setting flags on leftover backup volume %u ...", backupId);
1006             code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1007             EGOTO1(mfail, code, "Failed to set flags on the backup volume %u\n", backupId);
1008             VDONE;
1009
1010             VPRINT1("Deleting leftover backup volume %u ...", backupId);
1011             code = AFSVolDeleteVolume(fromconn,fromtid);
1012             EGOTO1(mfail, code, "Could not delete the leftover backup volume %u\n", backupId);
1013             VDONE;
1014
1015             VPRINT1("Ending transaction on leftover backup volume %u ...", backupId);
1016             code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1017             fromtid = 0;
1018             if (!code) code = rcode;
1019             EGOTO1(mfail, code,"Could not end the transaction for the leftover backup volume %u\n",backupId);
1020             VDONE;
1021         }
1022
1023         fromtid = 0;
1024         error = 0;
1025         goto mfail;
1026     }
1027
1028     /* From-info matches the vldb info about volid,
1029      * its ok start the move operation, the backup volume 
1030      * on the old site is deleted in the process 
1031      */
1032     if (afrompart == atopart) 
1033     {
1034         same = VLDB_IsSameAddrs (afromserver, atoserver, &error);
1035         EGOTO2(mfail, error, "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1036                 afromserver, error);
1037
1038         if ( same )
1039         {
1040                 EGOTO1(mfail, VOLSERVOLMOVED, "Warning: Moving volume %u to its home partition ignored!\n", afromvol);
1041         }
1042     }
1043
1044     pntg = 1;
1045     toconn   = UV_Bind(atoserver,   AFSCONF_VOLUMEPORT); /* get connections to the servers */
1046     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1047     fromtid = totid = 0;        /* initialize to uncreated */
1048
1049     /* ***
1050      * clone the read/write volume locally.
1051      * ***/
1052
1053     VPRINT1("Starting transaction on source volume %u ...", afromvol);
1054     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1055     EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1056     VDONE;
1057
1058     /* Get a clone id */
1059     VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1060     newVol = 0;
1061     vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1062     EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1063     VDONE;
1064
1065     /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1066     VPRINT1("Cloning source volume %u ...", afromvol);
1067     strcpy(vname, "move-clone-temp");
1068     code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &newVol);
1069     EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1070     VDONE;
1071
1072     /* lookup the name of the volume we just cloned */
1073     volid = afromvol;
1074     code = AFSVolGetName(fromconn, fromtid, &volName);
1075     EGOTO1(mfail, code, "Failed to get the name of the volume %u\n", newVol);
1076
1077     VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1078     rcode = 0;
1079     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1080     fromtid = 0;
1081     if (!code) code = rcode;
1082     EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1083     VDONE;
1084
1085     /* ***
1086      * Create the destination volume
1087      * ***/
1088
1089     VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1090     code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1091     EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1092     VDONE;
1093
1094     VPRINT1("Setting flags on cloned volume %u ...", newVol);
1095     code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1096     EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", newVol);
1097     VDONE;
1098
1099     /* remember time from which we've dumped the volume */
1100     VPRINT1("Getting status of cloned volume %u ...", newVol);
1101     code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1102     EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", newVol);
1103     VDONE;
1104
1105     fromDate = tstatus.creationDate-CLOCKSKEW;
1106
1107 #ifdef  ENABLE_BUGFIX_1165
1108     /*
1109      * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1110      * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1111      * don't use this information...
1112      */
1113     volumeInfo.volEntries_val = (volintInfo *)0;/*this hints the stub to allocate space*/
1114     volumeInfo.volEntries_len = 0;
1115     code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1116     EGOTO1(mfail, code, "Failed to get the volint Info of the cloned volume %u\n", afromvol);
1117
1118     infop = (volintInfo *) volumeInfo.volEntries_val;
1119     infop->maxquota = -1;                       /* Else it will replace the default quota */
1120 #endif
1121
1122     /* create a volume on the target machine */
1123     volid = afromvol;
1124     code = AFSVolTransCreate (toconn, volid, atopart, ITOffline, &totid);
1125     if (!code) 
1126     {  
1127       /* Delete the existing volume.
1128        * While we are deleting the volume in these steps, the transaction
1129        * we started against the cloned volume (clonetid above) will be
1130        * sitting idle. It will get cleaned up after 600 seconds
1131        */
1132         VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1133         code = AFSVolDeleteVolume(toconn, totid);
1134         EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", volid);
1135         VDONE;
1136         
1137         VPRINT1("Ending transaction on pre-existing volume %u on destination ...", volid);
1138         code = AFSVolEndTrans(toconn, totid, &rcode);
1139         totid = 0;
1140         if (!code) code = rcode;
1141         EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1142                volid);
1143         VDONE;
1144     }
1145
1146     VPRINT1("Creating the destination volume %u ...", volid);
1147     code = AFSVolCreateVolume (toconn, atopart, volName, volser_RW, volid, &volid, &totid);
1148     EGOTO1(mfail, code, "Failed to create the destination volume %u\n", volid);
1149     VDONE;
1150
1151     strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1152     free(volName);
1153     volName = NULL;
1154
1155     VPRINT1("Setting volume flags on destination volume %u ...", volid);
1156     code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1157     EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", volid);
1158     VDONE;
1159
1160     /***
1161      * Now dump the clone to the new volume
1162      ***/
1163
1164     destination.destHost = ntohl(atoserver);
1165     destination.destPort = AFSCONF_VOLUMEPORT;
1166     destination.destSSID = 1;
1167
1168     /* Copy the clone to the new volume */
1169     VPRINT2("Dumping from clone %u on source to volume %u on destination ...", newVol, afromvol);
1170     strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1171     cookie.type   = RWVOL;
1172     cookie.parent = entry.volumeId[RWVOL];
1173     cookie.clone  = 0;
1174     code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1175     EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1176     VDONE;
1177
1178     VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1179     code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1180     if (!code) code = rcode;
1181     clonetid = 0;
1182     EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1183     VDONE;
1184
1185     /* ***
1186      * reattach to the main-line volume, and incrementally dump it.
1187      * ***/
1188
1189     VPRINT1("Starting transaction on source volume %u ...", afromvol);
1190     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1191     EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1192     VDONE;
1193
1194     /* now do the incremental */
1195     VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1196     code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1197     EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1198     VDONE;
1199
1200     /* now adjust the flags so that the new volume becomes official */
1201     VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1202     code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1203     EGOTO(mfail, code, "Failed to set the flags to make old source volume offline\n");
1204     VDONE;
1205
1206     VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1207     code = AFSVolSetFlags(toconn, totid, 0);
1208     EGOTO(mfail, code, "Failed to set the flags to make new source volume online\n");
1209     VDONE;
1210
1211 #ifdef  ENABLE_BUGFIX_1165
1212     VPRINT1("Setting volume status on destination volume %u ...", volid);
1213     code = AFSVolSetInfo(toconn, totid, infop);
1214     EGOTO1(mfail, code, "Failed to set volume status on the destination volume %u\n", volid);
1215     VDONE;
1216 #endif
1217
1218     /* put new volume online */
1219     VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1220     code = AFSVolEndTrans(toconn, totid, &rcode);
1221     totid = 0;
1222     if (!code) code = rcode;
1223     EGOTO1(mfail, code, "Failed to end the transaction on the volume %u on the new site\n", afromvol);
1224     VDONE;
1225
1226     Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1227     MapNetworkToHost(&entry,&storeEntry);
1228     storeEntry.flags &= ~BACK_EXISTS;
1229
1230     if (TESTC)
1231     {
1232         fprintf(STDOUT, "Second test point - operation in progress but not complete.\n");
1233         fprintf(STDOUT,"...test here (y, n)? ");
1234         fflush(STDOUT);
1235         fscanf(stdin,"%c",&in);
1236         fscanf(stdin,"%c",&lf); /* toss away */
1237         if (in=='y')
1238         {
1239             fprintf(STDOUT,"type control-c\n");
1240             while(1)
1241             {
1242                 fprintf(stdout,".");
1243                 fflush(stdout);
1244                 sleep(1);
1245             }
1246         }
1247         /* or drop through */
1248     }
1249
1250     VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1251     vcode = VLDB_ReplaceEntry (afromvol, -1, &storeEntry, 
1252                                (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1253     if (vcode) 
1254     {
1255         fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %s %u \n",
1256                 storeEntry.name,afromvol);
1257         error = vcode;
1258         goto mfail;
1259     }
1260     islocked=0;
1261     VDONE;
1262
1263     if (TESTC)
1264     {
1265         fprintf(STDOUT, "Third test point - operation complete but no cleanup.\n");
1266         fprintf(STDOUT,"...test here (y, n)? ");
1267         fflush(STDOUT);
1268         fscanf(stdin,"%c",&in);
1269         fscanf(stdin,"%c",&lf); /* toss away */
1270         if (in=='y')
1271         {
1272             fprintf(STDOUT,"type control-c\n");
1273             while(1)
1274             {
1275                 fprintf(stdout,".");
1276                 fflush(stdout);
1277                 sleep(1);
1278             }
1279         }
1280         /* or drop through */
1281     }
1282
1283 #ifdef notdef
1284     /* This is tricky.  File server is very stupid, and if you mark the volume
1285      * as VTOutOfService, it may mark the *good* instance (if you're moving
1286      * between partitions on the same machine) as out of service.  Since
1287      * we're cleaning this code up in DEcorum, we're just going to kludge around
1288      * it for now by removing this call. */
1289     /* already out of service, just zap it now */
1290     code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1291     if (code)
1292     {
1293         fprintf(STDERR,"Failed to set the flags to make the old source volume offline\n");
1294         goto mfail;
1295     }
1296 #endif
1297     if (atoserver != afromserver) 
1298     {
1299         /* set forwarding pointer for moved volumes */
1300         VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1301         code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1302         EGOTO1(mfail, code, "Failed to set the forwarding pointer for the volume %u\n", afromvol);
1303         VDONE;
1304     }
1305
1306     VPRINT1("Deleting old volume %u on source ...", afromvol);
1307     code = AFSVolDeleteVolume(fromconn,fromtid);        /* zap original volume */
1308     EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n", afromvol); 
1309     VDONE;
1310     
1311     VPRINT1("Ending transaction on old volume %u on the source ...", afromvol);
1312     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1313     fromtid = 0;
1314     if (!code) code = rcode;
1315     EGOTO1(mfail, code, "Failed to end the transaction on the old volume %u on the source\n", afromvol);
1316     VDONE;
1317
1318     /* Delete the backup volume on the original site */
1319     VPRINT1("Creating transaction for backup volume %u on source ...", backupId);
1320     code = AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1321     VDONE;
1322     if (!code) 
1323     {
1324         VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1325         code = AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1326         EGOTO1(mfail, code, "Failed to set the flags on the backup volume %u on the source\n", backupId);
1327         VDONE;
1328
1329         VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1330         code = AFSVolDeleteVolume(fromconn,fromtid);
1331         EGOTO1(mfail, code, "Failed to delete the backup volume %u on the source\n", backupId);
1332         VDONE;
1333         
1334         VPRINT1("Ending transaction on backup volume %u on source ...", backupId);
1335         code = AFSVolEndTrans(fromconn,fromtid, &rcode);
1336         fromtid = 0;
1337         if (!code) code = rcode;
1338         EGOTO1(mfail, code, "Failed to end the transaction on the backup volume %u on the source\n", backupId);
1339         VDONE;
1340     }
1341     else code = 0;              /* no backup volume? that's okay */
1342
1343     fromtid = 0;
1344     VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1345     code = AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline, &clonetid);
1346     EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", newVol);
1347     VDONE;
1348     
1349     /* now delete the clone */
1350     VPRINT1("Deleting the cloned volume %u ...", newVol);
1351     code = AFSVolDeleteVolume(fromconn, clonetid);
1352     EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", newVol);
1353     VDONE;
1354     
1355     VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1356     code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1357     if (!code) code = rcode;
1358     clonetid = 0;
1359     EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", newVol);
1360     VDONE;
1361
1362     /* fall through */
1363     /* END OF MOVE */
1364
1365     if (TESTC)
1366     {
1367         fprintf(STDOUT,"Fourth test point - operation complete.\n");
1368         fprintf(STDOUT,"...test here (y, n)? ");
1369         fflush(STDOUT);
1370         fscanf(stdin,"%c",&in);
1371         fscanf(stdin,"%c",&lf); /* toss away */
1372         if (in=='y')
1373         {
1374             fprintf(STDOUT,"type control-c\n");
1375             while(1)
1376             {
1377                 fprintf(stdout,".");
1378                 fflush(stdout);
1379                 sleep(1);
1380             }
1381         }
1382         /* or drop through */
1383     }
1384
1385     /* normal cleanup code */
1386
1387     if (entry.flags & RO_EXISTS) fprintf(STDERR,"WARNING : readOnly copies still exist \n");
1388
1389     if (islocked)
1390     {
1391         VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1392         vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, -1, 
1393                           (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1394         if (vcode) 
1395         {
1396             VPRINT("\n");
1397             fprintf(STDERR," Could not release the lock on the VLDB entry for the volume %u \n",
1398                     afromvol);
1399             if (!error) error = vcode;
1400         }
1401         VDONE;
1402     }
1403     
1404     if (fromtid) 
1405     {
1406         VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1407         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1408         if (code || rcode)
1409         {
1410             VPRINT("\n");
1411             fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n", newVol);
1412             if (!error) error = (code ? code : rcode);
1413         }
1414         VDONE;
1415     }
1416
1417     if (clonetid) 
1418     {
1419         VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1420         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1421         if (code || rcode) 
1422         {
1423             VPRINT("\n");
1424             fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",newVol);
1425             if (!error) error = (code ? code : rcode);
1426         }
1427         VDONE;
1428     }
1429
1430     if (totid) 
1431     {
1432         VPRINT1("Cleanup: Ending transaction on destination volume %u ...", afromvol);
1433         code = AFSVolEndTrans(toconn, totid, &rcode);
1434         if (code) 
1435         {
1436             VPRINT("\n");
1437             fprintf(STDERR,"Could not end transaction on destination volume %u\n",afromvol);
1438             if (!error) error = (code ? code : rcode);
1439         }
1440         VDONE;
1441     }
1442     if (volName) free(volName);
1443 #ifdef  ENABLE_BUGFIX_1165
1444     if (infop)   free(infop);
1445 #endif
1446     if (fromconn) rx_DestroyConnection(fromconn);
1447     if (toconn)   rx_DestroyConnection(toconn);
1448     PrintError("",error);
1449     return error;
1450
1451     /* come here only when the sky falls */
1452 mfail:
1453
1454     if (pntg) 
1455     {
1456         fprintf(STDOUT,"vos move: operation interrupted, cleanup in progress...\n");
1457         fprintf(STDOUT,"clear transaction contexts\n");
1458         fflush(STDOUT);
1459     }
1460
1461     /* unlock VLDB entry */
1462     if (islocked)
1463     {
1464         VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1465         ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1466                   (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1467         VDONE;
1468     }
1469
1470     if (clonetid)
1471     {
1472         VPRINT("Recovery: Ending transaction on clone volume ...");
1473         AFSVolEndTrans(fromconn, clonetid, &rcode);
1474         VDONE;
1475     }
1476     if (totid)
1477     {
1478         VPRINT("Recovery: Ending transaction on destination volume ...");
1479         AFSVolEndTrans(toconn, totid, &rcode);
1480         VDONE;
1481     }
1482     if (fromtid)
1483     {  /* put it on-line */
1484         VPRINT("Recovery: Setting volume flags on source volume ...");
1485         AFSVolSetFlags(fromconn,fromtid,0);
1486         VDONE;
1487
1488         VPRINT("Recovery: Ending transaction on source volume ...");
1489         AFSVolEndTrans(fromconn, fromtid, &rcode);
1490         VDONE;
1491     }
1492
1493     VPRINT("Recovery: Accessing VLDB.\n");
1494     vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
1495     if (vcode)
1496     {
1497         fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
1498         fflush(STDOUT);
1499         goto done;
1500     }
1501     MapHostToNetwork(&entry);
1502
1503     /* Delete either the volume on the source location or the target location. 
1504      * If the vldb entry still points to the source location, then we know the
1505      * volume move didn't finish so we remove the volume from the target 
1506      * location. Otherwise, we remove the volume from the source location.
1507      */
1508     if (Lp_Match(afromserver,afrompart,&entry)) {  /* didn't move - delete target volume */
1509         if (pntg) {
1510             fprintf(STDOUT,
1511                     "move incomplete - attempt cleanup of target partition - no guarantee\n");
1512             fflush(STDOUT);
1513         }
1514
1515         if (volid && toconn) {
1516             VPRINT1("Recovery: Creating transaction for destination volume %u ...", volid);
1517             code=AFSVolTransCreate(toconn,volid,atopart, ITOffline,&totid);
1518
1519             if (!code) {
1520                 VDONE;
1521
1522                 VPRINT1("Recovery: Setting flags on destination volume %u ...", volid);
1523                 AFSVolSetFlags(toconn,totid, VTDeleteOnSalvage | VTOutOfService);
1524                 VDONE;
1525
1526                 VPRINT1("Recovery: Deleting destination volume %u ...", volid);
1527                 AFSVolDeleteVolume(toconn,totid);
1528                 VDONE;
1529
1530                 VPRINT1("Recovery: Ending transaction on destination volume %u ...", volid);
1531                 AFSVolEndTrans(toconn,totid,&rcode);
1532                 VDONE;
1533             }
1534             else
1535             {
1536                 VPRINT1("\nRecovery: Unable to start transaction on destination volume %u.\n", afromvol);
1537             }
1538         }
1539
1540         /* put source volume on-line */
1541         if (fromconn) {
1542             VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1543             code=AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1544             if (!code) {
1545                 VDONE;
1546
1547                 VPRINT1("Recovery: Setting flags on source volume %u ...", afromvol);
1548                 AFSVolSetFlags(fromconn,fromtid,0);
1549                 VDONE;
1550
1551                 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1552                 AFSVolEndTrans(fromconn,fromtid,&rcode);
1553                 VDONE;
1554             }
1555             else
1556             {
1557                 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1558             }
1559         }
1560     }
1561     else {      /* yep, move complete */
1562         if (pntg) {
1563             fprintf(STDOUT,
1564                     "move complete - attempt cleanup of source partition - no guarantee\n");
1565             fflush(STDOUT);
1566         }
1567
1568         /* delete backup volume */
1569         if (fromconn) {
1570             VPRINT1("Recovery: Creating transaction on backup volume %u ...", backupId);
1571             code=AFSVolTransCreate (fromconn,backupId,afrompart, ITOffline,&fromtid);
1572             if (!code) {
1573                 VDONE;
1574
1575                 VPRINT1("Recovery: Setting flags on backup volume %u ...", backupId);
1576                 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1577                 VDONE;
1578
1579                 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1580                 AFSVolDeleteVolume(fromconn,fromtid);
1581                 VDONE;
1582
1583                 VPRINT1("Recovery: Ending transaction on backup volume %u ...", backupId);
1584                 AFSVolEndTrans(fromconn,fromtid,&rcode);
1585                 VDONE;
1586             }
1587             else
1588             {
1589                 VPRINT1("\nRecovery: Unable to start transaction on backup volume %u.\n", backupId);
1590             }
1591
1592             /* delete source volume */
1593             VPRINT1("Recovery: Creating transaction on source volume %u ...", afromvol);
1594             code=AFSVolTransCreate (fromconn, afromvol, afrompart, ITBusy, &fromtid);
1595             if (!code) {
1596                 VDONE;
1597
1598                 VPRINT1("Recovery: Setting flags on backup volume %u ...", afromvol);
1599                 AFSVolSetFlags(fromconn,fromtid, VTDeleteOnSalvage | VTOutOfService);
1600                 VDONE;
1601
1602                 if (atoserver != afromserver)
1603                 {
1604                     VPRINT("Recovery: Setting volume forwarding pointer ...");
1605                     AFSVolSetForwarding(fromconn,fromtid,atoserver);
1606                     VDONE;
1607                 }
1608
1609                 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1610                 AFSVolDeleteVolume(fromconn,fromtid);
1611                 VDONE;
1612
1613                 VPRINT1("Recovery: Ending transaction on source volume %u ...", afromvol);
1614                 AFSVolEndTrans(fromconn,fromtid,&rcode);
1615                 VDONE;
1616             }
1617             else
1618             {
1619                 VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1620             }
1621         }
1622     }
1623
1624     /* common cleanup - delete local clone */
1625     if (newVol) {
1626         VPRINT1("Recovery: Creating transaction on clone volume %u ...", newVol);
1627         code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
1628         if (!code) {
1629             VDONE;
1630
1631             VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1632             AFSVolDeleteVolume(fromconn,clonetid);
1633             VDONE;
1634
1635             VPRINT1("Recovery: Ending transaction on clone volume %u ...", newVol);
1636             AFSVolEndTrans(fromconn,clonetid,&rcode);
1637             VDONE;
1638         }
1639         else
1640         {
1641             VPRINT1("\nRecovery: Unable to start transaction on source volume %u.\n", afromvol);
1642         }
1643     }
1644
1645     /* unlock VLDB entry */
1646     VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...", afromvol);
1647     ubik_Call (VL_ReleaseLock, cstruct, 0, afromvol, -1,
1648                (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1649     VDONE;
1650
1651 done:   /* routine cleanup */
1652     if (volName)  free(volName);
1653 #ifdef  ENABLE_BUGFIX_1165
1654     if (infop)    free(infop);
1655 #endif
1656     if (fromconn) rx_DestroyConnection(fromconn);
1657     if (toconn)   rx_DestroyConnection(toconn);
1658
1659     if (pntg) {
1660         fprintf(STDOUT,"cleanup complete - user verify desired result\n");
1661         fflush(STDOUT);
1662     }
1663     exit(1);
1664 }
1665
1666
1667 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1668  * <atopart>. The operation is almost idempotent 
1669  */
1670
1671 int UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver, 
1672         afs_int32 afrompart, char *atovolname, afs_int32 atoserver, afs_int32 atopart)
1673 {
1674     struct rx_connection *toconn, *fromconn ;
1675     afs_int32                fromtid, totid, clonetid;
1676     char                 vname[64];
1677     char                 tmpName[VOLSER_MAXVOLNAME +1];
1678     afs_int32                rcode;
1679     afs_int32                fromDate;
1680     struct restoreCookie cookie;
1681     register afs_int32       vcode, code;
1682     afs_int32                cloneVol, newVol;
1683     struct volser_status tstatus;
1684     struct destServer    destination;
1685
1686     struct nvldbentry    entry, newentry, storeEntry;
1687     int                  i, islocked, pntg;
1688     afs_int32                error;
1689     char                 in,lf;                         /* for test code */
1690     int                  same;
1691         int justclone = 0;
1692
1693     islocked = 0;
1694     fromconn = (struct rx_connection *)0;
1695     toconn   = (struct rx_connection *)0;
1696     fromtid  = 0;
1697     totid    = 0;
1698     clonetid = 0;
1699     error    = 0;
1700     pntg     = 0;
1701     newVol   = 0;
1702
1703     /* support control-c processing */
1704     if (setjmp(env)) goto mfail;
1705     (void) signal(SIGINT,sigint_handler);
1706  
1707     vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1708     EGOTO1(mfail, vcode, "Could not fetch the entry for the volume  %u from the VLDB \n", afromvol);
1709     MapHostToNetwork(&entry);
1710
1711     pntg = 1;
1712     toconn   = UV_Bind(atoserver,   AFSCONF_VOLUMEPORT); /* get connections to the servers */
1713     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1714     fromtid = totid = 0;        /* initialize to uncreated */
1715
1716
1717         /* check if we can shortcut and use a local clone instead of a full copy */
1718         if ( afromserver == atoserver && afrompart == atopart )
1719         {
1720                 justclone = 1;
1721         }
1722
1723     /* ***
1724      * clone the read/write volume locally.
1725      * ***/
1726
1727     VPRINT1("Starting transaction on source volume %u ...", afromvol);
1728     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1729     EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n", afromvol);
1730     VDONE;
1731
1732     /* Get a clone id */
1733     VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
1734     newVol = 0;
1735     vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &cloneVol);
1736     EGOTO1(mfail, vcode, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
1737     VDONE;
1738
1739     /* Get a new volume id */
1740     VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
1741     newVol = 0;
1742     vcode = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1743     EGOTO1(mfail, vcode, "Could not get an ID for the copy of volume %u from the VLDB\n", afromvol);
1744     VDONE;
1745
1746     /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1747     VPRINT1("Cloning source volume %u ...", afromvol);
1748     strcpy(vname, "copy-clone-temp");
1749     code = AFSVolClone(fromconn, fromtid, 0,readonlyVolume, vname, &cloneVol);
1750     EGOTO1(mfail, code, "Failed to clone the source volume %u\n", afromvol);
1751     VDONE;
1752
1753     VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1754     rcode = 0;
1755     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1756     fromtid = 0;
1757     if (!code) code = rcode;
1758     EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1759     VDONE;
1760
1761     /* ***
1762      * Create the destination volume
1763      * ***/
1764
1765     VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1766     code = AFSVolTransCreate (fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1767     EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1768     VDONE;
1769
1770     VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
1771     code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
1772     EGOTO1(mfail, code, "Could not set falgs on the cloned volume %u\n", cloneVol);
1773     VDONE;
1774
1775     /* remember time from which we've dumped the volume */
1776     VPRINT1("Getting status of cloned volume %u ...", cloneVol);
1777     code = AFSVolGetStatus (fromconn, clonetid, &tstatus);
1778     EGOTO1(mfail, code, "Failed to get the status of the cloned volume %u\n", cloneVol);
1779     VDONE;
1780
1781     fromDate = tstatus.creationDate-CLOCKSKEW;
1782
1783     /* create a volume on the target machine */
1784     code = AFSVolTransCreate (toconn, newVol, atopart, ITOffline, &totid);
1785     if (!code) 
1786     {  
1787       /* Delete the existing volume.
1788        * While we are deleting the volume in these steps, the transaction
1789        * we started against the cloned volume (clonetid above) will be
1790        * sitting idle. It will get cleaned up after 600 seconds
1791        */
1792         VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
1793                 code = AFSVolDeleteVolume(toconn, totid);
1794                 EGOTO1(mfail, code, "Could not delete the pre-existing volume %u on destination\n", newVol);
1795                 VDONE;
1796
1797                 VPRINT1("Ending transaction on pre-existing volume %u on destination ...", newVol);
1798                 code = AFSVolEndTrans(toconn, totid, &rcode);
1799                 totid = 0;
1800                 if (!code) code = rcode;
1801                 EGOTO1(mfail, code, "Could not end the transaction on pre-existing volume %u on destination\n",
1802                            newVol);
1803                 VDONE;
1804     }
1805
1806     VPRINT1("Creating the destination volume %u ...", newVol);
1807     code = AFSVolCreateVolume (toconn, atopart, atovolname, volser_RW, newVol, &newVol, &totid);
1808     EGOTO1(mfail, code, "Failed to create the destination volume %u\n", newVol);
1809     VDONE;
1810
1811     strncpy(tmpName, atovolname, VOLSER_OLDMAXVOLNAME);
1812
1813     VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1814     code = AFSVolSetFlags (toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1815     EGOTO1(mfail, code, "Failed to set the flags on the destination volume %u\n", newVol);
1816     VDONE;
1817
1818     /***
1819      * Now dump the clone to the new volume
1820      ***/
1821
1822     destination.destHost = ntohl(atoserver);
1823     destination.destPort = AFSCONF_VOLUMEPORT;
1824     destination.destSSID = 1;
1825
1826
1827 /* probably should have some code here that checks to see if we are copying to same server
1828 and partition - if so, just use a clone to save disk space */
1829
1830     /* Copy the clone to the new volume */
1831     VPRINT2("Dumping from clone %u on source to volume %u on destination ...", cloneVol, newVol);
1832     strncpy(cookie.name,tmpName,VOLSER_OLDMAXVOLNAME);
1833     cookie.type   = RWVOL;
1834     cookie.parent = 0;
1835     cookie.clone  = 0;
1836     code = AFSVolForward(fromconn, clonetid, 0, &destination, totid, &cookie);
1837     EGOTO1(mfail, code, "Failed to move data for the volume %u\n", newVol);
1838     VDONE;
1839
1840     VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1841     code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1842     if (!code) code = rcode;
1843     clonetid = 0;
1844     EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1845     VDONE;
1846
1847     /* ***
1848      * reattach to the main-line volume, and incrementally dump it.
1849      * ***/
1850
1851     VPRINT1("Starting transaction on source volume %u ...", afromvol);
1852     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1853     EGOTO1(mfail, code, "Failed to create a transaction on the source volume %u\n", afromvol);
1854     VDONE;
1855
1856     /* now do the incremental */
1857     VPRINT1("Doing the incremental dump from source to destination for volume %u ... ", afromvol);
1858     code = AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,&cookie);
1859     EGOTO(mfail, code, "Failed to do the incremental dump from rw volume on old site to rw volume on newsite\n");
1860     VDONE;
1861
1862     VPRINT1("Setting volume flags on destination volume %u ...", newVol);
1863     code = AFSVolSetFlags(toconn, totid, 0);
1864     EGOTO(mfail, code, "Failed to set the flags to make destination volume online\n");
1865     VDONE;
1866
1867     /* put new volume online */
1868     VPRINT1("Ending transaction on destination volume %u ...", newVol);
1869     code = AFSVolEndTrans(toconn, totid, &rcode);
1870     totid = 0;
1871     if (!code) code = rcode;
1872     EGOTO1(mfail, code, "Failed to end the transaction on the destination volume %u\n", newVol);
1873     VDONE;
1874
1875     VPRINT1("Ending transaction on source volume %u ...", afromvol);
1876     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1877     fromtid = 0;
1878     if (!code) code = rcode;
1879     EGOTO1(mfail, code, "Failed to end the transaction on the source volume %u\n", afromvol);
1880     VDONE;
1881
1882     fromtid = 0;
1883     VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
1884     code = AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline, &clonetid);
1885     EGOTO1(mfail, code, "Failed to start a transaction on the cloned volume%u\n", cloneVol);
1886     VDONE;
1887     
1888     /* now delete the clone */
1889     VPRINT1("Deleting the cloned volume %u ...", cloneVol);
1890     code = AFSVolDeleteVolume(fromconn, clonetid);
1891     EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", cloneVol);
1892     VDONE;
1893     
1894     VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
1895     code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1896     if (!code) code = rcode;
1897     clonetid = 0;
1898     EGOTO1(mfail, code, "Failed to end the transaction on the cloned volume %u\n", cloneVol);
1899     VDONE;
1900
1901         /* create the vldb entry for the copied volume */
1902     strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
1903     newentry.nServers = 1;
1904     newentry.serverNumber[0] = atoserver;
1905     newentry.serverPartition[0] = atopart;
1906     newentry.flags = RW_EXISTS;/* this records that rw volume exists */
1907     newentry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
1908     newentry.volumeId[RWVOL] = newVol;
1909     newentry.volumeId[ROVOL] = 0;
1910     newentry.volumeId[BACKVOL] = 0;
1911     newentry.cloneId = 0;
1912     /*map into right byte order, before passing to xdr, the stuff has to be in host
1913       byte order. Xdr converts it into network order */
1914     MapNetworkToHost(&newentry,&storeEntry);
1915     /* create the vldb entry */
1916     vcode = VLDB_CreateEntry(&storeEntry);
1917     if(vcode) {
1918                 fprintf(STDERR,"Could not create a VLDB entry for the volume %s %u\n", atovolname,newVol);
1919                 /*destroy the created volume*/
1920                 VPRINT1("Deleting the newly created volume %u\n",newVol);
1921                 AFSVolDeleteVolume(toconn,totid);
1922                 error = vcode;
1923                 goto mfail;
1924     }
1925     VPRINT2("Created the VLDB entry for the volume %s %u\n",atovolname,newVol);
1926
1927     /* normal cleanup code */
1928     
1929     if (fromtid) 
1930     {
1931         VPRINT1("Cleanup: Ending transaction on source volume %u ...", afromvol);
1932         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1933         if (code || rcode)
1934         {
1935             VPRINT("\n");
1936             fprintf(STDERR,"Could not end transaction on the source volume %u\n", afromvol);
1937             if (!error) error = (code ? code : rcode);
1938         }
1939         VDONE;
1940     }
1941
1942     if (clonetid) 
1943     {
1944         VPRINT1("Cleanup: Ending transaction on clone volume %u ...", cloneVol);
1945         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1946         if (code || rcode) 
1947         {
1948             VPRINT("\n");
1949             fprintf(STDERR,"Could not end transaction on the source's clone volume %u\n",cloneVol);
1950             if (!error) error = (code ? code : rcode);
1951         }
1952         VDONE;
1953     }
1954
1955     if (totid) 
1956     {
1957         VPRINT1("Cleanup: Ending transaction on destination volume %u ...", newVol);
1958         code = AFSVolEndTrans(toconn, totid, &rcode);
1959         if (code) 
1960         {
1961             VPRINT("\n");
1962             fprintf(STDERR,"Could not end transaction on destination volume %u\n", newVol);
1963             if (!error) error = (code ? code : rcode);
1964         }
1965         VDONE;
1966     }
1967     if (fromconn) rx_DestroyConnection(fromconn);
1968     if (toconn)   rx_DestroyConnection(toconn);
1969     PrintError("",error);
1970     return error;
1971
1972     /* come here only when the sky falls */
1973 mfail:
1974
1975     if (pntg) 
1976     {
1977         fprintf(STDOUT,"vos copy: operation interrupted, cleanup in progress...\n");
1978         fprintf(STDOUT,"clear transaction contexts\n");
1979         fflush(STDOUT);
1980     }
1981
1982     if (clonetid)
1983     {
1984         VPRINT("Recovery: Ending transaction on clone volume ...");
1985         AFSVolEndTrans(fromconn, clonetid, &rcode);
1986         VDONE;
1987     }
1988     if (totid)
1989     {
1990         VPRINT("Recovery: Ending transaction on destination volume ...");
1991         AFSVolEndTrans(toconn, totid, &rcode);
1992         VDONE;
1993     }
1994     if (fromtid)
1995     {  /* put it on-line */
1996                 VPRINT("Recovery: Ending transaction on source volume ...");
1997                 AFSVolEndTrans(fromconn, fromtid, &rcode);
1998                 VDONE;
1999     }
2000
2001     VPRINT("Recovery: Accessing VLDB.\n");
2002     vcode= VLDB_GetEntryByID (afromvol, -1, &entry);
2003     if (vcode)
2004     {
2005         fprintf(STDOUT,"FATAL: VLDB access error: abort cleanup\n");
2006         fflush(STDOUT);
2007         goto done;
2008     }
2009     MapHostToNetwork(&entry);
2010
2011     /* common cleanup - delete local clone */
2012     if (cloneVol) {
2013         VPRINT1("Recovery: Creating transaction on clone volume %u ...", cloneVol);
2014         code = AFSVolTransCreate (fromconn, newVol, afrompart, ITOffline, &clonetid);
2015         if (!code) {
2016             VDONE;
2017
2018             VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2019             AFSVolDeleteVolume(fromconn,clonetid);
2020             VDONE;
2021
2022             VPRINT1("Recovery: Ending transaction on clone volume %u ...", cloneVol);
2023             AFSVolEndTrans(fromconn,clonetid,&rcode);
2024             VDONE;
2025         }
2026         else
2027         {
2028             VPRINT1("\nRecovery: Unable to start transaction on clone volume %u.\n", cloneVol);
2029         }
2030     }
2031
2032 done:   /* routine cleanup */
2033     if (fromconn) rx_DestroyConnection(fromconn);
2034     if (toconn)   rx_DestroyConnection(toconn);
2035
2036     if (pntg) {
2037         fprintf(STDOUT,"cleanup complete - user verify desired result\n");
2038         fflush(STDOUT);
2039     }
2040     exit(1);
2041 }
2042
2043
2044
2045
2046
2047 /* Make a new backup of volume <avolid> on <aserver> and <apart> 
2048  * if one already exists, update it 
2049  */
2050
2051 int UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2052 {
2053     struct rx_connection *aconn = (struct rx_connection *)0;
2054     afs_int32 ttid = 0, btid = 0;
2055     afs_int32 backupID;
2056     afs_int32 code = 0, rcode = 0;
2057     char vname[VOLSER_MAXVOLNAME +1];
2058     struct nvldbentry entry, storeEntry;
2059     afs_int32 error = 0;
2060     int vldblocked = 0, vldbmod = 0, backexists = 1;
2061
2062     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2063
2064     /* the calls to VLDB will succeed only if avolid is a RW volume,
2065      * since we are following the RW hash chain for searching */
2066     code = VLDB_GetEntryByID(avolid, RWVOL, &entry); 
2067     if (code) {
2068        fprintf(STDERR, "Could not fetch the entry for the volume %u from the VLDB \n", avolid);
2069        error = code; goto bfail;
2070     }
2071     MapHostToNetwork(&entry); 
2072
2073     /* These operations require the VLDB be locked since it means the VLDB
2074      * will change or the vldb is already locked.
2075      */
2076     if (!(entry.flags & BACK_EXISTS)   ||               /* backup volume doesnt exist */
2077          (entry.flags & VLOP_ALLOPERS) ||               /* vldb lock already held */
2078          (entry.volumeId[BACKVOL] == INVALID_BID)) {    /* no assigned backup volume id */
2079
2080        code = ubik_Call(VL_SetLock,cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2081        if (code) {
2082           fprintf(STDERR,"Could not lock the VLDB entry for the volume %u\n",avolid);
2083           error = code;
2084           goto bfail;
2085        }
2086        vldblocked = 1;
2087
2088        /* Reread the vldb entry */
2089        code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2090        if (code) {
2091           fprintf(STDERR,"Could not fetch the entry for the volume %u from the VLDB \n",avolid);
2092           error = code;
2093           goto bfail;
2094        }
2095        MapHostToNetwork(&entry);
2096     }
2097
2098     if (!ISNAMEVALID(entry.name)) {
2099        fprintf(STDERR, "Name of the volume %s exceeds the size limit\n", entry.name);
2100        error = VOLSERBADNAME;
2101        goto bfail;
2102     }
2103
2104     backupID = entry.volumeId[BACKVOL];
2105     if (backupID == INVALID_BID) {
2106        /* Get a backup volume id from the VLDB and update the vldb
2107         * entry with it. 
2108         */
2109        code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
2110        if (code) {
2111           fprintf(STDERR,
2112                   "Could not allocate ID for the backup volume of  %u from the VLDB\n",
2113                   avolid);
2114           error = code;
2115           goto bfail;
2116        }
2117        entry.volumeId[BACKVOL] = backupID;
2118        vldbmod = 1;
2119     }
2120
2121     /* Test to see if the backup volume exists by trying to create
2122      * a transaction on the backup volume. We've assumed the backup exists.
2123      */
2124     code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2125     if (code) {
2126        if (code != VNOVOL) {
2127           fprintf(STDERR,"Could not reach the backup volume %u\n", backupID);
2128           error = code;
2129           goto bfail;
2130        }
2131        backexists = 0;                 /* backup volume does not exist */
2132     }
2133     if (btid) {
2134        code = AFSVolEndTrans(aconn, btid, &rcode);
2135        btid = 0;
2136        if (code || rcode) {
2137           fprintf(STDERR,
2138                   "Could not end transaction on the previous backup volume %u\n",
2139                   backupID);
2140           error = (code ? code : rcode);
2141           goto bfail;
2142        }
2143     }
2144
2145     /* Now go ahead and try to clone the RW volume.
2146      * First start a transaction on the RW volume 
2147      */
2148     code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2149     if (code) {
2150        fprintf(STDERR,"Could not start a transaction on the volume %u\n",avolid);
2151        error = code;
2152        goto bfail;
2153     }
2154
2155     /* Clone or reclone the volume, depending on whether the backup 
2156      * volume exists or not
2157      */
2158     if (backexists) {
2159        VPRINT1("Re-cloning backup volume %u ...", backupID);
2160
2161        code = AFSVolReClone(aconn, ttid, backupID);
2162        if (code) {
2163           fprintf(STDERR,"Could not re-clone backup volume %u\n", backupID);
2164           error = code;
2165           goto bfail;
2166        }
2167     }
2168     else {
2169        VPRINT1("Creating a new backup clone %u ...", backupID);
2170
2171        strcpy(vname, entry.name);
2172        strcat(vname,".backup");
2173
2174        code = AFSVolClone(aconn, ttid, 0,backupVolume, vname, &backupID);
2175        if (code) {
2176           fprintf(STDERR,"Failed to clone the volume %u\n",avolid);
2177           error = code;
2178           goto bfail;
2179        }
2180     }
2181
2182     /* End the transaction on the RW volume */
2183     code = AFSVolEndTrans(aconn, ttid, &rcode);
2184     ttid = 0;
2185     if (code || rcode) {
2186         fprintf(STDERR, "Failed to end the transaction on the rw volume %u\n", avolid); 
2187         error = (code ? code : rcode);
2188         goto bfail;
2189     }
2190
2191     /* Mork vldb as backup exists */
2192     if (!(entry.flags & BACK_EXISTS)) {
2193        entry.flags |= BACK_EXISTS;
2194        vldbmod = 1;
2195     }
2196
2197     /* Now go back to the backup volume and bring it on line */
2198     code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2199     if (code) {
2200         fprintf(STDERR,"Failed to start a transaction on the backup volume %u\n",backupID); 
2201         error = code;
2202         goto bfail;
2203     }
2204
2205     code = AFSVolSetFlags(aconn, btid, 0);
2206     if (code) {
2207         fprintf(STDERR,"Could not mark the backup volume %u on line \n",backupID);
2208         error = code;
2209         goto bfail;
2210     }
2211
2212     code = AFSVolEndTrans(aconn, btid, &rcode);
2213     btid = 0;
2214     if (code || rcode) {
2215         fprintf(STDERR, "Failed to end the transaction on the backup volume %u\n", backupID);
2216         error = (code ? code : rcode);
2217         goto bfail;
2218     }
2219
2220     VDONE;
2221
2222     /* Will update the vldb below */
2223
2224   bfail:
2225     if (ttid) {
2226        code =  AFSVolEndTrans(aconn, ttid, &rcode);
2227        if (code || rcode) {
2228           fprintf(STDERR, "Could not end transaction on the volume %u\n", avolid);
2229           if (!error)
2230              error = (code ? code : rcode);
2231        }
2232     }
2233
2234     if (btid) {
2235        code = AFSVolEndTrans(aconn, btid, &rcode);
2236        if (code || rcode) {
2237           fprintf(STDERR,"Could not end transaction the backup volume %u\n",backupID);
2238           if (!error)
2239              error = (code ? code : rcode);
2240        }
2241     }
2242
2243     /* Now update the vldb - if modified */
2244     if (vldblocked) {
2245        if (vldbmod) {
2246           MapNetworkToHost(&entry,&storeEntry);
2247           code = VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2248                                     (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2249           if (code) {
2250              fprintf(STDERR,"Could not update the VLDB entry for the volume %u \n",avolid);
2251              if (!error)
2252                 error = code;
2253           }
2254        }
2255        else {
2256           code = ubik_Call(VL_ReleaseLock,cstruct, 0, avolid, RWVOL, 
2257                            (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
2258           if (code) {
2259              fprintf(STDERR,"Could not unlock the VLDB entry for the volume %u \n",avolid);
2260              if (!error)
2261                 error = code;
2262           }
2263        }
2264     }
2265
2266     if (aconn)
2267        rx_DestroyConnection(aconn);
2268
2269     PrintError("",error);
2270     return error;
2271 }
2272
2273 static int DelVol (struct rx_connection *conn, afs_int32 vid, afs_int32 part, afs_int32 flags)
2274 {
2275   afs_int32 acode, ccode, rcode, tid;
2276   ccode = rcode = tid = 0;
2277
2278   acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2279   if (!acode) {              /* It really was there */
2280     acode = AFSVolDeleteVolume(conn, tid);
2281     if (acode) {
2282       fprintf(STDERR, "Failed to delete volume %u.\n", vid);
2283       PrintError ("", acode);
2284     }
2285     ccode = AFSVolEndTrans(conn, tid, &rcode);
2286     if (!ccode) 
2287       ccode = rcode;
2288     if (ccode) {
2289       fprintf(STDERR, "Failed to end transaction on volume %u.\n", vid);
2290       PrintError ("", ccode);
2291     }
2292   }
2293
2294 return acode;
2295 }
2296
2297 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
2298 #define ERROREXIT(ec) { error = (ec); goto rfail; }
2299
2300 /* Get a "transaction" on this replica.  Create the volume 
2301  * if necessary.  Return the time from which a dump should
2302  * be made (0 if it's a new volume)
2303  */
2304 static int GetTrans (struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr, 
2305         afs_int32 *transPtr, afs_int32 *timePtr)
2306 {
2307   afs_int32 volid;
2308   struct volser_status tstatus;
2309   int code, rcode, tcode;
2310   
2311   *connPtr  = (struct rx_connection *)0;
2312   *timePtr  = 0;
2313   *transPtr = 0;
2314
2315   /* get connection to the replication site */
2316   *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
2317   if (!*connPtr) goto fail;                                   /* server is down */
2318
2319   volid = vldbEntryPtr->volumeId[ROVOL];
2320   if (volid) 
2321     code = AFSVolTransCreate(*connPtr, volid, vldbEntryPtr->serverPartition[index], 
2322                              ITOffline, transPtr);
2323
2324   /* If the volume does not exist, create it */
2325   if (!volid || code) {
2326       char volname[64];
2327
2328       if (volid && (code != VNOVOL)){
2329           PrintError("Failed to start a transaction on the RO volume.\n",
2330                      code);
2331           goto fail;
2332       }
2333
2334       strcpy(volname, vldbEntryPtr->name);
2335       strcat(volname, ".readonly");
2336       
2337       if (verbose) {
2338           fprintf(STDOUT,"Creating new volume %u on replication site %s: ", 
2339                   volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2340           fflush(STDOUT);
2341       }
2342
2343       code = AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index], 
2344                                 volname, volser_RO,
2345                                 vldbEntryPtr->volumeId[RWVOL], &volid, transPtr);
2346       if (code) {
2347           PrintError("Failed to create the ro volume: ",code);
2348           goto fail;
2349       }
2350       vldbEntryPtr->volumeId[ROVOL] = volid;
2351
2352       VDONE;
2353
2354       /* The following is a bit redundant, since create sets these flags by default */
2355       code = AFSVolSetFlags(*connPtr, *transPtr, VTDeleteOnSalvage | VTOutOfService);
2356       if (code) {
2357           PrintError("Failed to set flags on the ro volume: ", code);
2358           goto fail;
2359       }
2360   }
2361
2362   /* Otherwise, the transaction did succeed, so get the creation date of the
2363    * latest RO volume on the replication site 
2364    */
2365   else {
2366       VPRINT2("Updating existing ro volume %u on %s ...\n",
2367           volid, hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
2368
2369       code  = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
2370       if (code) {
2371           PrintError("Failed to get status of volume on destination: ",code);
2372           goto fail;
2373       }
2374       *timePtr = tstatus.creationDate-CLOCKSKEW;
2375   }
2376   
2377   return 0;
2378
2379  fail:
2380   if (*transPtr) {
2381       tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
2382       *transPtr = 0;
2383       if (!tcode) tcode = rcode;
2384       if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode);
2385   }
2386
2387   return code;
2388 }
2389
2390 static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid, 
2391         afs_int32 fromdate, manyDests *tr, afs_int32 flags, void *cookie, manyResults *results)
2392 {
2393   int i;
2394
2395   for (i=0; i<tr->manyDests_len; i++) {
2396      results->manyResults_val[i] = AFSVolForward(fromconn, fromtid,
2397                                     fromdate, &(tr->manyDests_val[i].server), 
2398                                     tr->manyDests_val[i].trans, cookie);
2399   }
2400   return 0;
2401 }
2402
2403
2404 static int rel_compar (struct release *r1, struct release *r2)
2405 {
2406   return (r1->time - r2->time);
2407 }
2408
2409 /* UV_ReleaseVolume()
2410  *    Release volume <afromvol> on <afromserver> <afrompart> to all
2411  *    its RO sites (full release). Unless the previous release was
2412  *    incomplete: in which case we bring the remaining incomplete
2413  *    volumes up to date with the volumes that were released
2414  *    successfully.
2415  *    forceflag: Performs a full release.
2416  *
2417  *    Will create a clone from the RW, then dump the clone out to 
2418  *    the remaining replicas. If there is more than 1 RO sites,
2419  *    ensure that the VLDB says at least one RO is available all
2420  *    the time: Influences when we write back the VLDB entry.
2421  */
2422
2423 int UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, int forceflag)
2424 {
2425   char vname[64];
2426   afs_int32 code, vcode, rcode, tcode;
2427   afs_int32 cloneVolId, roVolId;
2428   struct replica *replicas=0;
2429   struct nvldbentry entry,storeEntry;
2430   int i, volcount, m, fullrelease, vldbindex;
2431   int failure;
2432   struct restoreCookie cookie;
2433   struct rx_connection **toconns=0;
2434   struct release *times=0;
2435   int nservers = 0;
2436   struct rx_connection *fromconn = (struct rx_connection *)0;
2437   afs_int32 error = 0;
2438   int islocked = 0;
2439   afs_int32 clonetid=0, onlinetid;
2440   afs_int32 fromtid=0;
2441   afs_uint32 fromdate, thisdate;
2442   int s;
2443   manyDests tr;
2444   manyResults results;
2445   int rwindex, roindex, roclone, roexists;
2446   afs_int32 rwcrdate;
2447   struct rtime {
2448     int     validtime;
2449     afs_uint32 time;
2450   } remembertime[NMAXNSERVERS];
2451   int releasecount = 0;
2452   struct volser_status volstatus;
2453
2454   memset((char *)remembertime, 0, sizeof(remembertime));
2455   memset((char *)&results, 0, sizeof(results));
2456
2457   vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
2458   if (vcode != VL_RERELEASE) 
2459       ONERROR(vcode, afromvol, "Could not lock the VLDB entry for the volume %u.\n");
2460   islocked = 1;
2461
2462   /* Get the vldb entry in readable format */
2463   vcode = VLDB_GetEntryByID (afromvol, RWVOL, &entry);
2464   ONERROR(vcode, afromvol, "Could not fetch the entry for the volume %u from the VLDB.\n");
2465   MapHostToNetwork(&entry);
2466
2467   if (verbose)
2468      EnumerateEntry(&entry);
2469
2470   if (!ISNAMEVALID(entry.name))
2471     ONERROR(VOLSERBADOP, entry.name, 
2472             "Volume name %s is too long, rename before releasing.\n");
2473   if (entry.volumeId[RWVOL] != afromvol)
2474     ONERROR(VOLSERBADOP, afromvol, 
2475             "The volume %u being released is not a read-write volume.\n");
2476   if (entry.nServers <= 1)  
2477     ONERROR(VOLSERBADOP, afromvol, 
2478             "Volume %u has no replicas - release operation is meaningless!\n");
2479   if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10)) 
2480     ONERROR(VOLSERBADOP, entry.name, 
2481             "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
2482
2483   /* roclone is true if one of the RO volumes is on the same
2484    * partition as the RW volume. In this case, we make the RO volume
2485    * on the same partition a clone instead of a complete copy.
2486    */
2487   
2488   roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
2489   roclone = ((roindex == -1) ? 0 : 1);
2490   rwindex = Lp_GetRwIndex(&entry);
2491   if (rwindex < 0)
2492      ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
2493
2494   /* Make sure we have a RO volume id to work with */
2495   if (entry.volumeId[ROVOL] == INVALID_BID) {
2496       /* need to get a new RO volume id */
2497       vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
2498       ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n"); 
2499
2500       entry.volumeId[ROVOL] = roVolId;
2501       MapNetworkToHost(&entry, &storeEntry);
2502       vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2503       ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2504   }
2505
2506   /* Will we be completing a previously unfinished release. -force overrides */
2507   for (fullrelease=1, i=0; (fullrelease && (i<entry.nServers)); i++) {
2508      if (entry.serverFlags[i] & NEW_REPSITE)
2509         fullrelease = 0;
2510   }
2511   if (forceflag && !fullrelease)
2512     fullrelease = 1;
2513
2514   /* Determine which volume id to use and see if it exists */
2515   cloneVolId = ((fullrelease || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
2516   code = VolumeExists(afromserver, afrompart, cloneVolId);
2517   roexists = ((code == ENODEV) ? 0 : 1);
2518   if (!roexists && !fullrelease)
2519      fullrelease = 1;      /* Do a full release if RO clone does not exist */
2520
2521   if (verbose) {
2522      if (fullrelease) {
2523         fprintf(STDOUT,"This is a complete release of the volume %u\n", afromvol);
2524      } else {
2525         fprintf(STDOUT,"This is a completion of the previous release\n");
2526      }
2527   }
2528      
2529   fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2530   if (!fromconn) 
2531      ONERROR(-1, afromserver, "Cannot establish connection with server 0x%x\n");
2532   
2533   if (fullrelease) {
2534      /* If the RO clone exists, then if the clone is a temporary
2535       * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2536       * (it was recently added), then also delete it. We do not
2537       * want to "reclone" a temporary RO clone.
2538       */
2539      if ( roexists && 
2540          (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE)) ) {
2541         code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2542         if (code && (code != VNOVOL))
2543            ERROREXIT(code);
2544         roexists = 0;
2545      }
2546
2547      /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2548       * write this entry out to the vlserver until after the first
2549       * RO volume is released (temp RO clones don't count).
2550       */
2551      for (i=0; i<entry.nServers; i++) {
2552         entry.serverFlags[i] &= ~NEW_REPSITE;
2553         entry.serverFlags[i] |=  RO_DONTUSE;
2554      }
2555      entry.serverFlags[rwindex] |=  NEW_REPSITE;
2556      entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2557       
2558      /* Begin transaction on RW and mark it busy while we clone it */
2559      code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &clonetid);
2560      ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2561
2562      /* Clone or reclone the volume */
2563      if (roexists) {
2564         VPRINT1("Recloning RW volume %u...", cloneVolId);
2565         code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2566         ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2567         VDONE;
2568      } else {
2569         if (roclone) {
2570            strcpy(vname, entry.name);
2571            strcat(vname, ".readonly");
2572            VPRINT("Cloning RW volume %u to permanent RO...");
2573         } else {
2574            strcpy(vname, "readonly-clone-temp");
2575            VPRINT("Cloning RW volume %u to temporary RO...");
2576         }
2577         code = AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, &cloneVolId);
2578         ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
2579         VDONE;
2580      }
2581
2582      /* Get the time the RW was created for future information */
2583      VPRINT1("Getting status of RW volume %u...", cloneVolId);
2584      code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
2585      ONERROR(code, cloneVolId, "Failed to get the status of the RW volume %u\n");
2586      VDONE;
2587      rwcrdate = volstatus.creationDate;
2588
2589      /* End the transaction on the RW volume */
2590      VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
2591      code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2592      clonetid = 0;
2593      ONERROR((code?code:rcode), cloneVolId, "Failed to end cloning transaction on RW %u\n");
2594      VDONE;
2595
2596      /* Remember clone volume ID in case we fail or are interrupted */
2597      entry.cloneId = cloneVolId;
2598
2599      if (roclone) {
2600         /* Bring the RO clone online - though not if it's a temporary clone */
2601         VPRINT1("Starting transaction on RO clone volume %u...", cloneVolId);
2602         code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline, &onlinetid);
2603         ONERROR(code, cloneVolId, "Failed to start transaction on volume %u\n");
2604         VDONE;
2605
2606         VPRINT1("Setting volume flags for volume %u...", cloneVolId);
2607         tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
2608         VDONE;
2609
2610         VPRINT1("Ending transaction on volume %u...", cloneVolId);
2611         code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
2612         ONERROR((code?code:rcode), cloneVolId, "Failed to end transaction on RO clone %u\n");
2613         VDONE;
2614
2615         ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
2616
2617         /* Sleep so that a client searching for an online volume won't
2618          * find the clone offline and then the next RO offline while the 
2619          * release brings the clone online and the next RO offline (race).
2620          * There is a fix in the 3.4 client that does not need this sleep
2621          * anymore, but we don't know what clients we have.
2622          */
2623         if (entry.nServers > 2)
2624            sleep(5);
2625
2626         /* Mark the RO clone in the VLDB as a good site (already released)*/
2627         entry.serverFlags[roindex] |=  NEW_REPSITE;
2628         entry.serverFlags[roindex] &= ~RO_DONTUSE;
2629         entry.flags                |=  RO_EXISTS;
2630
2631         releasecount++;
2632
2633         /* Write out the VLDB entry only if the clone is not a temporary
2634          * clone. If we did this to a temporary clone then we would end
2635          * up marking all the ROs as "old release" making the ROs
2636          * temporarily unavailable.
2637          */
2638         MapNetworkToHost(&entry, &storeEntry);
2639         VPRINT1("Replacing VLDB entry for %s...", entry.name);
2640         vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2641         ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
2642         VDONE;
2643      }
2644   }  
2645
2646   /* Now we will release from the clone to the remaining RO replicas.
2647    * The first 2 ROs (counting the non-temporary RO clone) are released
2648    * individually: releasecount. This is to reduce the race condition
2649    * of clients trying to find an on-line RO volume. The remaining ROs
2650    * are released in parallel but no more than half the number of ROs
2651    * (rounded up) at a time: nservers.
2652    */
2653
2654   strcpy(vname, entry.name);
2655   strcat(vname, ".readonly");
2656   memset(&cookie, 0, sizeof(cookie));
2657   strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
2658   cookie.type   = ROVOL;
2659   cookie.parent = entry.volumeId[RWVOL];
2660   cookie.clone  = 0;
2661
2662   nservers = entry.nServers/2;           /* how many to do at once, excluding clone */
2663   replicas   = (struct replica *)        malloc (sizeof(struct replica)*nservers+1);
2664   times      = (struct release *)        malloc (sizeof(struct release)*nservers+1);
2665   toconns    = (struct rx_connection **) malloc (sizeof(struct rx_connection *)*nservers+1);
2666   results.manyResults_val = (afs_int32 *)    malloc (sizeof(afs_int32)*nservers+1);
2667   if ( !replicas || !times || !! !results.manyResults_val || !toconns ) 
2668       ONERROR(ENOMEM, 0, "Failed to create transaction on the release clone\n");
2669
2670   memset(replicas, 0, (sizeof(struct replica)*nservers+1));
2671   memset(times, 0, (sizeof(struct release)*nservers+1));
2672   memset(toconns, 0, (sizeof(struct rx_connection *)*nservers+1));
2673   memset(results.manyResults_val, 0, (sizeof(afs_int32)*nservers+1));
2674
2675   /* Create a transaction on the cloned volume */
2676   VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
2677   code = AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
2678   if (!fullrelease && code)
2679      ONERROR(VOLSERNOVOL, afromvol,"Old clone is inaccessible. Try vos release -f %u.\n");
2680   ONERROR(code, 0, "Failed to create transaction on the release clone\n");
2681   VDONE;
2682
2683   /* For each index in the VLDB */
2684   for (vldbindex=0; vldbindex<entry.nServers; ) {
2685
2686      /* Get a transaction on the replicas. Pick replacas which have an old release. */
2687      for (volcount=0; ((volcount<nservers) && (vldbindex<entry.nServers)); vldbindex++) {
2688         /* The first two RO volumes will be released individually.
2689          * The rest are then released in parallel. This is a hack
2690          * for clients not recognizing right away when a RO volume
2691          * comes back on-line.
2692          */
2693         if ((volcount == 1) && (releasecount < 2))
2694            break;
2695
2696         if (vldbindex == roindex) continue;              /* the clone    */
2697         if ( (entry.serverFlags[vldbindex] & NEW_REPSITE) &&
2698             !(entry.serverFlags[vldbindex] & RO_DONTUSE) ) continue;
2699         if (!(entry.serverFlags[vldbindex] & ITSROVOL)) continue;  /* not a RO vol */
2700
2701
2702         /* Get a Transaction on this replica. Get a new connection if
2703          * necessary.  Create the volume if necessary.  Return the
2704          * time from which the dump should be made (0 if it's a new
2705          * volume).  Each volume might have a different time. 
2706          */
2707         replicas[volcount].server.destHost = ntohl(entry.serverNumber[vldbindex]);
2708         replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
2709         replicas[volcount].server.destSSID = 1;
2710         times[volcount].vldbEntryIndex = vldbindex;
2711         
2712         code = GetTrans(&entry, vldbindex, &(toconns[volcount]), 
2713                         &(replicas[volcount].trans), &(times[volcount].time));
2714         if (code) continue;
2715
2716         /* Thisdate is the date from which we want to pick up all changes */
2717         if (forceflag || !fullrelease || (rwcrdate > times[volcount].time)) {
2718            /* If the forceflag is set, then we want to do a full dump.
2719             * If it's not a full release, we can't be sure that the creation
2720             *  date is good (so we also do a full dump).
2721             * If the RW volume was replaced (its creation date is newer than
2722             *  the last release), then we can't be sure what has changed (so
2723             *  we do a full dump).
2724             */
2725            thisdate = 0;
2726         } else if (remembertime[vldbindex].validtime) {
2727            /* Trans was prev ended. Use the time from the prev trans
2728             * because, prev trans may have created the volume. In which
2729             * case time[volcount].time would be now instead of 0.
2730             */
2731            thisdate  = (remembertime[vldbindex].time < times[volcount].time) ? 
2732                         remembertime[vldbindex].time : times[volcount].time;
2733         } else {
2734            thisdate = times[volcount].time;
2735         }         
2736         remembertime[vldbindex].validtime = 1;
2737         remembertime[vldbindex].time = thisdate;
2738
2739         if (volcount == 0) {
2740            fromdate = thisdate;
2741         } else {
2742            /* Include this volume if it is within 15 minutes of the earliest */
2743            if (((fromdate>thisdate)?(fromdate-thisdate):(thisdate-fromdate)) > 900) {
2744               AFSVolEndTrans(toconns[volcount], replicas[volcount].trans, &rcode);
2745               replicas[volcount].trans = 0;
2746               break;
2747            }
2748            if (thisdate < fromdate)
2749               fromdate = thisdate;
2750         }
2751         volcount++;
2752      }
2753      if (!volcount) continue;
2754
2755      if (verbose) {
2756         fprintf(STDOUT,"Starting ForwardMulti from %u to %u on %s",
2757                 cloneVolId, entry.volumeId[ROVOL], 
2758                 hostutil_GetNameByINet(entry.serverNumber[times[0].vldbEntryIndex]));
2759
2760         for (s=1; s<volcount; s++) {
2761            fprintf(STDOUT," and %s",
2762                    hostutil_GetNameByINet(entry.serverNumber[times[s].vldbEntryIndex]));
2763         }
2764
2765         if (fromdate == 0)
2766            fprintf(STDOUT," (full release)");
2767         fprintf(STDOUT,".\n");
2768         fflush(STDOUT);
2769      }
2770
2771      /* Release the ones we have collected */
2772      tr.manyDests_val = &(replicas[0]);
2773      tr.manyDests_len = results.manyResults_len = volcount;
2774      code = AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2775      if (code == RXGEN_OPCODE) {               /* RPC Interface Mismatch */
2776         code = SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr, 0/*spare*/, &cookie, &results);
2777         nservers = 1;
2778      }
2779
2780      if (code) {
2781         PrintError("Release failed: ", code);
2782      } else {
2783         for (m=0; m<volcount; m++) {
2784            if (results.manyResults_val[m]) {
2785               if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
2786                  /* we retry timed out transaction. When it is
2787                   * not the first volume and the transaction wasn't found
2788                   * (assume it timed out and was garbage collected by volser).
2789                   */
2790                  PrintError("Failed to dump volume from clone to a ro site: ",
2791                             results.manyResults_val[m]);
2792               }
2793               continue;
2794            }
2795             
2796            code = AFSVolSetIdsTypes(toconns[m], replicas[m].trans, 
2797                                     vname, ROVOL, entry.volumeId[RWVOL], 0, 0);
2798            if (code) {
2799               if ((m == 0) || (code != ENOENT)) {
2800                  PrintError("Failed to set correct names and ids: ", code);
2801               }
2802               continue;
2803            }
2804
2805            /* have to clear dest. flags to ensure new vol goes online:
2806             * because the restore (forwarded) operation copied
2807             * the V_inService(=0) flag over to the destination. 
2808             */
2809            code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
2810            if (code) {
2811               if ((m == 0) || (code != ENOENT)) {
2812                  PrintError("Failed to set flags on ro volume: ", code);
2813               }
2814               continue;
2815            }
2816
2817            entry.serverFlags[times[m].vldbEntryIndex] |=  NEW_REPSITE;
2818            entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
2819            entry.flags                                |=  RO_EXISTS;
2820            releasecount++;
2821         }
2822      }   
2823
2824      /* End the transactions and destroy the connections */
2825      for (s=0; s<volcount; s++) {
2826         if (replicas[s].trans)
2827            code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
2828         replicas[s].trans = 0;
2829         if (!code) code = rcode;
2830         if (code) {
2831            if ((s == 0) || (code != ENOENT)) {
2832               PrintError("Could not end transaction on a ro volume: ", code);
2833            } else {
2834               PrintError("Transaction timed out on a ro volume. Will retry.\n", 0);
2835               if (times[s].vldbEntryIndex < vldbindex)
2836                  vldbindex = times[s].vldbEntryIndex;
2837            }
2838         }
2839            
2840         if (toconns[s])
2841            rx_DestroyConnection(toconns[s]);
2842         toconns[s] = 0;
2843      }
2844    
2845      MapNetworkToHost(&entry, &storeEntry);
2846      vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
2847      ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2848   } /* for each index in the vldb */
2849
2850   /* End the transaction on the cloned volume */
2851   code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2852   fromtid = 0;
2853   if (!code) code = rcode;
2854   if (code)
2855      PrintError("Failed to end transaction on rw volume: ", code);
2856   
2857   /* Figure out if any volume were not released and say so */
2858   for (failure=0, i=0; i<entry.nServers; i++) {
2859      if (!(entry.serverFlags[i] & NEW_REPSITE))
2860         failure++;
2861   }
2862   if (failure) {
2863      char pname[10];
2864      fprintf(STDERR, "The volume %u could not be released to the following %d sites:\n",
2865              afromvol, failure);
2866      for (i=0; i<entry.nServers; i++) {
2867         if (!(entry.serverFlags[i] & NEW_REPSITE)) {
2868            MapPartIdIntoName(entry.serverPartition[i],pname);
2869            fprintf(STDERR,"\t%35s %s\n", 
2870                    hostutil_GetNameByINet(entry.serverNumber[i]), pname);
2871         }
2872      }
2873
2874      MapNetworkToHost(&entry,&storeEntry);
2875      vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, LOCKREL_TIMESTAMP);
2876      ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2877
2878      ERROREXIT(VOLSERBADRELEASE);
2879   }
2880
2881   /* All the ROs were release successfully. Remove the temporary clone */
2882   if (!roclone) {
2883       if (verbose) {
2884           fprintf(STDOUT,"Deleting the releaseClone %u ...", cloneVolId);
2885           fflush(STDOUT);
2886       }
2887       code = DelVol (fromconn, cloneVolId, afrompart, ITOffline);
2888       ONERROR (code, cloneVolId, "Failed to delete volume %u.\n");
2889       VDONE;
2890   }
2891   entry.cloneId = 0;
2892
2893   for (i=0; i<entry.nServers; i++)
2894      entry.serverFlags[i] &= ~NEW_REPSITE;
2895
2896   /* Update the VLDB */
2897   VPRINT("updating VLDB ...");
2898
2899   MapNetworkToHost(&entry, &storeEntry);
2900   vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
2901                            LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2902   ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
2903   VDONE;
2904
2905  rfail:
2906   if (clonetid) {
2907       code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2908       clonetid = 0;
2909       if (code) {
2910           fprintf (STDERR,"Failed to end cloning transaction on the RW volume %u\n", afromvol);
2911           if (!error) error = code;
2912       }
2913   }
2914   if (fromtid) {
2915       code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2916       fromtid = 0;
2917       if (code) {
2918           fprintf (STDERR,"Failed to end transaction on the release clone %u\n", cloneVolId);
2919           if (!error) error = code;
2920       }
2921   }
2922   for (i=0; i<nservers; i++) {
2923       if (replicas && replicas[i].trans) {
2924           code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
2925           replicas[i].trans = 0;
2926           if (code) {
2927               fprintf(STDERR,"Failed to end transaction on ro volume %u at server 0x%x\n",
2928                       entry.volumeId[ROVOL], 
2929                       hostutil_GetNameByINet(htonl(replicas[i].server.destHost)));
2930               if (!error) error = code;
2931           }
2932       }
2933       if (toconns && toconns[i]) {
2934           rx_DestroyConnection(toconns[i]);
2935           toconns[i] = 0;
2936       }
2937   }
2938   if (islocked) {
2939       vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, afromvol, RWVOL, 
2940                         LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
2941       if (vcode) {
2942           fprintf(STDERR,"Could not release lock on the VLDB entry for volume %u\n", afromvol);
2943           if (!error) error = vcode;
2944       }
2945   }
2946
2947   PrintError("", error);
2948
2949   if (fromconn)                rx_DestroyConnection(fromconn);
2950   if (results.manyResults_val) free (results.manyResults_val);
2951   if (replicas)                free (replicas);
2952   if (toconns)                 free (toconns);
2953   if (times)                   free (times);
2954   return error;
2955 }
2956
2957
2958 void dump_sig_handler(int x)
2959 {
2960    fprintf(STDERR,"\nSignal handler: vos dump operation\n");
2961    longjmp(env,0);
2962 }
2963
2964 /* Dump the volume <afromvol> on <afromserver> and
2965  * <afrompart> to <afilename> starting from <fromdate>.
2966  * DumpFunction does the real work behind the scenes after
2967  * extracting parameters from the rock 
2968  */
2969 int UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, 
2970         afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
2971 {
2972    struct rx_connection *fromconn = (struct rx_connection *)0;
2973    struct rx_call       *fromcall = (struct rx_call *)0;
2974    afs_int32 fromtid=0, rxError=0, rcode=0;
2975    afs_int32 code, error = 0;
2976
2977    if (setjmp(env)) ERROR_EXIT(EPIPE);
2978 #ifndef AFS_NT40_ENV
2979    (void) signal(SIGPIPE, dump_sig_handler);
2980 #endif
2981    (void) signal(SIGINT,  dump_sig_handler);
2982
2983    if (!fromdate)
2984    {
2985       VPRINT("Full Dump ...\n");
2986    }
2987    else 
2988    {
2989       VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
2990    }
2991
2992    /* get connections to the servers */
2993    fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2994
2995    VPRINT1("Starting transaction on volume %u...", afromvol);
2996    code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2997    EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
2998    VDONE;
2999
3000    fromcall = rx_NewCall(fromconn);
3001
3002    VPRINT1("Starting volume dump on volume %u...", afromvol);
3003    code = StartAFSVolDump(fromcall, fromtid, fromdate);
3004    EGOTO(error_exit, code, "Could not start the dump process \n");
3005    VDONE;
3006
3007    VPRINT1("Dumping volume %u...", afromvol);
3008    code = DumpFunction(fromcall, rock);
3009    EGOTO(error_exit, code, "Error while dumping volume \n");
3010    VDONE;
3011
3012  error_exit: 
3013    if (fromcall) {
3014       code = rx_EndCall(fromcall, rxError);
3015       if (code) {
3016          fprintf(STDERR,"Error in rx_EndCall\n");
3017          if (!error) error = code;
3018       } 
3019    }
3020    if (fromtid) {
3021       VPRINT1("Ending transaction on volume %u...", afromvol);
3022       code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3023       if (code || rcode) {
3024          fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol);
3025          if (!error) error = (code?code:rcode);
3026       }
3027       VDONE;
3028    }
3029    if (fromconn)
3030       rx_DestroyConnection(fromconn);
3031
3032    PrintError("", error);
3033    return(error);
3034 }
3035
3036 /* Clone the volume <afromvol> on <afromserver> and
3037  * <afrompart>, and then dump the clone volume to 
3038  * <afilename> starting from <fromdate>.
3039  * DumpFunction does the real work behind the scenes after
3040  * extracting parameters from the rock 
3041  */
3042 int UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, 
3043         afs_int32 fromdate, afs_int32 (*DumpFunction)(), char *rock)
3044 {
3045         struct rx_connection *fromconn = (struct rx_connection *)0;
3046         struct rx_call       *fromcall = (struct rx_call *)0;
3047         afs_int32 fromtid=0, rxError=0, rcode=0;
3048         afs_int32 clonetid=0;
3049         afs_int32 code=0, vcode=0, error = 0;
3050         afs_int32 clonevol=0;
3051     char vname[64];
3052
3053         if (setjmp(env)) ERROR_EXIT(EPIPE);
3054 #ifndef AFS_NT40_ENV
3055         (void) signal(SIGPIPE, dump_sig_handler);
3056 #endif
3057         (void) signal(SIGINT,  dump_sig_handler);
3058
3059         if (!fromdate)
3060         {
3061           VPRINT("Full Dump ...\n");
3062         }
3063         else 
3064         {
3065           VPRINT1("Incremental Dump (as of %.24s)...\n", ctime((time_t *)&fromdate));
3066         }
3067
3068         /* get connections to the servers */
3069         fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3070
3071         VPRINT1("Starting transaction on volume %u...", afromvol);
3072         code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3073         EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be dumped\n", afromvol);
3074         VDONE;
3075
3076     /* Get a clone id */
3077     VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
3078     code = ubik_Call (VL_GetNewVolumeId, cstruct, 0, 1, &clonevol);
3079     EGOTO1(error_exit, code, "Could not get an ID for the clone of volume %u from the VLDB\n", afromvol);
3080     VDONE;
3081
3082     /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
3083     VPRINT2("Cloning source volume %u to clone volume %u...", afromvol, clonevol);
3084     strcpy(vname, "dump-clone-temp");
3085     code = AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
3086     EGOTO1(error_exit, code, "Failed to clone the source volume %u\n", afromvol);
3087     VDONE;
3088
3089     VPRINT1("Ending the transaction on the volume %u ...", afromvol);
3090     rcode = 0;
3091     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3092     fromtid = 0;
3093     if (!code) code = rcode;
3094     EGOTO1(error_exit, code, "Failed to end the transaction on the volume %u\n", afromvol);
3095     VDONE;
3096
3097
3098     VPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
3099     code = AFSVolTransCreate (fromconn, clonevol, afrompart, ITOffline, &clonetid);
3100     EGOTO1(error_exit, code, "Failed to start a transaction on the cloned volume%u\n", clonevol);
3101     VDONE;
3102
3103     VPRINT1("Setting flags on cloned volume %u ...", clonevol);
3104     code = AFSVolSetFlags (fromconn, clonetid, VTDeleteOnSalvage|VTOutOfService); /*redundant */
3105     EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n", clonevol);
3106     VDONE;
3107
3108
3109         fromcall = rx_NewCall(fromconn);
3110
3111         VPRINT1("Starting volume dump from cloned volume %u...", clonevol);
3112         code = StartAFSVolDump(fromcall, clonetid, fromdate);
3113         EGOTO(error_exit, code, "Could not start the dump process \n");
3114         VDONE;
3115
3116         VPRINT1("Dumping volume %u...", afromvol);
3117         code = DumpFunction(fromcall, rock);
3118         EGOTO(error_exit, code, "Error while dumping volume \n");
3119         VDONE;
3120
3121  error_exit: 
3122     /* now delete the clone */
3123     VPRINT1("Deleting the cloned volume %u ...", clonevol);
3124     code = AFSVolDeleteVolume(fromconn, clonetid);
3125         if ( code )
3126         {       
3127             fprintf(STDERR,"Failed to delete the cloned volume %u\n", clonevol);
3128         }
3129         else
3130         {
3131             VDONE;
3132         }
3133
3134         if (fromcall) {
3135                 code = rx_EndCall(fromcall, rxError);
3136                 if (code) {
3137                         fprintf(STDERR,"Error in rx_EndCall\n");
3138                         if (!error) error = code;
3139                 }       
3140         }
3141         if (fromtid) {
3142                 VPRINT1("Ending transaction on cloned volume %u...", clonevol);
3143                 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3144                 if (code || rcode) {
3145                         fprintf(STDERR,"Could not end transaction on the cloned volume %u\n", clonevol);
3146                         if (!error) error = (code?code:rcode);
3147                 }
3148                 VDONE;
3149         }
3150         if (fromconn)
3151                 rx_DestroyConnection(fromconn);
3152
3153         PrintError("", error);
3154         return(error);
3155 }
3156
3157
3158
3159 /*
3160  * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
3161  * the dump file <afilename>. WriteData does all the real work
3162  * after extracting params from the rock 
3163  */
3164 int UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid, 
3165         char tovolname[], int flags, afs_int32 (*WriteData)(), char *rock)
3166 {
3167     struct rx_connection *toconn,*tempconn;
3168     struct rx_call *tocall;
3169     afs_int32 totid, code, rcode, vcode,terror = 0;
3170     afs_int32 rxError = 0;
3171     struct volser_status tstatus;
3172     char partName[10];
3173     afs_int32 pvolid;
3174     afs_int32 temptid;
3175     int success;
3176     struct nvldbentry entry,storeEntry;
3177     afs_int32 error;
3178     int islocked;
3179     struct restoreCookie cookie;
3180     int reuseID;
3181     afs_int32 newDate, volflag, voltype, volsertype;
3182     int index, same, errcode;
3183     char apartName[10];
3184
3185
3186     memset(&cookie, 0, sizeof(cookie));
3187     islocked  = 0;
3188     success = 0;
3189     error = 0;
3190     reuseID = 1;
3191     tocall = (struct rx_call *)0;
3192     toconn = (struct rx_connection *)0;
3193     tempconn = (struct rx_connection *)0;
3194     totid = 0;
3195     temptid = 0;
3196
3197     if (flags & RV_RDONLY) {
3198         voltype    = ROVOL;
3199         volsertype = volser_RO;
3200     } else {
3201         voltype    = RWVOL;
3202         volsertype = volser_RW;
3203     }
3204
3205     pvolid = tovolid;
3206     toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
3207     if(pvolid == 0) {/*alot a new id if needed */
3208         vcode = VLDB_GetEntryByName(tovolname, &entry);
3209         if(vcode == VL_NOENT) {
3210             vcode = ubik_Call(VL_GetNewVolumeId,cstruct, 0, 1, &pvolid);
3211             if(vcode) {
3212                 fprintf(STDERR,"Could not get an Id for the volume %s\n",tovolname);
3213                 error = vcode;
3214                 goto refail;
3215             }
3216             reuseID = 0;
3217         } else if (flags & RV_RDONLY) {
3218             if (entry.flags & RW_EXISTS) {
3219                 fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
3220                 error = VOLSERBADOP;
3221                 goto refail;
3222             }
3223             if (!entry.volumeId[ROVOL]) {
3224                 fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
3225                 error = VOLSERBADOP;
3226                 goto refail;
3227             }
3228             pvolid = entry.volumeId[ROVOL];
3229         } else {
3230             pvolid = entry.volumeId[RWVOL];
3231         }
3232     }/* at this point we have a volume id to use/reuse for the volume to be restored */
3233
3234     if(strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
3235         EGOTO1(refail, VOLSERBADOP, "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",tovolname);
3236     }
3237     MapPartIdIntoName(topart, partName);
3238     fprintf(STDOUT,"Restoring volume %s Id %u on server %s partition %s ..", tovolname,
3239             pvolid, hostutil_GetNameByINet(toserver), partName);
3240     fflush(STDOUT);
3241     code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3242     if (code){
3243         if (flags & RV_FULLRST) { /* full restore: delete then create anew */
3244             VPRINT1("Deleting the previous volume %u ...",pvolid);
3245
3246             code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3247             EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3248
3249             code = AFSVolSetFlags(toconn, totid, VTDeleteOnSalvage | VTOutOfService);
3250             EGOTO1(refail, code, "Could not set flags on volume %u \n",pvolid);
3251
3252             code = AFSVolDeleteVolume(toconn,totid);
3253             EGOTO1(refail, code, "Could not delete volume %u\n",pvolid); 
3254
3255             code = AFSVolEndTrans(toconn, totid, &rcode);
3256             totid = 0;
3257             if (!code) code = rcode;
3258             EGOTO1(refail, code, "Could not end transaction on %u\n",pvolid);
3259
3260             VDONE;
3261
3262             code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
3263             EGOTO1(refail, code, "Could not create new volume %u\n",pvolid);
3264         }
3265         else{
3266             code = AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3267             EGOTO1(refail, code, "Failed to start transaction on %u\n",pvolid);
3268         }
3269     }
3270     cookie.parent = pvolid;
3271     cookie.type = voltype;
3272     cookie.clone = 0;
3273     strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
3274
3275     tocall = rx_NewCall(toconn);
3276     terror = StartAFSVolRestore(tocall,totid, 1,&cookie);
3277     if(terror) {
3278         fprintf(STDERR,"Volume restore Failed \n");
3279         error = terror;
3280         goto refail;
3281     }
3282     code = WriteData(tocall, rock);
3283     if(code) {
3284         fprintf(STDERR,"Could not transmit data\n");
3285         error = code;
3286         goto refail;
3287     }
3288     terror = rx_EndCall(tocall,rxError);
3289     tocall = (struct rx_call *) 0;
3290     if (terror) {
3291         fprintf(STDERR,"rx_EndCall Failed \n");
3292         error = terror;     
3293         goto refail;
3294     }
3295     code = AFSVolGetStatus(toconn,totid, &tstatus);
3296     if(code) {
3297         fprintf(STDERR,"Could not get status information about the volume %u\n",pvolid);
3298         error = code;
3299         goto refail;
3300     }
3301     code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
3302     if(code) {
3303         fprintf(STDERR,"Could not set the right type and ID on %u\n",pvolid); 
3304         error = code;
3305         goto refail;
3306     }
3307     newDate = time(0);
3308     code = AFSVolSetDate(toconn,totid, newDate);
3309     if(code) {
3310         fprintf(STDERR,"Could not set the date on %u\n",pvolid); 
3311         error = code;
3312         goto refail;
3313     }
3314
3315     volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
3316     code = AFSVolSetFlags(toconn, totid, volflag);
3317     if (code){
3318         fprintf(STDERR,"Could not mark %u online\n",pvolid );
3319         error = code;
3320         goto refail;
3321     }
3322    
3323 /* It isn't handled right in refail */
3324     code = AFSVolEndTrans(toconn, totid, &rcode);
3325     totid = 0;
3326     if(!code) code = rcode;
3327     if(code) {
3328         fprintf(STDERR,"Could not end transaction on %u\n",pvolid);
3329         error = code;
3330         goto refail;
3331     }
3332
3333     success = 1;
3334     fprintf(STDOUT," done\n");
3335     fflush(STDOUT);
3336     if (success && (!reuseID || (flags & RV_FULLRST))) {
3337         /* Volume was restored on the file server, update the 
3338          * VLDB to reflect the change.
3339          */
3340         vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
3341         if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
3342             fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",pvolid);
3343             error = vcode;
3344             goto refail;
3345         }
3346         if (!vcode) MapHostToNetwork(&entry);
3347         if(vcode == VL_NOENT) { /* it doesnot exist already */
3348             /*make the vldb return this indication specifically*/
3349             VPRINT("------- Creating a new VLDB entry ------- \n");
3350             strcpy(entry.name, tovolname);
3351             entry.nServers = 1;
3352             entry.serverNumber[0] = toserver;/*should be indirect */
3353             entry.serverPartition[0] = topart;
3354             entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3355             entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3356             if (flags & RV_RDONLY)
3357                 entry.volumeId[ROVOL] = pvolid;
3358             else if(tstatus.cloneID != 0){
3359                 entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
3360             }
3361             else
3362                 entry.volumeId[ROVOL] = INVALID_BID;
3363             entry.volumeId[RWVOL] = pvolid;
3364             entry.cloneId = 0;
3365             if(tstatus.backupID != 0){
3366                 entry.volumeId[BACKVOL] = tstatus.backupID;
3367                 /*this should come from status info on the volume if non zero */
3368             }
3369             else 
3370                 entry.volumeId[BACKVOL] = INVALID_BID;
3371             MapNetworkToHost(&entry,&storeEntry);
3372             vcode = VLDB_CreateEntry(&storeEntry);
3373             if(vcode) {
3374                 fprintf(STDERR,"Could not create the VLDB entry for volume number %u  \n",pvolid);
3375                 error = vcode;
3376                 goto refail;
3377             }
3378             islocked = 0;
3379             if (verbose) EnumerateEntry(&entry);
3380         }
3381         else {  /*update the existing entry */
3382             if(verbose) {
3383                 fprintf(STDOUT,"Updating the existing VLDB entry\n");
3384                 fprintf(STDOUT,"------- Old entry -------\n");
3385                 EnumerateEntry(&entry);
3386                 fprintf(STDOUT,"------- New entry -------\n");
3387             }
3388             vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
3389             if(vcode) {
3390                 fprintf(STDERR,"Could not lock the entry for volume number %u \n",pvolid);
3391                 error = vcode;
3392                 goto refail;
3393             }
3394             islocked = 1;
3395             strcpy(entry.name, tovolname);
3396
3397             /* Update the vlentry with the new information */
3398             if (flags & RV_RDONLY)
3399                 index = Lp_ROMatch(toserver, topart, &entry) - 1;
3400             else
3401                 index = Lp_GetRwIndex(&entry);
3402             if (index == -1) {
3403                /* Add the new site for the volume being restored */
3404                entry.serverNumber[entry.nServers]    = toserver;
3405                entry.serverPartition[entry.nServers] = topart;
3406                entry.serverFlags[entry.nServers]     =
3407                         (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3408                entry.nServers++;
3409             } else {
3410                /* This volume should be deleted on the old site
3411                 * if its different from new site.
3412                 */
3413                same = VLDB_IsSameAddrs(toserver, entry.serverNumber[index], &errcode);
3414                EPRINT2(errcode, "Failed to get info about server's %d address(es) from vlserver (err=%d)\n", 
3415                           toserver, errcode);
3416                if ( (!errcode && !same) || (entry.serverPartition[index] != topart) ) {
3417                   tempconn = UV_Bind(entry.serverNumber[index], AFSCONF_VOLUMEPORT);
3418                   
3419                   MapPartIdIntoName(entry.serverPartition[index], apartName);
3420                   VPRINT3("Deleting the previous volume %u on server %s, partition %s ...",
3421                              pvolid,
3422                              hostutil_GetNameByINet(entry.serverNumber[index]), apartName);
3423                   code = AFSVolTransCreate(tempconn, pvolid, entry.serverPartition[index], ITOffline, &temptid);
3424                   if (!code){
3425                      code = AFSVolSetFlags(tempconn, temptid, VTDeleteOnSalvage | VTOutOfService);
3426                      if(code) {
3427                         fprintf(STDERR,"Could not set flags on volume %u on the older site\n",pvolid);
3428                         error = code;
3429                         goto refail;
3430                      }
3431                      code = AFSVolDeleteVolume(tempconn,temptid);
3432                      if(code){
3433                         fprintf(STDERR,"Could not delete volume %u on the older site\n",pvolid);
3434                         error = code;
3435                         goto refail;
3436                      }
3437                      code = AFSVolEndTrans(tempconn, temptid, &rcode);
3438                      temptid = 0;
3439                      if(!code) code = rcode;
3440                      if(code){
3441                         fprintf(STDERR,"Could not end transaction on volume %u on the older site\n",pvolid);
3442                         error = code;
3443                         goto refail;
3444                      }
3445                      VDONE;
3446                      MapPartIdIntoName(entry.serverPartition[index],partName);
3447                   }
3448                }
3449                entry.serverNumber[index]    = toserver;
3450                entry.serverPartition[index] = topart;
3451             }
3452
3453             entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3454             MapNetworkToHost(&entry,&storeEntry);
3455             vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3456             if(vcode) {
3457                 fprintf(STDERR,"Could not update the entry for volume number %u  \n",pvolid);
3458                 error = vcode;
3459                 goto refail;
3460             }
3461             islocked = 0;
3462             if(verbose) EnumerateEntry(&entry);
3463         }
3464
3465
3466     }
3467     refail:
3468       if (tocall) {
3469           code = rx_EndCall(tocall, rxError);
3470           if (!error) error = code;
3471       }
3472       if(islocked) {
3473           vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3474           if(vcode) {
3475               fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %u\n",pvolid);
3476               if(!error) error = vcode;
3477           }
3478       }
3479       if(totid) {
3480           code = AFSVolEndTrans(toconn, totid, &rcode);
3481           if(!code) code = rcode;
3482           if(code) {
3483               fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
3484               if(!error) error = code;
3485           }
3486       }
3487       if(temptid) {
3488           code = AFSVolEndTrans(toconn, temptid, &rcode);
3489           if(!code) code = rcode;
3490           if(code) {
3491               fprintf(STDERR,"Could not end transaction on the volume %u \n",pvolid);
3492               if(!error) error = code;
3493           }
3494       }
3495       if(tempconn) rx_DestroyConnection(tempconn);
3496       if(toconn) rx_DestroyConnection(toconn);
3497       PrintError("",error);
3498       return error;
3499 }
3500
3501
3502 /*unlocks the vldb entry associated with <volid> */
3503 int UV_LockRelease(afs_int32 volid)
3504 {
3505         
3506         
3507     afs_int32 vcode;
3508
3509     VPRINT("Binding to the VLDB server\n");
3510     vcode = ubik_Call(VL_ReleaseLock,cstruct, 0,volid,-1,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
3511     if(vcode) {
3512         fprintf(STDERR,"Could not unlock the entry for volume number %u in VLDB \n",volid);
3513         PrintError("",vcode);
3514         return (vcode);
3515     }
3516     VPRINT("VLDB updated\n");
3517     return 0;
3518
3519 }
3520
3521 /*adds <server> and <part> as a readonly replication site for <volid>
3522 *in vldb */
3523 int UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
3524 {
3525     int j, nro=0, islocked=0;
3526     struct nvldbentry entry,storeEntry;
3527     afs_int32 vcode, error=0;
3528     char apartName[10];
3529
3530     error = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
3531     if (error) {
3532         fprintf(STDERR," Could not lock the VLDB entry for the volume %u \n", volid);
3533         goto asfail;
3534     }
3535     islocked = 1;
3536
3537     error = VLDB_GetEntryByID(volid,RWVOL, &entry);
3538     if (error) {
3539         fprintf(STDERR,"Could not fetch the VLDB entry for volume number %u  \n",volid);
3540         goto asfail;
3541
3542     }
3543     if (!ISNAMEVALID(entry.name)){
3544         fprintf(STDERR,"Volume name %s is too long, rename before adding site\n", entry.name);
3545         error = VOLSERBADOP;
3546         goto asfail;
3547     }
3548     MapHostToNetwork(&ent