vol: Use FDH_SIZE more consistently
[openafs.git] / src / volser / dumpstuff.c
index 8c01aa0..8c044d6 100644 (file)
@@ -64,9 +64,9 @@ static int DumpVnodeIndex(struct iod *iodp, Volume * vp,
 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);
@@ -265,12 +265,17 @@ ReadString(struct iod *iodp, char *to, int maxa)
     }
 }
 
-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;
 }
 
 /*
@@ -699,10 +704,8 @@ static int
 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;
@@ -771,62 +774,38 @@ DumpFile(struct iod *iodp, int vnode, FdHandle_t * handleP)
        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;
 }
@@ -989,7 +968,7 @@ DumpVnodeIndex(struct iod *iodp, Volume * vp, VnodeClass class,
     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) {
@@ -1093,7 +1072,11 @@ DumpVnode(struct iod *iodp, struct VnodeDiskObject *v, VolumeId volid,
     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),
@@ -1189,7 +1172,7 @@ ProcessIndex(Volume * vp, VnodeClass class, afs_foff_t ** Bufp, int *sizep,
        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 <=
@@ -1224,8 +1207,7 @@ ProcessIndex(Volume * vp, VnodeClass class, afs_foff_t ** Bufp, int *sizep,
 
 
 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;
@@ -1238,6 +1220,7 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
     int s1 = 0, s2 = 0, delo = 0, tdelo;
     int tag;
     VolumeDiskData saved_header;
+    afs_uint32 uptime, crtime;
 
     iod_Init(iodp, call);
 
@@ -1255,8 +1238,11 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
        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);
@@ -1277,7 +1263,9 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
 
     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;
        }
@@ -1286,6 +1274,8 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
            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;
        }
@@ -1325,6 +1315,8 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
         * 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);
@@ -1332,6 +1324,20 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
        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 */
@@ -1343,9 +1349,8 @@ RestoreVolume(struct rx_call *call, Volume * avp, int incremental,
 }
 
 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];
@@ -1359,6 +1364,7 @@ ReadVnodes(struct iod *iodp, Volume * vp, int incremental,
     FdHandle_t *fdP;
     Inode nearInode AFS_UNUSED;
     afs_int32 critical = 0;
+    int nbytes;
 
     tag = iod_getc(iodp);
     V_pref(vp, nearInode);
@@ -1424,9 +1430,18 @@ ReadVnodes(struct iod *iodp, Volume * vp, int incremental,
                    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':{
@@ -1907,7 +1922,7 @@ SizeDumpVnodeIndex(struct iod *iodp, Volume * vp, VnodeClass class,
     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) {