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