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