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