Hi Christoph,

On Mon, Sep 02, 2019 at 11:58:03PM -0700, Christoph Hellwig wrote:
> On Mon, Sep 02, 2019 at 11:50:38PM +0800, Gao Xiang wrote:
> > > > You means killing erofs_get_meta_page or avoid erofs_read_raw_page?
> > > > 
> > > >  - For killing erofs_get_meta_page, here is the current 
> > > > erofs_get_meta_page:
> > > 
> > > > I think it is simple enough. read_cache_page need write a similar
> > > > filler, or read_cache_page_gfp will call .readpage, and then
> > > > introduce buffer_heads, that is what I'd like to avoid now (no need 
> > > > these
> > > > bd_inode buffer_heads in memory...)
> > > 
> > > If using read_cache_page_gfp and ->readpage works, please do.  The
> > > fact that the block device inode uses buffer heads is an implementation
> > > detail that might not last very long and should be invisible to you.
> > > It also means you can get rid of a lot of code that you don't have
> > > to maintain and others don't have to update for global API changes.
> > 
> > I care about those useless buffer_heads in memory for our products...
> > 
> > Since we are nobh filesystem (a little request, could I use it
> > after buffer_heads are fully avoided, I have no idea why I need
> > those buffer_heads in memory.... But I think bd_inode is good
> > for caching metadata...)
> 
> Then please use read_cache_page with iomap_readpage(s), and write
> comment explaining why your are not using read_cache_page_gfp.

I implement a prelimitary version, but I have no idea it is a really
cleanup for now.

>From 001e3e64c81e4ced0d22b147e6abf90060e704b5 Mon Sep 17 00:00:00 2001
From: Gao Xiang <gaoxian...@huawei.com>
Date: Tue, 3 Sep 2019 16:13:00 +0800
Subject: [PATCH] erofs: use iomap_readpage for erofs_get_meta_page

Signed-off-by: Gao Xiang <gaoxian...@huawei.com>
---
 fs/erofs/Kconfig |  1 +
 fs/erofs/data.c  | 91 ++++++++++++++++++++++++++----------------------
 2 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
index 9d634d3a1845..c9eeb0bf4737 100644
--- a/fs/erofs/Kconfig
+++ b/fs/erofs/Kconfig
@@ -3,6 +3,7 @@
 config EROFS_FS
        tristate "EROFS filesystem support"
        depends on BLOCK
+       select FS_IOMAP
        help
          EROFS (Enhanced Read-Only File System) is a lightweight
          read-only file system with modern designs (eg. page-sized
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 3881c0689134..34c6e05fab71 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -5,6 +5,9 @@
  * Created by Gao Xiang <gaoxian...@huawei.com>
  */
 #include "internal.h"
+#include <linux/iomap.h>
+#include <linux/mpage.h>
+#include <linux/sched/mm.h>
 #include <linux/prefetch.h>
 
 #include <trace/events/erofs.h>
@@ -51,54 +54,60 @@ static struct bio *erofs_grab_raw_bio(struct super_block 
*sb,
        return bio;
 }
 
-struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr)
+static int erofs_meta_iomap_begin(struct inode *inode, loff_t pos,
+                                 loff_t length, unsigned int flags,
+                                 struct iomap *iomap)
 {
-       struct inode *const bd_inode = sb->s_bdev->bd_inode;
-       struct address_space *const mapping = bd_inode->i_mapping;
-       /* prefer retrying in the allocator to blindly looping below */
-       const gfp_t gfp = mapping_gfp_constraint(mapping, ~__GFP_FS);
-       struct page *page;
-       int err;
-
-repeat:
-       page = find_or_create_page(mapping, blkaddr, gfp);
-       if (!page)
-               return ERR_PTR(-ENOMEM);
-
-       DBG_BUGON(!PageLocked(page));
-
-       if (!PageUptodate(page)) {
-               struct bio *bio;
+       const unsigned int blkbits = inode->i_blkbits;
+
+       iomap->flags = 0;
+       iomap->bdev = I_BDEV(inode);
+       iomap->offset = round_down(pos, 1 << blkbits);
+       iomap->addr = iomap->offset;
+       iomap->length = round_up(length, 1 << blkbits);
+       iomap->type = IOMAP_MAPPED;
+       return 0;
+}
 
-               bio = erofs_grab_raw_bio(sb, blkaddr, 1, true);
+static const struct iomap_ops erofs_meta_iomap_ops = {
+       .iomap_begin = erofs_meta_iomap_begin,
+};
 
-               if (bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) {
-                       err = -EFAULT;
-                       goto err_out;
-               }
+static int
+erofs_meta_get_block(struct inode *inode, sector_t iblock,
+                    struct buffer_head *bh, int create)
+{
+       bh->b_bdev = I_BDEV(inode);
+       bh->b_blocknr = iblock;
+       set_buffer_mapped(bh);
+       return 0;
+}
 
-               submit_bio(bio);
-               lock_page(page);
+static int erofs_read_meta_page(void *file, struct page *page)
+{
+       /* in case of getting some pages with buffer_heads */
+       if (i_blocksize(page->mapping->host) == PAGE_SIZE &&
+           !page_has_buffers(page))
+               return iomap_readpage(page, &erofs_meta_iomap_ops);
+
+       /*
+        * cannot use blkdev_readpage or blkdev_get_block directly
+        * since static in block_dev.c
+        */
+       return mpage_readpage(page, erofs_meta_get_block);
+}
 
-               /* this page has been truncated by others */
-               if (page->mapping != mapping) {
-                       unlock_page(page);
-                       put_page(page);
-                       goto repeat;
-               }
+struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr)
+{
+       struct inode *const bd_inode = sb->s_bdev->bd_inode;
+       struct address_space *const mapping = bd_inode->i_mapping;
+       unsigned int nofs_flag;
+       struct page *page;
 
-               /* more likely a read error */
-               if (!PageUptodate(page)) {
-                       err = -EIO;
-                       goto err_out;
-               }
-       }
+       nofs_flag = memalloc_nofs_save();
+       page = read_cache_page(mapping, blkaddr, erofs_read_meta_page, NULL);
+       memalloc_nofs_restore(nofs_flag);
        return page;
-
-err_out:
-       unlock_page(page);
-       put_page(page);
-       return ERR_PTR(err);
 }
 
 static int erofs_map_blocks_flatmode(struct inode *inode,
-- 
2.17.1


_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to