2018-07-21 17:31:49

by Sean Fu

[permalink] [raw]
Subject: [PATCH] fs/buffer.c: Optimize grow_buffer function.

Use PAGE_SHIFT and i_blkbits of bd_inode directly to avoid ugly sizebits
calculation.
Remove ugly sizebits calculation.
Remove unnecessary sizebits parameter of grow_dev_page.

Reduces code size:

Before:

sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
text data bss dec hex filename
34037 1510 16 35563 8aeb fs/buffer.o

After:

sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
text data bss dec hex filename
34021 1510 16 35547 8adb fs/buffer.o

Signed-off-by: Sean Fu <[email protected]>
---
fs/buffer.c | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index 249b83f..143ad78 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -918,7 +918,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
*/
static int
grow_dev_page(struct block_device *bdev, sector_t block,
- pgoff_t index, int size, int sizebits, gfp_t gfp)
+ pgoff_t index, int size, gfp_t gfp)
{
struct inode *inode = bdev->bd_inode;
struct page *page;
@@ -945,7 +945,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
bh = page_buffers(page);
if (bh->b_size == size) {
end_block = init_page_buffers(page, bdev,
- (sector_t)index << sizebits,
+ (sector_t)index << (PAGE_SHIFT - inode->i_blkbits),
size);
goto done;
}
@@ -965,7 +965,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
*/
spin_lock(&inode->i_mapping->private_lock);
link_dev_buffers(page, bh);
- end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits,
+ end_block = init_page_buffers(page, bdev,
+ (sector_t)index << (PAGE_SHIFT - inode->i_blkbits),
size);
spin_unlock(&inode->i_mapping->private_lock);
done:
@@ -984,20 +985,13 @@ static int
grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
{
pgoff_t index;
- int sizebits;
-
- sizebits = -1;
- do {
- sizebits++;
- } while ((size << sizebits) < PAGE_SIZE);
-
- index = block >> sizebits;
+ index = block >> (PAGE_SHIFT - bdev->bd_inode->i_blkbits);

/*
* Check for a block which wants to lie outside our maximum possible
* pagecache index. (this comparison is done using sector_t types).
*/
- if (unlikely(index != block >> sizebits)) {
+ if (unlikely(index != block >> (PAGE_SHIFT - bdev->bd_inode->i_blkbits))) {
printk(KERN_ERR "%s: requested out-of-range block %llu for "
"device %pg\n",
__func__, (unsigned long long)block,
@@ -1006,7 +1000,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
}

/* Create a page with the proper size buffers.. */
- return grow_dev_page(bdev, block, index, size, sizebits, gfp);
+ return grow_dev_page(bdev, block, index, size, gfp);
}

static struct buffer_head *
--
2.6.2



2018-07-21 18:22:49

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH] fs/buffer.c: Optimize grow_buffer function.

On Sun, Jul 22, 2018 at 01:30:17AM +0800, Sean Fu wrote:
> Use PAGE_SHIFT and i_blkbits of bd_inode directly to avoid ugly sizebits
> calculation.
> Remove ugly sizebits calculation.
> Remove unnecessary sizebits parameter of grow_dev_page.
>
> Reduces code size:
>
> Before:
>
> sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
> text data bss dec hex filename
> 34037 1510 16 35563 8aeb fs/buffer.o
>
> After:
>
> sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
> text data bss dec hex filename
> 34021 1510 16 35547 8adb fs/buffer.o

First of all, 16 bytes is pretty much noise. What's more, the "remove ugly
sizebits calculation" part really needs an explanation of the reasons why
it's safe. You assume that size == 1<<bdev->bd_inode->i_blkbits; where's
the proof that it always holds?

2018-07-24 09:44:22

by Sean Fu

[permalink] [raw]
Subject: Re: [PATCH] fs/buffer.c: Optimize grow_buffer function.

On Sat, Jul 21, 2018 at 07:21:16PM +0100, Al Viro wrote:
> On Sun, Jul 22, 2018 at 01:30:17AM +0800, Sean Fu wrote:
> > Use PAGE_SHIFT and i_blkbits of bd_inode directly to avoid ugly sizebits
> > calculation.
> > Remove ugly sizebits calculation.
> > Remove unnecessary sizebits parameter of grow_dev_page.
> >
> > Reduces code size:
> >
> > Before:
> >
> > sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
> > text data bss dec hex filename
> > 34037 1510 16 35563 8aeb fs/buffer.o
> >
> > After:
> >
> > sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
> > text data bss dec hex filename
> > 34021 1510 16 35547 8adb fs/buffer.o
>
> First of all, 16 bytes is pretty much noise. What's more, the "remove ugly
> sizebits calculation" part really needs an explanation of the reasons why
> it's safe. You assume that size == 1<<bdev->bd_inode->i_blkbits; where's
> the proof that it always holds?
Thank your for taking a look and apologize for the noise.

I will take a deep look at it and especially history commits regarding with this.

BestRegards
Sean

2018-08-08 06:53:18

by Sean Fu

[permalink] [raw]
Subject: Re: [PATCH] fs/buffer.c: Optimize grow_buffer function.

On Sat, Jul 21, 2018 at 07:21:16PM +0100, Al Viro wrote:
> On Sun, Jul 22, 2018 at 01:30:17AM +0800, Sean Fu wrote:
> > Use PAGE_SHIFT and i_blkbits of bd_inode directly to avoid ugly sizebits
> > calculation.
> > Remove ugly sizebits calculation.
> > Remove unnecessary sizebits parameter of grow_dev_page.
> >
> > Reduces code size:
> >
> > Before:
> >
> > sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
> > text data bss dec hex filename
> > 34037 1510 16 35563 8aeb fs/buffer.o
> >
> > After:
> >
> > sean@linux-zmni:~/sda5/source/linus_repo/linux> size fs/buffer.o
> > text data bss dec hex filename
> > 34021 1510 16 35547 8adb fs/buffer.o
>
> First of all, 16 bytes is pretty much noise. What's more, the "remove ugly
> sizebits calculation" part really needs an explanation of the reasons why
> it's safe. You assume that size == 1<<bdev->bd_inode->i_blkbits; where's
> the proof that it always holds?

Got it, Thanks
This size can be page size(4096) besides block size (1<<bdev->bd_inode->i_blkbits).

I have another question about __getblk_slow function in fs/buffer.c
Actually __find_get_block already was invoked before entering __getblk_slow.
Can we move __find_get_block after grow_buffers in for loop of __getblk_slow?

for (;;) {
...
ret = grow_buffers(bdev, block, size, gfp);
...
bh = __find_get_block(bdev, block, size);
...
}