diff mbox

[1/4] btrfs-progs: Limit inline extent below page size

Message ID 20180301024747.26192-2-wqu@suse.com (mailing list archive)
State New, archived
Headers show

Commit Message

Qu Wenruo March 1, 2018, 2:47 a.m. UTC
Kernel doesn't support to drop extent inside an inlined extent.
And kernel tends to limit inline extent just below sectorsize, so also
limit it in btrfs-progs.

This fixes unexpected -EOPNOTSUPP error from __btrfs_drop_extents() on
converted btrfs.

Fixes: 806528b8755f ("Add Yan Zheng's ext3->btrfs conversion program")
Reported-by: Peter Y. Chuang <peteryuchuang@gmail.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 ctree.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

Comments

Nikolay Borisov March 1, 2018, 5:47 p.m. UTC | #1
On  1.03.2018 04:47, Qu Wenruo wrote:
> Kernel doesn't support to drop extent inside an inlined extent.
> And kernel tends to limit inline extent just below sectorsize, so also
> limit it in btrfs-progs.
> 
> This fixes unexpected -EOPNOTSUPP error from __btrfs_drop_extents() on
> converted btrfs.
> 
> Fixes: 806528b8755f ("Add Yan Zheng's ext3->btrfs conversion program")
> Reported-by: Peter Y. Chuang <peteryuchuang@gmail.com>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>  ctree.h | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/ctree.h b/ctree.h
> index 17cdac76c58c..0282deef339b 100644
> --- a/ctree.h
> +++ b/ctree.h
> @@ -20,6 +20,7 @@
>  #define __BTRFS_CTREE_H__
>  
>  #include <stdbool.h>
> +#include "internal.h"
>  
>  #if BTRFS_FLAT_INCLUDES
>  #include "list.h"
> @@ -1195,8 +1196,14 @@ static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_fs_info *info)
>  	(offsetof(struct btrfs_file_extent_item, disk_bytenr))
>  static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_fs_info *info)
>  {
> -	return BTRFS_MAX_ITEM_SIZE(info) -
> -		BTRFS_FILE_EXTENT_INLINE_DATA_START;
> +	/*
> +	 * Inline extent larger than pagesize could lead to kernel unexpected
> +	 * error when dropping extents, so we need to limit the inline extent
> +	 * size to less than sectorsize.
> +	 */
> +	return min_t(u32, info->sectorsize - 1,
> +		     BTRFS_MAX_ITEM_SIZE(info) -
> +		     BTRFS_FILE_EXTENT_INLINE_DATA_START);
>  }

Isn't the same change required in the kernel as well ?

>  
>  static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info)
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Qu Wenruo March 1, 2018, 11:43 p.m. UTC | #2
On 2018年03月02日 01:47, Nikolay Borisov wrote:
> 
> 
> On  1.03.2018 04:47, Qu Wenruo wrote:
>> Kernel doesn't support to drop extent inside an inlined extent.
>> And kernel tends to limit inline extent just below sectorsize, so also
>> limit it in btrfs-progs.
>>
>> This fixes unexpected -EOPNOTSUPP error from __btrfs_drop_extents() on
>> converted btrfs.
>>
>> Fixes: 806528b8755f ("Add Yan Zheng's ext3->btrfs conversion program")
>> Reported-by: Peter Y. Chuang <peteryuchuang@gmail.com>
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>> ---
>>  ctree.h | 11 +++++++++--
>>  1 file changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/ctree.h b/ctree.h
>> index 17cdac76c58c..0282deef339b 100644
>> --- a/ctree.h
>> +++ b/ctree.h
>> @@ -20,6 +20,7 @@
>>  #define __BTRFS_CTREE_H__
>>  
>>  #include <stdbool.h>
>> +#include "internal.h"
>>  
>>  #if BTRFS_FLAT_INCLUDES
>>  #include "list.h"
>> @@ -1195,8 +1196,14 @@ static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_fs_info *info)
>>  	(offsetof(struct btrfs_file_extent_item, disk_bytenr))
>>  static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_fs_info *info)
>>  {
>> -	return BTRFS_MAX_ITEM_SIZE(info) -
>> -		BTRFS_FILE_EXTENT_INLINE_DATA_START;
>> +	/*
>> +	 * Inline extent larger than pagesize could lead to kernel unexpected
>> +	 * error when dropping extents, so we need to limit the inline extent
>> +	 * size to less than sectorsize.
>> +	 */
>> +	return min_t(u32, info->sectorsize - 1,
>> +		     BTRFS_MAX_ITEM_SIZE(info) -
>> +		     BTRFS_FILE_EXTENT_INLINE_DATA_START);
>>  }
> 
> Isn't the same change required in the kernel as well ?

Yep, kernel patch underway.

Although, kernel puts a lot of extra check into cow_file_range_inline()
instead of using the macro directly, I would like to enhance the check
in parse_options() so we could get a correct max_inline prompt.
(Currently we could pass max_inline=4096, and kernel prompt also shows
4096, while we can only inline 4095 bytes)

Thanks,
Qu

> 
>>  
>>  static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info)
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
David Sterba March 9, 2018, 4:51 p.m. UTC | #3
On Thu, Mar 01, 2018 at 10:47:44AM +0800, Qu Wenruo wrote:
> Kernel doesn't support to drop extent inside an inlined extent.
> And kernel tends to limit inline extent just below sectorsize, so also
> limit it in btrfs-progs.
> 
> This fixes unexpected -EOPNOTSUPP error from __btrfs_drop_extents() on
> converted btrfs.
> 
> Fixes: 806528b8755f ("Add Yan Zheng's ext3->btrfs conversion program")
> Reported-by: Peter Y. Chuang <peteryuchuang@gmail.com>
> Signed-off-by: Qu Wenruo <wqu@suse.com>

This patch breaks test fsck/020-extent-ref-cases for image
inline_regular_coexist.img .
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/ctree.h b/ctree.h
index 17cdac76c58c..0282deef339b 100644
--- a/ctree.h
+++ b/ctree.h
@@ -20,6 +20,7 @@ 
 #define __BTRFS_CTREE_H__
 
 #include <stdbool.h>
+#include "internal.h"
 
 #if BTRFS_FLAT_INCLUDES
 #include "list.h"
@@ -1195,8 +1196,14 @@  static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_fs_info *info)
 	(offsetof(struct btrfs_file_extent_item, disk_bytenr))
 static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_fs_info *info)
 {
-	return BTRFS_MAX_ITEM_SIZE(info) -
-		BTRFS_FILE_EXTENT_INLINE_DATA_START;
+	/*
+	 * Inline extent larger than pagesize could lead to kernel unexpected
+	 * error when dropping extents, so we need to limit the inline extent
+	 * size to less than sectorsize.
+	 */
+	return min_t(u32, info->sectorsize - 1,
+		     BTRFS_MAX_ITEM_SIZE(info) -
+		     BTRFS_FILE_EXTENT_INLINE_DATA_START);
 }
 
 static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info)