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