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