diff options
author | Chris Mason <chris.mason@oracle.com> | 2011-10-27 16:25:12 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-10-27 16:25:12 -0400 |
commit | ff91b185f7ddad0f16fb0be4c6713d65daf1b03e (patch) | |
tree | 466c0566f5f3e08fe1beddd21de8f43f7312cc64 /restore.c | |
parent | ba1aa28496cf2a2c7ffff0521c6c858a0505d4c2 (diff) |
restore: deal with holes and set i_size correctly
This changes restore to set the i_size of the files it
copies out based on the size in the inode. It also changes
it to skip over holes.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'restore.c')
-rw-r--r-- | restore.c | 22 |
1 files changed, 20 insertions, 2 deletions
@@ -204,6 +204,10 @@ static int copy_one_extent(struct btrfs_root *root, int fd, ram_size = btrfs_file_extent_ram_bytes(leaf, fi); size_left = disk_size; + /* we found a hole */ + if (disk_size == 0) + return 0; + inbuf = malloc(disk_size); if (!inbuf) { fprintf(stderr, "No memory\n"); @@ -258,7 +262,7 @@ again: pos+total); if (done < 0) { free(inbuf); - fprintf(stderr, "Error writing: %d\n", errno); + fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno)); return -1; } total += done; @@ -278,7 +282,7 @@ again: done = pwrite(fd, outbuf+total, ram_size-total, pos+total); if (done < 0) { free(outbuf); - fprintf(stderr, "Error writing: %d\n", errno); + fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno)); return -1; } total += done; @@ -314,11 +318,13 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, struct extent_buffer *leaf; struct btrfs_path *path; struct btrfs_file_extent_item *fi; + struct btrfs_inode_item *inode_item; struct btrfs_key found_key; int ret; int extent_type; int compression; int loops = 0; + u64 found_size = 0; path = btrfs_alloc_path(); if (!path) { @@ -327,6 +333,14 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, } path->skip_locking = 1; + ret = btrfs_lookup_inode(NULL, root, path, key, 0); + if (ret == 0) { + inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_item); + found_size = btrfs_inode_size(path->nodes[0], inode_item); + } + btrfs_release_path(root, path); + key->offset = 0; key->type = BTRFS_EXTENT_DATA_KEY; @@ -370,6 +384,7 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, } else if (ret) { /* No more leaves to search */ btrfs_free_path(path); + goto set_size; return 0; } leaf = path->nodes[0]; @@ -415,6 +430,9 @@ next: } btrfs_free_path(path); +set_size: + if (found_size) + ftruncate(fd, (loff_t)found_size); return 0; } |