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