summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs_mgr/liblp/builder.cpp78
-rw-r--r--fs_mgr/liblp/builder_test.cpp50
-rw-r--r--fs_mgr/liblp/include/liblp/builder.h23
-rw-r--r--fs_mgr/liblp/include/liblp/metadata_format.h6
-rw-r--r--fs_mgr/liblp/utility_test.cpp3
5 files changed, 125 insertions, 35 deletions
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index d3c785d33..eb429b930 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -48,10 +48,20 @@ bool GetBlockDeviceInfo(const std::string& block_device, BlockDeviceInfo* device
48 PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed"; 48 PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
49 return false; 49 return false;
50 } 50 }
51 if (ioctl(fd, BLKALIGNOFF, &device_info->alignment_offset) < 0) { 51
52 int alignment_offset;
53 if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
52 PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed"; 54 PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
53 return false; 55 return false;
54 } 56 }
57 int logical_block_size;
58 if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
59 PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed";
60 return false;
61 }
62
63 device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
64 device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
55 return true; 65 return true;
56#else 66#else
57 (void)block_device; 67 (void)block_device;
@@ -178,6 +188,7 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) {
178 188
179 device_info_.alignment = geometry_.alignment; 189 device_info_.alignment = geometry_.alignment;
180 device_info_.alignment_offset = geometry_.alignment_offset; 190 device_info_.alignment_offset = geometry_.alignment_offset;
191 device_info_.logical_block_size = geometry_.logical_block_size;
181 return true; 192 return true;
182} 193}
183 194
@@ -201,6 +212,10 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata
201 LERROR << "Block device size must be a multiple of 512."; 212 LERROR << "Block device size must be a multiple of 512.";
202 return false; 213 return false;
203 } 214 }
215 if (device_info_.logical_block_size % LP_SECTOR_SIZE != 0) {
216 LERROR << "Logical block size must be a multiple of 512.";
217 return false;
218 }
204 if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) { 219 if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) {
205 LERROR << "Alignment offset is not sector-aligned."; 220 LERROR << "Alignment offset is not sector-aligned.";
206 return false; 221 return false;
@@ -244,6 +259,18 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata
244 return false; 259 return false;
245 } 260 }
246 261
262 // Finally, the size of the allocatable space must be a multiple of the
263 // logical block size. If we have no more free space after this
264 // computation, then we abort. Note that the last sector is inclusive,
265 // so we have to account for that.
266 uint64_t num_free_sectors = last_sector - first_sector + 1;
267 uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
268 if (num_free_sectors < sectors_per_block) {
269 LERROR << "Not enough space to allocate any partition tables.";
270 return false;
271 }
272 last_sector = first_sector + (num_free_sectors / sectors_per_block) * sectors_per_block - 1;
273
247 geometry_.first_logical_sector = first_sector; 274 geometry_.first_logical_sector = first_sector;
248 geometry_.last_logical_sector = last_sector; 275 geometry_.last_logical_sector = last_sector;
249 geometry_.metadata_max_size = metadata_max_size; 276 geometry_.metadata_max_size = metadata_max_size;
@@ -251,6 +278,7 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata
251 geometry_.alignment = device_info_.alignment; 278 geometry_.alignment = device_info_.alignment;
252 geometry_.alignment_offset = device_info_.alignment_offset; 279 geometry_.alignment_offset = device_info_.alignment_offset;
253 geometry_.block_device_size = device_info_.size; 280 geometry_.block_device_size = device_info_.size;
281 geometry_.logical_block_size = device_info.logical_block_size;
254 return true; 282 return true;
255} 283}
256 284
@@ -297,6 +325,7 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size)
297 uint64_t end; 325 uint64_t end;
298 326
299 Interval(uint64_t start, uint64_t end) : start(start), end(end) {} 327 Interval(uint64_t start, uint64_t end) : start(start), end(end) {}
328 uint64_t length() const { return end - start; }
300 bool operator<(const Interval& other) const { return start < other.start; } 329 bool operator<(const Interval& other) const { return start < other.start; }
301 }; 330 };
302 331
@@ -343,31 +372,46 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size)
343 free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1); 372 free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1);
344 } 373 }
345 374
375 const uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
376 CHECK(sectors_needed % sectors_per_block == 0);
377
346 // Find gaps that we can use for new extents. Note we store new extents in a 378 // Find gaps that we can use for new extents. Note we store new extents in a
347 // temporary vector, and only commit them if we are guaranteed enough free 379 // temporary vector, and only commit them if we are guaranteed enough free
348 // space. 380 // space.
349 std::vector<std::unique_ptr<LinearExtent>> new_extents; 381 std::vector<std::unique_ptr<LinearExtent>> new_extents;
350 for (const auto& region : free_regions) { 382 for (auto& region : free_regions) {
351 // This gap is enough to hold the remainder of the space requested, so we 383 if (region.length() % sectors_per_block != 0) {
352 // can allocate what we need and return. 384 // This should never happen, because it would imply that we
353 if (region.end - region.start >= sectors_needed) { 385 // once allocated an extent that was not a multiple of the
354 auto extent = std::make_unique<LinearExtent>(sectors_needed, region.start); 386 // block size. That extent would be rejected by DM_TABLE_LOAD.
355 sectors_needed -= extent->num_sectors(); 387 LERROR << "Region " << region.start << ".." << region.end
356 new_extents.push_back(std::move(extent)); 388 << " is not a multiple of the block size, " << sectors_per_block;
357 break; 389
390 // If for some reason the final region is mis-sized we still want
391 // to be able to grow partitions. So just to be safe, round the
392 // region down to the nearest block.
393 region.end = region.start + (region.length() / sectors_per_block) * sectors_per_block;
394 if (!region.length()) {
395 continue;
396 }
358 } 397 }
359 398
360 // This gap is not big enough to fit the remainder of the space requested, 399 uint64_t sectors = std::min(sectors_needed, region.length());
361 // so consume the whole thing and keep looking for more. 400 CHECK(sectors % sectors_per_block == 0);
362 auto extent = std::make_unique<LinearExtent>(region.end - region.start, region.start); 401
363 sectors_needed -= extent->num_sectors(); 402 auto extent = std::make_unique<LinearExtent>(sectors, region.start);
364 new_extents.push_back(std::move(extent)); 403 new_extents.push_back(std::move(extent));
404 sectors_needed -= sectors;
405 if (!sectors_needed) {
406 break;
407 }
365 } 408 }
366 if (sectors_needed) { 409 if (sectors_needed) {
367 LERROR << "Not enough free space to expand partition: " << partition->name(); 410 LERROR << "Not enough free space to expand partition: " << partition->name();
368 return false; 411 return false;
369 } 412 }
370 413
414 // Everything succeeded, so commit the new extents.
371 for (auto& extent : new_extents) { 415 for (auto& extent : new_extents) {
372 partition->AddExtent(std::move(extent)); 416 partition->AddExtent(std::move(extent));
373 } 417 }
@@ -435,6 +479,12 @@ uint64_t MetadataBuilder::AlignSector(uint64_t sector) {
435void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) { 479void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) {
436 device_info_.size = device_info.size; 480 device_info_.size = device_info.size;
437 481
482 // Note that if the logical block size changes, we're probably in trouble:
483 // we could have already built extents that will only work on the previous
484 // size.
485 DCHECK(partitions_.empty() ||
486 device_info_.logical_block_size == device_info.logical_block_size);
487
438 // The kernel does not guarantee these values are present, so we only 488 // The kernel does not guarantee these values are present, so we only
439 // replace existing values if the new values are non-zero. 489 // replace existing values if the new values are non-zero.
440 if (device_info.alignment) { 490 if (device_info.alignment) {
@@ -447,7 +497,7 @@ void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info)
447 497
448bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) { 498bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
449 // Align the space needed up to the nearest sector. 499 // Align the space needed up to the nearest sector.
450 uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE); 500 uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size);
451 501
452 if (aligned_size > partition->size()) { 502 if (aligned_size > partition->size()) {
453 return GrowPartition(partition, aligned_size); 503 return GrowPartition(partition, aligned_size);
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 4334d51a5..f1a91c479 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -92,11 +92,11 @@ TEST(liblp, PartitionAlignment) {
92 Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY); 92 Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
93 ASSERT_NE(system, nullptr); 93 ASSERT_NE(system, nullptr);
94 EXPECT_EQ(builder->ResizePartition(system, 10000), true); 94 EXPECT_EQ(builder->ResizePartition(system, 10000), true);
95 EXPECT_EQ(system->size(), 10240); 95 EXPECT_EQ(system->size(), 12288);
96 EXPECT_EQ(system->extents().size(), 1); 96 EXPECT_EQ(system->extents().size(), 1);
97 97
98 builder->ResizePartition(system, 9000); 98 builder->ResizePartition(system, 7000);
99 EXPECT_EQ(system->size(), 9216); 99 EXPECT_EQ(system->size(), 8192);
100 EXPECT_EQ(system->extents().size(), 1); 100 EXPECT_EQ(system->extents().size(), 1);
101} 101}
102 102
@@ -120,13 +120,13 @@ TEST(liblp, MetadataAlignment) {
120 120
121TEST(liblp, InternalAlignment) { 121TEST(liblp, InternalAlignment) {
122 // Test the metadata fitting within alignment. 122 // Test the metadata fitting within alignment.
123 BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0); 123 BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0, 4096);
124 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2); 124 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2);
125 ASSERT_NE(builder, nullptr); 125 ASSERT_NE(builder, nullptr);
126 unique_ptr<LpMetadata> exported = builder->Export(); 126 unique_ptr<LpMetadata> exported = builder->Export();
127 ASSERT_NE(exported, nullptr); 127 ASSERT_NE(exported, nullptr);
128 EXPECT_EQ(exported->geometry.first_logical_sector, 1536); 128 EXPECT_EQ(exported->geometry.first_logical_sector, 1536);
129 EXPECT_EQ(exported->geometry.last_logical_sector, 2035); 129 EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
130 130
131 // Test a large alignment offset thrown in. 131 // Test a large alignment offset thrown in.
132 device_info.alignment_offset = 753664; 132 device_info.alignment_offset = 753664;
@@ -135,7 +135,7 @@ TEST(liblp, InternalAlignment) {
135 exported = builder->Export(); 135 exported = builder->Export();
136 ASSERT_NE(exported, nullptr); 136 ASSERT_NE(exported, nullptr);
137 EXPECT_EQ(exported->geometry.first_logical_sector, 1472); 137 EXPECT_EQ(exported->geometry.first_logical_sector, 1472);
138 EXPECT_EQ(exported->geometry.last_logical_sector, 2035); 138 EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
139 139
140 // Alignment offset without alignment doesn't mean anything. 140 // Alignment offset without alignment doesn't mean anything.
141 device_info.alignment = 0; 141 device_info.alignment = 0;
@@ -150,7 +150,7 @@ TEST(liblp, InternalAlignment) {
150 exported = builder->Export(); 150 exported = builder->Export();
151 ASSERT_NE(exported, nullptr); 151 ASSERT_NE(exported, nullptr);
152 EXPECT_EQ(exported->geometry.first_logical_sector, 78); 152 EXPECT_EQ(exported->geometry.first_logical_sector, 78);
153 EXPECT_EQ(exported->geometry.last_logical_sector, 1975); 153 EXPECT_EQ(exported->geometry.last_logical_sector, 1973);
154 154
155 // Test a small alignment with no alignment offset. 155 // Test a small alignment with no alignment offset.
156 device_info.alignment = 11 * 1024; 156 device_info.alignment = 11 * 1024;
@@ -163,7 +163,7 @@ TEST(liblp, InternalAlignment) {
163} 163}
164 164
165TEST(liblp, InternalPartitionAlignment) { 165TEST(liblp, InternalPartitionAlignment) {
166 BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664); 166 BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664, 4096);
167 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2); 167 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
168 168
169 Partition* a = builder->AddPartition("a", TEST_GUID, 0); 169 Partition* a = builder->AddPartition("a", TEST_GUID, 0);
@@ -381,7 +381,7 @@ TEST(liblp, MetadataTooLarge) {
381 static const size_t kMetadataSize = 64 * 1024; 381 static const size_t kMetadataSize = 64 * 1024;
382 382
383 // No space to store metadata + geometry. 383 // No space to store metadata + geometry.
384 BlockDeviceInfo device_info(kDiskSize, 0, 0); 384 BlockDeviceInfo device_info(kDiskSize, 0, 0, 4096);
385 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1); 385 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
386 EXPECT_EQ(builder, nullptr); 386 EXPECT_EQ(builder, nullptr);
387 387
@@ -390,8 +390,8 @@ TEST(liblp, MetadataTooLarge) {
390 builder = MetadataBuilder::New(device_info, kMetadataSize, 1); 390 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
391 EXPECT_EQ(builder, nullptr); 391 EXPECT_EQ(builder, nullptr);
392 392
393 // Space for metadata + geometry + one free sector. 393 // Space for metadata + geometry + one free block.
394 device_info.size += LP_SECTOR_SIZE; 394 device_info.size += device_info.logical_block_size;
395 builder = MetadataBuilder::New(device_info, kMetadataSize, 1); 395 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
396 EXPECT_NE(builder, nullptr); 396 EXPECT_NE(builder, nullptr);
397 397
@@ -424,19 +424,21 @@ TEST(liblp, block_device_info) {
424 ASSERT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0); 424 ASSERT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
425 ASSERT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0); 425 ASSERT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0);
426 ASSERT_LE(device_info.alignment_offset, INT_MAX); 426 ASSERT_LE(device_info.alignment_offset, INT_MAX);
427 ASSERT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
427 428
428 // Having an alignment offset > alignment doesn't really make sense. 429 // Having an alignment offset > alignment doesn't really make sense.
429 ASSERT_LT(device_info.alignment_offset, device_info.alignment); 430 ASSERT_LT(device_info.alignment_offset, device_info.alignment);
430} 431}
431 432
432TEST(liblp, UpdateBlockDeviceInfo) { 433TEST(liblp, UpdateBlockDeviceInfo) {
433 BlockDeviceInfo device_info(1024 * 1024, 4096, 1024); 434 BlockDeviceInfo device_info(1024 * 1024, 4096, 1024, 4096);
434 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1); 435 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
435 ASSERT_NE(builder, nullptr); 436 ASSERT_NE(builder, nullptr);
436 437
437 EXPECT_EQ(builder->block_device_info().size, device_info.size); 438 EXPECT_EQ(builder->block_device_info().size, device_info.size);
438 EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment); 439 EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment);
439 EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset); 440 EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset);
441 EXPECT_EQ(builder->block_device_info().logical_block_size, device_info.logical_block_size);
440 442
441 device_info.alignment = 0; 443 device_info.alignment = 0;
442 device_info.alignment_offset = 2048; 444 device_info.alignment_offset = 2048;
@@ -450,3 +452,27 @@ TEST(liblp, UpdateBlockDeviceInfo) {
450 EXPECT_EQ(builder->block_device_info().alignment, 8192); 452 EXPECT_EQ(builder->block_device_info().alignment, 8192);
451 EXPECT_EQ(builder->block_device_info().alignment_offset, 2048); 453 EXPECT_EQ(builder->block_device_info().alignment_offset, 2048);
452} 454}
455
456TEST(liblp, InvalidBlockSize) {
457 BlockDeviceInfo device_info(1024 * 1024, 0, 0, 513);
458 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
459 EXPECT_EQ(builder, nullptr);
460}
461
462TEST(liblp, AlignedExtentSize) {
463 BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
464 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
465 ASSERT_NE(builder, nullptr);
466
467 Partition* partition = builder->AddPartition("system", TEST_GUID, 0);
468 ASSERT_NE(partition, nullptr);
469 ASSERT_TRUE(builder->ResizePartition(partition, 512));
470 EXPECT_EQ(partition->size(), 4096);
471}
472
473TEST(liblp, AlignedFreeSpace) {
474 // Only one sector free - at least one block is required.
475 BlockDeviceInfo device_info(10240, 0, 0, 4096);
476 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1);
477 ASSERT_EQ(builder, nullptr);
478}
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 0f96e3a60..e83b92297 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -32,11 +32,16 @@ class LinearExtent;
32 32
33// By default, partitions are aligned on a 1MiB boundary. 33// By default, partitions are aligned on a 1MiB boundary.
34static const uint32_t kDefaultPartitionAlignment = 1024 * 1024; 34static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
35static const uint32_t kDefaultBlockSize = 4096;
35 36
36struct BlockDeviceInfo { 37struct BlockDeviceInfo {
37 BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0) {} 38 BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
38 BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset) 39 BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset,
39 : size(size), alignment(alignment), alignment_offset(alignment_offset) {} 40 uint32_t logical_block_size)
41 : size(size),
42 alignment(alignment),
43 alignment_offset(alignment_offset),
44 logical_block_size(logical_block_size) {}
40 // Size of the block device, in bytes. 45 // Size of the block device, in bytes.
41 uint64_t size; 46 uint64_t size;
42 // Optimal target alignment, in bytes. Partition extents will be aligned to 47 // Optimal target alignment, in bytes. Partition extents will be aligned to
@@ -46,6 +51,8 @@ struct BlockDeviceInfo {
46 // |alignment_offset| on the target device is correctly aligned on its 51 // |alignment_offset| on the target device is correctly aligned on its
47 // parent device. This value must be 0 or a multiple of 512. 52 // parent device. This value must be 0 or a multiple of 512.
48 uint32_t alignment_offset; 53 uint32_t alignment_offset;
54 // Block size, for aligning extent sizes and partition sizes.
55 uint32_t logical_block_size;
49}; 56};
50 57
51// Abstraction around dm-targets that can be encoded into logical partition tables. 58// Abstraction around dm-targets that can be encoded into logical partition tables.
@@ -88,6 +95,8 @@ class ZeroExtent final : public Extent {
88}; 95};
89 96
90class Partition final { 97class Partition final {
98 friend class MetadataBuilder;
99
91 public: 100 public:
92 Partition(const std::string& name, const std::string& guid, uint32_t attributes); 101 Partition(const std::string& name, const std::string& guid, uint32_t attributes);
93 102
@@ -97,10 +106,6 @@ class Partition final {
97 // Remove all extents from this partition. 106 // Remove all extents from this partition.
98 void RemoveExtents(); 107 void RemoveExtents();
99 108
100 // Remove and/or shrink extents until the partition is the requested size.
101 // See MetadataBuilder::ShrinkPartition for more information.
102 void ShrinkTo(uint64_t requested_size);
103
104 const std::string& name() const { return name_; } 109 const std::string& name() const { return name_; }
105 uint32_t attributes() const { return attributes_; } 110 uint32_t attributes() const { return attributes_; }
106 const std::string& guid() const { return guid_; } 111 const std::string& guid() const { return guid_; }
@@ -108,6 +113,8 @@ class Partition final {
108 uint64_t size() const { return size_; } 113 uint64_t size() const { return size_; }
109 114
110 private: 115 private:
116 void ShrinkTo(uint64_t aligned_size);
117
111 std::string name_; 118 std::string name_;
112 std::string guid_; 119 std::string guid_;
113 std::vector<std::unique_ptr<Extent>> extents_; 120 std::vector<std::unique_ptr<Extent>> extents_;
@@ -144,7 +151,7 @@ class MetadataBuilder {
144 // size. This is a convenience method for tests. 151 // size. This is a convenience method for tests.
145 static std::unique_ptr<MetadataBuilder> New(uint64_t blockdev_size, uint32_t metadata_max_size, 152 static std::unique_ptr<MetadataBuilder> New(uint64_t blockdev_size, uint32_t metadata_max_size,
146 uint32_t metadata_slot_count) { 153 uint32_t metadata_slot_count) {
147 BlockDeviceInfo device_info(blockdev_size, 0, 0); 154 BlockDeviceInfo device_info(blockdev_size, 0, 0, kDefaultBlockSize);
148 return New(device_info, metadata_max_size, metadata_slot_count); 155 return New(device_info, metadata_max_size, metadata_slot_count);
149 } 156 }
150 157
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index e1323e11e..52c80f7f4 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -136,6 +136,12 @@ typedef struct LpMetadataGeometry {
136 * can be used to verify the geometry against a target device. 136 * can be used to verify the geometry against a target device.
137 */ 137 */
138 uint64_t block_device_size; 138 uint64_t block_device_size;
139
140 /* 76: Logical block size of the super partition block device. This is the
141 * minimal alignment for partition and extent sizes, and it must be a
142 * multiple of LP_SECTOR_SIZE.
143 */
144 uint32_t logical_block_size;
139} __attribute__((packed)) LpMetadataGeometry; 145} __attribute__((packed)) LpMetadataGeometry;
140 146
141/* The logical partition metadata has a number of tables; they are described 147/* The logical partition metadata has a number of tables; they are described
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 092dbf11c..7bf42aed9 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -40,7 +40,8 @@ TEST(liblp, GetMetadataOffset) {
40 80000, 40 80000,
41 0, 41 0,
42 0, 42 0,
43 1024 * 1024}; 43 1024 * 1024,
44 4096};
44 EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), 4096); 45 EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), 4096);
45 EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), 4096 + 16384); 46 EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), 4096 + 16384);
46 EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), 4096 + 16384 * 2); 47 EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), 4096 + 16384 * 2);