X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-restore.c;h=f228acab8276fbd7a5175f946c58e7b1fcb7c3a2;hb=HEAD;hp=09388b298f5b041a6541bad71b0a223cb403c359;hpb=fa48918bf0373003631698a030fb2cc0cf1f5fe5;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-restore.c b/cmds-restore.c index 09388b2..f228aca 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -29,6 +29,9 @@ #include #include #include +#if BTRFSRESTORE_ZSTD +#include +#endif #include #include #include @@ -156,6 +159,50 @@ static int decompress_lzo(struct btrfs_root *root, unsigned char *inbuf, return 0; } +static int decompress_zstd(const char *inbuf, char *outbuf, u64 compress_len, + u64 decompress_len) +{ +#if !BTRFSRESTORE_ZSTD + error("btrfs not compiled with zstd support"); + return -1; +#else + ZSTD_DStream *strm; + size_t zret; + int ret = 0; + ZSTD_inBuffer in = {inbuf, compress_len, 0}; + ZSTD_outBuffer out = {outbuf, decompress_len, 0}; + + strm = ZSTD_createDStream(); + if (!strm) { + error("zstd create failed"); + return -1; + } + + zret = ZSTD_initDStream(strm); + if (ZSTD_isError(zret)) { + error("zstd init failed: %s", ZSTD_getErrorName(zret)); + ret = -1; + goto out; + } + + zret = ZSTD_decompressStream(strm, &out, &in); + if (ZSTD_isError(zret)) { + error("zstd decompress failed %s\n", ZSTD_getErrorName(zret)); + ret = -1; + goto out; + } + if (zret != 0) { + error("zstd frame incomplete"); + ret = -1; + goto out; + } + +out: + ZSTD_freeDStream(strm); + return ret; +#endif +} + static int decompress(struct btrfs_root *root, char *inbuf, char *outbuf, u64 compress_len, u64 *decompress_len, int compress) { @@ -166,6 +213,9 @@ static int decompress(struct btrfs_root *root, char *inbuf, char *outbuf, case BTRFS_COMPRESS_LZO: return decompress_lzo(root, (unsigned char *)inbuf, outbuf, compress_len, decompress_len); + case BTRFS_COMPRESS_ZSTD: + return decompress_zstd(inbuf, outbuf, compress_len, + *decompress_len); default: break; } @@ -181,6 +231,7 @@ static int next_leaf(struct btrfs_root *root, struct btrfs_path *path) int offset = 1; struct extent_buffer *c; struct extent_buffer *next = NULL; + struct btrfs_fs_info *fs_info = root->fs_info; again: for (; level < BTRFS_MAX_LEVEL; level++) { @@ -210,7 +261,7 @@ again: if (path->reada) reada_for_search(root, path, level, slot, 0); - next = read_node_slot(root, c, slot); + next = read_node_slot(fs_info, c, slot); if (extent_buffer_uptodate(next)) break; offset++; @@ -226,7 +277,7 @@ again: break; if (path->reada) reada_for_search(root, path, level, 0, 0); - next = read_node_slot(root, next, 0); + next = read_node_slot(fs_info, next, 0); if (!extent_buffer_uptodate(next)) goto again; } @@ -345,8 +396,8 @@ static int copy_one_extent(struct btrfs_root *root, int fd, } again: length = size_left; - ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, - bytenr, &length, &multi, mirror_num, NULL); + ret = btrfs_map_block(root->fs_info, READ, bytenr, &length, &multi, + mirror_num, NULL); if (ret) { error("cannot map block logical %llu length %llu: %d", (unsigned long long)bytenr, @@ -365,8 +416,7 @@ again: done = pread(dev_fd, inbuf+count, length, dev_bytenr); /* Need both checks, or we miss negative values due to u64 conversion */ if (done < 0 || done < length) { - num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, - bytenr, length); + num_copies = btrfs_num_copies(root->fs_info, bytenr, length); mirror_num++; /* mirror_num is 1-indexed, so num_copies is a valid mirror. */ if (mirror_num > num_copies) { @@ -392,7 +442,7 @@ again: pos+total); if (done < 0) { ret = -1; - error("cannot write data: %d %s", errno, strerror(errno)); + error("cannot write data: %d %m", errno); goto out; } total += done; @@ -403,8 +453,7 @@ again: ret = decompress(root, inbuf, outbuf, disk_size, &ram_size, compress); if (ret) { - num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, - bytenr, length); + num_copies = btrfs_num_copies(root->fs_info, bytenr, length); mirror_num++; if (mirror_num >= num_copies) { ret = -1; @@ -538,8 +587,8 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, data_len = len; if (fsetxattr(fd, name, data, data_len, 0)) - error("setting extended attribute %s on file %s: %s", - name, file_name, strerror(errno)); + error("setting extended attribute %s on file %s: %m", + name, file_name); len = sizeof(*di) + name_len + data_len; cur += len; @@ -575,13 +624,13 @@ static int copy_metadata(struct btrfs_root *root, int fd, ret = fchown(fd, btrfs_inode_uid(path.nodes[0], inode_item), btrfs_inode_gid(path.nodes[0], inode_item)); if (ret) { - error("failed to change owner: %s", strerror(errno)); + error("failed to change owner: %m"); goto out; } ret = fchmod(fd, btrfs_inode_mode(path.nodes[0], inode_item)); if (ret) { - error("failed to change mode: %s", strerror(errno)); + error("failed to change mode: %m"); goto out; } @@ -595,7 +644,7 @@ static int copy_metadata(struct btrfs_root *root, int fd, ret = futimens(fd, times); if (ret) { - error("failed to set times: %s", strerror(errno)); + error("failed to set times: %m"); goto out; } } @@ -855,8 +904,8 @@ static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, if (!dry_run) { ret = symlink(symlink_target, path_name); if (ret < 0) { - fprintf(stderr, "Failed to restore symlink '%s': %s\n", - path_name, strerror(errno)); + fprintf(stderr, "Failed to restore symlink '%s': %m\n", + path_name); goto out; } } @@ -888,8 +937,7 @@ static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, btrfs_inode_gid(path.nodes[0], inode_item), AT_SYMLINK_NOFOLLOW); if (ret) { - fprintf(stderr, "Failed to change owner: %s\n", - strerror(errno)); + fprintf(stderr, "Failed to change owner: %m\n"); goto out; } @@ -903,7 +951,7 @@ static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, ret = utimensat(-1, file, times, AT_SYMLINK_NOFOLLOW); if (ret) - fprintf(stderr, "Failed to set times: %s\n", strerror(errno)); + fprintf(stderr, "Failed to set times: %m\n"); out: btrfs_release_path(&path); return ret; @@ -1233,8 +1281,15 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, for (i = super_mirror; i < BTRFS_SUPER_MIRROR_MAX; i++) { bytenr = btrfs_sb_offset(i); + + /* + * Restore won't allocate extent and doesn't care anything + * in extent tree. Skip block group item search will allow + * restore to be executed on heavily damaged fs. + */ fs_info = open_ctree_fs_info(dev, bytenr, root_location, 0, - OPEN_CTREE_PARTIAL); + OPEN_CTREE_PARTIAL | + OPEN_CTREE_NO_BLOCK_GROUPS); if (fs_info) break; fprintf(stderr, "Could not open root, trying backup super\n"); @@ -1255,8 +1310,8 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, if (!root_location) root_location = btrfs_super_root(fs_info->super_copy); generation = btrfs_super_generation(fs_info->super_copy); - root->node = read_tree_block(root, root_location, - fs_info->nodesize, generation); + root->node = read_tree_block(fs_info, root_location, + generation); if (!extent_buffer_uptodate(root->node)) { fprintf(stderr, "Error opening tree root\n"); close_ctree(root); @@ -1502,8 +1557,7 @@ int cmd_restore(int argc, char **argv) if (fs_location != 0) { free_extent_buffer(root->node); - root->node = read_tree_block(root, fs_location, - root->fs_info->nodesize, 0); + root->node = read_tree_block(root->fs_info, fs_location, 0); if (!extent_buffer_uptodate(root->node)) { fprintf(stderr, "Failed to read fs location\n"); ret = 1;