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