683702311fd134bb0da09c62a61da7b0f0531ebb
[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;
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     if (!roexists && !fullrelease)
2935         fullrelease = 1;        /* Do a full release if RO clone does not exist */
2936
2937     if (verbose) {
2938         if (fullrelease) {
2939             fprintf(STDOUT, "This is a complete release of the volume %lu\n",
2940                     (unsigned long)afromvol);
2941         } else {
2942             fprintf(STDOUT, "This is a completion of the previous release\n");
2943         }
2944     }
2945
2946     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2947     if (!fromconn)
2948         ONERROR(-1, afromserver,
2949                 "Cannot establish connection with server 0x%x\n");
2950
2951     if (fullrelease) {
2952         /* If the RO clone exists, then if the clone is a temporary
2953          * clone, delete it. Or if the RO clone is marked RO_DONTUSE
2954          * (it was recently added), then also delete it. We do not
2955          * want to "reclone" a temporary RO clone.
2956          */
2957         if (roexists
2958             && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
2959             code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
2960             if (code && (code != VNOVOL))
2961                 ERROREXIT(code);
2962             roexists = 0;
2963         }
2964
2965         /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
2966          * write this entry out to the vlserver until after the first
2967          * RO volume is released (temp RO clones don't count).
2968          */
2969         for (i = 0; i < entry.nServers; i++) {
2970             entry.serverFlags[i] &= ~NEW_REPSITE;
2971             entry.serverFlags[i] |= RO_DONTUSE;
2972         }
2973         entry.serverFlags[rwindex] |= NEW_REPSITE;
2974         entry.serverFlags[rwindex] &= ~RO_DONTUSE;
2975
2976         /* Begin transaction on RW and mark it busy while we clone it */
2977         code =
2978             AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
2979                               &clonetid);
2980         ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
2981
2982         /* Clone or reclone the volume */
2983         if (roexists) {
2984             VPRINT1("Recloning RW volume %u...", cloneVolId);
2985             code = AFSVolReClone(fromconn, clonetid, cloneVolId);
2986             ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
2987             VDONE;
2988         } else {
2989             if (roclone) {
2990                 strcpy(vname, entry.name);
2991                 strcat(vname, ".readonly");
2992                 VPRINT("Cloning RW volume %u to permanent RO...");
2993             } else {
2994                 strcpy(vname, "readonly-clone-temp");
2995                 VPRINT("Cloning RW volume %u to temporary RO...");
2996             }
2997             code =
2998                 AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
2999                             &cloneVolId);
3000             ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
3001             VDONE;
3002         }
3003
3004         /* Get the time the RW was created for future information */
3005         VPRINT1("Getting status of RW volume %u...", cloneVolId);
3006         code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3007         ONERROR(code, cloneVolId,
3008                 "Failed to get the status of the RW volume %u\n");
3009         VDONE;
3010         rwcrdate = volstatus.creationDate;
3011
3012         /* End the transaction on the RW volume */
3013         VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
3014         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3015         clonetid = 0;
3016         ONERROR((code ? code : rcode), cloneVolId,
3017                 "Failed to end cloning transaction on RW %u\n");
3018         VDONE;
3019
3020         /* Remember clone volume ID in case we fail or are interrupted */
3021         entry.cloneId = cloneVolId;
3022
3023         if (roclone) {
3024             /* Bring the RO clone online - though not if it's a temporary clone */
3025             VPRINT1("Starting transaction on RO clone volume %u...",
3026                     cloneVolId);
3027             code =
3028                 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
3029                                   &onlinetid);
3030             ONERROR(code, cloneVolId,
3031                     "Failed to start transaction on volume %u\n");
3032             VDONE;
3033
3034             VPRINT1("Setting volume flags for volume %u...", cloneVolId);
3035             tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
3036             VDONE;
3037
3038             VPRINT1("Ending transaction on volume %u...", cloneVolId);
3039             code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
3040             ONERROR((code ? code : rcode), cloneVolId,
3041                     "Failed to end transaction on RO clone %u\n");
3042             VDONE;
3043
3044             ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
3045
3046             /* Sleep so that a client searching for an online volume won't
3047              * find the clone offline and then the next RO offline while the 
3048              * release brings the clone online and the next RO offline (race).
3049              * There is a fix in the 3.4 client that does not need this sleep
3050              * anymore, but we don't know what clients we have.
3051              */
3052             if (entry.nServers > 2)
3053                 sleep(5);
3054
3055             /* Mark the RO clone in the VLDB as a good site (already released) */
3056             entry.serverFlags[roindex] |= NEW_REPSITE;
3057             entry.serverFlags[roindex] &= ~RO_DONTUSE;
3058             entry.flags |= RO_EXISTS;
3059
3060             releasecount++;
3061
3062             /* Write out the VLDB entry only if the clone is not a temporary
3063              * clone. If we did this to a temporary clone then we would end
3064              * up marking all the ROs as "old release" making the ROs
3065              * temporarily unavailable.
3066              */
3067             MapNetworkToHost(&entry, &storeEntry);
3068             VPRINT1("Replacing VLDB entry for %s...", entry.name);
3069             vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3070             ONERROR(vcode, entry.name,
3071                     "Could not update vldb entry for %s.\n");
3072             VDONE;
3073         }
3074     }
3075
3076     /* Now we will release from the clone to the remaining RO replicas.
3077      * The first 2 ROs (counting the non-temporary RO clone) are released
3078      * individually: releasecount. This is to reduce the race condition
3079      * of clients trying to find an on-line RO volume. The remaining ROs
3080      * are released in parallel but no more than half the number of ROs
3081      * (rounded up) at a time: nservers.
3082      */
3083
3084     strcpy(vname, entry.name);
3085     strcat(vname, ".readonly");
3086     memset(&cookie, 0, sizeof(cookie));
3087     strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
3088     cookie.type = ROVOL;
3089     cookie.parent = entry.volumeId[RWVOL];
3090     cookie.clone = 0;
3091
3092     nservers = entry.nServers / 2;      /* how many to do at once, excluding clone */
3093     replicas =
3094         (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
3095     times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
3096     toconns =
3097         (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
3098                                         nservers + 1);
3099     results.manyResults_val =
3100         (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
3101     if (!replicas || !times || !!!results.manyResults_val || !toconns)
3102         ONERROR(ENOMEM, 0,
3103                 "Failed to create transaction on the release clone\n");
3104
3105     memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
3106     memset(times, 0, (sizeof(struct release) * nservers + 1));
3107     memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
3108     memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
3109
3110     /* Create a transaction on the cloned volume */
3111     VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
3112     code =
3113         AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
3114     if (!fullrelease && code)
3115         ONERROR(VOLSERNOVOL, afromvol,
3116                 "Old clone is inaccessible. Try vos release -f %u.\n");
3117     ONERROR(code, 0, "Failed to create transaction on the release clone\n");
3118     VDONE;
3119
3120     /* For each index in the VLDB */
3121     for (vldbindex = 0; vldbindex < entry.nServers;) {
3122
3123         /* Get a transaction on the replicas. Pick replacas which have an old release. */
3124         for (volcount = 0;
3125              ((volcount < nservers) && (vldbindex < entry.nServers));
3126              vldbindex++) {
3127             /* The first two RO volumes will be released individually.
3128              * The rest are then released in parallel. This is a hack
3129              * for clients not recognizing right away when a RO volume
3130              * comes back on-line.
3131              */
3132             if ((volcount == 1) && (releasecount < 2))
3133                 break;
3134
3135             if (vldbindex == roindex)
3136                 continue;       /* the clone    */
3137             if ((entry.serverFlags[vldbindex] & NEW_REPSITE)
3138                 && !(entry.serverFlags[vldbindex] & RO_DONTUSE))
3139                 continue;
3140             if (!(entry.serverFlags[vldbindex] & ITSROVOL))
3141                 continue;       /* not a RO vol */
3142
3143
3144             /* Get a Transaction on this replica. Get a new connection if
3145              * necessary.  Create the volume if necessary.  Return the
3146              * time from which the dump should be made (0 if it's a new
3147              * volume).  Each volume might have a different time. 
3148              */
3149             replicas[volcount].server.destHost =
3150                 ntohl(entry.serverNumber[vldbindex]);
3151             replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
3152             replicas[volcount].server.destSSID = 1;
3153             times[volcount].vldbEntryIndex = vldbindex;
3154
3155             code =
3156                 GetTrans(&entry, vldbindex, &(toconns[volcount]),
3157                          &(replicas[volcount].trans),
3158                          &(times[volcount].time));
3159             if (code)
3160                 continue;
3161
3162             /* Thisdate is the date from which we want to pick up all changes */
3163             if (forceflag || !fullrelease
3164                 || (rwcrdate > times[volcount].time)) {
3165                 /* If the forceflag is set, then we want to do a full dump.
3166                  * If it's not a full release, we can't be sure that the creation
3167                  *  date is good (so we also do a full dump).
3168                  * If the RW volume was replaced (its creation date is newer than
3169                  *  the last release), then we can't be sure what has changed (so
3170                  *  we do a full dump).
3171                  */
3172                 thisdate = 0;
3173             } else if (remembertime[vldbindex].validtime) {
3174                 /* Trans was prev ended. Use the time from the prev trans
3175                  * because, prev trans may have created the volume. In which
3176                  * case time[volcount].time would be now instead of 0.
3177                  */
3178                 thisdate =
3179                     (remembertime[vldbindex].time <
3180                      times[volcount].time) ? remembertime[vldbindex].
3181                     time : times[volcount].time;
3182             } else {
3183                 thisdate = times[volcount].time;
3184             }
3185             remembertime[vldbindex].validtime = 1;
3186             remembertime[vldbindex].time = thisdate;
3187
3188             if (volcount == 0) {
3189                 fromdate = thisdate;
3190             } else {
3191                 /* Include this volume if it is within 15 minutes of the earliest */
3192                 if (((fromdate >
3193                       thisdate) ? (fromdate - thisdate) : (thisdate -
3194                                                            fromdate)) > 900) {
3195                     AFSVolEndTrans(toconns[volcount],
3196                                    replicas[volcount].trans, &rcode);
3197                     replicas[volcount].trans = 0;
3198                     break;
3199                 }
3200                 if (thisdate < fromdate)
3201                     fromdate = thisdate;
3202             }
3203             volcount++;
3204         }
3205         if (!volcount)
3206             continue;
3207
3208         if (verbose) {
3209             fprintf(STDOUT, "Starting ForwardMulti from %lu to %u on %s",
3210                     (unsigned long)cloneVolId, entry.volumeId[ROVOL],
3211                     hostutil_GetNameByINet(entry.
3212                                            serverNumber[times[0].
3213                                                         vldbEntryIndex]));
3214
3215             for (s = 1; s < volcount; s++) {
3216                 fprintf(STDOUT, " and %s",
3217                         hostutil_GetNameByINet(entry.
3218                                                serverNumber[times[s].
3219                                                             vldbEntryIndex]));
3220             }
3221
3222             if (fromdate == 0)
3223                 fprintf(STDOUT, " (full release)");
3224             fprintf(STDOUT, ".\n");
3225             fflush(STDOUT);
3226         }
3227
3228         /* Release the ones we have collected */
3229         tr.manyDests_val = &(replicas[0]);
3230         tr.manyDests_len = results.manyResults_len = volcount;
3231         code =
3232             AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr,
3233                                   0 /*spare */ , &cookie, &results);
3234         if (code == RXGEN_OPCODE) {     /* RPC Interface Mismatch */
3235             code =
3236                 SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr,
3237                                         0 /*spare */ , &cookie, &results);
3238             nservers = 1;
3239         }
3240
3241         if (code) {
3242             PrintError("Release failed: ", code);
3243         } else {
3244             for (m = 0; m < volcount; m++) {
3245                 if (results.manyResults_val[m]) {
3246                     if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
3247                         /* we retry timed out transaction. When it is
3248                          * not the first volume and the transaction wasn't found
3249                          * (assume it timed out and was garbage collected by volser).
3250                          */
3251                         PrintError
3252                             ("Failed to dump volume from clone to a ro site: ",
3253                              results.manyResults_val[m]);
3254                     }
3255                     continue;
3256                 }
3257
3258                 code =
3259                     AFSVolSetIdsTypes(toconns[m], replicas[m].trans, vname,
3260                                       ROVOL, entry.volumeId[RWVOL], 0, 0);
3261                 if (code) {
3262                     if ((m == 0) || (code != ENOENT)) {
3263                         PrintError("Failed to set correct names and ids: ",
3264                                    code);
3265                     }
3266                     continue;
3267                 }
3268
3269                 /* have to clear dest. flags to ensure new vol goes online:
3270                  * because the restore (forwarded) operation copied
3271                  * the V_inService(=0) flag over to the destination. 
3272                  */
3273                 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
3274                 if (code) {
3275                     if ((m == 0) || (code != ENOENT)) {
3276                         PrintError("Failed to set flags on ro volume: ",
3277                                    code);
3278                     }
3279                     continue;
3280                 }
3281
3282                 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
3283                 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
3284                 entry.flags |= RO_EXISTS;
3285                 releasecount++;
3286             }
3287         }
3288
3289         /* End the transactions and destroy the connections */
3290         for (s = 0; s < volcount; s++) {
3291             if (replicas[s].trans)
3292                 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
3293             replicas[s].trans = 0;
3294             if (!code)
3295                 code = rcode;
3296             if (code) {
3297                 if ((s == 0) || (code != ENOENT)) {
3298                     PrintError("Could not end transaction on a ro volume: ",
3299                                code);
3300                 } else {
3301                     PrintError
3302                         ("Transaction timed out on a ro volume. Will retry.\n",
3303                          0);
3304                     if (times[s].vldbEntryIndex < vldbindex)
3305                         vldbindex = times[s].vldbEntryIndex;
3306                 }
3307             }
3308
3309             if (toconns[s])
3310                 rx_DestroyConnection(toconns[s]);
3311             toconns[s] = 0;
3312         }
3313
3314         MapNetworkToHost(&entry, &storeEntry);
3315         vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3316         ONERROR(vcode, afromvol,
3317                 " Could not update VLDB entry for volume %u\n");
3318     }                           /* for each index in the vldb */
3319
3320     /* End the transaction on the cloned volume */
3321     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3322     fromtid = 0;
3323     if (!code)
3324         code = rcode;
3325     if (code)
3326         PrintError("Failed to end transaction on rw volume: ", code);
3327
3328     /* Figure out if any volume were not released and say so */
3329     for (failure = 0, i = 0; i < entry.nServers; i++) {
3330         if (!(entry.serverFlags[i] & NEW_REPSITE))
3331             failure++;
3332     }
3333     if (failure) {
3334         char pname[10];
3335         fprintf(STDERR,
3336                 "The volume %lu could not be released to the following %d sites:\n",
3337                 (unsigned long)afromvol, failure);
3338         for (i = 0; i < entry.nServers; i++) {
3339             if (!(entry.serverFlags[i] & NEW_REPSITE)) {
3340                 MapPartIdIntoName(entry.serverPartition[i], pname);
3341                 fprintf(STDERR, "\t%35s %s\n",
3342                         hostutil_GetNameByINet(entry.serverNumber[i]), pname);
3343             }
3344         }
3345
3346         MapNetworkToHost(&entry, &storeEntry);
3347         vcode =
3348             VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
3349                               LOCKREL_TIMESTAMP);
3350         ONERROR(vcode, afromvol,
3351                 " Could not update VLDB entry for volume %u\n");
3352
3353         ERROREXIT(VOLSERBADRELEASE);
3354     }
3355
3356     /* All the ROs were release successfully. Remove the temporary clone */
3357     if (!roclone) {
3358         if (verbose) {
3359             fprintf(STDOUT, "Deleting the releaseClone %lu ...",
3360                     (unsigned long)cloneVolId);
3361             fflush(STDOUT);
3362         }
3363         code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
3364         ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
3365         VDONE;
3366     }
3367     entry.cloneId = 0;
3368
3369     for (i = 0; i < entry.nServers; i++)
3370         entry.serverFlags[i] &= ~NEW_REPSITE;
3371
3372     /* Update the VLDB */
3373     VPRINT("updating VLDB ...");
3374
3375     MapNetworkToHost(&entry, &storeEntry);
3376     vcode =
3377         VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
3378                           LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3379     ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
3380     VDONE;
3381
3382   rfail:
3383     if (clonetid) {
3384         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3385         clonetid = 0;
3386         if (code) {
3387             fprintf(STDERR,
3388                     "Failed to end cloning transaction on the RW volume %lu\n",
3389                     (unsigned long)afromvol);
3390             if (!error)
3391                 error = code;
3392         }
3393     }
3394     if (fromtid) {
3395         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3396         fromtid = 0;
3397         if (code) {
3398             fprintf(STDERR,
3399                     "Failed to end transaction on the release clone %lu\n",
3400                     (unsigned long)cloneVolId);
3401             if (!error)
3402                 error = code;
3403         }
3404     }
3405     for (i = 0; i < nservers; i++) {
3406         if (replicas && replicas[i].trans) {
3407             code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
3408             replicas[i].trans = 0;
3409             if (code) {
3410                 fprintf(STDERR,
3411                         "Failed to end transaction on ro volume %u at server 0x%x\n",
3412                         entry.volumeId[ROVOL],
3413                         hostutil_GetNameByINet(htonl
3414                                                (replicas[i].server.
3415                                                 destHost)));
3416                 if (!error)
3417                     error = code;
3418             }
3419         }
3420         if (toconns && toconns[i]) {
3421             rx_DestroyConnection(toconns[i]);
3422             toconns[i] = 0;
3423         }
3424     }
3425     if (islocked) {
3426         vcode =
3427             ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, RWVOL,
3428                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3429         if (vcode) {
3430             fprintf(STDERR,
3431                     "Could not release lock on the VLDB entry for volume %lu\n",
3432                     (unsigned long)afromvol);
3433             if (!error)
3434                 error = vcode;
3435         }
3436     }
3437
3438     PrintError("", error);
3439
3440     if (fromconn)
3441         rx_DestroyConnection(fromconn);
3442     if (results.manyResults_val)
3443         free(results.manyResults_val);
3444     if (replicas)
3445         free(replicas);
3446     if (toconns)
3447         free(toconns);
3448     if (times)
3449         free(times);
3450     return error;
3451 }
3452
3453
3454 void
3455 dump_sig_handler(int x)
3456 {
3457     fprintf(STDERR, "\nSignal handler: vos dump operation\n");
3458     longjmp(env, 0);
3459 }
3460
3461 /* Dump the volume <afromvol> on <afromserver> and
3462  * <afrompart> to <afilename> starting from <fromdate>.
3463  * DumpFunction does the real work behind the scenes after
3464  * extracting parameters from the rock 
3465  */
3466 int
3467 UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
3468               afs_int32 fromdate, afs_int32(*DumpFunction) (), char *rock)
3469 {
3470     struct rx_connection *fromconn = (struct rx_connection *)0;
3471     struct rx_call *fromcall = (struct rx_call *)0;
3472     afs_int32 fromtid = 0, rxError = 0, rcode = 0;
3473     afs_int32 code, error = 0;
3474
3475     if (setjmp(env))
3476         ERROR_EXIT(EPIPE);
3477 #ifndef AFS_NT40_ENV
3478     (void)signal(SIGPIPE, dump_sig_handler);
3479 #endif
3480     (void)signal(SIGINT, dump_sig_handler);
3481
3482     if (!fromdate) {
3483         VPRINT("Full Dump ...\n");
3484     } else {
3485         VPRINT1("Incremental Dump (as of %.24s)...\n",
3486                 ctime((time_t *) & fromdate));
3487     }
3488
3489     /* get connections to the servers */
3490     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3491
3492     VPRINT1("Starting transaction on volume %u...", afromvol);
3493     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3494     EGOTO1(error_exit, code,
3495            "Could not start transaction on the volume %u to be dumped\n",
3496            afromvol);
3497     VDONE;
3498
3499     fromcall = rx_NewCall(fromconn);
3500
3501     VPRINT1("Starting volume dump on volume %u...", afromvol);
3502     code = StartAFSVolDump(fromcall, fromtid, fromdate);
3503     EGOTO(error_exit, code, "Could not start the dump process \n");
3504     VDONE;
3505
3506     VPRINT1("Dumping volume %u...", afromvol);
3507     code = DumpFunction(fromcall, rock);
3508     EGOTO(error_exit, code, "Error while dumping volume \n");
3509     VDONE;
3510
3511   error_exit:
3512     if (fromcall) {
3513         code = rx_EndCall(fromcall, rxError);
3514         if (code) {
3515             fprintf(STDERR, "Error in rx_EndCall\n");
3516             if (!error)
3517                 error = code;
3518         }
3519     }
3520     if (fromtid) {
3521         VPRINT1("Ending transaction on volume %u...", afromvol);
3522         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3523         if (code || rcode) {
3524             fprintf(STDERR, "Could not end transaction on the volume %lu\n",
3525                     (unsigned long)afromvol);
3526             if (!error)
3527                 error = (code ? code : rcode);
3528         }
3529         VDONE;
3530     }
3531     if (fromconn)
3532         rx_DestroyConnection(fromconn);
3533
3534     PrintError("", error);
3535     return (error);
3536 }
3537
3538 /* Clone the volume <afromvol> on <afromserver> and
3539  * <afrompart>, and then dump the clone volume to 
3540  * <afilename> starting from <fromdate>.
3541  * DumpFunction does the real work behind the scenes after
3542  * extracting parameters from the rock 
3543  */
3544 int
3545 UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver,
3546                     afs_int32 afrompart, afs_int32 fromdate,
3547                     afs_int32(*DumpFunction) (), char *rock)
3548 {
3549     struct rx_connection *fromconn = (struct rx_connection *)0;
3550     struct rx_call *fromcall = (struct rx_call *)0;
3551     afs_int32 fromtid = 0, rxError = 0, rcode = 0;
3552     afs_int32 clonetid = 0;
3553     afs_int32 code = 0, vcode = 0, error = 0;
3554     afs_int32 clonevol = 0;
3555     char vname[64];
3556
3557     if (setjmp(env))
3558         ERROR_EXIT(EPIPE);
3559 #ifndef AFS_NT40_ENV
3560     (void)signal(SIGPIPE, dump_sig_handler);
3561 #endif
3562     (void)signal(SIGINT, dump_sig_handler);
3563
3564     if (!fromdate) {
3565         VPRINT("Full Dump ...\n");
3566     } else {
3567         VPRINT1("Incremental Dump (as of %.24s)...\n",
3568                 ctime((time_t *) & fromdate));
3569     }
3570
3571     /* get connections to the servers */
3572     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3573
3574     VPRINT1("Starting transaction on volume %u...", afromvol);
3575     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3576     EGOTO1(error_exit, code,
3577            "Could not start transaction on the volume %u to be dumped\n",
3578            afromvol);
3579     VDONE;
3580
3581     /* Get a clone id */
3582     VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
3583     code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &clonevol);
3584     EGOTO1(error_exit, code,
3585            "Could not get an ID for the clone of volume %u from the VLDB\n",
3586            afromvol);
3587     VDONE;
3588
3589     /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
3590     VPRINT2("Cloning source volume %u to clone volume %u...", afromvol,
3591             clonevol);
3592     strcpy(vname, "dump-clone-temp");
3593     code =
3594         AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
3595     EGOTO1(error_exit, code, "Failed to clone the source volume %u\n",
3596            afromvol);
3597     VDONE;
3598
3599     VPRINT1("Ending the transaction on the volume %u ...", afromvol);
3600     rcode = 0;
3601     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3602     fromtid = 0;
3603     if (!code)
3604         code = rcode;
3605     EGOTO1(error_exit, code,
3606            "Failed to end the transaction on the volume %u\n", afromvol);
3607     VDONE;
3608
3609
3610     VPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
3611     code =
3612         AFSVolTransCreate(fromconn, clonevol, afrompart, ITOffline,
3613                           &clonetid);
3614     EGOTO1(error_exit, code,
3615            "Failed to start a transaction on the cloned volume%u\n",
3616            clonevol);
3617     VDONE;
3618
3619     VPRINT1("Setting flags on cloned volume %u ...", clonevol);
3620     code = AFSVolSetFlags(fromconn, clonetid, VTDeleteOnSalvage | VTOutOfService);      /*redundant */
3621     EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n",
3622            clonevol);
3623     VDONE;
3624
3625
3626     fromcall = rx_NewCall(fromconn);
3627
3628     VPRINT1("Starting volume dump from cloned volume %u...", clonevol);
3629     code = StartAFSVolDump(fromcall, clonetid, fromdate);
3630     EGOTO(error_exit, code, "Could not start the dump process \n");
3631     VDONE;
3632
3633     VPRINT1("Dumping volume %u...", afromvol);
3634     code = DumpFunction(fromcall, rock);
3635     EGOTO(error_exit, code, "Error while dumping volume \n");
3636     VDONE;
3637
3638   error_exit:
3639     /* now delete the clone */
3640     VPRINT1("Deleting the cloned volume %u ...", clonevol);
3641     code = AFSVolDeleteVolume(fromconn, clonetid);
3642     if (code) {
3643         fprintf(STDERR, "Failed to delete the cloned volume %lu\n",
3644                 (unsigned long)clonevol);
3645     } else {
3646         VDONE;
3647     }
3648
3649     if (fromcall) {
3650         code = rx_EndCall(fromcall, rxError);
3651         if (code) {
3652             fprintf(STDERR, "Error in rx_EndCall\n");
3653             if (!error)
3654                 error = code;
3655         }
3656     }
3657     if (clonetid) {
3658         VPRINT1("Ending transaction on cloned volume %u...", clonevol);
3659         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3660         if (code || rcode) {
3661             fprintf(STDERR,
3662                     "Could not end transaction on the cloned volume %lu\n",
3663                     (unsigned long)clonevol);
3664             if (!error)
3665                 error = (code ? code : rcode);
3666         }
3667         VDONE;
3668     }
3669     if (fromconn)
3670         rx_DestroyConnection(fromconn);
3671
3672     PrintError("", error);
3673     return (error);
3674 }
3675
3676
3677
3678 /*
3679  * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
3680  * the dump file <afilename>. WriteData does all the real work
3681  * after extracting params from the rock 
3682  */
3683 int
3684 UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
3685                  char tovolname[], int flags, afs_int32(*WriteData) (),
3686                  char *rock)
3687 {
3688     struct rx_connection *toconn, *tempconn;
3689     struct rx_call *tocall;
3690     afs_int32 totid, code, rcode, vcode, terror = 0;
3691     afs_int32 rxError = 0;
3692     struct volser_status tstatus;
3693     char partName[10];
3694     afs_int32 pvolid;
3695     afs_int32 temptid;
3696     int success;
3697     struct nvldbentry entry, storeEntry;
3698     afs_int32 error;
3699     int islocked;
3700     struct restoreCookie cookie;
3701     int reuseID;
3702     afs_int32 newDate, volflag, voltype, volsertype;
3703     int index, same, errcode;
3704     char apartName[10];
3705
3706
3707     memset(&cookie, 0, sizeof(cookie));
3708     islocked = 0;
3709     success = 0;
3710     error = 0;
3711     reuseID = 1;
3712     tocall = (struct rx_call *)0;
3713     toconn = (struct rx_connection *)0;
3714     tempconn = (struct rx_connection *)0;
3715     totid = 0;
3716     temptid = 0;
3717
3718     if (flags & RV_RDONLY) {
3719         voltype = ROVOL;
3720         volsertype = volser_RO;
3721     } else {
3722         voltype = RWVOL;
3723         volsertype = volser_RW;
3724     }
3725
3726     pvolid = tovolid;
3727     toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
3728     if (pvolid == 0) {          /*alot a new id if needed */
3729         vcode = VLDB_GetEntryByName(tovolname, &entry);
3730         if (vcode == VL_NOENT) {
3731             vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &pvolid);
3732             if (vcode) {
3733                 fprintf(STDERR, "Could not get an Id for the volume %s\n",
3734                         tovolname);
3735                 error = vcode;
3736                 goto refail;
3737             }
3738             reuseID = 0;
3739         } else if (flags & RV_RDONLY) {
3740             if (entry.flags & RW_EXISTS) {
3741                 fprintf(STDERR,
3742                         "Entry for ReadWrite volume %s already exists!\n",
3743                         entry.name);
3744                 error = VOLSERBADOP;
3745                 goto refail;
3746             }
3747             if (!entry.volumeId[ROVOL]) {
3748                 fprintf(STDERR,
3749                         "Existing entry for volume %s has no ReadOnly ID\n",
3750                         tovolname);
3751                 error = VOLSERBADOP;
3752                 goto refail;
3753             }
3754             pvolid = entry.volumeId[ROVOL];
3755         } else {
3756             pvolid = entry.volumeId[RWVOL];
3757         }
3758     }
3759     /* at this point we have a volume id to use/reuse for the volume to be restored */
3760     if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
3761         EGOTO1(refail, VOLSERBADOP,
3762                "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",
3763                tovolname);
3764     }
3765     MapPartIdIntoName(topart, partName);
3766     fprintf(STDOUT, "Restoring volume %s Id %lu on server %s partition %s ..",
3767             tovolname, (unsigned long)pvolid,
3768             hostutil_GetNameByINet(toserver), partName);
3769     fflush(STDOUT);
3770     code =
3771         AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0, &pvolid,
3772                            &totid);
3773     if (code) {
3774         if (flags & RV_FULLRST) {       /* full restore: delete then create anew */
3775             VPRINT1("Deleting the previous volume %u ...", pvolid);
3776
3777             code =
3778                 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3779             EGOTO1(refail, code, "Failed to start transaction on %u\n",
3780                    pvolid);
3781
3782             code =
3783                 AFSVolSetFlags(toconn, totid,
3784                                VTDeleteOnSalvage | VTOutOfService);
3785             EGOTO1(refail, code, "Could not set flags on volume %u \n",
3786                    pvolid);
3787
3788             code = AFSVolDeleteVolume(toconn, totid);
3789             EGOTO1(refail, code, "Could not delete volume %u\n", pvolid);
3790
3791             code = AFSVolEndTrans(toconn, totid, &rcode);
3792             totid = 0;
3793             if (!code)
3794                 code = rcode;
3795             EGOTO1(refail, code, "Could not end transaction on %u\n", pvolid);
3796
3797             VDONE;
3798
3799             code =
3800                 AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,
3801                                    &pvolid, &totid);
3802             EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
3803         } else {
3804             code =
3805                 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
3806             EGOTO1(refail, code, "Failed to start transaction on %u\n",
3807                    pvolid);
3808         }
3809     }
3810     cookie.parent = pvolid;
3811     cookie.type = voltype;
3812     cookie.clone = 0;
3813     strncpy(cookie.name, tovolname, VOLSER_OLDMAXVOLNAME);
3814
3815     tocall = rx_NewCall(toconn);
3816     terror = StartAFSVolRestore(tocall, totid, 1, &cookie);
3817     if (terror) {
3818         fprintf(STDERR, "Volume restore Failed \n");
3819         error = terror;
3820         goto refail;
3821     }
3822     code = WriteData(tocall, rock);
3823     if (code) {
3824         fprintf(STDERR, "Could not transmit data\n");
3825         error = code;
3826         goto refail;
3827     }
3828     terror = rx_EndCall(tocall, rxError);
3829     tocall = (struct rx_call *)0;
3830     if (terror) {
3831         fprintf(STDERR, "rx_EndCall Failed \n");
3832         error = terror;
3833         goto refail;
3834     }
3835     code = AFSVolGetStatus(toconn, totid, &tstatus);
3836     if (code) {
3837         fprintf(STDERR,
3838                 "Could not get status information about the volume %lu\n",
3839                 (unsigned long)pvolid);
3840         error = code;
3841         goto refail;
3842     }
3843     code = AFSVolSetIdsTypes(toconn, totid, tovolname, voltype, pvolid, 0, 0);
3844     if (code) {
3845         fprintf(STDERR, "Could not set the right type and ID on %lu\n",
3846                 (unsigned long)pvolid);
3847         error = code;
3848         goto refail;
3849     }
3850     newDate = time(0);
3851     code = AFSVolSetDate(toconn, totid, newDate);
3852     if (code) {
3853         fprintf(STDERR, "Could not set the date on %lu\n",
3854                 (unsigned long)pvolid);
3855         error = code;
3856         goto refail;
3857     }
3858
3859     volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0);      /* off or on-line */
3860     code = AFSVolSetFlags(toconn, totid, volflag);
3861     if (code) {
3862         fprintf(STDERR, "Could not mark %lu online\n", (unsigned long)pvolid);
3863         error = code;
3864         goto refail;
3865     }
3866
3867 /* It isn't handled right in refail */
3868     code = AFSVolEndTrans(toconn, totid, &rcode);
3869     totid = 0;
3870     if (!code)
3871         code = rcode;
3872     if (code) {
3873         fprintf(STDERR, "Could not end transaction on %lu\n",
3874                 (unsigned long)pvolid);
3875         error = code;
3876         goto refail;
3877     }
3878
3879     success = 1;
3880     fprintf(STDOUT, " done\n");
3881     fflush(STDOUT);
3882     if (success && (!reuseID || (flags & RV_FULLRST))) {
3883         /* Volume was restored on the file server, update the 
3884          * VLDB to reflect the change.
3885          */
3886         vcode = VLDB_GetEntryByID(pvolid, voltype, &entry);
3887         if (vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
3888             fprintf(STDERR,
3889                     "Could not fetch the entry for volume number %lu from VLDB \n",
3890                     (unsigned long)pvolid);
3891             error = vcode;
3892             goto refail;
3893         }
3894         if (!vcode)
3895             MapHostToNetwork(&entry);
3896         if (vcode == VL_NOENT) {        /* it doesnot exist already */
3897             /*make the vldb return this indication specifically */
3898             VPRINT("------- Creating a new VLDB entry ------- \n");
3899             strcpy(entry.name, tovolname);
3900             entry.nServers = 1;
3901             entry.serverNumber[0] = toserver;   /*should be indirect */
3902             entry.serverPartition[0] = topart;
3903             entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3904             entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
3905             if (flags & RV_RDONLY)
3906                 entry.volumeId[ROVOL] = pvolid;
3907             else if (tstatus.cloneID != 0) {
3908                 entry.volumeId[ROVOL] = tstatus.cloneID;        /*this should come from status info on the volume if non zero */
3909             } else
3910                 entry.volumeId[ROVOL] = INVALID_BID;
3911             entry.volumeId[RWVOL] = pvolid;
3912             entry.cloneId = 0;
3913             if (tstatus.backupID != 0) {
3914                 entry.volumeId[BACKVOL] = tstatus.backupID;
3915                 /*this should come from status info on the volume if non zero */
3916             } else
3917                 entry.volumeId[BACKVOL] = INVALID_BID;
3918             MapNetworkToHost(&entry, &storeEntry);
3919             vcode = VLDB_CreateEntry(&storeEntry);
3920             if (vcode) {
3921                 fprintf(STDERR,
3922                         "Could not create the VLDB entry for volume number %lu  \n",
3923                         (unsigned long)pvolid);
3924                 error = vcode;
3925                 goto refail;
3926             }
3927             islocked = 0;
3928             if (verbose)
3929                 EnumerateEntry(&entry);
3930         } else {                /*update the existing entry */
3931             if (verbose) {
3932                 fprintf(STDOUT, "Updating the existing VLDB entry\n");
3933                 fprintf(STDOUT, "------- Old entry -------\n");
3934                 EnumerateEntry(&entry);
3935                 fprintf(STDOUT, "------- New entry -------\n");
3936             }
3937             vcode =
3938                 ubik_Call(VL_SetLock, cstruct, 0, pvolid, voltype,
3939                           VLOP_RESTORE);
3940             if (vcode) {
3941                 fprintf(STDERR,
3942                         "Could not lock the entry for volume number %lu \n",
3943                         (unsigned long)pvolid);
3944                 error = vcode;
3945                 goto refail;
3946             }
3947             islocked = 1;
3948             strcpy(entry.name, tovolname);
3949
3950             /* Update the vlentry with the new information */
3951             if (flags & RV_RDONLY)
3952                 index = Lp_ROMatch(toserver, topart, &entry) - 1;
3953             else
3954                 index = Lp_GetRwIndex(&entry);
3955             if (index == -1) {
3956                 /* Add the new site for the volume being restored */
3957                 entry.serverNumber[entry.nServers] = toserver;
3958                 entry.serverPartition[entry.nServers] = topart;
3959                 entry.serverFlags[entry.nServers] =
3960                     (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
3961                 entry.nServers++;
3962             } else {
3963                 /* This volume should be deleted on the old site
3964                  * if its different from new site.
3965                  */
3966                 same =
3967                     VLDB_IsSameAddrs(toserver, entry.serverNumber[index],
3968                                      &errcode);
3969                 EPRINT2(errcode,
3970                         "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
3971                         toserver, errcode);
3972                 if ((!errcode && !same)
3973                     || (entry.serverPartition[index] != topart)) {
3974                     tempconn =
3975                         UV_Bind(entry.serverNumber[index],
3976                                 AFSCONF_VOLUMEPORT);
3977
3978                     MapPartIdIntoName(entry.serverPartition[index],
3979                                       apartName);
3980                     VPRINT3
3981                         ("Deleting the previous volume %u on server %s, partition %s ...",
3982                          pvolid,
3983                          hostutil_GetNameByINet(entry.serverNumber[index]),
3984                          apartName);
3985                     code =
3986                         AFSVolTransCreate(tempconn, pvolid,
3987                                           entry.serverPartition[index],
3988                                           ITOffline, &temptid);
3989                     if (!code) {
3990                         code =
3991                             AFSVolSetFlags(tempconn, temptid,
3992                                            VTDeleteOnSalvage |
3993                                            VTOutOfService);
3994                         if (code) {
3995                             fprintf(STDERR,
3996                                     "Could not set flags on volume %lu on the older site\n",
3997                                     (unsigned long)pvolid);
3998                             error = code;
3999                             goto refail;
4000                         }
4001                         code = AFSVolDeleteVolume(tempconn, temptid);
4002                         if (code) {
4003                             fprintf(STDERR,
4004                                     "Could not delete volume %lu on the older site\n",
4005                                     (unsigned long)pvolid);
4006                             error = code;
4007                             goto refail;
4008                         }
4009                         code = AFSVolEndTrans(tempconn, temptid, &rcode);
4010                         temptid = 0;
4011                         if (!code)
4012                             code = rcode;
4013                         if (code) {
4014                             fprintf(STDERR,
4015                                     "Could not end transaction on volume %lu on the older site\n",
4016                                     (unsigned long)pvolid);
4017                             error = code;
4018                             goto refail;
4019                         }
4020                         VDONE;
4021                         MapPartIdIntoName(entry.serverPartition[index],
4022                                           partName);
4023                     }
4024                 }
4025                 entry.serverNumber[index] = toserver;
4026                 entry.serverPartition[index] = topart;
4027             }
4028
4029             entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
4030             MapNetworkToHost(&entry, &storeEntry);
4031             vcode =
4032                 VLDB_ReplaceEntry(pvolid, voltype, &storeEntry,
4033                                   LOCKREL_OPCODE | LOCKREL_AFSID |
4034                                   LOCKREL_TIMESTAMP);
4035             if (vcode) {
4036                 fprintf(STDERR,
4037                         "Could not update the entry for volume number %lu  \n",
4038                         (unsigned long)pvolid);
4039                 error = vcode;
4040                 goto refail;
4041             }
4042             islocked = 0;
4043             if (verbose)
4044                 EnumerateEntry(&entry);
4045         }
4046
4047
4048     }
4049   refail:
4050     if (tocall) {
4051         code = rx_EndCall(tocall, rxError);
4052         if (!error)
4053             error = code;
4054     }
4055     if (islocked) {
4056         vcode =
4057             ubik_Call(VL_ReleaseLock, cstruct, 0, pvolid, voltype,
4058                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4059         if (vcode) {
4060             fprintf(STDERR,
4061                     "Could not release lock on the VLDB entry for the volume %lu\n",
4062                     (unsigned long)pvolid);
4063             if (!error)
4064                 error = vcode;
4065         }
4066     }
4067     if (totid) {
4068         code = AFSVolEndTrans(toconn, totid, &rcode);
4069         if (!code)
4070             code = rcode;
4071         if (code) {
4072             fprintf(STDERR, "Could not end transaction on the volume %lu \n",
4073                     (unsigned long)pvolid);
4074             if (!error)
4075                 error = code;
4076         }
4077     }
4078     if (temptid) {
4079         code = AFSVolEndTrans(toconn, temptid, &rcode);
4080         if (!code)
4081             code = rcode;
4082         if (code) {
4083             fprintf(STDERR, "Could not end transaction on the volume %lu \n",
4084                     (unsigned long)pvolid);
4085             if (!error)
4086                 error = code;
4087         }
4088     }
4089     if (tempconn)
4090         rx_DestroyConnection(tempconn);
4091     if (toconn)
4092         rx_DestroyConnection(toconn);
4093     PrintError("", error);
4094     return error;
4095 }
4096
4097
4098 /*unlocks the vldb entry associated with <volid> */
4099 int
4100 UV_LockRelease(afs_int32 volid)
4101 {
4102
4103
4104     afs_int32 vcode;
4105
4106     VPRINT("Binding to the VLDB server\n");
4107     vcode =
4108         ubik_Call(VL_ReleaseLock, cstruct, 0, volid, -1,
4109                   LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4110     if (vcode) {
4111         fprintf(STDERR,
4112                 "Could not unlock the entry for volume number %lu in VLDB \n",
4113                 (unsigned long)volid);
4114         PrintError("", vcode);
4115         return (vcode);
4116     }
4117     VPRINT("VLDB updated\n");
4118     return 0;
4119
4120 }
4121
4122 /*adds <server> and <part> as a readonly replication site for <volid>
4123 *in vldb */
4124 int
4125 UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
4126 {
4127     int j, nro = 0, islocked = 0;
4128     struct nvldbentry entry, storeEntry;
4129     afs_int32 vcode, error = 0;
4130     char apartName[10];
4131
4132     error = ubik_Call(VL_SetLock, cstruct, 0, volid, RWVOL, VLOP_ADDSITE);
4133     if (error) {