linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling
@ 2022-06-29 11:38 Qu Wenruo
  2022-06-29 11:38 ` [PATCH 1/8] fs: fat: unexport file_fat_read_at() Qu Wenruo
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

[CHANGELOG]
RFC->v1:
- More (manual) testing
  Unfortunately, in the latest master (75967970850a), the fs-tests.sh
  always seems to hang at preparing the fs image.

  Thus still has to do manual testing, tested btrfs, ext4 and fat, with
  aligned and unaligned read, also added soft link read, all looks fine here.

  Extra testing is still appreciated.

- Two more btrfs specific bug fixes
  All exposed during manual tests

- Remove the tailing unaligned block handling
  In fact, all fses can easily handle such case, just a min() call is
  enough.

- Remove the support for sandboxfs
  Since it's using read() calls, really no need to do block alignment
  check.

- Enhanced blocksize check
  Ensure the returned blocksize is not only non-error, but also
  non-zero.

This patchset can be fetched from github:
https://github.com/adam900710/u-boot/tree/fs_unaligned_read

[BACKGROUND]
Unlike FUSE/Kernel which always pass aligned read range, U-boot fs code
just pass the request range to underlying fses.

Under most case, this works fine, as U-boot only really needs to read
the whole file (aka, 0 for both offset and len, len will be later
determined using file size).

But if some advanced user/script wants to extract kernel/initramfs from
combined image, we may need to do unaligned read in that case.

[ADVANTAGE]
This patchset will handle unaligned read range in _fs_read():

- Get blocksize of the underlying fs

- Read the leading block contianing the unaligned range
  The full block will be stored in a local buffer, then only copy
  the bytes in the unaligned range into the destination buffer.

  If the first block covers the whole range, we just call it aday.

- Read the remaining range which starts at block aligned offset
  For most common case, which is 0 offset and 0 len, the code will not
  be changed at all.

Just one extra get_blocksize() call, and for FAT/Btrfs/EROFS they all have
cached blocksize, thus it takes almost no extra cost.

Although for EXT4, it doesn't seem to cache the blocksize globally,
thus has to do a path resolve and grab the blocksize.

[DISADVANTAGE]
The involved problem is:

- Extra path resolving
  All those supported fs may have to do one extra path resolve if the
  read offset is not aligned.

  For EXT4, it will do one extra path resolve just to grab the
  blocksize.

For data read which starts at offset 0 (the most common case), it
should cause *NO* difference in performance.
As the extra handling is only for unaligned offset.

The common path is not really modified.

[SUPPORTED FSES]

- Btrfs (manually tested*)
- Ext4 (manually tested)
- FAT (manually tested)
- Erofs
- ubifs (unable to test, due to compile failure)

*: Failed to get the test cases run, thus have to go sandbox mode, and
attach an image with target fs, load the target file (with unaligned
range) and compare the result using md5sum.

For EXT4/FAT, they may need extra cleanup, as their existing unaligned
range handling is no longer needed anymore, cleaning them up should free 
more code lines than the added one.

Just not confident enough to modify them all by myself.

[UNSUPPORTED FSES]
- Squashfs
  They don't support non-zero offset, thus it can not handle the block
  aligned range.
  Need extra help to add block aligned offset support.

- Semihostfs
- Sandboxfs
  They all use read() directly, no need to do alignment check at all.

Extra testing/feedback is always appreciated.

Qu Wenruo (8):
  fs: fat: unexport file_fat_read_at()
  fs: btrfs: fix a bug which no data get read if the length is not 0
  fs: btrfs: fix a crash if specified range is beyond file size
  fs: btrfs: move the unaligned read code to _fs_read() for btrfs
  fs: ext4: rely on _fs_read() to handle leading unaligned block read
  fs: fat: rely on higher layer to get block aligned read range
  fs: ubifs: rely on higher layer to do unaligned read
  fs: erofs: add unaligned read range handling

 fs/btrfs/btrfs.c      |  33 ++++++++---
 fs/btrfs/inode.c      |  89 +++--------------------------
 fs/erofs/internal.h   |   1 +
 fs/erofs/super.c      |   6 ++
 fs/ext4/ext4fs.c      |  22 +++++++
 fs/fat/fat.c          |  17 +++++-
 fs/fs.c               | 130 +++++++++++++++++++++++++++++++++++++++---
 fs/ubifs/ubifs.c      |  13 +++--
 include/btrfs.h       |   1 +
 include/erofs.h       |   1 +
 include/ext4fs.h      |   1 +
 include/fat.h         |   3 +-
 include/ubifs_uboot.h |   1 +
 13 files changed, 212 insertions(+), 106 deletions(-)

-- 
2.36.1


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

* [PATCH 1/8] fs: fat: unexport file_fat_read_at()
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-07-25 22:28   ` Tom Rini
  2022-06-29 11:38 ` [PATCH 2/8] fs: btrfs: fix a bug which no data get read if the length is not 0 Qu Wenruo
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

That function is only utilized inside fat driver, unexport it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/fat/fat.c  | 4 ++--
 include/fat.h | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index df9ea2c028fc..dcceccbcee0a 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1243,8 +1243,8 @@ out_free_itr:
 	return ret;
 }
 
-int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
-		     loff_t maxsize, loff_t *actread)
+static int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
+			    loff_t maxsize, loff_t *actread)
 {
 	fsdata fsdata;
 	fat_itr *itr;
diff --git a/include/fat.h b/include/fat.h
index bd8e450b33a3..a9756fb4cd1b 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -200,8 +200,6 @@ static inline u32 sect_to_clust(fsdata *fsdata, int sect)
 int file_fat_detectfs(void);
 int fat_exists(const char *filename);
 int fat_size(const char *filename, loff_t *size);
-int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
-		     loff_t maxsize, loff_t *actread);
 int file_fat_read(const char *filename, void *buffer, int maxsize);
 int fat_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
 int fat_register_device(struct blk_desc *dev_desc, int part_no);
-- 
2.36.1


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

* [PATCH 2/8] fs: btrfs: fix a bug which no data get read if the length is not 0
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
  2022-06-29 11:38 ` [PATCH 1/8] fs: fat: unexport file_fat_read_at() Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-29 11:38 ` [PATCH 3/8] fs: btrfs: fix a crash if specified range is beyond file size Qu Wenruo
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

[BUG]
When testing with unaligned read, if a specific length is passed in,
btrfs driver will read out nothing:

 => load host 0 $kernel_addr_r 5k_file 0x1000 0
 0 bytes read in 0 ms

But if no length is passed in, it works fine, even if we pass a non-zero
length:

 => load host 0 $kernel_addr_r 5k_file 0 0x1000
 1024 bytes read in 0 ms

[CAUSE]
In btrfs_read() if we have a larger size than our file, we will try to
truncate it using the file size.

However the real file size is not initialized if @len is not zero, thus
we always truncate our length to 0, and cause the problem.

[FIX]
Fix it by just always do the file size check.

In fact btrfs_size() always follow soft link, thus it will return the
real file size correctly.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/btrfs.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index 741c6e20f533..9145727058d4 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -246,16 +246,17 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
 		return -EINVAL;
 	}
 
-	if (!len) {
-		ret = btrfs_size(file, &real_size);
-		if (ret < 0) {
-			error("Failed to get inode size: %s", file);
-			return ret;
-		}
-		len = real_size;
+	ret = btrfs_size(file, &real_size);
+	if (ret < 0) {
+		error("Failed to get inode size: %s", file);
+		return ret;
 	}
 
-	if (len > real_size - offset)
+	/*
+	 * If the length is 0 (meaning read the whole file) or the range is
+	 * beyond file size, truncate it to the end of the file.
+	 */
+	if (!len || len > real_size - offset)
 		len = real_size - offset;
 
 	ret = btrfs_file_read(root, ino, offset, len, buf);
-- 
2.36.1


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

* [PATCH 3/8] fs: btrfs: fix a crash if specified range is beyond file size
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
  2022-06-29 11:38 ` [PATCH 1/8] fs: fat: unexport file_fat_read_at() Qu Wenruo
  2022-06-29 11:38 ` [PATCH 2/8] fs: btrfs: fix a bug which no data get read if the length is not 0 Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-29 11:38 ` [PATCH 4/8] fs: btrfs: move the unaligned read code to _fs_read() for btrfs Qu Wenruo
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

