/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
+#include <roken.h>
-#include <sys/types.h>
#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#else
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#endif
-#include <sys/stat.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else /* AFS_PTHREAD_ENV */
-#include <afs/assert.h>
-#endif /* AFS_PTHREAD_ENV */
-#include <rx/xdr.h>
+
+#include <afs/opr.h>
#include <rx/rx.h>
+#include <rx/rx_queue.h>
#include <afs/afsint.h>
#include <afs/nfs.h>
#include <afs/errors.h>
#include <afs/vnode.h>
#include <afs/volume.h>
#include <afs/partition.h>
-#include "dump.h"
#include <afs/daemon_com.h>
#include <afs/fssync.h>
#include <afs/acl.h>
#include <afs/com_err.h>
#include <afs/vol_prototypes.h>
+
+#include "dump.h"
#include "volser.h"
#include "volint.h"
#include "dumpstuff.h"
/*@printflike@*/ extern void Log(const char *format, ...);
extern int DoLogging;
+extern int DoPreserveVolumeStats;
/* Forward Declarations */
-static int DumpDumpHeader(register struct iod *iodp, register Volume * vp,
+static int DumpDumpHeader(struct iod *iodp, Volume * vp,
afs_int32 fromtime);
-static int DumpPartial(register struct iod *iodp, register Volume * vp,
+static int DumpPartial(struct iod *iodp, Volume * vp,
afs_int32 fromtime, int dumpAllDirs);
-static int DumpVnodeIndex(register struct iod *iodp, Volume * vp,
+static int DumpVnodeIndex(struct iod *iodp, Volume * vp,
VnodeClass class, afs_int32 fromtime,
int forcedump);
-static int DumpVnode(register struct iod *iodp, struct VnodeDiskObject *v,
- int volid, int vnodeNumber, int dumpEverything);
-static int ReadDumpHeader(register struct iod *iodp, struct DumpHeader *hp);
-static int ReadVnodes(register struct iod *iodp, Volume * vp, int incremental,
- afs_int32 * Lbuf, afs_int32 s1, afs_int32 * Sbuf,
+static int DumpVnode(struct iod *iodp, struct VnodeDiskObject *v,
+ VolumeId volid, int vnodeNumber, int dumpEverything);
+static int ReadDumpHeader(struct iod *iodp, struct DumpHeader *hp);
+static int ReadVnodes(struct iod *iodp, Volume * vp, int incremental,
+ afs_foff_t * Lbuf, afs_int32 s1, afs_foff_t * Sbuf,
afs_int32 s2, afs_int32 delo);
static afs_fsize_t volser_WriteFile(int vn, struct iod *iodp,
FdHandle_t * handleP, int tag,
Error * status);
-static int SizeDumpDumpHeader(register struct iod *iodp, register Volume * vp,
+static int SizeDumpDumpHeader(struct iod *iodp, Volume * vp,
afs_int32 fromtime,
- register struct volintSize *size);
-static int SizeDumpPartial(register struct iod *iodp, register Volume * vp,
+ struct volintSize *size);
+static int SizeDumpPartial(struct iod *iodp, Volume * vp,
afs_int32 fromtime, int dumpAllDirs,
- register struct volintSize *size);
-static int SizeDumpVnodeIndex(register struct iod *iodp, Volume * vp,
+ struct volintSize *size);
+static int SizeDumpVnodeIndex(struct iod *iodp, Volume * vp,
VnodeClass class, afs_int32 fromtime,
int forcedump,
- register struct volintSize *size);
-static int SizeDumpVnode(register struct iod *iodp, struct VnodeDiskObject *v,
- int volid, int vnodeNumber, int dumpEverything,
- register struct volintSize *size);
+ struct volintSize *size);
+static int SizeDumpVnode(struct iod *iodp, struct VnodeDiskObject *v,
+ VolumeId volid, int vnodeNumber, int dumpEverything,
+ struct volintSize *size);
#define MAX_SECTIONS 3
-#define MIN_TLV_TAG 5
+
+/* The TLV range must start above D_MAX */
+#define MIN_TLV_TAG 21
#define MAX_TLV_TAG 0x60
#define MAX_STANDARD_TAG 0x7a
static afs_uint32 oldtags[MAX_SECTIONS][16];
}
static void
-iod_Init(register struct iod *iodp, register struct rx_call *call)
+iod_Init(struct iod *iodp, struct rx_call *call)
{
iodp->call = call;
iodp->haveOldChar = 0;
/* For the single dump case, it's ok to just return the "bytes written"
* that rx_Write returns, since all the callers of iod_Write abort when
* the returned value is less than they expect. For the multi dump case,
- * I don't think we want half the replicas to go bad just because one
- * connection timed out, but if they all time out, then we should give up.
+ * I don't think we want half the replicas to go bad just because one
+ * connection timed out, but if they all time out, then we should give up.
*/
static int
iod_Write(struct iod *iodp, char *buf, int nbytes)
int code, i;
int one_success = 0;
- assert((iodp->call && iodp->ncalls == 1 && !iodp->calls)
+ opr_Assert((iodp->call && iodp->ncalls == 1 && !iodp->calls)
|| (!iodp->call && iodp->ncalls >= 1 && iodp->calls));
if (iodp->call) {
}
static int
-iod_getc(register struct iod *iodp)
+iod_getc(struct iod *iodp)
{
unsigned char t;
}
static int
-ReadShort(register struct iod *iodp, register unsigned short *sp)
+ReadShort(struct iod *iodp, unsigned short *sp)
{
- register int b1, b0;
+ int b1, b0;
b1 = iod_getc(iodp);
if (b1 == EOF)
return 0;
}
static int
-ReadInt32(register struct iod *iodp, afs_uint32 * lp)
+ReadInt32(struct iod *iodp, afs_uint32 * lp)
{
- afs_uint32 register b3, b2, b1, b0;
+ afs_uint32 b3, b2, b1, b0;
b3 = iod_getc(iodp);
if (b3 == EOF)
return 0;
}
static void
-ReadString(register struct iod *iodp, register char *to, register int maxa)
+ReadString(struct iod *iodp, char *to, int maxa)
{
- register int c;
+ int c;
*to = '\0';
if (maxa == 0)
}
}
-static void
-ReadByteString(register struct iod *iodp, register byte * to,
- register int size)
+static int
+ReadByteString(struct iod *iodp, byte * to, int size)
{
- while (size--)
- *to++ = iod_getc(iodp);
+ int nbytes = 0;
+ int c;
+
+ while (size-- > 0 && (c = iod_getc(iodp)) != EOF) {
+ *to++ = c;
+ nbytes++;
+ }
+ return nbytes;
}
/*
* returns 1 on success and 0 otherwise
*/
static afs_int32
-ReadStandardTagLen(register struct iod *iodp, unsigned char tag, afs_int32 section,
+ReadStandardTagLen(struct iod *iodp, unsigned char tag, afs_int32 section,
afs_size_t *length)
{
afs_int32 code, i;
afs_uint32 off = tag >> 5;
afs_uint32 mask = 1 << (tag & 0x1f);
- unsigned char len, buf[8], *p;
+ int len;
+ unsigned char buf[8], *p;
if (!oldtagsInited)
initNonStandardTags();
}
if (tag <= MAX_TLV_TAG) {
len = iod_getc(iodp);
- if (len < 128)
+ if (len == EOF)
+ return VOLSERDUMPERROR;
+ else if (len < 128)
*length = len;
else {
len &= 0x7f;
static char skipbuf[256];
static afs_int32
-SkipData(register struct iod *iodp, afs_size_t length)
+SkipData(struct iod *iodp, afs_size_t length)
{
while (length > 256) {
if (iod_Read(iodp, (char *)&skipbuf, 256) != 256)
}
static int
-ReadVolumeHeader(register struct iod *iodp, VolumeDiskData * vol)
+ReadVolumeHeader(struct iod *iodp, VolumeDiskData * vol)
{
- register int tag;
+ int tag;
afs_uint32 trash;
afs_int32 critical = 0;
memset(vol, 0, sizeof(*vol));
}
static int
-DumpTag(register struct iod *iodp, register int tag)
+DumpTag(struct iod *iodp, int tag)
{
char p;
}
static int
-DumpByte(register struct iod *iodp, char tag, byte value)
+DumpByte(struct iod *iodp, char tag, byte value)
{
char tbuffer[2];
- register byte *p = (unsigned char *)tbuffer;
+ byte *p = (unsigned char *)tbuffer;
*p++ = tag;
*p = value;
return ((iod_Write(iodp, tbuffer, 2) == 2) ? 0 : VOLSERDUMPERROR);
}
-#define putint32(p, v) *p++ = v>>24, *p++ = v>>16, *p++ = v>>8, *p++ = v
-#define putshort(p, v) *p++ = v>>8, *p++ = v
+#define afs_putint32(p, v) *p++ = v>>24, *p++ = v>>16, *p++ = v>>8, *p++ = v
+#define afs_putshort(p, v) *p++ = v>>8, *p++ = v
static int
-DumpDouble(register struct iod *iodp, char tag, register afs_uint32 value1,
- register afs_uint32 value2)
+DumpDouble(struct iod *iodp, char tag, afs_uint32 value1,
+ afs_uint32 value2)
{
char tbuffer[9];
- register byte *p = (unsigned char *)tbuffer;
+ byte *p = (unsigned char *)tbuffer;
*p++ = tag;
- putint32(p, value1);
- putint32(p, value2);
+ afs_putint32(p, value1);
+ afs_putint32(p, value2);
return ((iod_Write(iodp, tbuffer, 9) == 9) ? 0 : VOLSERDUMPERROR);
}
static int
-DumpInt32(register struct iod *iodp, char tag, register afs_uint32 value)
+DumpInt32(struct iod *iodp, char tag, afs_uint32 value)
{
char tbuffer[5];
- register byte *p = (unsigned char *)tbuffer;
+ byte *p = (unsigned char *)tbuffer;
*p++ = tag;
- putint32(p, value);
+ afs_putint32(p, value);
return ((iod_Write(iodp, tbuffer, 5) == 5) ? 0 : VOLSERDUMPERROR);
}
static int
-DumpArrayInt32(register struct iod *iodp, char tag,
- register afs_uint32 * array, register int nelem)
+DumpArrayInt32(struct iod *iodp, char tag,
+ afs_uint32 * array, int nelem)
{
char tbuffer[4];
- register afs_uint32 v;
+ afs_uint32 v;
int code = 0;
- register byte *p = (unsigned char *)tbuffer;
+ byte *p = (unsigned char *)tbuffer;
*p++ = tag;
- putshort(p, nelem);
+ afs_putshort(p, nelem);
code = iod_Write(iodp, tbuffer, 3);
if (code != 3)
return VOLSERDUMPERROR;
p = (unsigned char *)tbuffer;
v = *array++; /*this was register */
- putint32(p, v);
+ afs_putint32(p, v);
code = iod_Write(iodp, tbuffer, 4);
if (code != 4)
return VOLSERDUMPERROR;
}
static int
-DumpShort(register struct iod *iodp, char tag, unsigned int value)
+DumpShort(struct iod *iodp, char tag, unsigned int value)
{
char tbuffer[3];
- register byte *p = (unsigned char *)tbuffer;
+ byte *p = (unsigned char *)tbuffer;
*p++ = tag;
*p++ = value >> 8;
*p = value;
}
static int
-DumpBool(register struct iod *iodp, char tag, unsigned int value)
+DumpBool(struct iod *iodp, char tag, unsigned int value)
{
char tbuffer[2];
- register byte *p = (unsigned char *)tbuffer;
+ byte *p = (unsigned char *)tbuffer;
*p++ = tag;
*p = value;
return ((iod_Write(iodp, tbuffer, 2) == 2) ? 0 : VOLSERDUMPERROR);
}
static int
-DumpString(register struct iod *iodp, char tag, register char *s)
+DumpString(struct iod *iodp, char tag, char *s)
{
- register int n;
+ int n;
int code = 0;
code = iod_Write(iodp, &tag, 1);
if (code != 1)
}
static int
-DumpByteString(register struct iod *iodp, char tag, register byte * bs,
- register int nbytes)
+DumpByteString(struct iod *iodp, char tag, byte * bs,
+ int nbytes)
{
int code = 0;
}
static afs_int32
-DumpStandardTag(register struct iod *iodp, char tag, afs_uint32 section)
+DumpStandardTag(struct iod *iodp, char tag, afs_uint32 section)
{
afs_int32 code;
afs_uint32 off = tag >> 5;
return VOLSERDUMPERROR;
}
code = iod_Write(iodp, &tag, 1);
+ if (code != 1)
+ return VOLSERDUMPERROR;
return 0;
}
AFS_UNUSED
static afs_int32
-DumpStandardTagLen(register struct iod *iodp, char tag, afs_uint32 section,
+DumpStandardTagLen(struct iod *iodp, char tag, afs_uint32 section,
afs_size_t length)
{
char buf[10];
{
int code = 0, error = 0;
afs_int32 pad = 0;
- afs_int32 offset = 0;
+ afs_foff_t offset = 0;
afs_sfsize_t nbytes, howBig;
ssize_t n;
size_t howMany;
- afs_foff_t lcode = 0;
+ afs_foff_t howFar = 0;
byte *p;
afs_uint32 hi, lo;
+ afs_ino_str_t stmp;
#ifndef AFS_NT40_ENV
struct afs_stat status;
+#else
+ LARGE_INTEGER fileSize;
#endif
- afs_sfsize_t size;
#ifdef AFS_AIX_ENV
#include <sys/statfs.h>
#if defined(AFS_AIX52_ENV)
#endif
#ifdef AFS_NT40_ENV
- howBig = _filelength(handleP->fd_fd);
+ if (!GetFileSizeEx(handleP->fd_fd, &fileSize)) {
+ Log("DumpFile: GetFileSizeEx returned error code %d on descriptor %d\n", GetLastError(), handleP->fd_fd);
+ return VOLSERDUMPERROR;
+ }
+ howBig = fileSize.QuadPart;
howMany = 4096;
#else
howBig = status.st_size;
#ifdef AFS_AIX_ENV
- /* Unfortunately in AIX valuable fields such as st_blksize are
+ /* Unfortunately in AIX valuable fields such as st_blksize are
* gone from the stat structure.
*/
#if defined(AFS_AIX52_ENV)
#endif /* AFS_NT40_ENV */
- size = FDH_SIZE(handleP);
- SplitInt64(size, hi, lo);
+ SplitInt64(howBig, hi, lo);
if (hi == 0L) {
code = DumpInt32(iodp, 'f', lo);
} else {
return VOLSERDUMPERROR;
}
- for (nbytes = size; (nbytes && !error); nbytes -= howMany) {
+ for (nbytes = howBig; (nbytes && !error); nbytes -= howMany) {
if (nbytes < howMany)
howMany = nbytes;
- /* Read the data - unless we know we can't */
- n = (lcode ? 0 : FDH_READ(handleP, p, howMany));
+ /* Read the data */
+ n = FDH_PREAD(handleP, p, howMany, howFar);
+ howFar += n;
/* If read any good data and we null padded previously, log the
* amount that we had null padded.
*/
if ((n > 0) && pad) {
- Log("1 Volser: DumpFile: Null padding file %d bytes at offset %u\n", pad, offset);
+ Log("1 Volser: DumpFile: Null padding file %d bytes at offset %lld\n", pad, (long long)offset);
pad = 0;
}
/* Record the read error */
if (n < 0) {
n = 0;
- Log("1 Volser: DumpFile: Error reading inode %s for vnode %d: %s\n", PrintInode(NULL, handleP->fd_ih->ih_ino), vnode, afs_error_message(errno));
+ 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));
} else if (!pad) {
- Log("1 Volser: DumpFile: Error reading inode %s for vnode %d\n", PrintInode(NULL, handleP->fd_ih->ih_ino), vnode);
+ Log("1 Volser: DumpFile: Error reading inode %s for vnode %d\n", PrintInode(stmp, handleP->fd_ih->ih_ino), vnode);
}
- /* Pad the rest of the buffer with zeros. Remember offset we started
+ /* Pad the rest of the buffer with zeros. Remember offset we started
* padding. Keep total tally of padding.
*/
memset(p + n, 0, howMany - n);
/* Now seek over the data we could not get. An error here means we
* can't do the next read.
*/
- lcode = FDH_SEEK(handleP, (size_t)((size - nbytes) + howMany), SEEK_SET);
- if (lcode != ((size - nbytes) + howMany)) {
- if (lcode < 0) {
- Log("1 Volser: DumpFile: Error seeking in inode %s for vnode %d: %s\n", PrintInode(NULL, handleP->fd_ih->ih_ino), vnode, afs_error_message(errno));
- } else {
- Log("1 Volser: DumpFile: Error seeking in inode %s for vnode %d\n", PrintInode(NULL, handleP->fd_ih->ih_ino), vnode);
- lcode = -1;
- }
- } else {
- lcode = 0;
- }
+ howFar = (size_t)((howBig - nbytes) + howMany);
}
/* Now write the data out */
}
if (pad) { /* Any padding we hadn't reported yet */
- Log("1 Volser: DumpFile: Null padding file: %d bytes at offset %u\n",
- pad, offset);
+ Log("1 Volser: DumpFile: Null padding file: %d bytes at offset %lld\n",
+ pad, (long long)offset);
}
free(p);
}
static int
-DumpVolumeHeader(register struct iod *iodp, register Volume * vp)
+DumpVolumeHeader(struct iod *iodp, Volume * vp)
{
int code = 0;
static char nullString[1] = ""; /*The ``contents'' of motd */
}
static int
-DumpEnd(register struct iod *iodp)
+DumpEnd(struct iod *iodp)
{
return (DumpInt32(iodp, D_DUMPEND, DUMPENDMAGIC));
}
/* Dump a whole volume */
int
-DumpVolume(register struct rx_call *call, register Volume * vp,
+DumpVolume(struct rx_call *call, Volume * vp,
afs_int32 fromtime, int dumpAllDirs)
{
struct iod iod;
int code = 0;
- register struct iod *iodp = &iod;
+ struct iod *iodp = &iod;
iod_Init(iodp, call);
if (!code)
/* A partial dump (no dump header) */
static int
-DumpPartial(register struct iod *iodp, register Volume * vp,
+DumpPartial(struct iod *iodp, Volume * vp,
afs_int32 fromtime, int dumpAllDirs)
{
int code = 0;
}
static int
-DumpVnodeIndex(register struct iod *iodp, Volume * vp, VnodeClass class,
+DumpVnodeIndex(struct iod *iodp, Volume * vp, VnodeClass class,
afs_int32 fromtime, int forcedump)
{
- register int code = 0;
- register struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
+ int code = 0;
+ struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
char buf[SIZEOF_LARGEDISKVNODE];
struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
StreamHandle_t *file;
FdHandle_t *fdP;
afs_sfsize_t size, nVnodes;
int flag;
- register int vnodeIndex;
+ int vnodeIndex;
fdP = IH_OPEN(vp->vnodeIndex[class].handle);
- assert(fdP != NULL);
+ opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
- assert(file != NULL);
+ opr_Assert(file != NULL);
size = OS_SIZE(fdP->fd_fd);
- assert(size != -1);
+ opr_Assert(size != -1);
nVnodes = (size / vcp->diskSize) - 1;
if (nVnodes > 0) {
- assert((nVnodes + 1) * vcp->diskSize == size);
- assert(STREAM_SEEK(file, vcp->diskSize, 0) == 0);
+ opr_Assert((nVnodes + 1) * vcp->diskSize == size);
+ opr_Assert(STREAM_ASEEK(file, vcp->diskSize) == 0);
} else
nVnodes = 0;
for (vnodeIndex = 0;
}
static int
-DumpDumpHeader(register struct iod *iodp, register Volume * vp,
+DumpDumpHeader(struct iod *iodp, Volume * vp,
afs_int32 fromtime)
{
int code = 0;
if (!code)
code = DumpString(iodp, 'n', V_name(vp));
dumpTimes[0] = fromtime;
- dumpTimes[1] = V_backupDate(vp); /* Until the time the clone was made */
+ switch (V_type(vp)) {
+ case readwriteVolume:
+ dumpTimes[1] = V_updateDate(vp); /* until last update */
+ break;
+ case readonlyVolume:
+ dumpTimes[1] = V_creationDate(vp); /* until clone was updated */
+ break;
+ case backupVolume:
+ /* until backup was made */
+ dumpTimes[1] = V_backupDate(vp) != 0 ? V_backupDate(vp) :
+ V_creationDate(vp);
+ break;
+ default:
+ code = EINVAL;
+ }
if (!code)
code = DumpArrayInt32(iodp, 't', (afs_uint32 *) dumpTimes, 2);
return code;
}
static int
-DumpVnode(register struct iod *iodp, struct VnodeDiskObject *v, int volid,
+DumpVnode(struct iod *iodp, struct VnodeDiskObject *v, VolumeId volid,
int vnodeNumber, int dumpEverything)
{
int code = 0;
IHandle_t *ihP;
FdHandle_t *fdP;
+ afs_ino_str_t stmp;
if (!v || v->type == vNull)
return code;
if (!code)
code = DumpInt32(iodp, 's', v->serverModifyTime);
if (v->type == vDirectory) {
- acl_HtonACL(VVnodeDiskACL(v));
+ code = acl_HtonACL(VVnodeDiskACL(v));
+ if (code) {
+ Log("DumpVnode: Skipping invalid acl vnode %u (volume %"AFS_VOLID_FMT")\n",
+ vnodeNumber, afs_printable_VolumeId_lu(volid));
+ }
if (!code)
code =
DumpByteString(iodp, 'A', (byte *) VVnodeDiskACL(v),
VAclDiskSize(v));
}
if (VNDISK_GET_INO(v)) {
+ afs_sfsize_t indexlen, disklen;
IH_INIT(ihP, iodp->device, iodp->parentId, VNDISK_GET_INO(v));
fdP = IH_OPEN(ihP);
if (fdP == NULL) {
- Log("1 Volser: DumpVnode: dump: Unable to open inode %llu for vnode %u (volume %i); not dumped, error %d\n", (afs_uintmax_t) VNDISK_GET_INO(v), vnodeNumber, volid, errno);
+ Log("1 Volser: DumpVnode: dump: Unable to open inode %s "
+ "for vnode %u (volume %" AFS_VOLID_FMT "); "
+ "not dumped, error %d\n",
+ PrintInode(stmp, VNDISK_GET_INO(v)), vnodeNumber,
+ afs_printable_VolumeId_lu(volid), errno);
+ IH_RELEASE(ihP);
+ return VOLSERREAD_DUMPERROR;
+ }
+ VNDISK_GET_LEN(indexlen, v);
+ disklen = FDH_SIZE(fdP);
+ if (indexlen != disklen) {
+ FDH_REALLYCLOSE(fdP);
IH_RELEASE(ihP);
+ Log("DumpVnode: volume %"AFS_VOLID_FMT" "
+ "vnode %lu has inconsistent length "
+ "(index %lu disk %lu); aborting dump\n",
+ afs_printable_VolumeId_lu(volid), (unsigned long)vnodeNumber,
+ (unsigned long)indexlen, (unsigned long)disklen);
return VOLSERREAD_DUMPERROR;
}
code = DumpFile(iodp, vnodeNumber, fdP);
int
-ProcessIndex(Volume * vp, VnodeClass class, afs_int32 ** Bufp, int *sizep,
+ProcessIndex(Volume * vp, VnodeClass class, afs_foff_t ** Bufp, int *sizep,
int del)
{
- int i, nVnodes, offset, code;
- afs_int32 *Buf;
+ int i, nVnodes, code;
+ afs_foff_t offset;
+ afs_foff_t *Buf;
int cnt = 0;
afs_sfsize_t size;
StreamHandle_t *afile;
FdHandle_t *fdP;
struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
char buf[SIZEOF_LARGEDISKVNODE], zero[SIZEOF_LARGEDISKVNODE];
- register struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
+ struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
+ afs_ino_str_t stmp;
memset(zero, 0, sizeof(zero)); /* zero out our proto-vnode */
fdP = IH_OPEN(vp->vnodeIndex[class].handle);
for (i = 0; i < *sizep; i++) {
if (Buf[i]) {
cnt++;
- STREAM_SEEK(afile, Buf[i], 0);
+ STREAM_ASEEK(afile, Buf[i]);
code = STREAM_READ(vnode, vcp->diskSize, 1, afile);
if (code == 1) {
if (vnode->type != vNull && VNDISK_GET_INO(vnode)) {
cnt1++;
if (DoLogging) {
- Log("RestoreVolume %u Cleanup: Removing old vnode=%u inode=%llu size=unknown\n",
- V_id(vp), bitNumberToVnodeNumber(i, class),
- (afs_uintmax_t) VNDISK_GET_INO(vnode));
+ Log("RestoreVolume %"AFS_VOLID_FMT" "
+ "Cleanup: Removing old vnode=%u inode=%s "
+ "size=unknown\n",
+ afs_printable_VolumeId_lu(V_id(vp)),
+ bitNumberToVnodeNumber(i, class),
+ PrintInode(stmp, VNDISK_GET_INO(vnode)));
}
IH_DEC(V_linkHandle(vp), VNDISK_GET_INO(vnode),
V_parentId(vp));
DOPOLL;
}
- STREAM_SEEK(afile, Buf[i], 0);
+ STREAM_ASEEK(afile, Buf[i]);
(void)STREAM_WRITE(zero, vcp->diskSize, 1, afile); /* Zero it out */
}
Buf[i] = 0;
OS_SYNC(afile->str_fd);
} else {
size = OS_SIZE(fdP->fd_fd);
- assert(size != -1);
+ opr_Assert(size != -1);
nVnodes =
(size <=
vcp->diskSize ? 0 : size - vcp->diskSize) >> vcp->logSize;
if (nVnodes > 0) {
- if (DoLogging) {
- Log("RestoreVolume ProcessIndex: Set up %d inodes for volume %d\n",
- nVnodes, V_id(vp));
- }
- Buf = (afs_int32 *) malloc(nVnodes * sizeof(afs_int32));
+ Buf = calloc(nVnodes, sizeof(afs_foff_t));
if (Buf == NULL) {
STREAM_CLOSE(afile);
FDH_CLOSE(fdP);
return -1;
}
- memset(Buf, 0, nVnodes * sizeof(afs_int32));
- STREAM_SEEK(afile, offset = vcp->diskSize, 0);
+ STREAM_ASEEK(afile, offset = vcp->diskSize);
while (1) {
code = STREAM_READ(vnode, vcp->diskSize, 1, afile);
if (code != 1) {
}
offset += vcp->diskSize;
}
- if (DoLogging) {
- Log("RestoreVolume ProcessIndex: found %d inodes\n", cnt);
- }
*Bufp = Buf;
*sizep = nVnodes;
}
int
-RestoreVolume(register struct rx_call *call, Volume * avp, int incremental,
+RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
struct restoreCookie *cookie)
{
VolumeDiskData vol;
struct DumpHeader header;
afs_uint32 endMagic;
Error error = 0, vupdate;
- register Volume *vp;
+ Volume *vp;
struct iod iod;
- register struct iod *iodp = &iod;
- afs_int32 *b1 = NULL, *b2 = NULL;
+ struct iod *iodp = &iod;
+ afs_foff_t *b1 = NULL, *b2 = NULL;
int s1 = 0, s2 = 0, delo = 0, tdelo;
int tag;
+ VolumeDiskData saved_header;
+ afs_uint32 uptime, crtime;
iod_Init(iodp, call);
vp = avp;
+ if (DoPreserveVolumeStats) {
+ CopyVolumeStats(&V_disk(vp), &saved_header);
+ }
+
if (!ReadDumpHeader(iodp, &header)) {
Log("1 Volser: RestoreVolume: Error reading header file for dump; aborted\n");
return VOLSERREAD_DUMPERROR;
vol.cloneId = cookie->clone;
vol.parentId = cookie->parent;
+ V_needsSalvaged(vp) = 0;
+
tdelo = delo;
while (1) {
if (ReadVnodes(iodp, vp, 0, b1, s1, b2, s2, tdelo)) {
}
clean:
- ClearVolumeStats(&vol);
+ if (DoPreserveVolumeStats) {
+ CopyVolumeStats(&saved_header, &vol);
+ } else {
+ ClearVolumeStats(&vol);
+ }
+ if (V_needsSalvaged(vp)) {
+ /* needsSalvaged may have been set while we tried to write volume data.
+ * prevent it from getting overwritten. */
+ vol.needsSalvaged = V_needsSalvaged(vp);
+ }
+ crtime = V_creationDate(vp);
+ uptime = V_updateDate(vp);
CopyVolumeHeader(&vol, &V_disk(vp));
V_destroyMe(vp) = 0;
VUpdateVolume(&vupdate, vp);
Log("1 Volser: RestoreVolume: Unable to rewrite volume header; restore aborted\n");
error = VOLSERREAD_DUMPERROR;
goto out;
+ } else {
+ /*
+ * If the volume was not a new empty volume and the restored dump was
+ * older than the volume in question, this is probably a mistake, and
+ * may mean the resulting volume is corrupted. Log the following message
+ * to give a clue as to why this volume suddenly looks strange or corrupt.
+ */
+ if ((crtime != uptime) && (uptime > V_updateDate(vp))) {
+ Log("1 Volser: RestoreVolume: volume %s (%u) appears to have been partially or "
+ "completely restored to an earlier version (updateDate went from %u to %u). "
+ "This is allowed, but may indicate a mistake in whatever tool is restoring "
+ "this volume. If this volume appears corrupted, this is probably why.\n",
+ V_name(vp), V_id(vp), uptime, V_updateDate(vp));
+ }
}
out:
/* Free the malloced space above */
if (b1)
- free((char *)b1);
+ free(b1);
if (b2)
- free((char *)b2);
+ free(b2);
return error;
}
static int
-ReadVnodes(register struct iod *iodp, Volume * vp, int incremental,
- afs_int32 * Lbuf, afs_int32 s1, afs_int32 * Sbuf, afs_int32 s2,
+ReadVnodes(struct iod *iodp, Volume * vp, int incremental,
+ afs_foff_t * Lbuf, afs_int32 s1, afs_foff_t * Sbuf, afs_int32 s2,
afs_int32 delo)
{
afs_int32 vnodeNumber;
char buf[SIZEOF_LARGEDISKVNODE];
- register int tag;
+ int tag;
struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
struct VnodeDiskObject oldvnode;
int idx;
struct VnodeClassInfo *vcp;
IHandle_t *tmpH;
FdHandle_t *fdP;
- Inode nearInode;
+ Inode nearInode AFS_UNUSED;
afs_int32 critical = 0;
+ int nbytes;
tag = iod_getc(iodp);
V_pref(vp, nearInode);
while (tag == D_VNODE) {
int haveStuff = 0;
+ int saw_f = 0;
memset(buf, 0, sizeof(buf));
if (!ReadInt32(iodp, (afs_uint32 *) & vnodeNumber))
break;
if (!ReadInt32(iodp, &vnode->uniquifier))
return VOLSERREAD_DUMPERROR;
- if (DoLogging) {
- Log("ReadVnodes: setup %d/%d\n", vnodeNumber, vnode->uniquifier);
- }
while ((tag = iod_getc(iodp)) > D_MAX && tag != EOF) {
haveStuff = 1;
if (critical)
return VOLSERREAD_DUMPERROR;
break;
case 'A':
- ReadByteString(iodp, (byte *) VVnodeDiskACL(vnode),
+ nbytes = ReadByteString(iodp, (byte *) VVnodeDiskACL(vnode),
VAclDiskSize(vnode));
- acl_NtohACL(VVnodeDiskACL(vnode));
+ if (nbytes != VAclDiskSize(vnode)) {
+ Log("ReadVnodes: could not read acl for vnode %lu in dump.\n",
+ (unsigned long)vnodeNumber);
+ return VOLSERREAD_DUMPERROR;
+ }
+ if (acl_NtohACL(VVnodeDiskACL(vnode)) != 0) {
+ Log("ReadVnodes: invalid acl for vnode %lu in dump.\n",
+ (unsigned long)vnodeNumber);
+ return VOLSERREAD_DUMPERROR;
+ }
break;
case 'h':
case 'f':{
Error error;
afs_fsize_t vnodeLength;
- ino =
- IH_CREATE(V_linkHandle(vp), V_device(vp),
+ if (saw_f) {
+ Log("Volser: ReadVnodes: warning: ignoring duplicate "
+ "file entries for vnode %lu in dump\n",
+ (unsigned long)vnodeNumber);
+ volser_WriteFile(vnodeNumber, iodp, NULL, tag, &error);
+ break;
+ }
+ saw_f = 1;
+
+ tmpH =
+ IH_CREATE_INIT(V_linkHandle(vp), V_device(vp),
VPartitionPath(V_partition(vp)), nearInode,
V_parentId(vp), vnodeNumber,
vnode->uniquifier, vnode->dataVersion);
- if (!VALID_INO(ino)) {
+ if (!tmpH) {
Log("1 Volser: ReadVnodes: IH_CREATE: %s - restore aborted\n",
afs_error_message(errno));
+ V_needsSalvaged(vp) = 1;
return VOLSERREAD_DUMPERROR;
}
+ ino = tmpH->ih_ino;
nearInode = ino;
VNDISK_SET_INO(vnode, ino);
- IH_INIT(tmpH, vp->device, V_parentId(vp), ino);
fdP = IH_OPEN(tmpH);
if (fdP == NULL) {
Log("1 Volser: ReadVnodes: IH_OPEN: %s - restore aborted\n",
afs_error_message(errno));
IH_RELEASE(tmpH);
+ V_needsSalvaged(vp) = 1;
return VOLSERREAD_DUMPERROR;
}
vnodeLength =
Log("1 Volser: ReadVnodes: IDEC inode %llu\n",
(afs_uintmax_t) ino);
IH_DEC(V_linkHandle(vp), ino, V_parentId(vp));
+ V_needsSalvaged(vp) = 1;
return VOLSERREAD_DUMPERROR;
}
break;
if (fdP == NULL) {
Log("1 Volser: ReadVnodes: Error opening vnode index: %s; restore aborted\n",
afs_error_message(errno));
+ V_needsSalvaged(vp) = 1;
return VOLSERREAD_DUMPERROR;
}
- if (FDH_SEEK(fdP, vnodeIndexOffset(vcp, vnodeNumber), SEEK_SET) <
- 0) {
- Log("1 Volser: ReadVnodes: Error seeking into vnode index: %s; restore aborted\n",
- afs_error_message(errno));
- FDH_REALLYCLOSE(fdP);
- return VOLSERREAD_DUMPERROR;
- }
- if (FDH_READ(fdP, &oldvnode, sizeof(oldvnode)) ==
+ if (FDH_PREAD(fdP, &oldvnode, sizeof(oldvnode), vnodeIndexOffset(vcp, vnodeNumber)) ==
sizeof(oldvnode)) {
if (oldvnode.type != vNull && VNDISK_GET_INO(&oldvnode)) {
IH_DEC(V_linkHandle(vp), VNDISK_GET_INO(&oldvnode),
}
}
vnode->vnodeMagic = vcp->magic;
- if (FDH_SEEK(fdP, vnodeIndexOffset(vcp, vnodeNumber), SEEK_SET) <
- 0) {
- Log("1 Volser: ReadVnodes: Error seeking into vnode index: %s; restore aborted\n",
- afs_error_message(errno));
- FDH_REALLYCLOSE(fdP);
- return VOLSERREAD_DUMPERROR;
- }
- if (FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
+ if (FDH_PWRITE(fdP, vnode, vcp->diskSize, vnodeIndexOffset(vcp, vnodeNumber)) != vcp->diskSize) {
Log("1 Volser: ReadVnodes: Error writing vnode index: %s; restore aborted\n",
afs_error_message(errno));
FDH_REALLYCLOSE(fdP);
+ V_needsSalvaged(vp) = 1;
return VOLSERREAD_DUMPERROR;
}
FDH_CLOSE(fdP);
/* called with disk file only. Note that we don't have to worry about rx_Read
* needing to read an ungetc'd character, since the ReadInt32 will have read
* it instead.
+ *
+ * if handleP == NULL, don't write the file anywhere; just read and discard
+ * the file contents
*/
static afs_fsize_t
volser_WriteFile(int vn, struct iod *iodp, FdHandle_t * handleP, int tag,
afs_fsize_t filesize;
afs_fsize_t written = 0;
size_t size = 8192;
- register afs_fsize_t nbytes;
+ afs_fsize_t nbytes;
unsigned char *p;
*status = 0;
-#ifdef AFS_64BIT_ENV
{
afs_uint32 filesize_high = 0L, filesize_low = 0L;
if (tag == 'h') {
}
FillInt64(filesize, filesize_high, filesize_low);
}
-#else /* !AFS_64BIT_ENV */
- if (!ReadInt32(iodp, &filesize)) {
- *status = 1;
- return (0);
- }
-#endif /* !AFS_64BIT_ENV */
- p = (unsigned char *)malloc(size);
+ p = malloc(size);
if (p == NULL) {
*status = 2;
return (0);
*status = 3;
break;
}
- nBytes = FDH_WRITE(handleP, p, size);
- if (nBytes > 0)
- written += nBytes;
- if (nBytes != size) {
- Log("1 Volser: WriteFile: Error writing (%u) bytes to vnode %d: %s; restore aborted\n", (int)(nBytes & 0xffffffff), vn, afs_error_message(errno));
- *status = 4;
- break;
+ if (handleP) {
+ nBytes = FDH_PWRITE(handleP, p, size, written);
+ if (nBytes > 0)
+ written += nBytes;
+ if (nBytes != size) {
+ Log("1 Volser: WriteFile: Error writing (%u) bytes to vnode %d; %s; restore aborted\n", (int)(nBytes & 0xffffffff), vn, afs_error_message(errno));
+ *status = 4;
+ break;
+ }
}
}
free(p);
}
static int
-ReadDumpHeader(register struct iod *iodp, struct DumpHeader *hp)
+ReadDumpHeader(struct iod *iodp, struct DumpHeader *hp)
{
- register int tag;
+ int tag;
afs_uint32 beginMagic;
afs_int32 critical = 0;
if (iod_getc(iodp) != D_DUMPHEADER || !ReadInt32(iodp, &beginMagic)
hp->nDumpTimes = 0;
while ((tag = iod_getc(iodp)) > D_MAX) {
unsigned short arrayLength;
- register int i;
+ int i;
if (critical)
critical--;
switch (tag) {
/* ----- Below are the calls that calculate dump size ----- */
static int
-SizeDumpVolumeHeader(register struct iod *iodp, register Volume * vp,
- register struct volintSize *v_size)
+SizeDumpVolumeHeader(struct iod *iodp, Volume * vp,
+ struct volintSize *v_size)
{
int code = 0;
static char nullString[1] = ""; /*The ``contents'' of motd */
}
static int
-SizeDumpEnd(register struct iod *iodp, register struct volintSize *v_size)
+SizeDumpEnd(struct iod *iodp, struct volintSize *v_size)
{
int code = 0;
afs_uint64 addvar;
}
int
-SizeDumpVolume(register struct rx_call *call, register Volume * vp,
+SizeDumpVolume(struct rx_call *call, Volume * vp,
afs_int32 fromtime, int dumpAllDirs,
- register struct volintSize *v_size)
+ struct volintSize *v_size)
{
int code = 0;
- register struct iod *iodp = (struct iod *)0;
+ struct iod *iodp = (struct iod *)0;
/* iod_Init(iodp, call); */
if (!code)
}
static int
-SizeDumpDumpHeader(register struct iod *iodp, register Volume * vp,
- afs_int32 fromtime, register struct volintSize *v_size)
+SizeDumpDumpHeader(struct iod *iodp, Volume * vp,
+ afs_int32 fromtime, struct volintSize *v_size)
{
int code = 0;
/* int UseLatestReadOnlyClone = 1; */
}
static int
-SizeDumpVnode(register struct iod *iodp, struct VnodeDiskObject *v, int volid,
+SizeDumpVnode(struct iod *iodp, struct VnodeDiskObject *v, VolumeId volid,
int vnodeNumber, int dumpEverything,
- register struct volintSize *v_size)
+ struct volintSize *v_size)
{
int code = 0;
afs_uint64 addvar;
}
if (VNDISK_GET_INO(v)) {
- FillInt64(addvar,0, (v->length + 5));
+ VNDISK_GET_LEN(addvar, v);
+ if (v->vn_length_hi)
+ addvar += 9;
+ else
+ addvar += 5;
AddUInt64(v_size->dump_size, addvar, &v_size->dump_size);
}
return code;
/* A partial dump (no dump header) */
static int
-SizeDumpPartial(register struct iod *iodp, register Volume * vp,
+SizeDumpPartial(struct iod *iodp, Volume * vp,
afs_int32 fromtime, int dumpAllDirs,
- register struct volintSize *v_size)
+ struct volintSize *v_size)
{
int code = 0;
if (!code)
}
static int
-SizeDumpVnodeIndex(register struct iod *iodp, Volume * vp, VnodeClass class,
+SizeDumpVnodeIndex(struct iod *iodp, Volume * vp, VnodeClass class,
afs_int32 fromtime, int forcedump,
- register struct volintSize *v_size)
+ struct volintSize *v_size)
{
- register int code = 0;
- register struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
+ int code = 0;
+ struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
char buf[SIZEOF_LARGEDISKVNODE];
struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
StreamHandle_t *file;
FdHandle_t *fdP;
afs_sfsize_t size, nVnodes;
int flag;
- register int vnodeIndex;
+ int vnodeIndex;
fdP = IH_OPEN(vp->vnodeIndex[class].handle);
- assert(fdP != NULL);
+ opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
- assert(file != NULL);
+ opr_Assert(file != NULL);
size = OS_SIZE(fdP->fd_fd);
- assert(size != -1);
+ opr_Assert(size != -1);
nVnodes = (size / vcp->diskSize) - 1;
if (nVnodes > 0) {
- assert((nVnodes + 1) * vcp->diskSize == size);
- assert(STREAM_SEEK(file, vcp->diskSize, 0) == 0);
+ opr_Assert((nVnodes + 1) * vcp->diskSize == size);
+ opr_Assert(STREAM_ASEEK(file, vcp->diskSize) == 0);
} else
nVnodes = 0;
for (vnodeIndex = 0;