Skip to content

Commit c31bc2b

Browse files
committed
btrfs-progs: image: factor out the restore part from main.c
The remaining part of restore functionality starting from restore_metadump() has been factored out. Same incremental set of changes so the diff is not clean. Signed-off-by: David Sterba <[email protected]>
1 parent 554ec8f commit c31bc2b

File tree

6 files changed

+2122
-2081
lines changed

6 files changed

+2122
-2081
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ convert_objects = convert/main.o convert/common.o convert/source-fs.o \
262262
convert/source-ext2.o convert/source-reiserfs.o \
263263
mkfs/common.o check/clear-cache.o
264264
mkfs_objects = mkfs/main.o mkfs/common.o mkfs/rootdir.o
265-
image_objects = image/main.o image/sanitize.o image/image-create.o image/common.o
265+
image_objects = image/main.o image/sanitize.o image/image-create.o image/common.o \
266+
image/image-restore.o
266267
tune_objects = tune/main.o tune/seeding.o tune/change-uuid.o tune/change-metadata-uuid.o \
267268
tune/convert-bgt.o tune/change-csum.o check/clear-cache.o
268269
all_objects = $(objects) $(cmds_objects) $(libbtrfs_objects) $(convert_objects) \

image/common.c

+195
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,75 @@
11
#include "kerncompat.h"
2+
#include <sys/stat.h>
23
#include <stddef.h>
4+
#include <fcntl.h>
5+
#include <unistd.h>
36
#include "kernel-shared/ctree.h"
7+
#include "kernel-shared/disk-io.h"
48
#include "crypto/crc32c.h"
9+
#include "common/device-utils.h"
10+
#include "common/messages.h"
11+
#include "image/metadump.h"
512
#include "image/common.h"
613

