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