X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-restore.c;h=ade35f0f880fc77e22ea0639c013af5c0095ec7f;hb=58720c644152a411a28acb699fae27479128524a;hp=8fc8b2a000dac8719c99c1d0d777e92ff4f375e2;hpb=bea9ba0acb38e8b3a49fa1b38b574dd79bdb1a42;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-restore.c b/cmds-restore.c index 8fc8b2a..ade35f0 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -29,6 +29,9 @@ #include #include #include +#if BTRFSRESTORE_ZSTD +#include +#endif #include #include #include @@ -42,6 +45,7 @@ #include "volumes.h" #include "utils.h" #include "commands.h" +#include "help.h" static char fs_name[PATH_MAX]; static char path_name[PATH_MAX]; @@ -56,7 +60,6 @@ static int get_xattrs = 0; static int dry_run = 0; #define LZO_LEN 4 -#define PAGE_CACHE_SIZE 4096 #define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3) static int decompress_zlib(char *inbuf, char *outbuf, u64 compress_len, @@ -68,7 +71,7 @@ static int decompress_zlib(char *inbuf, char *outbuf, u64 compress_len, memset(&strm, 0, sizeof(strm)); ret = inflateInit(&strm); if (ret != Z_OK) { - fprintf(stderr, "inflate init returnd %d\n", ret); + error("zlib init returned %d", ret); return -1; } @@ -79,7 +82,7 @@ static int decompress_zlib(char *inbuf, char *outbuf, u64 compress_len, ret = inflate(&strm, Z_NO_FLUSH); if (ret != Z_STREAM_END) { (void)inflateEnd(&strm); - fprintf(stderr, "failed to inflate: %d\n", ret); + error("zlib inflate failed: %d", ret); return -1; } @@ -93,8 +96,8 @@ static inline size_t read_compress_length(unsigned char *buf) return le32_to_cpu(dlen); } -static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len, - u64 *decompress_len) +static int decompress_lzo(struct btrfs_root *root, unsigned char *inbuf, + char *outbuf, u64 compress_len, u64 *decompress_len) { size_t new_len; size_t in_len; @@ -105,7 +108,7 @@ static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len, ret = lzo_init(); if (ret != LZO_E_OK) { - fprintf(stderr, "lzo init returned %d\n", ret); + error("lzo init returned %d", ret); return -1; } @@ -119,20 +122,19 @@ static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len, in_len = read_compress_length(inbuf); if ((tot_in + LZO_LEN + in_len) > tot_len) { - fprintf(stderr, "bad compress length %lu\n", + error("bad compress length %lu", (unsigned long)in_len); return -1; } inbuf += LZO_LEN; tot_in += LZO_LEN; - - new_len = lzo1x_worst_compress(PAGE_CACHE_SIZE); + new_len = lzo1x_worst_compress(root->fs_info->sectorsize); ret = lzo1x_decompress_safe((const unsigned char *)inbuf, in_len, (unsigned char *)outbuf, (void *)&new_len, NULL); if (ret != LZO_E_OK) { - fprintf(stderr, "failed to inflate: %d\n", ret); + error("lzo decompress failed: %d", ret); return -1; } out_len += new_len; @@ -144,8 +146,8 @@ static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len, * If the 4 byte header does not fit to the rest of the page we * have to move to the next one, unless we read some garbage */ - mod_page = tot_in % PAGE_CACHE_SIZE; - rem_page = PAGE_CACHE_SIZE - mod_page; + mod_page = tot_in % root->fs_info->sectorsize; + rem_page = root->fs_info->sectorsize - mod_page; if (rem_page < LZO_LEN) { inbuf += rem_page; tot_in += rem_page; @@ -157,21 +159,68 @@ static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len, return 0; } -static int decompress(char *inbuf, char *outbuf, u64 compress_len, - u64 *decompress_len, int compress) +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) { switch (compress) { case BTRFS_COMPRESS_ZLIB: return decompress_zlib(inbuf, outbuf, compress_len, *decompress_len); case BTRFS_COMPRESS_LZO: - return decompress_lzo((unsigned char *)inbuf, outbuf, compress_len, - decompress_len); + 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; } - fprintf(stderr, "invalid compression type: %d\n", compress); + error("invalid compression type: %d", compress); return -1; } @@ -182,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++) { @@ -211,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++; @@ -227,14 +277,15 @@ 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; } return 0; } -static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos) +static int copy_one_inline(struct btrfs_root *root, int fd, + struct btrfs_path *path, u64 pos) { struct extent_buffer *leaf = path->nodes[0]; struct btrfs_file_extent_item *fi; @@ -269,11 +320,11 @@ static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos) ram_size = btrfs_file_extent_ram_bytes(leaf, fi); outbuf = calloc(1, ram_size); if (!outbuf) { - fprintf(stderr, "No memory\n"); + error("not enough memory"); return -ENOMEM; } - ret = decompress(buf, outbuf, len, &ram_size, compress); + ret = decompress(root, buf, outbuf, len, &ram_size, compress); if (ret) { free(outbuf); return ret; @@ -331,31 +382,33 @@ static int copy_one_extent(struct btrfs_root *root, int fd, inbuf = malloc(size_left); if (!inbuf) { - fprintf(stderr, "No memory\n"); + error("not enough memory"); return -ENOMEM; } if (compress != BTRFS_COMPRESS_NONE) { outbuf = calloc(1, ram_size); if (!outbuf) { - fprintf(stderr, "No memory\n"); + error("not enough memory"); free(inbuf); return -ENOMEM; } } 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) { - fprintf(stderr, "Error mapping block %d\n", ret); + error("cannot map block logical %llu length %llu: %d", + (unsigned long long)bytenr, + (unsigned long long)length, ret); goto out; } device = multi->stripes[0].dev; dev_fd = device->fd; device->total_ios++; dev_bytenr = multi->stripes[0].physical; - kfree(multi); + free(multi); if (size_left < length) length = size_left; @@ -363,13 +416,13 @@ 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) { ret = -1; - fprintf(stderr, "Exhausted mirrors trying to read\n"); + error("exhausted mirrors trying to read (%d > %d)", + mirror_num, num_copies); goto out; } fprintf(stderr, "Trying another mirror\n"); @@ -389,7 +442,7 @@ again: pos+total); if (done < 0) { ret = -1; - fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno)); + error("cannot write data: %d %m", errno); goto out; } total += done; @@ -398,10 +451,9 @@ again: goto out; } - ret = decompress(inbuf, outbuf, disk_size, &ram_size, compress); + 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; @@ -459,7 +511,7 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, int fd, const char *file_name) { struct btrfs_key key; - struct btrfs_path *path; + struct btrfs_path path; struct extent_buffer *leaf; struct btrfs_dir_item *di; u32 name_len = 0; @@ -470,26 +522,21 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, char *data = NULL; int ret = 0; + btrfs_init_path(&path); key.objectid = inode; key.type = BTRFS_XATTR_ITEM_KEY; key.offset = 0; - - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) goto out; - leaf = path->nodes[0]; + leaf = path.nodes[0]; while (1) { - if (path->slots[0] >= btrfs_header_nritems(leaf)) { + if (path.slots[0] >= btrfs_header_nritems(leaf)) { do { - ret = next_leaf(root, path); + ret = next_leaf(root, &path); if (ret < 0) { - fprintf(stderr, - "Error searching for extended attributes: %d\n", + error("searching for extended attributes: %d", ret); goto out; } else if (ret) { @@ -497,17 +544,17 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, ret = 0; goto out; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; } while (!leaf); continue; } - btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); + btrfs_item_key_to_cpu(leaf, &key, path.slots[0]); if (key.type != BTRFS_XATTR_ITEM_KEY || key.objectid != inode) break; cur = 0; - total_len = btrfs_item_size_nr(leaf, path->slots[0]); - di = btrfs_item_ptr(leaf, path->slots[0], + total_len = btrfs_item_size_nr(leaf, path.slots[0]); + di = btrfs_item_ptr(leaf, path.slots[0], struct btrfs_dir_item); while (cur < total_len) { @@ -539,23 +586,19 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, len); data_len = len; - if (fsetxattr(fd, name, data, data_len, 0)) { - int err = errno; - - fprintf(stderr, - "Error setting extended attribute %s on file %s: %s\n", - name, file_name, strerror(err)); - } + if (fsetxattr(fd, name, data, data_len, 0)) + error("setting extended attribute %s on file %s: %m", + name, file_name); len = sizeof(*di) + name_len + data_len; cur += len; di = (struct btrfs_dir_item *)((char *)di + len); } - path->slots[0]++; + path.slots[0]++; } ret = 0; out: - btrfs_free_path(path); + btrfs_release_path(&path); free(name); free(data); @@ -565,56 +608,48 @@ out: static int copy_metadata(struct btrfs_root *root, int fd, struct btrfs_key *key) { - struct btrfs_path *path; + struct btrfs_path path; struct btrfs_inode_item *inode_item; int ret; - path = btrfs_alloc_path(); - if (!path) { - fprintf(stderr, "ERROR: Ran out of memory\n"); - return -ENOMEM; - } - - ret = btrfs_lookup_inode(NULL, root, path, key, 0); + btrfs_init_path(&path); + ret = btrfs_lookup_inode(NULL, root, &path, key, 0); if (ret == 0) { struct btrfs_timespec *bts; struct timespec times[2]; - inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], + inode_item = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_inode_item); - ret = fchown(fd, btrfs_inode_uid(path->nodes[0], inode_item), - btrfs_inode_gid(path->nodes[0], inode_item)); + ret = fchown(fd, btrfs_inode_uid(path.nodes[0], inode_item), + btrfs_inode_gid(path.nodes[0], inode_item)); if (ret) { - fprintf(stderr, "ERROR: Failed to change owner: %s\n", - strerror(errno)); + error("failed to change owner: %m"); goto out; } - ret = fchmod(fd, btrfs_inode_mode(path->nodes[0], inode_item)); + ret = fchmod(fd, btrfs_inode_mode(path.nodes[0], inode_item)); if (ret) { - fprintf(stderr, "ERROR: Failed to change mode: %s\n", - strerror(errno)); + error("failed to change mode: %m"); goto out; } bts = btrfs_inode_atime(inode_item); - times[0].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); - times[0].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); + times[0].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); + times[0].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); bts = btrfs_inode_mtime(inode_item); - times[1].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); - times[1].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); + times[1].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); + times[1].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); ret = futimens(fd, times); if (ret) { - fprintf(stderr, "ERROR: Failed to set times: %s\n", - strerror(errno)); + error("failed to set times: %m"); goto out; } } out: - btrfs_free_path(path); + btrfs_release_path(&path); return ret; } @@ -622,7 +657,7 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, const char *file) { struct extent_buffer *leaf; - struct btrfs_path *path; + struct btrfs_path path; struct btrfs_file_extent_item *fi; struct btrfs_inode_item *inode_item; struct btrfs_timespec *bts; @@ -635,17 +670,12 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, struct timespec times[2]; int times_ok = 0; - path = btrfs_alloc_path(); - if (!path) { - fprintf(stderr, "Ran out of memory\n"); - return -ENOMEM; - } - - ret = btrfs_lookup_inode(NULL, root, path, key, 0); + btrfs_init_path(&path); + ret = btrfs_lookup_inode(NULL, root, &path, key, 0); if (ret == 0) { - inode_item = btrfs_item_ptr(path->nodes[0], path->slots[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); + found_size = btrfs_inode_size(path.nodes[0], inode_item); if (restore_metadata) { /* @@ -653,49 +683,48 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, * copyout is finished. */ - ret = fchown(fd, btrfs_inode_uid(path->nodes[0], inode_item), - btrfs_inode_gid(path->nodes[0], inode_item)); + ret = fchown(fd, btrfs_inode_uid(path.nodes[0], inode_item), + btrfs_inode_gid(path.nodes[0], inode_item)); if (ret && !ignore_errors) goto out; - ret = fchmod(fd, btrfs_inode_mode(path->nodes[0], inode_item)); + ret = fchmod(fd, btrfs_inode_mode(path.nodes[0], inode_item)); if (ret && !ignore_errors) goto out; bts = btrfs_inode_atime(inode_item); - times[0].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); - times[0].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); + times[0].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); + times[0].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); bts = btrfs_inode_mtime(inode_item); - times[1].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); - times[1].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); + times[1].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); + times[1].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); times_ok = 1; } } - btrfs_release_path(path); + btrfs_release_path(&path); key->offset = 0; key->type = BTRFS_EXTENT_DATA_KEY; - ret = btrfs_search_slot(NULL, root, key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); if (ret < 0) { - fprintf(stderr, "Error searching %d\n", ret); + error("searching extent data returned %d", ret); goto out; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; while (!leaf) { - ret = next_leaf(root, path); + ret = next_leaf(root, &path); if (ret < 0) { - fprintf(stderr, "Error getting next leaf %d\n", - ret); + error("cannot get next leaf: %d", ret); goto out; } else if (ret > 0) { /* No more leaves to search */ ret = 0; goto out; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; } while (1) { @@ -710,32 +739,32 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, else if (resp == LOOP_DONTASK) loops = -1; } - if (path->slots[0] >= btrfs_header_nritems(leaf)) { + if (path.slots[0] >= btrfs_header_nritems(leaf)) { do { - ret = next_leaf(root, path); + ret = next_leaf(root, &path); if (ret < 0) { fprintf(stderr, "Error searching %d\n", ret); goto out; } else if (ret) { /* No more leaves to search */ - btrfs_free_path(path); + btrfs_release_path(&path); goto set_size; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; } while (!leaf); continue; } - btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); + btrfs_item_key_to_cpu(leaf, &found_key, path.slots[0]); if (found_key.objectid != key->objectid) break; if (found_key.type != key->type) break; - fi = btrfs_item_ptr(leaf, path->slots[0], + fi = btrfs_item_ptr(leaf, path.slots[0], struct btrfs_file_extent_item); extent_type = btrfs_file_extent_type(leaf, fi); compression = btrfs_file_extent_compression(leaf, fi); if (compression >= BTRFS_COMPRESS_LAST) { - fprintf(stderr, "Don't support compression yet %d\n", + warning("compression type %d not supported", compression); ret = -1; goto out; @@ -744,7 +773,7 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) goto next; if (extent_type == BTRFS_FILE_EXTENT_INLINE) { - ret = copy_one_inline(fd, path, found_key.offset); + ret = copy_one_inline(root, fd, &path, found_key.offset); if (ret) goto out; } else if (extent_type == BTRFS_FILE_EXTENT_REG) { @@ -753,13 +782,13 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, if (ret) goto out; } else { - printf("Weird extent type %d\n", extent_type); + warning("weird extent type %d", extent_type); } next: - path->slots[0]++; + path.slots[0]++; } - btrfs_free_path(path); + btrfs_release_path(&path); set_size: if (found_size) { ret = ftruncate(fd, (loff_t)found_size); @@ -779,7 +808,7 @@ set_size: return 0; out: - btrfs_free_path(path); + btrfs_release_path(&path); return ret; } @@ -816,7 +845,7 @@ static int overwrite_ok(const char * path) static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, const char *file) { - struct btrfs_path *path; + struct btrfs_path path; struct extent_buffer *leaf; struct btrfs_file_extent_item *extent_item; struct btrfs_inode_item *inode_item; @@ -840,30 +869,26 @@ static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, } } + btrfs_init_path(&path); key->type = BTRFS_EXTENT_DATA_KEY; key->offset = 0; - - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - - ret = btrfs_search_slot(NULL, root, key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); if (ret < 0) goto out; - leaf = path->nodes[0]; + leaf = path.nodes[0]; if (!leaf) { fprintf(stderr, "Error getting leaf for symlink '%s'\n", file); ret = -1; goto out; } - extent_item = btrfs_item_ptr(leaf, path->slots[0], + extent_item = btrfs_item_ptr(leaf, path.slots[0], struct btrfs_file_extent_item); len = btrfs_file_extent_inline_item_len(leaf, - btrfs_item_nr(path->slots[0])); - if (len > PATH_MAX) { + btrfs_item_nr(path.slots[0])); + if (len >= PATH_MAX) { fprintf(stderr, "Symlink '%s' target length %d is longer than PATH_MAX\n", fs_name, len); ret = -1; @@ -879,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; } } @@ -897,39 +922,38 @@ static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, key->type = BTRFS_INODE_ITEM_KEY; key->offset = 0; - btrfs_release_path(path); + btrfs_release_path(&path); - ret = btrfs_lookup_inode(NULL, root, path, key, 0); + ret = btrfs_lookup_inode(NULL, root, &path, key, 0); if (ret) { fprintf(stderr, "Failed to lookup inode for '%s'\n", file); goto out; } - inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], + inode_item = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_inode_item); - ret = fchownat(-1, file, btrfs_inode_uid(path->nodes[0], inode_item), - btrfs_inode_gid(path->nodes[0], inode_item), + ret = fchownat(-1, file, btrfs_inode_uid(path.nodes[0], inode_item), + 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; } bts = btrfs_inode_atime(inode_item); - times[0].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); - times[0].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); + times[0].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); + times[0].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); bts = btrfs_inode_mtime(inode_item); - times[1].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); - times[1].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); + times[1].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); + times[1].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); 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_free_path(path); + btrfs_release_path(&path); return ret; } @@ -937,7 +961,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, const char *output_rootdir, const char *in_dir, const regex_t *mreg) { - struct btrfs_path *path; + struct btrfs_path path; struct extent_buffer *leaf; struct btrfs_dir_item *dir_item; struct btrfs_key found_key, location; @@ -949,16 +973,10 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, int loops = 0; u8 type; - path = btrfs_alloc_path(); - if (!path) { - fprintf(stderr, "Ran out of memory\n"); - return -ENOMEM; - } - + btrfs_init_path(&path); key->offset = 0; key->type = BTRFS_DIR_INDEX_KEY; - - ret = btrfs_search_slot(NULL, root, key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); if (ret < 0) { fprintf(stderr, "Error searching %d\n", ret); goto out; @@ -966,12 +984,12 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, ret = 0; - leaf = path->nodes[0]; + leaf = path.nodes[0]; while (!leaf) { if (verbose > 1) printf("No leaf after search, looking for the next " "leaf\n"); - ret = next_leaf(root, path); + ret = next_leaf(root, &path); if (ret < 0) { fprintf(stderr, "Error getting next leaf %d\n", ret); @@ -984,7 +1002,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, ret = 0; goto out; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; } while (leaf) { @@ -995,9 +1013,9 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, break; } - if (path->slots[0] >= btrfs_header_nritems(leaf)) { + if (path.slots[0] >= btrfs_header_nritems(leaf)) { do { - ret = next_leaf(root, path); + ret = next_leaf(root, &path); if (ret < 0) { fprintf(stderr, "Error searching %d\n", ret); @@ -1011,11 +1029,11 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, ret = 0; goto out; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; } while (!leaf); continue; } - btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); + btrfs_item_key_to_cpu(leaf, &found_key, path.slots[0]); if (found_key.objectid != key->objectid) { if (verbose > 1) printf("Found objectid=%Lu, key=%Lu\n", @@ -1028,7 +1046,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, found_key.type, key->type); break; } - dir_item = btrfs_item_ptr(leaf, path->slots[0], + dir_item = btrfs_item_ptr(leaf, path.slots[0], struct btrfs_dir_item); name_ptr = (unsigned long)(dir_item + 1); name_len = btrfs_dir_name_len(leaf, dir_item); @@ -1160,12 +1178,12 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, if (ret < 0) { if (ignore_errors) goto next; - btrfs_free_path(path); + btrfs_release_path(&path); return ret; } } next: - path->slots[0]++; + path.slots[0]++; } if (restore_metadata) { @@ -1193,7 +1211,7 @@ next: if (verbose) printf("Done searching %s\n", in_dir); out: - btrfs_free_path(path); + btrfs_release_path(&path); return ret; } @@ -1202,7 +1220,7 @@ static int do_list_roots(struct btrfs_root *root) struct btrfs_key key; struct btrfs_key found_key; struct btrfs_disk_key disk_key; - struct btrfs_path *path; + struct btrfs_path path; struct extent_buffer *leaf; struct btrfs_root_item ri; unsigned long offset; @@ -1210,38 +1228,33 @@ static int do_list_roots(struct btrfs_root *root) int ret; root = root->fs_info->tree_root; - path = btrfs_alloc_path(); - if (!path) { - fprintf(stderr, "Failed to alloc path\n"); - return -ENOMEM; - } + btrfs_init_path(&path); key.offset = 0; key.objectid = 0; key.type = BTRFS_ROOT_ITEM_KEY; - - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) { fprintf(stderr, "Failed to do search %d\n", ret); - btrfs_free_path(path); + btrfs_release_path(&path); return -1; } - leaf = path->nodes[0]; + leaf = path.nodes[0]; while (1) { - slot = path->slots[0]; + slot = path.slots[0]; if (slot >= btrfs_header_nritems(leaf)) { - ret = btrfs_next_leaf(root, path); + ret = btrfs_next_leaf(root, &path); if (ret) break; - leaf = path->nodes[0]; - slot = path->slots[0]; + leaf = path.nodes[0]; + slot = path.slots[0]; } btrfs_item_key(leaf, &disk_key, slot); btrfs_disk_key_to_cpu(&found_key, &disk_key); - if (btrfs_key_type(&found_key) != BTRFS_ROOT_ITEM_KEY) { - path->slots[0]++; + if (found_key.type != BTRFS_ROOT_ITEM_KEY) { + path.slots[0]++; continue; } @@ -1251,9 +1264,9 @@ static int do_list_roots(struct btrfs_root *root) btrfs_print_key(&disk_key); printf(" %Lu level %d\n", btrfs_root_bytenr(&ri), btrfs_root_level(&ri)); - path->slots[0]++; + path.slots[0]++; } - btrfs_free_path(path); + btrfs_release_path(&path); return 0; } @@ -1268,7 +1281,7 @@ 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); - fs_info = open_ctree_fs_info(dev, bytenr, root_location, + fs_info = open_ctree_fs_info(dev, bytenr, root_location, 0, OPEN_CTREE_PARTIAL); if (fs_info) break; @@ -1290,8 +1303,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, - root->leafsize, 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); @@ -1324,36 +1337,30 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, static int find_first_dir(struct btrfs_root *root, u64 *objectid) { - struct btrfs_path *path; + struct btrfs_path path; struct btrfs_key found_key; struct btrfs_key key; int ret = -1; int i; + btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_DIR_INDEX_KEY; key.offset = 0; - - path = btrfs_alloc_path(); - if (!path) { - fprintf(stderr, "Ran out of memory\n"); - return ret; - } - - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) { fprintf(stderr, "Error searching %d\n", ret); goto out; } - if (!path->nodes[0]) { + if (!path.nodes[0]) { fprintf(stderr, "No leaf!\n"); goto out; } again: - for (i = path->slots[0]; - i < btrfs_header_nritems(path->nodes[0]); i++) { - btrfs_item_key_to_cpu(path->nodes[0], &found_key, i); + for (i = path.slots[0]; + i < btrfs_header_nritems(path.nodes[0]); i++) { + btrfs_item_key_to_cpu(path.nodes[0], &found_key, i); if (found_key.type != key.type) continue; @@ -1364,7 +1371,7 @@ again: goto out; } do { - ret = next_leaf(root, path); + ret = next_leaf(root, &path); if (ret < 0) { fprintf(stderr, "Error getting next leaf %d\n", ret); @@ -1373,12 +1380,12 @@ again: fprintf(stderr, "No more leaves\n"); goto out; } - } while (!path->nodes[0]); - if (path->nodes[0]) + } while (!path.nodes[0]); + if (path.nodes[0]) goto again; printf("Couldn't find a dir index item\n"); out: - btrfs_free_path(path); + btrfs_release_path(&path); return ret; } @@ -1387,9 +1394,9 @@ const char * const cmd_restore_usage[] = { "Try to restore files from a damaged filesystem (unmounted)", "", "-s|--snapshots get snapshots", - "-x|--xattr get extended attributes", + "-x|--xattr restore extended attributes", "-m|--metadata restore owner, mode and times", - "-S|--symlinks restore symbolic links", + "-S|--symlink restore symbolic links", "-v|--verbose verbose", "-i|--ignore-errors ignore errors", "-o|--overwrite overwrite", @@ -1428,8 +1435,10 @@ int cmd_restore(int argc, char **argv) while (1) { int opt; + enum { GETOPT_VAL_PATH_REGEX = 256 }; static const struct option long_options[] = { - { "path-regex", required_argument, NULL, 256}, + { "path-regex", required_argument, NULL, + GETOPT_VAL_PATH_REGEX }, { "dry-run", no_argument, NULL, 'D'}, { "metadata", no_argument, NULL, 'm'}, { "symlinks", no_argument, NULL, 'S'}, @@ -1502,8 +1511,7 @@ int cmd_restore(int argc, char **argv) case 'c': match_cflags |= REG_ICASE; break; - /* long option without single letter alternative */ - case 256: + case GETOPT_VAL_PATH_REGEX: match_regstr = optarg; break; case 'x': @@ -1542,7 +1550,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->leafsize, 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;