[BUG]
When try to read a range beyond file size, btrfs driver will cause
crash/segfault:

 => load host 0 $kernel_addr_r 5k_file 0 0x2000
 SEGFAULT

[CAUSE]
In btrfs_read(), if @len is 0, we will truncated it to file end, but if
file end is beyond our file size, this truncation will underflow @len,
making it -3K in this case.

And later that @len is used to memzero the output buffer, resulting
above crash.

[FIX]
Just error out if @offset is already beyond our file size.

Now it will fail properly with correct error message:

 => load host 0 $kernel_addr_r 5m_origin 0 0x2000
 BTRFS: Read range beyond file size, offset 8192 file size 5120

 Failed to load '5m_origin'

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/btrfs.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index 9145727058d4..bf9e1f2f17cf 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -252,6 +252,12 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
 		return ret;
 	}
 
+	if (offset >= real_size) {
+		error("Read range beyond file size, offset %llu file size %llu",
+			offset, real_size);
+		return -EINVAL;
+	}
+
 	/*
 	 * If the length is 0 (meaning read the whole file) or the range is
 	 * beyond file size, truncate it to the end of the file.
-- 
2.36.1


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

* [PATCH 4/8] fs: btrfs: move the unaligned read code to _fs_read() for btrfs
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
                   ` (2 preceding siblings ...)
  2022-06-29 11:38 ` [PATCH 3/8] fs: btrfs: fix a crash if specified range is beyond file size Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-29 11:38 ` [PATCH 5/8] fs: ext4: rely on _fs_read() to handle leading unaligned block read Qu Wenruo
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

Unlike FUSE or kernel, U-boot filesystem code makes the underly fs code
to handle the unaligned read (aka, read range is not aligned to fs block
size).

This makes underlying fs code harder to implement, as  they have to handle
unaligned read all by themselves.

This patch will change the behavior, starting from btrfs, by moving the
unaligned read code into _fs_read().

The idea is pretty simple, if we have an unaligned read request, we
handle it in the following steps:

1. Grab the blocksize of the fs

2. Read the leading unaligned range
   We will read the block that @offset is in, and copy the
   requested part into buf.

   The the block we read covers the whole range, we just call it a day.

3. Read the remaining part
   The tailing part may be unaligned, but all fses handles the tailing
   part much easier than the leading unaligned part.

   As they just need to do a min(extent_size, start + len - cur) to
   calculate the real read size.

   In fact, for most file reading, the file size is not aligned and we
   need to handle the tailing part anyway.

There is a btrfs specific cleanup involved:

- In btrfs_file_read(), merge the tailing unaligned read into the main
  loop.
  Just reuse the existing read length calculation is enough.

- Remove read_and_truncate_page() call
  Since there is no explicit leading/tailing unaligned read anymore.

This has been tested with a proper randomly populated btrfs file, then
tried in sandbox mode with different aligned and unaligned range and
compare the output with md5sum.

Cc: Marek Behun <marek.behun@nic.cz>
Cc: linux-btrfs@vger.kernel.org
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/btrfs.c |  10 ++++
 fs/btrfs/inode.c |  89 +++-----------------------------
 fs/fs.c          | 130 ++++++++++++++++++++++++++++++++++++++++++++---
 include/btrfs.h  |   1 +
 4 files changed, 141 insertions(+), 89 deletions(-)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index bf9e1f2f17cf..7c8f4a3dfb87 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -234,6 +234,10 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
 	int ret;
 
 	ASSERT(fs_info);
+
+	/* Higher layer has ensures it never pass unaligned offset in. */
+	ASSERT(IS_ALIGNED(offset, fs_info->sectorsize));
+
 	ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
 				file, &root, &ino, &type, 40);
 	if (ret < 0) {
@@ -275,6 +279,12 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
 	return 0;
 }
 
