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