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 int ReadVnodes(struct iod *iodp, Volume * vp, 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 void
-ReadByteString(struct iod *iodp, byte * to,
- 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;
}
/*
DumpFile(struct iod *iodp, int vnode, FdHandle_t * handleP)
{
int code = 0, error = 0;
- afs_int32 pad = 0;
- afs_foff_t offset = 0;
afs_sfsize_t nbytes, howBig;
- ssize_t n;
+ ssize_t n = 0;
size_t howMany;
afs_foff_t howFar = 0;
byte *p;
return VOLSERDUMPERROR;
}
- for (nbytes = howBig; (nbytes && !error); nbytes -= howMany) {
+ for (nbytes = howBig; (nbytes && !error); ) {
if (nbytes < howMany)
howMany = nbytes;
/* Read the data */
n = FDH_PREAD(handleP, p, howMany, howFar);
- howFar += n;
+ if (n < 0) {
+ 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));
+ error = VOLSERDUMPERROR;
- /* 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 %lld\n", pad, (long long)offset);
- pad = 0;
+ } else if (n == 0) {
+ Log("1 Volser: DumpFile: Premature EOF reading inode %s for vnode %d\n",
+ PrintInode(stmp, handleP->fd_ih->ih_ino), vnode);
+ error = VOLSERDUMPERROR;
}
-
- /* If didn't read enough data, null padd the rest of the buffer. This
- * can happen if, for instance, the media has some bad spots. We don't
- * want to quit the dump, so we start null padding.
- */
- if (n < howMany) {
- /* Record the read error */
- if (n < 0) {
- n = 0;
- 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(stmp, handleP->fd_ih->ih_ino), vnode);
- }
-
- /* Pad the rest of the buffer with zeros. Remember offset we started
- * padding. Keep total tally of padding.
- */
- memset(p + n, 0, howMany - n);
- if (!pad)
- offset = (howBig - nbytes) + n;
- pad += (howMany - n);
-
- /* Now seek over the data we could not get. An error here means we
- * can't do the next read.
- */
- howFar = (size_t)((howBig - nbytes) + howMany);
+ if (error != 0) {
+ break;
}
+ howFar += n;
+ nbytes -= n;
+
/* Now write the data out */
- if (iod_Write(iodp, (char *)p, howMany) != howMany)
+ if (iod_Write(iodp, (char *)p, n) != n)
error = VOLSERDUMPERROR;
#ifndef AFS_PTHREAD_ENV
IOMGR_Poll();
#endif
}
- if (pad) { /* Any padding we hadn't reported yet */
- Log("1 Volser: DumpFile: Null padding file: %d bytes at offset %lld\n",
- pad, (long long)offset);
- }
-
free(p);
return error;
}
opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
opr_Assert(file != NULL);
- size = OS_SIZE(fdP->fd_fd);
+ size = FDH_SIZE(fdP);
opr_Assert(size != -1);
nVnodes = (size / vcp->diskSize) - 1;
if (nVnodes > 0) {
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),
STREAM_FLUSH(afile); /* ensure 0s are on the disk */
OS_SYNC(afile->str_fd);
} else {
- size = OS_SIZE(fdP->fd_fd);
+ size = FDH_SIZE(fdP);
opr_Assert(size != -1);
nVnodes =
(size <=
int
-RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
- struct restoreCookie *cookie)
+RestoreVolume(struct rx_call *call, Volume * avp, struct restoreCookie *cookie)
{
VolumeDiskData vol;
struct DumpHeader header;
int s1 = 0, s2 = 0, delo = 0, tdelo;
int tag;
VolumeDiskData saved_header;
+ afs_uint32 uptime, crtime;
iod_Init(iodp, call);
Log("1 Volser: RestoreVolume: Volume header missing from dump; not restored\n");
return VOLSERREAD_DUMPERROR;
}
- if (ReadVolumeHeader(iodp, &vol) == VOLSERREAD_DUMPERROR)
+ if (ReadVolumeHeader(iodp, &vol) == VOLSERREAD_DUMPERROR) {
+ Log("1 Volser: RestoreVolume: Error reading volume header (id: %u); aborted\n",
+ V_id(vp));
return VOLSERREAD_DUMPERROR;
+ }
if (!delo)
delo = ProcessIndex(vp, vLarge, &b1, &s1, 0);
tdelo = delo;
while (1) {
- if (ReadVnodes(iodp, vp, 0, b1, s1, b2, s2, tdelo)) {
+ if (ReadVnodes(iodp, vp, b1, s1, b2, s2, tdelo)) {
+ Log("1 Volser: RestoreVolume: Error reading vnodes (id: %u); aborted\n",
+ V_id(vp));
error = VOLSERREAD_DUMPERROR;
goto clean;
}
break;
if (ReadVolumeHeader(iodp, &vol) == VOLSERREAD_DUMPERROR) {
+ Log("1 Volser: RestoreVolume: Error reading volume header (id: %u); aborted\n",
+ V_id(vp));
error = VOLSERREAD_DUMPERROR;
goto out;
}
* 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 */
}
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)
+ReadVnodes(struct iod *iodp, Volume * vp, afs_foff_t * Lbuf, afs_int32 s1,
+ afs_foff_t * Sbuf, afs_int32 s2, afs_int32 delo)
{
afs_int32 vnodeNumber;
char buf[SIZEOF_LARGEDISKVNODE];
FdHandle_t *fdP;
Inode nearInode AFS_UNUSED;
afs_int32 critical = 0;
+ int nbytes;
tag = iod_getc(iodp);
V_pref(vp, nearInode);
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':{
opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
opr_Assert(file != NULL);
- size = OS_SIZE(fdP->fd_fd);
+ size = FDH_SIZE(fdP);
opr_Assert(size != -1);
nVnodes = (size / vcp->diskSize) - 1;
if (nVnodes > 0) {