-
Notifications
You must be signed in to change notification settings - Fork 0
/
0001-Btrfs-use-backup-superblocks-to-mount.patch
195 lines (183 loc) · 6.03 KB
/
0001-Btrfs-use-backup-superblocks-to-mount.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
From 6855c3a14d3446a1423a563e168ae7b2c569ee2f Mon Sep 17 00:00:00 2001
From: Wang Shilong <wangshilong1991@gmail.com>
Date: Tue, 24 Sep 2013 23:00:45 +0800
Subject: [PATCH 1/2] Btrfs: use backup superblocks to mount
Only used for Nari, not common case anyway.
Signed-off-by: Wang Shilong <wangshilong1991@gmail.com>
---
fs/btrfs/disk-io.c | 18 +++++--------
fs/btrfs/disk-io.h | 1 +
fs/btrfs/volumes.c | 75 +++++++++++++++++++++++++++++-------------------------
3 files changed, 47 insertions(+), 47 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3032a67..12db40d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -359,7 +359,7 @@ out:
* Return 0 if the superblock checksum type matches the checksum value of that
* algorithm. Pass the raw disk superblock data.
*/
-static int btrfs_check_super_csum(char *raw_disk_sb)
+int btrfs_check_super_csum(char *raw_disk_sb)
{
struct btrfs_super_block *disk_sb =
(struct btrfs_super_block *)raw_disk_sb;
@@ -2341,16 +2341,6 @@ int open_ctree(struct super_block *sb,
}
/*
- * We want to check superblock checksum, the type is stored inside.
- * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k).
- */
- if (btrfs_check_super_csum(bh->b_data)) {
- printk(KERN_ERR "btrfs: superblock checksum mismatch\n");
- err = -EINVAL;
- goto fail_alloc;
- }
-
- /*
* super_copy is zeroed at allocation time and we never touch the
* following bytes up to INFO_SIZE, the checksum is calculated from
* the whole block of INFO_SIZE
@@ -3035,7 +3025,7 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
* So, we need to add a special mount option to scan for
* later supers, using BTRFS_SUPER_MIRROR_MAX instead
*/
- for (i = 0; i < 1; i++) {
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
bytenr = btrfs_sb_offset(i);
if (bytenr + BTRFS_SUPER_INFO_SIZE >=
i_size_read(bdev->bd_inode))
@@ -3051,6 +3041,10 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
brelse(bh);
continue;
}
+ if (btrfs_check_super_csum(bh->b_data)) {
+ brelse(bh);
+ continue;
+ }
if (!latest || btrfs_super_generation(super) > transid) {
brelse(latest);
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index b71acd6e..0e0ba86 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -127,6 +127,7 @@ int btree_lock_page_hook(struct page *page, void *data,
void (*flush_fn)(void *));
int btrfs_calc_num_tolerated_disk_barrier_failures(
struct btrfs_fs_info *fs_info);
+int btrfs_check_super_csum(char *raw_disk_sb);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
void btrfs_init_lockdep(void);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a057735..d7699a7 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -840,6 +840,15 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
return ret;
}
+static int check_super(u64 bytenr, struct btrfs_super_block *disk_super)
+{
+ if (btrfs_super_bytenr(disk_super) != bytenr ||
+ btrfs_super_magic(disk_super) != BTRFS_MAGIC)
+ return 1;
+
+ return btrfs_check_super_csum((char *)disk_super);
+}
+
/*
* Look for a btrfs signature on a device. This may be called out of the mount path
* and we are not allowed to call set_blocksize during the scan. The superblock
@@ -858,53 +867,51 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
u64 total_devices;
u64 bytenr;
pgoff_t index;
+ int i;
+ int found = 0;
- /*
- * we would like to check all the supers, but that would make
- * a btrfs mount succeed after a mkfs from a different FS.
- * So, we need to add a special mount option to scan for
- * later supers, using BTRFS_SUPER_MIRROR_MAX instead
- */
- bytenr = btrfs_sb_offset(0);
flags |= FMODE_EXCL;
mutex_lock(&uuid_mutex);
-
bdev = blkdev_get_by_path(path, flags, holder);
-
if (IS_ERR(bdev)) {
ret = PTR_ERR(bdev);
goto error;
}
-
- /* make sure our super fits in the device */
- if (bytenr + PAGE_CACHE_SIZE >= i_size_read(bdev->bd_inode))
- goto error_bdev_put;
-
/* make sure our super fits in the page */
if (sizeof(*disk_super) > PAGE_CACHE_SIZE)
goto error_bdev_put;
- /* make sure our super doesn't straddle pages on disk */
- index = bytenr >> PAGE_CACHE_SHIFT;
- if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_CACHE_SHIFT != index)
- goto error_bdev_put;
-
- /* pull in the page with our super */
- page = read_cache_page_gfp(bdev->bd_inode->i_mapping,
- index, GFP_NOFS);
-
- if (IS_ERR_OR_NULL(page))
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+ bytenr = btrfs_sb_offset(i);
+
+ /* make sure our super fits in the device */
+ if (bytenr + PAGE_CACHE_SIZE >= i_size_read(bdev->bd_inode))
+ goto error_bdev_put;
+
+ /* make sure our super doesn't straddle pages on disk */
+ index = bytenr >> PAGE_CACHE_SHIFT;
+ if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_CACHE_SHIFT != index)
+ goto error_bdev_put;
+ /* pull in the page with our super */
+ page = read_cache_page_gfp(bdev->bd_inode->i_mapping,
+ index, GFP_NOFS);
+ if (IS_ERR_OR_NULL(page))
+ continue;
+ p = kmap(page);
+ /* align our pointer to the offset of the super block */
+ disk_super = p + (bytenr & ~PAGE_CACHE_MASK);
+ if (check_super(bytenr, disk_super)) {
+ kunmap(page);
+ page_cache_release(page);
+ continue;
+ } else {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
goto error_bdev_put;
- p = kmap(page);
-
- /* align our pointer to the offset of the super block */
- disk_super = p + (bytenr & ~PAGE_CACHE_MASK);
-
- if (btrfs_super_bytenr(disk_super) != bytenr ||
- btrfs_super_magic(disk_super) != BTRFS_MAGIC)
- goto error_unmap;
-
devid = btrfs_stack_device_id(&disk_super->dev_item);
transid = btrfs_super_generation(disk_super);
total_devices = btrfs_super_num_devices(disk_super);
@@ -923,10 +930,8 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
if (!ret && fs_devices_ret)
(*fs_devices_ret)->total_devices = total_devices;
-error_unmap:
kunmap(page);
page_cache_release(page);
-
error_bdev_put:
blkdev_put(bdev, flags);
error:
--
1.7.11.7