diff options
author | Kent Overstreet <koverstreet@google.com> | 2013-04-11 18:14:35 -0400 |
---|---|---|
committer | Kent Overstreet <koverstreet@google.com> | 2013-04-20 20:56:12 -0400 |
commit | 2903381fce71004a7ce24d40fad53ba8236a3921 (patch) | |
tree | f493d51bdf17b2376e3f79fe0aecc8a7a9e37263 /drivers/md | |
parent | cef5279735d3f6f0243e626963e6d5c84efade0a (diff) |
bcache: Take data offset from the bdev superblock.
Add a new superblock version, and consolidate related defines.
Signed-off-by: Gabriel de Perthuis <g2p.code+bcache@gmail.com>
Signed-off-by: Kent Overstreet <koverstreet@google.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/bcache/bcache.h | 47 | ||||
-rw-r--r-- | drivers/md/bcache/request.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 108 |
3 files changed, 100 insertions, 57 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index f05723565f17..340146d7c17f 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h | |||
@@ -223,11 +223,17 @@ struct bkey { | |||
223 | #define BKEY_PADDED(key) \ | 223 | #define BKEY_PADDED(key) \ |
224 | union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; } | 224 | union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; } |
225 | 225 | ||
226 | /* Version 1: Backing device | 226 | /* Version 0: Cache device |
227 | * Version 1: Backing device | ||
227 | * Version 2: Seed pointer into btree node checksum | 228 | * Version 2: Seed pointer into btree node checksum |
228 | * Version 3: New UUID format | 229 | * Version 3: Cache device with new UUID format |
230 | * Version 4: Backing device with data offset | ||
229 | */ | 231 | */ |
230 | #define BCACHE_SB_VERSION 3 | 232 | #define BCACHE_SB_VERSION_CDEV 0 |
233 | #define BCACHE_SB_VERSION_BDEV 1 | ||
234 | #define BCACHE_SB_VERSION_CDEV_WITH_UUID 3 | ||
235 | #define BCACHE_SB_VERSION_BDEV_WITH_OFFSET 4 | ||
236 | #define BCACHE_SB_MAX_VERSION 4 | ||
231 | 237 | ||
232 | #define SB_SECTOR 8 | 238 | #define SB_SECTOR 8 |
233 | #define SB_SIZE 4096 | 239 | #define SB_SIZE 4096 |
@@ -236,13 +242,12 @@ struct bkey { | |||
236 | /* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */ | 242 | /* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */ |
237 | #define MAX_CACHES_PER_SET 8 | 243 | #define MAX_CACHES_PER_SET 8 |
238 | 244 | ||
239 | #define BDEV_DATA_START 16 /* sectors */ | 245 | #define BDEV_DATA_START_DEFAULT 16 /* sectors */ |
240 | 246 | ||
241 | struct cache_sb { | 247 | struct cache_sb { |
242 | uint64_t csum; | 248 | uint64_t csum; |
243 | uint64_t offset; /* sector where this sb was written */ | 249 | uint64_t offset; /* sector where this sb was written */ |
244 | uint64_t version; | 250 | uint64_t version; |
245 | #define CACHE_BACKING_DEV 1 | ||
246 | 251 | ||
247 | uint8_t magic[16]; | 252 | uint8_t magic[16]; |
248 | 253 | ||
@@ -257,12 +262,28 @@ struct cache_sb { | |||
257 | uint64_t seq; | 262 | uint64_t seq; |
258 | uint64_t pad[8]; | 263 | uint64_t pad[8]; |
259 | 264 | ||
260 | uint64_t nbuckets; /* device size */ | 265 | union { |
261 | uint16_t block_size; /* sectors */ | 266 | struct { |
262 | uint16_t bucket_size; /* sectors */ | 267 | /* Cache devices */ |
268 | uint64_t nbuckets; /* device size */ | ||
269 | |||
270 | uint16_t block_size; /* sectors */ | ||
271 | uint16_t bucket_size; /* sectors */ | ||
263 | 272 | ||
264 | uint16_t nr_in_set; | 273 | uint16_t nr_in_set; |
265 | uint16_t nr_this_dev; | 274 | uint16_t nr_this_dev; |
275 | }; | ||
276 | struct { | ||
277 | /* Backing devices */ | ||
278 | uint64_t data_offset; | ||
279 | |||
280 | /* | ||
281 | * block_size from the cache device section is still used by | ||
282 | * backing devices, so don't add anything here until we fix | ||
283 | * things to not need it for backing devices anymore | ||
284 | */ | ||
285 | }; | ||
286 | }; | ||
266 | 287 | ||
267 | uint32_t last_mount; /* time_t */ | 288 | uint32_t last_mount; /* time_t */ |
268 | 289 | ||
@@ -861,6 +882,12 @@ static inline bool key_merging_disabled(struct cache_set *c) | |||
861 | #endif | 882 | #endif |
862 | } | 883 | } |
863 | 884 | ||
885 | static inline bool SB_IS_BDEV(const struct cache_sb *sb) | ||
886 | { | ||
887 | return sb->version == BCACHE_SB_VERSION_BDEV | ||
888 | || sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET; | ||
889 | } | ||
890 | |||
864 | struct bbio { | 891 | struct bbio { |
865 | unsigned submit_time_us; | 892 | unsigned submit_time_us; |
866 | union { | 893 | union { |
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 83731dc36f34..e5ff12e52d5b 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c | |||
@@ -1220,7 +1220,7 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio) | |||
1220 | part_stat_unlock(); | 1220 | part_stat_unlock(); |
1221 | 1221 | ||
1222 | bio->bi_bdev = dc->bdev; | 1222 | bio->bi_bdev = dc->bdev; |
1223 | bio->bi_sector += BDEV_DATA_START; | 1223 | bio->bi_sector += dc->sb.data_offset; |
1224 | 1224 | ||
1225 | if (cached_dev_get(dc)) { | 1225 | if (cached_dev_get(dc)) { |
1226 | s = search_alloc(bio, d); | 1226 | s = search_alloc(bio, d); |
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 5fa3cd2d9ff0..f1e69f2fad37 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c | |||
@@ -110,15 +110,7 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev, | |||
110 | 110 | ||
111 | sb->flags = le64_to_cpu(s->flags); | 111 | sb->flags = le64_to_cpu(s->flags); |
112 | sb->seq = le64_to_cpu(s->seq); | 112 | sb->seq = le64_to_cpu(s->seq); |
113 | |||
114 | sb->nbuckets = le64_to_cpu(s->nbuckets); | ||
115 | sb->block_size = le16_to_cpu(s->block_size); | ||
116 | sb->bucket_size = le16_to_cpu(s->bucket_size); | ||
117 | |||
118 | sb->nr_in_set = le16_to_cpu(s->nr_in_set); | ||
119 | sb->nr_this_dev = le16_to_cpu(s->nr_this_dev); | ||
120 | sb->last_mount = le32_to_cpu(s->last_mount); | 113 | sb->last_mount = le32_to_cpu(s->last_mount); |
121 | |||
122 | sb->first_bucket = le16_to_cpu(s->first_bucket); | 114 | sb->first_bucket = le16_to_cpu(s->first_bucket); |
123 | sb->keys = le16_to_cpu(s->keys); | 115 | sb->keys = le16_to_cpu(s->keys); |
124 | 116 | ||
@@ -147,53 +139,77 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev, | |||
147 | if (bch_is_zero(sb->uuid, 16)) | 139 | if (bch_is_zero(sb->uuid, 16)) |
148 | goto err; | 140 | goto err; |
149 | 141 | ||
150 | err = "Unsupported superblock version"; | 142 | switch (sb->version) { |
151 | if (sb->version > BCACHE_SB_VERSION) | 143 | case BCACHE_SB_VERSION_BDEV: |
152 | goto err; | 144 | sb->block_size = le16_to_cpu(s->block_size); |
145 | sb->data_offset = BDEV_DATA_START_DEFAULT; | ||
146 | break; | ||
147 | case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: | ||
148 | sb->block_size = le16_to_cpu(s->block_size); | ||
149 | sb->data_offset = le64_to_cpu(s->data_offset); | ||
150 | |||
151 | err = "Bad data offset"; | ||
152 | if (sb->data_offset < BDEV_DATA_START_DEFAULT) | ||
153 | goto err; | ||
153 | 154 | ||
154 | err = "Bad block/bucket size"; | 155 | break; |
155 | if (!is_power_of_2(sb->block_size) || sb->block_size > PAGE_SECTORS || | 156 | case BCACHE_SB_VERSION_CDEV: |
156 | !is_power_of_2(sb->bucket_size) || sb->bucket_size < PAGE_SECTORS) | 157 | case BCACHE_SB_VERSION_CDEV_WITH_UUID: |
157 | goto err; | 158 | sb->nbuckets = le64_to_cpu(s->nbuckets); |
159 | sb->block_size = le16_to_cpu(s->block_size); | ||
160 | sb->bucket_size = le16_to_cpu(s->bucket_size); | ||
158 | 161 | ||
159 | err = "Too many buckets"; | 162 | sb->nr_in_set = le16_to_cpu(s->nr_in_set); |
160 | if (sb->nbuckets > LONG_MAX) | 163 | sb->nr_this_dev = le16_to_cpu(s->nr_this_dev); |
161 | goto err; | ||
162 | 164 | ||
163 | err = "Not enough buckets"; | 165 | err = "Too many buckets"; |
164 | if (sb->nbuckets < 1 << 7) | 166 | if (sb->nbuckets > LONG_MAX) |
165 | goto err; | 167 | goto err; |
166 | 168 | ||
167 | err = "Invalid superblock: device too small"; | 169 | err = "Not enough buckets"; |
168 | if (get_capacity(bdev->bd_disk) < sb->bucket_size * sb->nbuckets) | 170 | if (sb->nbuckets < 1 << 7) |
169 | goto err; | 171 | goto err; |
170 | 172 | ||
171 | if (sb->version == CACHE_BACKING_DEV) | 173 | err = "Bad block/bucket size"; |
172 | goto out; | 174 | if (!is_power_of_2(sb->block_size) || |
175 | sb->block_size > PAGE_SECTORS || | ||
176 | !is_power_of_2(sb->bucket_size) || | ||
177 | sb->bucket_size < PAGE_SECTORS) | ||
178 | goto err; | ||
173 | 179 | ||
174 | err = "Bad UUID"; | 180 | err = "Invalid superblock: device too small"; |
175 | if (bch_is_zero(sb->set_uuid, 16)) | 181 | if (get_capacity(bdev->bd_disk) < sb->bucket_size * sb->nbuckets) |
176 | goto err; | 182 | goto err; |
177 | 183 | ||
178 | err = "Bad cache device number in set"; | 184 | err = "Bad UUID"; |
179 | if (!sb->nr_in_set || | 185 | if (bch_is_zero(sb->set_uuid, 16)) |
180 | sb->nr_in_set <= sb->nr_this_dev || | 186 | goto err; |
181 | sb->nr_in_set > MAX_CACHES_PER_SET) | ||
182 | goto err; | ||
183 | 187 | ||
184 | err = "Journal buckets not sequential"; | 188 | err = "Bad cache device number in set"; |
185 | for (i = 0; i < sb->keys; i++) | 189 | if (!sb->nr_in_set || |
186 | if (sb->d[i] != sb->first_bucket + i) | 190 | sb->nr_in_set <= sb->nr_this_dev || |
191 | sb->nr_in_set > MAX_CACHES_PER_SET) | ||
187 | goto err; | 192 | goto err; |
188 | 193 | ||
189 | err = "Too many journal buckets"; | 194 | err = "Journal buckets not sequential"; |
190 | if (sb->first_bucket + sb->keys > sb->nbuckets) | 195 | for (i = 0; i < sb->keys; i++) |
191 | goto err; | 196 | if (sb->d[i] != sb->first_bucket + i) |
197 | goto err; | ||
192 | 198 | ||
193 | err = "Invalid superblock: first bucket comes before end of super"; | 199 | err = "Too many journal buckets"; |
194 | if (sb->first_bucket * sb->bucket_size < 16) | 200 | if (sb->first_bucket + sb->keys > sb->nbuckets) |
201 | goto err; | ||
202 | |||
203 | err = "Invalid superblock: first bucket comes before end of super"; | ||
204 | if (sb->first_bucket * sb->bucket_size < 16) | ||
205 | goto err; | ||
206 | |||
207 | break; | ||
208 | default: | ||
209 | err = "Unsupported superblock version"; | ||
195 | goto err; | 210 | goto err; |
196 | out: | 211 | } |
212 | |||
197 | sb->last_mount = get_seconds(); | 213 | sb->last_mount = get_seconds(); |
198 | err = NULL; | 214 | err = NULL; |
199 | 215 | ||
@@ -286,7 +302,7 @@ void bcache_write_super(struct cache_set *c) | |||
286 | for_each_cache(ca, c, i) { | 302 | for_each_cache(ca, c, i) { |
287 | struct bio *bio = &ca->sb_bio; | 303 | struct bio *bio = &ca->sb_bio; |
288 | 304 | ||
289 | ca->sb.version = BCACHE_SB_VERSION; | 305 | ca->sb.version = BCACHE_SB_VERSION_CDEV_WITH_UUID; |
290 | ca->sb.seq = c->sb.seq; | 306 | ca->sb.seq = c->sb.seq; |
291 | ca->sb.last_mount = c->sb.last_mount; | 307 | ca->sb.last_mount = c->sb.last_mount; |
292 | 308 | ||
@@ -1049,7 +1065,7 @@ static const char *register_bdev(struct cache_sb *sb, struct page *sb_page, | |||
1049 | 1065 | ||
1050 | g = dc->disk.disk; | 1066 | g = dc->disk.disk; |
1051 | 1067 | ||
1052 | set_capacity(g, dc->bdev->bd_part->nr_sects - 16); | 1068 | set_capacity(g, dc->bdev->bd_part->nr_sects - dc->sb.data_offset); |
1053 | 1069 | ||
1054 | bch_cached_dev_request_init(dc); | 1070 | bch_cached_dev_request_init(dc); |
1055 | 1071 | ||
@@ -1802,7 +1818,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, | |||
1802 | if (err) | 1818 | if (err) |
1803 | goto err_close; | 1819 | goto err_close; |
1804 | 1820 | ||
1805 | if (sb->version == CACHE_BACKING_DEV) { | 1821 | if (SB_IS_BDEV(sb)) { |
1806 | struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL); | 1822 | struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL); |
1807 | 1823 | ||
1808 | err = register_bdev(sb, sb_page, bdev, dc); | 1824 | err = register_bdev(sb, sb_page, bdev, dc); |