linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Ensure size values are rounded down
@ 2017-06-16 11:39 Nikolay Borisov
  2017-06-16 11:39 ` [PATCH v2 1/2] btrfs: Manually implement device_total_bytes getter/setter Nikolay Borisov
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Nikolay Borisov @ 2017-06-16 11:39 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba, Nikolay Borisov

Hello, 

Here is a small series which fixes an issue that got reported internally to 
Suse and which affects devices whose size is not multiple of sectorsize. More
information can be found in the changelog for patch 2

The first patch in the series re-implements the btrfs_device_total_bytes
getter/setters manually so that we can add a WARN_ON to catch future offenders. 
I haven't implemented all 4 function that the macros do since we only ever use
the getter and setter. 

The second patch ensures that all the values passed to the setter are rounded 
down to a multiple of sectorsize. I also have an xfstest patch which passes
after this series is applied. 

Changes since v1: 
 * Moved some of the text from previous cover letter, into patch 2 to make 
 explanation of the bug more coherent. 
 * The first patch now only implements getter/setter while the 2nd patch 
 adds the WARN_ON 

Nikolay Borisov (2):
  btrfs: Manually implement device_total_bytes getter/setter
  btrfs: Round down values which are written for total_bytes_size

 fs/btrfs/ctree.h   | 21 ++++++++++++++++++++-
 fs/btrfs/volumes.c | 18 +++++++++++++-----
 2 files changed, 33 insertions(+), 6 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] btrfs: Manually implement device_total_bytes getter/setter
  2017-06-16 11:39 [PATCH v2 0/2] Ensure size values are rounded down Nikolay Borisov
@ 2017-06-16 11:39 ` Nikolay Borisov
  2017-06-16 11:39 ` [PATCH v2 2/2] btrfs: Round down values which are written for total_bytes_size Nikolay Borisov
  2017-06-19 16:34 ` [PATCH v2 0/2] Ensure size values are rounded down David Sterba
  2 siblings, 0 replies; 5+ messages in thread
From: Nikolay Borisov @ 2017-06-16 11:39 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba, Nikolay Borisov

The device->total_bytes member needs to always be rounded down to sectorsize
so that it corresponds to the value of super->total_bytes. However, there are
multiple places where the setter is fed a value which is not rounded which
can cause a fs to be unmountable due to the check introduced in
99e3ecfcb9f4 ("Btrfs: add more validation checks for superblock"). This patch
implements the getter/setter manually so that in a later patch I can add
necessary code to catch offenders.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 fs/btrfs/ctree.h | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 0334452a7be1..ce4929ad5914 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1552,8 +1552,26 @@ static inline void btrfs_set_##name(type *s, u##bits val)		\
 	s->member = cpu_to_le##bits(val);				\
 }
 
+
+static inline u64 btrfs_device_total_bytes(struct extent_buffer *eb,
+					   struct btrfs_dev_item *s)
+{
+	BUILD_BUG_ON(sizeof(u64) !=
+		     sizeof(((struct btrfs_dev_item *)0))->total_bytes);
+	return btrfs_get_64(eb, s, offsetof(struct btrfs_dev_item,
+					    total_bytes));
+}
+static inline void btrfs_set_device_total_bytes(struct extent_buffer *eb,
+						struct btrfs_dev_item *s,
+						u64 val)
+{
+	BUILD_BUG_ON(sizeof(u64) !=
+		     sizeof(((struct btrfs_dev_item *)0))->total_bytes);
+	btrfs_set_64(eb, s, offsetof(struct btrfs_dev_item, total_bytes), val);
+}
+
+
 BTRFS_SETGET_FUNCS(device_type, struct btrfs_dev_item, type, 64);
-BTRFS_SETGET_FUNCS(device_total_bytes, struct btrfs_dev_item, total_bytes, 64);
 BTRFS_SETGET_FUNCS(device_bytes_used, struct btrfs_dev_item, bytes_used, 64);
 BTRFS_SETGET_FUNCS(device_io_align, struct btrfs_dev_item, io_align, 32);
 BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] btrfs: Round down values which are written for total_bytes_size
  2017-06-16 11:39 [PATCH v2 0/2] Ensure size values are rounded down Nikolay Borisov
  2017-06-16 11:39 ` [PATCH v2 1/2] btrfs: Manually implement device_total_bytes getter/setter Nikolay Borisov
@ 2017-06-16 11:39 ` Nikolay Borisov
  2017-06-18  3:09   ` Duncan
  2017-06-19 16:34 ` [PATCH v2 0/2] Ensure size values are rounded down David Sterba
  2 siblings, 1 reply; 5+ messages in thread
