Blob Blame History Raw
commit 0ece1a1c5bd9224a158138ea79bdffdcb7feda68
Author: Eric Sandeen <sandeen@sandeen.net>
Date:   Wed Oct 2 18:41:09 2013 +0000

    xfsdump: handle large, wholly-sparse files
    
    In restore_extent_group(), we loop over all extent headers for an inode
    in the stream, and add up the cumulatively restored size, accounting
    for both HOLE and DATA records and advancing restoredsz as we go.
    
    But for a wholly-sparse file, we have no HOLE header, only
    a LAST header, and restoredsz remains at 0.
    
    This makes it look like it's a partially-restored file, split
    across streams because the final restoredsz for this stream is
    less than the file size, and we go to partial_reg(), which
    allocates one slot in persp->a.parrest[] for this inode.  But
    we've also called partial_reg() with offset/sz of 0/0, which is
    less than the file size so this inode never looks "done."
    
    Normally partial_check2() would clear the persp->a.parrest[]
    slot in the array when the file is fully restored, but in
    this case, that is never satisfied.  So all stream slots
    get filled as we encounter more inodes like this, and we
    eventually get:
    
    "partial_reg: Out of records. Extend attrs applied early."
    
    Fix this by recognizing that if we hit a LAST header with
    no restoredsz set (i.e. the LAST header is the only header),
    set restoredsz to EOF (bstatp->bs_size) to indicate that
    restoration of this file is complete, skip the call to
    partial_reg(), and all is well.
    
    Signed-off-by: Eric Sandeen <sandeen@redhat.com>
    Reviewed-by: Rich Johnston <rjohnston@sgi.com>
    Signed-off-by: Rich Johnston <rjohnston@sgi.com>

Index: xfsdump-3.1.3/restore/content.c
===================================================================
--- xfsdump-3.1.3.orig/restore/content.c
+++ xfsdump-3.1.3/restore/content.c
@@ -7516,6 +7516,11 @@ restore_extent_group( drive_t *drivep,
 		 * we are done.
 		 */
 		if ( ehdr.eh_type == EXTENTHDR_TYPE_LAST ) {
+			/* For a wholly sparse file, there is no HOLE
+			 * record; advance restoredsz to EOF.
+			 */
+			if (!restoredsz)
+				restoredsz = bstatp->bs_size;
 			break;
 		}