2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
19 #include <rx/rx_queue.h>
20 #include <afs/afsint.h>
22 #include <afs/errors.h>
25 #include <afs/ihandle.h>
26 #include <afs/vnode.h>
27 #include <afs/volume.h>
28 #include <afs/partition.h>
29 #include <afs/daemon_com.h>
30 #include <afs/fssync.h>
32 #include <afs/com_err.h>
33 #include <afs/vol_prototypes.h>
38 #include "dumpstuff.h"
42 #define afs_stat stat64
43 #define afs_fstat fstat64
44 #else /* !O_LARGEFILE */
46 #define afs_fstat fstat
47 #endif /* !O_LARGEFILE */
48 #endif /* !AFS_NT40_ENV */
50 /*@printflike@*/ extern void Log(const char *format
, ...);
53 extern int DoPreserveVolumeStats
;
56 /* Forward Declarations */
57 static int DumpDumpHeader(struct iod
*iodp
, Volume
* vp
,
59 static int DumpPartial(struct iod
*iodp
, Volume
* vp
,
60 afs_int32 fromtime
, int dumpAllDirs
);
61 static int DumpVnodeIndex(struct iod
*iodp
, Volume
* vp
,
62 VnodeClass
class, afs_int32 fromtime
,
64 static int DumpVnode(struct iod
*iodp
, struct VnodeDiskObject
*v
,
65 VolumeId volid
, int vnodeNumber
, int dumpEverything
);
66 static int ReadDumpHeader(struct iod
*iodp
, struct DumpHeader
*hp
);
67 static int ReadVnodes(struct iod
*iodp
, Volume
* vp
, int incremental
,
68 afs_foff_t
* Lbuf
, afs_int32 s1
, afs_foff_t
* Sbuf
,
69 afs_int32 s2
, afs_int32 delo
);
70 static afs_fsize_t
volser_WriteFile(int vn
, struct iod
*iodp
,
71 FdHandle_t
* handleP
, int tag
,
74 static int SizeDumpDumpHeader(struct iod
*iodp
, Volume
* vp
,
76 struct volintSize
*size
);
77 static int SizeDumpPartial(struct iod
*iodp
, Volume
* vp
,
78 afs_int32 fromtime
, int dumpAllDirs
,
79 struct volintSize
*size
);
80 static int SizeDumpVnodeIndex(struct iod
*iodp
, Volume
* vp
,
81 VnodeClass
class, afs_int32 fromtime
,
83 struct volintSize
*size
);
84 static int SizeDumpVnode(struct iod
*iodp
, struct VnodeDiskObject
*v
,
85 VolumeId volid
, int vnodeNumber
, int dumpEverything
,
86 struct volintSize
*size
);
88 #define MAX_SECTIONS 3
90 /* The TLV range must start above D_MAX */
91 #define MIN_TLV_TAG 21
92 #define MAX_TLV_TAG 0x60
93 #define MAX_STANDARD_TAG 0x7a
94 static afs_uint32 oldtags
[MAX_SECTIONS
][16];
95 int oldtagsInited
= 0;
98 RegisterTag(afs_int32 section
, unsigned char tag
)
100 afs_uint32 off
= tag
>> 5;
101 afs_uint32 mask
= 1 << (tag
& 0x1f);
102 oldtags
[section
][off
] |= mask
;
106 initNonStandardTags(void)
108 RegisterTag(0, 'n'); /* volume name */
109 RegisterTag(0, 't'); /* fromtime, V_backupDate */
110 RegisterTag(1, 'A'); /* V_accessDate */
111 RegisterTag(1, 'C'); /* V_creationDate */
112 RegisterTag(1, 'D'); /* V_dayUseDate */
113 RegisterTag(1, 'E'); /* V_expirationDate */
114 RegisterTag(1, 'M'); /* nullstring (motd) */
115 RegisterTag(1, 'U'); /* V_updateDate */
116 RegisterTag(1, 'W'); /* V_weekUse */
117 RegisterTag(1, 'Z'); /* V_dayUse */
118 RegisterTag(1, 'O'); /* V_offlineMessage */
119 RegisterTag(1, 'b'); /* V_blessed */
120 RegisterTag(1, 'n'); /* V_name */
121 RegisterTag(1, 's'); /* V_inService */
122 RegisterTag(1, 't'); /* V_type */
123 RegisterTag(2, 'A'); /* VVnodeDiskACL */
124 RegisterTag(2, 'b'); /* modeBits */
125 RegisterTag(2, 'f'); /* small file */
126 RegisterTag(2, 'h'); /* large file */
127 RegisterTag(2, 'l'); /* linkcount */
128 RegisterTag(2, 't'); /* type */
133 iod_Init(struct iod
*iodp
, struct rx_call
*call
)
136 iodp
->haveOldChar
= 0;
138 iodp
->calls
= (struct rx_call
**)0;
142 iod_InitMulti(struct iod
*iodp
, struct rx_call
**calls
, int ncalls
,
147 iodp
->haveOldChar
= 0;
148 iodp
->ncalls
= ncalls
;
150 iodp
->call
= (struct rx_call
*)0;
153 /* N.B. iod_Read doesn't check for oldchar (see previous comment) */
154 #define iod_Read(iodp, buf, nbytes) rx_Read((iodp)->call, buf, nbytes)
156 /* For the single dump case, it's ok to just return the "bytes written"
157 * that rx_Write returns, since all the callers of iod_Write abort when
158 * the returned value is less than they expect. For the multi dump case,
159 * I don't think we want half the replicas to go bad just because one
160 * connection timed out, but if they all time out, then we should give up.
163 iod_Write(struct iod
*iodp
, char *buf
, int nbytes
)
168 opr_Assert((iodp
->call
&& iodp
->ncalls
== 1 && !iodp
->calls
)
169 || (!iodp
->call
&& iodp
->ncalls
>= 1 && iodp
->calls
));
172 code
= rx_Write(iodp
->call
, buf
, nbytes
);
176 for (i
= 0; i
< iodp
->ncalls
; i
++) {
177 if (iodp
->calls
[i
] && !iodp
->codes
[i
]) {
178 code
= rx_Write(iodp
->calls
[i
], buf
, nbytes
);
179 if (code
!= nbytes
) { /* everything gets merged into a single error */
180 iodp
->codes
[i
] = VOLSERDUMPERROR
; /* but that's exactly what the */
181 } /* standard dump does, anyways */
186 } /* for all calls */
195 iod_ungetc(struct iod
*iodp
, int achar
)
197 iodp
->oldChar
= achar
;
198 iodp
->haveOldChar
= 1;
202 iod_getc(struct iod
*iodp
)
206 if (iodp
->haveOldChar
) {
207 iodp
->haveOldChar
= 0;
208 return iodp
->oldChar
;
210 if (iod_Read(iodp
, (char *) &t
, 1) == 1)
216 ReadShort(struct iod
*iodp
, unsigned short *sp
)
225 *sp
= (b1
<< 8) | b0
;
230 ReadInt32(struct iod
*iodp
, afs_uint32
* lp
)
232 afs_uint32 b3
, b2
, b1
, b0
;
245 *lp
= (((((b3
<< 8) | b2
) << 8) | b1
) << 8) | b0
;
250 ReadString(struct iod
*iodp
, char *to
, int maxa
)
259 if ((*to
++ = c
= iod_getc(iodp
)) == 0 || c
== EOF
)
263 while ((c
= iod_getc(iodp
)) && c
!= EOF
);
269 ReadByteString(struct iod
*iodp
, byte
* to
, int size
)
274 while (size
-- > 0 && (c
= iod_getc(iodp
)) != EOF
) {
282 * returns 1 on success and 0 otherwise
285 ReadStandardTagLen(struct iod
*iodp
, unsigned char tag
, afs_int32 section
,
289 afs_uint32 off
= tag
>> 5;
290 afs_uint32 mask
= 1 << (tag
& 0x1f);
292 unsigned char buf
[8], *p
;
295 initNonStandardTags();
297 if (tag
< MIN_TLV_TAG
298 || tag
> MAX_STANDARD_TAG
299 || section
>= MAX_SECTIONS
300 || (oldtags
[section
][ off
] & mask
)) {
301 Log("Trying to use ReadStandardTag with tag 0x%02x for section %d, aborting\n", tag
, section
);
304 if (tag
<= MAX_TLV_TAG
) {
305 len
= iod_getc(iodp
);
307 return VOLSERDUMPERROR
;
312 if ((code
= iod_Read(iodp
, (char *)buf
, len
)) != len
)
313 return VOLSERDUMPERROR
;
315 p
= (unsigned char *)&buf
;
316 for (i
=0; i
<len
; i
++) {
317 *length
= ((*length
) << 8) | *p
++;
321 if (tag
< MAX_STANDARD_TAG
)
327 static char skipbuf
[256];
330 SkipData(struct iod
*iodp
, afs_size_t length
)
332 while (length
> 256) {
333 if (iod_Read(iodp
, (char *)&skipbuf
, 256) != 256)
337 if (iod_Read(iodp
, (char *)&skipbuf
, length
) != length
)
342 static char *secname
[3] = {"ReadDumpHeader", "ReadVolumeHeader", "ReadVnodes"};
345 HandleUnknownTag(struct iod
*iodp
, int tag
, afs_int32 section
,
348 afs_size_t taglen
= 0;
352 Log("%s: unknown critical tag x%02x, aborting\n",
353 secname
[section
], tag
);
356 Log("%s: unknown tag x%02x found, skipping\n", secname
[section
], tag
);
357 if (tag
>= 0x06 && tag
<= 0x60) {
358 if (!ReadStandardTagLen(iodp
, tag
, 1, &taglen
)) {
359 Log("%s: error reading length field for tag x%02x, aborting\n",
360 secname
[section
], tag
);
363 if (!SkipData(iodp
, taglen
)) {
364 Log("%s: error skipping %llu bytes for tag x%02x, aborting\n",
365 secname
[section
], taglen
, tag
);
370 if (tag
>= 0x61 && tag
<= 0x7a) {
371 if (!ReadInt32(iodp
, &trash
)) {
372 Log("%s: error skipping int32 for tag x%02x, aborting\n",
373 secname
[section
], tag
);
378 if (tag
>= 0x7b && tag
< 0x80) /* dataless tag */
380 Log("%s: unknown invalid tag x%02x, aborting\n", secname
[section
], tag
);
385 ReadVolumeHeader(struct iod
*iodp
, VolumeDiskData
* vol
)
389 afs_int32 critical
= 0;
390 memset(vol
, 0, sizeof(*vol
));
391 while ((tag
= iod_getc(iodp
)) > D_MAX
&& tag
!= EOF
) {
396 if (!ReadInt32(iodp
, &vol
->id
))
397 return VOLSERREAD_DUMPERROR
;
400 if (!ReadInt32(iodp
, &trash
))
401 return VOLSERREAD_DUMPERROR
;
404 ReadString(iodp
, vol
->name
, sizeof(vol
->name
));
405 /*this means the name of the retsored volume could be possibly different. In conjunction with SAFSVolSignalRestore */
408 vol
->inService
= iod_getc(iodp
);
411 vol
->blessed
= iod_getc(iodp
);
414 if (!ReadInt32(iodp
, &vol
->uniquifier
))
415 return VOLSERREAD_DUMPERROR
;
418 vol
->type
= iod_getc(iodp
);
421 if (!ReadInt32(iodp
, &vol
->parentId
))
422 return VOLSERREAD_DUMPERROR
;
425 if (!ReadInt32(iodp
, &vol
->cloneId
))
426 return VOLSERREAD_DUMPERROR
;
429 if (!ReadInt32(iodp
, (afs_uint32
*) & vol
->maxquota
))
430 return VOLSERREAD_DUMPERROR
;
433 if (!ReadInt32(iodp
, (afs_uint32
*) & vol
->minquota
))
434 return VOLSERREAD_DUMPERROR
;
437 if (!ReadInt32(iodp
, (afs_uint32
*) & vol
->diskused
))
438 return VOLSERREAD_DUMPERROR
; /* Bogus: should calculate this */
441 if (!ReadInt32(iodp
, (afs_uint32
*) & vol
->filecount
))
442 return VOLSERREAD_DUMPERROR
;
445 if (!ReadInt32(iodp
, &vol
->accountNumber
))
446 return VOLSERREAD_DUMPERROR
;
449 if (!ReadInt32(iodp
, &vol
->owner
))
450 return VOLSERREAD_DUMPERROR
;
453 if (!ReadInt32(iodp
, &vol
->creationDate
))
454 return VOLSERREAD_DUMPERROR
;
457 if (!ReadInt32(iodp
, &vol
->accessDate
))
458 return VOLSERREAD_DUMPERROR
;
461 if (!ReadInt32(iodp
, &vol
->updateDate
))
462 return VOLSERREAD_DUMPERROR
;
465 if (!ReadInt32(iodp
, &vol
->expirationDate
))
466 return VOLSERREAD_DUMPERROR
;
469 if (!ReadInt32(iodp
, &vol
->backupDate
))
470 return VOLSERREAD_DUMPERROR
;
473 ReadString(iodp
, vol
->offlineMessage
,
474 sizeof(vol
->offlineMessage
));
478 * Detailed volume statistics are never stored in dumps,
479 * so we just restore either the null string if this volume
480 * had already been set to store statistics, or the old motd
481 * contents otherwise. It doesn't matter, since this field
482 * will soon get initialized anyway.
484 ReadString(iodp
, (char *)(vol
->stat_reads
), VMSGSIZE
);
487 unsigned short length
;
490 if (!ReadShort(iodp
, &length
))
491 return VOLSERREAD_DUMPERROR
;
492 for (i
= 0; i
< length
; i
++) {
493 if (!ReadInt32(iodp
, &data
))
494 return VOLSERREAD_DUMPERROR
;
495 if (i
< sizeof(vol
->weekUse
) / sizeof(vol
->weekUse
[0]))
496 vol
->weekUse
[i
] = data
;
501 if (!ReadInt32(iodp
, &vol
->dayUseDate
))
502 return VOLSERREAD_DUMPERROR
;
505 if (!ReadInt32(iodp
, (afs_uint32
*) & vol
->dayUse
))
506 return VOLSERREAD_DUMPERROR
;
509 if (!ReadInt32(iodp
, (afs_uint32
*) &trash
/*volUpdateCounter*/))
510 return VOLSERREAD_DUMPERROR
;
516 if (!HandleUnknownTag(iodp
, tag
, 1, critical
))
517 return VOLSERREAD_DUMPERROR
;
520 iod_ungetc(iodp
, tag
);
525 DumpTag(struct iod
*iodp
, int tag
)
530 return ((iod_Write(iodp
, &p
, 1) == 1) ? 0 : VOLSERDUMPERROR
);
535 DumpByte(struct iod
*iodp
, char tag
, byte value
)
538 byte
*p
= (unsigned char *)tbuffer
;
541 return ((iod_Write(iodp
, tbuffer
, 2) == 2) ? 0 : VOLSERDUMPERROR
);
544 #define afs_putint32(p, v) *p++ = v>>24, *p++ = v>>16, *p++ = v>>8, *p++ = v
545 #define afs_putshort(p, v) *p++ = v>>8, *p++ = v
548 DumpDouble(struct iod
*iodp
, char tag
, afs_uint32 value1
,
552 byte
*p
= (unsigned char *)tbuffer
;
554 afs_putint32(p
, value1
);
555 afs_putint32(p
, value2
);
556 return ((iod_Write(iodp
, tbuffer
, 9) == 9) ? 0 : VOLSERDUMPERROR
);
560 DumpInt32(struct iod
*iodp
, char tag
, afs_uint32 value
)
563 byte
*p
= (unsigned char *)tbuffer
;
565 afs_putint32(p
, value
);
566 return ((iod_Write(iodp
, tbuffer
, 5) == 5) ? 0 : VOLSERDUMPERROR
);
570 DumpArrayInt32(struct iod
*iodp
, char tag
,
571 afs_uint32
* array
, int nelem
)
576 byte
*p
= (unsigned char *)tbuffer
;
578 afs_putshort(p
, nelem
);
579 code
= iod_Write(iodp
, tbuffer
, 3);
581 return VOLSERDUMPERROR
;
583 p
= (unsigned char *)tbuffer
;
584 v
= *array
++; /*this was register */
587 code
= iod_Write(iodp
, tbuffer
, 4);
589 return VOLSERDUMPERROR
;
595 DumpShort(struct iod
*iodp
, char tag
, unsigned int value
)
598 byte
*p
= (unsigned char *)tbuffer
;
602 return ((iod_Write(iodp
, tbuffer
, 3) == 3) ? 0 : VOLSERDUMPERROR
);
606 DumpBool(struct iod
*iodp
, char tag
, unsigned int value
)
609 byte
*p
= (unsigned char *)tbuffer
;
612 return ((iod_Write(iodp
, tbuffer
, 2) == 2) ? 0 : VOLSERDUMPERROR
);
616 DumpString(struct iod
*iodp
, char tag
, char *s
)
620 code
= iod_Write(iodp
, &tag
, 1);
622 return VOLSERDUMPERROR
;
624 code
= iod_Write(iodp
, s
, n
);
626 return VOLSERDUMPERROR
;
631 DumpByteString(struct iod
*iodp
, char tag
, byte
* bs
,
636 code
= iod_Write(iodp
, &tag
, 1);
638 return VOLSERDUMPERROR
;
639 code
= iod_Write(iodp
, (char *)bs
, nbytes
);
641 return VOLSERDUMPERROR
;
646 DumpStandardTag(struct iod
*iodp
, char tag
, afs_uint32 section
)
649 afs_uint32 off
= tag
>> 5;
650 afs_uint32 mask
= 1 << (tag
& 0x1f);
653 initNonStandardTags();
655 if (tag
< MIN_TLV_TAG
656 || tag
> MAX_STANDARD_TAG
657 || section
>= MAX_SECTIONS
658 || (oldtags
[section
][ off
] & mask
)) {
659 Log("Trying to use DumpStandardTag with tag 0x%02x for section %d, aborting\n", tag
, section
);
660 return VOLSERDUMPERROR
;
662 code
= iod_Write(iodp
, &tag
, 1);
664 return VOLSERDUMPERROR
;
670 DumpStandardTagLen(struct iod
*iodp
, char tag
, afs_uint32 section
,
677 if (tag
< MIN_TLV_TAG
|| tag
> MAX_TLV_TAG
) {
678 Log("Trying to use DumpStandardTagLen with tag 0x%02x for section %d, aborting\n", tag
, section
);
679 return VOLSERDUMPERROR
;
681 code
= DumpStandardTag(iodp
, tag
, section
);
685 if (length
< 128) { /* byte after tag contains length */
688 } else { /* byte after tag contains length of length field | 0x80 */
689 for (len
=0; length
; length
=length
>> 8) {
697 code
= iod_Write(iodp
, p
, len
);
699 return VOLSERDUMPERROR
;
704 DumpFile(struct iod
*iodp
, int vnode
, FdHandle_t
* handleP
)
706 int code
= 0, error
= 0;
708 afs_foff_t offset
= 0;
709 afs_sfsize_t nbytes
, howBig
;
712 afs_foff_t howFar
= 0;
717 struct afs_stat status
;
719 LARGE_INTEGER fileSize
;
722 #include <sys/statfs.h>
723 #if defined(AFS_AIX52_ENV)
724 struct statfs64 tstatfs
;
725 #else /* !AFS_AIX52_ENV */
726 struct statfs tstatfs
;
727 #endif /* !AFS_AIX52_ENV */
732 if (!GetFileSizeEx(handleP
->fd_fd
, &fileSize
)) {
733 Log("DumpFile: GetFileSizeEx returned error code %d on descriptor %d\n", GetLastError(), handleP
->fd_fd
);
734 return VOLSERDUMPERROR
;
736 howBig
= fileSize
.QuadPart
;
740 afs_fstat(handleP
->fd_fd
, &status
);
741 howBig
= status
.st_size
;
744 /* Unfortunately in AIX valuable fields such as st_blksize are
745 * gone from the stat structure.
747 #if defined(AFS_AIX52_ENV)
748 statfs_code
= fstatfs64(handleP
->fd_fd
, &tstatfs
);
749 #else /* !AFS_AIX52_ENV */
750 statfs_code
= fstatfs(handleP
->fd_fd
, &tstatfs
);
751 #endif /* !AFS_AIX52_ENV */
752 if (statfs_code
!= 0) {
753 Log("DumpFile: fstatfs returned error code %d on descriptor %d\n", errno
, handleP
->fd_fd
);
754 return VOLSERDUMPERROR
;
756 howMany
= tstatfs
.f_bsize
;
758 howMany
= status
.st_blksize
;
759 #endif /* AFS_AIX_ENV */
760 #endif /* AFS_NT40_ENV */
763 SplitInt64(howBig
, hi
, lo
);
765 code
= DumpInt32(iodp
, 'f', lo
);
767 code
= DumpDouble(iodp
, 'h', hi
, lo
);
770 return VOLSERDUMPERROR
;
775 Log("1 Volser: DumpFile: not enough memory to allocate %u bytes\n", (unsigned)howMany
);
776 return VOLSERDUMPERROR
;
779 for (nbytes
= howBig
; (nbytes
&& !error
); nbytes
-= howMany
) {
780 if (nbytes
< howMany
)
784 n
= FDH_PREAD(handleP
, p
, howMany
, howFar
);
787 /* If read any good data and we null padded previously, log the
788 * amount that we had null padded.
790 if ((n
> 0) && pad
) {
791 Log("1 Volser: DumpFile: Null padding file %d bytes at offset %lld\n", pad
, (long long)offset
);
795 /* If didn't read enough data, null padd the rest of the buffer. This
796 * can happen if, for instance, the media has some bad spots. We don't
797 * want to quit the dump, so we start null padding.
800 /* Record the read error */
803 Log("1 Volser: DumpFile: Error reading inode %s for vnode %d: %s\n", PrintInode(stmp
, handleP
->fd_ih
->ih_ino
), vnode
, afs_error_message(errno
));
805 Log("1 Volser: DumpFile: Error reading inode %s for vnode %d\n", PrintInode(stmp
, handleP
->fd_ih
->ih_ino
), vnode
);
808 /* Pad the rest of the buffer with zeros. Remember offset we started
809 * padding. Keep total tally of padding.
811 memset(p
+ n
, 0, howMany
- n
);
813 offset
= (howBig
- nbytes
) + n
;
814 pad
+= (howMany
- n
);
816 /* Now seek over the data we could not get. An error here means we
817 * can't do the next read.
819 howFar
= (size_t)((howBig
- nbytes
) + howMany
);
822 /* Now write the data out */
823 if (iod_Write(iodp
, (char *)p
, howMany
) != howMany
)
824 error
= VOLSERDUMPERROR
;
825 #ifndef AFS_PTHREAD_ENV
830 if (pad
) { /* Any padding we hadn't reported yet */
831 Log("1 Volser: DumpFile: Null padding file: %d bytes at offset %lld\n",
832 pad
, (long long)offset
);
840 DumpVolumeHeader(struct iod
*iodp
, Volume
* vp
)
843 static char nullString
[1] = ""; /*The ``contents'' of motd */
846 code
= DumpTag(iodp
, D_VOLUMEHEADER
);
848 code
= DumpInt32(iodp
, 'i', V_id(vp
));
851 code
= DumpInt32(iodp
, 'v', V_stamp(vp
).version
);
853 code
= DumpString(iodp
, 'n', V_name(vp
));
855 code
= DumpBool(iodp
, 's', V_inService(vp
));
857 code
= DumpBool(iodp
, 'b', V_blessed(vp
));
859 code
= DumpInt32(iodp
, 'u', V_uniquifier(vp
));
861 code
= DumpByte(iodp
, 't', (byte
) V_type(vp
));
863 code
= DumpInt32(iodp
, 'p', V_parentId(vp
));
866 code
= DumpInt32(iodp
, 'c', V_cloneId(vp
));
868 code
= DumpInt32(iodp
, 'q', V_maxquota(vp
));
870 code
= DumpInt32(iodp
, 'm', V_minquota(vp
));
872 code
= DumpInt32(iodp
, 'd', V_diskused(vp
));
874 code
= DumpInt32(iodp
, 'f', V_filecount(vp
));
876 code
= DumpInt32(iodp
, 'a', V_accountNumber(vp
));
878 code
= DumpInt32(iodp
, 'o', V_owner(vp
));
880 code
= DumpInt32(iodp
, 'C', V_creationDate(vp
)); /* Rw volume creation date */
882 code
= DumpInt32(iodp
, 'A', V_accessDate(vp
));
884 code
= DumpInt32(iodp
, 'U', V_updateDate(vp
));
886 code
= DumpInt32(iodp
, 'E', V_expirationDate(vp
));
888 code
= DumpInt32(iodp
, 'B', V_backupDate(vp
)); /* Rw volume backup clone date */
890 code
= DumpString(iodp
, 'O', V_offlineMessage(vp
));
892 * We do NOT dump the detailed volume statistics residing in the old
893 * motd field, since we cannot tell from the info in a dump whether
894 * statistics data has been put there. Instead, we dump a null string,
895 * just as if that was what the motd contained.
898 code
= DumpString(iodp
, 'M', nullString
);
901 DumpArrayInt32(iodp
, 'W', (afs_uint32
*) V_weekUse(vp
),
902 sizeof(V_weekUse(vp
)) / sizeof(V_weekUse(vp
)[0]));
904 code
= DumpInt32(iodp
, 'D', V_dayUseDate(vp
));
906 code
= DumpInt32(iodp
, 'Z', V_dayUse(vp
));
911 DumpEnd(struct iod
*iodp
)
913 return (DumpInt32(iodp
, D_DUMPEND
, DUMPENDMAGIC
));
916 /* Guts of the dump code */
918 /* Dump a whole volume */
920 DumpVolume(struct rx_call
*call
, Volume
* vp
,
921 afs_int32 fromtime
, int dumpAllDirs
)
925 struct iod
*iodp
= &iod
;
926 iod_Init(iodp
, call
);
929 code
= DumpDumpHeader(iodp
, vp
, fromtime
);
932 code
= DumpPartial(iodp
, vp
, fromtime
, dumpAllDirs
);
934 /* hack follows. Errors should be handled quite differently in this version of dump than they used to be.*/
935 if (rx_Error(iodp
->call
)) {
936 Log("1 Volser: DumpVolume: Rx call failed during dump, error %d\n",
937 rx_Error(iodp
->call
));
938 return VOLSERDUMPERROR
;
941 code
= DumpEnd(iodp
);
946 /* Dump a volume to multiple places*/
948 DumpVolMulti(struct rx_call
**calls
, int ncalls
, Volume
* vp
,
949 afs_int32 fromtime
, int dumpAllDirs
, int *codes
)
953 iod_InitMulti(&iod
, calls
, ncalls
, codes
);
956 code
= DumpDumpHeader(&iod
, vp
, fromtime
);
958 code
= DumpPartial(&iod
, vp
, fromtime
, dumpAllDirs
);
960 code
= DumpEnd(&iod
);
964 /* A partial dump (no dump header) */
966 DumpPartial(struct iod
*iodp
, Volume
* vp
,
967 afs_int32 fromtime
, int dumpAllDirs
)
971 code
= DumpVolumeHeader(iodp
, vp
);
973 code
= DumpVnodeIndex(iodp
, vp
, vLarge
, fromtime
, dumpAllDirs
);
975 code
= DumpVnodeIndex(iodp
, vp
, vSmall
, fromtime
, 0);
980 DumpVnodeIndex(struct iod
*iodp
, Volume
* vp
, VnodeClass
class,
981 afs_int32 fromtime
, int forcedump
)
984 struct VnodeClassInfo
*vcp
= &VnodeClassInfo
[class];
985 char buf
[SIZEOF_LARGEDISKVNODE
];
986 struct VnodeDiskObject
*vnode
= (struct VnodeDiskObject
*)buf
;
987 StreamHandle_t
*file
;
989 afs_sfsize_t size
, nVnodes
;
993 fdP
= IH_OPEN(vp
->vnodeIndex
[class].handle
);
994 opr_Assert(fdP
!= NULL
);
995 file
= FDH_FDOPEN(fdP
, "r+");
996 opr_Assert(file
!= NULL
);
997 size
= OS_SIZE(fdP
->fd_fd
);
998 opr_Assert(size
!= -1);
999 nVnodes
= (size
/ vcp
->diskSize
) - 1;
1001 opr_Assert((nVnodes
+ 1) * vcp
->diskSize
== size
);
1002 opr_Assert(STREAM_ASEEK(file
, vcp
->diskSize
) == 0);
1005 for (vnodeIndex
= 0;
1006 nVnodes
&& STREAM_READ(vnode
, vcp
->diskSize
, 1, file
) == 1 && !code
;
1007 nVnodes
--, vnodeIndex
++) {
1008 flag
= forcedump
|| (vnode
->serverModifyTime
>= fromtime
);
1009 /* Note: the >= test is very important since some old volumes may not have
1010 * a serverModifyTime. For an epoch dump, this results in 0>=0 test, which
1011 * does dump the file! */
1014 DumpVnode(iodp
, vnode
, V_id(vp
),
1015 bitNumberToVnodeNumber(vnodeIndex
, class), flag
);
1016 #ifndef AFS_PTHREAD_ENV
1018 IOMGR_Poll(); /* if we dont' xfr data, but scan instead, could lose conn */
1027 DumpDumpHeader(struct iod
*iodp
, Volume
* vp
,
1031 int UseLatestReadOnlyClone
= 1;
1032 afs_int32 dumpTimes
[2];
1033 iodp
->device
= vp
->device
;
1034 iodp
->parentId
= V_parentId(vp
);
1035 iodp
->dumpPartition
= vp
->partition
;
1037 code
= DumpDouble(iodp
, D_DUMPHEADER
, DUMPBEGINMAGIC
, DUMPVERSION
);
1040 DumpInt32(iodp
, 'v',
1041 UseLatestReadOnlyClone
? V_id(vp
) : V_parentId(vp
));
1043 code
= DumpString(iodp
, 'n', V_name(vp
));
1044 dumpTimes
[0] = fromtime
;
1045 switch (V_type(vp
)) {
1046 case readwriteVolume
:
1047 dumpTimes
[1] = V_updateDate(vp
); /* until last update */
1049 case readonlyVolume
:
1050 dumpTimes
[1] = V_creationDate(vp
); /* until clone was updated */
1053 /* until backup was made */
1054 dumpTimes
[1] = V_backupDate(vp
) != 0 ? V_backupDate(vp
) :
1061 code
= DumpArrayInt32(iodp
, 't', (afs_uint32
*) dumpTimes
, 2);
1066 DumpVnode(struct iod
*iodp
, struct VnodeDiskObject
*v
, VolumeId volid
,
1067 int vnodeNumber
, int dumpEverything
)
1074 if (!v
|| v
->type
== vNull
)
1077 code
= DumpDouble(iodp
, D_VNODE
, vnodeNumber
, v
->uniquifier
);
1078 if (!dumpEverything
)
1081 code
= DumpByte(iodp
, 't', (byte
) v
->type
);
1083 code
= DumpShort(iodp
, 'l', v
->linkCount
); /* May not need this */
1085 code
= DumpInt32(iodp
, 'v', v
->dataVersion
);
1087 code
= DumpInt32(iodp
, 'm', v
->unixModifyTime
);
1089 code
= DumpInt32(iodp
, 'a', v
->author
);
1091 code
= DumpInt32(iodp
, 'o', v
->owner
);
1092 if (!code
&& v
->group
)
1093 code
= DumpInt32(iodp
, 'g', v
->group
); /* default group is 0 */
1095 code
= DumpShort(iodp
, 'b', v
->modeBits
);
1097 code
= DumpInt32(iodp
, 'p', v
->parent
);
1099 code
= DumpInt32(iodp
, 's', v
->serverModifyTime
);
1100 if (v
->type
== vDirectory
) {
1101 code
= acl_HtonACL(VVnodeDiskACL(v
));
1103 Log("DumpVnode: Skipping invalid acl vnode %u (volume %"AFS_VOLID_FMT
")\n",
1104 vnodeNumber
, afs_printable_VolumeId_lu(volid
));
1108 DumpByteString(iodp
, 'A', (byte
*) VVnodeDiskACL(v
),
1111 if (VNDISK_GET_INO(v
)) {
1112 afs_sfsize_t indexlen
, disklen
;
1113 IH_INIT(ihP
, iodp
->device
, iodp
->parentId
, VNDISK_GET_INO(v
));
1116 Log("1 Volser: DumpVnode: dump: Unable to open inode %s "
1117 "for vnode %u (volume %" AFS_VOLID_FMT
"); "
1118 "not dumped, error %d\n",
1119 PrintInode(stmp
, VNDISK_GET_INO(v
)), vnodeNumber
,
1120 afs_printable_VolumeId_lu(volid
), errno
);
1122 return VOLSERREAD_DUMPERROR
;
1124 VNDISK_GET_LEN(indexlen
, v
);
1125 disklen
= FDH_SIZE(fdP
);
1126 if (indexlen
!= disklen
) {
1127 FDH_REALLYCLOSE(fdP
);
1129 Log("DumpVnode: volume %"AFS_VOLID_FMT
" "
1130 "vnode %lu has inconsistent length "
1131 "(index %lu disk %lu); aborting dump\n",
1132 afs_printable_VolumeId_lu(volid
), (unsigned long)vnodeNumber
,
1133 (unsigned long)indexlen
, (unsigned long)disklen
);
1134 return VOLSERREAD_DUMPERROR
;
1136 code
= DumpFile(iodp
, vnodeNumber
, fdP
);
1145 ProcessIndex(Volume
* vp
, VnodeClass
class, afs_foff_t
** Bufp
, int *sizep
,
1148 int i
, nVnodes
, code
;
1153 StreamHandle_t
*afile
;
1155 struct VnodeClassInfo
*vcp
= &VnodeClassInfo
[class];
1156 char buf
[SIZEOF_LARGEDISKVNODE
], zero
[SIZEOF_LARGEDISKVNODE
];
1157 struct VnodeDiskObject
*vnode
= (struct VnodeDiskObject
*)buf
;
1160 memset(zero
, 0, sizeof(zero
)); /* zero out our proto-vnode */
1161 fdP
= IH_OPEN(vp
->vnodeIndex
[class].handle
);
1164 afile
= FDH_FDOPEN(fdP
, "r+");
1168 for (i
= 0; i
< *sizep
; i
++) {
1171 STREAM_ASEEK(afile
, Buf
[i
]);
1172 code
= STREAM_READ(vnode
, vcp
->diskSize
, 1, afile
);
1174 if (vnode
->type
!= vNull
&& VNDISK_GET_INO(vnode
)) {
1177 Log("RestoreVolume %"AFS_VOLID_FMT
" "
1178 "Cleanup: Removing old vnode=%u inode=%s "
1180 afs_printable_VolumeId_lu(V_id(vp
)),
1181 bitNumberToVnodeNumber(i
, class),
1182 PrintInode(stmp
, VNDISK_GET_INO(vnode
)));
1184 IH_DEC(V_linkHandle(vp
), VNDISK_GET_INO(vnode
),
1188 STREAM_ASEEK(afile
, Buf
[i
]);
1189 (void)STREAM_WRITE(zero
, vcp
->diskSize
, 1, afile
); /* Zero it out */
1195 Log("RestoreVolume Cleanup: Removed %d inodes for volume %d\n",
1198 STREAM_FLUSH(afile
); /* ensure 0s are on the disk */
1199 OS_SYNC(afile
->str_fd
);
1201 size
= OS_SIZE(fdP
->fd_fd
);
1202 opr_Assert(size
!= -1);
1205 vcp
->diskSize
? 0 : size
- vcp
->diskSize
) >> vcp
->logSize
;
1207 Buf
= calloc(nVnodes
, sizeof(afs_foff_t
));
1209 STREAM_CLOSE(afile
);
1213 STREAM_ASEEK(afile
, offset
= vcp
->diskSize
);
1215 code
= STREAM_READ(vnode
, vcp
->diskSize
, 1, afile
);
1219 if (vnode
->type
!= vNull
&& VNDISK_GET_INO(vnode
)) {
1220 Buf
[(offset
>> vcp
->logSize
) - 1] = offset
;
1223 offset
+= vcp
->diskSize
;
1229 STREAM_CLOSE(afile
);
1236 RestoreVolume(struct rx_call
*call
, Volume
* avp
, int incremental
,
1237 struct restoreCookie
*cookie
)
1240 struct DumpHeader header
;
1241 afs_uint32 endMagic
;
1242 Error error
= 0, vupdate
;
1245 struct iod
*iodp
= &iod
;
1246 afs_foff_t
*b1
= NULL
, *b2
= NULL
;
1247 int s1
= 0, s2
= 0, delo
= 0, tdelo
;
1249 VolumeDiskData saved_header
;
1251 iod_Init(iodp
, call
);
1255 if (DoPreserveVolumeStats
) {
1256 CopyVolumeStats(&V_disk(vp
), &saved_header
);
1259 if (!ReadDumpHeader(iodp
, &header
)) {
1260 Log("1 Volser: RestoreVolume: Error reading header file for dump; aborted\n");
1261 return VOLSERREAD_DUMPERROR
;
1263 if (iod_getc(iodp
) != D_VOLUMEHEADER
) {
1264 Log("1 Volser: RestoreVolume: Volume header missing from dump; not restored\n");
1265 return VOLSERREAD_DUMPERROR
;
1267 if (ReadVolumeHeader(iodp
, &vol
) == VOLSERREAD_DUMPERROR
)
1268 return VOLSERREAD_DUMPERROR
;
1271 delo
= ProcessIndex(vp
, vLarge
, &b1
, &s1
, 0);
1273 delo
= ProcessIndex(vp
, vSmall
, &b2
, &s2
, 0);
1275 Log("1 Volser: RestoreVolume: ProcessIndex failed; not restored\n");
1276 error
= VOLSERREAD_DUMPERROR
;
1280 strncpy(vol
.name
, cookie
->name
, VOLSER_OLDMAXVOLNAME
);
1281 vol
.type
= cookie
->type
;
1282 vol
.cloneId
= cookie
->clone
;
1283 vol
.parentId
= cookie
->parent
;
1285 V_needsSalvaged(vp
) = 0;
1289 if (ReadVnodes(iodp
, vp
, 0, b1
, s1
, b2
, s2
, tdelo
)) {
1290 error
= VOLSERREAD_DUMPERROR
;
1293 tag
= iod_getc(iodp
);
1294 if (tag
!= D_VOLUMEHEADER
)
1297 if (ReadVolumeHeader(iodp
, &vol
) == VOLSERREAD_DUMPERROR
) {
1298 error
= VOLSERREAD_DUMPERROR
;
1302 if (tag
!= D_DUMPEND
|| !ReadInt32(iodp
, &endMagic
)
1303 || endMagic
!= DUMPENDMAGIC
) {
1304 Log("1 Volser: RestoreVolume: End of dump not found; restore aborted\n");
1305 error
= VOLSERREAD_DUMPERROR
;
1310 if (iod_getc(iodp
) != EOF
) {
1311 Log("1 Volser: RestoreVolume: Unrecognized postamble in dump; restore aborted\n");
1312 error
= VOLSERREAD_DUMPERROR
;
1317 delo
= ProcessIndex(vp
, vLarge
, &b1
, &s1
, 1);
1319 delo
= ProcessIndex(vp
, vSmall
, &b2
, &s2
, 1);
1321 error
= VOLSERREAD_DUMPERROR
;
1327 if (DoPreserveVolumeStats
) {
1328 CopyVolumeStats(&saved_header
, &vol
);
1330 ClearVolumeStats(&vol
);
1332 if (V_needsSalvaged(vp
)) {
1333 /* needsSalvaged may have been set while we tried to write volume data.
1334 * prevent it from getting overwritten. */
1335 vol
.needsSalvaged
= V_needsSalvaged(vp
);
1337 CopyVolumeHeader(&vol
, &V_disk(vp
));
1338 V_destroyMe(vp
) = 0;
1339 VUpdateVolume(&vupdate
, vp
);
1341 Log("1 Volser: RestoreVolume: Unable to rewrite volume header; restore aborted\n");
1342 error
= VOLSERREAD_DUMPERROR
;
1346 /* Free the malloced space above */
1355 ReadVnodes(struct iod
*iodp
, Volume
* vp
, int incremental
,
1356 afs_foff_t
* Lbuf
, afs_int32 s1
, afs_foff_t
* Sbuf
, afs_int32 s2
,
1359 afs_int32 vnodeNumber
;
1360 char buf
[SIZEOF_LARGEDISKVNODE
];
1362 struct VnodeDiskObject
*vnode
= (struct VnodeDiskObject
*)buf
;
1363 struct VnodeDiskObject oldvnode
;
1366 struct VnodeClassInfo
*vcp
;
1369 Inode nearInode AFS_UNUSED
;
1370 afs_int32 critical
= 0;
1373 tag
= iod_getc(iodp
);
1374 V_pref(vp
, nearInode
);
1375 while (tag
== D_VNODE
) {
1378 memset(buf
, 0, sizeof(buf
));
1379 if (!ReadInt32(iodp
, (afs_uint32
*) & vnodeNumber
))
1382 if (!ReadInt32(iodp
, &vnode
->uniquifier
))
1383 return VOLSERREAD_DUMPERROR
;
1385 while ((tag
= iod_getc(iodp
)) > D_MAX
&& tag
!= EOF
) {
1391 vnode
->type
= (VnodeType
) iod_getc(iodp
);
1396 if (!ReadShort(iodp
, &tlc
))
1397 return VOLSERREAD_DUMPERROR
;
1398 vnode
->linkCount
= (signed int)tlc
;
1402 if (!ReadInt32(iodp
, &vnode
->dataVersion
))
1403 return VOLSERREAD_DUMPERROR
;
1406 if (!ReadInt32(iodp
, &vnode
->unixModifyTime
))
1407 return VOLSERREAD_DUMPERROR
;
1410 if (!ReadInt32(iodp
, &vnode
->serverModifyTime
))
1411 return VOLSERREAD_DUMPERROR
;
1414 if (!ReadInt32(iodp
, &vnode
->author
))
1415 return VOLSERREAD_DUMPERROR
;
1418 if (!ReadInt32(iodp
, &vnode
->owner
))
1419 return VOLSERREAD_DUMPERROR
;
1422 if (!ReadInt32(iodp
, (afs_uint32
*) & vnode
->group
))
1423 return VOLSERREAD_DUMPERROR
;
1426 unsigned short modeBits
;
1427 if (!ReadShort(iodp
, &modeBits
))
1428 return VOLSERREAD_DUMPERROR
;
1429 vnode
->modeBits
= (unsigned int)modeBits
;
1433 if (!ReadInt32(iodp
, &vnode
->parent
))
1434 return VOLSERREAD_DUMPERROR
;
1437 nbytes
= ReadByteString(iodp
, (byte
*) VVnodeDiskACL(vnode
),
1438 VAclDiskSize(vnode
));
1439 if (nbytes
!= VAclDiskSize(vnode
)) {
1440 Log("ReadVnodes: could not read acl for vnode %lu in dump.\n",
1441 (unsigned long)vnodeNumber
);
1442 return VOLSERREAD_DUMPERROR
;
1444 if (acl_NtohACL(VVnodeDiskACL(vnode
)) != 0) {
1445 Log("ReadVnodes: invalid acl for vnode %lu in dump.\n",
1446 (unsigned long)vnodeNumber
);
1447 return VOLSERREAD_DUMPERROR
;
1454 afs_fsize_t vnodeLength
;
1457 Log("Volser: ReadVnodes: warning: ignoring duplicate "
1458 "file entries for vnode %lu in dump\n",
1459 (unsigned long)vnodeNumber
);
1460 volser_WriteFile(vnodeNumber
, iodp
, NULL
, tag
, &error
);
1466 IH_CREATE_INIT(V_linkHandle(vp
), V_device(vp
),
1467 VPartitionPath(V_partition(vp
)), nearInode
,
1468 V_parentId(vp
), vnodeNumber
,
1469 vnode
->uniquifier
, vnode
->dataVersion
);
1471 Log("1 Volser: ReadVnodes: IH_CREATE: %s - restore aborted\n",
1472 afs_error_message(errno
));
1473 V_needsSalvaged(vp
) = 1;
1474 return VOLSERREAD_DUMPERROR
;
1478 VNDISK_SET_INO(vnode
, ino
);
1479 fdP
= IH_OPEN(tmpH
);
1481 Log("1 Volser: ReadVnodes: IH_OPEN: %s - restore aborted\n",
1482 afs_error_message(errno
));
1484 V_needsSalvaged(vp
) = 1;
1485 return VOLSERREAD_DUMPERROR
;
1488 volser_WriteFile(vnodeNumber
, iodp
, fdP
, tag
, &error
);
1489 VNDISK_SET_LEN(vnode
, vnodeLength
);
1490 FDH_REALLYCLOSE(fdP
);
1493 Log("1 Volser: ReadVnodes: IDEC inode %llu\n",
1494 (afs_uintmax_t
) ino
);
1495 IH_DEC(V_linkHandle(vp
), ino
, V_parentId(vp
));
1496 V_needsSalvaged(vp
) = 1;
1497 return VOLSERREAD_DUMPERROR
;
1505 if (!HandleUnknownTag(iodp
, tag
, 2, critical
))
1506 return VOLSERREAD_DUMPERROR
;
1510 class = vnodeIdToClass(vnodeNumber
);
1511 vcp
= &VnodeClassInfo
[class];
1513 /* Mark this vnode as in this dump - so we don't delete it later */
1515 idx
= (vnodeIndexOffset(vcp
, vnodeNumber
) >> vcp
->logSize
) - 1;
1516 if (class == vLarge
) {
1517 if (Lbuf
&& (idx
< s1
))
1520 if (Sbuf
&& (idx
< s2
))
1526 FdHandle_t
*fdP
= IH_OPEN(vp
->vnodeIndex
[class].handle
);
1528 Log("1 Volser: ReadVnodes: Error opening vnode index: %s; restore aborted\n",
1529 afs_error_message(errno
));
1530 V_needsSalvaged(vp
) = 1;
1531 return VOLSERREAD_DUMPERROR
;
1533 if (FDH_PREAD(fdP
, &oldvnode
, sizeof(oldvnode
), vnodeIndexOffset(vcp
, vnodeNumber
)) ==
1535 if (oldvnode
.type
!= vNull
&& VNDISK_GET_INO(&oldvnode
)) {
1536 IH_DEC(V_linkHandle(vp
), VNDISK_GET_INO(&oldvnode
),
1540 vnode
->vnodeMagic
= vcp
->magic
;
1541 if (FDH_PWRITE(fdP
, vnode
, vcp
->diskSize
, vnodeIndexOffset(vcp
, vnodeNumber
)) != vcp
->diskSize
) {
1542 Log("1 Volser: ReadVnodes: Error writing vnode index: %s; restore aborted\n",
1543 afs_error_message(errno
));
1544 FDH_REALLYCLOSE(fdP
);
1545 V_needsSalvaged(vp
) = 1;
1546 return VOLSERREAD_DUMPERROR
;
1551 iod_ungetc(iodp
, tag
);
1557 /* called with disk file only. Note that we don't have to worry about rx_Read
1558 * needing to read an ungetc'd character, since the ReadInt32 will have read
1561 * if handleP == NULL, don't write the file anywhere; just read and discard
1565 volser_WriteFile(int vn
, struct iod
*iodp
, FdHandle_t
* handleP
, int tag
,
1570 afs_fsize_t filesize
;
1571 afs_fsize_t written
= 0;
1579 afs_uint32 filesize_high
= 0L, filesize_low
= 0L;
1581 if (!ReadInt32(iodp
, &filesize_high
)) {
1586 if (!ReadInt32(iodp
, &filesize_low
)) {
1590 FillInt64(filesize
, filesize_high
, filesize_low
);
1597 for (nbytes
= filesize
; nbytes
; nbytes
-= size
) {
1601 if ((code
= iod_Read(iodp
, (char *) p
, size
)) != size
) {
1602 Log("1 Volser: WriteFile: Error reading dump file %d size=%llu nbytes=%u (%d of %u): %s; restore aborted\n", vn
, (afs_uintmax_t
) filesize
, nbytes
, code
, (unsigned)size
, afs_error_message(errno
));
1607 nBytes
= FDH_PWRITE(handleP
, p
, size
, written
);
1610 if (nBytes
!= size
) {
1611 Log("1 Volser: WriteFile: Error writing (%u) bytes to vnode %d; %s; restore aborted\n", (int)(nBytes
& 0xffffffff), vn
, afs_error_message(errno
));
1622 ReadDumpHeader(struct iod
*iodp
, struct DumpHeader
*hp
)
1625 afs_uint32 beginMagic
;
1626 afs_int32 critical
= 0;
1627 if (iod_getc(iodp
) != D_DUMPHEADER
|| !ReadInt32(iodp
, &beginMagic
)
1628 || !ReadInt32(iodp
, (afs_uint32
*) & hp
->version
)
1629 || beginMagic
!= DUMPBEGINMAGIC
)
1633 while ((tag
= iod_getc(iodp
)) > D_MAX
) {
1634 unsigned short arrayLength
;
1640 if (!ReadInt32(iodp
, &hp
->volumeId
))
1644 ReadString(iodp
, hp
->volumeName
, sizeof(hp
->volumeName
));
1647 if (!ReadShort(iodp
, &arrayLength
))
1649 hp
->nDumpTimes
= (arrayLength
>> 1);
1650 for (i
= 0; i
< hp
->nDumpTimes
; i
++)
1651 if (!ReadInt32(iodp
, (afs_uint32
*) & hp
->dumpTimes
[i
].from
)
1652 || !ReadInt32(iodp
, (afs_uint32
*) & hp
->dumpTimes
[i
].to
))
1659 if (!HandleUnknownTag(iodp
, tag
, 0, critical
))
1660 return VOLSERREAD_DUMPERROR
;
1663 if (!hp
->volumeId
|| !hp
->nDumpTimes
) {
1666 iod_ungetc(iodp
, tag
);
1671 /* ----- Below are the calls that calculate dump size ----- */
1674 SizeDumpVolumeHeader(struct iod
*iodp
, Volume
* vp
,
1675 struct volintSize
*v_size
)
1678 static char nullString
[1] = ""; /*The ``contents'' of motd */
1681 /* if (!code) code = DumpTag(iodp, D_VOLUMEHEADER); */
1682 FillInt64(addvar
,0, 1);
1683 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1684 /* if (!code) {code = DumpInt32(iodp, 'i',V_id(vp));} */
1685 FillInt64(addvar
,0, 5);
1686 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1687 /* if (!code) code = DumpInt32(iodp, 'v',V_stamp(vp).version); */
1688 FillInt64(addvar
,0, 5);
1689 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1690 /* if (!code) code = DumpString(iodp, 'n',V_name(vp)); */
1691 FillInt64(addvar
,0, (2 + strlen(V_name(vp
))));
1692 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1693 /* if (!code) code = DumpBool(iodp, 's',V_inService(vp)); */
1694 FillInt64(addvar
,0, 2);
1695 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1696 /* if (!code) code = DumpBool(iodp, 'b',V_blessed(vp)); */
1697 FillInt64(addvar
,0, 2);
1698 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1699 /* if (!code) code = DumpInt32(iodp, 'u',V_uniquifier(vp)); */
1700 FillInt64(addvar
,0, 5);
1701 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1702 /* if (!code) code = DumpByte(iodp, 't',(byte)V_type(vp)); */
1703 FillInt64(addvar
,0, 2);
1704 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1705 /* if (!code){ code = DumpInt32(iodp, 'p',V_parentId(vp));} */
1706 FillInt64(addvar
,0, 5);
1707 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1708 /* if (!code) code = DumpInt32(iodp, 'c',V_cloneId(vp)); */
1709 FillInt64(addvar
,0, 5);
1710 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1711 /* if (!code) code = DumpInt32(iodp, 'q',V_maxquota(vp)); */
1712 FillInt64(addvar
,0, 5);
1713 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1714 /* if (!code) code = DumpInt32(iodp, 'm',V_minquota(vp)); */
1715 FillInt64(addvar
,0, 5);
1716 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1717 /* if (!code) code = DumpInt32(iodp, 'd',V_diskused(vp)); */
1718 FillInt64(addvar
,0, 5);
1719 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1720 /* if (!code) code = DumpInt32(iodp, 'f',V_filecount(vp)); */
1721 FillInt64(addvar
,0, 5);
1722 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1723 /* if (!code) code = DumpInt32(iodp, 'a', V_accountNumber(vp)); */
1724 FillInt64(addvar
,0, 5);
1725 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1726 /* if (!code) code = DumpInt32(iodp, 'o', V_owner(vp)); */
1727 FillInt64(addvar
,0, 5);
1728 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1729 /* if (!code) code = DumpInt32(iodp, 'C',V_creationDate(vp)); /\* Rw volume creation date *\/ */
1730 FillInt64(addvar
,0, 5);
1731 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1732 /* if (!code) code = DumpInt32(iodp, 'A',V_accessDate(vp)); */
1733 FillInt64(addvar
,0, 5);
1734 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1735 /* if (!code) code = DumpInt32(iodp, 'U',V_updateDate(vp)); */
1736 FillInt64(addvar
,0, 5);
1737 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1738 /* if (!code) code = DumpInt32(iodp, 'E',V_expirationDate(vp)); */
1739 FillInt64(addvar
,0, 5);
1740 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1741 /* if (!code) code = DumpInt32(iodp, 'B',V_backupDate(vp)); /\* Rw volume backup clone date *\/ */
1742 FillInt64(addvar
,0, 5);
1743 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1744 /* if (!code) code = DumpString(iodp, 'O',V_offlineMessage(vp)); */
1745 FillInt64(addvar
,0, (2 + strlen(V_offlineMessage(vp
))));
1746 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1748 /* * We do NOT dump the detailed volume statistics residing in the old */
1749 /* * motd field, since we cannot tell from the info in a dump whether */
1750 /* * statistics data has been put there. Instead, we dump a null string, */
1751 /* * just as if that was what the motd contained. */
1753 /* if (!code) code = DumpString(iodp, 'M', nullString); */
1754 FillInt64(addvar
,0, (2 + strlen(nullString
)));
1755 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1756 /* if (!code) code = DumpArrayInt32(iodp, 'W', (afs_uint32 *)V_weekUse(vp), sizeof(V_weekUse(vp))/sizeof(V_weekUse(vp)[0])); */
1757 FillInt64(addvar
,0, (3 + 4 * (sizeof(V_weekUse(vp
)) / sizeof(V_weekUse(vp
)[0]))));
1758 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1759 /* if (!code) code = DumpInt32(iodp, 'D', V_dayUseDate(vp)); */
1760 FillInt64(addvar
,0, 5);
1761 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1762 /* if (!code) code = DumpInt32(iodp, 'Z', V_dayUse(vp)); */
1763 FillInt64(addvar
,0, 5);
1764 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1769 SizeDumpEnd(struct iod
*iodp
, struct volintSize
*v_size
)
1773 FillInt64(addvar
,0, 5);
1774 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1779 SizeDumpVolume(struct rx_call
*call
, Volume
* vp
,
1780 afs_int32 fromtime
, int dumpAllDirs
,
1781 struct volintSize
*v_size
)
1784 struct iod
*iodp
= (struct iod
*)0;
1785 /* iod_Init(iodp, call); */
1788 code
= SizeDumpDumpHeader(iodp
, vp
, fromtime
, v_size
);
1790 code
= SizeDumpPartial(iodp
, vp
, fromtime
, dumpAllDirs
, v_size
);
1792 code
= SizeDumpEnd(iodp
, v_size
);
1798 SizeDumpDumpHeader(struct iod
*iodp
, Volume
* vp
,
1799 afs_int32 fromtime
, struct volintSize
*v_size
)
1802 /* int UseLatestReadOnlyClone = 1; */
1803 /* afs_int32 dumpTimes[2]; */
1805 /* iodp->device = vp->device; */
1806 /* iodp->parentId = V_parentId(vp); */
1807 /* iodp->dumpPartition = vp->partition; */
1809 ZeroInt64(v_size
->dump_size
); /* initialize the size */
1810 /* if (!code) code = DumpDouble(iodp, D_DUMPHEADER, DUMPBEGINMAGIC, DUMPVERSION); */
1811 FillInt64(addvar
,0, 9);
1812 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1813 /* if (!code) code = DumpInt32(iodp, 'v', UseLatestReadOnlyClone? V_id(vp): V_parentId(vp)); */
1814 FillInt64(addvar
,0, 5);
1815 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1816 /* if (!code) code = DumpString(iodp, 'n',V_name(vp)); */
1817 FillInt64(addvar
,0, (2 + strlen(V_name(vp
))));
1818 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1819 /* dumpTimes[0] = fromtime; */
1820 /* dumpTimes[1] = V_backupDate(vp); /\* Until the time the clone was made *\/ */
1821 /* if (!code) code = DumpArrayInt32(iodp, 't', (afs_uint32 *)dumpTimes, 2); */
1822 FillInt64(addvar
,0, (3 + 4 * 2));
1823 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1828 SizeDumpVnode(struct iod
*iodp
, struct VnodeDiskObject
*v
, VolumeId volid
,
1829 int vnodeNumber
, int dumpEverything
,
1830 struct volintSize
*v_size
)
1835 if (!v
|| v
->type
== vNull
)
1837 /* if (!code) code = DumpDouble(iodp, D_VNODE, vnodeNumber, v->uniquifier); */
1838 FillInt64(addvar
,0, 9);
1839 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1840 if (!dumpEverything
)
1842 /* if (!code) code = DumpByte(iodp, 't',(byte)v->type); */
1843 FillInt64(addvar
,0, 2);
1844 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1845 /* if (!code) code = DumpShort(iodp, 'l', v->linkCount); /\* May not need this *\/ */
1846 FillInt64(addvar
,0, 3);
1847 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1848 /* if (!code) code = DumpInt32(iodp, 'v', v->dataVersion); */
1849 FillInt64(addvar
,0, 5);
1850 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1851 /* if (!code) code = DumpInt32(iodp, 'm', v->unixModifyTime); */
1852 FillInt64(addvar
,0, 5);
1853 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1854 /* if (!code) code = DumpInt32(iodp, 'a', v->author); */
1855 FillInt64(addvar
,0, 5);
1856 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1857 /* if (!code) code = DumpInt32(iodp, 'o', v->owner); */
1858 FillInt64(addvar
,0, 5);
1859 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1860 /* if (!code && v->group) code = DumpInt32(iodp, 'g', v->group); /\* default group is 0 *\/ */
1862 FillInt64(addvar
,0, 5);
1863 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1865 /* if (!code) code = DumpShort(iodp, 'b', v->modeBits); */
1866 FillInt64(addvar
,0, 3);
1867 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1868 /* if (!code) code = DumpInt32(iodp, 'p', v->parent); */
1869 FillInt64(addvar
,0, 5);
1870 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1871 /* if (!code) code = DumpInt32(iodp, 's', v->serverModifyTime); */
1872 FillInt64(addvar
,0, 5);
1873 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1874 if (v
->type
== vDirectory
) {
1875 /* acl_HtonACL(VVnodeDiskACL(v)); */
1876 /* if (!code) code = DumpByteString(iodp, 'A', (byte *) VVnodeDiskACL(v), VAclDiskSize(v)); */
1877 FillInt64(addvar
,0, (1 + VAclDiskSize(v
)));
1878 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1881 if (VNDISK_GET_INO(v
)) {
1882 VNDISK_GET_LEN(addvar
, v
);
1883 if (v
->vn_length_hi
)
1887 AddUInt64(v_size
->dump_size
, addvar
, &v_size
->dump_size
);
1892 /* A partial dump (no dump header) */
1894 SizeDumpPartial(struct iod
*iodp
, Volume
* vp
,
1895 afs_int32 fromtime
, int dumpAllDirs
,
1896 struct volintSize
*v_size
)
1900 code
= SizeDumpVolumeHeader(iodp
, vp
, v_size
);
1903 SizeDumpVnodeIndex(iodp
, vp
, vLarge
, fromtime
, dumpAllDirs
,
1906 code
= SizeDumpVnodeIndex(iodp
, vp
, vSmall
, fromtime
, 0, v_size
);
1911 SizeDumpVnodeIndex(struct iod
*iodp
, Volume
* vp
, VnodeClass
class,
1912 afs_int32 fromtime
, int forcedump
,
1913 struct volintSize
*v_size
)
1916 struct VnodeClassInfo
*vcp
= &VnodeClassInfo
[class];
1917 char buf
[SIZEOF_LARGEDISKVNODE
];
1918 struct VnodeDiskObject
*vnode
= (struct VnodeDiskObject
*)buf
;
1919 StreamHandle_t
*file
;
1921 afs_sfsize_t size
, nVnodes
;
1925 fdP
= IH_OPEN(vp
->vnodeIndex
[class].handle
);
1926 opr_Assert(fdP
!= NULL
);
1927 file
= FDH_FDOPEN(fdP
, "r+");
1928 opr_Assert(file
!= NULL
);
1929 size
= OS_SIZE(fdP
->fd_fd
);
1930 opr_Assert(size
!= -1);
1931 nVnodes
= (size
/ vcp
->diskSize
) - 1;
1933 opr_Assert((nVnodes
+ 1) * vcp
->diskSize
== size
);
1934 opr_Assert(STREAM_ASEEK(file
, vcp
->diskSize
) == 0);
1937 for (vnodeIndex
= 0;
1938 nVnodes
&& STREAM_READ(vnode
, vcp
->diskSize
, 1, file
) == 1 && !code
;
1939 nVnodes
--, vnodeIndex
++) {
1940 flag
= forcedump
|| (vnode
->serverModifyTime
>= fromtime
);
1941 /* Note: the >= test is very important since some old volumes may not have
1942 * a serverModifyTime. For an epoch dump, this results in 0>=0 test, which
1943 * does dump the file! */
1946 SizeDumpVnode(iodp
, vnode
, V_id(vp
),
1947 bitNumberToVnodeNumber(vnodeIndex
, class), flag
,