From: Nikolay Borisov @ 2017-06-16 11:39 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba, Nikolay Borisov

We got an internal report about a file system not wanting to mount
following 99e3ecfcb9f4 ("Btrfs: add more validation checks for superblock").

BTRFS error (device sdb1): super_total_bytes 1000203816960 mismatch with
fs_devices total_rw_bytes 1000203820544

Substracting the numbers we get a difference of less than a 4kb. Upon closer
inspection it became apparent that mkfs actually rounds down the size of the
device to a multiple of sector size. However, the same cannot be said for
various functions which modify the total size and are called from btrfs_balanace
as well as when adding a new device. So this patch ensures that values being
saved into on-disk data structures are always rounded down to a multiple of
sectorsize

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 fs/btrfs/ctree.h   |  1 +
 fs/btrfs/volumes.c | 18 +++++++++++++-----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ce4929ad5914..a75a23f9d68e 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1567,6 +1567,7 @@ static inline void btrfs_set_device_total_bytes(struct extent_buffer *eb,
 {
 	BUILD_BUG_ON(sizeof(u64) !=
 		     sizeof(((struct btrfs_dev_item *)0))->total_bytes);
+	WARN_ON(!IS_ALIGNED(val, eb->fs_info->sectorsize));
 	btrfs_set_64(eb, s, offsetof(struct btrfs_dev_item, total_bytes), val);
 }
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e37f95976443..adf32f46a73f 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2387,7 +2387,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
 	device->io_width = fs_info->sectorsize;
 	device->io_align = fs_info->sectorsize;
 	device->sector_size = fs_info->sectorsize;
-	device->total_bytes = i_size_read(bdev->bd_inode);
+	device->total_bytes = round_down(i_size_read(bdev->bd_inode),
+					 fs_info->sectorsize);
 	device->disk_total_bytes = device->total_bytes;
 	device->commit_total_bytes = device->total_bytes;
 	device->fs_info = fs_info;
@@ -2424,7 +2425,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
 
 	tmp = btrfs_super_total_bytes(fs_info->super_copy);
 	btrfs_set_super_total_bytes(fs_info->super_copy,
-				    tmp + device->total_bytes);
+		round_down(tmp + device->total_bytes, fs_info->sectorsize));
 
 	tmp = btrfs_super_num_devices(fs_info->super_copy);
 	btrfs_set_super_num_devices(fs_info->super_copy, tmp + 1);
@@ -2687,6 +2688,8 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
 	if (!device->writeable)
 		return -EACCES;
 
+	new_size = round_down(new_size, fs_info->sectorsize);
+
 	mutex_lock(&fs_info->chunk_mutex);
 	old_total = btrfs_super_total_bytes(super_copy);
 	diff = new_size - device->total_bytes;
@@ -2699,7 +2702,8 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
 
 	fs_devices = fs_info->fs_devices;
 
-	btrfs_set_super_total_bytes(super_copy, old_total + diff);
+	btrfs_set_super_total_bytes(super_copy,
+			round_down(old_total + diff, fs_info->sectorsize));
 	device->fs_devices->total_rw_bytes += diff;
 
 	btrfs_device_set_total_bytes(device, new_size);
@@ -4389,7 +4393,10 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
 	struct btrfs_super_block *super_copy = fs_info->super_copy;
 	u64 old_total = btrfs_super_total_bytes(super_copy);
 	u64 old_size = btrfs_device_get_total_bytes(device);
-	u64 diff = old_size - new_size;
+	u64 diff;
+
+	new_size = round_down(new_size, fs_info->sectorsize);
+	diff = old_size - new_size;
 
 	if (device->is_tgtdev_for_dev_replace)
 		return -EINVAL;