+int btrfs_get_blocksize(const char *filename)
+{
+	ASSERT(current_fs_info);
+	return current_fs_info->sectorsize;
+}
+
 void btrfs_close(void)
 {
 	if (current_fs_info) {
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d00b5153336d..bef0a972f40d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -620,44 +620,6 @@ check_next:
 	return 1;
 }
 
-static int read_and_truncate_page(struct btrfs_path *path,
-				  struct btrfs_file_extent_item *fi,
-				  int start, int len, char *dest)
-{
-	struct extent_buffer *leaf = path->nodes[0];
-	struct btrfs_fs_info *fs_info = leaf->fs_info;
-	u64 aligned_start = round_down(start, fs_info->sectorsize);
-	u8 extent_type;
-	char *buf;
-	int page_off = start - aligned_start;
-	int page_len = fs_info->sectorsize - page_off;
-	int ret;
-
-	ASSERT(start + len <= aligned_start + fs_info->sectorsize);
-	buf = malloc_cache_aligned(fs_info->sectorsize);
-	if (!buf)
-		return -ENOMEM;
-
-	extent_type = btrfs_file_extent_type(leaf, fi);
-	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-		ret = btrfs_read_extent_inline(path, fi, buf);
-		memcpy(dest, buf + page_off, min(page_len, ret));
-		free(buf);
-		return len;
-	}
-
-	ret = btrfs_read_extent_reg(path, fi,
-			round_down(start, fs_info->sectorsize),
-			fs_info->sectorsize, buf);
-	if (ret < 0) {
-		free(buf);
-		return ret;
-	}
-	memcpy(dest, buf + page_off, page_len);
-	free(buf);
-	return len;
-}
-
 int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len,
 		    char *dest)
 {
@@ -666,7 +628,6 @@ int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len,
 	struct btrfs_path path;
 	struct btrfs_key key;
 	u64 aligned_start = round_down(file_offset, fs_info->sectorsize);
-	u64 aligned_end = round_down(file_offset + len, fs_info->sectorsize);
 	u64 next_offset;
 	u64 cur = aligned_start;
 	int ret = 0;
@@ -676,34 +637,14 @@ int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len,
 	/* Set the whole dest all zero, so we won't need to bother holes */
 	memset(dest, 0, len);
 
-	/* Read out the leading unaligned part */
-	if (aligned_start != file_offset) {
-		ret = lookup_data_extent(root, &path, ino, aligned_start,
-					 &next_offset);
-		if (ret < 0)
-			goto out;
-		if (ret == 0) {
-			/* Read the unaligned part out*/
-			fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
-					struct btrfs_file_extent_item);
-			ret = read_and_truncate_page(&path, fi, file_offset,
-					round_up(file_offset, fs_info->sectorsize) -
-					file_offset, dest);
-			if (ret < 0)
-				goto out;
-			cur += fs_info->sectorsize;
-		} else {
-			/* The whole file is a hole */
-			if (!next_offset) {
-				memset(dest, 0, len);
-				return len;
-			}
-			cur = next_offset;
-		}
-	}
+	/*
+	 * Ensured by higher layer, which should have already handled the
+	 * first unaligned sector.
+	 */
+	ASSERT(aligned_start == file_offset);
 
 	/* Read the aligned part */
-	while (cur < aligned_end) {
+	while (cur < file_offset + len) {
 		u64 extent_num_bytes;
 		u8 type;
 
@@ -746,27 +687,13 @@ int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len,
 		extent_num_bytes = btrfs_file_extent_num_bytes(path.nodes[0],
 							       fi);
 		ret = btrfs_read_extent_reg(&path, fi, cur,
-				min(extent_num_bytes, aligned_end - cur),
+				min(extent_num_bytes, file_offset + len - cur),
 				dest + cur - file_offset);
 		if (ret < 0)
 			goto out;
-		cur += min(extent_num_bytes, aligned_end - cur);
+		cur += min(extent_num_bytes, file_offset + len - cur);
 	}
 
-	/* Read the tailing unaligned part*/
-	if (file_offset + len != aligned_end) {
-		btrfs_release_path(&path);
-		ret = lookup_data_extent(root, &path, ino, aligned_end,
-					 &next_offset);
-		/* <0 is error, >0 means no extent */
-		if (ret)
-			goto out;
-		fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
-				    struct btrfs_file_extent_item);
-		ret = read_and_truncate_page(&path, fi, aligned_end,
-				file_offset + len - aligned_end,
-				dest + aligned_end - file_offset);
-	}
 out:
 	btrfs_release_path(&path);
 	if (ret < 0)
diff --git a/fs/fs.c b/fs/fs.c
index 6de1a3eb6d5d..f9df8d9ec9a4 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -28,6 +28,7 @@
 #include <efi_loader.h>
 #include <squashfs.h>
 #include <erofs.h>
+#include <memalign.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -139,6 +140,11 @@ static inline int fs_mkdir_unsupported(const char *dirname)
 	return -1;
 }
 
