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