vos-syncv-dryrun-20080210
[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 #include <string.h>
20 #ifdef  AFS_AIX_ENV
21 #include <sys/statfs.h>
22 #endif
23 #ifdef AFS_NT40_ENV
24 #include <fcntl.h>
25 #include <winsock2.h>
26 #else
27 #include <sys/file.h>
28 #include <netinet/in.h>
29 #endif
30
31 #include <lock.h>
32 #include <afs/voldefs.h>
33 #include <rx/xdr.h>
34 #include <rx/rx.h>
35 #include <afs/vlserver.h>
36 #include <afs/nfs.h>
37 #include <afs/cellconfig.h>
38 #include <afs/keys.h>
39 #include <ubik.h>
40 #include <afs/afsint.h>
41 #include "volser.h"
42 #include "volint.h"
43 #include "lockdata.h"
44 #include <afs/com_err.h>
45 #include <rx/rxkad.h>
46 #include <afs/kautils.h>
47 #include <afs/cmd.h>
48 #include <errno.h>
49 #define ERRCODE_RANGE 8         /* from error_table.h */
50 #define CLOCKSKEW   2           /* not really skew, but resolution */
51 #define CLOCKADJ(x) (((x) < CLOCKSKEW) ? 0 : (x) - CLOCKSKEW)
52
53 /* for UV_MoveVolume() recovery */
54
55 #include <afs/procmgmt.h>       /* signal(), kill(), wait(), etc. */
56 #include <setjmp.h>
57
58 #include <volser_prototypes.h>
59
60 struct ubik_client *cstruct;
61 int verbose = 0;
62
63 struct release {
64     afs_int32 crtime;
65     afs_int32 uptime;
66     afs_int32 vldbEntryIndex;
67 };
68
69 /* Utility macros used by rest of this source file */
70 #define EPRINT(ec, es) \
71 do { \
72         fprintf(STDERR, "\n"); \
73         fprintf(STDERR, (es)); \
74         PrintError("   ",ec); \
75 } while (0)
76
77 #define EPRINT1(ec, es, ep1) \
78 do { \
79         fprintf(STDERR, "\n"); \
80         fprintf(STDERR, (es), (ep1)); \
81         PrintError("   ",ec); \
82 } while (0)
83
84 #define EPRINT2(ec, es, ep1, ep2) \
85 do { \
86         fprintf(STDERR, "\n"); \
87         fprintf(STDERR, (es), (ep1), (ep2)); \
88         PrintError("   ",ec); \
89 } while (0)
90
91 #define EPRINT3(ec, es, ep1, ep2, ep3) \
92 do { \
93         fprintf(STDERR, "\n"); \
94         fprintf(STDERR, (es), (ep1), (ep2), (ep3)); \
95         PrintError("   ",ec); \
96 } while (0)
97
98 #define EGOTO(where, ec, es) \
99 do { \
100         if (ec) { \
101                 EPRINT((ec),(es)); \
102                 error = (ec); \
103                 goto where; \
104         } \
105 } while (0)
106
107 #define EGOTO1(where, ec, es, ep1) \
108 do { \
109         if (ec) { \
110                 EPRINT1((ec),(es),(ep1)); \
111                 error = (ec); \
112                 goto where; \
113         } \
114 } while (0)
115
116 #define EGOTO2(where, ec, es, ep1, ep2) \
117 do { \
118         if (ec) { \
119                 EPRINT2((ec),(es),(ep1),(ep2)); \
120                 error = (ec); \
121                 goto where; \
122         } \
123 } while (0)
124
125 #define EGOTO3(where, ec, es, ep1, ep2, ep3) \
126 do { \
127         if (ec) { \
128                 EPRINT3((ec),(es),(ep1),(ep2),(ep3)); \
129                 error = (ec); \
130                 goto where; \
131         } \
132 } while (0)
133
134 #define VPRINT(es) \
135         { if (verbose) { fprintf(STDOUT, (es)); fflush(STDOUT); } }
136 #define VPRINT1(es, p) \
137         { if (verbose) { fprintf(STDOUT, (es), (p)); fflush(STDOUT); } }
138 #define VPRINT2(es, p1, p2) \
139         { if (verbose) { fprintf(STDOUT, (es), (p1), (p2)); fflush(STDOUT); } }
140 #define VPRINT3(es, p1, p2, p3) \
141         { if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
142 #define VDONE \
143         { if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
144 #define VEPRINT(es) \
145         { if (verbose) { fprintf(STDERR, (es)); fflush(STDERR); } }
146 #define VEPRINT1(es, p) \
147         { if (verbose) { fprintf(STDERR, (es), (p)); fflush(STDERR); } }
148 #define VEPRINT2(es, p1, p2) \
149         { if (verbose) { fprintf(STDERR, (es), (p1), (p2)); fflush(STDERR); } }
150 #define VEPRINT3(es, p1, p2, p3) \
151         { if (verbose) { fprintf(STDERR, (es), (p1), (p2), (p3)); fflush(STDERR); } }
152 #define VEDONE \
153         { if (verbose) { fprintf(STDERR, " done\n"); fflush(STDERR); } }
154
155
156
157 /* getting rid of this */
158 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
159
160
161 /* Protos for static routines */
162 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
163                                       afs_int32 apart, afs_int32 okvol,
164                                       afs_int32 delvol);
165 static int DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
166                   afs_int32 flags);
167 static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
168                     struct rx_connection **connPtr, afs_int32 * transPtr,
169                     afs_int32 * crtimePtr, afs_int32 * uptimePtr);
170 static int SimulateForwardMultiple(struct rx_connection *fromconn,
171                                    afs_int32 fromtid, afs_int32 fromdate,
172                                    manyDests * tr, afs_int32 flags,
173                                    void *cookie, manyResults * results);
174 static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
175                              afs_int32 apart, afs_int32 * modentry,
176                              afs_uint32 * maxvolid);
177
178
179 /*map the partition <partId> into partition name <partName>*/
180 void
181 MapPartIdIntoName(afs_int32 partId, char *partName)
182 {
183     if (partId < 26) {          /* what if partId > = 26 ? */
184         strcpy(partName, "/vicep");
185         partName[6] = partId + 'a';
186         partName[7] = '\0';
187         return;
188     } else if (partId < VOLMAXPARTS) {
189         strcpy(partName, "/vicep");
190         partId -= 26;
191         partName[6] = 'a' + (partId / 26);
192         partName[7] = 'a' + (partId % 26);
193         partName[8] = '\0';
194         return;
195     }
196 }
197
198 int
199 yesprompt(char *str)
200 {
201     int response, c;
202     int code;
203
204     fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
205     response = c = getchar();
206     while (!(c == EOF || c == '\n'))
207         c = getchar();          /*skip to end of line */
208     code = (response == 'y' || response == 'Y');
209     return code;
210 }
211
212
213 int
214 PrintError(char *msg, afs_int32 errcode)
215 {
216     fprintf(STDERR, msg);
217     /*replace by a big switch statement */
218     switch (errcode) {
219     case 0:
220         break;
221     case -1:
222         fprintf(STDERR, "Possible communication failure\n");
223         break;
224     case VSALVAGE:
225         fprintf(STDERR, "Volume needs to be salvaged\n");
226         break;
227     case VNOVNODE:
228         fprintf(STDERR, "Bad vnode number quoted\n");
229         break;
230     case VNOVOL:
231         fprintf(STDERR,
232                 "Volume not attached, does not exist, or not on line\n");
233         break;
234     case VVOLEXISTS:
235         fprintf(STDERR, "Volume already exists\n");
236         break;
237     case VNOSERVICE:
238         fprintf(STDERR, "Volume is not in service\n");
239         break;
240     case VOFFLINE:
241         fprintf(STDERR, "Volume is off line\n");
242         break;
243     case VONLINE:
244         fprintf(STDERR, "Volume is already on line\n");
245         break;
246     case VDISKFULL:
247         fprintf(STDERR, "Partition is full\n");
248         break;
249     case VOVERQUOTA:
250         fprintf(STDERR, "Volume max quota exceeded\n");
251         break;
252     case VBUSY:
253         fprintf(STDERR, "Volume temporarily unavailable\n");
254         break;
255     case VMOVED:
256         fprintf(STDERR, "Volume has moved to another server\n");
257         break;
258     case VL_IDEXIST:
259         fprintf(STDERR, "VLDB: volume Id exists in the vldb\n");
260         break;
261     case VL_IO:
262         fprintf(STDERR, "VLDB: a read terminated too early\n");
263         break;
264     case VL_NAMEEXIST:
265         fprintf(STDERR, "VLDB: volume entry exists in the vldb\n");
266         break;
267     case VL_CREATEFAIL:
268         fprintf(STDERR, "VLDB: internal creation failure\n");
269         break;
270     case VL_NOENT:
271         fprintf(STDERR, "VLDB: no such entry\n");
272         break;
273     case VL_EMPTY:
274         fprintf(STDERR, "VLDB: vldb database is empty\n");
275         break;
276     case VL_ENTDELETED:
277         fprintf(STDERR, "VLDB: entry is deleted (soft delete)\n");
278         break;
279     case VL_BADNAME:
280         fprintf(STDERR, "VLDB: volume name is illegal\n");
281         break;
282     case VL_BADINDEX:
283         fprintf(STDERR, "VLDB: index was out of range\n");
284         break;
285     case VL_BADVOLTYPE:
286         fprintf(STDERR, "VLDB: bad volume type\n");
287         break;
288     case VL_BADSERVER:
289         fprintf(STDERR, "VLDB: illegal server number (not within limits)\n");
290         break;
291     case VL_BADPARTITION:
292         fprintf(STDERR, "VLDB: bad partition number\n");
293         break;
294     case VL_REPSFULL:
295         fprintf(STDERR, "VLDB: run out of space for replication sites\n");
296         break;
297     case VL_NOREPSERVER:
298         fprintf(STDERR, "VLDB: no such repsite server exists\n");
299         break;
300     case VL_DUPREPSERVER:
301         fprintf(STDERR, "VLDB: replication site server already exists\n");
302         break;
303     case VL_RWNOTFOUND:
304         fprintf(STDERR, "VLDB: parent r/w entry not found\n");
305         break;
306     case VL_BADREFCOUNT:
307         fprintf(STDERR, "VLDB: illegal reference count number\n");
308         break;
309     case VL_SIZEEXCEEDED:
310         fprintf(STDERR, "VLDB: vldb size for attributes exceeded\n");
311         break;
312     case VL_BADENTRY:
313         fprintf(STDERR, "VLDB: bad incoming vldb entry\n");
314         break;
315     case VL_BADVOLIDBUMP:
316         fprintf(STDERR, "VLDB: illegal max volid increment\n");
317         break;
318     case VL_IDALREADYHASHED:
319         fprintf(STDERR, "VLDB: (RO/BACK) Id already hashed\n");
320         break;
321     case VL_ENTRYLOCKED:
322         fprintf(STDERR, "VLDB: vldb entry is already locked\n");
323         break;
324     case VL_BADVOLOPER:
325         fprintf(STDERR, "VLDB: bad volume operation code\n");
326         break;
327     case VL_BADRELLOCKTYPE:
328         fprintf(STDERR, "VLDB: bad release lock type\n");
329         break;
330     case VL_RERELEASE:
331         fprintf(STDERR, "VLDB: status report: last release was aborted\n");
332         break;
333     case VL_BADSERVERFLAG:
334         fprintf(STDERR, "VLDB: invalid replication site server flag\n");
335         break;
336     case VL_PERM:
337         fprintf(STDERR, "VLDB: no permission access for call\n");
338         break;
339     case VOLSERREAD_DUMPERROR:
340         fprintf(STDERR,
341                 "VOLSER:  Problems encountered in reading the dump file !\n");
342         break;
343     case VOLSERDUMPERROR:
344         fprintf(STDERR, "VOLSER: Problems encountered in doing the dump !\n");
345         break;
346     case VOLSERATTACH_ERROR:
347         fprintf(STDERR, "VOLSER: Could not attach the volume\n");
348         break;
349     case VOLSERDETACH_ERROR:
350         fprintf(STDERR, "VOLSER: Could not detach the volume\n");
351         break;
352     case VOLSERILLEGAL_PARTITION:
353         fprintf(STDERR, "VOLSER: encountered illegal partition number\n");
354         break;
355     case VOLSERBAD_ACCESS:
356         fprintf(STDERR, "VOLSER: permission denied, not a super user\n");
357         break;
358     case VOLSERVLDB_ERROR:
359         fprintf(STDERR, "VOLSER: error detected in the VLDB\n");
360         break;
361     case VOLSERBADNAME:
362         fprintf(STDERR, "VOLSER: error in volume name\n");
363         break;
364     case VOLSERVOLMOVED:
365         fprintf(STDERR, "VOLSER: volume has moved\n");
366         break;
367     case VOLSERBADOP:
368         fprintf(STDERR, "VOLSER: illegal operation\n");
369         break;
370     case VOLSERBADRELEASE:
371         fprintf(STDERR, "VOLSER: release could not be completed\n");
372         break;
373     case VOLSERVOLBUSY:
374         fprintf(STDERR, "VOLSER: volume is busy\n");
375         break;
376     case VOLSERNO_MEMORY:
377         fprintf(STDERR, "VOLSER: volume server is out of memory\n");
378         break;
379     case VOLSERNOVOL:
380         fprintf(STDERR,
381                 "VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
382         break;
383     case VOLSERMULTIRWVOL:
384         fprintf(STDERR,
385                 "VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
386         break;
387     case VOLSERFAILEDOP:
388         fprintf(STDERR,
389                 "VOLSER: not all entries were successfully processed\n");
390         break;
391     default:
392         {
393
394             afs_int32 offset;
395
396             initialize_KA_error_table();
397             initialize_RXK_error_table();
398             initialize_KTC_error_table();
399             initialize_ACFG_error_table();
400             initialize_CMD_error_table();
401             initialize_VL_error_table();
402
403             offset = errcode & ((1 << ERRCODE_RANGE) - 1);
404             fprintf(STDERR, "%s: %s\n", afs_error_table_name(errcode),
405                     afs_error_message(errcode));
406             break;
407         }
408     }
409     return 0;
410 }
411
412 void init_volintInfo(struct volintInfo *vinfo) {
413     memset(vinfo, 0, sizeof(struct volintInfo));
414
415     vinfo->maxquota = -1;
416     vinfo->dayUse = -1;
417     vinfo->creationDate = -1;
418     vinfo->updateDate = -1;
419     vinfo->flags = -1;
420     vinfo->spare0 = -1;
421     vinfo->spare1 = -1;
422     vinfo->spare2 = -1;
423     vinfo->spare3 = -1;
424 }
425
426 static struct rx_securityClass *uvclass = 0;
427 static int uvindex = -1;
428 /* called by VLDBClient_Init to set the security module to be used in the RPC */
429 int
430 UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
431 {
432     uvindex = aindex;
433     uvclass = as;
434     return 0;
435 }
436
437 /* bind to volser on <port> <aserver> */
438 /* takes server address in network order, port in host order.  dumb */
439 struct rx_connection *
440 UV_Bind(afs_int32 aserver, afs_int32 port)
441 {
442     register struct rx_connection *tc;
443
444     tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass,
445                           uvindex);
446     return tc;
447 }
448
449 /* if <okvol> is allright(indicated by beibg able to
450  * start a transaction, delete the <delvol> */
451 static afs_int32
452 CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
453                      afs_int32 okvol, afs_int32 delvol)
454 {
455     afs_int32 error, code, tid, rcode;
456
457     error = 0;
458     code = 0;
459
460     if (okvol == 0) {
461         code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
462         if (!error && code)
463             error = code;
464         code = AFSVolDeleteVolume(aconn, tid);
465         if (!error && code)
466             error = code;
467         code = AFSVolEndTrans(aconn, tid, &rcode);
468         if (!code)
469             code = rcode;
470         if (!error && code)
471             error = code;
472         return error;
473     } else {
474         code = AFSVolTransCreate(aconn, okvol, apart, ITOffline, &tid);
475         if (!code) {
476             code = AFSVolEndTrans(aconn, tid, &rcode);
477             if (!code)
478                 code = rcode;
479             if (!error && code)
480                 error = code;
481             code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
482             if (!error && code)
483                 error = code;
484             code = AFSVolDeleteVolume(aconn, tid);
485             if (!error && code)
486                 error = code;
487             code = AFSVolEndTrans(aconn, tid, &rcode);
488             if (!code)
489                 code = rcode;
490             if (!error && code)
491                 error = code;
492         } else
493             error = code;
494         return error;
495     }
496 }
497
498 /* called by EmuerateEntry, show vldb entry in a reasonable format */
499 void
500 SubEnumerateEntry(struct nvldbentry *entry)
501 {
502     int i;
503     char pname[10];
504     int isMixed = 0;
505
506 #ifdef notdef
507     fprintf(STDOUT, "   readWriteID %-10u ", entry->volumeId[RWVOL]);
508     if (entry->flags & RW_EXISTS)
509         fprintf(STDOUT, " valid \n");
510     else
511         fprintf(STDOUT, " invalid \n");
512     fprintf(STDOUT, "   readOnlyID  %-10u ", entry->volumeId[ROVOL]);
513     if (entry->flags & RO_EXISTS)
514         fprintf(STDOUT, " valid \n");
515     else
516         fprintf(STDOUT, " invalid \n");
517     fprintf(STDOUT, "   backUpID    %-10u ", entry->volumeId[BACKVOL]);
518     if (entry->flags & BACK_EXISTS)
519         fprintf(STDOUT, " valid \n");
520     else
521         fprintf(STDOUT, " invalid \n");
522     if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
523         fprintf(STDOUT, "    releaseClone %-10u \n", entry->cloneId);
524 #else
525     if (entry->flags & RW_EXISTS)
526         fprintf(STDOUT, "    RWrite: %-10u", entry->volumeId[RWVOL]);
527     if (entry->flags & RO_EXISTS)
528         fprintf(STDOUT, "    ROnly: %-10u", entry->volumeId[ROVOL]);
529     if (entry->flags & BACK_EXISTS)
530         fprintf(STDOUT, "    Backup: %-10u", entry->volumeId[BACKVOL]);
531     if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
532         fprintf(STDOUT, "    RClone: %-10lu", (unsigned long)entry->cloneId);
533     fprintf(STDOUT, "\n");
534 #endif
535     fprintf(STDOUT, "    number of sites -> %lu\n",
536             (unsigned long)entry->nServers);
537     for (i = 0; i < entry->nServers; i++) {
538         if (entry->serverFlags[i] & NEW_REPSITE)
539             isMixed = 1;
540     }
541     for (i = 0; i < entry->nServers; i++) {
542         MapPartIdIntoName(entry->serverPartition[i], pname);
543         fprintf(STDOUT, "       server %s partition %s ",
544                 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
545         if (entry->serverFlags[i] & ITSRWVOL)
546             fprintf(STDOUT, "RW Site ");
547         else
548             fprintf(STDOUT, "RO Site ");
549         if (isMixed) {
550             if (entry->serverFlags[i] & NEW_REPSITE)
551                 fprintf(STDOUT," -- New release");
552             else
553                 if (!(entry->serverFlags[i] & ITSRWVOL))
554                     fprintf(STDOUT," -- Old release");
555         } else {
556             if (entry->serverFlags[i] & RO_DONTUSE)
557                 fprintf(STDOUT, " -- Not released");
558         }
559         fprintf(STDOUT, "\n");
560     }
561
562     return;
563
564 }
565
566 /*enumerate the vldb entry corresponding to <entry> */
567 void
568 EnumerateEntry(struct nvldbentry *entry)
569 {
570
571     fprintf(STDOUT, "\n");
572     fprintf(STDOUT, "%s \n", entry->name);
573     SubEnumerateEntry(entry);
574     return;
575 }
576
577 /* forcibly remove a volume.  Very dangerous call */
578 int
579 UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
580 {
581     register struct rx_connection *tconn;
582     register afs_int32 code;
583
584     tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
585     if (tconn) {
586         code = AFSVolNukeVolume(tconn, partid, volid);
587         rx_DestroyConnection(tconn);
588     } else
589         code = 0;
590     return code;
591 }
592
593 /* like df. Return usage of <pname> on <server> in <partition> */
594 int
595 UV_PartitionInfo(afs_int32 server, char *pname,
596                  struct diskPartition *partition)
597 {
598     register struct rx_connection *aconn;
599     afs_int32 code;
600
601     code = 0;
602     aconn = (struct rx_connection *)0;
603     aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
604     code = AFSVolPartitionInfo(aconn, pname, partition);
605     if (code) {
606         fprintf(STDERR, "Could not get information on partition %s\n", pname);
607         PrintError("", code);
608     }
609     if (aconn)
610         rx_DestroyConnection(aconn);
611     return code;
612 }
613
614 /* old interface to create volume */
615 int
616 UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname,
617                 afs_int32 * anewid)
618 {
619     afs_int32 code;
620     code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
621     return code;
622 }
623
624 /* create a volume, given a server, partition number, volume name --> sends
625 * back new vol id in <anewid>*/
626 int
627 UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname,
628                  afs_int32 aquota, afs_int32 aspare1, afs_int32 aspare2,
629                  afs_int32 aspare3, afs_int32 aspare4, afs_int32 * anewid)
630 {
631
632     register struct rx_connection *aconn;
633     afs_int32 tid;
634     register afs_int32 code;
635     afs_int32 error;
636     afs_int32 rcode, vcode;
637     struct nvldbentry entry, storeEntry;        /*the new vldb entry */
638     struct volintInfo tstatus;
639
640     tid = 0;
641     aconn = (struct rx_connection *)0;
642     error = 0;
643
644     init_volintInfo(&tstatus);
645     tstatus.maxquota = aquota;
646
647     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
648     /* next the next 3 available ids from the VLDB */
649     vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 3, anewid);
650     EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n", aname);
651
652     code =
653         AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
654     EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n", aname,
655            *anewid);
656
657     code = AFSVolSetInfo(aconn, tid, &tstatus);
658     if (code)
659         EPRINT(code, "Could not change quota, continuing...\n");
660
661     code = AFSVolSetFlags(aconn, tid, 0);       /* bring it online (mark it InService */
662     EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n", aname,
663            *anewid);
664
665     VPRINT2("Volume %s %u created and brought online\n", aname, *anewid);
666
667     /* set up the vldb entry for this volume */
668     strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
669     entry.nServers = 1;
670     entry.serverNumber[0] = aserver;    /* this should have another 
671                                          * level of indirection later */
672     entry.serverPartition[0] = apart;   /* this should also have 
673                                          * another indirection level */
674     entry.flags = RW_EXISTS;    /* this records that rw volume exists */
675     entry.serverFlags[0] = ITSRWVOL;    /*this rep site has rw  vol */
676     entry.volumeId[RWVOL] = *anewid;
677     entry.volumeId[ROVOL] = *anewid + 1;        /* rw,ro, bk id are related in the default case */
678     entry.volumeId[BACKVOL] = *anewid + 2;
679     entry.cloneId = 0;
680     /*map into right byte order, before passing to xdr, the stuff has to be in host
681      * byte order. Xdr converts it into network order */
682     MapNetworkToHost(&entry, &storeEntry);
683     /* create the vldb entry */
684     vcode = VLDB_CreateEntry(&storeEntry);
685     if (vcode) {
686         fprintf(STDERR,
687                 "Could not create a VLDB entry for the volume %s %lu\n",
688                 aname, (unsigned long)*anewid);
689         /*destroy the created volume */
690         VPRINT1("Deleting the newly created volume %u\n", *anewid);
691         AFSVolDeleteVolume(aconn, tid);
692         error = vcode;
693         goto cfail;
694     }
695     VPRINT2("Created the VLDB entry for the volume %s %u\n", aname, *anewid);
696     /* volume created, now terminate the transaction and release the connection */
697     code = AFSVolEndTrans(aconn, tid, &rcode);  /*if it crashes before this
698                                                  * the volume will come online anyway when transaction timesout , so if
699                                                  * vldb entry exists then the volume is guaranteed to exist too wrt create */
700     tid = 0;
701     if (code) {
702         fprintf(STDERR,
703                 "Failed to end the transaction on the volume %s %lu\n", aname,
704                 (unsigned long)*anewid);
705         error = code;
706         goto cfail;
707     }
708
709   cfail:
710     if (tid) {
711         code = AFSVolEndTrans(aconn, tid, &rcode);
712         if (code)
713             fprintf(STDERR, "WARNING: could not end transaction\n");
714     }
715     if (aconn)
716         rx_DestroyConnection(aconn);
717     PrintError("", error);
718     return error;
719
720
721 }
722
723 /* create a volume, given a server, partition number, volume name --> sends
724 * back new vol id in <anewid>*/
725 int
726 UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname,
727                 afs_int32 aid)
728 {
729     register struct rx_connection *aconn;
730     afs_int32 error;
731     afs_int32 vcode;
732     struct nvldbentry entry, storeEntry;        /*the new vldb entry */
733
734     aconn = (struct rx_connection *)0;
735     error = 0;
736
737     /* set up the vldb entry for this volume */
738     strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
739     entry.nServers = 1;
740     entry.serverNumber[0] = aserver;    /* this should have another 
741                                          * level of indirection later */
742     entry.serverPartition[0] = apart;   /* this should also have 
743                                          * another indirection level */
744     entry.flags = RW_EXISTS;    /* this records that rw volume exists */
745     entry.serverFlags[0] = ITSRWVOL;    /*this rep site has rw  vol */
746     entry.volumeId[RWVOL] = aid;
747 #ifdef notdef
748     entry.volumeId[ROVOL] = anewid + 1; /* rw,ro, bk id are related in the default case */
749     entry.volumeId[BACKVOL] = *anewid + 2;
750 #else
751     entry.volumeId[ROVOL] = 0;
752     entry.volumeId[BACKVOL] = 0;
753 #endif
754     entry.cloneId = 0;
755     /*map into right byte order, before passing to xdr, the stuff has to be in host
756      * byte order. Xdr converts it into network order */
757     MapNetworkToHost(&entry, &storeEntry);
758     /* create the vldb entry */
759     vcode = VLDB_CreateEntry(&storeEntry);
760     if (vcode) {
761         fprintf(STDERR,
762                 "Could not create a VLDB entry for the  volume %s %lu\n",
763                 aname, (unsigned long)aid);
764         error = vcode;
765         goto cfail;
766     }
767     VPRINT2("Created the VLDB entry for the volume %s %u\n", aname, aid);
768
769   cfail:
770     if (aconn)
771         rx_DestroyConnection(aconn);
772     PrintError("", error);
773     return error;
774 }
775
776 /* Delete the volume <volid>on <aserver> <apart>
777  * the physical entry gets removed from the vldb only if the ref count 
778  * becomes zero
779  */
780 int
781 UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
782 {
783     struct rx_connection *aconn = (struct rx_connection *)0;
784     afs_int32 ttid = 0;
785     afs_int32 code, rcode;
786     afs_int32 error = 0;
787     struct nvldbentry entry, storeEntry;
788     int islocked = 0;
789     afs_int32 avoltype = -1, vtype;
790     int notondisk = 0, notinvldb = 0;
791
792     /* Find and read bhe VLDB entry for this volume */
793     code = ubik_VL_SetLock(cstruct, 0, avolid, avoltype, VLOP_DELETE);
794     if (code) {
795         if (code != VL_NOENT) {
796             EGOTO1(error_exit, code,
797                    "Could not lock VLDB entry for the volume %u\n", avolid);
798         }
799         notinvldb = 1;
800     } else {
801         islocked = 1;
802
803         code = VLDB_GetEntryByID(avolid, avoltype, &entry);
804         EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",
805                avolid);
806         MapHostToNetwork(&entry);
807
808         if (verbose)
809             EnumerateEntry(&entry);
810     }
811
812     /* Whether volume is in the VLDB or not. Delete the volume on disk */
813     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
814     code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
815     if (code) {
816         if (code == VNOVOL) {
817             notondisk = 1;
818         } else {
819             EGOTO1(error_exit, code, "Transaction on volume %u failed\n",
820                    avolid);
821         }
822     } else {
823         VPRINT1("Trying to delete the volume %u ...", avolid);
824
825         code = AFSVolDeleteVolume(aconn, ttid);
826         EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
827
828         code = AFSVolEndTrans(aconn, ttid, &rcode);
829         code = (code ? code : rcode);
830         ttid = 0;
831         EGOTO1(error_exit, code,
832                "Could not end the transaction for the volume %u \n", avolid);
833         VDONE;
834     }
835
836     /* Now update the VLDB entry.
837      * But first, verify we have a VLDB entry.
838      * Whether volume is on disk or not. Delete the volume in VLDB.
839      */
840     if (notinvldb)
841         ERROR_EXIT(0);
842
843     if (avolid == entry.volumeId[BACKVOL]) {
844         /* Its a backup volume, modify the VLDB entry. Check that the
845          * backup volume is on the server/partition we asked to delete.
846          */
847         if (!(entry.flags & BACK_EXISTS) || !Lp_Match(aserver, apart, &entry)) {
848             notinvldb = 2;      /* Not on this server and partition */
849             ERROR_EXIT(0);
850         }
851
852         VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
853
854         entry.flags &= ~BACK_EXISTS;
855         vtype = BACKVOL;
856     }
857
858     else if (avolid == entry.volumeId[ROVOL]) {
859         /* Its a read-only volume, modify the VLDB entry. Check that the
860          * readonly volume is on the server/partition we asked to delete.
861          * If flags does not have RO_EIXSTS set, then this may mean the RO 
862          * hasn't been released (and could exist in VLDB).
863          */
864         if (!Lp_ROMatch(aserver, apart, &entry)) {
865             notinvldb = 2;      /* Not found on this server and partition */
866             ERROR_EXIT(0);
867         }
868
869         if (verbose)
870             fprintf(STDOUT,
871                     "Marking the readonly volume %lu deleted in the VLDB\n",
872                     (unsigned long)avolid);
873
874         Lp_SetROValue(&entry, aserver, apart, 0, 0);    /* delete the site */
875         entry.nServers--;
876         if (!Lp_ROMatch(0, 0, &entry))
877             entry.flags &= ~RO_EXISTS;  /* This was the last ro volume */
878         vtype = ROVOL;
879     }
880
881     else if (avolid == entry.volumeId[RWVOL]) {
882         /* It's a rw volume, delete the backup volume, modify the VLDB entry.
883          * Check that the readwrite volumes is on the server/partition we
884          * asked to delete.
885          */
886         if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver, apart, &entry)) {
887             notinvldb = 2;      /* Not found on this server and partition */
888             ERROR_EXIT(0);
889         }
890
891         /* Delete backup if it exists */
892         code =
893             AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart,
894                               ITOffline, &ttid);
895         if (!code) {
896             if (verbose) {
897                 fprintf(STDOUT, "Trying to delete the backup volume %u ...",
898                         entry.volumeId[BACKVOL]);
899                 fflush(STDOUT);
900             }
901             code = AFSVolDeleteVolume(aconn, ttid);
902             EGOTO1(error_exit, code, "Could not delete the volume %u \n",
903                    entry.volumeId[BACKVOL]);
904
905             code = AFSVolEndTrans(aconn, ttid, &rcode);
906             ttid = 0;
907             code = (code ? code : rcode);
908             EGOTO1(error_exit, code,
909                    "Could not end the transaction for the volume %u \n",
910                    entry.volumeId[BACKVOL]);
911             if (verbose)
912                 fprintf(STDOUT, " done\n");
913         }
914
915         if (verbose)
916             fprintf(STDOUT,
917                     "Marking the readwrite volume %lu%s deleted in the VLDB\n",
918                     (unsigned long)avolid,
919                     ((entry.
920                       flags & BACK_EXISTS) ? ", and its backup volume," :
921                      ""));
922
923         Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
924         entry.nServers--;
925         entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
926         vtype = RWVOL;
927
928         if (entry.flags & RO_EXISTS)
929             fprintf(STDERR, "WARNING: ReadOnly copy(s) may still exist\n");
930     }
931
932     else {
933         notinvldb = 2;          /* Not found on this server and partition */
934         ERROR_EXIT(0);
935     }
936
937     /* Either delete or replace the VLDB entry */
938     if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
939         if (verbose)
940             fprintf(STDOUT,
941                     "Last reference to the VLDB entry for %lu - deleting entry\n",
942                     (unsigned long)avolid);
943         code = ubik_VL_DeleteEntry(cstruct, 0, avolid, vtype);
944         EGOTO1(error_exit, code,
945                "Could not delete the VLDB entry for the volume %u \n",
946                avolid);
947     } else {
948         MapNetworkToHost(&entry, &storeEntry);
949         code =
950             VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
951                               (LOCKREL_OPCODE | LOCKREL_AFSID |
952                                LOCKREL_TIMESTAMP));
953         EGOTO1(error_exit, code,
954                "Could not update the VLDB entry for the volume %u \n",
955                avolid);
956     }
957     islocked = 0;
958
959   error_exit:
960     if (error)
961         EPRINT(error, "\n");
962
963     if (notondisk && notinvldb) {
964         EPRINT2(VOLSERNOVOL, "Volume %u does not exist %s\n", avolid,
965                 ((notinvldb == 2) ? "on server and partition" : ""));
966         if (!error)
967             error = VOLSERNOVOL;
968     } else if (notondisk) {
969         fprintf(STDERR,
970                 "WARNING: Volume %lu did not exist on the partition\n",
971                 (unsigned long)avolid);
972     } else if (notinvldb) {
973         fprintf(STDERR, "WARNING: Volume %lu does not exist in VLDB %s\n",
974                 (unsigned long)avolid,
975                 ((notinvldb == 2) ? "on server and partition" : ""));
976     }
977
978     if (ttid) {
979         code = AFSVolEndTrans(aconn, ttid, &rcode);
980         code = (code ? code : rcode);
981         if (code) {
982             fprintf(STDERR, "Could not end transaction on the volume %lu\n",
983                     (unsigned long)avolid);
984             PrintError("", code);
985             if (!error)
986                 error = code;
987         }
988     }
989
990     if (islocked) {
991         code =
992             ubik_VL_ReleaseLock(cstruct, 0, avolid, -1,
993                                 (LOCKREL_OPCODE | LOCKREL_AFSID | 
994                                  LOCKREL_TIMESTAMP));
995         if (code) {
996             EPRINT1(code,
997                     "Could not release the lock on the VLDB entry for the volume %u \n",
998                     avolid);
999             if (!error)
1000                 error = code;
1001         }
1002     }
1003
1004     if (aconn)
1005         rx_DestroyConnection(aconn);
1006     return error;
1007 }
1008
1009 /* add recovery to UV_MoveVolume */
1010
1011 #define TESTC   0               /* set to test recovery code, clear for production */
1012
1013 jmp_buf env;
1014 int interrupt = 0;
1015
1016 void
1017 sigint_handler(int x)
1018 {
1019     if (interrupt)
1020         longjmp(env, 0);
1021
1022     fprintf(STDOUT, "\nSIGINT handler: vos move operation in progress\n");
1023     fprintf(STDOUT,
1024             "WARNING: may leave AFS storage and metadata in indeterminate state\n");
1025     fprintf(STDOUT, "enter second control-c to exit\n");
1026     fflush(STDOUT);
1027
1028     interrupt = 1;
1029     (void)signal(SIGINT, sigint_handler);
1030
1031     return;
1032 }
1033
1034 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1035  * <atopart>.  The operation is almost idempotent.  The following
1036  * flags are recognized:
1037  * 
1038  *     RV_NOCLONE - don't use a copy clone
1039  */
1040
1041 int
1042 UV_MoveVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
1043                afs_int32 atoserver, afs_int32 atopart, int flags)
1044 {
1045     struct rx_connection *toconn, *fromconn;
1046     afs_int32 fromtid, totid, clonetid;
1047     char vname[64];
1048     char *volName = 0;
1049     char tmpName[VOLSER_MAXVOLNAME + 1];
1050     afs_int32 rcode;
1051     afs_int32 fromDate;
1052     struct restoreCookie cookie;
1053     register afs_int32 vcode, code;
1054     afs_int32 newVol, volid, backupId;
1055     struct volser_status tstatus;
1056     struct destServer destination;
1057
1058     struct nvldbentry entry, storeEntry;
1059     int i, islocked, pntg;
1060     afs_int32 error;
1061     char in, lf;                /* for test code */
1062     int same;
1063
1064 #ifdef  ENABLE_BUGFIX_1165
1065     volEntries volumeInfo;
1066     struct volintInfo *infop = 0;
1067 #endif
1068
1069     islocked = 0;
1070     fromconn = (struct rx_connection *)0;
1071     toconn = (struct rx_connection *)0;
1072     fromtid = 0;
1073     totid = 0;
1074     clonetid = 0;
1075     error = 0;
1076     volid = 0;
1077     pntg = 0;
1078     backupId = 0;
1079     newVol = 0;
1080
1081     /* support control-c processing */
1082     if (setjmp(env))
1083         goto mfail;
1084     (void)signal(SIGINT, sigint_handler);
1085
1086     if (TESTC) {
1087         fprintf(STDOUT,
1088                 "\nThere are three tests points - verifies all code paths through recovery.\n");
1089         fprintf(STDOUT, "First test point - operation not started.\n");
1090         fprintf(STDOUT, "...test here (y, n)? ");
1091         fflush(STDOUT);
1092         fscanf(stdin, "%c", &in);
1093         fscanf(stdin, "%c", &lf);       /* toss away */
1094         if (in == 'y') {
1095             fprintf(STDOUT, "type control-c\n");
1096             while (1) {
1097                 fprintf(stdout, ".");
1098                 fflush(stdout);
1099                 sleep(1);
1100             }
1101         }
1102         /* or drop through */
1103     }
1104
1105     vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1106     EGOTO1(mfail, vcode,
1107            "Could not fetch the entry for the volume  %u from the VLDB \n",
1108            afromvol);
1109
1110     if (entry.volumeId[RWVOL] != afromvol) {
1111         fprintf(STDERR, "Only RW volume can be moved\n");
1112         exit(1);
1113     }
1114
1115     vcode = ubik_VL_SetLock(cstruct, 0, afromvol, RWVOL, VLOP_MOVE);
1116     EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
1117     islocked = 1;
1118
1119     vcode = VLDB_GetEntryByID(afromvol, RWVOL, &entry);
1120     EGOTO1(mfail, vcode,
1121            "Could not fetch the entry for the volume  %u from the VLDB \n",
1122            afromvol);
1123
1124     backupId = entry.volumeId[BACKVOL];
1125     MapHostToNetwork(&entry);
1126
1127     if (!Lp_Match(afromserver, afrompart, &entry)) {
1128         /* the from server and partition do not exist in the vldb entry corresponding to volid */
1129         if (!Lp_Match(atoserver, atopart, &entry)) {
1130             /* the to server and partition do not exist in the vldb entry corresponding to volid */
1131             fprintf(STDERR, "The volume %lu is not on the specified site. \n",
1132                     (unsigned long)afromvol);
1133             fprintf(STDERR, "The current site is :");
1134             for (i = 0; i < entry.nServers; i++) {
1135                 if (entry.serverFlags[i] == ITSRWVOL) {
1136                     char pname[10];
1137                     MapPartIdIntoName(entry.serverPartition[i], pname);
1138                     fprintf(STDERR, " server %s partition %s \n",
1139                             hostutil_GetNameByINet(entry.serverNumber[i]),
1140                             pname);
1141                 }
1142             }
1143             vcode =
1144                 ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
1145                           (LOCKREL_OPCODE | LOCKREL_AFSID |
1146                            LOCKREL_TIMESTAMP));
1147             EGOTO1(mfail, vcode,
1148                    " Could not release lock on the VLDB entry for the volume %u \n",
1149                    afromvol);
1150
1151             return VOLSERVOLMOVED;
1152         }
1153
1154         /* delete the volume afromvol on src_server */
1155         /* from-info does not exist but to-info does =>
1156          * we have already done the move, but the volume
1157          * may still be existing physically on from fileserver
1158          */
1159         fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1160         fromtid = 0;
1161         pntg = 1;
1162
1163         code =
1164             AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline,
1165                               &fromtid);
1166         if (!code) {            /* volume exists - delete it */
1167             VPRINT1("Setting flags on leftover source volume %u ...",
1168                     afromvol);
1169             code =
1170                 AFSVolSetFlags(fromconn, fromtid,
1171                                VTDeleteOnSalvage | VTOutOfService);
1172             EGOTO1(mfail, code,
1173                    "Failed to set flags on the leftover source volume %u\n",
1174                    afromvol);
1175             VDONE;
1176
1177             VPRINT1("Deleting leftover source volume %u ...", afromvol);
1178             code = AFSVolDeleteVolume(fromconn, fromtid);
1179             EGOTO1(mfail, code,
1180                    "Failed to delete the leftover source volume %u\n",
1181                    afromvol);
1182             VDONE;
1183
1184             VPRINT1("Ending transaction on leftover source volume %u ...",
1185                     afromvol);
1186             code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1187             fromtid = 0;
1188             if (!code)
1189                 code = rcode;
1190             EGOTO1(mfail, code,
1191                    "Could not end the transaction for the leftover source volume %u \n",
1192                    afromvol);
1193             VDONE;
1194         }
1195
1196         /*delete the backup volume now */
1197         fromtid = 0;
1198         code =
1199             AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
1200                               &fromtid);
1201         if (!code) {            /* backup volume exists - delete it */
1202             VPRINT1("Setting flags on leftover backup volume %u ...",
1203                     backupId);
1204             code =
1205                 AFSVolSetFlags(fromconn, fromtid,
1206                                VTDeleteOnSalvage | VTOutOfService);
1207             EGOTO1(mfail, code,
1208                    "Failed to set flags on the backup volume %u\n", backupId);
1209             VDONE;
1210
1211             VPRINT1("Deleting leftover backup volume %u ...", backupId);
1212             code = AFSVolDeleteVolume(fromconn, fromtid);
1213             EGOTO1(mfail, code,
1214                    "Could not delete the leftover backup volume %u\n",
1215                    backupId);
1216             VDONE;
1217
1218             VPRINT1("Ending transaction on leftover backup volume %u ...",
1219                     backupId);
1220             code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1221             fromtid = 0;
1222             if (!code)
1223                 code = rcode;
1224             EGOTO1(mfail, code,
1225                    "Could not end the transaction for the leftover backup volume %u\n",
1226                    backupId);
1227             VDONE;
1228         }
1229
1230         fromtid = 0;
1231         error = 0;
1232         goto mfail;
1233     }
1234
1235     /* From-info matches the vldb info about volid,
1236      * its ok start the move operation, the backup volume 
1237      * on the old site is deleted in the process 
1238      */
1239     if (afrompart == atopart) {
1240         same = VLDB_IsSameAddrs(afromserver, atoserver, &error);
1241         EGOTO2(mfail, error,
1242                "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1243                afromserver, error);
1244
1245         if (same) {
1246             EGOTO1(mfail, VOLSERVOLMOVED,
1247                    "Warning: Moving volume %u to its home partition ignored!\n",
1248                    afromvol);
1249         }
1250     }
1251
1252     pntg = 1;
1253     toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT);    /* get connections to the servers */
1254     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1255     fromtid = totid = 0;        /* initialize to uncreated */
1256
1257     /* ***
1258      * clone the read/write volume locally.
1259      * ***/
1260
1261     VPRINT1("Starting transaction on source volume %u ...", afromvol);
1262     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1263     EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
1264            afromvol);
1265     VDONE;
1266
1267     if (!(flags & RV_NOCLONE)) {
1268         /* Get a clone id */
1269         VPRINT1("Allocating new volume id for clone of volume %u ...",
1270                 afromvol);
1271         newVol = 0;
1272         vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &newVol);
1273         EGOTO1(mfail, vcode,
1274                "Could not get an ID for the clone of volume %u from the VLDB\n",
1275                afromvol);
1276         VDONE;
1277
1278         /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1279         VPRINT1("Cloning source volume %u ...", afromvol);
1280         strcpy(vname, "move-clone-temp");
1281         code =
1282             AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &newVol);
1283         EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
1284                afromvol);
1285         VDONE;
1286     }
1287
1288     /* lookup the name of the volume we just cloned */
1289     volid = afromvol;
1290     code = AFSVolGetName(fromconn, fromtid, &volName);
1291     EGOTO1(mfail, code, "Failed to get the name of the volume %u\n",
1292            afromvol);
1293
1294     VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1295     rcode = 0;
1296     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1297     fromtid = 0;
1298     if (!code)
1299         code = rcode;
1300     EGOTO1(mfail, code,
1301            "Failed to end the transaction on the source volume %u\n",
1302            afromvol);
1303     VDONE;
1304
1305     /* ***
1306      * Create the destination volume
1307      * ***/
1308
1309     if (!(flags & RV_NOCLONE)) {
1310         /* All of this is to get the fromDate */
1311         VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1312         code =
1313             AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1314                               &clonetid);
1315         EGOTO1(mfail, code,
1316                "Failed to start a transaction on the cloned volume%u\n",
1317                newVol);
1318         VDONE;
1319
1320         VPRINT1("Setting flags on cloned volume %u ...", newVol);
1321         code =
1322             AFSVolSetFlags(fromconn, clonetid,
1323                            VTDeleteOnSalvage | VTOutOfService); /*redundant */
1324         EGOTO1(mfail, code, "Could not set flags on the cloned volume %u\n",
1325                newVol);
1326         VDONE;
1327
1328         /* remember time from which we've dumped the volume */
1329         VPRINT1("Getting status of cloned volume %u ...", newVol);
1330         code = AFSVolGetStatus(fromconn, clonetid, &tstatus);
1331         EGOTO1(mfail, code,
1332                "Failed to get the status of the cloned volume %u\n",
1333                newVol);
1334         VDONE;
1335
1336         fromDate = CLOCKADJ(tstatus.creationDate);
1337     } else {
1338         /* With RV_NOCLONE, just do a full copy from the source */
1339         fromDate = 0;
1340     }
1341
1342
1343 #ifdef  ENABLE_BUGFIX_1165
1344     /*
1345      * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1346      * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1347      * don't use this information...
1348      */
1349     volumeInfo.volEntries_val = (volintInfo *) 0;       /*this hints the stub to allocate space */
1350     volumeInfo.volEntries_len = 0;
1351     code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1352     EGOTO1(mfail, code,
1353            "Failed to get the volint Info of the cloned volume %u\n",
1354            afromvol);
1355
1356     infop = (volintInfo *) volumeInfo.volEntries_val;
1357     infop->maxquota = -1;       /* Else it will replace the default quota */
1358     infop->creationDate = -1;   /* Else it will use the source creation date */
1359     infop->updateDate = -1;     /* Else it will use the source update date */
1360 #endif
1361
1362     /* create a volume on the target machine */
1363     volid = afromvol;
1364     code = AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
1365     if (!code) {
1366         /* Delete the existing volume.
1367          * While we are deleting the volume in these steps, the transaction
1368          * we started against the cloned volume (clonetid above) will be
1369          * sitting idle. It will get cleaned up after 600 seconds
1370          */
1371         VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1372         code = AFSVolDeleteVolume(toconn, totid);
1373         EGOTO1(mfail, code,
1374                "Could not delete the pre-existing volume %u on destination\n",
1375                volid);
1376         VDONE;
1377
1378         VPRINT1
1379             ("Ending transaction on pre-existing volume %u on destination ...",
1380              volid);
1381         code = AFSVolEndTrans(toconn, totid, &rcode);
1382         totid = 0;
1383         if (!code)
1384             code = rcode;
1385         EGOTO1(mfail, code,
1386                "Could not end the transaction on pre-existing volume %u on destination\n",
1387                volid);
1388         VDONE;
1389     }
1390
1391     VPRINT1("Creating the destination volume %u ...", volid);
1392     code =
1393         AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &volid,
1394                            &totid);
1395     EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
1396            volid);
1397     VDONE;
1398
1399     strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1400     free(volName);
1401     volName = NULL;
1402
1403     VPRINT1("Setting volume flags on destination volume %u ...", volid);
1404     code =
1405         AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1406     EGOTO1(mfail, code,
1407            "Failed to set the flags on the destination volume %u\n", volid);
1408     VDONE;
1409
1410     /***
1411      * Now dump the clone to the new volume
1412      ***/
1413
1414     destination.destHost = ntohl(atoserver);
1415     destination.destPort = AFSCONF_VOLUMEPORT;
1416     destination.destSSID = 1;
1417
1418     strncpy(cookie.name, tmpName, VOLSER_OLDMAXVOLNAME);
1419     cookie.type = RWVOL;
1420     cookie.parent = entry.volumeId[RWVOL];
1421     cookie.clone = 0;
1422
1423     if (!(flags & RV_NOCLONE)) {
1424         /* Copy the clone to the new volume */
1425         VPRINT2("Dumping from clone %u on source to volume %u on destination ...",
1426                 newVol, afromvol);
1427         code =
1428             AFSVolForward(fromconn, clonetid, 0, &destination, totid,
1429                           &cookie);
1430         EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1431         VDONE;
1432
1433         VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1434         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1435         if (!code)
1436             code = rcode;
1437         clonetid = 0;
1438         EGOTO1(mfail, code,
1439                "Failed to end the transaction on the cloned volume %u\n",
1440                newVol);
1441         VDONE;
1442     }
1443
1444     /* ***
1445      * reattach to the main-line volume, and incrementally dump it.
1446      * ***/
1447
1448     VPRINT1("Starting transaction on source volume %u ...", afromvol);
1449     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1450     EGOTO1(mfail, code,
1451            "Failed to create a transaction on the source volume %u\n",
1452            afromvol);
1453     VDONE;
1454
1455     /* now do the incremental */
1456     VPRINT2
1457         ("Doing the%s dump from source to destination for volume %u ... ",
1458          (flags & RV_NOCLONE) ? "" : " incremental",
1459          afromvol);
1460     code =
1461         AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
1462                       &cookie);
1463     EGOTO1(mfail, code,
1464            "Failed to do the%s dump from rw volume on old site to rw volume on newsite\n",
1465           (flags & RV_NOCLONE) ? "" : " incremental");
1466     VDONE;
1467
1468     /* now adjust the flags so that the new volume becomes official */
1469     VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1470     code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1471     EGOTO(mfail, code,
1472           "Failed to set the flags to make old source volume offline\n");
1473     VDONE;
1474
1475     VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1476     code = AFSVolSetFlags(toconn, totid, 0);
1477     EGOTO(mfail, code,
1478           "Failed to set the flags to make new source volume online\n");
1479     VDONE;
1480
1481 #ifdef  ENABLE_BUGFIX_1165
1482     VPRINT1("Setting volume status on destination volume %u ...", volid);
1483     code = AFSVolSetInfo(toconn, totid, infop);
1484     EGOTO1(mfail, code,
1485            "Failed to set volume status on the destination volume %u\n",
1486            volid);
1487     VDONE;
1488 #endif
1489
1490     /* put new volume online */
1491     VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1492     code = AFSVolEndTrans(toconn, totid, &rcode);
1493     totid = 0;
1494     if (!code)
1495         code = rcode;
1496     EGOTO1(mfail, code,
1497            "Failed to end the transaction on the volume %u on the new site\n",
1498            afromvol);
1499     VDONE;
1500
1501     Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1502     MapNetworkToHost(&entry, &storeEntry);
1503     storeEntry.flags &= ~BACK_EXISTS;
1504
1505     if (TESTC) {
1506         fprintf(STDOUT,
1507                 "Second test point - operation in progress but not complete.\n");
1508         fprintf(STDOUT, "...test here (y, n)? ");
1509         fflush(STDOUT);
1510         fscanf(stdin, "%c", &in);
1511         fscanf(stdin, "%c", &lf);       /* toss away */
1512         if (in == 'y') {
1513             fprintf(STDOUT, "type control-c\n");
1514             while (1) {
1515                 fprintf(stdout, ".");
1516                 fflush(stdout);
1517                 sleep(1);
1518             }
1519         }
1520         /* or drop through */
1521     }
1522
1523     VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1524     vcode =
1525         VLDB_ReplaceEntry(afromvol, -1, &storeEntry,
1526                           (LOCKREL_OPCODE | LOCKREL_AFSID |
1527                            LOCKREL_TIMESTAMP));
1528     if (vcode) {
1529         fprintf(STDERR,
1530                 " Could not release the lock on the VLDB entry for the volume %s %lu \n",
1531                 storeEntry.name, (unsigned long)afromvol);
1532         error = vcode;
1533         goto mfail;
1534     }
1535     islocked = 0;
1536     VDONE;
1537
1538     if (TESTC) {
1539         fprintf(STDOUT,
1540                 "Third test point - operation complete but no cleanup.\n");
1541         fprintf(STDOUT, "...test here (y, n)? ");
1542         fflush(STDOUT);
1543         fscanf(stdin, "%c", &in);
1544         fscanf(stdin, "%c", &lf);       /* toss away */
1545         if (in == 'y') {
1546             fprintf(STDOUT, "type control-c\n");
1547             while (1) {
1548                 fprintf(stdout, ".");
1549                 fflush(stdout);
1550                 sleep(1);
1551             }
1552         }
1553         /* or drop through */
1554     }
1555 #ifdef notdef
1556     /* This is tricky.  File server is very stupid, and if you mark the volume
1557      * as VTOutOfService, it may mark the *good* instance (if you're moving
1558      * between partitions on the same machine) as out of service.  Since
1559      * we're cleaning this code up in DEcorum, we're just going to kludge around
1560      * it for now by removing this call. */
1561     /* already out of service, just zap it now */
1562     code =
1563         AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1564     if (code) {
1565         fprintf(STDERR,
1566                 "Failed to set the flags to make the old source volume offline\n");
1567         goto mfail;
1568     }
1569 #endif
1570     if (atoserver != afromserver) {
1571         /* set forwarding pointer for moved volumes */
1572         VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1573         code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1574         EGOTO1(mfail, code,
1575                "Failed to set the forwarding pointer for the volume %u\n",
1576                afromvol);
1577         VDONE;
1578     }
1579
1580     VPRINT1("Deleting old volume %u on source ...", afromvol);
1581     code = AFSVolDeleteVolume(fromconn, fromtid);       /* zap original volume */
1582     EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n",
1583            afromvol);
1584     VDONE;
1585
1586     VPRINT1("Ending transaction on old volume %u on the source ...",
1587             afromvol);
1588     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1589     fromtid = 0;
1590     if (!code)
1591         code = rcode;
1592     EGOTO1(mfail, code,
1593            "Failed to end the transaction on the old volume %u on the source\n",
1594            afromvol);
1595     VDONE;
1596
1597     /* Delete the backup volume on the original site */
1598     VPRINT1("Creating transaction for backup volume %u on source ...",
1599             backupId);
1600     code =
1601         AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1602     VDONE;
1603     if (!code) {
1604         VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1605         code =
1606             AFSVolSetFlags(fromconn, fromtid,
1607                            VTDeleteOnSalvage | VTOutOfService);
1608         EGOTO1(mfail, code,
1609                "Failed to set the flags on the backup volume %u on the source\n",
1610                backupId);
1611         VDONE;
1612
1613         VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1614         code = AFSVolDeleteVolume(fromconn, fromtid);
1615         EGOTO1(mfail, code,
1616                "Failed to delete the backup volume %u on the source\n",
1617                backupId);
1618         VDONE;
1619
1620         VPRINT1("Ending transaction on backup volume %u on source ...",
1621                 backupId);
1622         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1623         fromtid = 0;
1624         if (!code)
1625             code = rcode;
1626         EGOTO1(mfail, code,
1627                "Failed to end the transaction on the backup volume %u on the source\n",
1628                backupId);
1629         VDONE;
1630     } else
1631         code = 0;               /* no backup volume? that's okay */
1632
1633     fromtid = 0;
1634     if (!(flags & RV_NOCLONE)) {
1635         VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1636         code =
1637             AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1638                               &clonetid);
1639         EGOTO1(mfail, code,
1640                "Failed to start a transaction on the cloned volume%u\n",
1641                newVol);
1642         VDONE;
1643
1644         /* now delete the clone */
1645         VPRINT1("Deleting the cloned volume %u ...", newVol);
1646         code = AFSVolDeleteVolume(fromconn, clonetid);
1647         EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
1648                newVol);
1649         VDONE;
1650
1651         VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1652         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1653         if (!code)
1654             code = rcode;
1655         clonetid = 0;
1656         EGOTO1(mfail, code,
1657                "Failed to end the transaction on the cloned volume %u\n",
1658                newVol);
1659         VDONE;
1660     }
1661
1662     /* fall through */
1663     /* END OF MOVE */
1664
1665     if (TESTC) {
1666         fprintf(STDOUT, "Fourth test point - operation complete.\n");
1667         fprintf(STDOUT, "...test here (y, n)? ");
1668         fflush(STDOUT);
1669         fscanf(stdin, "%c", &in);
1670         fscanf(stdin, "%c", &lf);       /* toss away */
1671         if (in == 'y') {
1672             fprintf(STDOUT, "type control-c\n");
1673             while (1) {
1674                 fprintf(stdout, ".");
1675                 fflush(stdout);
1676                 sleep(1);
1677             }
1678         }
1679         /* or drop through */
1680     }
1681
1682     /* normal cleanup code */
1683
1684     if (entry.flags & RO_EXISTS)
1685         fprintf(STDERR, "WARNING : readOnly copies still exist \n");
1686
1687     if (islocked) {
1688         VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1689         vcode =
1690             ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
1691                       (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1692         if (vcode) {
1693             VPRINT("\n");
1694             fprintf(STDERR,
1695                     " Could not release the lock on the VLDB entry for the volume %lu \n",
1696                     (unsigned long)afromvol);
1697             if (!error)
1698                 error = vcode;
1699         }
1700         VDONE;
1701     }
1702
1703     if (fromtid) {
1704         VPRINT1("Cleanup: Ending transaction on source volume %u ...",
1705                 afromvol);
1706         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1707         if (code || rcode) {
1708             VPRINT("\n");
1709             fprintf(STDERR,
1710                     "Could not end transaction on the source volume %lu\n",
1711                     (unsigned long)afromvol);
1712             if (!error)
1713                 error = (code ? code : rcode);
1714         }
1715         VDONE;
1716     }
1717
1718     if (clonetid) {
1719         VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1720         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1721         if (code || rcode) {
1722             VPRINT("\n");
1723             fprintf(STDERR,
1724                     "Could not end transaction on the source's clone volume %lu\n",
1725                     (unsigned long)newVol);
1726             if (!error)
1727                 error = (code ? code : rcode);
1728         }
1729         VDONE;
1730     }
1731
1732     if (totid) {
1733         VPRINT1("Cleanup: Ending transaction on destination volume %u ...",
1734                 afromvol);
1735         code = AFSVolEndTrans(toconn, totid, &rcode);
1736         if (code) {
1737             VPRINT("\n");
1738             fprintf(STDERR,
1739                     "Could not end transaction on destination volume %lu\n",
1740                     (unsigned long)afromvol);
1741             if (!error)
1742                 error = (code ? code : rcode);
1743         }
1744         VDONE;
1745     }
1746     if (volName)
1747         free(volName);
1748 #ifdef  ENABLE_BUGFIX_1165
1749     if (infop)
1750         free(infop);
1751 #endif
1752     if (fromconn)
1753         rx_DestroyConnection(fromconn);
1754     if (toconn)
1755         rx_DestroyConnection(toconn);
1756     PrintError("", error);
1757     return error;
1758
1759     /* come here only when the sky falls */
1760   mfail:
1761
1762     if (pntg) {
1763         fprintf(STDOUT,
1764                 "vos move: operation interrupted, cleanup in progress...\n");
1765         fprintf(STDOUT, "clear transaction contexts\n");
1766         fflush(STDOUT);
1767     }
1768
1769     /* unlock VLDB entry */
1770     if (islocked) {
1771         VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1772         ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
1773                   (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1774         VDONE;
1775     }
1776
1777     if (clonetid) {
1778         VPRINT("Recovery: Ending transaction on clone volume ...");
1779         AFSVolEndTrans(fromconn, clonetid, &rcode);
1780         VDONE;
1781     }
1782     if (totid) {
1783         VPRINT("Recovery: Ending transaction on destination volume ...");
1784         AFSVolEndTrans(toconn, totid, &rcode);
1785         VDONE;
1786     }
1787     if (fromtid) {              /* put it on-line */
1788         VPRINT("Recovery: Setting volume flags on source volume ...");
1789         AFSVolSetFlags(fromconn, fromtid, 0);
1790         VDONE;
1791
1792         VPRINT("Recovery: Ending transaction on source volume ...");
1793         AFSVolEndTrans(fromconn, fromtid, &rcode);
1794         VDONE;
1795     }
1796
1797     VPRINT("Recovery: Accessing VLDB.\n");
1798     vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1799     if (vcode) {
1800         fprintf(STDOUT, "FATAL: VLDB access error: abort cleanup\n");
1801         fflush(STDOUT);
1802         goto done;
1803     }
1804     MapHostToNetwork(&entry);
1805
1806     /* Delete either the volume on the source location or the target location. 
1807      * If the vldb entry still points to the source location, then we know the
1808      * volume move didn't finish so we remove the volume from the target 
1809      * location. Otherwise, we remove the volume from the source location.
1810      */
1811     if (Lp_Match(afromserver, afrompart, &entry)) {     /* didn't move - delete target volume */
1812         if (pntg) {
1813             fprintf(STDOUT,
1814                     "move incomplete - attempt cleanup of target partition - no guarantee\n");
1815             fflush(STDOUT);
1816         }
1817
1818         if (volid && toconn) {
1819             VPRINT1
1820                 ("Recovery: Creating transaction for destination volume %u ...",
1821                  volid);
1822             code =
1823                 AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
1824
1825             if (!code) {
1826                 VDONE;
1827
1828                 VPRINT1
1829                     ("Recovery: Setting flags on destination volume %u ...",
1830                      volid);
1831                 AFSVolSetFlags(toconn, totid,
1832                                VTDeleteOnSalvage | VTOutOfService);
1833                 VDONE;
1834
1835                 VPRINT1("Recovery: Deleting destination volume %u ...",
1836                         volid);
1837                 AFSVolDeleteVolume(toconn, totid);
1838                 VDONE;
1839
1840                 VPRINT1
1841                     ("Recovery: Ending transaction on destination volume %u ...",
1842                      volid);
1843                 AFSVolEndTrans(toconn, totid, &rcode);
1844                 VDONE;
1845             } else {
1846                 VPRINT1
1847                     ("\nRecovery: Unable to start transaction on destination volume %u.\n",
1848                      afromvol);
1849             }
1850         }
1851
1852         /* put source volume on-line */
1853         if (fromconn) {
1854             VPRINT1("Recovery: Creating transaction on source volume %u ...",
1855                     afromvol);
1856             code =
1857                 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1858                                   &fromtid);
1859             if (!code) {
1860                 VDONE;
1861
1862                 VPRINT1("Recovery: Setting flags on source volume %u ...",
1863                         afromvol);
1864                 AFSVolSetFlags(fromconn, fromtid, 0);
1865                 VDONE;
1866
1867                 VPRINT1
1868                     ("Recovery: Ending transaction on source volume %u ...",
1869                      afromvol);
1870                 AFSVolEndTrans(fromconn, fromtid, &rcode);
1871                 VDONE;
1872             } else {
1873                 VPRINT1
1874                     ("\nRecovery: Unable to start transaction on source volume %u.\n",
1875                      afromvol);
1876             }
1877         }
1878     } else {                    /* yep, move complete */
1879         if (pntg) {
1880             fprintf(STDOUT,
1881                     "move complete - attempt cleanup of source partition - no guarantee\n");
1882             fflush(STDOUT);
1883         }
1884
1885         /* delete backup volume */
1886         if (fromconn) {
1887             VPRINT1("Recovery: Creating transaction on backup volume %u ...",
1888                     backupId);
1889             code =
1890                 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
1891                                   &fromtid);
1892             if (!code) {
1893                 VDONE;
1894
1895                 VPRINT1("Recovery: Setting flags on backup volume %u ...",
1896                         backupId);
1897                 AFSVolSetFlags(fromconn, fromtid,
1898                                VTDeleteOnSalvage | VTOutOfService);
1899                 VDONE;
1900
1901                 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1902                 AFSVolDeleteVolume(fromconn, fromtid);
1903                 VDONE;
1904
1905                 VPRINT1
1906                     ("Recovery: Ending transaction on backup volume %u ...",
1907                      backupId);
1908                 AFSVolEndTrans(fromconn, fromtid, &rcode);
1909                 VDONE;
1910             } else {
1911                 VPRINT1
1912                     ("\nRecovery: Unable to start transaction on backup volume %u.\n",
1913                      backupId);
1914             }
1915
1916             /* delete source volume */
1917             VPRINT1("Recovery: Creating transaction on source volume %u ...",
1918                     afromvol);
1919             code =
1920                 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1921                                   &fromtid);
1922             if (!code) {
1923                 VDONE;
1924
1925                 VPRINT1("Recovery: Setting flags on backup volume %u ...",
1926                         afromvol);
1927                 AFSVolSetFlags(fromconn, fromtid,
1928                                VTDeleteOnSalvage | VTOutOfService);
1929                 VDONE;
1930
1931                 if (atoserver != afromserver) {
1932                     VPRINT("Recovery: Setting volume forwarding pointer ...");
1933                     AFSVolSetForwarding(fromconn, fromtid, atoserver);
1934                     VDONE;
1935                 }
1936
1937                 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1938                 AFSVolDeleteVolume(fromconn, fromtid);
1939                 VDONE;
1940
1941                 VPRINT1
1942                     ("Recovery: Ending transaction on source volume %u ...",
1943                      afromvol);
1944                 AFSVolEndTrans(fromconn, fromtid, &rcode);
1945                 VDONE;
1946             } else {
1947                 VPRINT1
1948                     ("\nRecovery: Unable to start transaction on source volume %u.\n",
1949                      afromvol);
1950             }
1951         }
1952     }
1953
1954     /* common cleanup - delete local clone */
1955     if (newVol) {
1956         VPRINT1("Recovery: Creating transaction on clone volume %u ...",
1957                 newVol);
1958         code =
1959             AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1960                               &clonetid);
1961         if (!code) {
1962             VDONE;
1963
1964             VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1965             AFSVolDeleteVolume(fromconn, clonetid);
1966             VDONE;
1967
1968             VPRINT1("Recovery: Ending transaction on clone volume %u ...",
1969                     newVol);
1970             AFSVolEndTrans(fromconn, clonetid, &rcode);
1971             VDONE;
1972         } else {
1973             VPRINT1
1974                 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1975                  afromvol);
1976         }
1977     }
1978
1979     /* unlock VLDB entry */
1980     VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...",
1981             afromvol);
1982     ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
1983               (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1984     VDONE;
1985
1986   done:                 /* routine cleanup */
1987     if (volName)
1988         free(volName);
1989 #ifdef  ENABLE_BUGFIX_1165
1990     if (infop)
1991         free(infop);
1992 #endif
1993     if (fromconn)
1994         rx_DestroyConnection(fromconn);
1995     if (toconn)
1996         rx_DestroyConnection(toconn);
1997
1998     if (pntg) {
1999         fprintf(STDOUT, "cleanup complete - user verify desired result\n");
2000         fflush(STDOUT);
2001     }
2002     exit(1);
2003 }
2004
2005
2006 int
2007 UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2008               afs_int32 atoserver, afs_int32 atopart)
2009 {
2010     return UV_MoveVolume2(afromvol, afromserver, afrompart,
2011                           atoserver, atopart, 0);
2012 }
2013
2014
2015 /* Copy volume <afromvol> from <afromserver> <afrompart> to <atoserver>
2016  * <atopart>.  The new volume is named by <atovolname>.  The new volume
2017  * has ID <atovolid> if that is nonzero; otherwise a new ID is allocated
2018  * from the VLDB.  the following flags are supported:
2019  * 
2020  *     RV_RDONLY  - target volume is RO
2021  *     RV_OFFLINE - leave target volume offline
2022  *     RV_CPINCR  - do incremental dump if target exists
2023  *     RV_NOVLDB  - don't create/update VLDB entry
2024  *     RV_NOCLONE - don't use a copy clone
2025  */
2026 int
2027 UV_CopyVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2028                char *atovolname, afs_int32 atoserver, afs_int32 atopart,
2029                afs_int32 atovolid, int flags)
2030 {
2031     struct rx_connection *toconn, *fromconn;
2032     afs_int32 fromtid, totid, clonetid;
2033     char vname[64];
2034     afs_int32 rcode;
2035     afs_int32 fromDate, cloneFromDate;
2036     struct restoreCookie cookie;
2037     register afs_int32 vcode, code;
2038     afs_int32 cloneVol, newVol, volflag;
2039     struct volser_status tstatus;
2040     struct destServer destination;
2041
2042     struct nvldbentry entry, newentry, storeEntry;
2043     int islocked, pntg;
2044     afs_int32 error;
2045     int justclone = 0;
2046
2047     islocked = 0;
2048     fromconn = (struct rx_connection *)0;
2049     toconn = (struct rx_connection *)0;
2050     fromtid = 0;
2051     totid = 0;
2052     clonetid = 0;
2053     error = 0;
2054     pntg = 0;
2055     newVol = 0;
2056
2057     /* support control-c processing */
2058     if (setjmp(env))
2059         goto mfail;
2060     (void)signal(SIGINT, sigint_handler);
2061
2062     vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
2063     EGOTO1(mfail, vcode,
2064            "Could not fetch the entry for the volume  %u from the VLDB \n",
2065            afromvol);
2066     MapHostToNetwork(&entry);
2067
2068     pntg = 1;
2069     toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT);    /* get connections to the servers */
2070     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2071     fromtid = totid = 0;        /* initialize to uncreated */
2072
2073
2074     /* check if we can shortcut and use a local clone instead of a full copy */
2075     if (afromserver == atoserver && afrompart == atopart) {
2076         justclone = 1;
2077     }
2078
2079     /* ***
2080      * clone the read/write volume locally.
2081      * ***/
2082
2083     cloneVol = 0;
2084     if (!(flags & RV_NOCLONE)) {
2085         VPRINT1("Starting transaction on source volume %u ...", afromvol);
2086         code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
2087                                  &fromtid);
2088         EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
2089                afromvol);
2090         VDONE;
2091
2092         /* Get a clone id */
2093         VPRINT1("Allocating new volume id for clone of volume %u ...",
2094                 afromvol);
2095         cloneVol = 0;
2096         vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &cloneVol);
2097         EGOTO1(mfail, vcode,
2098            "Could not get an ID for the clone of volume %u from the VLDB\n",
2099            afromvol);
2100         VDONE;
2101     }
2102
2103     if (atovolid) {
2104         newVol = atovolid;
2105     } else {
2106         /* Get a new volume id */
2107         VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
2108         newVol = 0;
2109         vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &newVol);
2110         EGOTO1(mfail, vcode,
2111                "Could not get an ID for the copy of volume %u from the VLDB\n",
2112                afromvol);
2113         VDONE;
2114     }
2115
2116     if (!(flags & RV_NOCLONE)) {
2117         /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
2118         VPRINT1("Cloning source volume %u ...", afromvol);
2119         strcpy(vname, "copy-clone-temp");
2120         code =
2121             AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname,
2122                         &cloneVol);
2123         EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
2124                afromvol);
2125         VDONE;
2126
2127         VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
2128         rcode = 0;
2129         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2130         fromtid = 0;
2131         if (!code)
2132             code = rcode;
2133         EGOTO1(mfail, code,
2134                "Failed to end the transaction on the source volume %u\n",
2135                afromvol);
2136         VDONE;
2137     }
2138
2139     /* ***
2140      * Create the destination volume
2141      * ***/
2142
2143     if (!(flags & RV_NOCLONE)) {
2144         VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
2145         code =
2146             AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2147                           &clonetid);
2148         EGOTO1(mfail, code,
2149                "Failed to start a transaction on the cloned volume%u\n",
2150                cloneVol);
2151         VDONE;
2152
2153         VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
2154         code =
2155             AFSVolSetFlags(fromconn, clonetid,
2156                            VTDeleteOnSalvage | VTOutOfService); /*redundant */
2157         EGOTO1(mfail, code, "Could not set flags on the cloned volume %u\n",
2158                cloneVol);
2159         VDONE;
2160
2161         /* remember time from which we've dumped the volume */
2162         VPRINT1("Getting status of cloned volume %u ...", cloneVol);
2163         code = AFSVolGetStatus(fromconn, clonetid, &tstatus);
2164         EGOTO1(mfail, code,
2165                "Failed to get the status of the cloned volume %u\n",
2166                cloneVol);
2167         VDONE;
2168
2169         fromDate = CLOCKADJ(tstatus.creationDate);
2170     } else {
2171         fromDate = 0;
2172     }
2173
2174     /* create a volume on the target machine */
2175     cloneFromDate = 0;
2176     code = AFSVolTransCreate(toconn, newVol, atopart, ITOffline, &totid);
2177     if (!code) {
2178         if ((flags & RV_CPINCR)) {
2179             VPRINT1("Getting status of pre-existing volume %u ...", newVol);
2180             code = AFSVolGetStatus(toconn, totid, &tstatus);
2181             EGOTO1(mfail, code,
2182                    "Failed to get the status of the pre-existing volume %u\n",
2183                    newVol);
2184             VDONE;
2185
2186             /* Using the update date should be OK here, but add some fudge */
2187             cloneFromDate = CLOCKADJ(tstatus.updateDate);
2188             if ((flags & RV_NOCLONE))
2189                 fromDate = cloneFromDate;
2190
2191             /* XXX We should check that the source volume's creationDate is
2192              * XXX not newer than the existing target volume, and if not,
2193              * XXX throw away the existing target and do a full dump. */
2194
2195             goto cpincr;
2196         }
2197
2198         /* Delete the existing volume.
2199          * While we are deleting the volume in these steps, the transaction
2200          * we started against the cloned volume (clonetid above) will be
2201          * sitting idle. It will get cleaned up after 600 seconds
2202          */
2203         VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
2204         code = AFSVolDeleteVolume(toconn, totid);
2205         EGOTO1(mfail, code,
2206                "Could not delete the pre-existing volume %u on destination\n",
2207                newVol);
2208         VDONE;
2209
2210         VPRINT1
2211             ("Ending transaction on pre-existing volume %u on destination ...",
2212              newVol);
2213         code = AFSVolEndTrans(toconn, totid, &rcode);
2214         totid = 0;
2215         if (!code)
2216             code = rcode;
2217         EGOTO1(mfail, code,
2218                "Could not end the transaction on pre-existing volume %u on destination\n",
2219                newVol);
2220         VDONE;
2221     }
2222
2223     VPRINT1("Creating the destination volume %u ...", newVol);
2224     code =
2225         AFSVolCreateVolume(toconn, atopart, atovolname,
2226                            (flags & RV_RDONLY) ? volser_RO : volser_RW,
2227                            newVol, &newVol, &totid);
2228     EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
2229            newVol);
2230     VDONE;
2231
2232     VPRINT1("Setting volume flags on destination volume %u ...", newVol);
2233     code =
2234         AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
2235     EGOTO1(mfail, code,
2236            "Failed to set the flags on the destination volume %u\n", newVol);
2237     VDONE;
2238
2239 cpincr:
2240
2241     destination.destHost = ntohl(atoserver);
2242     destination.destPort = AFSCONF_VOLUMEPORT;
2243     destination.destSSID = 1;
2244
2245     strncpy(cookie.name, atovolname, VOLSER_OLDMAXVOLNAME);
2246     cookie.type = (flags & RV_RDONLY) ? ROVOL : RWVOL;
2247     cookie.parent = 0;
2248     cookie.clone = 0;
2249
2250     /***
2251      * Now dump the clone to the new volume
2252      ***/
2253
2254     if (!(flags & RV_NOCLONE)) {
2255         /* XXX probably should have some code here that checks to see if
2256          * XXX we are copying to same server and partition - if so, just
2257          * XXX use a clone to save disk space */
2258
2259         /* Copy the clone to the new volume */
2260         VPRINT2("Dumping from clone %u on source to volume %u on destination ...",
2261             cloneVol, newVol);
2262         code =
2263             AFSVolForward(fromconn, clonetid, cloneFromDate, &destination,
2264                           totid, &cookie);
2265         EGOTO1(mfail, code, "Failed to move data for the volume %u\n",
2266                newVol);
2267         VDONE;
2268
2269         VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
2270         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2271         if (!code)
2272             code = rcode;
2273         clonetid = 0;
2274         EGOTO1(mfail, code,
2275                "Failed to end the transaction on the cloned volume %u\n",
2276                cloneVol);
2277         VDONE;
2278     }
2279
2280     /* ***
2281      * reattach to the main-line volume, and incrementally dump it.
2282      * ***/
2283
2284     VPRINT1("Starting transaction on source volume %u ...", afromvol);
2285     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2286     EGOTO1(mfail, code,
2287            "Failed to create a transaction on the source volume %u\n",
2288            afromvol);
2289     VDONE;
2290
2291     /* now do the incremental */
2292     VPRINT2
2293         ("Doing the%s dump from source to destination for volume %u ... ",
2294          (flags & RV_NOCLONE) ? "" : " incremental",
2295          afromvol);
2296     code =
2297         AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
2298                       &cookie);
2299     EGOTO1(mfail, code,
2300            "Failed to do the%s dump from old site to new site\n",
2301            afromvol);
2302     VDONE;
2303
2304     VPRINT1("Setting volume flags on destination volume %u ...", newVol);
2305     volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0);      /* off or on-line */
2306     code = AFSVolSetFlags(toconn, totid, volflag);
2307     EGOTO(mfail, code,
2308           "Failed to set the flags to make destination volume online\n");
2309     VDONE;
2310
2311     /* put new volume online */
2312     VPRINT1("Ending transaction on destination volume %u ...", newVol);
2313     code = AFSVolEndTrans(toconn, totid, &rcode);
2314     totid = 0;
2315     if (!code)
2316         code = rcode;
2317     EGOTO1(mfail, code,
2318            "Failed to end the transaction on the destination volume %u\n",
2319            newVol);
2320     VDONE;
2321
2322     VPRINT1("Ending transaction on source volume %u ...", afromvol);
2323     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2324     fromtid = 0;
2325     if (!code)
2326         code = rcode;
2327     EGOTO1(mfail, code,
2328            "Failed to end the transaction on the source volume %u\n",
2329            afromvol);
2330     VDONE;
2331
2332     fromtid = 0;
2333
2334     if (!(flags & RV_NOCLONE)) {
2335         VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
2336         code =
2337             AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2338                               &clonetid);
2339         EGOTO1(mfail, code,
2340                "Failed to start a transaction on the cloned volume%u\n",
2341                cloneVol);
2342         VDONE;
2343
2344         /* now delete the clone */
2345         VPRINT1("Deleting the cloned volume %u ...", cloneVol);
2346         code = AFSVolDeleteVolume(fromconn, clonetid);
2347         EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
2348                cloneVol);
2349         VDONE;
2350
2351         VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
2352         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2353         if (!code)
2354             code = rcode;
2355         clonetid = 0;
2356         EGOTO1(mfail, code,
2357                "Failed to end the transaction on the cloned volume %u\n",
2358                cloneVol);
2359         VDONE;
2360     }
2361
2362     if (!(flags & RV_NOVLDB)) {
2363         /* create the vldb entry for the copied volume */
2364         strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
2365         newentry.nServers = 1;
2366         newentry.serverNumber[0] = atoserver;
2367         newentry.serverPartition[0] = atopart;
2368         newentry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2369         newentry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2370         newentry.volumeId[RWVOL] = newVol;
2371         newentry.volumeId[ROVOL] = (flags & RV_RDONLY) ? newVol : 0;
2372         newentry.volumeId[BACKVOL] = 0;
2373         newentry.cloneId = 0;
2374         /*map into right byte order, before passing to xdr, the stuff has to be in host
2375          * byte order. Xdr converts it into network order */
2376         MapNetworkToHost(&newentry, &storeEntry);
2377         /* create the vldb entry */
2378         vcode = VLDB_CreateEntry(&storeEntry);
2379         if (vcode) {
2380             fprintf(STDERR,
2381                     "Could not create a VLDB entry for the volume %s %lu\n",
2382                     atovolname, (unsigned long)newVol);
2383             /*destroy the created volume */
2384             VPRINT1("Deleting the newly created volume %u\n", newVol);
2385             AFSVolDeleteVolume(toconn, totid);
2386             error = vcode;
2387             goto mfail;
2388         }
2389         VPRINT2("Created the VLDB entry for the volume %s %u\n", atovolname,
2390                 newVol);
2391     }
2392
2393     /* normal cleanup code */
2394
2395     if (fromtid) {
2396         VPRINT1("Cleanup: Ending transaction on source volume %u ...",
2397                 afromvol);
2398         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2399         if (code || rcode) {
2400             VPRINT("\n");
2401             fprintf(STDERR,
2402                     "Could not end transaction on the source volume %lu\n",
2403                     (unsigned long)afromvol);
2404             if (!error)
2405                 error = (code ? code : rcode);
2406         }
2407         VDONE;
2408     }
2409
2410     if (clonetid) {
2411         VPRINT1("Cleanup: Ending transaction on clone volume %u ...",
2412                 cloneVol);
2413         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2414         if (code || rcode) {
2415             VPRINT("\n");
2416             fprintf(STDERR,
2417                     "Could not end transaction on the source's clone volume %lu\n",
2418                     (unsigned long)cloneVol);
2419             if (!error)
2420                 error = (code ? code : rcode);
2421         }
2422         VDONE;
2423     }
2424
2425     if (totid) {
2426         VPRINT1("Cleanup: Ending transaction on destination volume %u ...",
2427                 newVol);
2428         code = AFSVolEndTrans(toconn, totid, &rcode);
2429         if (code) {
2430             VPRINT("\n");
2431             fprintf(STDERR,
2432                     "Could not end transaction on destination volume %lu\n",
2433                     (unsigned long)newVol);
2434             if (!error)
2435                 error = (code ? code : rcode);
2436         }
2437         VDONE;
2438     }
2439     if (fromconn)
2440         rx_DestroyConnection(fromconn);
2441     if (toconn)
2442         rx_DestroyConnection(toconn);
2443     PrintError("", error);
2444     return error;
2445
2446     /* come here only when the sky falls */
2447   mfail:
2448
2449     if (pntg) {
2450         fprintf(STDOUT,
2451                 "vos copy: operation interrupted, cleanup in progress...\n");
2452         fprintf(STDOUT, "clear transaction contexts\n");
2453         fflush(STDOUT);
2454     }
2455
2456     if (clonetid) {
2457         VPRINT("Recovery: Ending transaction on clone volume ...");
2458         AFSVolEndTrans(fromconn, clonetid, &rcode);
2459         VDONE;
2460     }
2461     if (totid) {
2462         VPRINT("Recovery: Ending transaction on destination volume ...");
2463         AFSVolEndTrans(toconn, totid, &rcode);
2464         VDONE;
2465     }
2466     if (fromtid) {              /* put it on-line */
2467         VPRINT("Recovery: Ending transaction on source volume ...");
2468         AFSVolEndTrans(fromconn, fromtid, &rcode);
2469         VDONE;
2470     }
2471
2472     VPRINT("Recovery: Accessing VLDB.\n");
2473     vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
2474     if (vcode) {
2475         fprintf(STDOUT, "FATAL: VLDB access error: abort cleanup\n");
2476         fflush(STDOUT);
2477         goto done;
2478     }
2479     MapHostToNetwork(&entry);
2480
2481     /* common cleanup - delete local clone */
2482     if (cloneVol) {
2483         VPRINT1("Recovery: Creating transaction on clone volume %u ...",
2484                 cloneVol);
2485         code =
2486             AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2487                               &clonetid);
2488         if (!code) {
2489             VDONE;
2490
2491             VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2492             AFSVolDeleteVolume(fromconn, clonetid);
2493             VDONE;
2494
2495             VPRINT1("Recovery: Ending transaction on clone volume %u ...",
2496                     cloneVol);
2497             AFSVolEndTrans(fromconn, clonetid, &rcode);
2498             VDONE;
2499         } else {
2500             VPRINT1
2501                 ("\nRecovery: Unable to start transaction on clone volume %u.\n",
2502                  cloneVol);
2503         }
2504     }
2505
2506   done:                 /* routine cleanup */
2507     if (fromconn)
2508         rx_DestroyConnection(fromconn);
2509     if (toconn)
2510         rx_DestroyConnection(toconn);
2511
2512     if (pntg) {
2513         fprintf(STDOUT, "cleanup complete - user verify desired result\n");
2514         fflush(STDOUT);
2515     }
2516     exit(1);
2517 }
2518
2519
2520 int
2521 UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2522               char *atovolname, afs_int32 atoserver, afs_int32 atopart)
2523 {
2524     return UV_CopyVolume2(afromvol, afromserver, afrompart,
2525                           atovolname, atoserver, atopart, 0, 0);
2526 }
2527
2528
2529
2530 /* Make a new backup of volume <avolid> on <aserver> and <apart> 
2531  * if one already exists, update it 
2532  */
2533
2534 int
2535 UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2536 {
2537     struct rx_connection *aconn = (struct rx_connection *)0;
2538     afs_int32 ttid = 0, btid = 0;
2539     afs_int32 backupID;
2540     afs_int32 code = 0, rcode = 0;
2541     char vname[VOLSER_MAXVOLNAME + 1];
2542     struct nvldbentry entry, storeEntry;
2543     afs_int32 error = 0;
2544     int vldblocked = 0, vldbmod = 0, backexists = 1;
2545
2546     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2547
2548     /* the calls to VLDB will succeed only if avolid is a RW volume,
2549      * since we are following the RW hash chain for searching */
2550     code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2551     if (code) {
2552         fprintf(STDERR,
2553                 "Could not fetch the entry for the volume %lu from the VLDB \n",
2554                 (unsigned long)avolid);
2555         error = code;
2556         goto bfail;
2557     }
2558     MapHostToNetwork(&entry);
2559
2560     /* These operations require the VLDB be locked since it means the VLDB
2561      * will change or the vldb is already locked.
2562      */
2563     if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
2564         (entry.flags & VLOP_ALLOPERS) ||        /* vldb lock already held */
2565         (entry.volumeId[BACKVOL] == INVALID_BID)) {     /* no assigned backup volume id */
2566
2567         code = ubik_VL_SetLock(cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2568         if (code) {
2569             fprintf(STDERR,
2570                     "Could not lock the VLDB entry for the volume %lu\n",
2571                     (unsigned long)avolid);
2572             error = code;
2573             goto bfail;
2574         }
2575         vldblocked = 1;
2576
2577         /* Reread the vldb entry */
2578         code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2579         if (code) {
2580             fprintf(STDERR,
2581                     "Could not fetch the entry for the volume %lu from the VLDB \n",
2582                     (unsigned long)avolid);
2583             error = code;
2584             goto bfail;
2585         }
2586         MapHostToNetwork(&entry);
2587     }
2588
2589     if (!ISNAMEVALID(entry.name)) {
2590         fprintf(STDERR, "Name of the volume %s exceeds the size limit\n",
2591                 entry.name);
2592         error = VOLSERBADNAME;
2593         goto bfail;
2594     }
2595
2596     backupID = entry.volumeId[BACKVOL];
2597     if (backupID == INVALID_BID) {
2598         /* Get a backup volume id from the VLDB and update the vldb
2599          * entry with it. 
2600          */
2601         code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &backupID);
2602         if (code) {
2603             fprintf(STDERR,
2604                     "Could not allocate ID for the backup volume of  %lu from the VLDB\n",
2605                     (unsigned long)avolid);
2606             error = code;
2607             goto bfail;
2608         }
2609         entry.volumeId[BACKVOL] = backupID;
2610         vldbmod = 1;
2611     }
2612
2613     /* Test to see if the backup volume exists by trying to create
2614      * a transaction on the backup volume. We've assumed the backup exists.
2615      */
2616     code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2617     if (code) {
2618         if (code != VNOVOL) {
2619             fprintf(STDERR, "Could not reach the backup volume %lu\n",
2620                     (unsigned long)backupID);
2621             error = code;
2622             goto bfail;
2623         }
2624         backexists = 0;         /* backup volume does not exist */
2625     }
2626     if (btid) {
2627         code = AFSVolEndTrans(aconn, btid, &rcode);
2628         btid = 0;
2629         if (code || rcode) {
2630             fprintf(STDERR,
2631                     "Could not end transaction on the previous backup volume %lu\n",
2632                     (unsigned long)backupID);
2633             error = (code ? code : rcode);
2634             goto bfail;
2635         }
2636     }
2637
2638     /* Now go ahead and try to clone the RW volume.
2639      * First start a transaction on the RW volume 
2640      */
2641     code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2642     if (code) {
2643         fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
2644                 (unsigned long)avolid);
2645         error = code;
2646         goto bfail;
2647     }
2648
2649     /* Clone or reclone the volume, depending on whether the backup 
2650      * volume exists or not
2651      */
2652     if (backexists) {
2653         VPRINT1("Re-cloning backup volume %u ...", backupID);
2654
2655         code = AFSVolReClone(aconn, ttid, backupID);
2656         if (code) {
2657             fprintf(STDERR, "Could not re-clone backup volume %lu\n",
2658                     (unsigned long)backupID);
2659             error = code;
2660             goto bfail;
2661         }
2662     } else {
2663         VPRINT1("Creating a new backup clone %u ...", backupID);
2664
2665         strcpy(vname, entry.name);
2666         strcat(vname, ".backup");
2667
2668         code = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID);
2669         if (code) {
2670             fprintf(STDERR, "Failed to clone the volume %lu\n",
2671                     (unsigned long)avolid);
2672             error = code;
2673             goto bfail;
2674         }
2675     }
2676
2677     /* End the transaction on the RW volume */
2678     code = AFSVolEndTrans(aconn, ttid, &rcode);
2679     ttid = 0;
2680     if (code || rcode) {
2681         fprintf(STDERR,
2682                 "Failed to end the transaction on the rw volume %lu\n",
2683                 (unsigned long)avolid);
2684         error = (code ? code : rcode);
2685         goto bfail;
2686     }
2687
2688     /* Mork vldb as backup exists */
2689     if (!(entry.flags & BACK_EXISTS)) {
2690         entry.flags |= BACK_EXISTS;
2691         vldbmod = 1;
2692     }
2693
2694     /* Now go back to the backup volume and bring it on line */
2695     code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2696     if (code) {
2697         fprintf(STDERR,
2698                 "Failed to start a transaction on the backup volume %lu\n",
2699                 (unsigned long)backupID);
2700         error = code;
2701         goto bfail;
2702     }
2703
2704     code = AFSVolSetFlags(aconn, btid, 0);
2705     if (code) {
2706         fprintf(STDERR, "Could not mark the backup volume %lu on line \n",
2707                 (unsigned long)backupID);
2708         error = code;
2709         goto bfail;
2710     }
2711
2712     code = AFSVolEndTrans(aconn, btid, &rcode);
2713     btid = 0;
2714     if (code || rcode) {
2715         fprintf(STDERR,
2716                 "Failed to end the transaction on the backup volume %lu\n",
2717                 (unsigned long)backupID);
2718         error = (code ? code : rcode);
2719         goto bfail;
2720     }
2721
2722     VDONE;
2723
2724     /* Will update the vldb below */
2725
2726   bfail:
2727     if (ttid) {
2728         code = AFSVolEndTrans(aconn, ttid, &rcode);
2729         if (code || rcode) {
2730             fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2731                     (unsigned long)avolid);
2732             if (!error)
2733                 error = (code ? code : rcode);
2734         }
2735     }
2736
2737     if (btid) {
2738         code = AFSVolEndTrans(aconn, btid, &rcode);
2739         if (code || rcode) {
2740             fprintf(STDERR,
2741                     "Could not end transaction the backup volume %lu\n",
2742                     (unsigned long)backupID);
2743             if (!error)
2744                 error = (code ? code : rcode);
2745         }
2746     }
2747
2748     /* Now update the vldb - if modified */
2749     if (vldblocked) {
2750         if (vldbmod) {
2751             MapNetworkToHost(&entry, &storeEntry);
2752             code =
2753                 VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2754                                   (LOCKREL_OPCODE | LOCKREL_AFSID |
2755                                    LOCKREL_TIMESTAMP));
2756             if (code) {
2757                 fprintf(STDERR,
2758                         "Could not update the VLDB entry for the volume %lu \n",
2759                         (unsigned long)avolid);
2760                 if (!error)
2761                     error = code;
2762             }
2763         } else {
2764             code =
2765                 ubik_VL_ReleaseLock(cstruct, 0, avolid, RWVOL,
2766                           (LOCKREL_OPCODE | LOCKREL_AFSID |
2767                            LOCKREL_TIMESTAMP));
2768             if (code) {
2769                 fprintf(STDERR,
2770                         "Could not unlock the VLDB entry for the volume %lu \n",
2771                         (unsigned long)avolid);
2772                 if (!error)
2773                     error = code;
2774             }
2775         }
2776     }
2777
2778     if (aconn)
2779         rx_DestroyConnection(aconn);
2780
2781     PrintError("", error);
2782     return error;
2783 }
2784
2785 /* Make a new clone of volume <avolid> on <aserver> and <apart> 
2786  * using volume ID <acloneid>, or a new ID allocated from the VLDB.
2787  * The new volume is named by <aname>, or by appending ".clone" to
2788  * the existing name if <aname> is NULL.  The following flags are
2789  * supported:
2790  * 
2791  *     RV_RDONLY  - target volume is RO
2792  *     RV_OFFLINE - leave target volume offline
2793  */
2794
2795 int
2796 UV_CloneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid,
2797                afs_int32 acloneid, char *aname, int flags)
2798 {
2799     struct rx_connection *aconn = (struct rx_connection *)0;
2800     afs_int32 ttid = 0, btid = 0;
2801     afs_int32 code = 0, rcode = 0;
2802     char vname[VOLSER_MAXVOLNAME + 1];
2803     afs_int32 error = 0;
2804     int backexists = 1;
2805     volEntries volumeInfo;
2806
2807     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2808
2809     if (!aname) {
2810         volumeInfo.volEntries_val = (volintInfo *) 0;
2811         volumeInfo.volEntries_len = 0;
2812         code = AFSVolListOneVolume(aconn, apart, avolid, &volumeInfo);
2813         if (code) {
2814             fprintf(stderr, "Could not get info for volume %lu\n",
2815                     (unsigned long)avolid);
2816             error = code;
2817             goto bfail;
2818         }
2819         strncpy(vname, volumeInfo.volEntries_val[0].name,
2820                 VOLSER_OLDMAXVOLNAME - 7);
2821         vname[VOLSER_OLDMAXVOLNAME - 7] = 0;
2822         strcat(vname, ".clone");
2823         aname = vname;
2824         if (volumeInfo.volEntries_val)
2825             free(volumeInfo.volEntries_val);
2826     }
2827
2828     if (!acloneid) {
2829         /* Get a clone id */
2830         VPRINT1("Allocating new volume id for clone of volume %u ...",
2831                 avolid);
2832         code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &acloneid);
2833         EGOTO1(bfail, code,
2834            "Could not get an ID for the clone of volume %u from the VLDB\n",
2835            avolid);
2836         VDONE;
2837     }
2838
2839     /* Test to see if the clone volume exists by trying to create
2840      * a transaction on the clone volume. We've assumed the clone exists.
2841      */
2842     /* XXX I wonder what happens if the clone has some other parent... */
2843     code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
2844     if (code) {
2845         if (code != VNOVOL) {
2846             fprintf(STDERR, "Could not reach the clone volume %lu\n",
2847                     (unsigned long)acloneid);
2848             error = code;
2849             goto bfail;
2850         }
2851         backexists = 0;         /* backup volume does not exist */
2852     }
2853     if (btid) {
2854         code = AFSVolEndTrans(aconn, btid, &rcode);
2855         btid = 0;
2856         if (code || rcode) {
2857             fprintf(STDERR,
2858                     "Could not end transaction on the previous clone volume %lu\n",
2859                     (unsigned long)acloneid);
2860             error = (code ? code : rcode);
2861             goto bfail;
2862         }
2863     }
2864
2865     /* Now go ahead and try to clone the RW volume.
2866      * First start a transaction on the RW volume 
2867      */
2868     code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2869     if (code) {
2870         fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
2871                 (unsigned long)avolid);
2872         error = code;
2873         goto bfail;
2874     }
2875
2876     /* Clone or reclone the volume, depending on whether the backup 
2877      * volume exists or not
2878      */
2879     if (backexists) {
2880         VPRINT1("Re-cloning clone volume %u ...", acloneid);
2881
2882         code = AFSVolReClone(aconn, ttid, acloneid);
2883         if (code) {
2884             fprintf(STDERR, "Could not re-clone backup volume %lu\n",
2885                     (unsigned long)acloneid);
2886             error = code;
2887             goto bfail;
2888         }
2889     } else {
2890         VPRINT1("Creating a new clone %u ...", acloneid);
2891
2892         code = AFSVolClone(aconn, ttid, 0,
2893                            (flags & RV_RDONLY) ? readonlyVolume : backupVolume,
2894                            aname, &acloneid);
2895         if (code) {
2896             fprintf(STDERR, "Failed to clone the volume %lu\n",
2897                     (unsigned long)avolid);
2898             error = code;
2899             goto bfail;
2900         }
2901     }
2902
2903     /* End the transaction on the RW volume */
2904     code = AFSVolEndTrans(aconn, ttid, &rcode);
2905     ttid = 0;
2906     if (code || rcode) {
2907         fprintf(STDERR,
2908                 "Failed to end the transaction on the rw volume %lu\n",
2909                 (unsigned long)avolid);
2910         error = (code ? code : rcode);
2911         goto bfail;
2912     }
2913
2914     /* Now go back to the backup volume and bring it on line */
2915     if (!(flags & RV_OFFLINE)) {
2916         code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
2917         if (code) {
2918             fprintf(STDERR,
2919                     "Failed to start a transaction on the clone volume %lu\n",
2920                     (unsigned long)acloneid);
2921             error = code;
2922             goto bfail;
2923         }
2924
2925         code = AFSVolSetFlags(aconn, btid, 0);
2926         if (code) {
2927             fprintf(STDERR, "Could not mark the clone volume %lu on line \n",
2928                     (unsigned long)acloneid);
2929             error = code;
2930             goto bfail;
2931         }
2932
2933         code = AFSVolEndTrans(aconn, btid, &rcode);
2934         btid = 0;
2935         if (code || rcode) {
2936             fprintf(STDERR,
2937                     "Failed to end the transaction on the clone volume %lu\n",
2938                     (unsigned long)acloneid);
2939             error = (code ? code : rcode);
2940             goto bfail;
2941         }
2942     }
2943
2944     VDONE;
2945
2946   bfail:
2947     if (ttid) {
2948         code = AFSVolEndTrans(aconn, ttid, &rcode);
2949         if (code || rcode) {
2950             fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2951                     (unsigned long)avolid);
2952             if (!error)
2953                 error = (code ? code : rcode);
2954         }
2955     }
2956
2957     if (btid) {
2958         code = AFSVolEndTrans(aconn, btid, &rcode);
2959         if (code || rcode) {
2960             fprintf(STDERR,
2961                     "Could not end transaction on the clone volume %lu\n",
2962                     (unsigned long)acloneid);
2963             if (!error)
2964                 error = (code ? code : rcode);
2965         }
2966     }
2967
2968     if (aconn)
2969         rx_DestroyConnection(aconn);
2970
2971     PrintError("", error);
2972     return error;
2973 }
2974
2975 static int
2976 DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
2977        afs_int32 flags)
2978 {
2979     afs_int32 acode, ccode, rcode, tid;
2980     ccode = rcode = tid = 0;
2981
2982     acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2983     if (!acode) {               /* It really was there */
2984         acode = AFSVolDeleteVolume(conn, tid);
2985         if (acode) {
2986             fprintf(STDERR, "Failed to delete volume %lu.\n",
2987                     (unsigned long)vid);
2988             PrintError("", acode);
2989         }
2990         ccode = AFSVolEndTrans(conn, tid, &rcode);
2991         if (!ccode)
2992             ccode = rcode;
2993         if (ccode) {
2994             fprintf(STDERR, "Failed to end transaction on volume %lu.\n",
2995                     (unsigned long)vid);
2996             PrintError("", ccode);
2997         }
2998     }
2999
3000     return acode;
3001 }
3002
3003 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
3004 #define ERROREXIT(ec) { error = (ec); goto rfail; }
3005
3006 /* Get a "transaction" on this replica.  Create the volume 
3007  * if necessary.  Return the time from which a dump should
3008  * be made (0 if it's a new volume)
3009  */
3010 static int
3011 GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
3012          struct rx_connection **connPtr, afs_int32 * transPtr,
3013          afs_int32 * crtimePtr, afs_int32 * uptimePtr)
3014 {
3015     afs_int32 volid;
3016     struct volser_status tstatus;
3017     int code, rcode, tcode;
3018
3019     *connPtr = (struct rx_connection *)0;
3020     *transPtr = 0;
3021     *crtimePtr = 0;
3022     *uptimePtr = 0;
3023
3024     /* get connection to the replication site */
3025     *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
3026     if (!*connPtr)
3027         goto fail;              /* server is down */
3028
3029     volid = vldbEntryPtr->volumeId[ROVOL];
3030     if (volid)
3031         code =
3032             AFSVolTransCreate(*connPtr, volid,
3033                               vldbEntryPtr->serverPartition[index], ITOffline,
3034                               transPtr);
3035
3036     /* If the volume does not exist, create it */
3037     if (!volid || code) {
3038         char volname[64];
3039
3040         if (volid && (code != VNOVOL)) {
3041             PrintError("Failed to start a transaction on the RO volume.\n",
3042                        code);
3043             goto fail;
3044         }
3045
3046         strcpy(volname, vldbEntryPtr->name);
3047         strcat(volname, ".readonly");
3048
3049         if (verbose) {
3050             fprintf(STDOUT,
3051                     "Creating new volume %lu on replication site %s: ",
3052                     (unsigned long)volid,
3053                     hostutil_GetNameByINet(vldbEntryPtr->
3054                                            serverNumber[index]));
3055             fflush(STDOUT);
3056         }
3057
3058         code =
3059             AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
3060                                volname, volser_RO,
3061                                vldbEntryPtr->volumeId[RWVOL], &volid,
3062                                transPtr);
3063         if (code) {
3064             PrintError("Failed to create the ro volume: ", code);
3065             goto fail;
3066         }
3067         vldbEntryPtr->volumeId[ROVOL] = volid;
3068
3069         VDONE;
3070
3071         /* The following is a bit redundant, since create sets these flags by default */
3072         code =
3073             AFSVolSetFlags(*connPtr, *transPtr,
3074                            VTDeleteOnSalvage | VTOutOfService);
3075         if (code) {
3076             PrintError("Failed to set flags on the ro volume: ", code);
3077             goto fail;
3078         }
3079     }
3080
3081     /* Otherwise, the transaction did succeed, so get the creation date of the
3082      * latest RO volume on the replication site 
3083      */
3084     else {
3085         VPRINT2("Updating existing ro volume %u on %s ...\n", volid,
3086                 hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
3087
3088         code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
3089         if (code) {
3090             PrintError("Failed to get status of volume on destination: ",
3091                        code);
3092             goto fail;
3093         }
3094         *crtimePtr = CLOCKADJ(tstatus.creationDate);
3095         *uptimePtr = CLOCKADJ(tstatus.updateDate);
3096     }
3097
3098     return 0;
3099
3100   fail:
3101     if (*transPtr) {
3102         tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
3103         *transPtr = 0;
3104         if (!tcode)
3105             tcode = rcode;
3106         if (tcode)
3107             PrintError("Could not end transaction on a ro volume: ", tcode);
3108     }
3109
3110     return code;
3111 }
3112
3113 static int
3114 SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
3115                         afs_int32 fromdate, manyDests * tr, afs_int32 flags,
3116                         void *cookie, manyResults * results)
3117 {
3118     int i;
3119
3120     for (i = 0; i < tr->manyDests_len; i++) {
3121         results->manyResults_val[i] =
3122             AFSVolForward(fromconn, fromtid, fromdate,
3123                           &(tr->manyDests_val[i].server),
3124                           tr->manyDests_val[i].trans, cookie);
3125     }
3126     return 0;
3127 }
3128
3129
3130 /* UV_ReleaseVolume()
3131  *    Release volume <afromvol> on <afromserver> <afrompart> to all
3132  *    its RO sites (full release). Unless the previous release was
3133  *    incomplete: in which case we bring the remaining incomplete
3134  *    volumes up to date with the volumes that were released
3135  *    successfully.
3136  *    forceflag: Performs a full release.
3137  *
3138  *    Will create a clone from the RW, then dump the clone out to 
3139  *    the remaining replicas. If there is more than 1 RO sites,
3140  *    ensure that the VLDB says at least one RO is available all
3141  *    the time: Influences when we write back the VLDB entry.
3142  */
3143
3144 int
3145 UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
3146                  afs_int32 afrompart, int forceflag)
3147 {
3148     char vname[64];
3149     afs_int32 code, vcode, rcode, tcode;
3150     afs_int32 cloneVolId, roVolId;
3151     struct replica *replicas = 0;
3152     struct nvldbentry entry, storeEntry;
3153     int i, volcount, m, fullrelease, vldbindex;
3154     int failure;
3155     struct restoreCookie cookie;
3156     struct rx_connection **toconns = 0;
3157     struct release *times = 0;
3158     int nservers = 0;
3159     struct rx_connection *fromconn = (struct rx_connection *)0;
3160     afs_int32 error = 0;
3161     int islocked = 0;
3162     afs_int32 clonetid = 0, onlinetid;
3163     afs_int32 fromtid = 0;
3164     afs_uint32 fromdate, thisdate;
3165     time_t tmv;
3166     int s;
3167     manyDests tr;
3168     manyResults results;
3169     int rwindex, roindex, roclone, roexists;
3170     afs_int32 rwcrdate, rwupdate, clcrdate;
3171     struct rtime {
3172         int validtime;
3173         afs_uint32 uptime;
3174     } remembertime[NMAXNSERVERS];
3175     int releasecount = 0;
3176     struct volser_status volstatus;
3177
3178     memset((char *)remembertime, 0, sizeof(remembertime));
3179     memset((char *)&results, 0, sizeof(results));
3180
3181     vcode = ubik_VL_SetLock(cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
3182     if (vcode != VL_RERELEASE)
3183         ONERROR(vcode, afromvol,
3184                 "Could not lock the VLDB entry for the volume %u.\n");
3185     islocked = 1;
3186
3187     /* Get the vldb entry in readable format */
3188     vcode = VLDB_GetEntryByID(afromvol, RWVOL, &entry);
3189     ONERROR(vcode, afromvol,
3190             "Could not fetch the entry for the volume %u from the VLDB.\n");
3191     MapHostToNetwork(&entry);
3192
3193     if (verbose)
3194         EnumerateEntry(&entry);
3195
3196     if (!ISNAMEVALID(entry.name))
3197         ONERROR(VOLSERBADOP, entry.name,
3198                 "Volume name %s is too long, rename before releasing.\n");
3199     if (entry.volumeId[RWVOL] != afromvol)
3200         ONERROR(VOLSERBADOP, afromvol,
3201                 "The volume %u being released is not a read-write volume.\n");
3202     if (entry.nServers <= 1)
3203         ONERROR(VOLSERBADOP, afromvol,
3204                 "Volume %u has no replicas - release operation is meaningless!\n");
3205     if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
3206         ONERROR(VOLSERBADOP, entry.name,
3207                 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
3208
3209     /* roclone is true if one of the RO volumes is on the same
3210      * partition as the RW volume. In this case, we make the RO volume
3211      * on the same partition a clone instead of a complete copy.
3212      */
3213
3214     roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
3215     roclone = ((roindex == -1) ? 0 : 1);
3216     rwindex = Lp_GetRwIndex(&entry);
3217     if (rwindex < 0)
3218         ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
3219
3220     /* Make sure we have a RO volume id to work with */
3221     if (entry.volumeId[ROVOL] == INVALID_BID) {
3222         /* need to get a new RO volume id */
3223         vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &roVolId);
3224         ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
3225
3226         entry.volumeId[ROVOL] = roVolId;
3227         MapNetworkToHost(&entry, &storeEntry);
3228         vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3229         ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
3230     }
3231
3232     /* Will we be completing a previously unfinished release. -force overrides */
3233     for (s = 0, m = 0, fullrelease=0, i=0; (i<entry.nServers); i++) {
3234         if (entry.serverFlags[i] & ITSROVOL) {
3235             m++;
3236             if (entry.serverFlags[i] & NEW_REPSITE) s++;
3237         }
3238     }
3239     if ((forceflag && !fullrelease) || (s == m) || (s == 0))
3240         fullrelease = 1;
3241
3242     /* Determine which volume id to use and see if it exists */
3243     cloneVolId =
3244         ((fullrelease
3245           || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
3246     code = VolumeExists(afromserver, afrompart, cloneVolId);
3247     roexists = ((code == ENODEV) ? 0 : 1);
3248
3249     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3250     if (!fromconn)
3251         ONERROR(-1, afromserver,
3252                 "Cannot establish connection with server 0x%x\n");
3253
3254     if (!fullrelease) {
3255         if (!roexists)
3256             fullrelease = 1;    /* Do a full release if RO clone does not exist */
3257         else {
3258             /* Begin transaction on RW and mark it busy while we query it */
3259             code = AFSVolTransCreate(
3260                         fromconn, afromvol, afrompart, ITBusy, &fromtid
3261                    );
3262             ONERROR(code, afromvol,
3263                     "Failed to start transaction on RW volume %u\n");
3264
3265             /* Query the creation date for the RW */
3266             code = AFSVolGetStatus(fromconn, fromtid, &volstatus);
3267             ONERROR(code, afromvol,
3268                     "Failed to get the status of RW volume %u\n");
3269             rwcrdate = volstatus.creationDate;
3270             rwupdate = volstatus.updateDate;
3271
3272             /* End transaction on RW */
3273             code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3274             fromtid = 0;
3275             ONERROR((code ? code : rcode), afromvol,
3276                     "Failed to end transaction on RW volume %u\n");
3277
3278             /* Begin transaction on clone and mark it busy while we query it */
3279             code = AFSVolTransCreate(
3280                         fromconn, cloneVolId, afrompart, ITBusy, &clonetid
3281                    );
3282             ONERROR(code, cloneVolId,
3283                     "Failed to start transaction on RW clone %u\n");
3284
3285             /* Query the creation date for the clone */
3286             code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3287             ONERROR(code, cloneVolId,
3288                     "Failed to get the status of RW clone %u\n");
3289             clcrdate = volstatus.creationDate;
3290
3291             /* End transaction on clone */
3292             code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3293             clonetid = 0;
3294             ONERROR((code ? code : rcode), cloneVolId,
3295                     "Failed to end transaction on RW clone %u\n");
3296
3297             if (rwcrdate > clcrdate)
3298                 fullrelease = 2;/* Do a full release if RO clone older than RW */
3299         }
3300     }
3301
3302     if (verbose) {
3303         switch (fullrelease) {
3304             case 2:
3305                 fprintf(STDOUT, "RW %lu changed, doing a complete release\n",
3306                         (unsigned long)afromvol);
3307                 break;
3308             case 1:
3309                 fprintf(STDOUT, "This is a complete release of volume %lu\n",
3310                         (unsigned long)afromvol);
3311                 break;
3312             case 0:
3313                 fprintf(STDOUT, "This is a completion of a previous release\n");
3314                 break;
3315         }
3316     }
3317
3318     if (fullrelease) {
3319         /* If the RO clone exists, then if the clone is a temporary
3320          * clone, delete it. Or if the RO clone is marked RO_DONTUSE
3321          * (it was recently added), then also delete it. We do not
3322          * want to "reclone" a temporary RO clone.
3323          */
3324         if (roexists
3325             && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
3326             code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
3327             if (code && (code != VNOVOL))
3328                 ERROREXIT(code);
3329             roexists = 0;
3330         }
3331
3332         /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
3333          * write this entry out to the vlserver until after the first
3334          * RO volume is released (temp RO clones don't count).
3335          */
3336         for (i = 0; i < entry.nServers; i++) {
3337             entry.serverFlags[i] &= ~NEW_REPSITE;
3338             entry.serverFlags[i] |= RO_DONTUSE;
3339         }
3340         entry.serverFlags[rwindex] |= NEW_REPSITE;
3341         entry.serverFlags[rwindex] &= ~RO_DONTUSE;
3342
3343         /* Begin transaction on RW and mark it busy while we clone it */
3344         code =
3345             AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
3346                               &clonetid);
3347         ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
3348
3349         /* Clone or reclone the volume */
3350         if (roexists) {
3351             VPRINT1("Recloning RW volume %u...", cloneVolId);
3352             code = AFSVolReClone(fromconn, clonetid, cloneVolId);
3353             ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
3354             VDONE;
3355         } else {
3356             if (roclone) {
3357                 strcpy(vname, entry.name);
3358                 strcat(vname, ".readonly");
3359                 VPRINT1("Cloning RW volume %u to permanent RO...", afromvol);
3360             } else {
3361                 strcpy(vname, "readonly-clone-temp");
3362                 VPRINT1("Cloning RW volume %u to temporary RO...", afromvol);
3363             }
3364             code =
3365                 AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
3366                             &cloneVolId);
3367             ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
3368             VDONE;
3369         }
3370
3371         /* Get the time the RW was created for future information */
3372         VPRINT1("Getting status of RW volume %u...", afromvol);
3373         code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3374         ONERROR(code, afromvol,
3375                 "Failed to get the status of the RW volume %u\n");
3376         VDONE;
3377         rwcrdate = volstatus.creationDate;
3378         rwupdate = volstatus.updateDate;
3379
3380         /* End the transaction on the RW volume */
3381         VPRINT1("Ending cloning transaction on RW volume %u...", afromvol);
3382         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3383         clonetid = 0;
3384         ONERROR((code ? code : rcode), afromvol,
3385                 "Failed to end cloning transaction on RW %u\n");
3386         VDONE;
3387
3388         /* Remember clone volume ID in case we fail or are interrupted */
3389         entry.cloneId = cloneVolId;
3390
3391         if (roclone) {
3392             /* Bring the RO clone online - though not if it's a temporary clone */
3393             VPRINT1("Starting transaction on RO clone volume %u...",
3394                     cloneVolId);
3395             code =
3396                 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
3397                                   &onlinetid);
3398             ONERROR(code, cloneVolId,
3399                     "Failed to start transaction on volume %u\n");
3400             VDONE;
3401
3402             VPRINT1("Setting volume flags for volume %u...", cloneVolId);
3403             tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
3404             VDONE;
3405
3406             VPRINT1("Ending transaction on volume %u...", cloneVolId);
3407             code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
3408             ONERROR((code ? code : rcode), cloneVolId,
3409                     "Failed to end transaction on RO clone %u\n");
3410             VDONE;
3411
3412             ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
3413
3414             /* Sleep so that a client searching for an online volume won't
3415              * find the clone offline and then the next RO offline while the 
3416              * release brings the clone online and the next RO offline (race).
3417              * There is a fix in the 3.4 client that does not need this sleep
3418              * anymore, but we don't know what clients we have.
3419              */
3420             if (entry.nServers > 2)
3421                 sleep(5);
3422
3423             /* Mark the RO clone in the VLDB as a good site (already released) */
3424             entry.serverFlags[roindex] |= NEW_REPSITE;
3425             entry.serverFlags[roindex] &= ~RO_DONTUSE;
3426             entry.flags |= RO_EXISTS;
3427
3428             releasecount++;
3429
3430             /* Write out the VLDB entry only if the clone is not a temporary
3431              * clone. If we did this to a temporary clone then we would end
3432              * up marking all the ROs as "old release" making the ROs
3433              * temporarily unavailable.
3434              */
3435             MapNetworkToHost(&entry, &storeEntry);
3436             VPRINT1("Replacing VLDB entry for %s...", entry.name);
3437             vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3438             ONERROR(vcode, entry.name,
3439                     "Could not update vldb entry for %s.\n");
3440             VDONE;
3441         }
3442     }
3443
3444     /* Now we will release from the clone to the remaining RO replicas.
3445      * The first 2 ROs (counting the non-temporary RO clone) are released
3446      * individually: releasecount. This is to reduce the race condition
3447      * of clients trying to find an on-line RO volume. The remaining ROs
3448      * are released in parallel but no more than half the number of ROs
3449      * (rounded up) at a time: nservers.
3450      */
3451
3452     strcpy(vname, entry.name);
3453     strcat(vname, ".readonly");
3454     memset(&cookie, 0, sizeof(cookie));
3455     strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
3456     cookie.type = ROVOL;
3457     cookie.parent = entry.volumeId[RWVOL];
3458     cookie.clone = 0;
3459
3460     nservers = entry.nServers / 2;      /* how many to do at once, excluding clone */
3461     replicas =
3462         (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
3463     times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
3464     toconns =
3465         (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
3466                                         nservers + 1);
3467     results.manyResults_val =
3468         (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
3469     if (!replicas || !times || !!!results.manyResults_val || !toconns)
3470         ONERROR(ENOMEM, 0,
3471                 "Failed to create transaction on the release clone\n");
3472
3473     memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
3474     memset(times, 0, (sizeof(struct release) * nservers + 1));
3475     memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
3476     memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
3477
3478     /* Create a transaction on the cloned volume */
3479     VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
3480     code =
3481         AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
3482     if (!fullrelease && code)
3483         ONERROR(VOLSERNOVOL, afromvol,
3484                 "Old clone is inaccessible. Try vos release -f %u.\n");
3485     ONERROR(code, 0, "Failed to create transaction on the release clone\n");
3486     VDONE;
3487
3488     /* For each index in the VLDB */
3489     for (vldbindex = 0; vldbindex < entry.nServers;) {
3490
3491         /* Get a transaction on the replicas. Pick replacas which have an old release. */
3492         for (volcount = 0;
3493              ((volcount < nservers) && (vldbindex < entry.nServers));
3494              vldbindex++) {
3495             /* The first two RO volumes will be released individually.
3496              * The rest are then released in parallel. This is a hack
3497              * for clients not recognizing right away when a RO volume
3498              * comes back on-line.
3499              */
3500             if ((volcount == 1) && (releasecount < 2))
3501                 break;
3502
3503             if (vldbindex == roindex)
3504                 continue;       /* the clone    */
3505             if ((entry.serverFlags[vldbindex] & NEW_REPSITE)
3506                 && !(entry.serverFlags[vldbindex] & RO_DONTUSE))
3507                 continue;
3508             if (!(entry.serverFlags[vldbindex] & ITSROVOL))
3509                 continue;       /* not a RO vol */
3510
3511
3512             /* Get a Transaction on this replica. Get a new connection if
3513              * necessary.  Create the volume if necessary.  Return the
3514              * time from which the dump should be made (0 if it's a new
3515              * volume).  Each volume might have a different time. 
3516              */
3517             replicas[volcount].server.destHost =
3518                 ntohl(entry.serverNumber[vldbindex]);
3519             replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
3520             replicas[volcount].server.destSSID = 1;
3521             times[volcount].vldbEntryIndex = vldbindex;
3522
3523             code =
3524                 GetTrans(&entry, vldbindex, &(toconns[volcount]),
3525                          &(replicas[volcount].trans),
3526                          &(times[volcount].crtime),
3527                          &(times[volcount].uptime));
3528             if (code)
3529                 continue;
3530
3531             /* Thisdate is the date from which we want to pick up all changes */
3532             if (forceflag || !fullrelease
3533                 || (rwcrdate > times[volcount].crtime)) {
3534                 /* If the forceflag is set, then we want to do a full dump.
3535                  * If it's not a full release, we can't be sure that the creation
3536                  *  date is good (so we also do a full dump).
3537                  * If the RW volume was replaced (its creation date is newer than
3538                  *  the last release), then we can't be sure what has changed (so
3539                  *  we do a full dump).
3540                  */
3541                 thisdate = 0;
3542             } else if (remembertime[vldbindex].validtime) {
3543                 /* Trans was prev ended. Use the time from the prev trans
3544                  * because, prev trans may have created the volume. In which
3545                  * case time[volcount].time would be now instead of 0.
3546                  */
3547                 thisdate =
3548                     (remembertime[vldbindex].uptime < times[volcount].uptime)
3549                         ? remembertime[vldbindex].uptime
3550                         : times[volcount].uptime;
3551             } else {
3552                 thisdate = times[volcount].uptime;
3553             }
3554             remembertime[vldbindex].validtime = 1;
3555             remembertime[vldbindex].uptime = thisdate;
3556
3557             if (volcount == 0) {
3558                 fromdate = thisdate;
3559             } else {
3560                 /* Include this volume if it is within 15 minutes of the earliest */
3561                 if (((fromdate >
3562                       thisdate) ? (fromdate - thisdate) : (thisdate -
3563                                                            fromdate)) > 900) {
3564                     AFSVolEndTrans(toconns[volcount],
3565                                    replicas[volcount].trans, &rcode);
3566                     replicas[volcount].trans = 0;
3567                     break;
3568                 }
3569                 if (thisdate < fromdate)
3570                     fromdate = thisdate;
3571             }
3572             volcount++;
3573         }
3574         if (!volcount)
3575             continue;
3576
3577         if (verbose) {
3578             fprintf(STDOUT, "Starting ForwardMulti from %lu to %u on %s",
3579                     (unsigned long)cloneVolId, entry.volumeId[ROVOL],
3580                     hostutil_GetNameByINet(entry.
3581                                            serverNumber[times[0].
3582                                                         vldbEntryIndex]));
3583
3584             for (s = 1; s < volcount; s++) {
3585                 fprintf(STDOUT, " and %s",
3586                         hostutil_GetNameByINet(entry.
3587                                                serverNumber[times[s].
3588                                                             vldbEntryIndex]));
3589             }
3590
3591             if (fromdate == 0)
3592                 fprintf(STDOUT, " (full release)");
3593             else {
3594                 tmv = fromdate;
3595                 fprintf(STDOUT, " (as of %.24s)", ctime(&tmv));
3596             }
3597             fprintf(STDOUT, ".\n");
3598             fflush(STDOUT);
3599         }
3600
3601         /* Release the ones we have collected */
3602         tr.manyDests_val = &(replicas[0]);
3603         tr.manyDests_len = results.manyResults_len = volcount;
3604         code =
3605             AFSVolForwardMultiple(fromconn, fromtid, fromdate, &tr,
3606                                   0 /*spare */ , &cookie, &results);
3607         if (code == RXGEN_OPCODE) {     /* RPC Interface Mismatch */
3608             code =
3609                 SimulateForwardMultiple(fromconn, fromtid, fromdate, &tr,
3610                                         0 /*spare */ , &cookie, &results);
3611             nservers = 1;
3612         }
3613
3614         if (code) {
3615             PrintError("Release failed: ", code);
3616         } else {
3617             for (m = 0; m < volcount; m++) {
3618                 if (results.manyResults_val[m]) {
3619                     if ((m == 0) || (results.manyResults_val[m] != ENOENT)) {
3620                         /* we retry timed out transaction. When it is
3621                          * not the first volume and the transaction wasn't found
3622                          * (assume it timed out and was garbage collected by volser).
3623                          */
3624                         PrintError
3625                             ("Failed to dump volume from clone to a ro site: ",
3626                              results.manyResults_val[m]);
3627                     }
3628                     continue;
3629                 }
3630
3631                 code =
3632                     AFSVolSetIdsTypes(toconns[m], replicas[m].trans, vname,
3633                                       ROVOL, entry.volumeId[RWVOL], 0, 0);
3634                 if (code) {
3635                     if ((m == 0) || (code != ENOENT)) {
3636                         PrintError("Failed to set correct names and ids: ",
3637                                    code);
3638                     }
3639                     continue;
3640                 }
3641
3642                 /* have to clear dest. flags to ensure new vol goes online:
3643                  * because the restore (forwarded) operation copied
3644                  * the V_inService(=0) flag over to the destination. 
3645                  */
3646                 code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
3647                 if (code) {
3648                     if ((m == 0) || (code != ENOENT)) {
3649                         PrintError("Failed to set flags on ro volume: ",
3650                                    code);
3651                     }
3652                     continue;
3653                 }
3654
3655                 entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
3656                 entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
3657                 entry.flags |= RO_EXISTS;
3658                 releasecount++;
3659             }
3660         }
3661
3662         /* End the transactions and destroy the connections */
3663         for (s = 0; s < volcount; s++) {
3664             if (replicas[s].trans)
3665                 code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
3666             replicas[s].trans = 0;
3667             if (!code)
3668                 code = rcode;
3669             if (code) {
3670                 if ((s == 0) || (code != ENOENT)) {
3671                     PrintError("Could not end transaction on a ro volume: ",
3672                                code);
3673                 } else {
3674                     PrintError
3675                         ("Transaction timed out on a ro volume. Will retry.\n",
3676                          0);
3677                     if (times[s].vldbEntryIndex < vldbindex)
3678                         vldbindex = times[s].vldbEntryIndex;
3679                 }
3680             }
3681
3682             if (toconns[s])
3683                 rx_DestroyConnection(toconns[s]);
3684             toconns[s] = 0;
3685         }
3686
3687         MapNetworkToHost(&entry, &storeEntry);
3688         vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3689         ONERROR(vcode, afromvol,
3690                 " Could not update VLDB entry for volume %u\n");
3691     }                           /* for each index in the vldb */
3692
3693     /* End the transaction on the cloned volume */
3694     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3695     fromtid = 0;
3696     if (!code)
3697         code = rcode;
3698     if (code)
3699         PrintError("Failed to end transaction on rw volume: ", code);
3700
3701     /* Figure out if any volume were not released and say so */
3702     for (failure = 0, i = 0; i < entry.nServers; i++) {
3703         if (!(entry.serverFlags[i] & NEW_REPSITE))
3704             failure++;
3705     }
3706     if (failure) {
3707         char pname[10];
3708         fprintf(STDERR,
3709                 "The volume %lu could not be released to the following %d sites:\n",
3710                 (unsigned long)afromvol, failure);
3711         for (i = 0; i < entry.nServers; i++) {
3712             if (!(entry.serverFlags[i] & NEW_REPSITE)) {
3713                 MapPartIdIntoName(entry.serverPartition[i], pname);
3714                 fprintf(STDERR, "\t%35s %s\n",
3715                         hostutil_GetNameByINet(entry.serverNumber[i]), pname);
3716             }
3717         }
3718
3719         MapNetworkToHost(&entry, &storeEntry);
3720         vcode =
3721             VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
3722                               LOCKREL_TIMESTAMP);
3723         ONERROR(vcode, afromvol,
3724                 " Could not update VLDB entry for volume %u\n");
3725
3726         ERROREXIT(VOLSERBADRELEASE);
3727     }
3728
3729     /* All the ROs were release successfully. Remove the temporary clone */
3730     if (!roclone) {
3731         if (verbose) {
3732             fprintf(STDOUT, "Deleting the releaseClone %lu ...",
3733                     (unsigned long)cloneVolId);
3734             fflush(STDOUT);
3735         }
3736         code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
3737         ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
3738         VDONE;
3739     }
3740     entry.cloneId = 0;
3741
3742     for (i = 0; i < entry.nServers; i++)
3743         entry.serverFlags[i] &= ~NEW_REPSITE;
3744
3745     /* Update the VLDB */
3746     VPRINT("updating VLDB ...");
3747
3748     MapNetworkToHost(&entry, &storeEntry);
3749     vcode =
3750         VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
3751                           LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3752     ONERROR(vcode, afromvol, " Could not update VLDB entry for volume %u\n");
3753     VDONE;
3754
3755   rfail:
3756     if (clonetid) {
3757         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3758         clonetid = 0;
3759         if (code) {
3760             fprintf(STDERR,
3761                     "Failed to end cloning transaction on the RW volume %lu\n",
3762                     (unsigned long)afromvol);
3763             if (!error)
3764                 error = code;
3765         }
3766     }
3767     if (fromtid) {
3768         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3769         fromtid = 0;
3770         if (code) {
3771             fprintf(STDERR,
3772                     "Failed to end transaction on the release clone %lu\n",
3773                     (unsigned long)cloneVolId);
3774             if (!error)
3775                 error = code;
3776         }
3777     }
3778     for (i = 0; i < nservers; i++) {
3779         if (replicas && replicas[i].trans) {
3780             code = AFSVolEndTrans(toconns[i], replicas[i].trans, &rcode);
3781             replicas[i].trans = 0;
3782             if (code) {
3783                 fprintf(STDERR,
3784                         "Failed to end transaction on ro volume %u at server %s\n",
3785                         entry.volumeId[ROVOL],
3786                         hostutil_GetNameByINet(htonl
3787                                                (replicas[i].server.
3788                                                 destHost)));
3789                 if (!error)
3790                     error = code;
3791             }
3792         }
3793         if (toconns && toconns[i]) {
3794             rx_DestroyConnection(toconns[i]);
3795             toconns[i] = 0;
3796         }
3797     }
3798     if (islocked) {
3799         vcode =
3800             ubik_VL_ReleaseLock(cstruct, 0, afromvol, RWVOL,
3801                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
3802         if (vcode) {
3803             fprintf(STDERR,
3804                     "Could not release lock on the VLDB entry for volume %lu\n",
3805                     (unsigned long)afromvol);
3806             if (!error)
3807                 error = vcode;
3808         }
3809     }
3810
3811     PrintError("", error);
3812
3813     if (fromconn)
3814         rx_DestroyConnection(fromconn);
3815     if (results.manyResults_val)
3816         free(results.manyResults_val);
3817     if (replicas)
3818         free(replicas);
3819     if (toconns)
3820         free(toconns);
3821     if (times)
3822         free(times);
3823     return error;
3824 }
3825
3826
3827 void
3828 dump_sig_handler(int x)
3829 {
3830     fprintf(STDERR, "\nSignal handler: vos dump operation\n");
3831     longjmp(env, 0);
3832 }
3833
3834 /* Dump the volume <afromvol> on <afromserver> and
3835  * <afrompart> to <afilename> starting from <fromdate>.
3836  * DumpFunction does the real work behind the scenes after
3837  * extracting parameters from the rock 
3838  */
3839 int
3840 UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
3841               afs_int32 fromdate, afs_int32(*DumpFunction) (), char *rock,
3842               afs_int32 flags)
3843 {
3844     struct rx_connection *fromconn = (struct rx_connection *)0;
3845     struct rx_call *fromcall = (struct rx_call *)0;
3846     afs_int32 fromtid = 0, rxError = 0, rcode = 0;
3847     afs_int32 code, error = 0, retry = 0;
3848     time_t tmv = fromdate;
3849
3850     if (setjmp(env))
3851         ERROR_EXIT(EPIPE);
3852 #ifndef AFS_NT40_ENV
3853     (void)signal(SIGPIPE, dump_sig_handler);
3854 #endif
3855     (void)signal(SIGINT, dump_sig_handler);
3856
3857     if (!fromdate) {
3858         VEPRINT("Full Dump ...\n");
3859     } else {
3860         VEPRINT1("Incremental Dump (as of %.24s)...\n",
3861                 ctime(&tmv));
3862     }
3863
3864     /* get connections to the servers */
3865     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3866
3867     VEPRINT1("Starting transaction on volume %u...", afromvol);
3868     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3869     EGOTO1(error_exit, code,
3870            "Could not start transaction on the volume %u to be dumped\n",
3871            afromvol);
3872     VEDONE;
3873
3874     fromcall = rx_NewCall(fromconn);
3875
3876     VEPRINT1("Starting volume dump on volume %u...", afromvol);
3877     if (flags & VOLDUMPV2_OMITDIRS) 
3878         code = StartAFSVolDumpV2(fromcall, fromtid, fromdate, flags);
3879     else
3880       retryold:
3881         code = StartAFSVolDump(fromcall, fromtid, fromdate);
3882     EGOTO(error_exit, code, "Could not start the dump process \n");
3883     VEDONE;
3884
3885     VEPRINT1("Dumping volume %u...", afromvol);
3886     code = DumpFunction(fromcall, rock);
3887     if (code == RXGEN_OPCODE) 
3888         goto error_exit;
3889     EGOTO(error_exit, code, "Error while dumping volume \n");
3890     VEDONE;
3891
3892   error_exit:
3893     if (fromcall) {
3894         code = rx_EndCall(fromcall, rxError);
3895         if (code && code != RXGEN_OPCODE) 
3896             fprintf(STDERR, "Error in rx_EndCall\n");
3897         if (code && !error)
3898             error = code;
3899     }
3900     if (fromtid) {
3901         VEPRINT1("Ending transaction on volume %u...", afromvol);
3902         code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3903         if (code || rcode) {
3904             fprintf(STDERR, "Could not end transaction on the volume %lu\n",
3905                     (unsigned long)afromvol);
3906             if (!error)
3907                 error = (code ? code : rcode);
3908         }
3909         VEDONE;
3910     }
3911     if (fromconn)
3912         rx_DestroyConnection(fromconn);
3913
3914     if (retry)
3915         goto retryold;
3916     if (error != RXGEN_OPCODE)
3917         PrintError("", error);
3918     return (error);
3919 }
3920
3921 /* Clone the volume <afromvol> on <afromserver> and
3922  * <afrompart>, and then dump the clone volume to 
3923  * <afilename> starting from <fromdate>.
3924  * DumpFunction does the real work behind the scenes after
3925  * extracting parameters from the rock 
3926  */
3927 int
3928 UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver,
3929                     afs_int32 afrompart, afs_int32 fromdate,
3930                     afs_int32(*DumpFunction) (), char *rock, afs_int32 flags)
3931 {
3932     struct rx_connection *fromconn = (struct rx_connection *)0;
3933     struct rx_call *fromcall = (struct rx_call *)0;
3934     afs_int32 fromtid = 0, rxError = 0, rcode = 0;
3935     afs_int32 clonetid = 0;
3936     afs_int32 code = 0, vcode = 0, error = 0;
3937     afs_int32 clonevol = 0;
3938     char vname[64];
3939     time_t tmv = fromdate;
3940
3941     if (setjmp(env))
3942         ERROR_EXIT(EPIPE);
3943 #ifndef AFS_NT40_ENV
3944     (void)signal(SIGPIPE, dump_sig_handler);
3945 #endif
3946     (void)signal(SIGINT, dump_sig_handler);
3947
3948     if (!fromdate) {
3949         VEPRINT("Full Dump ...\n");
3950     } else {
3951         VEPRINT1("Incremental Dump (as of %.24s)...\n",
3952                 ctime(&tmv));
3953     }
3954
3955     /* get connections to the servers */
3956     fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3957
3958     VEPRINT1("Starting transaction on volume %u...", afromvol);
3959     code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
3960     EGOTO1(error_exit, code,
3961            "Could not start transaction on the volume %u to be dumped\n",
3962            afromvol);
3963     VEDONE;
3964
3965     /* Get a clone id */
3966     VEPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
3967     code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &clonevol);
3968     EGOTO1(error_exit, code,
3969            "Could not get an ID for the clone of volume %u from the VLDB\n",
3970            afromvol);
3971     VEDONE;
3972
3973     /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
3974     VEPRINT2("Cloning source volume %u to clone volume %u...", afromvol,
3975             clonevol);
3976     strcpy(vname, "dump-clone-temp");
3977     code =
3978         AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
3979     EGOTO1(error_exit, code, "Failed to clone the source volume %u\n",
3980            afromvol);
3981     VEDONE;
3982
3983     VEPRINT1("Ending the transaction on the volume %u ...", afromvol);
3984     rcode = 0;
3985     code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3986     fromtid = 0;
3987     if (!code)
3988         code = rcode;
3989     EGOTO1(error_exit, code,
3990            "Failed to end the transaction on the volume %u\n", afromvol);
3991     VEDONE;
3992
3993
3994     VEPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
3995     code =
3996         AFSVolTransCreate(fromconn, clonevol, afrompart, ITOffline,
3997                           &clonetid);
3998     EGOTO1(error_exit, code,
3999            "Failed to start a transaction on the cloned volume%u\n",
4000            clonevol);
4001     VEDONE;
4002
4003     VEPRINT1("Setting flags on cloned volume %u ...", clonevol);
4004     code = AFSVolSetFlags(fromconn, clonetid, VTDeleteOnSalvage | VTOutOfService);      /*redundant */
4005     EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n",
4006            clonevol);
4007     VEDONE;
4008
4009
4010     fromcall = rx_NewCall(fromconn);
4011
4012     VEPRINT1("Starting volume dump from cloned volume %u...", clonevol);
4013     if (flags & VOLDUMPV2_OMITDIRS) 
4014         code = StartAFSVolDumpV2(fromcall, clonetid, fromdate, flags);
4015     else
4016         code = StartAFSVolDump(fromcall, clonetid, fromdate);
4017     EGOTO(error_exit, code, "Could not start the dump process \n");
4018     VEDONE;
4019
4020     VEPRINT1("Dumping volume %u...", afromvol);
4021     code = DumpFunction(fromcall, rock);
4022     EGOTO(error_exit, code, "Error while dumping volume \n");
4023     VEDONE;
4024
4025   error_exit:
4026     /* now delete the clone */
4027     VEPRINT1("Deleting the cloned volume %u ...", clonevol);
4028     code = AFSVolDeleteVolume(fromconn, clonetid);
4029     if (code) {
4030         fprintf(STDERR, "Failed to delete the cloned volume %lu\n",
4031                 (unsigned long)clonevol);
4032     } else {
4033         VEDONE;
4034     }
4035
4036     if (fromcall) {
4037         code = rx_EndCall(fromcall, rxError);
4038         if (code) {
4039             fprintf(STDERR, "Error in rx_EndCall\n");
4040             if (!error)
4041                 error = code;
4042         }
4043     }
4044     if (clonetid) {
4045         VEPRINT1("Ending transaction on cloned volume %u...", clonevol);
4046         code = AFSVolEndTrans(fromconn, clonetid, &rcode);
4047         if (code || rcode) {
4048             fprintf(STDERR,
4049                     "Could not end transaction on the cloned volume %lu\n",
4050                     (unsigned long)clonevol);
4051             if (!error)
4052                 error = (code ? code : rcode);
4053         }
4054         VEDONE;
4055     }
4056     if (fromconn)
4057         rx_DestroyConnection(fromconn);
4058
4059     PrintError("", error);
4060     return (error);
4061 }
4062
4063
4064
4065 /*
4066  * Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
4067  * the dump file <afilename>. WriteData does all the real work
4068  * after extracting params from the rock 
4069  */
4070 int
4071 UV_RestoreVolume2(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
4072                   afs_int32 toparentid, char tovolname[], int flags,
4073                   afs_int32(*WriteData) (), char *rock)
4074 {
4075     struct rx_connection *toconn, *tempconn;
4076     struct rx_call *tocall;
4077     afs_int32 totid, code, rcode, vcode, terror = 0;
4078     afs_int32 rxError = 0;
4079     struct volser_status tstatus;
4080     struct volintInfo vinfo;
4081     char partName[10];
4082     char tovolreal[VOLSER_OLDMAXVOLNAME];
4083     afs_int32 pvolid, pparentid;
4084     afs_int32 temptid;
4085     int success;
4086     struct nvldbentry entry, storeEntry;
4087     afs_int32 error;
4088     int islocked;
4089     struct restoreCookie cookie;
4090     int reuseID;
4091     afs_int32 volflag, voltype, volsertype;
4092     afs_int32 oldCreateDate, oldUpdateDate, newCreateDate, newUpdateDate;
4093     int index, same, errcode;
4094     char apartName[10];
4095
4096
4097     memset(&cookie, 0, sizeof(cookie));
4098     islocked = 0;
4099     success = 0;
4100     error = 0;
4101     reuseID = 1;
4102     tocall = (struct rx_call *)0;
4103     toconn = (struct rx_connection *)0;
4104     tempconn = (struct rx_connection *)0;
4105     totid = 0;
4106     temptid = 0;
4107
4108     if (flags & RV_RDONLY) {
4109         voltype = ROVOL;
4110         volsertype = volser_RO;
4111     } else {
4112         voltype = RWVOL;
4113         volsertype = volser_RW;
4114     }
4115
4116     pvolid = tovolid;
4117     pparentid = toparentid;
4118     toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
4119     if (pvolid == 0) {          /*alot a new id if needed */
4120         vcode = VLDB_GetEntryByName(tovolname, &entry);
4121         if (vcode == VL_NOENT) {
4122             vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &pvolid);
4123             if (vcode) {
4124                 fprintf(STDERR, "Could not get an Id for the volume %s\n",
4125                         tovolname);
4126                 error = vcode;
4127                 goto refail;
4128             }
4129             reuseID = 0;
4130         } else if (flags & RV_RDONLY) {
4131             if (entry.flags & RW_EXISTS) {
4132                 fprintf(STDERR,
4133                         "Entry for ReadWrite volume %s already exists!\n",
4134                         entry.name);
4135                 error = VOLSERBADOP;
4136                 goto refail;
4137             }
4138             if (!entry.volumeId[ROVOL]) {
4139                 fprintf(STDERR,
4140                         "Existing entry for volume %s has no ReadOnly ID\n",
4141                         tovolname);
4142                 error = VOLSERBADOP;
4143                 goto refail;
4144             }
4145             pvolid = entry.volumeId[ROVOL];
4146             pparentid = entry.volumeId[RWVOL];
4147         } else {
4148             pvolid = entry.volumeId[RWVOL];
4149             pparentid = entry.volumeId[RWVOL];
4150         }
4151     }
4152     if (!pparentid) pparentid = pvolid;
4153     /* at this point we have a volume id to use/reuse for the volume to be restored */
4154     strncpy(tovolreal, tovolname, VOLSER_OLDMAXVOLNAME);
4155             
4156     if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
4157         EGOTO1(refail, VOLSERBADOP,
4158                "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",
4159                tovolname);
4160     } else {
4161         if ((pparentid != pvolid) && (flags & RV_RDONLY)) {
4162             if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 10)) {
4163                 EGOTO1(refail, VOLSERBADOP,
4164                        "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n", tovolname);
4165             }
4166             snprintf(tovolreal, VOLSER_OLDMAXVOLNAME, "%s.readonly", tovolname);
4167         }
4168     }
4169     MapPartIdIntoName(topart, partName);
4170     fprintf(STDOUT, "Restoring volume %s Id %lu on server %s partition %s ..",
4171             tovolreal, (unsigned long)pvolid,
4172             hostutil_GetNameByINet(toserver), partName);
4173     fflush(STDOUT);
4174     code =
4175         AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid, &pvolid,
4176                            &totid);
4177     if (code) {
4178         if (flags & RV_FULLRST) {       /* full restore: delete then create anew */
4179             VPRINT1("Deleting the previous volume %u ...", pvolid);
4180
4181             code =
4182                 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
4183             EGOTO1(refail, code, "Failed to start transaction on %u\n",
4184                    pvolid);
4185
4186             code = AFSVolGetStatus(toconn, totid, &tstatus);
4187             EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
4188                    pvolid);
4189
4190             oldCreateDate = tstatus.creationDate;
4191             oldUpdateDate = tstatus.updateDate;
4192
4193             code =
4194                 AFSVolSetFlags(toconn, totid,
4195                                VTDeleteOnSalvage | VTOutOfService);
4196             EGOTO1(refail, code, "Could not set flags on volume %u \n",
4197                    pvolid);
4198
4199             code = AFSVolDeleteVolume(toconn, totid);
4200             EGOTO1(refail, code, "Could not delete volume %u\n", pvolid);
4201
4202             code = AFSVolEndTrans(toconn, totid, &rcode);
4203             totid = 0;
4204             if (!code)
4205                 code = rcode;
4206             EGOTO1(refail, code, "Could not end transaction on %u\n", pvolid);
4207
4208             VDONE;
4209
4210             code =
4211                 AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid,
4212                                    &pvolid, &totid);
4213             EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
4214         } else {
4215             code =
4216                 AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
4217             EGOTO1(refail, code, "Failed to start transaction on %u\n",
4218                    pvolid);
4219
4220             code = AFSVolGetStatus(toconn, totid, &tstatus);
4221             EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
4222                    pvolid);
4223
4224             oldCreateDate = tstatus.creationDate;
4225             oldUpdateDate = tstatus.updateDate;
4226         }
4227     } else {
4228         oldCreateDate = 0;
4229         oldUpdateDate = 0;
4230     }
4231
4232     cookie.parent = pparentid;
4233     cookie.type = voltype;
4234     cookie.clone = 0;
4235     strncpy(cookie.name, tovolreal, VOLSER_OLDMAXVOLNAME);
4236
4237     tocall = rx_NewCall(toconn);
4238     terror = StartAFSVolRestore(tocall, totid, 1, &cookie);
4239     if (terror) {
4240         fprintf(STDERR, "Volume restore Failed \n");
4241         error = terror;
4242         goto refail;
4243     }
4244     code = WriteData(tocall, rock);
4245     if (code) {
4246         fprintf(STDERR, "Could not transmit data\n");
4247         error = code;
4248         goto refail;
4249     }
4250     terror = rx_EndCall(tocall, rxError);
4251     tocall = (struct rx_call *)0;
4252     if (terror) {
4253         fprintf(STDERR, "rx_EndCall Failed \n");
4254         error = terror;
4255         goto refail;
4256     }
4257     code = AFSVolGetStatus(toconn, totid, &tstatus);
4258     if (code) {
4259         fprintf(STDERR,
4260                 "Could not get status information about the volume %lu\n",
4261                 (unsigned long)pvolid);
4262         error = code;
4263         goto refail;
4264     }
4265     code = AFSVolSetIdsTypes(toconn, totid, tovolreal, voltype, pparentid, 0, 0);
4266     if (code) {
4267         fprintf(STDERR, "Could not set the right type and ID on %lu\n",
4268                 (unsigned long)pvolid);
4269         error = code;
4270         goto refail;
4271     }
4272
4273     if (flags & RV_CRDUMP)
4274         newCreateDate = tstatus.creationDate;
4275     else if (flags & RV_CRKEEP && oldCreateDate != 0)
4276         newCreateDate = oldCreateDate;
4277     else
4278         newCreateDate = time(0);
4279     if (flags & RV_LUDUMP)
4280         newUpdateDate = tstatus.updateDate;
4281     else if (flags & RV_LUKEEP)
4282         newUpdateDate = oldUpdateDate;
4283     else
4284         newUpdateDate = time(0);
4285     code = AFSVolSetDate(toconn,totid, newCreateDate);
4286     if (code) {
4287         fprintf(STDERR, "Could not set the 'creation' date on %u\n", pvolid);
4288         error = code;
4289         goto refail;
4290     }
4291
4292     init_volintInfo(&vinfo);
4293     vinfo.creationDate = newCreateDate;
4294     vinfo.updateDate = newUpdateDate;
4295     code = AFSVolSetInfo(toconn, totid, &vinfo);
4296     if (code) {
4297         fprintf(STDERR, "Could not set the 'last updated' date on %u\n",
4298                 pvolid);
4299         error = code;
4300         goto refail;
4301     }
4302
4303     volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0);      /* off or on-line */
4304     code = AFSVolSetFlags(toconn, totid, volflag);
4305     if (code) {
4306         fprintf(STDERR, "Could not mark %lu online\n", (unsigned long)pvolid);
4307         error = code;
4308         goto refail;
4309     }
4310
4311 /* It isn't handled right in refail */
4312     code = AFSVolEndTrans(toconn, totid, &rcode);
4313     totid = 0;
4314     if (!code)
4315         code = rcode;
4316     if (code) {
4317         fprintf(STDERR, "Could not end transaction on %lu\n",
4318                 (unsigned long)pvolid);
4319         error = code;
4320         goto refail;
4321     }
4322
4323     success = 1;
4324     fprintf(STDOUT, " done\n");
4325     fflush(STDOUT);
4326     if (success && (!reuseID || (flags & RV_FULLRST))) {
4327         /* Volume was restored on the file server, update the 
4328          * VLDB to reflect the change.
4329          */
4330         vcode = VLDB_GetEntryByID(pvolid, voltype, &entry);
4331         if (vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
4332             fprintf(STDERR,
4333                     "Could not fetch the entry for volume number %lu from VLDB \n",
4334                     (unsigned long)pvolid);
4335             error = vcode;
4336             goto refail;
4337         }
4338         if (!vcode)
4339             MapHostToNetwork(&entry);
4340         if (vcode == VL_NOENT) {        /* it doesnot exist already */
4341             /*make the vldb return this indication specifically */
4342             VPRINT("------- Creating a new VLDB entry ------- \n");
4343             strcpy(entry.name, tovolname);
4344             entry.nServers = 1;
4345             entry.serverNumber[0] = toserver;   /*should be indirect */
4346             entry.serverPartition[0] = topart;
4347             entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
4348             entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
4349             if (flags & RV_RDONLY)
4350                 entry.volumeId[ROVOL] = pvolid;
4351             else if (tstatus.cloneID != 0) {
4352                 entry.volumeId[ROVOL] = tstatus.cloneID;        /*this should come from status info on the volume if non zero */
4353             } else
4354                 entry.volumeId[ROVOL] = INVALID_BID;
4355             entry.volumeId[RWVOL] = pparentid;
4356             entry.cloneId = 0;
4357             if (tstatus.backupID != 0) {
4358                 entry.volumeId[BACKVOL] = tstatus.backupID;
4359                 /*this should come from status info on the volume if non zero */
4360             } else
4361                 entry.volumeId[BACKVOL] = INVALID_BID;
4362             MapNetworkToHost(&entry, &storeEntry);
4363             vcode = VLDB_CreateEntry(&storeEntry);
4364             if (vcode) {
4365                 fprintf(STDERR,
4366                         "Could not create the VLDB entry for volume number %lu  \n",
4367                         (unsigned long)pvolid);
4368                 error = vcode;
4369                 goto refail;
4370             }
4371             islocked = 0;
4372             if (verbose)
4373                 EnumerateEntry(&entry);
4374         } else {                /*update the existing entry */
4375             if (verbose) {
4376                 fprintf(STDOUT, "Updating the existing VLDB entry\n");
4377                 fprintf(STDOUT, "------- Old entry -------\n");
4378                 EnumerateEntry(&entry);
4379                 fprintf(STDOUT, "------- New entry -------\n");
4380             }
4381             vcode =
4382                 ubik_VL_SetLock(cstruct, 0, pvolid, voltype,
4383                           VLOP_RESTORE);
4384             if (vcode) {
4385                 fprintf(STDERR,
4386                         "Could not lock the entry for volume number %lu \n",
4387                         (unsigned long)pvolid);
4388                 error = vcode;
4389                 goto refail;
4390             }
4391             islocked = 1;
4392             strcpy(entry.name, tovolname);
4393
4394             /* Update the vlentry with the new information */
4395             if (flags & RV_RDONLY)
4396                 index = Lp_ROMatch(toserver, topart, &entry) - 1;
4397             else
4398                 index = Lp_GetRwIndex(&entry);
4399             if (index == -1) {
4400                 /* Add the new site for the volume being restored */
4401                 entry.serverNumber[entry.nServers] = toserver;
4402                 entry.serverPartition[entry.nServers] = topart;
4403                 entry.serverFlags[entry.nServers] =
4404                     (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
4405                 entry.nServers++;
4406             } else {
4407                 /* This volume should be deleted on the old site
4408                  * if its different from new site.
4409                  */
4410                 same =
4411                     VLDB_IsSameAddrs(toserver, entry.serverNumber[index],
4412                                      &errcode);
4413                 if (errcode)
4414                     EPRINT2(errcode,
4415                             "Failed to get info about server's %d address(es) from vlserver (err=%d)\n",
4416                             toserver, errcode);
4417                 if ((!errcode && !same)
4418                     || (entry.serverPartition[index] != topart)) {
4419                     if (flags & RV_NODEL) {
4420                         VPRINT2
4421                             ("Not deleting the previous volume %u on server %s, ...",
4422                              pvolid,
4423                              hostutil_GetNameByINet(entry.serverNumber[index]));
4424                     } else {
4425                         tempconn =
4426                             UV_Bind(entry.serverNumber[index],
4427                                     AFSCONF_VOLUMEPORT);
4428                         
4429                         MapPartIdIntoName(entry.serverPartition[index],
4430                                           apartName);
4431                         VPRINT3
4432                             ("Deleting the previous volume %u on server %s, partition %s ...",
4433                              pvolid,
4434                              hostutil_GetNameByINet(entry.serverNumber[index]),
4435                              apartName);
4436                         code =
4437                             AFSVolTransCreate(tempconn, pvolid,
4438                                               entry.serverPartition[index],
4439                                               ITOffline, &temptid);
4440                         if (!code) {
4441                             code =
4442                                 AFSVolSetFlags(tempconn, temptid,
4443                                                VTDeleteOnSalvage |
4444                                                VTOutOfService);
4445                             if (code) {
4446                                 fprintf(STDERR,
4447                                         "Could not set flags on volume %lu on the older site\n",
4448                                         (unsigned long)pvolid);
4449                                 error = code;
4450                                 goto refail;
4451                             }
4452                             code = AFSVolDeleteVolume(tempconn, temptid);
4453                             if (code) {
4454                                 fprintf(STDERR,
4455                                         "Could not delete volume %lu on the older site\n",
4456                                         (unsigned long)pvolid);
4457                                 error = code;
4458                                 goto refail;
4459                             }
4460                             code = AFSVolEndTrans(tempconn, temptid, &rcode);
4461                             temptid = 0;
4462                             if (!code)
4463                                 code = rcode;
4464                             if (code) {
4465                                 fprintf(STDERR,
4466                                         "Could not end transaction on volume %lu on the older site\n",
4467                                         (unsigned long)pvolid);
4468                                 error = code;
4469                                 goto refail;
4470                             }
4471                             VDONE;
4472                             MapPartIdIntoName(entry.serverPartition[index],
4473                                               partName);
4474                         }
4475                     }
4476                 }
4477                 entry.serverNumber[index] = toserver;
4478                 entry.serverPartition[index] = topart;
4479             }
4480
4481             entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
4482             MapNetworkToHost(&entry, &storeEntry);
4483             vcode =
4484                 VLDB_ReplaceEntry(pvolid, voltype, &storeEntry,
4485                                   LOCKREL_OPCODE | LOCKREL_AFSID |
4486                                   LOCKREL_TIMESTAMP);
4487             if (vcode) {
4488                 fprintf(STDERR,
4489                         "Could not update the entry for volume number %lu  \n",
4490                         (unsigned long)pvolid);
4491                 error = vcode;
4492                 goto refail;
4493             }
4494             islocked = 0;
4495             if (verbose)
4496                 EnumerateEntry(&entry);
4497         }
4498
4499
4500     }
4501   refail:
4502     if (tocall) {
4503         code = rx_EndCall(tocall, rxError);
4504         if (!error)
4505             error = code;
4506     }
4507     if (islocked) {
4508         vcode =
4509             ubik_VL_ReleaseLock(cstruct, 0, pvolid, voltype,
4510                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4511         if (vcode) {
4512             fprintf(STDERR,
4513                     "Could not release lock on the VLDB entry for the volume %lu\n",
4514                     (unsigned long)pvolid);
4515             if (!error)
4516                 error = vcode;
4517         }
4518     }
4519     if (totid) {
4520         code = AFSVolEndTrans(toconn, totid, &rcode);
4521         if (!code)
4522             code = rcode;
4523         if (code) {
4524             fprintf(STDERR, "Could not end transaction on the volume %lu \n",
4525                     (unsigned long)pvolid);
4526             if (!error)
4527                 error = code;
4528         }
4529     }
4530     if (temptid) {
4531         code = AFSVolEndTrans(toconn, temptid, &rcode);
4532         if (!code)
4533             code = rcode;
4534         if (code) {
4535             fprintf(STDERR, "Could not end transaction on the volume %lu \n",
4536                     (unsigned long)pvolid);
4537             if (!error)
4538                 error = code;
4539         }
4540     }
4541     if (tempconn)
4542         rx_DestroyConnection(tempconn);
4543     if (toconn)
4544         rx_DestroyConnection(toconn);
4545     PrintError("", error);
4546     return error;
4547 }
4548
4549 int
4550 UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
4551                  char tovolname[], int flags, afs_int32(*WriteData) (),
4552                  char *rock)
4553 {
4554     return UV_RestoreVolume2(toserver, topart, tovolid, 0, tovolname, flags,
4555                              WriteData, rock);
4556 }
4557
4558
4559 /*unlocks the vldb entry associated with <volid> */
4560 int
4561 UV_LockRelease(afs_int32 volid)
4562 {
4563
4564
4565     afs_int32 vcode;
4566
4567     VPRINT("Binding to the VLDB server\n");
4568     vcode =
4569         ubik_VL_ReleaseLock(cstruct, 0, volid, -1,
4570                   LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4571     if (vcode) {
4572         fprintf(STDERR,
4573                 "Could not unlock the entry for volume number %lu in VLDB \n",
4574                 (unsigned long)volid);
4575         PrintError("", vcode);
4576         return (vcode);
4577     }
4578     VPRINT("VLDB updated\n");
4579     return 0;
4580
4581 }
4582
4583 /*adds <server> and <part> as a readonly replication site for <volid>
4584 *in vldb */
4585 int
4586 UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid, afs_int32 valid)
4587 {
4588     int j, nro = 0, islocked = 0;
4589     struct nvldbentry entry, storeEntry;
4590     afs_int32 vcode, error = 0;
4591     char apartName[10];
4592
4593     error = ubik_VL_SetLock(cstruct, 0, volid, RWVOL, VLOP_ADDSITE);
4594     if (error) {
4595         fprintf(STDERR,
4596                 " Could not lock the VLDB entry for the volume %lu \n",
4597                 (unsigned long)volid);
4598         goto asfail;
4599     }
4600     islocked = 1;
4601
4602     error = VLDB_GetEntryByID(volid, RWVOL, &entry);
4603     if (error) {
4604         fprintf(STDERR,
4605                 "Could not fetch the VLDB entry for volume number %lu  \n",
4606                 (unsigned long)volid);
4607         goto asfail;
4608
4609     }
4610     if (!ISNAMEVALID(entry.name)) {
4611         fprintf(STDERR,
4612                 "Volume name %s is too long, rename before adding site\n",
4613                 entry.name);
4614         error = VOLSERBADOP;
4615         goto asfail;
4616     }
4617     MapHostToNetwork(&entry);
4618
4619     /* See if it's too many entries */
4620     if (entry.nServers >= NMAXNSERVERS) {
4621         fprintf(STDERR, "Total number of entries will exceed %u\n",
4622                 NMAXNSERVERS);
4623         error = VOLSERBADOP;
4624         goto asfail;
4625     }
4626
4627     /* See if it's on the same server */
4628     for (j = 0; j < entry.nServers; j++) {
4629         if (entry.serverFlags[j] & ITSROVOL) {
4630             nro++;
4631             if (VLDB_IsSameAddrs(server, entry.serverNumber[j], &error)) {
4632                 if (error) {
4633                     fprintf(STDERR,
4634                             "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
4635                             server, error);
4636                 } else {
4637                     MapPartIdIntoName(entry.serverPartition[j], apartName);
4638                     fprintf(STDERR,
4639                             "RO already exists on partition %s. Multiple ROs on a single server aren't allowed\n",
4640                             apartName);
4641                     error = VOLSERBADOP;
4642                 }
4643                 goto asfail;
4644             }
4645         }
4646     }
4647
4648     /* See if it's too many RO sites - leave one for the RW */
4649     if (nro >= NMAXNSERVERS - 1) {
4650         fprintf(STDERR, "Total number of sites will exceed %u\n",
4651                 NMAXNSERVERS - 1);
4652         error = VOLSERBADOP;
4653         goto asfail;
4654     }
4655
4656     VPRINT("Adding a new site ...");
4657     entry.serverNumber[entry.nServers] = server;
4658     entry.serverPartition[entry.nServers] = part;
4659     if (!valid) {
4660         entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
4661     } else {
4662         entry.serverFlags[entry.nServers] = (ITSROVOL);
4663     }
4664     entry.nServers++;
4665
4666     MapNetworkToHost(&entry, &storeEntry);
4667     error =
4668         VLDB_ReplaceEntry(volid, RWVOL, &storeEntry,
4669                           LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4670     if (error) {
4671         fprintf(STDERR, "Could not update entry for volume %lu \n",
4672                 (unsigned long)volid);
4673         goto asfail;
4674     }
4675     islocked = 0;
4676     VDONE;
4677
4678   asfail:
4679     if (islocked) {
4680         vcode =
4681             ubik_VL_ReleaseLock(cstruct, 0, volid, RWVOL,
4682                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4683         if (vcode) {
4684             fprintf(STDERR,
4685                     "Could not release lock on volume entry for %lu \n",
4686                     (unsigned long)volid);
4687             PrintError("", vcode);
4688         }
4689     }
4690
4691     PrintError("", error);
4692     return error;
4693 }
4694
4695 /*removes <server> <part> as read only site for <volid> from the vldb */
4696 int
4697 UV_RemoveSite(afs_int32 server, afs_int32 part, afs_int32 volid)
4698 {
4699     afs_int32 vcode;
4700     struct nvldbentry entry, storeEntry;
4701     int islocked;
4702
4703     vcode = ubik_VL_SetLock(cstruct, 0, volid, RWVOL, VLOP_ADDSITE);
4704     if (vcode) {
4705         fprintf(STDERR, " Could not lock the VLDB entry for volume %lu \n",
4706                 (unsigned long)volid);
4707         PrintError("", vcode);
4708         return (vcode);
4709     }
4710     islocked = 1;
4711     vcode = VLDB_GetEntryByID(volid, RWVOL, &entry);
4712     if (vcode) {
4713         fprintf(STDERR,
4714                 "Could not fetch the entry for volume number %lu from VLDB \n",
4715                 (unsigned long)volid);
4716         PrintError("", vcode);
4717         return (vcode);
4718     }
4719     MapHostToNetwork(&entry);
4720     if (!Lp_ROMatch(server, part, &entry)) {
4721         /*this site doesnot exist  */
4722         fprintf(STDERR, "This site is not a replication site \n");
4723         vcode =
4724             ubik_VL_ReleaseLock(cstruct, 0, volid, RWVOL,
4725                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4726         if (vcode) {
4727             fprintf(STDERR, "Could not update entry for volume %lu \n",
4728                     (unsigned long)volid);
4729             PrintError("", vcode);
4730             ubik_VL_ReleaseLock(cstruct, 0, volid, RWVOL,
4731                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4732             return (vcode);
4733         }
4734         return VOLSERBADOP;
4735     } else {                    /*remove the rep site */
4736         Lp_SetROValue(&entry, server, part, 0, 0);
4737         entry.nServers--;
4738         if ((entry.nServers == 1) && (entry.flags & RW_EXISTS))
4739             entry.flags &= ~RO_EXISTS;
4740         if (entry.nServers < 1) {       /*this is the last ref */
4741             VPRINT1("Deleting the VLDB entry for %u ...", volid);
4742             fflush(STDOUT);
4743             vcode = ubik_VL_DeleteEntry(cstruct, 0, volid, ROVOL);
4744             if (vcode) {
4745                 fprintf(STDERR,
4746                         "Could not delete VLDB entry for volume %lu \n",
4747                         (unsigned long)volid);
4748                 PrintError("", vcode);
4749                 return (vcode);
4750             }
4751             VDONE;
4752         }
4753         MapNetworkToHost(&entry, &storeEntry);
4754         fprintf(STDOUT, "Deleting the replication site for volume %lu ...",
4755                 (unsigned long)volid);
4756         fflush(STDOUT);
4757         vcode =
4758             VLDB_ReplaceEntry(volid, RWVOL, &storeEntry,
4759                               LOCKREL_OPCODE | LOCKREL_AFSID |
4760                               LOCKREL_TIMESTAMP);
4761         if (vcode) {
4762             fprintf(STDERR,
4763                     "Could not release lock on volume entry for %lu \n",
4764                     (unsigned long)volid);
4765             PrintError("", vcode);
4766             ubik_VL_ReleaseLock(cstruct, 0, volid, RWVOL,
4767                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4768             return (vcode);
4769         }
4770         VDONE;
4771     }
4772     return 0;
4773 }
4774
4775 /*sets <server> <part> as read/write site for <volid> in the vldb */
4776 int
4777 UV_ChangeLocation(afs_int32 server, afs_int32 part, afs_int32 volid)
4778 {
4779     afs_int32 vcode;
4780     struct nvldbentry entry, storeEntry;
4781     int index;
4782
4783     vcode = ubik_VL_SetLock(cstruct, 0, volid, RWVOL, VLOP_ADDSITE);
4784     if (vcode) {
4785         fprintf(STDERR, " Could not lock the VLDB entry for volume %lu \n",
4786                 (unsigned long)volid);
4787         PrintError("", vcode);
4788         return (vcode);
4789     }
4790     vcode = VLDB_GetEntryByID(volid, RWVOL, &entry);
4791     if (vcode) {
4792         fprintf(STDERR,
4793                 "Could not fetch the entry for volume number %lu from VLDB \n",
4794                 (unsigned long)volid);
4795         PrintError("", vcode);
4796         return (vcode);
4797     }
4798     MapHostToNetwork(&entry);
4799     index = Lp_GetRwIndex(&entry);
4800     if (index < 0) {
4801         /* no RW site exists  */
4802         fprintf(STDERR, "No existing RW site for volume %lu",
4803                 (unsigned long)volid);
4804         vcode =
4805             ubik_VL_ReleaseLock(cstruct, 0, volid, RWVOL,
4806                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4807         if (vcode) {
4808             fprintf(STDERR,
4809                     "Could not release lock on entry for volume %lu \n",
4810                     (unsigned long)volid);
4811             PrintError("", vcode);
4812             return (vcode);
4813         }
4814         return VOLSERBADOP;
4815     } else {                    /* change the RW site */
4816         entry.serverNumber[index] = server;
4817         entry.serverPartition[index] = part;
4818         MapNetworkToHost(&entry, &storeEntry);
4819         vcode =
4820             VLDB_ReplaceEntry(volid, RWVOL, &storeEntry,
4821                               LOCKREL_OPCODE | LOCKREL_AFSID |
4822                               LOCKREL_TIMESTAMP);
4823         if (vcode) {
4824             fprintf(STDERR, "Could not update entry for volume %lu \n",
4825                     (unsigned long)volid);
4826             PrintError("", vcode);
4827             ubik_VL_ReleaseLock(cstruct, 0, volid, RWVOL,
4828                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
4829             return (vcode);
4830         }
4831         VDONE;
4832     }
4833     return 0;
4834 }
4835
4836 /*list all the partitions on <aserver> */
4837 int
4838 UV_ListPartitions(afs_int32 aserver, struct partList *ptrPartList,
4839                   afs_int32 * cntp)
4840 {
4841     struct rx_connection *aconn;
4842     struct pIDs partIds;
4843     struct partEntries partEnts;
4844     register int i, j = 0, code;
4845
4846     *cntp = 0;
4847     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4848
4849     partEnts.partEntries_len = 0;
4850     partEnts.partEntries_val = NULL;
4851     code = AFSVolXListPartitions(aconn, &partEnts);     /* this is available only on new servers */
4852     if (code == RXGEN_OPCODE) {
4853         for (i = 0; i < 26; i++)        /* try old interface */
4854             partIds.partIds[i] = -1;
4855         code = AFSVolListPartitions(aconn, &partIds);
4856         if (!code) {
4857             for (i = 0; i < 26; i++) {
4858                 if ((partIds.partIds[i]) != -1) {
4859                     ptrPartList->partId[j] = partIds.partIds[i];
4860                     ptrPartList->partFlags[j] = PARTVALID;
4861                     j++;
4862                 } else
4863                     ptrPartList->partFlags[i] = 0;
4864             }
4865             *cntp = j;
4866         }
4867     } else if (!code) {
4868         *cntp = partEnts.partEntries_len;
4869         if (*cntp > VOLMAXPARTS) {
4870             fprintf(STDERR,
4871                     "Warning: number of partitions on the server too high %d (process only %d)\n",
4872                     *cntp, VOLMAXPARTS);
4873             *cntp = VOLMAXPARTS;
4874         }
4875         for (i = 0; i < *cntp; i++) {
4876             ptrPartList->partId[i] = partEnts.partEntries_val[i];
4877             ptrPartList->partFlags[i] = PARTVALID;
4878         }
4879         free(partEnts.partEntries_val);
4880     }
4881
4882    /* out: */
4883     if (code)
4884         fprintf(STDERR,
4885                 "Could not fetch the list of partitions from the server\n");
4886     PrintError("", code);
4887     if (aconn)
4888         rx_DestroyConnection(aconn);
4889     return code;
4890 }
4891
4892
4893 /*zap the list of volumes specified by volPtrArray (the volCloneId field).
4894  This is used by the backup system */
4895 int
4896 UV_ZapVolumeClones(afs_int32 aserver, afs_int32 apart,
4897                    struct volDescription *volPtr, afs_int32 arraySize)
4898 {
4899     struct rx_connection *aconn;
4900     struct volDescription *curPtr;
4901     int curPos;
4902     afs_int32 code = 0;
4903     afs_int32 rcode = 0;
4904     afs_int32 success = 1;
4905     afs_int32 tid;
4906
4907     aconn = (struct rx_connection *)0;
4908     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4909     curPos = 0;
4910     for (curPtr = volPtr; curPos < arraySize; curPtr++) {
4911         if (curPtr->volFlags & CLONEVALID) {
4912             curPtr->volFlags &= ~CLONEZAPPED;
4913             success = 1;
4914             code =
4915                 AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline,
4916                                   &tid);
4917             if (code)
4918                 success = 0;
4919             else {
4920                 code = AFSVolDeleteVolume(aconn, tid);
4921                 if (code)
4922                     success = 0;
4923                 code = AFSVolEndTrans(aconn, tid, &rcode);
4924                 if (code || rcode)
4925                     success = 0;
4926             }
4927             if (success)
4928                 curPtr->volFlags |= CLONEZAPPED;
4929             if (!success)
4930                 fprintf(STDERR, "Could not zap volume %lu\n",
4931                         (unsigned long)curPtr->volCloneId);
4932             if (success)
4933                 VPRINT2("Clone of %s %u deleted\n", curPtr->volName,
4934                         curPtr->volCloneId);
4935             curPos++;
4936             tid = 0;
4937         }
4938     }
4939     if (aconn)
4940         rx_DestroyConnection(aconn);
4941     return 0;
4942 }
4943
4944 /*return a list of clones of the volumes specified by volPtrArray. Used by the 
4945  backup system */
4946 int
4947 UV_GenerateVolumeClones(afs_int32 aserver, afs_int32 apart,
4948                         struct volDescription *volPtr, afs_int32 arraySize)
4949 {
4950     struct rx_connection *aconn;
4951     struct volDescription *curPtr;
4952     int curPos;
4953     afs_int32 code = 0;
4954     afs_int32 rcode = 0;
4955     afs_int32 tid;
4956     int reuseCloneId = 0;
4957     afs_int32 curCloneId = 0;
4958     char cloneName[256];        /*max vol name */
4959
4960     aconn = (struct rx_connection *)0;
4961     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
4962     curPos = 0;
4963     if ((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
4964         reuseCloneId = 1;
4965     else {                      /*get a bunch of id's from vldb */
4966         code =
4967             ubik_VL_GetNewVolumeId(cstruct, 0, arraySize, &curCloneId);
4968         if (code) {
4969             fprintf(STDERR, "Could not get ID's for the clone from VLDB\n");
4970             PrintError("", code);
4971             return code;
4972         }
4973     }
4974
4975     for (curPtr = volPtr; curPos < arraySize; curPtr++) {
4976         if (curPtr->volFlags & ENTRYVALID) {
4977
4978             curPtr->volFlags |= CLONEVALID;
4979             /*make a clone of curParentId and record as curPtr->volCloneId */
4980             code =
4981                 AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline,
4982                                   &tid);
4983             if (code)
4984                 VPRINT2("Clone for volume %s %u failed \n", curPtr->volName,
4985                         curPtr->volId);
4986             if (code) {
4987                 curPtr->volFlags &= ~CLONEVALID;        /*cant clone */
4988                 curPos++;
4989                 continue;
4990             }
4991             if (strlen(curPtr->volName) < (VOLSER_OLDMAXVOLNAME - 9)) {
4992                 strcpy(cloneName, curPtr->volName);
4993                 strcat(cloneName, "-tmpClone-");
4994             } else
4995                 strcpy(cloneName, "-tmpClone");
4996             if (reuseCloneId) {
4997                 curPtr->volCloneId = curCloneId;
4998                 curCloneId++;
4999             }
5000
5001             code =
5002                 AFSVolClone(aconn, tid, 0, readonlyVolume, cloneName,
5003                             &(curPtr->volCloneId));
5004             if (code) {
5005                 curPtr->volFlags &= ~CLONEVALID;
5006                 curPos++;
5007                 fprintf(STDERR, "Could not clone %s due to error %lu\n",
5008                         curPtr->volName, (unsigned long)code);
5009                 code = AFSVolEndTrans(aconn, tid, &rcode);
5010                 if (code)
5011                     fprintf(STDERR, "WARNING: could not end transaction\n");
5012                 continue;
5013             }
5014             VPRINT2("********** Cloned %s temporary %u\n", cloneName,
5015                     curPtr->volCloneId);
5016             code = AFSVolEndTrans(aconn, tid, &rcode);
5017             if (code || rcode) {
5018                 curPtr->volFlags &= ~CLONEVALID;
5019                 curPos++;
5020                 continue;
5021             }
5022
5023             curPos++;
5024         }
5025     }
5026     if (aconn)
5027         rx_DestroyConnection(aconn);
5028     return 0;
5029 }
5030
5031
5032 /*list all the volumes on <aserver> and <apart>. If all = 1, then all the
5033 * relevant fields of the volume are also returned. This is a heavy weight operation.*/
5034 int
5035 UV_ListVolumes(afs_int32 aserver, afs_int32 apart, int all,
5036                struct volintInfo **resultPtr, afs_int32 * size)
5037 {
5038     struct rx_connection *aconn;
5039     afs_int32 code = 0;
5040     volEntries volumeInfo;
5041
5042     code = 0;
5043     *size = 0;
5044     *resultPtr = (volintInfo *) 0;
5045     volumeInfo.volEntries_val = (volintInfo *) 0;       /*this hints the stub to allocate space */
5046     volumeInfo.volEntries_len = 0;
5047
5048     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
5049     code = AFSVolListVolumes(aconn, apart, all, &volumeInfo);
5050     if (code) {
5051         fprintf(STDERR,
5052                 "Could not fetch the list of volumes from the server\n");
5053     } else {
5054         *resultPtr = volumeInfo.volEntries_val;
5055         *size = volumeInfo.volEntries_len;
5056     }
5057
5058     if (aconn)
5059         rx_DestroyConnection(aconn);
5060     PrintError("", code);
5061     return code;
5062 }
5063
5064 /*------------------------------------------------------------------------
5065  * EXPORTED UV_XListVolumes
5066  *
5067  * Description:
5068  *      List the extended information for all the volumes on a particular
5069  *      File Server and partition.  We may either return the volume's ID
5070  *      or all of its extended information.
5071  *
5072  * Arguments:
5073  *      a_serverID         : Address of the File Server for which we want
5074  *                              extended volume info.
5075  *      a_partID           : Partition for which we want the extended
5076  *                              volume info.
5077  *      a_all              : If non-zero, fetch ALL the volume info,
5078  *                              otherwise just the volume ID.
5079  *      a_resultPP         : Ptr to the address of the area containing
5080  *                              the returned volume info.
5081  *      a_numEntsInResultP : Ptr for the value we set for the number of
5082  *                              entries returned.
5083  *
5084  * Returns:
5085  *      0 on success,
5086  *      Otherise, the return value of AFSVolXListVolumes.
5087  *
5088  * Environment:
5089  *      This routine is closely related to UV_ListVolumes, which returns
5090  *      only the standard level of detail on AFS volumes. It is a
5091  *      heavyweight operation, zipping through all the volume entries for
5092  *      a given server/partition.
5093  *
5094  * Side Effects:
5095  *      As advertised.
5096  *------------------------------------------------------------------------*/
5097
5098 int
5099 UV_XListVolumes(afs_int32 a_serverID, afs_int32 a_partID, int a_all,
5100                 struct volintXInfo **a_resultPP,
5101                 afs_int32 * a_numEntsInResultP)
5102 {
5103     struct rx_connection *rxConnP;      /*Ptr to the Rx connection involved */
5104     afs_int32 code;             /*Error code to return */
5105     volXEntries volumeXInfo;    /*Area for returned extended vol info */
5106
5107     /*
5108      * Set up our error code and the area for returned extended volume info.
5109      * We set the val field to a null pointer as a hint for the stub to
5110      * allocate space.
5111      */
5112     code = 0;
5113     *a_numEntsInResultP = 0;
5114     *a_resultPP = (volintXInfo *) 0;
5115     volumeXInfo.volXEntries_val = (volintXInfo *) 0;
5116     volumeXInfo.volXEntries_len = 0;
5117
5118     /*
5119      * Bind to the Volume Server port on the File Server machine in question,
5120      * then go for it.
5121      */
5122     rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
5123     code = AFSVolXListVolumes(rxConnP, a_partID, a_all, &volumeXInfo);
5124     if (code)
5125         fprintf(STDERR, "[UV_XListVolumes] Couldn't fetch volume list\n");
5126     else {
5127         /*
5128          * We got the info; pull out the pointer to where the results lie
5129          * and how many entries are there.
5130          */
5131         *a_resultPP = volumeXInfo.volXEntries_val;
5132         *a_numEntsInResultP = volumeXInfo.volXEntries_len;
5133     }
5134
5135     /*
5136      * If we got an Rx connection, throw it away.
5137      */
5138     if (rxConnP)
5139         rx_DestroyConnection(rxConnP);
5140
5141     PrintError("", code);
5142     return (code);
5143 }                               /*UV_XListVolumes */
5144
5145 /* get all the information about volume <volid> on <aserver> and <apart> */
5146 int
5147 UV_ListOneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 volid,
5148                  struct volintInfo **resultPtr)
5149 {
5150     struct rx_connection *aconn;
5151     afs_int32 code = 0;
5152     volEntries volumeInfo;
5153
5154     code = 0;
5155
5156     *resultPtr = (volintInfo *) 0;
5157     volumeInfo.volEntries_val = (volintInfo *) 0;       /*this hints the stub to allocate space */
5158     volumeInfo.volEntries_len = 0;
5159
5160     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
5161     code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
5162     if (code) {
5163         fprintf(STDERR,
5164                 "Could not fetch the information about volume %lu from the server\n",
5165                 (unsigned long)volid);
5166     } else {
5167         *resultPtr = volumeInfo.volEntries_val;
5168
5169     }
5170
5171     if (aconn)
5172         rx_DestroyConnection(aconn);
5173     PrintError("", code);
5174     return code;
5175 }
5176
5177 /*------------------------------------------------------------------------
5178  * EXPORTED UV_XListOneVolume
5179  *
5180  * Description:
5181  *      List the extended information for a volume on a particular File
5182  *      Server and partition.
5183  *
5184  * Arguments:
5185  *      a_serverID         : Address of the File Server for which we want
5186  *                              extended volume info.
5187  *      a_partID           : Partition for which we want the extended
5188  *                              volume info.
5189  *      a_volID            : Volume ID for which we want the info.
5190  *      a_resultPP         : Ptr to the address of the area containing
5191  *                              the returned volume info.
5192  *
5193  * Returns:
5194  *      0 on success,
5195  *      Otherise, the return value of AFSVolXListOneVolume.
5196  *
5197  * Environment:
5198  *      This routine is closely related to UV_ListOneVolume, which returns
5199  *      only the standard level of detail on the chosen AFS volume.
5200  *
5201  * Side Effects:
5202  *      As advertised.
5203  *------------------------------------------------------------------------*/
5204
5205 int
5206 UV_XListOneVolume(afs_int32 a_serverID, afs_int32 a_partID, afs_int32 a_volID,
5207                   struct volintXInfo **a_resultPP)
5208 {
5209     struct rx_connection *rxConnP;      /*Rx connection to Volume Server */
5210     afs_int32 code;             /*Error code */
5211     volXEntries volumeXInfo;    /*Area for returned info */
5212
5213     /*
5214      * Set up our error code, and the area we're in which we are returning
5215      * the info.  Setting the val field to a null pointer tells the stub
5216      * to allocate space for us.
5217      */
5218     code = 0;
5219     *a_resultPP = (volintXInfo *) 0;
5220     volumeXInfo.volXEntries_val = (volintXInfo *) 0;
5221     volumeXInfo.volXEntries_len = 0;
5222
5223     /*
5224      * Bind to the Volume Server port on the File Server machine in question,
5225      * then go for it.
5226      */
5227     rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
5228     code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
5229     if (code)
5230         fprintf(STDERR,
5231                 "[UV_XListOneVolume] Couldn't fetch the volume information\n");
5232     else
5233         /*
5234          * We got the info; pull out the pointer to where the results lie.
5235          */
5236         *a_resultPP = volumeXInfo.volXEntries_val;
5237
5238     /*
5239      * If we got an Rx connection, throw it away.
5240      */
5241     if (rxConnP)
5242         rx_DestroyConnection(rxConnP);
5243
5244     PrintError("", code);
5245     return code;
5246 }
5247
5248 /* CheckVolume()
5249  *    Given a volume we read from a partition, check if it is 
5250  *    represented in the VLDB correctly.
5251  * 
5252  *    The VLDB is looked up by the RW volume id (not its name).
5253  *    The RW contains the true name of the volume (BK and RO set
5254  *       the name in the VLDB only on creation of the VLDB entry).
5255  *    We want rules strict enough that when we check all volumes
5256  *       on one partition, it does not need to be done again. IE:
5257  *       two volumes on different partitions won't constantly 
5258  *       change a VLDB entry away from what the other set.
5259  *    For RW and BK volumes, we will always check the VLDB to see 
5260  *       if the two exist on the server/partition. May seem redundant,
5261  *       but this is an easy check of the VLDB. IE: if the VLDB entry
5262  *       says the BK exists but no BK volume is there, we will detect
5263  *       this when we check the RW volume.
5264  *    VLDB entries are locked only when a change needs to be done.
5265  *    Output changed to look a lot like the "vos syncserv" otuput.
5266  */
5267 static afs_int32
5268 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver, afs_int32 apart,
5269             afs_int32 * modentry, afs_uint32 * maxvolid)
5270 {
5271     int idx, j;
5272     afs_int32 code, error = 0;
5273     struct nvldbentry entry, storeEntry;
5274     char pname[10];
5275     int pass = 0, islocked = 0, createentry, addvolume, modified, mod, doit = 1;
5276     afs_int32 rwvolid;
5277
5278     if (modentry) {
5279         if (*modentry == 1)
5280             doit = 0;
5281         *modentry = 0;
5282     }
5283     rwvolid =
5284         ((volumeinfo->type ==
5285           RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
5286
5287   retry:
5288     /* Check to see if the VLDB is ok without locking it (pass 1).
5289      * If it will change, then lock the VLDB entry, read it again,
5290      * then make the changes to it (pass 2).
5291      */
5292     if (++pass == 2) {
5293         code = ubik_VL_SetLock(cstruct, 0, rwvolid, RWVOL, VLOP_DELETE);
5294         if (code) {
5295             fprintf(STDERR, "Could not lock VLDB entry for %lu\n",
5296                     (unsigned long)rwvolid);
5297             ERROR_EXIT(code);
5298         }
5299         islocked = 1;
5300     }
5301
5302     createentry = 0;            /* Do we need to create a VLDB entry */
5303     addvolume = 0;              /* Add this volume to the VLDB entry */
5304     modified = 0;               /* The VLDB entry was modified */
5305
5306     /* Read the entry from VLDB by its RW volume id */
5307     code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
5308     if (code) {
5309         if (code != VL_NOENT) {
5310             fprintf(STDOUT,
5311                     "Could not retreive the VLDB entry for volume %lu \n",
5312                     (unsigned long)rwvolid);
5313             ERROR_EXIT(code);
5314         }
5315
5316         memset(&entry, 0, sizeof(entry));
5317         vsu_ExtractName(entry.name, volumeinfo->name);  /* Store name of RW */
5318
5319         createentry = 1;
5320     } else {
5321         MapHostToNetwork(&entry);
5322     }
5323
5324     if (verbose && (pass == 1)) {
5325         fprintf(STDOUT, "_______________________________\n");
5326         fprintf(STDOUT, "\n-- status before -- \n");
5327         if (createentry) {
5328             fprintf(STDOUT, "\n**does not exist**\n");
5329         } else {
5330             if ((entry.flags & RW_EXISTS) || (entry.flags & RO_EXISTS)
5331                 || (entry.flags & BACK_EXISTS))
5332                 EnumerateEntry(&entry);
5333         }
5334         fprintf(STDOUT, "\n");
5335     }
5336
5337     if (volumeinfo->type == RWVOL) {    /* RW volume exists */
5338         if (createentry) {
5339             idx = 0;
5340             entry.nServers = 1;
5341             addvolume++;
5342         } else {
5343             /* Check existence of RW and BK volumes */
5344             code = CheckVldbRWBK(&entry, &mod);
5345             if (code)
5346                 ERROR_EXIT(code);
5347             if (mod)
5348                 modified++;
5349
5350             idx = Lp_GetRwIndex(&entry);
5351             if (idx == -1) {    /* RW index not found in the VLDB entry */
5352                 idx = entry.nServers;   /* put it into next index */
5353                 entry.nServers++;
5354                 addvolume++;
5355             } else {            /* RW index found in the VLDB entry. */
5356                 /* Verify if this volume's location matches where the VLDB says it is */
5357                 if (!Lp_Match(aserver, apart, &entry)) {
5358                     if (entry.flags & RW_EXISTS) {
5359                         /* The RW volume exists elsewhere - report this one a duplicate */
5360                         if (pass == 1) {
5361                             MapPartIdIntoName(apart, pname);
5362                             fprintf(STDERR,
5363                                     "*** Warning: Orphaned RW volume %lu exists on %s %s\n",
5364                                     (unsigned long)rwvolid,
5365                                     hostutil_GetNameByINet(aserver), pname);
5366                             MapPartIdIntoName(entry.serverPartition[idx],
5367                                               pname);
5368                             fprintf(STDERR,
5369                                     "    VLDB reports RW volume %lu exists on %s %s\n",
5370                                     (unsigned long)rwvolid,
5371                                     hostutil_GetNameByINet(entry.
5372                                                            serverNumber[idx]),
5373                                     pname);
5374                         }
5375                     } else {
5376                         /* The RW volume does not exist - have VLDB point to this one */
5377                         addvolume++;
5378
5379                         /* Check for orphaned BK volume on old partition */
5380                         if (entry.flags & BACK_EXISTS) {
5381                             if (pass == 1) {
5382                                 MapPartIdIntoName(entry.serverPartition[idx],
5383                                                   pname);
5384                                 fprintf(STDERR,
5385                                         "*** Warning: Orphaned BK volume %u exists on %s %s\n",
5386                                         entry.volumeId[BACKVOL],
5387                                         hostutil_GetNameByINet(entry.
5388                                                                serverNumber
5389                                                                [idx]), pname);
5390                                 MapPartIdIntoName(apart, pname);
5391                                 fprintf(STDERR,
5392                                         "    VLDB reports its RW volume %lu exists on %s %s\n",
5393                                         (unsigned long)rwvolid,
5394                                         hostutil_GetNameByINet(aserver),
5395                                         pname);
5396                             }
5397                         }
5398                     }
5399                 } else {
5400                     /* Volume location matches the VLDB location */
5401                     if ((volumeinfo->backupID && !entry.volumeId[BACKVOL])
5402                         || (volumeinfo->cloneID && !entry.volumeId[ROVOL])
5403                         ||
5404                         (strncmp
5405                          (entry.name, volumeinfo->name,
5406                           VOLSER_OLDMAXVOLNAME) != 0)) {
5407                         addvolume++;
5408                     }
5409                 }
5410             }
5411         }
5412
5413         if (addvolume) {
5414             entry.flags |= RW_EXISTS;
5415             entry.volumeId[RWVOL] = rwvolid;
5416             if (!entry.volumeId[BACKVOL])
5417                 entry.volumeId[BACKVOL] = volumeinfo->backupID;
5418             if (!entry.volumeId[ROVOL])
5419                 entry.volumeId[ROVOL] = volumeinfo->cloneID;
5420
5421             entry.serverFlags[idx] = ITSRWVOL;
5422             entry.serverNumber[idx] = aserver;
5423             entry.serverPartition[idx] = apart;
5424             strncpy(entry.name, volumeinfo->name, VOLSER_OLDMAXVOLNAME);
5425
5426             modified++;
5427
5428             /* One last check - to update BK if need to */
5429             code = CheckVldbRWBK(&entry, &mod);
5430             if (code)
5431                 ERROR_EXIT(code);
5432             if (mod)
5433                 modified++;
5434         }
5435     }
5436
5437     else if (volumeinfo->type == BACKVOL) {     /* A BK volume */
5438         if (createentry) {
5439             idx = 0;
5440             entry.nServers = 1;
5441             addvolume++;
5442         } else {
5443             /* Check existence of RW and BK volumes */
5444             code = CheckVldbRWBK(&entry, &mod);
5445             if (code)
5446                 ERROR_EXIT(code);
5447             if (mod)
5448                 modified++;
5449
5450             idx = Lp_GetRwIndex(&entry);
5451             if (idx == -1) {    /* RW index not found in the VLDB entry */
5452                 idx = entry.nServers;   /* Put it into next index */
5453                 entry.nServers++;
5454                 addvolume++;
5455             } else {            /* RW index found in the VLDB entry */
5456                 /* Verify if this volume's location matches where the VLDB says it is */
5457                 if (!Lp_Match(aserver, apart, &entry)) {
5458                     /* VLDB says RW and/or BK is elsewhere - report this BK volume orphaned */
5459                     if (pass == 1) {
5460                         MapPartIdIntoName(apart, pname);
5461                         fprintf(STDERR,
5462                                 "*** Warning: Orphaned BK volume %lu exists on %s %s\n",
5463                                 (unsigned long)volumeinfo->volid,
5464                                 hostutil_GetNameByINet(aserver), pname);
5465                         MapPartIdIntoName(entry.serverPartition[idx], pname);
5466                         fprintf(STDERR,
5467                                 "    VLDB reports its RW/BK volume %lu exists on %s %s\n",
5468                                 (unsigned long)rwvolid,
5469                                 hostutil_GetNameByINet(entry.
5470                                                        serverNumber[idx]),
5471                                 pname);
5472                     }
5473                 } else {
5474                     if (volumeinfo->volid != entry.volumeId[BACKVOL]) {
5475                         if (!(entry.flags & BACK_EXISTS)) {
5476                             addvolume++;
5477                         } else if (volumeinfo->volid >
5478                                    entry.volumeId[BACKVOL]) {
5479                             addvolume++;
5480
5481                             if (pass == 1) {
5482                                 MapPartIdIntoName(entry.serverPartition[idx],
5483                                                   pname);
5484                                 fprintf(STDERR,
5485                                         "*** Warning: Orphaned BK volume %u exists on %s %s\n",
5486                                         entry.volumeId[BACKVOL],
5487                                         hostutil_GetNameByINet(aserver),
5488                                         pname);
5489                                 fprintf(STDERR,
5490                                         "    VLDB reports its BK volume ID is %lu\n",
5491                                         (unsigned long)volumeinfo->volid);
5492                             }
5493                         } else {
5494                             if (pass == 1) {
5495                                 MapPartIdIntoName(entry.serverPartition[idx],
5496                                                   pname);
5497                                 fprintf(STDERR,
5498                                         "*** Warning: Orphaned BK volume %lu exists on %s %s\n",
5499                                         (unsigned long)volumeinfo->volid,
5500                                         hostutil_GetNameByINet(aserver),
5501                                         pname);
5502                                 fprintf(STDERR,
5503                                         "    VLDB reports its BK volume ID is %u\n",
5504                                         entry.volumeId[BACKVOL]);
5505                             }
5506                         }
5507                     } else if (!entry.volumeId[BACKVOL]) {
5508                         addvolume++;
5509                     }
5510                 }
5511             }
5512         }
5513         if (addvolume) {
5514             entry.flags |= BACK_EXISTS;
5515             entry.volumeId[RWVOL] = rwvolid;
5516             entry.volumeId[BACKVOL] = volumeinfo->volid;
5517
5518             entry.serverNumber[idx] = aserver;
5519             entry.serverPartition[idx] = apart;
5520             entry.serverFlags[idx] = ITSRWVOL;
5521
5522             modified++;
5523         }
5524     }
5525
5526     else if (volumeinfo->type == ROVOL) {       /* A RO volume */
5527         if (volumeinfo->volid == entry.volumeId[ROVOL]) {
5528             /* This is a quick check to see if the RO entry exists in the 
5529              * VLDB so we avoid the CheckVldbRO() call (which checks if each
5530              * RO volume listed in the VLDB exists).
5531              */
5532             idx = Lp_ROMatch(aserver, apart, &entry) - 1;
5533             if (idx == -1) {
5534                 idx = entry.nServers;
5535                 entry.nServers++;
5536                 addvolume++;
5537             } else {
5538                 if (!(entry.flags & RO_EXISTS)) {
5539                     addvolume++;
5540                 }
5541             }
5542         } else {
5543             /* Before we correct the VLDB entry, make sure all the
5544              * ROs listed in the VLDB exist.
5545              */
5546             code = CheckVldbRO(&entry, &mod);
5547             if (code)
5548                 ERROR_EXIT(code);
5549             if (mod)
5550                 modified++;
5551
5552             if (!(entry.flags & RO_EXISTS)) {
5553                 /* No RO exists in the VLDB entry - add this one */
5554                 idx = entry.nServers;
5555                 entry.nServers++;
5556                 addvolume++;
5557             } else if (volumeinfo->volid > entry.volumeId[ROVOL]) {
5558                 /* The volume headers's RO ID does not match that in the VLDB entry,
5559                  * and the vol hdr's ID is greater (implies more recent). So delete
5560                  * all the RO volumes listed in VLDB entry and add this volume.
5561                  */
5562                 for (j = 0; j < entry.nServers; j++) {
5563                     if (entry.serverFlags[j] & ITSROVOL) {
5564                         /* Verify this volume exists and print message we are orphaning it */
5565                         if (pass == 1) {
5566                             MapPartIdIntoName(apart, pname);
5567                             fprintf(STDERR,
5568                                     "*** Warning: Orphaned RO volume %u exists on %s %s\n",
5569                                     entry.volumeId[ROVOL],
5570                                     hostutil_GetNameByINet(entry.
5571                                                            serverNumber[j]),
5572                                     pname);
5573                             fprintf(STDERR,
5574                                     "    VLDB reports its RO volume ID is %lu\n",
5575                                     (unsigned long)volumeinfo->volid);
5576                         }
5577
5578                         Lp_SetRWValue(&entry, entry.serverNumber[idx],
5579                                       entry.serverPartition[idx], 0L, 0L);
5580                         entry.nServers--;
5581                         modified++;
5582                         j--;
5583                     }
5584                 }
5585
5586                 idx = entry.nServers;
5587                 entry.nServers++;
5588                 addvolume++;
5589             } else if (volumeinfo->volid < entry.volumeId[ROVOL]) {
5590                 /* The volume headers's RO ID does not match that in the VLDB entry,
5591                  * and the vol hdr's ID is lower (implies its older). So orphan it.
5592                  */
5593                 if (pass == 1) {
5594                     MapPartIdIntoName(apart, pname);
5595                     fprintf(STDERR,
5596                             "*** Warning: Orphaned RO volume %lu exists on %s %s\n",
5597                             (unsigned long)volumeinfo->volid,
5598                             hostutil_GetNameByINet(aserver), pname);
5599                     fprintf(STDERR,
5600                             "    VLDB reports its RO volume ID is %u\n",
5601                             entry.volumeId[ROVOL]);
5602                 }
5603             } else {
5604                 /* The RO volume ID in the volume header match that in the VLDB entry,
5605                  * and there exist RO volumes in the VLDB entry. See if any of them
5606                  * are this one. If not, then we add it.
5607                  */
5608                 idx = Lp_ROMatch(aserver, apart, &entry) - 1;
5609                 if (idx == -1) {
5610                     idx = entry.nServers;
5611                     entry.nServers++;
5612                     addvolume++;
5613                 }
5614             }
5615         }
5616
5617         if (addvolume) {
5618             entry.flags |= RO_EXISTS;
5619             entry.volumeId[RWVOL] = rwvolid;
5620             entry.volumeId[ROVOL] = volumeinfo->volid;
5621
5622             entry.serverNumber[idx] = aserver;
5623             entry.serverPartition[idx] = apart;
5624             entry.serverFlags[idx] = ITSROVOL;
5625
5626             modified++;
5627         }
5628     }
5629
5630     /* Remember largest volume id */
5631     if (entry.volumeId[ROVOL] > *maxvolid)
5632         *maxvolid = entry.volumeId[ROVOL];
5633     if (entry.volumeId[BACKVOL] > *maxvolid)
5634         *maxvolid = entry.volumeId[BACKVOL];
5635     if (entry.volumeId[RWVOL] > *maxvolid)
5636         *maxvolid = entry.volumeId[RWVOL];
5637
5638     if (modified && doit) {
5639         MapNetworkToHost(&entry, &storeEntry);
5640
5641         if (createentry) {
5642             code = VLDB_CreateEntry(&storeEntry);
5643             if (code) {
5644                 fprintf(STDOUT,
5645                         "Could not create a VLDB entry for the volume %lu\n",
5646                         (unsigned long)rwvolid);
5647                 ERROR_EXIT(code);
5648             }
5649         } else {
5650             if (pass == 1)
5651                 goto retry;
5652             code =
5653                 VLDB_ReplaceEntry(rwvolid, RWVOL, &storeEntry,
5654                                   LOCKREL_OPCODE | LOCKREL_AFSID |
5655                                   LOCKREL_TIMESTAMP);
5656             if (code) {
5657                 fprintf(STDERR, "Could not update entry for %lu\n",
5658                         (unsigned long)rwvolid);
5659                 ERROR_EXIT(code);
5660             }
5661         }
5662         if (modentry)
5663             *modentry = modified;
5664     } else if (pass == 2) {
5665         code =
5666             ubik_VL_ReleaseLock(cstruct, 0, rwvolid, RWVOL,
5667                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
5668         if (code) {
5669             PrintError("Could not unlock VLDB entry ", code);
5670         }
5671     }
5672
5673     if (verbose && doit) {
5674         fprintf(STDOUT, "-- status after --\n");
5675         if (modified)
5676             EnumerateEntry(&entry);
5677         else
5678             fprintf(STDOUT, "\n**no change**\n");
5679     }
5680
5681   error_exit:
5682     VPRINT("\n_______________________________\n");
5683     return (error);
5684 }
5685
5686 int
5687 sortVolumes(const void *a, const void *b)
5688 {
5689     volintInfo *v1 = (volintInfo *) a;
5690     volintInfo *v2 = (volintInfo *) b;
5691     afs_int32 rwvolid1, rwvolid2;
5692
5693     rwvolid1 = ((v1->type == RWVOL) ? v1->volid : v1->parentID);
5694     rwvolid2 = ((v2->type == RWVOL) ? v2->volid : v2->parentID);
5695
5696     if (rwvolid1 > rwvolid2)
5697         return -1;              /* lower RW id goes first */
5698     if (rwvolid1 < rwvolid2)
5699         return 1;
5700
5701     if (v1->type == RWVOL)
5702         return -1;              /* RW vols go first */
5703     if (v2->type == RWVOL)
5704         return 1;
5705
5706     if ((v1->type == BACKVOL) && (v2->type == ROVOL))
5707         return -1;              /* BK vols next */
5708     if ((v1->type == ROVOL) && (v2->type == BACKVOL))
5709         return 1;
5710
5711     if (v1->volid < v2->volid)
5712         return 1;               /* larger volids first */
5713     if (v1->volid > v2->volid)
5714         return -1;
5715     return 0;
5716 }
5717
5718 /* UV_SyncVolume()
5719  *      Synchronise <aserver> <apart>(if flags = 1) <avolid>.
5720  *      Synchronize an individual volume against a sever and partition.
5721  *      Checks the VLDB entry (similar to syncserv) as well as checks
5722  *      if the volume exists on specified servers (similar to syncvldb).
5723  */
5724 int
5725 UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
5726 {
5727     struct rx_connection *aconn = 0;
5728     afs_int32 j, k, code, vcode, error = 0;
5729     afs_int32 tverbose, mod, modified = 0;
5730     struct nvldbentry vldbentry;
5731     afs_int32 volumeid = 0;
5732     volEntries volumeInfo;
5733     struct partList PartList;
5734     afs_int32 pcnt, rv;
5735     afs_int32 maxvolid = 0;
5736
5737     volumeInfo.volEntries_val = (volintInfo *) 0;
5738     volumeInfo.volEntries_len = 0;
5739
5740     if (!aserver && (flags & 1)) {
5741         /* fprintf(STDERR,"Partition option requires a server option\n"); */
5742         ERROR_EXIT(EINVAL);
5743     }
5744
5745     /* Turn verbose logging off and do our own verbose logging */
5746     tverbose = verbose;
5747     if (flags & 2) 
5748         tverbose = 1;
5749     verbose = 0;
5750
5751     /* Read the VLDB entry */
5752     vcode = VLDB_GetEntryByName(avolname, &vldbentry);
5753     if (vcode && (vcode != VL_NOENT)) {
5754         fprintf(STDERR, "Could not access the VLDB for volume %s\n",
5755                 avolname);
5756         ERROR_EXIT(vcode);
5757     } else if (!vcode) {
5758         MapHostToNetwork(&vldbentry);
5759     }
5760
5761     if (tverbose) {
5762         fprintf(STDOUT, "Processing VLDB entry %s ...\n", avolname);
5763         fprintf(STDOUT, "_______________________________\n");
5764         fprintf(STDOUT, "\n-- status before -- \n");
5765         if (vcode) {
5766             fprintf(STDOUT, "\n**does not exist**\n");
5767         } else {
5768             if ((vldbentry.flags & RW_EXISTS) || (vldbentry.flags & RO_EXISTS)
5769                 || (vldbentry.flags & BACK_EXISTS))
5770                 EnumerateEntry(&vldbentry);
5771         }
5772         fprintf(STDOUT, "\n");
5773     }
5774
5775     /* Verify that all of the VLDB entries exist on the repective servers 
5776      * and partitions (this does not require that avolname be a volume ID).
5777      * Equivalent to a syncserv.
5778      */
5779     if (!vcode) {
5780         /* Tell CheckVldb not to update if appropriate */
5781         if (flags & 2)
5782             mod = 1;
5783         else
5784             mod = 0;
5785         code = CheckVldb(&vldbentry, &mod);
5786         if (code) {
5787             fprintf(STDERR, "Could not process VLDB entry for volume %s\n",
5788                     vldbentry.name);
5789             ERROR_EXIT(code);
5790         }
5791         if (mod)
5792             modified++;
5793     }
5794
5795     /* If aserver is given, we will search for the desired volume on it */
5796     if (aserver) {
5797         /* Generate array of partitions on the server that we will check */
5798         if (!(flags & 1)) {
5799             code = UV_ListPartitions(aserver, &PartList, &pcnt);
5800             if (code) {
5801                 fprintf(STDERR,
5802                         "Could not fetch the list of partitions from the server\n");
5803                 ERROR_EXIT(code);
5804             }
5805         } else {
5806             PartList.partId[0] = apart;
5807             pcnt = 1;
5808         }
5809
5810         aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
5811
5812         /* If a volume ID were given, search for it on each partition */
5813         if ((volumeid = atol(avolname))) {
5814             for (j = 0; j < pcnt; j++) {
5815                 code =
5816                     AFSVolListOneVolume(aconn, PartList.partId[j], volumeid,
5817                                         &volumeInfo);
5818                 if (code) {
5819                     if (code != ENODEV) {
5820                         fprintf(STDERR, "Could not query server\n");
5821                         ERROR_EXIT(code);
5822                     }
5823                 } else {
5824                     if (flags & 2)
5825                         mod = 1;
5826                     else
5827                         mod = 0;
5828                     /* Found one, sync it with VLDB entry */
5829                     code =
5830                         CheckVolume(volumeInfo.volEntries_val, aserver,
5831                                     PartList.partId[j], &mod, &maxvolid);
5832                     if (code)
5833                         ERROR_EXIT(code);
5834                     if (mod)
5835                         modified++;
5836                 }
5837
5838                 if (volumeInfo.volEntries_val)
5839                     free(volumeInfo.volEntries_val);
5840                 volumeInfo.volEntries_val = (volintInfo *) 0;
5841                 volumeInfo.volEntries_len = 0;
5842             }
5843         }
5844
5845         /* Check to see if the RW, BK, and RO IDs exist on any
5846          * partitions. We get the volume IDs from the VLDB.
5847          */
5848         rv = 1;                 /* Read the VLDB entry ? */
5849         for (j = 0; j < MAXTYPES; j++) {        /* for RW, RO, and BK IDs */
5850             if (rv) {
5851                 vcode = VLDB_GetEntryByName(avolname, &vldbentry);
5852                 if (vcode) {
5853                     if (vcode == VL_NOENT)
5854                         break;
5855                     fprintf(STDERR,
5856                             "Could not access the VLDB for volume %s\n",
5857                             avolname);
5858                     ERROR_EXIT(vcode);
5859                 }
5860                 rv = 0;
5861             }
5862
5863             if (vldbentry.volumeId[j] == 0)
5864                 continue;
5865
5866             for (k = 0; k < pcnt; k++) {        /* For each partition */
5867                 volumeInfo.volEntries_val = (volintInfo *) 0;
5868                 volumeInfo.volEntries_len = 0;
5869                 code =
5870                     AFSVolListOneVolume(aconn, PartList.partId[k],
5871                                         vldbentry.volumeId[j], &volumeInfo);
5872                 if (code) {
5873                     if (code != ENODEV) {
5874                         fprintf(STDERR, "Could not query server\n");
5875                         ERROR_EXIT(code);
5876                     }
5877                 } else {
5878                     if (flags & 2)
5879                         mod = 1;
5880                     else
5881                         mod = 0;
5882                     /* Found one, sync it with VLDB entry */
5883                     code =
5884                         CheckVolume(volumeInfo.volEntries_val, aserver,
5885                                     PartList.partId[k], &mod, &maxvolid);
5886                     if (code)
5887                         ERROR_EXIT(code);
5888                     if (mod)
5889                         modified++, rv++;
5890                 }
5891
5892                 if (volumeInfo.volEntries_val)
5893                     free(volumeInfo.volEntries_val);
5894                 volumeInfo.volEntries_val = (volintInfo *) 0;
5895                 volumeInfo.volEntries_len = 0;
5896             }
5897         }
5898     }
5899
5900     /* if (aserver) */
5901     /* If verbose output, print a summary of what changed */
5902     if (tverbose && !(flags & 2)) {
5903         fprintf(STDOUT, "-- status after --\n");
5904         code = VLDB_GetEntryByName(avolname, &vldbentry);
5905         if (code && (code != VL_NOENT)) {
5906             fprintf(STDERR, "Could not access the VLDB for volume %s\n",
5907                     avolname);
5908             ERROR_EXIT(code);
5909         }
5910         if (modified && (code == VL_NOENT)) {
5911             fprintf(STDOUT, "\n**entry deleted**\n");
5912         } else if (modified) {
5913             EnumerateEntry(&vldbentry);
5914         } else {
5915             fprintf(STDOUT, "\n**no change**\n");
5916         }
5917         fprintf(STDOUT, "\n_______________________________\n");
5918     }
5919
5920   error_exit:
5921     /* Now check if the maxvolid is larger than that stored in the VLDB */
5922     if (maxvolid) {
5923         afs_int32 maxvldbid = 0;
5924         code = ubik_VL_GetNewVolumeId(cstruct, 0, 0, &maxvldbid);
5925         if (code) {
5926             fprintf(STDERR,
5927                     "Could not get the highest allocated volume id from the VLDB\n");
5928             if (!error)
5929                 error = code;
5930         } else if (maxvolid > maxvldbid) {
5931             afs_int32 id, nid;
5932             id = maxvolid - maxvldbid + 1;
5933             code = ubik_VL_GetNewVolumeId(cstruct, 0, id, &nid);
5934             if (code) {
5935                 fprintf(STDERR,
5936                         "Error in increasing highest allocated volume id in VLDB\n");
5937                 if (!error)
5938                     error = code;
5939             }
5940         }
5941     }
5942
5943     verbose = tverbose;
5944     if (verbose) {
5945         if (error)
5946             fprintf(STDOUT, "...error encountered");
5947         else
5948             fprintf(STDOUT, "...done entry\n");
5949     }
5950     if (aconn)
5951         rx_DestroyConnection(aconn);
5952     if (volumeInfo.volEntries_val)
5953         free(volumeInfo.volEntries_val);
5954
5955     PrintError("", error);
5956     return error;
5957 }
5958
5959 /* UV_SyncVldb()
5960  *      Synchronise vldb with the file server <aserver> and,
5961  *      optionally, <apart>.
5962  */
5963 int
5964 UV_SyncVldb(afs_int32 aserver, afs_int32 apart, int flags, int force)
5965 {
5966     struct rx_connection *aconn;
5967     afs_int32 code, error = 0;
5968     int i, j, pfail;
5969     volEntries volumeInfo;
5970     struct partList PartList;
5971     afs_int32 pcnt;
5972     char pname[10];
5973     volintInfo *vi;
5974     afs_int32 failures = 0, modifications = 0, tentries = 0;
5975     afs_int32 modified;
5976     afs_uint32 maxvolid = 0;
5977
5978     volumeInfo.volEntries_val = (volintInfo *) 0;
5979     volumeInfo.volEntries_len = 0;
5980
5981     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
5982
5983     /* Generate array of partitions to check */
5984     if (!(flags & 1)) {
5985         code = UV_ListPartitions(aserver, &PartList, &pcnt);
5986         if (code) {
5987             fprintf(STDERR,
5988                     "Could not fetch the list of partitions from the server\n");
5989             ERROR_EXIT(code);
5990         }
5991     } else {
5992         PartList.partId[0] = apart;
5993         pcnt = 1;
5994     }
5995
5996     VPRINT("Processing volume entries ...\n");
5997
5998     /* Step through the array of partitions */
5999     for (i = 0; i < pcnt; i++) {
6000         apart = PartList.partId[i];
6001         MapPartIdIntoName(apart, pname);
6002
6003         volumeInfo.volEntries_val = (volintInfo *) 0;
6004         volumeInfo.volEntries_len = 0;
6005         code = AFSVolListVolumes(aconn, apart, 1, &volumeInfo);
6006         if (code) {
6007             fprintf(STDERR,
6008                     "Could not fetch the list of volumes from the server\n");
6009             ERROR_EXIT(code);
6010         }
6011
6012         /* May want to sort the entries: RW, BK (high to low), RO (high to low) */
6013         qsort((char *)volumeInfo.volEntries_val, volumeInfo.volEntries_len,
6014               sizeof(volintInfo), sortVolumes);
6015
6016         pfail = 0;
6017         for (vi = volumeInfo.volEntries_val, j = 0;
6018              j < volumeInfo.volEntries_len; j++, vi++) {
6019             if (!vi->status)
6020                 continue;
6021
6022             tentries++;
6023
6024             if (verbose) {
6025                 fprintf(STDOUT,
6026                         "Processing volume entry %d: %s (%lu) on server %s %s...\n",
6027                         j + 1, vi->name, (unsigned long)vi->volid,
6028                         hostutil_GetNameByINet(aserver), pname);
6029                 fflush(STDOUT);
6030             }
6031
6032             if (flags & 2)
6033                 modified = 1;
6034             else
6035                 modified = 0;
6036             code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
6037             if (code) {
6038                 PrintError("", code);
6039                 failures++;
6040                 pfail++;
6041             } else if (modified) {
6042                 modifications++;
6043             }
6044
6045             if (verbose) {
6046                 if (code) {
6047                     fprintf(STDOUT, "...error encountered\n\n");
6048                 } else {
6049                     fprintf(STDOUT, "...done entry %d\n\n", j + 1);
6050                 }
6051             }
6052         }
6053
6054         if (pfail) {
6055             fprintf(STDERR,
6056                     "Could not process entries on server %s partition %s\n",
6057                     hostutil_GetNameByINet(aserver), pname);
6058         }
6059         if (volumeInfo.volEntries_val) {
6060             free(volumeInfo.volEntries_val);
6061             volumeInfo.volEntries_val = 0;
6062         }
6063
6064     }                           /* thru all partitions */
6065
6066     if (flags & 2) {
6067         VPRINT3("Total entries: %u, Failed to process %d, Would change %d\n", 
6068                 tentries, failures, modifications);
6069     } else {
6070         VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n", 
6071                 tentries, failures, modifications);
6072     }
6073
6074   error_exit:
6075     /* Now check if the maxvolid is larger than that stored in the VLDB */
6076     if (maxvolid) {
6077         afs_int32 maxvldbid = 0;
6078         code = ubik_VL_GetNewVolumeId(cstruct, 0, 0, &maxvldbid);
6079         if (code) {
6080             fprintf(STDERR,
6081                     "Could not get the highest allocated volume id from the VLDB\n");
6082             if (!error)
6083                 error = code;
6084         } else if (maxvolid > maxvldbid) {
6085             afs_int32 id, nid;
6086             id = maxvolid - maxvldbid + 1;
6087             code = ubik_VL_GetNewVolumeId(cstruct, 0, id, &nid);
6088             if (code) {
6089                 fprintf(STDERR,
6090                         "Error in increasing highest allocated volume id in VLDB\n");
6091                 if (!error)
6092                     error = code;
6093             }
6094         }
6095     }
6096
6097     if (aconn)
6098         rx_DestroyConnection(aconn);
6099     if (volumeInfo.volEntries_val)
6100         free(volumeInfo.volEntries_val);
6101     PrintError("", error);
6102     return (error);
6103 }
6104
6105 /* VolumeExists()
6106  *      Determine if a volume exists on a server and partition.
6107  *      Try creating a transaction on the volume. If we can,
6108  *      the volume exists, if not, then return the error code.
6109  *      Some error codes mean the volume is unavailable but
6110  *      still exists - so we catch these error codes.
6111  */
6112 afs_int32
6113 VolumeExists(afs_int32 server, afs_int32 partition, afs_int32 volumeid)
6114 {
6115     struct rx_connection *conn = (struct rx_connection *)0;
6116     afs_int32 code = -1;
6117     volEntries volumeInfo;
6118
6119     conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
6120     if (conn) {
6121         volumeInfo.volEntries_val = (volintInfo *) 0;
6122         volumeInfo.volEntries_len = 0;
6123         code = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
6124         if (volumeInfo.volEntries_val)
6125             free(volumeInfo.volEntries_val);
6126         if (code == VOLSERILLEGAL_PARTITION)
6127             code = ENODEV;
6128         rx_DestroyConnection(conn);
6129     }
6130     return code;
6131 }
6132
6133 /* CheckVldbRWBK()
6134  *
6135  */
6136 afs_int32
6137 CheckVldbRWBK(struct nvldbentry * entry, afs_int32 * modified)
6138 {
6139     int modentry = 0;
6140     int idx;
6141     afs_int32 code, error = 0;
6142     char pname[10];
6143
6144     if (modified)
6145         *modified = 0;
6146     idx = Lp_GetRwIndex(entry);
6147
6148     /* Check to see if the RW volume exists and set the RW_EXISTS
6149      * flag accordingly.
6150      */
6151     if (idx == -1) {            /* Did not find a RW entry */
6152         if (entry->flags & RW_EXISTS) { /* ... yet entry says RW exists */
6153             entry->flags &= ~RW_EXISTS; /* ... so say RW does not exist */
6154             modentry++;
6155         }
6156     } else {
6157         code =
6158             VolumeExists(entry->serverNumber[idx],
6159                          entry->serverPartition[idx], entry->volumeId[RWVOL]);
6160         if (code == 0) {        /* RW volume exists */
6161             if (!(entry->flags & RW_EXISTS)) {  /* ... yet entry says RW does not exist */
6162                 entry->flags |= RW_EXISTS;      /* ... so say RW does exist */
6163                 modentry++;
6164             }
6165         } else if (code == ENODEV) {    /* RW volume does not exist */
6166             if (entry->flags & RW_EXISTS) {     /* ... yet entry says RW exists */
6167                 entry->flags &= ~RW_EXISTS;     /* ... so say RW does not exist */
6168                 modentry++;
6169             }
6170         } else {
6171             /* If VLDB says it didn't exist, then ignore error */
6172             if (entry->flags & RW_EXISTS) {
6173                 MapPartIdIntoName(entry->serverPartition[idx], pname);
6174                 fprintf(STDERR,
6175                         "Transaction call failed for RW volume %u on server %s %s\n",
6176                         entry->volumeId[RWVOL],
6177                         hostutil_GetNameByINet(entry->serverNumber[idx]),
6178                         pname);
6179                 ERROR_EXIT(code);
6180             }
6181         }
6182     }
6183
6184     /* Check to see if the BK volume exists and set the BACK_EXISTS
6185      * flag accordingly. idx already ponts to the RW entry.
6186      */
6187     if (idx == -1) {            /* Did not find a RW entry */
6188         if (entry->flags & BACK_EXISTS) {       /* ... yet entry says BK exists */
6189             entry->flags &= ~BACK_EXISTS;       /* ... so say BK does not exist */
6190             modentry++;
6191         }
6192     } else {                    /* Found a RW entry */
6193         code =
6194             VolumeExists(entry->serverNumber[idx],
6195                          entry->serverPartition[idx],
6196                          entry->volumeId[BACKVOL]);
6197         if (code == 0) {        /* BK volume exists */
6198             if (!(entry->flags & BACK_EXISTS)) {        /* ... yet entry says BK does not exist */
6199                 entry->flags |= BACK_EXISTS;    /* ... so say BK does exist */
6200                 modentry++;
6201             }
6202         } else if (code == ENODEV) {    /* BK volume does not exist */
6203             if (entry->flags & BACK_EXISTS) {   /* ... yet entry says BK exists */
6204                 entry->flags &= ~BACK_EXISTS;   /* ... so say BK does not exist */
6205                 modentry++;
6206             }
6207         } else {
6208             /* If VLDB says it didn't exist, then ignore error */
6209             if (entry->flags & BACK_EXISTS) {
6210                 MapPartIdIntoName(entry->serverPartition[idx], pname);
6211                 fprintf(STDERR,
6212                         "Transaction call failed for BK volume %u on server %s %s\n",
6213                         entry->volumeId[BACKVOL],
6214                         hostutil_GetNameByINet(entry->serverNumber[idx]),
6215                         pname);
6216                 ERROR_EXIT(code);
6217             }
6218         }
6219     }
6220
6221     /* If there is an idx but the BK and RW volumes no
6222      * longer exist, then remove the RW entry.
6223      */
6224     if ((idx != -1) && !(entry->flags & RW_EXISTS)
6225         && !(entry->flags & BACK_EXISTS)) {
6226         Lp_SetRWValue(entry, entry->serverNumber[idx],
6227                       entry->serverPartition[idx], 0L, 0L);
6228         entry->nServers--;
6229         modentry++;
6230     }
6231
6232   error_exit:
6233     if (modified)
6234         *modified = modentry;
6235     return (error);
6236 }
6237
6238 int
6239 CheckVldbRO(struct nvldbentry *entry, afs_int32 * modified)
6240 {
6241     int idx;
6242     int foundro = 0, modentry = 0;
6243     afs_int32 code, error = 0;
6244     char pname[10];
6245
6246     if (modified)
6247         *modified = 0;
6248
6249     /* Check to see if the RO volumes exist and set the RO_EXISTS
6250      * flag accordingly. 
6251      */
6252     for (idx = 0; idx < entry->nServers; idx++) {
6253         if (!(entry->serverFlags[idx] & ITSROVOL)) {
6254             continue;           /* not a RO */
6255         }
6256
6257         code =
6258             VolumeExists(entry->serverNumber[idx],
6259                          entry->serverPartition[idx], entry->volumeId[ROVOL]);
6260         if (code == 0) {        /* RO volume exists */
6261             foundro++;
6262         } else if (code == ENODEV) {    /* RW volume does not exist */
6263             Lp_SetROValue(entry, entry->serverNumber[idx],
6264                           entry->serverPartition[idx], 0L, 0L);
6265             entry->nServers--;
6266             idx--;
6267             modentry++;
6268         } else {
6269             MapPartIdIntoName(entry->serverPartition[idx], pname);
6270             fprintf(STDERR,
6271                     "Transaction call failed for RO %u on server %s %s\n",
6272                     entry->volumeId[ROVOL],
6273                     hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
6274             ERROR_EXIT(code);
6275         }
6276     }
6277
6278     if (foundro) {              /* A RO volume exists */
6279         if (!(entry->flags & RO_EXISTS)) {      /* ... yet entry says RW does not exist */
6280             entry->flags |= RO_EXISTS;  /* ... so say RW does exist */
6281             modentry++;
6282         }
6283     } else {                    /* A RO volume does not exist */
6284         if (entry->flags & RO_EXISTS) { /* ... yet entry says RO exists */
6285             entry->flags &= ~RO_EXISTS; /* ... so say RO does not exist */
6286             modentry++;
6287         }
6288     }
6289
6290   error_exit:
6291     if (modified)
6292         *modified = modentry;
6293     return (error);
6294 }
6295
6296 /* CheckVldb()
6297  *      Ensure that <entry> matches with the info on file servers
6298  */
6299 afs_int32
6300 CheckVldb(struct nvldbentry * entry, afs_int32 * modified)
6301 {
6302     afs_int32 code, error = 0;
6303     struct nvldbentry storeEntry;
6304     int islocked = 0, mod, modentry, delentry = 0;
6305     int pass = 0, doit=1;
6306
6307     if (modified) {
6308         if (*modified == 1) 
6309             doit = 0;
6310         *modified = 0;
6311     }
6312     if (verbose) {
6313         fprintf(STDOUT, "_______________________________\n");
6314         fprintf(STDOUT, "\n-- status before -- \n");
6315         if ((entry->flags & RW_EXISTS) || (entry->flags & RO_EXISTS)
6316             || (entry->flags & BACK_EXISTS))
6317             EnumerateEntry(entry);
6318         fprintf(STDOUT, "\n");
6319     }
6320
6321     if (strlen(entry->name) > (VOLSER_OLDMAXVOLNAME - 10)) {
6322         fprintf(STDERR, "Volume name %s exceeds limit of %d characters\n",
6323                 entry->name, VOLSER_OLDMAXVOLNAME - 10);
6324     }
6325
6326   retry:
6327     /* Check to see if the VLDB is ok without locking it (pass 1).
6328      * If it will change, then lock the VLDB entry, read it again,
6329      * then make the changes to it (pass 2).
6330      */
6331     if (++pass == 2) {
6332         code =
6333             ubik_VL_SetLock(cstruct, 0, entry->volumeId[RWVOL], RWVOL,
6334                       VLOP_DELETE);
6335         if (code) {
6336             fprintf(STDERR, "Could not lock VLDB entry for %u \n",
6337                     entry->volumeId[RWVOL]);
6338             ERROR_EXIT(code);
6339         }
6340         islocked = 1;
6341
6342         code = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, entry);
6343         if (code) {
6344             fprintf(STDERR, "Could not read VLDB entry for volume %s\n",
6345                     entry->name);
6346             ERROR_EXIT(code);
6347         } else {
6348             MapHostToNetwork(entry);
6349         }
6350     }
6351
6352     modentry = 0;
6353
6354     /* Check if the RW and BK entries are ok */
6355     code = CheckVldbRWBK(entry, &mod);
6356     if (code)
6357         ERROR_EXIT(code);
6358     if (mod && (pass == 1) && doit)
6359         goto retry;
6360     if (mod)
6361         modentry++;
6362
6363     /* Check if the RO volumes entries are ok */
6364     code = CheckVldbRO(entry, &mod);
6365     if (code)
6366         ERROR_EXIT(code);
6367     if (mod && (pass == 1) && doit)
6368         goto retry;
6369     if (mod)
6370         modentry++;
6371
6372     /* The VLDB entry has been updated. If it as been modified, then 
6373      * write the entry back out the the VLDB.
6374      */
6375     if (modentry && doit) {
6376         if (pass == 1)
6377             goto retry;
6378
6379         if (!(entry->flags & RW_EXISTS) && !(entry->flags & BACK_EXISTS)
6380             && !(entry->flags & RO_EXISTS) && doit) {
6381             /* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
6382             code =
6383                 ubik_VL_DeleteEntry(cstruct, 0, entry->volumeId[RWVOL],
6384                           RWVOL);
6385             if (code) {
6386                 fprintf(STDERR,
6387                         "Could not delete VLDB entry for volume %u \n",
6388                         entry->volumeId[RWVOL]);
6389                 ERROR_EXIT(code);
6390             }
6391             delentry = 1;
6392         } else {
6393             /* Replace old entry with our new one */
6394             MapNetworkToHost(entry, &storeEntry);
6395             code =
6396                 VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry,
6397                                   (LOCKREL_OPCODE | LOCKREL_AFSID |
6398                                    LOCKREL_TIMESTAMP));
6399             if (code) {
6400                 fprintf(STDERR, "Could not update VLDB entry for volume %u\n",
6401                         entry->volumeId[RWVOL]);
6402                 ERROR_EXIT(code);
6403             }
6404         }
6405         if (modified)
6406             *modified = 1;
6407         islocked = 0;
6408     }
6409
6410     if (verbose && doit) {
6411         fprintf(STDOUT, "-- status after --\n");
6412         if (delentry)
6413             fprintf(STDOUT, "\n**entry deleted**\n");
6414         else if (modentry)
6415             EnumerateEntry(entry);
6416         else
6417             fprintf(STDOUT, "\n**no change**\n");
6418     }
6419
6420   error_exit:
6421     VPRINT("\n_______________________________\n");
6422
6423     if (islocked) {
6424         code =
6425             ubik_VL_ReleaseLock(cstruct, 0, entry->volumeId[RWVOL],
6426                       RWVOL,
6427                       (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
6428         if (code) {
6429             fprintf(STDERR,
6430                     "Could not release lock on VLDB entry for volume %u\n",
6431                     entry->volumeId[RWVOL]);
6432             if (!error)
6433                 error = code;
6434         }
6435     }
6436     return error;
6437 }
6438
6439 /* UV_SyncServer()
6440  *      Synchronise <aserver> <apart>(if flags = 1) with the VLDB.
6441  */
6442 int
6443 UV_SyncServer(afs_int32 aserver, afs_int32 apart, int flags, int force)
6444 {
6445     struct rx_connection *aconn;
6446     afs_int32 code, error = 0;
6447     afs_int32 nentries, tentries = 0;
6448     struct VldbListByAttributes attributes;
6449     nbulkentries arrayEntries;
6450     afs_int32 failures = 0, modified, modifications = 0;
6451     struct nvldbentry *vlentry;
6452     afs_int32 si, nsi, j;
6453
6454     if (flags & 2) 
6455         verbose = 1;
6456
6457     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
6458
6459     /* Set up attributes to search VLDB  */
6460     attributes.server = ntohl(aserver);
6461     attributes.Mask = VLLIST_SERVER;
6462     if ((flags & 1)) {
6463         attributes.partition = apart;
6464         attributes.Mask |= VLLIST_PARTITION;
6465     }
6466
6467     VPRINT("Processing VLDB entries ...\n");
6468
6469     /* While we need to collect more VLDB entries */
6470     for (si = 0; si != -1; si = nsi) {
6471         memset(&arrayEntries, 0, sizeof(arrayEntries));
6472
6473         /* Collect set of VLDB entries */
6474         code =
6475             VLDB_ListAttributesN2(&attributes, 0, si, &nentries,
6476                                   &arrayEntries, &nsi);
6477         if (code == RXGEN_OPCODE) {
6478             code = VLDB_ListAttributes(&attributes, &nentries, &arrayEntries);
6479             nsi = -1;
6480         }
6481         if (code) {
6482             fprintf(STDERR, "Could not access the VLDB for attributes\n");
6483             ERROR_EXIT(code);
6484         }
6485         tentries += nentries;
6486
6487         for (j = 0; j < nentries; j++) {
6488             vlentry = &arrayEntries.nbulkentries_val[j];
6489             MapHostToNetwork(vlentry);
6490
6491             VPRINT1("Processing VLDB entry %d ...\n", j + 1);
6492
6493             /* Tell CheckVldb not to update if appropriate */
6494             if (flags & 2)
6495                 modified = 1;
6496             else
6497                 modified = 0;
6498             code = CheckVldb(vlentry, &modified);
6499             if (code) {
6500                 PrintError("", code);
6501                 fprintf(STDERR,
6502                         "Could not process VLDB entry for volume %s\n",
6503                         vlentry->name);
6504                 failures++;
6505             } else if (modified) {
6506                 modifications++;
6507             }
6508
6509             if (verbose) {
6510                 if (code) {
6511                     fprintf(STDOUT, "...error encountered\n\n");
6512                 } else {
6513                     fprintf(STDOUT, "...done entry %d\n\n", j + 1);
6514                 }
6515             }
6516         }
6517
6518         if (arrayEntries.nbulkentries_val) {
6519             free(arrayEntries.nbulkentries_val);
6520             arrayEntries.nbulkentries_val = 0;
6521         }
6522     }
6523
6524     if (flags & 2) {
6525         VPRINT3("Total entries: %u, Failed to process %d, Would change %d\n",
6526                 tentries, failures, modifications);
6527     } else {
6528         VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n", 
6529                 tentries, failures, modifications);
6530     }
6531
6532   error_exit:
6533     if (aconn)
6534         rx_DestroyConnection(aconn);
6535     if (arrayEntries.nbulkentries_val)
6536         free(arrayEntries.nbulkentries_val);
6537
6538     if (failures)
6539         error = VOLSERFAILEDOP;
6540     return error;
6541 }
6542
6543 /*rename volume <oldname> to <newname>, changing the names of the related 
6544  *readonly and backup volumes. This operation is also idempotent.
6545  *salvager is capable of recovering from rename operation stopping halfway.
6546  *to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
6547 int
6548 UV_RenameVolume(struct nvldbentry *entry, char oldname[], char newname[])
6549 {
6550     struct nvldbentry storeEntry;
6551     afs_int32 vcode, code, rcode, error;
6552     int i, index;
6553     char nameBuffer[256];
6554     afs_int32 tid;
6555     struct rx_connection *aconn;
6556     int islocked;
6557
6558     error = 0;
6559     aconn = (struct rx_connection *)0;
6560     tid = 0;
6561     islocked = 0;
6562
6563     vcode = ubik_VL_SetLock(cstruct, 0, entry->volumeId[RWVOL], RWVOL, VLOP_ADDSITE);   /*last param is dummy */
6564     if (vcode) {
6565         fprintf(STDERR,
6566                 " Could not lock the VLDB entry for the  volume %u \n",
6567                 entry->volumeId[RWVOL]);
6568         error = vcode;
6569         goto rvfail;
6570     }
6571     islocked = 1;
6572     strncpy(entry->name, newname, VOLSER_OLDMAXVOLNAME);
6573     MapNetworkToHost(entry, &storeEntry);
6574     vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry, 0);
6575     if (vcode) {
6576         fprintf(STDERR, "Could not update VLDB entry for %u\n",
6577                 entry->volumeId[RWVOL]);
6578         error = vcode;
6579         goto rvfail;
6580     }
6581     VPRINT1("Recorded the new name %s in VLDB\n", newname);
6582     /*at this stage the intent to rename is recorded in the vldb, as far as the vldb 
6583      * is concerned, oldname is lost */
6584     if (entry->flags & RW_EXISTS) {
6585         index = Lp_GetRwIndex(entry);
6586         if (index == -1) {      /* there is a serious discrepancy */
6587             fprintf(STDERR,
6588                     "There is a serious discrepancy in VLDB entry for volume %u\n",
6589                     entry->volumeId[RWVOL]);
6590             fprintf(STDERR, "try building VLDB from scratch\n");
6591             error = VOLSERVLDB_ERROR;
6592             goto rvfail;
6593         }
6594         aconn = UV_Bind(entry->serverNumber[index], AFSCONF_VOLUMEPORT);
6595         code =
6596             AFSVolTransCreate(aconn, entry->volumeId[RWVOL],
6597                               entry->serverPartition[index], ITOffline, &tid);
6598         if (code) {             /*volume doesnot exist */
6599             fprintf(STDERR,
6600                     "Could not start transaction on the rw volume %u\n",
6601                     entry->volumeId[RWVOL]);
6602             error = code;
6603             goto rvfail;
6604         } else {                /*volume exists, process it */
6605
6606             code =
6607                 AFSVolSetIdsTypes(aconn, tid, newname, RWVOL,
6608                                   entry->volumeId[RWVOL],
6609                                   entry->volumeId[ROVOL],
6610                                   entry->volumeId[BACKVOL]);
6611             if (!code) {
6612                 VPRINT2("Renamed rw volume %s to %s\n", oldname, newname);
6613                 code = AFSVolEndTrans(aconn, tid, &rcode);
6614                 tid = 0;
6615                 if (code) {
6616                     fprintf(STDERR,
6617                             "Could not  end transaction on volume %s %u\n",
6618                             entry->name, entry->volumeId[RWVOL]);
6619                     error = code;
6620                     goto rvfail;
6621                 }
6622             } else {
6623                 fprintf(STDERR, "Could not  set parameters on volume %s %u\n",
6624                         entry->name, entry->volumeId[RWVOL]);
6625                 error = code;
6626                 goto rvfail;
6627             }
6628         }
6629         if (aconn)
6630             rx_DestroyConnection(aconn);
6631         aconn = (struct rx_connection *)0;
6632     }
6633     /*end rw volume processing */
6634     if (entry->flags & BACK_EXISTS) {   /*process the backup volume */
6635         index = Lp_GetRwIndex(entry);
6636         if (index == -1) {      /* there is a serious discrepancy */
6637             fprintf(STDERR,
6638                     "There is a serious discrepancy in the VLDB entry for the backup volume %u\n",
6639                     entry->volumeId[BACKVOL]);
6640             fprintf(STDERR, "try building VLDB from scratch\n");
6641             error = VOLSERVLDB_ERROR;
6642             goto rvfail;
6643         }
6644         aconn = UV_Bind(entry->serverNumber[index], AFSCONF_VOLUMEPORT);
6645         code =
6646             AFSVolTransCreate(aconn, entry->volumeId[BACKVOL],
6647                               entry->serverPartition[index], ITOffline, &tid);
6648         if (code) {             /*volume doesnot exist */
6649             fprintf(STDERR,
6650                     "Could not start transaction on the backup volume  %u\n",
6651                     entry->volumeId[BACKVOL]);
6652             error = code;
6653             goto rvfail;
6654         } else {                /*volume exists, process it */
6655             if (strlen(newname) > (VOLSER_OLDMAXVOLNAME - 8)) {
6656                 fprintf(STDERR,
6657                         "Volume name %s.backup exceeds the limit of %u characters\n",
6658                         newname, VOLSER_OLDMAXVOLNAME);
6659                 error = code;
6660                 goto rvfail;
6661             }
6662             strcpy(nameBuffer, newname);
6663             strcat(nameBuffer, ".backup");
6664
6665             code =
6666                 AFSVolSetIdsTypes(aconn, tid, nameBuffer, BACKVOL,
6667                                   entry->volumeId[RWVOL], 0, 0);
6668             if (!code) {
6669                 VPRINT1("Renamed backup volume to %s \n", nameBuffer);
6670                 code = AFSVolEndTrans(aconn, tid, &rcode);
6671                 tid = 0;
6672                 if (code) {
6673                     fprintf(STDERR,
6674                             "Could not  end transaction on the backup volume %u\n",
6675                             entry->volumeId[BACKVOL]);
6676                     error = code;
6677                     goto rvfail;
6678                 }
6679             } else {
6680                 fprintf(STDERR,
6681                         "Could not  set parameters on the backup volume %u\n",
6682                         entry->volumeId[BACKVOL]);
6683                 error = code;
6684                 goto rvfail;
6685             }
6686         }
6687     }                           /* end backup processing */
6688     if (aconn)
6689         rx_DestroyConnection(aconn);
6690     aconn = (struct rx_connection *)0;
6691     if (entry->flags & RO_EXISTS) {     /*process the ro volumes */
6692         for (i = 0; i < entry->nServers; i++) {
6693             if (entry->serverFlags[i] & ITSROVOL) {
6694                 aconn = UV_Bind(entry->serverNumber[i], AFSCONF_VOLUMEPORT);
6695                 code =
6696                     AFSVolTransCreate(aconn, entry->volumeId[ROVOL],
6697                                       entry->serverPartition[i], ITOffline,
6698                                       &tid);
6699                 if (code) {     /*volume doesnot exist */
6700                     fprintf(STDERR,
6701                             "Could not start transaction on the ro volume %u\n",
6702                             entry->volumeId[ROVOL]);
6703                     error = code;
6704                     goto rvfail;
6705                 } else {        /*volume exists, process it */
6706                     strcpy(nameBuffer, newname);
6707                     strcat(nameBuffer, ".readonly");
6708                     if (strlen(nameBuffer) > (VOLSER_OLDMAXVOLNAME - 1)) {
6709                         fprintf(STDERR,
6710                                 "Volume name %s exceeds the limit of %u characters\n",
6711                                 nameBuffer, VOLSER_OLDMAXVOLNAME);
6712                         error = code;
6713                         goto rvfail;
6714                     }
6715                     code =
6716                         AFSVolSetIdsTypes(aconn, tid, nameBuffer, ROVOL,
6717                                           entry->volumeId[RWVOL], 0, 0);
6718                     if (!code) {
6719                         VPRINT2("Renamed RO volume %s on host %s\n",
6720                                 nameBuffer,
6721                                 hostutil_GetNameByINet(entry->
6722                                                        serverNumber[i]));
6723                         code = AFSVolEndTrans(aconn, tid, &rcode);
6724                         tid = 0;
6725                         if (code) {
6726                             fprintf(STDERR,
6727                                     "Could not  end transaction on volume %u\n",
6728                                     entry->volumeId[ROVOL]);
6729                             error = code;
6730                             goto rvfail;
6731                         }
6732                     } else {
6733                         fprintf(STDERR,
6734                                 "Could not  set parameters on the ro volume %u\n",
6735                                 entry->volumeId[ROVOL]);
6736                         error = code;
6737                         goto rvfail;
6738                     }
6739                 }
6740                 if (aconn)
6741                     rx_DestroyConnection(aconn);
6742                 aconn = (struct rx_connection *)0;
6743             }
6744         }
6745     }
6746   rvfail:
6747     if (islocked) {
6748         vcode =
6749             ubik_VL_ReleaseLock(cstruct, 0, entry->volumeId[RWVOL],
6750                       RWVOL,
6751                       LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
6752         if (vcode) {
6753             fprintf(STDERR,
6754                     "Could not unlock the VLDB entry for the volume %s %u\n",
6755                     entry->name, entry->volumeId[RWVOL]);
6756             if (!error)
6757                 error = vcode;
6758         }
6759     }
6760     if (tid) {
6761         code = AFSVolEndTrans(aconn, tid, &rcode);
6762         if (!code)
6763             code = rcode;
6764         if (code) {
6765             fprintf(STDERR, "Failed to end transaction on a volume \n");
6766             if (!error)
6767                 error = code;
6768         }
6769     }
6770     if (aconn)
6771         rx_DestroyConnection(aconn);
6772     PrintError("", error);
6773     return error;
6774
6775 }
6776
6777 /*report on all the active transactions on volser */
6778 int
6779 UV_VolserStatus(afs_int32 server, transDebugInfo ** rpntr, afs_int32 * rcount)
6780 {
6781     struct rx_connection *aconn;
6782     transDebugEntries transInfo;
6783     afs_int32 code = 0;
6784
6785     aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
6786     transInfo.transDebugEntries_val = (transDebugInfo *) 0;
6787     transInfo.transDebugEntries_len = 0;
6788     code = AFSVolMonitor(aconn, &transInfo);
6789     if (code) {
6790         fprintf(STDERR,
6791                 "Could not access status information about the server\n");
6792         PrintError("", code);
6793         if (transInfo.transDebugEntries_val)
6794             free(transInfo.transDebugEntries_val);
6795         if (aconn)
6796             rx_DestroyConnection(aconn);
6797         return code;
6798     } else {
6799         *rcount = transInfo.transDebugEntries_len;
6800         *rpntr = transInfo.transDebugEntries_val;
6801         if (aconn)
6802             rx_DestroyConnection(aconn);
6803         return 0;
6804     }
6805
6806
6807 }
6808
6809 /*delete the volume without interacting with the vldb */
6810 int
6811 UV_VolumeZap(afs_int32 server, afs_int32 part, afs_int32 volid)
6812 {
6813     afs_int32 rcode, ttid, error, code;
6814     struct rx_connection *aconn;
6815
6816     code = 0;
6817     error = 0;
6818     ttid = 0;
6819
6820     aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
6821     code = AFSVolTransCreate(aconn, volid, part, ITOffline, &ttid);
6822     if (code) {
6823         fprintf(STDERR, "Could not start transaction on volume %lu\n",
6824                 (unsigned long)volid);
6825         error = code;
6826         goto zfail;
6827     }
6828     code = AFSVolDeleteVolume(aconn, ttid);
6829     if (code) {
6830         fprintf(STDERR, "Could not delete volume %lu\n",
6831                 (unsigned long)volid);
6832         error = code;
6833         goto zfail;
6834     }
6835     code = AFSVolEndTrans(aconn, ttid, &rcode);
6836     ttid = 0;
6837     if (!code)
6838         code = rcode;
6839     if (code) {
6840         fprintf(STDERR, "Could not end transaction on volume %lu\n",
6841                 (unsigned long)volid);
6842         error = code;
6843         goto zfail;
6844     }
6845   zfail:
6846     if (ttid) {
6847         code = AFSVolEndTrans(aconn, ttid, &rcode);
6848         if (!code)
6849             code = rcode;
6850         if (!error)
6851             error = code;
6852     }
6853     PrintError("", error);
6854     if (aconn)
6855         rx_DestroyConnection(aconn);
6856     return error;
6857 }
6858
6859 int
6860 UV_SetVolume(afs_int32 server, afs_int32 partition, afs_int32 volid,
6861              afs_int32 transflag, afs_int32 setflag, int sleeptime)
6862 {
6863     struct rx_connection *conn = 0;
6864     afs_int32 tid = 0;
6865     afs_int32 code, error = 0, rcode;
6866
6867     conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
6868     if (!conn) {
6869         fprintf(STDERR, "SetVolumeStatus: Bind Failed");
6870         ERROR_EXIT(-1);
6871     }
6872
6873     code = AFSVolTransCreate(conn, volid, partition, transflag, &tid);
6874     if (code) {
6875         fprintf(STDERR, "SetVolumeStatus: TransCreate Failed\n");
6876         ERROR_EXIT(code);
6877     }
6878
6879     code = AFSVolSetFlags(conn, tid, setflag);
6880     if (code) {
6881         fprintf(STDERR, "SetVolumeStatus: SetFlags Failed\n");
6882         ERROR_EXIT(code);
6883     }
6884
6885     if (sleeptime) {
6886 #ifdef AFS_PTHREAD_ENV
6887         sleep(sleeptime);
6888 #else
6889         IOMGR_Sleep(sleeptime);
6890 #endif
6891     }
6892
6893   error_exit:
6894     if (tid) {
6895         rcode = 0;
6896         code = AFSVolEndTrans(conn, tid, &rcode);
6897         if (code || rcode) {
6898             fprintf(STDERR, "SetVolumeStatus: EndTrans Failed\n");
6899             if (!error)
6900                 error = (code ? code : rcode);
6901         }
6902     }
6903
6904     if (conn)
6905         rx_DestroyConnection(conn);
6906     return (error);
6907 }
6908
6909 int
6910 UV_SetVolumeInfo(afs_int32 server, afs_int32 partition, afs_int32 volid,
6911                  volintInfo * infop)
6912 {
6913     struct rx_connection *conn = 0;
6914     afs_int32 tid = 0;
6915     afs_int32 code, error = 0, rcode;
6916
6917     conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
6918     if (!conn) {
6919         fprintf(STDERR, "SetVolumeInfo: Bind Failed");
6920         ERROR_EXIT(-1);
6921     }
6922
6923     code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
6924     if (code) {
6925         fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
6926         ERROR_EXIT(code);
6927     }
6928
6929     code = AFSVolSetInfo(conn, tid, infop);
6930     if (code) {
6931         fprintf(STDERR, "SetVolumeInfo: SetInfo Failed\n");
6932         ERROR_EXIT(code);
6933     }
6934
6935   error_exit:
6936     if (tid) {
6937         rcode = 0;
6938         code = AFSVolEndTrans(conn, tid, &rcode);
6939         if (code || rcode) {
6940             fprintf(STDERR, "SetVolumeInfo: EndTrans Failed\n");
6941             if (!error)
6942                 error = (code ? code : rcode);
6943         }
6944     }
6945
6946     if (conn)
6947         rx_DestroyConnection(conn);
6948     return (error);
6949 }
6950
6951 int
6952 UV_GetSize(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
6953            afs_int32 fromdate, struct volintSize *vol_size)
6954 {
6955     struct rx_connection *aconn = (struct rx_connection *)0;
6956     afs_int32 tid = 0, rcode = 0;
6957     afs_int32 code, error = 0;
6958
6959
6960     /* get connections to the servers */
6961     aconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
6962
6963     VPRINT1("Starting transaction on volume %u...", afromvol);
6964     code = AFSVolTransCreate(aconn, afromvol, afrompart, ITBusy, &tid);
6965     EGOTO1(error_exit, code,
6966            "Could not start transaction on the volume %u to be measured\n",
6967            afromvol);
6968     VDONE;
6969
6970     VPRINT1("Getting size of volume on volume %u...", afromvol);
6971     code = AFSVolGetSize(aconn, tid, fromdate, vol_size);
6972     EGOTO(error_exit, code, "Could not start the measurement process \n");
6973     VDONE;
6974
6975   error_exit:
6976     if (tid) {
6977         VPRINT1("Ending transaction on volume %u...", afromvol);
6978         code = AFSVolEndTrans(aconn, tid, &rcode);
6979         if (code || rcode) {
6980             fprintf(STDERR, "Could not end transaction on the volume %u\n",
6981                     afromvol);
6982             fprintf(STDERR, "error codes: %d and %d\n", code, rcode);
6983             if (!error)
6984                 error = (code ? code : rcode);
6985         }
6986         VDONE;
6987     }
6988     if (aconn)
6989         rx_DestroyConnection(aconn);
6990
6991     PrintError("", error);
6992     return (error);
6993 }
6994
6995 /*maps the host addresses in <old > (present in network byte order) to
6996  that in< new> (present in host byte order )*/
6997 void
6998 MapNetworkToHost(struct nvldbentry *old, struct nvldbentry *new)
6999 {
7000     int i, count;
7001
7002     /*copy all the fields */
7003     strcpy(new->name, old->name);
7004 /*    new->volumeType = old->volumeType;*/
7005     new->nServers = old->nServers;
7006     count = old->nServers;
7007     if (count < NMAXNSERVERS)
7008         count++;
7009     for (i = 0; i < count; i++) {
7010         new->serverNumber[i] = ntohl(old->serverNumber[i]);
7011         new->serverPartition[i] = old->serverPartition[i];
7012         new->serverFlags[i] = old->serverFlags[i];
7013     }
7014     new->volumeId[RWVOL] = old->volumeId[RWVOL];
7015     new->volumeId[ROVOL] = old->volumeId[ROVOL];
7016     new->volumeId[BACKVOL] = old->volumeId[BACKVOL];
7017     new->cloneId = old->cloneId;
7018     new->flags = old->flags;
7019 }
7020
7021 /*maps the host entries in <entry> which are present in host byte order to network byte order */
7022 void
7023 MapHostToNetwork(struct nvldbentry *entry)
7024 {
7025     int i, count;
7026
7027     count = entry->nServers;
7028     if (count < NMAXNSERVERS)
7029         count++;
7030     for (i = 0; i < count; i++) {
7031         entry->serverNumber[i] = htonl(entry->serverNumber[i]);
7032     }
7033 }