14+
const struct dump_version dump_versions[] = {
15+
/*
16+
* The original format, which only supports tree blocks and free space
17+
* cache dump.
18+
*/
19+
{ .version = 0,
20+
.max_pending_size = SZ_256K,
21+
.magic_cpu = 0xbd5c25e27295668bULL,
22+
.extra_sb_flags = 1 },
23+
#if EXPERIMENTAL
24+
/*
25+
* The new format, with much larger item size to contain any data
26+
* extents.
27+
*/
28+
{ .version = 1,
29+
.max_pending_size = SZ_256M,
30+
.magic_cpu = 0x31765f506d55445fULL, /* ascii _DUmP_v1, no null */
31+
.extra_sb_flags = 0 },
32+
#endif
33+
};
34+
35+
const struct dump_version *current_version = &dump_versions[0];
36+
37+
int detect_version(FILE *in)
38+
{
39+
struct meta_cluster *cluster;
40+
u8 buf[IMAGE_BLOCK_SIZE];
41+
bool found = false;
42+
int i;
43+
int ret;
44+
45+
if (fseek(in, 0, SEEK_SET) < 0) {
46+
error("seek failed: %m");
47+
return -errno;
48+
}
49+
ret = fread(buf, IMAGE_BLOCK_SIZE, 1, in);
50+
if (!ret) {
51+
error("failed to read header");
52+
return -EIO;
53+
}
54+
55+
fseek(in, 0, SEEK_SET);
56+
cluster = (struct meta_cluster *)buf;
57+
for (i = 0; i < ARRAY_SIZE(dump_versions); i++) {
58+
if (le64_to_cpu(cluster->header.magic) ==
59+
dump_versions[i].magic_cpu) {
60+
found = true;
61+
current_version = &dump_versions[i];
62+
break;
63+
}
64+
}
65+
66+
if (!found) {
67+
error("unrecognized header format");
68+
return -EINVAL;
69+
}
70+
return 0;
71+
}
72+
773
void csum_block(u8 *buf, size_t len)
874
{
975
u16 csum_size = btrfs_csum_type_size(BTRFS_CSUM_TYPE_CRC32);
@@ -13,3 +79,132 @@ void csum_block(u8 *buf, size_t len)
1379
put_unaligned_le32(~crc, result);
1480
memcpy(buf, result, csum_size);
1581
}
82+
83+
void write_backup_supers(int fd, u8 *buf)
84+
{
85+
struct btrfs_super_block *super = (struct btrfs_super_block *)buf;
86+
struct stat st;
87+
u64 size;
88+
u64 bytenr;
89+
int i;
90+
int ret;
91+
92+
if (fstat(fd, &st)) {
93+
error(
94+
"cannot stat restore point, won't be able to write backup supers: %m");
95+
return;
96+
}
97+
98+
size = device_get_partition_size_fd_stat(fd, &st);
99+
100+
for (i = 1; i < BTRFS_SUPER_MIRROR_MAX; i++) {
101+
bytenr = btrfs_sb_offset(i);
102+
if (bytenr + BTRFS_SUPER_INFO_SIZE > size)
103+
break;
104+
btrfs_set_super_bytenr(super, bytenr);
105+
csum_block(buf, BTRFS_SUPER_INFO_SIZE);
106+
ret = pwrite(fd, buf, BTRFS_SUPER_INFO_SIZE, bytenr);
107+
if (ret < BTRFS_SUPER_INFO_SIZE) {
108+
if (ret < 0)
109+
error(
110+
"problem writing out backup super block %d: %m", i);
111+
else
112+
error("short write writing out backup super block");
113+
break;
114+
}
115+
}
116+
}
117+
118+
int update_disk_super_on_device(struct btrfs_fs_info *info,
119+
const char *other_dev, u64 cur_devid)
120+
{
121+
struct btrfs_key key;
122+
struct extent_buffer *leaf;
123+
struct btrfs_path path;
124+
struct btrfs_dev_item *dev_item;
125+
struct btrfs_super_block disk_super;
126+
char dev_uuid[BTRFS_UUID_SIZE];
127+
char fs_uuid[BTRFS_UUID_SIZE];
128+
u64 devid, type, io_align, io_width;
129+
u64 sector_size, total_bytes, bytes_used;
130+
int fp = -1;
131+
int ret;
132+
133+
key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
134+
key.type = BTRFS_DEV_ITEM_KEY;
135+
key.offset = cur_devid;
136+
137+
btrfs_init_path(&path);
138+
ret = btrfs_search_slot(NULL, info->chunk_root, &key, &path, 0, 0);
139+
if (ret) {
140+
error("search key failed: %d", ret);
141+
ret = -EIO;
142+
goto out;
143+
}
144+
145+
leaf = path.nodes[0];
146+
dev_item = btrfs_item_ptr(leaf, path.slots[0],
147+
struct btrfs_dev_item);
148+
149+
devid = btrfs_device_id(leaf, dev_item);
150+
if (devid != cur_devid) {
151+
error("devid mismatch: %llu != %llu", devid, cur_devid);
152+
ret = -EIO;
153+
goto out;
154+
}
155+
156+
type = btrfs_device_type(leaf, dev_item);
157+
io_align = btrfs_device_io_align(leaf, dev_item);
158+
io_width = btrfs_device_io_width(leaf, dev_item);
159+
sector_size = btrfs_device_sector_size(leaf, dev_item);
160+
total_bytes = btrfs_device_total_bytes(leaf, dev_item);
161+
bytes_used = btrfs_device_bytes_used(leaf, dev_item);
162+
read_extent_buffer(leaf, dev_uuid, (unsigned long)btrfs_device_uuid(dev_item), BTRFS_UUID_SIZE);
163+
read_extent_buffer(leaf, fs_uuid, (unsigned long)btrfs_device_fsid(dev_item), BTRFS_UUID_SIZE);
164+
165+
btrfs_release_path(&path);
166+
167+
printf("update disk super on %s devid=%llu\n", other_dev, devid);
168+
169+
/* update other devices' super block */
170+
fp = open(other_dev, O_CREAT | O_RDWR, 0600);
171+
if (fp < 0) {
172+
error("could not open %s: %m", other_dev);
173+
ret = -EIO;
174+
goto out;
175+
}
176+
177+
memcpy(&disk_super, info->super_copy, BTRFS_SUPER_INFO_SIZE);
178+
179+
dev_item = &disk_super.dev_item;
180+
181+
btrfs_set_stack_device_type(dev_item, type);
182+
btrfs_set_stack_device_id(dev_item, devid);
183+
btrfs_set_stack_device_total_bytes(dev_item, total_bytes);
184+
btrfs_set_stack_device_bytes_used(dev_item, bytes_used);
185+
btrfs_set_stack_device_io_align(dev_item, io_align);
186+
btrfs_set_stack_device_io_width(dev_item, io_width);
187+
btrfs_set_stack_device_sector_size(dev_item, sector_size);
188+
memcpy(dev_item->uuid, dev_uuid, BTRFS_UUID_SIZE);
189+
memcpy(dev_item->fsid, fs_uuid, BTRFS_UUID_SIZE);
190+
csum_block((u8 *)&disk_super, BTRFS_SUPER_INFO_SIZE);
191+
192+
ret = pwrite(fp, &disk_super, BTRFS_SUPER_INFO_SIZE, BTRFS_SUPER_INFO_OFFSET);
193+
if (ret != BTRFS_SUPER_INFO_SIZE) {
194+
if (ret < 0) {
195+
errno = ret;
196+
error("cannot write superblock: %m");
197+
} else {
198+
error("cannot write superblock");
199+
}
200+
ret = -EIO;
201+
goto out;
202+
}
203+
204+
write_backup_supers(fp, (u8 *)&disk_super);
205+
206+
out:
207+
if (fp != -1)
208+
close(fp);
209+
return ret;
210+
}

image/common.h

+5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
#define __BTRFS_IMAGE_COMMON_H__
1919

2020
#include "kerncompat.h"
21+
#include <stdio.h>
2122

2223
void csum_block(u8 *buf, size_t len);
24+
int detect_version(FILE *in);
25+
int update_disk_super_on_device(struct btrfs_fs_info *info,
26+
const char *other_dev, u64 cur_devid);
27+
void write_backup_supers(int fd, u8 *buf);
2328

2429
#endif

0 commit comments

Comments
 (0)