@@ -4516,7 +4523,8 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
 			      &fs_info->fs_devices->resized_devices);
 
 	WARN_ON(diff > old_total);
-	btrfs_set_super_total_bytes(super_copy, old_total - diff);
+	btrfs_set_super_total_bytes(super_copy,
+			round_down(old_total - diff, fs_info->sectorsize));
 	mutex_unlock(&fs_info->chunk_mutex);
 
 	/* Now btrfs_update_device() will change the on-disk size. */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] btrfs: Round down values which are written for total_bytes_size
  2017-06-16 11:39 ` [PATCH v2 2/2] btrfs: Round down values which are written for total_bytes_size Nikolay Borisov
@ 2017-06-18  3:09   ` Duncan
  0 siblings, 0 replies; 5+ messages in thread
From: Duncan @ 2017-06-18  3:09 UTC (permalink / raw)
  To: linux-btrfs

Nikolay Borisov posted on Fri, 16 Jun 2017 14:39:20 +0300 as excerpted:

Not a dev but I can read descriptions.  Three typos in this paragraph:

> Substracting the numbers we get a difference of less than a 4kb. Upon

Subtracting

> closer inspection it became apparent that mkfs actually rounds down the
> size of the device to a multiple of sector size. However, the same
> cannot be said for various functions which modify the total size and are
> called from btrfs_balanace as well as when adding a new device. So this

btrfs_balance

> patch ensures that values being saved into on-disk data structures are
> always rounded down to a multiple of sectorsize

Missing sentence-terminating "."

(They're likely trivial enough to be fixed at apply time if there's no 
further code changes.)

-- 
Duncan - List replies preferred.   No HTML msgs.
"Every nonfree program has a lord, a master --
and if you use the program, he is your master."  Richard Stallman


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/2] Ensure size values are rounded down
  2017-06-16 11:39 [PATCH v2 0/2] Ensure size values are rounded down Nikolay Borisov
  2017-06-16 11:39 ` [PATCH v2 1/2] btrfs: Manually implement device_total_bytes getter/setter Nikolay Borisov
  2017-06-16 11:39 ` [PATCH v2 2/2] btrfs: Round down values which are written for total_bytes_size Nikolay Borisov
@ 2017-06-19 16:34 ` David Sterba
  2 siblings, 0 replies; 5+ messages in thread
From: David Sterba @ 2017-06-19 16:34 UTC (permalink / raw)
  To: Nikolay Borisov; +Cc: linux-btrfs, dsterba

On Fri, Jun 16, 2017 at 02:39:18PM +0300, Nikolay Borisov wrote:
> Hello, 
> 
> Here is a small series which fixes an issue that got reported internally to 
> Suse and which affects devices whose size is not multiple of sectorsize. More
> information can be found in the changelog for patch 2
> 
> The first patch in the series re-implements the btrfs_device_total_bytes
> getter/setters manually so that we can add a WARN_ON to catch future offenders. 
> I haven't implemented all 4 function that the macros do since we only ever use
> the getter and setter. 
> 
> The second patch ensures that all the values passed to the setter are rounded 
> down to a multiple of sectorsize. I also have an xfstest patch which passes
> after this series is applied. 
> 
> Changes since v1: 
>  * Moved some of the text from previous cover letter, into patch 2 to make 
>  explanation of the bug more coherent. 
>  * The first patch now only implements getter/setter while the 2nd patch 
>  adds the WARN_ON 
> 
> Nikolay Borisov (2):
>   btrfs: Manually implement device_total_bytes getter/setter
>   btrfs: Round down values which are written for total_bytes_size

Added to the queue, with the fixups.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-06-19 16:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-16 11:39 [PATCH v2 0/2] Ensure size values are rounded down Nikolay Borisov
2017-06-16 11:39 ` [PATCH v2 1/2] btrfs: Manually implement device_total_bytes getter/setter Nikolay Borisov
2017-06-16 11:39 ` [PATCH v2 2/2] btrfs: Round down values which are written for total_bytes_size Nikolay Borisov
2017-06-18  3:09   ` Duncan
2017-06-19 16:34 ` [PATCH v2 0/2] Ensure size values are rounded down David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).