+static inline int fs_get_blocksize_unsupported(const char *filename)
+{
+	return -1;
+}
+
 struct fstype_info {
 	int fstype;
 	char *name;
@@ -158,6 +164,14 @@ struct fstype_info {
 	int (*size)(const char *filename, loff_t *size);
 	int (*read)(const char *filename, void *buf, loff_t offset,
 		    loff_t len, loff_t *actread);
+	/*
+	 * Report the minimal data blocksize the fs supprts.
+	 *
+	 * This is used to handle unaligned read offset.
+	 * If not supported, read() will handle the unaligned offset all by
+	 * itself.
+	 */
+	int (*get_blocksize)(const char *filename);
 	int (*write)(const char *filename, void *buf, loff_t offset,
 		     loff_t len, loff_t *actwrite);
 	void (*close)(void);
@@ -193,6 +207,7 @@ static struct fstype_info fstypes[] = {
 		.exists = fat_exists,
 		.size = fat_size,
 		.read = fat_read_file,
+		.get_blocksize = fs_get_blocksize_unsupported,
 #if CONFIG_IS_ENABLED(FAT_WRITE)
 		.write = file_fat_write,
 		.unlink = fat_unlink,
@@ -221,6 +236,7 @@ static struct fstype_info fstypes[] = {
 		.exists = ext4fs_exists,
 		.size = ext4fs_size,
 		.read = ext4_read_file,
+		.get_blocksize = fs_get_blocksize_unsupported,
 #ifdef CONFIG_CMD_EXT4_WRITE
 		.write = ext4_write_file,
 		.ln = ext4fs_create_link,
@@ -245,6 +261,11 @@ static struct fstype_info fstypes[] = {
 		.exists = sandbox_fs_exists,
 		.size = sandbox_fs_size,
 		.read = fs_read_sandbox,
+		/*
+		 * Sandbox doesn't need to bother blocksize, as its
+		 * os_read() can handle unaligned range without any problem.
+		 */
+		.get_blocksize = fs_get_blocksize_unsupported,
 		.write = fs_write_sandbox,
 		.uuid = fs_uuid_unsupported,
 		.opendir = fs_opendir_unsupported,
@@ -264,6 +285,12 @@ static struct fstype_info fstypes[] = {
 		.exists = fs_exists_unsupported,
 		.size = smh_fs_size,
 		.read = smh_fs_read,
+		/*
+		 * Semihost doesn't need to bother blocksize, as it is using
+		 * read() system calls, and can handle unaligned range without
+		 * any problem.
+		 */
+		.get_blocksize = fs_get_blocksize_unsupported,
 		.write = smh_fs_write,
 		.uuid = fs_uuid_unsupported,
 		.opendir = fs_opendir_unsupported,
@@ -284,6 +311,7 @@ static struct fstype_info fstypes[] = {
 		.exists = ubifs_exists,
 		.size = ubifs_size,
 		.read = ubifs_read,
+		.get_blocksize = fs_get_blocksize_unsupported,
 		.write = fs_write_unsupported,
 		.uuid = fs_uuid_unsupported,
 		.opendir = fs_opendir_unsupported,
@@ -305,6 +333,7 @@ static struct fstype_info fstypes[] = {
 		.exists = btrfs_exists,
 		.size = btrfs_size,
 		.read = btrfs_read,
+		.get_blocksize = btrfs_get_blocksize,
 		.write = fs_write_unsupported,
 		.uuid = btrfs_uuid,
 		.opendir = fs_opendir_unsupported,
@@ -324,6 +353,7 @@ static struct fstype_info fstypes[] = {
 		.readdir = sqfs_readdir,
 		.ls = fs_ls_generic,
 		.read = sqfs_read,
+		.get_blocksize = fs_get_blocksize_unsupported,
 		.size = sqfs_size,
 		.close = sqfs_close,
 		.closedir = sqfs_closedir,
@@ -345,6 +375,7 @@ static struct fstype_info fstypes[] = {
 		.readdir = erofs_readdir,
 		.ls = fs_ls_generic,
 		.read = erofs_read,
+		.get_blocksize = fs_get_blocksize_unsupported,
 		.size = erofs_size,
 		.close = erofs_close,
 		.closedir = erofs_closedir,
@@ -366,6 +397,7 @@ static struct fstype_info fstypes[] = {
 		.exists = fs_exists_unsupported,
 		.size = fs_size_unsupported,
 		.read = fs_read_unsupported,
+		.get_blocksize = fs_get_blocksize_unsupported,
 		.write = fs_write_unsupported,
 		.uuid = fs_uuid_unsupported,
 		.opendir = fs_opendir_unsupported,
@@ -579,7 +611,11 @@ static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
 {
 	struct fstype_info *info = fs_get_info(fs_type);
 	void *buf;
+	int blocksize;
 	int ret;
+	loff_t cur = offset;
+	loff_t bytes_read = 0;
+	loff_t total_read = 0;
 
 #ifdef CONFIG_LMB
 	if (do_lmb_check) {
@@ -589,19 +625,97 @@ static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
 	}
 #endif
 
+	blocksize = info->get_blocksize(filename);
 	/*
-	 * We don't actually know how many bytes are being read, since len==0
-	 * means read the whole file.
+	 * The fs doesn't report its blocksize, let its read() to handle
+	 * the unaligned read.
+	 */
+	if (blocksize < 0) {
+		buf = map_sysmem(addr, len);
+		ret = info->read(filename, buf, offset, len, actread);
+
+		/* If we requested a specific number of bytes, check we got it */
+		if (ret == 0 && len && *actread != len)
+			log_debug("** %s shorter than offset + len **\n", filename);
+		goto out;
+	}
+
+	if (unlikely(blocksize == 0)) {
+		log_err("invalid blocksize 0 found\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * @len can be 0, meaning read the whole file.
+	 * And we can not rely on info->size(), as some fses doesn't resolve
+	 * softlinks to their final destinations.
 	 */
 	buf = map_sysmem(addr, len);
-	ret = info->read(filename, buf, offset, len, actread);
-	unmap_sysmem(buf);
 
-	/* If we requested a specific number of bytes, check we got it */
-	if (ret == 0 && len && *actread != len)
-		log_debug("** %s shorter than offset + len **\n", filename);
-	fs_close();
+	/* Unaligned read offset, handle the unaligned read here. */
+	if (!IS_ALIGNED(offset, blocksize)) {
+		void *block_buf;
+		const int offset_in_block = offset % blocksize;
+		int copy_len;
+
+		block_buf = malloc_cache_aligned(blocksize);
+		if (!block_buf) {
+			log_err("** Unable to alloc memory for one block **\n");
+			return -ENOMEM;
+		}
+		memset(block_buf, 0, blocksize);
+
+		cur = round_down(offset, blocksize);
+		ret = info->read(filename, block_buf, cur, blocksize,
+				 &bytes_read);
+		if (ret < 0) {
+			log_err("** Failed to read %s at offset %llu, %d **\n",
+				filename, cur, ret);
+			free(block_buf);
+			goto out;
+		}
+		if (bytes_read <= offset_in_block) {
+			log_err("** Offset %llu is beyond file size of %s **\n",
+				offset, filename);
+			free(block_buf);
+			ret = -EIO;
+			goto out;
+		}
+
+		copy_len = min_t(int, blocksize, bytes_read) - offset_in_block;
+		memcpy(buf, block_buf + offset_in_block, copy_len);
+		free(block_buf);
+		total_read += copy_len;
+
+		/*
+		 * A short read on the block, or we have already covered the
+		 * whole read range, just call it a day.
+		 */
+		if (bytes_read < blocksize ||
+		    (len && offset + len <= cur + blocksize))
+			goto out;
+
+		cur += blocksize;
+		if (len)
+			len -= copy_len;
+	}
+
+	ret = info->read(filename, buf + total_read, cur, len, &bytes_read);
+	if (ret < 0) {
+		log_err("** failed to read %s off %llu len %llu, %d **\n",
+			filename, cur, len, ret);
+		goto out;
+	}
+	if (len && bytes_read < len)
+		log_debug("** %s short read, off %llu len %llu actual read %llu **\n",
+			  filename, cur, len, bytes_read);
+	total_read += bytes_read;
 
+out:
+	unmap_sysmem(buf);
+	fs_close();
+	if (!ret)
+		*actread = total_read;
 	return ret;
 }
 
diff --git a/include/btrfs.h b/include/btrfs.h
index a7605e158970..bba71ec02893 100644
--- a/include/btrfs.h
+++ b/include/btrfs.h
@@ -17,6 +17,7 @@ int btrfs_ls(const char *);
 int btrfs_exists(const char *);
 int btrfs_size(const char *, loff_t *);
 int btrfs_read(const char *, void *, loff_t, loff_t, loff_t *);
+int btrfs_get_blocksize(const char *);
 void btrfs_close(void);
 int btrfs_uuid(char *);
 void btrfs_list_subvols(void);
-- 
2.36.1


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

* [PATCH 5/8] fs: ext4: rely on _fs_read() to handle leading unaligned block read
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
                   ` (3 preceding siblings ...)
  2022-06-29 11:38 ` [PATCH 4/8] fs: btrfs: move the unaligned read code to _fs_read() for btrfs Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-29 11:38 ` [PATCH 6/8] fs: fat: rely on higher layer to get block aligned read range Qu Wenruo
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

Just add ext4_get_blocksize() and a new assert() in ext4fs_read_file().

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Several cleanup candicate:

1. ext_fs->blksz is never populated, thus it's always 0
   We can not easily grab blocksize just like btrfs in this case.

   Thus we have to go the same calculation in ext4fs_read_file().

2. can not easily cleanup @skipfirst in ext4fs_read_file()
   It seems to screw up with soft link read.
---
 fs/ext4/ext4fs.c | 22 ++++++++++++++++++++++
 fs/fs.c          |  2 +-
 include/ext4fs.h |  1 +
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 4c89152ce4ad..b0568e77a895 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -69,6 +69,8 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
 	short status;
 	struct ext_block_cache cache;
 
+	assert(IS_ALIGNED(pos, blocksize));
+
 	ext_cache_init(&cache);
 
 	/* Adjust len so it we can't read past the end of the file. */
@@ -259,6 +261,26 @@ int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
 	return ext4fs_read(buf, offset, len, len_read);
 }
 
+int ext4_get_blocksize(const char *filename)
+{
+	struct ext_filesystem *fs;
+	int log2blksz;
+	int log2_fs_blocksize;
+	loff_t file_len;
+	int ret;
+
+	ret = ext4fs_open(filename, &file_len);
+	if (ret < 0) {
+		printf("** File not found %s **\n", filename);
+		return -1;
+	}
+	fs = get_fs();
+	log2blksz = fs->dev_desc->log2blksz;
+	log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_file->data) - log2blksz;
+
+	return (1 << (log2_fs_blocksize + log2blksz));
+}
+
 int ext4fs_uuid(char *uuid_str)
 {
 	if (ext4fs_root == NULL)
diff --git a/fs/fs.c b/fs/fs.c
index f9df8d9ec9a4..3cd2c88a4895 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -236,7 +236,7 @@ static struct fstype_info fstypes[] = {
 		.exists = ext4fs_exists,
 		.size = ext4fs_size,
 		.read = ext4_read_file,
-		.get_blocksize = fs_get_blocksize_unsupported,
+		.get_blocksize = ext4_get_blocksize,
 #ifdef CONFIG_CMD_EXT4_WRITE
 		.write = ext4_write_file,
 		.ln = ext4fs_create_link,
diff --git a/include/ext4fs.h b/include/ext4fs.h
index cb5d9cc0a5c0..0f4cf32dcc2a 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -161,6 +161,7 @@ int ext4fs_probe(struct blk_desc *fs_dev_desc,
 		 struct disk_partition *fs_partition);
 int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
 		   loff_t *actread);
+int ext4_get_blocksize(const char *filename);
 int ext4_read_superblock(char *buffer);
 int ext4fs_uuid(char *uuid_str);
 void ext_cache_init(struct ext_block_cache *cache);
-- 
2.36.1


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

* [PATCH 6/8] fs: fat: rely on higher layer to get block aligned read range
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
                   ` (4 preceding siblings ...)
  2022-06-29 11:38 ` [PATCH 5/8] fs: ext4: rely on _fs_read() to handle leading unaligned block read Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-29 11:38 ` [PATCH 7/8] fs: ubifs: rely on higher layer to do unaligned read Qu Wenruo
  2022-06-29 11:38 ` [PATCH 8/8] fs: erofs: add unaligned read range handling Qu Wenruo
  7 siblings, 0 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

Just implement fat_get_blocksize() for fat, so that fat_read_file()
always get a block aligned read range.

Unfortunately I'm not experienced enough to cleanup the fat code, thus
further cleanup is appreciated.

Cc: Tom Rini <trini@konsulko.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/fat/fat.c  | 13 +++++++++++++
 fs/fs.c       |  2 +-
 include/fat.h |  1 +
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index dcceccbcee0a..e13035e8e6d1 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1299,6 +1299,19 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
 	return ret;
 }
 
+int fat_get_blocksize(const char *filename)
+{
+	fsdata fsdata = {0};
+	int ret;
+
+	ret = get_fs_info(&fsdata);
+	if (ret)
+		return ret;
+
+	free(fsdata.fatbuf);
+	return fsdata.sect_size;
+}
+
 typedef struct {
 	struct fs_dir_stream parent;
 	struct fs_dirent dirent;
diff --git a/fs/fs.c b/fs/fs.c
index 3cd2c88a4895..09625f52e913 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -207,7 +207,7 @@ static struct fstype_info fstypes[] = {
 		.exists = fat_exists,
 		.size = fat_size,
 		.read = fat_read_file,
-		.get_blocksize = fs_get_blocksize_unsupported,
+		.get_blocksize = fat_get_blocksize,
 #if CONFIG_IS_ENABLED(FAT_WRITE)
 		.write = file_fat_write,
 		.unlink = fat_unlink,
diff --git a/include/fat.h b/include/fat.h
index a9756fb4cd1b..c03a2bebecef 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -201,6 +201,7 @@ int file_fat_detectfs(void);
 int fat_exists(const char *filename);
 int fat_size(const char *filename, loff_t *size);
 int file_fat_read(const char *filename, void *buffer, int maxsize);
+int fat_get_blocksize(const char *filename);
 int fat_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
 int fat_register_device(struct blk_desc *dev_desc, int part_no);
 
-- 
2.36.1


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

* [PATCH 7/8] fs: ubifs: rely on higher layer to do unaligned read
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
                   ` (5 preceding siblings ...)
  2022-06-29 11:38 ` [PATCH 6/8] fs: fat: rely on higher layer to get block aligned read range Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-29 11:38 ` [PATCH 8/8] fs: erofs: add unaligned read range handling Qu Wenruo
  7 siblings, 0 replies; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

Currently ubifs doesn't support unaligned read offset, thanks to the
recent _fs_read() work to handle unaligned read, we only need to
implement ubifs_get_blocksize() to take advantage of it.

Now ubifs can do unaligned read without any problem.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Unfortunately I can not test ubifs, as enabling UBI would cause compile
failure due to missing of <asm/atomic.h> header.
---
 fs/fs.c               |  2 +-
 fs/ubifs/ubifs.c      | 13 ++++++++-----
 include/ubifs_uboot.h |  1 +
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index 09625f52e913..61bae1051406 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -311,7 +311,7 @@ static struct fstype_info fstypes[] = {
 		.exists = ubifs_exists,
 		.size = ubifs_size,
 		.read = ubifs_read,
-		.get_blocksize = fs_get_blocksize_unsupported,
+		.get_blocksize = ubifs_get_blocksize,
 		.write = fs_write_unsupported,
 		.uuid = fs_uuid_unsupported,
 		.opendir = fs_opendir_unsupported,
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index d3026e310168..a8ab556dd376 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -846,11 +846,9 @@ int ubifs_read(const char *filename, void *buf, loff_t offset,
 
 	*actread = 0;
 
-	if (offset & (PAGE_SIZE - 1)) {
-		printf("ubifs: Error offset must be a multiple of %d\n",
-		       PAGE_SIZE);
-		return -1;
-	}
+	/* Higher layer should ensure it always pass page aligned range. */
+	assert(IS_ALIGNED(offset, PAGE_SIZE));
+	assert(IS_ALIGNED(size, PAGE_SIZE));
 
 	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
 	/* ubifs_findfile will resolve symlinks, so we know that we get
@@ -920,6 +918,11 @@ out:
 	return err;
 }
 
+int ubifs_get_blocksize(const char *filename)
+{
+	return PAGE_SIZE;
+}
+
 void ubifs_close(void)
 {
 }
diff --git a/include/ubifs_uboot.h b/include/ubifs_uboot.h
index b025779d59ff..bcd21715314a 100644
--- a/include/ubifs_uboot.h
+++ b/include/ubifs_uboot.h
@@ -29,6 +29,7 @@ int ubifs_exists(const char *filename);
 int ubifs_size(const char *filename, loff_t *size);
 int ubifs_read(const char *filename, void *buf, loff_t offset,
 	       loff_t size, loff_t *actread);
+int ubifs_get_blocksize(const char *filename);
 void ubifs_close(void);
 
 #endif /* __UBIFS_UBOOT_H__ */
-- 
2.36.1


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

* [PATCH 8/8] fs: erofs: add unaligned read range handling
  2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
                   ` (6 preceding siblings ...)
  2022-06-29 11:38 ` [PATCH 7/8] fs: ubifs: rely on higher layer to do unaligned read Qu Wenruo
@ 2022-06-29 11:38 ` Qu Wenruo
  2022-06-30 12:21   ` Huang Jianan
  7 siblings, 1 reply; 13+ messages in thread
From: Qu Wenruo @ 2022-06-29 11:38 UTC (permalink / raw)
  To: u-boot
  Cc: marek.behun, linux-btrfs, jnhuang95, linux-erofs, trini,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

I'm not an expert on erofs, but my quick glance didn't expose any
special handling on unaligned range, thus I think the U-boot erofs
driver doesn't really support unaligned read range.

This patch will add erofs_get_blocksize() so erofs can benefit from the
generic unaligned read support.

Cc: Huang Jianan <jnhuang95@gmail.com>
Cc: linux-erofs@lists.ozlabs.org
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/erofs/internal.h | 1 +
 fs/erofs/super.c    | 6 ++++++
 fs/fs.c             | 2 +-
 include/erofs.h     | 1 +
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 4af7c91560cc..d368a6481bf1 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -83,6 +83,7 @@ struct erofs_sb_info {
 	u16 available_compr_algs;
 	u16 lz4_max_distance;
 	u32 checksum;
+	u32 blocksize;
 	u16 extra_devices;
 	union {
 		u16 devt_slotoff;		/* used for mkfs */
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 4cca322b9ead..df01d2e719a7 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -99,7 +99,13 @@ int erofs_read_superblock(void)
 
 	sbi.build_time = le64_to_cpu(dsb->build_time);
 	sbi.build_time_nsec = le32_to_cpu(dsb->build_time_nsec);
+	sbi.blocksize = 1 << blkszbits;
 
 	memcpy(&sbi.uuid, dsb->uuid, sizeof(dsb->uuid));
 	return erofs_init_devices(&sbi, dsb);
 }
+
+int erofs_get_blocksize(const char *filename)
+{
+	return sbi.blocksize;
+}
diff --git a/fs/fs.c b/fs/fs.c
index 61bae1051406..e92174d89c28 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -375,7 +375,7 @@ static struct fstype_info fstypes[] = {
 		.readdir = erofs_readdir,
 		.ls = fs_ls_generic,
 		.read = erofs_read,
-		.get_blocksize = fs_get_blocksize_unsupported,
+		.get_blocksize = erofs_get_blocksize,
 		.size = erofs_size,
 		.close = erofs_close,
 		.closedir = erofs_closedir,
diff --git a/include/erofs.h b/include/erofs.h
index 1fbe82bf72cb..18bd6807c538 100644
--- a/include/erofs.h
+++ b/include/erofs.h
@@ -10,6 +10,7 @@ int erofs_probe(struct blk_desc *fs_dev_desc,
 		struct disk_partition *fs_partition);
 int erofs_read(const char *filename, void *buf, loff_t offset,
 	       loff_t len, loff_t *actread);
+int erofs_get_blocksize(const char *filename);
 int erofs_size(const char *filename, loff_t *size);
 int erofs_exists(const char *filename);
 void erofs_close(void);
-- 
2.36.1


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

* Re: [PATCH 8/8] fs: erofs: add unaligned read range handling
  2022-06-29 11:38 ` [PATCH 8/8] fs: erofs: add unaligned read range handling Qu Wenruo
@ 2022-06-30 12:21   ` Huang Jianan
  0 siblings, 0 replies; 13+ messages in thread
From: Huang Jianan @ 2022-06-30 12:21 UTC (permalink / raw)
  To: Qu Wenruo, u-boot
  Cc: marek.behun, linux-btrfs, linux-erofs, trini, joaomarcos.costa,
	thomas.petazzoni, miquel.raynal



在 2022/6/29 19:38, Qu Wenruo 写道:
> I'm not an expert on erofs, but my quick glance didn't expose any
> special handling on unaligned range, thus I think the U-boot erofs
> driver doesn't really support unaligned read range.
> 
> This patch will add erofs_get_blocksize() so erofs can benefit from the
> generic unaligned read support.
> 
> Cc: Huang Jianan <jnhuang95@gmail.com>
> Cc: linux-erofs@lists.ozlabs.org
> Signed-off-by: Qu Wenruo <wqu@suse.com>
Looks good to me,

Reviewed-by: Huang Jianan <jnhuang95@gmail.com>

Thanks,
Jianan
> ---
>   fs/erofs/internal.h | 1 +
>   fs/erofs/super.c    | 6 ++++++
>   fs/fs.c             | 2 +-
>   include/erofs.h     | 1 +
>   4 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
> index 4af7c91560cc..d368a6481bf1 100644
> --- a/fs/erofs/internal.h
> +++ b/fs/erofs/internal.h
> @@ -83,6 +83,7 @@ struct erofs_sb_info {
>   	u16 available_compr_algs;
>   	u16 lz4_max_distance;
>   	u32 checksum;
> +	u32 blocksize;
>   	u16 extra_devices;
>   	union {
>   		u16 devt_slotoff;		/* used for mkfs */
> diff --git a/fs/erofs/super.c b/fs/erofs/super.c
> index 4cca322b9ead..df01d2e719a7 100644
> --- a/fs/erofs/super.c
> +++ b/fs/erofs/super.c
> @@ -99,7 +99,13 @@ int erofs_read_superblock(void)
>   
>   	sbi.build_time = le64_to_cpu(dsb->build_time);
>   	sbi.build_time_nsec = le32_to_cpu(dsb->build_time_nsec);
> +	sbi.blocksize = 1 << blkszbits;
>   
>   	memcpy(&sbi.uuid, dsb->uuid, sizeof(dsb->uuid));
>   	return erofs_init_devices(&sbi, dsb);
>   }
> +
> +int erofs_get_blocksize(const char *filename)
> +{
> +	return sbi.blocksize;
> +}
> diff --git a/fs/fs.c b/fs/fs.c
> index 61bae1051406..e92174d89c28 100644
> --- a/fs/fs.c
> +++ b/fs/fs.c
> @@ -375,7 +375,7 @@ static struct fstype_info fstypes[] = {
>   		.readdir = erofs_readdir,
>   		.ls = fs_ls_generic,
>   		.read = erofs_read,
> -		.get_blocksize = fs_get_blocksize_unsupported,
> +		.get_blocksize = erofs_get_blocksize,
>   		.size = erofs_size,
>   		.close = erofs_close,
>   		.closedir = erofs_closedir,
> diff --git a/include/erofs.h b/include/erofs.h
> index 1fbe82bf72cb..18bd6807c538 100644
> --- a/include/erofs.h
> +++ b/include/erofs.h
> @@ -10,6 +10,7 @@ int erofs_probe(struct blk_desc *fs_dev_desc,
>   		struct disk_partition *fs_partition);
>   int erofs_read(const char *filename, void *buf, loff_t offset,
>   	       loff_t len, loff_t *actread);
> +int erofs_get_blocksize(const char *filename);
>   int erofs_size(const char *filename, loff_t *size);
>   int erofs_exists(const char *filename);
>   void erofs_close(void);

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

* Re: [PATCH 1/8] fs: fat: unexport file_fat_read_at()
  2022-06-29 11:38 ` [PATCH 1/8] fs: fat: unexport file_fat_read_at() Qu Wenruo
@ 2022-07-25 22:28   ` Tom Rini
  2022-07-26  1:35     ` Qu Wenruo
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Rini @ 2022-07-25 22:28 UTC (permalink / raw)
  To: Qu Wenruo
  Cc: u-boot, marek.behun, linux-btrfs, jnhuang95, linux-erofs,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal

[-- Attachment #1: Type: text/plain, Size: 454 bytes --]

On Wed, Jun 29, 2022 at 07:38:22PM +0800, Qu Wenruo wrote:

> That function is only utilized inside fat driver, unexport it.
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>

The series has a fails to build on nokia_rx51:
https://source.denx.de/u-boot/u-boot/-/jobs/471877#L483
which to me says doing 64bit division (likely related to block size,
etc) without using the appropriate helper macros to turn them in to bit
shifts instead.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [PATCH 1/8] fs: fat: unexport file_fat_read_at()
  2022-07-25 22:28   ` Tom Rini
@ 2022-07-26  1:35     ` Qu Wenruo
  2022-07-26  2:12       ` Tom Rini
  0 siblings, 1 reply; 13+ messages in thread
From: Qu Wenruo @ 2022-07-26  1:35 UTC (permalink / raw)
  To: Tom Rini, Qu Wenruo
  Cc: u-boot, marek.behun, linux-btrfs, jnhuang95, linux-erofs,
	joaomarcos.costa, thomas.petazzoni, miquel.raynal



On 2022/7/26 06:28, Tom Rini wrote:
> On Wed, Jun 29, 2022 at 07:38:22PM +0800, Qu Wenruo wrote:
>
>> That function is only utilized inside fat driver, unexport it.
>>
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>
> The series has a fails to build on nokia_rx51:
> https://source.denx.de/u-boot/u-boot/-/jobs/471877#L483
> which to me says doing 64bit division (likely related to block size,
> etc) without using the appropriate helper macros to turn them in to bit
> shifts instead.
>
Should I update and resend the series or just send the incremental
update to fix the U64/U32 division?

Thanks,
Qu

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

* Re: [PATCH 1/8] fs: fat: unexport file_fat_read_at()
  2022-07-26  1:35     ` Qu Wenruo
@ 2022-07-26  2:12       ` Tom Rini
  0 siblings, 0 replies; 13+ messages in thread
From: Tom Rini @ 2022-07-26  2:12 UTC (permalink / raw)
  To: Qu Wenruo
  Cc: Qu Wenruo, u-boot, marek.behun, linux-btrfs, jnhuang95,
	linux-erofs, joaomarcos.costa, thomas.petazzoni, miquel.raynal

[-- Attachment #1: Type: text/plain, Size: 774 bytes --]

On Tue, Jul 26, 2022 at 09:35:51AM +0800, Qu Wenruo wrote:
> 
> 
> On 2022/7/26 06:28, Tom Rini wrote:
> > On Wed, Jun 29, 2022 at 07:38:22PM +0800, Qu Wenruo wrote:
> > 
> > > That function is only utilized inside fat driver, unexport it.
> > > 
> > > Signed-off-by: Qu Wenruo <wqu@suse.com>
> > 
> > The series has a fails to build on nokia_rx51:
> > https://source.denx.de/u-boot/u-boot/-/jobs/471877#L483
> > which to me says doing 64bit division (likely related to block size,
> > etc) without using the appropriate helper macros to turn them in to bit
> > shifts instead.
> > 
> Should I update and resend the series or just send the incremental
> update to fix the U64/U32 division?

Please rebase and resend the whole series, thanks.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

end of thread, other threads:[~2022-07-26  2:12 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-29 11:38 [PATCH 0/8] U-boot: fs: add generic unaligned read offset handling Qu Wenruo
2022-06-29 11:38 ` [PATCH 1/8] fs: fat: unexport file_fat_read_at() Qu Wenruo
2022-07-25 22:28   ` Tom Rini
2022-07-26  1:35     ` Qu Wenruo
2022-07-26  2:12       ` Tom Rini
2022-06-29 11:38 ` [PATCH 2/8] fs: btrfs: fix a bug which no data get read if the length is not 0 Qu Wenruo
2022-06-29 11:38 ` [PATCH 3/8] fs: btrfs: fix a crash if specified range is beyond file size Qu Wenruo
2022-06-29 11:38 ` [PATCH 4/8] fs: btrfs: move the unaligned read code to _fs_read() for btrfs Qu Wenruo
2022-06-29 11:38 ` [PATCH 5/8] fs: ext4: rely on _fs_read() to handle leading unaligned block read Qu Wenruo
2022-06-29 11:38 ` [PATCH 6/8] fs: fat: rely on higher layer to get block aligned read range Qu Wenruo
2022-06-29 11:38 ` [PATCH 7/8] fs: ubifs: rely on higher layer to do unaligned read Qu Wenruo
2022-06-29 11:38 ` [PATCH 8/8] fs: erofs: add unaligned read range handling Qu Wenruo
2022-06-30 12:21   ` Huang Jianan

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).