[f2fs-dev] 答复: [PATCH -next] f2fs: add flush_dcache_page after page was written

2022-09-12 Thread zhangqilong via Linux-f2fs-devel
> 
> On 2022/8/25 10:41, Zhang Qilong wrote:
> > If the written page was mapped more than twice, the written data here
> > will not be seen by others. We add the flush_dcache_page to fix it.
> >
> > Fixes:0a2aa8fbb9693 ("f2fs: refactor __exchange_data_block for speed
> > up")
> > Signed-off-by: Zhang Qilong 
> > ---
> >   fs/f2fs/file.c | 1 +
> >   1 file changed, 1 insertion(+)
> >
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index
> > ab9844eaa62c..b593e41dbfb3 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -1273,6 +1273,7 @@ static int __clone_blkaddrs(struct inode
> *src_inode, struct inode *dst_inode,
> > return PTR_ERR(pdst);
> > }
> > memcpy_page(pdst, 0, psrc, 0, PAGE_SIZE);
> > +   flush_dcache_page(pdst);
> 
> __clone_blkaddrs() was introduced for fallocate() w/
> FALLOC_FL_COLLAPSE_RANGE and FALLOC_FL_INSERT_RANGE cases, they
> are both covered w/ invalidate_lock, and before __clone_blkaddrs(), it
> will call truncate_pagecache() to drop all mapping of pagecache, so it's
> safe here?
> 
> Instead, in f2fs_move_file_range(), we need to cover
> __exchange_data_block() w/ invalidate_lock and drop pagecache as well
> as fallocate() does?

Yes ,it seems has the problem. I test it just now through the POC( ioctl(fd1, 
F2FS_IOC_MOVE_RANGE, ). I read the old data before dropping the cache. It 
refreshes the source file data after manually dropping cache. I will propose a 
new patch to solve this problem.

Thanks,

> 
> Thanks,
> 
> > set_page_dirty(pdst);
> > f2fs_put_page(pdst, 1);
> > f2fs_put_page(psrc, 1);

___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH] f2fs: fix to detect obsolete inner inode during fill_super()

2022-09-12 Thread Jaegeuk Kim
On 09/08, Chao Yu wrote:
> Sometimes we can get a cached meta_inode which has no aops yet. Let's set it
> all the time to fix the below panic.
> 
> Unable to handle kernel NULL pointer dereference at virtual address 
> 
> Mem abort info:
>   ESR = 0x8604
>   EC = 0x21: IABT (current EL), IL = 32 bits
>   SET = 0, FnV = 0
>   EA = 0, S1PTW = 0
>   FSC = 0x04: level 0 translation fault
> user pgtable: 4k pages, 48-bit VAs, pgdp=000109ee4000
> [] pgd=, p4d=
> Internal error: Oops: 8604 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 1 PID: 3045 Comm: syz-executor330 Not tainted 
> 6.0.0-rc2-syzkaller-16455-ga41a877bc12d #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS 
> Google 07/22/2022
> pstate: 8045 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : 0x0
> lr : folio_mark_dirty+0xbc/0x208 mm/page-writeback.c:2748
> sp : 800012783970
> x29: 800012783970 x28:  x27: 800012783b08
> x26: 0001 x25: 0400 x24: 0001
> x23: c736e000 x22: 0045 x21: 05ffc015
> x20: ca7403b8 x19: fc00032ec600 x18: 0181
> x17: 8c04d6bc x16: 8dbb8658 x15: 
> x14:  x13:  x12: 
> x11: ff80883e9814 x10:  x9 : 883e9814
> x8 :  x7 :  x6 : 
> x5 : cbb19000 x4 : cb3d2000 x3 : cbb18f80
> x2 : fff0 x1 : fc00032ec600 x0 : ca7403b8
> Call trace:
>  0x0
>  set_page_dirty+0x38/0xbc mm/folio-compat.c:62
>  f2fs_update_meta_page+0x80/0xa8 fs/f2fs/segment.c:2369
>  do_checkpoint+0x794/0xea8 fs/f2fs/checkpoint.c:1522
>  f2fs_write_checkpoint+0x3b8/0x568 fs/f2fs/checkpoint.c:1679
> 
> The root cause is, quoted from Jaegeuk:
> 
> It turned out there is a bug in reiserfs which doesn't free the root
> inode (ino=2). That leads f2fs to find an ino=2 with the previous
> superblock point used by reiserfs. That stale inode has no valid
> mapping that f2fs can use, result in kernel panic.
> 
> This patch adds sanity check in f2fs_iget() to avoid finding stale
> inode during inner inode initialization.
> 
> Cc: sta...@vger.kernel.org
> Reported-by: syzbot+775a3440817f74fdd...@syzkaller.appspotmail.com
> Signed-off-by: Jaegeuk Kim 
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/inode.c | 11 +++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index ccb29034af59..df1a82fbfaf2 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -493,6 +493,17 @@ struct inode *f2fs_iget_inner(struct super_block *sb, 
> unsigned long ino)
>   struct inode *inode;
>   int ret = 0;
>  
> + if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi) ||
> + ino == F2FS_COMPRESS_INO(sbi)) {
> + inode = ilookup(sb, ino);
> + if (inode) {
> + iput(inode);
> + f2fs_err(sbi, "there is obsoleted inner inode %lu 
> cached in hash table",
> + ino);
> + return ERR_PTR(-EFSCORRUPTED);

Well, this does not indicate f2fs is corrupted. I'd rather expect to fix
reiserfs instead of f2fs workaround which hides the bug.

> + }
> + }
> +
>   inode = iget_locked(sb, ino);
>   if (!inode)
>   return ERR_PTR(-ENOMEM);
> -- 
> 2.25.1


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 22/23] nilfs2: Convert nilfs_clear_dirty_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
Acked-by: Ryusuke Konishi 
---
 fs/nilfs2/page.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 5c96084e829f..b66f4e988016 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -358,22 +358,22 @@ void nilfs_copy_back_pages(struct address_space *dmap,
  */
 void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
 {
-   struct pagevec pvec;
+   struct folio_batch fbatch;
unsigned int i;
pgoff_t index = 0;
 
-   pagevec_init();
+   folio_batch_init();
 
-   while (pagevec_lookup_tag(, mapping, ,
-   PAGECACHE_TAG_DIRTY)) {
-   for (i = 0; i < pagevec_count(); i++) {
-   struct page *page = pvec.pages[i];
+   while (filemap_get_folios_tag(mapping, , (pgoff_t)-1,
+   PAGECACHE_TAG_DIRTY, )) {
+   for (i = 0; i < folio_batch_count(); i++) {
+   struct folio *folio = fbatch.folios[i];
 
-   lock_page(page);
-   nilfs_clear_dirty_page(page, silent);
-   unlock_page(page);
+   folio_lock(folio);
+   nilfs_clear_dirty_page(>page, silent);
+   folio_unlock(folio);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
 }
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 05/23] afs: Convert afs_writepages_region() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert to use folios throughout. This function is in preparation to
remove find_get_pages_range_tag().

Also modified this function to write the whole batch one at a time,
rather than calling for a new set every single write.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/afs/write.c | 114 +
 1 file changed, 59 insertions(+), 55 deletions(-)

diff --git a/fs/afs/write.c b/fs/afs/write.c
index 9ebdd36eaf2f..c17dbd82a38c 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -699,82 +699,86 @@ static int afs_writepages_region(struct address_space 
*mapping,
 loff_t start, loff_t end, loff_t *_next)
 {
struct folio *folio;
-   struct page *head_page;
+   struct folio_batch fbatch;
ssize_t ret;
+   unsigned int i;
int n, skips = 0;
 
_enter("%llx,%llx,", start, end);
+   folio_batch_init();
 
do {
pgoff_t index = start / PAGE_SIZE;
 
-   n = find_get_pages_range_tag(mapping, , end / PAGE_SIZE,
-PAGECACHE_TAG_DIRTY, 1, 
_page);
+   n = filemap_get_folios_tag(mapping, , end / PAGE_SIZE,
+   PAGECACHE_TAG_DIRTY, );
+
if (!n)
break;
+   for (i = 0; i < n; i++) {
+   folio = fbatch.folios[i];
+   start = folio_pos(folio); /* May regress with THPs */
 
-   folio = page_folio(head_page);
-   start = folio_pos(folio); /* May regress with THPs */
-
-   _debug("wback %lx", folio_index(folio));
+   _debug("wback %lx", folio_index(folio));
 
-   /* At this point we hold neither the i_pages lock nor the
-* page lock: the page may be truncated or invalidated
-* (changing page->mapping to NULL), or even swizzled
-* back from swapper_space to tmpfs file mapping
-*/
-   if (wbc->sync_mode != WB_SYNC_NONE) {
-   ret = folio_lock_killable(folio);
-   if (ret < 0) {
-   folio_put(folio);
-   return ret;
-   }
-   } else {
-   if (!folio_trylock(folio)) {
-   folio_put(folio);
-   return 0;
+   /* At this point we hold neither the i_pages lock nor 
the
+* page lock: the page may be truncated or invalidated
+* (changing page->mapping to NULL), or even swizzled
+* back from swapper_space to tmpfs file mapping
+*/
+   if (wbc->sync_mode != WB_SYNC_NONE) {
+   ret = folio_lock_killable(folio);
+   if (ret < 0) {
+   folio_batch_release();
+   return ret;
+   }
+   } else {
+   if (!folio_trylock(folio))
+   continue;
}
-   }
 
-   if (folio_mapping(folio) != mapping ||
-   !folio_test_dirty(folio)) {
-   start += folio_size(folio);
-   folio_unlock(folio);
-   folio_put(folio);
-   continue;
-   }
+   if (folio->mapping != mapping ||
+   !folio_test_dirty(folio)) {
+   start += folio_size(folio);
+   folio_unlock(folio);
+   continue;
+   }
 
-   if (folio_test_writeback(folio) ||
-   folio_test_fscache(folio)) {
-   folio_unlock(folio);
-   if (wbc->sync_mode != WB_SYNC_NONE) {
-   folio_wait_writeback(folio);
+   if (folio_test_writeback(folio) ||
+   folio_test_fscache(folio)) {
+   folio_unlock(folio);
+   if (wbc->sync_mode != WB_SYNC_NONE) {
+   folio_wait_writeback(folio);
 #ifdef CONFIG_AFS_FSCACHE
-   folio_wait_fscache(folio);
+   folio_wait_fscache(folio);
 #endif
-   } else {
-   start += folio_size(folio);
+   } else {
+   start += folio_size(folio);
+   }
+   if (wbc->sync_mode == WB_SYNC_NONE) {
+ 

[f2fs-dev] [PATCH v2 06/23] btrfs: Convert btree_write_cache_pages() to use filemap_get_folio_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
Acked-by: David Sterba 
---
 fs/btrfs/extent_io.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index cf4f19e80e2f..d1fa072bfdd0 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4844,14 +4844,14 @@ int btree_write_cache_pages(struct address_space 
*mapping,
int ret = 0;
int done = 0;
int nr_to_write_done = 0;
-   struct pagevec pvec;
-   int nr_pages;
+   struct folio_batch fbatch;
+   unsigned int nr_folios;
pgoff_t index;
pgoff_t end;/* Inclusive */
int scanned = 0;
xa_mark_t tag;
 
-   pagevec_init();
+   folio_batch_init();
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* Start from prev offset */
end = -1;
@@ -4874,14 +4874,15 @@ int btree_write_cache_pages(struct address_space 
*mapping,
if (wbc->sync_mode == WB_SYNC_ALL)
tag_pages_for_writeback(mapping, index, end);
while (!done && !nr_to_write_done && (index <= end) &&
-  (nr_pages = pagevec_lookup_range_tag(, mapping, , end,
-   tag))) {
+  (nr_folios = filemap_get_folios_tag(mapping, , end,
+   tag, ))) {
unsigned i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
 
-   ret = submit_eb_page(page, wbc, , _context);
+   ret = submit_eb_page(>page, wbc, ,
+   _context);
if (ret == 0)
continue;
if (ret < 0) {
@@ -4896,7 +4897,7 @@ int btree_write_cache_pages(struct address_space *mapping,
 */
nr_to_write_done = wbc->nr_to_write <= 0;
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
if (!scanned && !done) {
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 08/23] ceph: Convert ceph_writepages_start() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

This change does NOT support large folios. This shouldn't be an issue as
of now since ceph only utilizes folios of size 1 anyways, and there is a
lot of work to be done on ceph conversions to folios for later patches
at some point.

Also some minor renaming for consistency.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/ceph/addr.c | 138 +
 1 file changed, 70 insertions(+), 68 deletions(-)

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index dcf701b05cc1..33dbe55b08be 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -792,7 +792,7 @@ static int ceph_writepages_start(struct address_space 
*mapping,
struct ceph_vino vino = ceph_vino(inode);
pgoff_t index, start_index, end = -1;
struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
int rc = 0;
unsigned int wsize = i_blocksize(inode);
struct ceph_osd_request *req = NULL;
@@ -821,7 +821,7 @@ static int ceph_writepages_start(struct address_space 
*mapping,
if (fsc->mount_options->wsize < wsize)
wsize = fsc->mount_options->wsize;
 
-   pagevec_init();
+   folio_batch_init();
 
start_index = wbc->range_cyclic ? mapping->writeback_index : 0;
index = start_index;
@@ -869,9 +869,9 @@ static int ceph_writepages_start(struct address_space 
*mapping,
 
while (!done && index <= end) {
int num_ops = 0, op_idx;
-   unsigned i, pvec_pages, max_pages, locked_pages = 0;
+   unsigned i, nr_folios, max_pages, locked_pages = 0;
struct page **pages = NULL, **data_pages;
-   struct page *page;
+   struct folio *folio;
pgoff_t strip_unit_end = 0;
u64 offset = 0, len = 0;
bool from_pool = false;
@@ -879,28 +879,28 @@ static int ceph_writepages_start(struct address_space 
*mapping,
max_pages = wsize >> PAGE_SHIFT;
 
 get_more_pages:
-   pvec_pages = pagevec_lookup_range_tag(, mapping, ,
-   end, PAGECACHE_TAG_DIRTY);
-   dout("pagevec_lookup_range_tag got %d\n", pvec_pages);
-   if (!pvec_pages && !locked_pages)
+   nr_folios = filemap_get_folios_tag(mapping, ,
+   end, PAGECACHE_TAG_DIRTY, );
+   dout("filemap_get_folios_tag got %d\n", nr_folios);
+   if (!nr_folios && !locked_pages)
break;
-   for (i = 0; i < pvec_pages && locked_pages < max_pages; i++) {
-   page = pvec.pages[i];
-   dout("? %p idx %lu\n", page, page->index);
+   for (i = 0; i < nr_folios && locked_pages < max_pages; i++) {
+   folio = fbatch.folios[i];
+   dout("? %p idx %lu\n", folio, folio->index);
if (locked_pages == 0)
-   lock_page(page);  /* first page */
-   else if (!trylock_page(page))
+   folio_lock(folio); /* first folio */
+   else if (!folio_trylock(folio))
break;
 
/* only dirty pages, or our accounting breaks */
-   if (unlikely(!PageDirty(page)) ||
-   unlikely(page->mapping != mapping)) {
-   dout("!dirty or !mapping %p\n", page);
-   unlock_page(page);
+   if (unlikely(!folio_test_dirty(folio)) ||
+   unlikely(folio->mapping != mapping)) {
+   dout("!dirty or !mapping %p\n", folio);
+   folio_unlock(folio);
continue;
}
/* only if matching snap context */
-   pgsnapc = page_snap_context(page);
+   pgsnapc = page_snap_context(>page);
if (pgsnapc != snapc) {
dout("page snapc %p %lld != oldest %p %lld\n",
 pgsnapc, pgsnapc->seq, snapc, snapc->seq);
@@ -908,11 +908,10 @@ static int ceph_writepages_start(struct address_space 
*mapping,
!ceph_wbc.head_snapc &&
wbc->sync_mode != WB_SYNC_NONE)
should_loop = true;
-   unlock_page(page);
+   folio_unlock(folio);
continue;
}
-   if (page_offset(page) >= ceph_wbc.i_size) {
-

[f2fs-dev] [PATCH v2 02/23] filemap: Added filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
This is the equivalent of find_get_pages_range_tag(), except for folios
instead of pages.

One noteable difference is filemap_get_folios_tag() does not take in a
maximum pages argument. It instead tries to fill a folio batch and stops
either once full (15 folios) or reaching the end of the search range.

The new function supports large folios, the initial function did not
since all callers don't use large folios.

Signed-off-by: Vishal Moola (Oracle) 
---
 include/linux/pagemap.h |  2 ++
 mm/filemap.c| 53 +
 2 files changed, 55 insertions(+)

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 4d3092d6b2c0..85cc96c82c2c 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -740,6 +740,8 @@ unsigned filemap_get_folios(struct address_space *mapping, 
pgoff_t *start,
pgoff_t end, struct folio_batch *fbatch);
 unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
   unsigned int nr_pages, struct page **pages);
+unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start,
+   pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch);
 unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t 
*index,
pgoff_t end, xa_mark_t tag, unsigned int nr_pages,
struct page **pages);
diff --git a/mm/filemap.c b/mm/filemap.c
index 15800334147b..3ded72a65668 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2254,6 +2254,59 @@ unsigned find_get_pages_contig(struct address_space 
*mapping, pgoff_t index,
 }
 EXPORT_SYMBOL(find_get_pages_contig);
 
+/**
+ * filemap_get_folios_tag - Get a batch of folios matching @tag.
+ * @mapping:The address_space to search
+ * @start:  The starting page index
+ * @end:The final page index (inclusive)
+ * @tag:The tag index
+ * @fbatch: The batch to fill
+ *
+ * Same as filemap_get_folios, but only returning folios tagged with @tag
+ *
+ * Return: The number of folios found
+ * Also update @start to index the next folio for traversal
+ */
+unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start,
+   pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch)
+{
+   XA_STATE(xas, >i_pages, *start);
+   struct folio *folio;
+
+   rcu_read_lock();
+   while ((folio = find_get_entry(, end, tag)) != NULL) {
+   /* Shadow entries should never be tagged, but this iteration
+* is lockless so there is a window for page reclaim to evict
+* a page we saw tagged. Skip over it.
+*/
+   if (xa_is_value(folio))
+   continue;
+   if (!folio_batch_add(fbatch, folio)) {
+   unsigned long nr = folio_nr_pages(folio);
+
+   if (folio_test_hugetlb(folio))
+   nr = 1;
+   *start = folio->index + nr;
+   goto out;
+   }
+   }
+   /*
+* We come here when there is no page beyond @end. We take care to not
+* overflow the index @start as it confuses some of the callers. This
+* breaks the iteration when there is a page at index -1 but that is
+* already broke anyway.
+*/
+   if (end == (pgoff_t)-1)
+   *start = (pgoff_t)-1;
+   else
+   *start = end + 1;
+out:
+   rcu_read_unlock();
+
+   return folio_batch_count(fbatch);
+}
+EXPORT_SYMBOL(filemap_get_folios_tag);
+
 /**
  * find_get_pages_range_tag - Find and return head pages matching @tag.
  * @mapping:   the address_space to search
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 13/23] f2fs: Convert f2fs_sync_node_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios. This is in preparation for the removal
of find_get_pages_range_tag(). Does NOT support large folios.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/f2fs/node.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index c2b54c58392a..cf8665f04c0d 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1933,23 +1933,24 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
bool do_balance, enum iostat_type io_type)
 {
pgoff_t index;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
int step = 0;
int nwritten = 0;
int ret = 0;
-   int nr_pages, done = 0;
+   int nr_folios, done = 0;
 
-   pagevec_init();
+   folio_batch_init();
 
 next_step:
index = 0;
 
-   while (!done && (nr_pages = pagevec_lookup_tag(,
-   NODE_MAPPING(sbi), , PAGECACHE_TAG_DIRTY))) {
+   while (!done && (nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi),
+   , (pgoff_t)-1, PAGECACHE_TAG_DIRTY,
+   ))) {
int i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct page *page = [i]->page;
bool submitted = false;
 
/* give a priority to WB_SYNC threads */
@@ -2024,7 +2025,7 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
if (--wbc->nr_to_write == 0)
break;
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
 
if (wbc->nr_to_write == 0) {
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 11/23] f2fs: Convert f2fs_fsync_node_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios. This is in preparation for the removal
of find_get_pages_range_tag(). Does NOT support large
folios.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/f2fs/node.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index e06a0c478b39..a3c5eedfcf64 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1726,12 +1726,12 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, 
struct inode *inode,
unsigned int *seq_id)
 {
pgoff_t index;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
int ret = 0;
struct page *last_page = NULL;
bool marked = false;
nid_t ino = inode->i_ino;
-   int nr_pages;
+   int nr_folios;
int nwritten = 0;
 
if (atomic) {
@@ -1740,20 +1740,21 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, 
struct inode *inode,
return PTR_ERR_OR_ZERO(last_page);
}
 retry:
-   pagevec_init();
+   folio_batch_init();
index = 0;
 
-   while ((nr_pages = pagevec_lookup_tag(, NODE_MAPPING(sbi), ,
-   PAGECACHE_TAG_DIRTY))) {
+   while ((nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), ,
+   (pgoff_t)-1, PAGECACHE_TAG_DIRTY,
+   ))) {
int i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct page *page = [i]->page;
bool submitted = false;
 
if (unlikely(f2fs_cp_error(sbi))) {
f2fs_put_page(last_page, 0);
-   pagevec_release();
+   folio_batch_release();
ret = -EIO;
goto out;
}
@@ -1819,7 +1820,7 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, 
struct inode *inode,
break;
}
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
 
if (ret || marked)
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 10/23] ext4: Convert mpage_prepare_extent_to_map() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted the function to use folios throughout. This is in preparation
for the removal of find_get_pages_range_tag(). Now supports large
folios.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/ext4/inode.c | 55 -
 1 file changed, 27 insertions(+), 28 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 601214453c3a..fbd876e10a85 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2565,8 +2565,8 @@ static int ext4_da_writepages_trans_blocks(struct inode 
*inode)
 static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
 {
struct address_space *mapping = mpd->inode->i_mapping;
-   struct pagevec pvec;
-   unsigned int nr_pages;
+   struct folio_batch fbatch;
+   unsigned int nr_folios;
long left = mpd->wbc->nr_to_write;
pgoff_t index = mpd->first_page;
pgoff_t end = mpd->last_page;
@@ -2580,18 +2580,17 @@ static int mpage_prepare_extent_to_map(struct 
mpage_da_data *mpd)
tag = PAGECACHE_TAG_TOWRITE;
else
tag = PAGECACHE_TAG_DIRTY;
-
-   pagevec_init();
+   folio_batch_init();
mpd->map.m_len = 0;
mpd->next_page = index;
while (index <= end) {
-   nr_pages = pagevec_lookup_range_tag(, mapping, , end,
-   tag);
-   if (nr_pages == 0)
+   nr_folios = filemap_get_folios_tag(mapping, , end,
+   tag, );
+   if (nr_folios == 0)
break;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
 
/*
 * Accumulated enough dirty pages? This doesn't apply
@@ -2605,10 +2604,10 @@ static int mpage_prepare_extent_to_map(struct 
mpage_da_data *mpd)
goto out;
 
/* If we can't merge this page, we are done. */
-   if (mpd->map.m_len > 0 && mpd->next_page != page->index)
+   if (mpd->map.m_len > 0 && mpd->next_page != 
folio->index)
goto out;
 
-   lock_page(page);
+   folio_lock(folio);
/*
 * If the page is no longer dirty, or its mapping no
 * longer corresponds to inode we are writing (which
@@ -2616,16 +2615,16 @@ static int mpage_prepare_extent_to_map(struct 
mpage_da_data *mpd)
 * page is already under writeback and we are not doing
 * a data integrity writeback, skip the page
 */
-   if (!PageDirty(page) ||
-   (PageWriteback(page) &&
+   if (!folio_test_dirty(folio) ||
+   (folio_test_writeback(folio) &&
 (mpd->wbc->sync_mode == WB_SYNC_NONE)) ||
-   unlikely(page->mapping != mapping)) {
-   unlock_page(page);
+   unlikely(folio->mapping != mapping)) {
+   folio_unlock(folio);
continue;
}
 
-   wait_on_page_writeback(page);
-   BUG_ON(PageWriteback(page));
+   folio_wait_writeback(folio);
+   BUG_ON(folio_test_writeback(folio));
 
/*
 * Should never happen but for buggy code in
@@ -2636,33 +2635,33 @@ static int mpage_prepare_extent_to_map(struct 
mpage_da_data *mpd)
 *
 * [1] 
https://lore.kernel.org/linux-mm/20180103100430.ge4...@quack2.suse.cz
 */
-   if (!page_has_buffers(page)) {
-   ext4_warning_inode(mpd->inode, "page %lu does 
not have buffers attached", page->index);
-   ClearPageDirty(page);
-   unlock_page(page);
+   if (!folio_buffers(folio)) {
+   ext4_warning_inode(mpd->inode, "page %lu does 
not have buffers attached", folio->index);
+   folio_clear_dirty(folio);
+   folio_unlock(folio);
continue;
}
 
if (mpd->map.m_len == 0)
-   mpd->first_page = page->index;
-   mpd->next_page = page->index + 1;
+   mpd->first_page = folio->index;
+   mpd->next_page = folio->index + folio_nr_pages(folio);
/* Add all dirty 

[f2fs-dev] [PATCH v2 17/23] gfs2: Convert gfs2_write_cache_jdata() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted function to use folios throughout. This is in preparation for
the removal of find_get_pgaes_range_tag().

Also had to modify and rename gfs2_write_jdata_pagevec() to take in
and utilize folio_batch rather than pagevec and use folios rather
than pages. gfs2_write_jdata_batch() now supports large folios.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/gfs2/aops.c | 64 +++---
 1 file changed, 35 insertions(+), 29 deletions(-)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 05bee80ac7de..8f87c2551a3d 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -195,67 +195,71 @@ static int gfs2_writepages(struct address_space *mapping,
 }
 
 /**
- * gfs2_write_jdata_pagevec - Write back a pagevec's worth of pages
+ * gfs2_write_jdata_batch - Write back a folio batch's worth of folios
  * @mapping: The mapping
  * @wbc: The writeback control
- * @pvec: The vector of pages
- * @nr_pages: The number of pages to write
+ * @fbatch: The batch of folios
  * @done_index: Page index
  *
  * Returns: non-zero if loop should terminate, zero otherwise
  */
 
-static int gfs2_write_jdata_pagevec(struct address_space *mapping,
+static int gfs2_write_jdata_batch(struct address_space *mapping,
struct writeback_control *wbc,
-   struct pagevec *pvec,
-   int nr_pages,
+   struct folio_batch *fbatch,
pgoff_t *done_index)
 {
struct inode *inode = mapping->host;
struct gfs2_sbd *sdp = GFS2_SB(inode);
-   unsigned nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);
+   unsigned nrblocks;
int i;
int ret;
+   int nr_pages = 0;
+   int nr_folios = folio_batch_count(fbatch);
+
+   for (i = 0; i < nr_folios; i++)
+   nr_pages += folio_nr_pages(fbatch->folios[i]);
+   nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);
 
ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
if (ret < 0)
return ret;
 
-   for(i = 0; i < nr_pages; i++) {
-   struct page *page = pvec->pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch->folios[i];
 
-   *done_index = page->index;
+   *done_index = folio->index;
 
-   lock_page(page);
+   folio_lock(folio);
 
-   if (unlikely(page->mapping != mapping)) {
+   if (unlikely(folio->mapping != mapping)) {
 continue_unlock:
-   unlock_page(page);
+   folio_unlock(folio);
continue;
}
 
-   if (!PageDirty(page)) {
+   if (!folio_test_dirty(folio)) {
/* someone wrote it for us */
goto continue_unlock;
}
 
-   if (PageWriteback(page)) {
+   if (folio_test_writeback(folio)) {
if (wbc->sync_mode != WB_SYNC_NONE)
-   wait_on_page_writeback(page);
+   folio_wait_writeback(folio);
else
goto continue_unlock;
}
 
-   BUG_ON(PageWriteback(page));
-   if (!clear_page_dirty_for_io(page))
+   BUG_ON(folio_test_writeback(folio));
+   if (!folio_clear_dirty_for_io(folio))
goto continue_unlock;
 
trace_wbc_writepage(wbc, inode_to_bdi(inode));
 
-   ret = __gfs2_jdata_writepage(page, wbc);
+   ret = __gfs2_jdata_writepage(>page, wbc);
if (unlikely(ret)) {
if (ret == AOP_WRITEPAGE_ACTIVATE) {
-   unlock_page(page);
+   folio_unlock(folio);
ret = 0;
} else {
 
@@ -268,7 +272,8 @@ static int gfs2_write_jdata_pagevec(struct address_space 
*mapping,
 * not be suitable for data integrity
 * writeout).
 */
-   *done_index = page->index + 1;
+   *done_index = folio->index +
+   folio_nr_pages(folio);
ret = 1;
break;
}
@@ -305,8 +310,8 @@ static int gfs2_write_cache_jdata(struct address_space 
*mapping,
 {
int ret = 0;
int done = 0;
-   struct pagevec pvec;
-   int nr_pages;
+   struct folio_batch fbatch;
+   int nr_folios;
pgoff_t writeback_index;
pgoff_t index;
pgoff_t end;
@@ -315,7 +320,7 @@ static int gfs2_write_cache_jdata(struct address_space 
*mapping,
int 

[f2fs-dev] [PATCH v2 14/23] f2fs: Convert f2fs_write_cache_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted the function to use folios. This is in preparation for the
removal of find_get_pages_range_tag().

Also modified f2fs_all_cluster_page_ready to take in a folio_batch instead
of pagevec. This does NOT support large folios. The function currently
only utilizes folios of size 1 so this shouldn't cause any issues right
now.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/f2fs/compress.c | 13 +
 fs/f2fs/data.c | 69 +-
 fs/f2fs/f2fs.h |  5 ++--
 3 files changed, 47 insertions(+), 40 deletions(-)

diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 70e97075e535..e1bd2e859f64 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -841,10 +841,11 @@ bool f2fs_cluster_can_merge_page(struct compress_ctx *cc, 
pgoff_t index)
return is_page_in_cluster(cc, index);
 }
 
-bool f2fs_all_cluster_page_ready(struct compress_ctx *cc, struct page **pages,
-   int index, int nr_pages, bool uptodate)
+bool f2fs_all_cluster_page_ready(struct compress_ctx *cc,
+   struct folio_batch *fbatch,
+   int index, int nr_folios, bool uptodate)
 {
-   unsigned long pgidx = pages[index]->index;
+   unsigned long pgidx = fbatch->folios[index]->index;
int i = uptodate ? 0 : 1;
 
/*
@@ -854,13 +855,13 @@ bool f2fs_all_cluster_page_ready(struct compress_ctx *cc, 
struct page **pages,
if (uptodate && (pgidx % cc->cluster_size))
return false;
 
-   if (nr_pages - index < cc->cluster_size)
+   if (nr_folios - index < cc->cluster_size)
return false;
 
for (; i < cc->cluster_size; i++) {
-   if (pages[index + i]->index != pgidx + i)
+   if (fbatch->folios[index + i]->index != pgidx + i)
return false;
-   if (uptodate && !PageUptodate(pages[index + i]))
+   if (uptodate && !folio_test_uptodate(fbatch->folios[index + i]))
return false;
}
 
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index aa3ccddfa037..b14747598b39 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2917,7 +2917,7 @@ static int f2fs_write_cache_pages(struct address_space 
*mapping,
 {
int ret = 0;
int done = 0, retry = 0;
-   struct page *pages[F2FS_ONSTACK_PAGES];
+   struct folio_batch fbatch;
struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
struct bio *bio = NULL;
sector_t last_block;
@@ -2938,7 +2938,7 @@ static int f2fs_write_cache_pages(struct address_space 
*mapping,
.private = NULL,
};
 #endif
-   int nr_pages;
+   int nr_folios;
pgoff_t index;
pgoff_t end;/* Inclusive */
pgoff_t done_index;
@@ -2948,6 +2948,8 @@ static int f2fs_write_cache_pages(struct address_space 
*mapping,
int submitted = 0;
int i;
 
+   folio_batch_init();
+
if (get_dirty_pages(mapping->host) <=
SM_I(F2FS_M_SB(mapping))->min_hot_blocks)
set_inode_flag(mapping->host, FI_HOT_DATA);
@@ -2973,13 +2975,13 @@ static int f2fs_write_cache_pages(struct address_space 
*mapping,
tag_pages_for_writeback(mapping, index, end);
done_index = index;
while (!done && !retry && (index <= end)) {
-   nr_pages = find_get_pages_range_tag(mapping, , end,
-   tag, F2FS_ONSTACK_PAGES, pages);
-   if (nr_pages == 0)
+   nr_folios = filemap_get_folios_tag(mapping, , end,
+   tag, );
+   if (nr_folios == 0)
break;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
bool need_readd;
 readd:
need_readd = false;
@@ -2996,7 +2998,7 @@ static int f2fs_write_cache_pages(struct address_space 
*mapping,
}
 
if (!f2fs_cluster_can_merge_page(,
-   page->index)) {
+   folio->index)) {
ret = f2fs_write_multi_pages(,
, wbc, io_type);
if (!ret)
@@ -3005,27 +3007,28 @@ static int f2fs_write_cache_pages(struct address_space 
*mapping,
}
 
if (unlikely(f2fs_cp_error(sbi)))
-   goto lock_page;
+   goto lock_folio;
 
if (!f2fs_cluster_is_empty())
-

[f2fs-dev] [PATCH v2 16/23] f2fs: Convert f2fs_sync_meta_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios. This is in preparation for the removal
of find_get_pages_range_tag().

Initially the function was checking if the previous page index is truly the
previous page i.e. 1 index behind the current page. To convert to folios and
maintain this check we need to make the check
folio->index != prev + folio_nr_pages(previous folio) since we don't know
how many pages are in a folio.

At index i == 0 the check is guaranteed to succeed, so to workaround indexing
bounds we can simply ignore the check for that specific index. This makes the
initial assignment of prev trivial, so I removed that as well.

Also modified a comment in commit_checkpoint for consistency.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/f2fs/checkpoint.c | 49 +++-
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 8259e0fa97e1..9f6694f7d723 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -377,59 +377,62 @@ long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, enum 
page_type type,
 {
struct address_space *mapping = META_MAPPING(sbi);
pgoff_t index = 0, prev = ULONG_MAX;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
long nwritten = 0;
-   int nr_pages;
+   int nr_folios;
struct writeback_control wbc = {
.for_reclaim = 0,
};
struct blk_plug plug;
 
-   pagevec_init();
+   folio_batch_init();
 
blk_start_plug();
 
-   while ((nr_pages = pagevec_lookup_tag(, mapping, ,
-   PAGECACHE_TAG_DIRTY))) {
+   while ((nr_folios = filemap_get_folios_tag(mapping, ,
+   (pgoff_t)-1,
+   PAGECACHE_TAG_DIRTY, ))) {
int i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
 
-   if (prev == ULONG_MAX)
-   prev = page->index - 1;
-   if (nr_to_write != LONG_MAX && page->index != prev + 1) 
{
-   pagevec_release();
+   if (nr_to_write != LONG_MAX && i != 0 &&
+   folio->index != prev +
+   folio_nr_pages(fbatch.folios[i-1])) {
+   folio_batch_release();
goto stop;
}
 
-   lock_page(page);
+   folio_lock(folio);
 
-   if (unlikely(page->mapping != mapping)) {
+   if (unlikely(folio->mapping != mapping)) {
 continue_unlock:
-   unlock_page(page);
+   folio_unlock(folio);
continue;
}
-   if (!PageDirty(page)) {
+   if (!folio_test_dirty(folio)) {
/* someone wrote it for us */
goto continue_unlock;
}
 
-   f2fs_wait_on_page_writeback(page, META, true, true);
+   f2fs_wait_on_page_writeback(>page, META,
+   true, true);
 
-   if (!clear_page_dirty_for_io(page))
+   if (!folio_clear_dirty_for_io(folio))
goto continue_unlock;
 
-   if (__f2fs_write_meta_page(page, , io_type)) {
-   unlock_page(page);
+   if (__f2fs_write_meta_page(>page, ,
+   io_type)) {
+   folio_unlock(folio);
break;
}
-   nwritten++;
-   prev = page->index;
+   nwritten += folio_nr_pages(folio);
+   prev = folio->index;
if (unlikely(nwritten >= nr_to_write))
break;
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
 stop:
@@ -1381,7 +1384,7 @@ static void commit_checkpoint(struct f2fs_sb_info *sbi,
};
 
/*
-* pagevec_lookup_tag and lock_page again will take
+* filemap_get_folios_tag and lock_page again will take
 * some extra time. Therefore, f2fs_update_meta_pages and
 * f2fs_sync_meta_pages are combined in this function.
 */
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net

[f2fs-dev] [PATCH v2 19/23] nilfs2: Convert nilfs_lookup_dirty_node_buffers() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
Acked-by: Ryusuke Konishi 
---
 fs/nilfs2/segment.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index c3f3484c4412..6f2ca279d230 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -737,20 +737,19 @@ static void nilfs_lookup_dirty_node_buffers(struct inode 
*inode,
 {
struct nilfs_inode_info *ii = NILFS_I(inode);
struct inode *btnc_inode = ii->i_assoc_inode;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
struct buffer_head *bh, *head;
unsigned int i;
pgoff_t index = 0;
 
if (!btnc_inode)
return;
+   folio_batch_init();
 
-   pagevec_init();
-
-   while (pagevec_lookup_tag(, btnc_inode->i_mapping, ,
-   PAGECACHE_TAG_DIRTY)) {
-   for (i = 0; i < pagevec_count(); i++) {
-   bh = head = page_buffers(pvec.pages[i]);
+   while (filemap_get_folios_tag(btnc_inode->i_mapping, ,
+   (pgoff_t)-1, PAGECACHE_TAG_DIRTY, )) {
+   for (i = 0; i < folio_batch_count(); i++) {
+   bh = head = folio_buffers(fbatch.folios[i]);
do {
if (buffer_dirty(bh) &&
!buffer_async_write(bh)) {
@@ -761,7 +760,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode 
*inode,
bh = bh->b_this_page;
} while (bh != head);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
 }
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 15/23] f2fs: Convert last_fsync_dnode() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert to use folios. This is in preparation for the removal of
find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/f2fs/node.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index cf8665f04c0d..b993be76013e 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1513,23 +1513,24 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, 
nid_t ino)
 static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino)
 {
pgoff_t index;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
struct page *last_page = NULL;
-   int nr_pages;
+   int nr_folios;
 
-   pagevec_init();
+   folio_batch_init();
index = 0;
 
-   while ((nr_pages = pagevec_lookup_tag(, NODE_MAPPING(sbi), ,
-   PAGECACHE_TAG_DIRTY))) {
+   while ((nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), ,
+   (pgoff_t)-1, PAGECACHE_TAG_DIRTY,
+   ))) {
int i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct page *page = [i]->page;
 
if (unlikely(f2fs_cp_error(sbi))) {
f2fs_put_page(last_page, 0);
-   pagevec_release();
+   folio_batch_release();
return ERR_PTR(-EIO);
}
 
@@ -1560,7 +1561,7 @@ static struct page *last_fsync_dnode(struct f2fs_sb_info 
*sbi, nid_t ino)
last_page = page;
unlock_page(page);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
return last_page;
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 12/23] f2fs: Convert f2fs_flush_inline_data() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios. This is in preparation for the removal
of find_get_pages_tag(). Does NOT support large folios.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/f2fs/node.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index a3c5eedfcf64..c2b54c58392a 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1885,17 +1885,18 @@ static bool flush_dirty_inode(struct page *page)
 void f2fs_flush_inline_data(struct f2fs_sb_info *sbi)
 {
pgoff_t index = 0;
-   struct pagevec pvec;
-   int nr_pages;
+   struct folio_batch fbatch;
+   int nr_folios;
 
-   pagevec_init();
+   folio_batch_init();
 
-   while ((nr_pages = pagevec_lookup_tag(,
-   NODE_MAPPING(sbi), , PAGECACHE_TAG_DIRTY))) {
+   while ((nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), ,
+   (pgoff_t)-1, PAGECACHE_TAG_DIRTY,
+   ))) {
int i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct page *page = [i]->page;
 
if (!IS_DNODE(page))
continue;
@@ -1922,7 +1923,7 @@ void f2fs_flush_inline_data(struct f2fs_sb_info *sbi)
}
unlock_page(page);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
 }
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 09/23] cifs: Convert wdata_alloc_and_fillpages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios. This is in preparation for the removal
of find_get_pages_range_tag(). Now also supports the use of large
folios.

Since tofind might be larger than the max number of folios in a
folio_batch (15), we loop through filling in wdata->pages pulling more
batches until we either reach tofind pages or run out of folios.

This function may not return all pages in the last found folio before
tofind pages are reached.

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/cifs/file.c | 33 ++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index fa738adc031f..c4da53b57369 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2517,14 +2517,41 @@ wdata_alloc_and_fillpages(pgoff_t tofind, struct 
address_space *mapping,
  unsigned int *found_pages)
 {
struct cifs_writedata *wdata;
-
+   struct folio_batch fbatch;
+   unsigned int i, idx, p, nr;
wdata = cifs_writedata_alloc((unsigned int)tofind,
 cifs_writev_complete);
if (!wdata)
return NULL;
 
-   *found_pages = find_get_pages_range_tag(mapping, index, end,
-   PAGECACHE_TAG_DIRTY, tofind, wdata->pages);
+   folio_batch_init();
+   *found_pages = 0;
+
+again:
+   nr = filemap_get_folios_tag(mapping, index, end,
+   PAGECACHE_TAG_DIRTY, );
+   if (!nr)
+   goto out; /* No dirty pages left in the range */
+
+   for (i = 0; i < nr; i++) {
+   struct folio *folio = fbatch.folios[i];
+
+   idx = 0;
+   p = folio_nr_pages(folio);
+add_more:
+   wdata->pages[*found_pages] = folio_page(folio, idx);
+   if (++*found_pages == tofind) {
+   folio_batch_release();
+   goto out;
+   }
+   if (++idx < p) {
+   folio_ref_inc(folio);
+   goto add_more;
+   }
+   }
+   folio_batch_release();
+   goto again;
+out:
return wdata;
 }
 
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 18/23] nilfs2: Convert nilfs_lookup_dirty_data_buffers() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
---
 fs/nilfs2/segment.c | 29 -
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 0afe0832c754..c3f3484c4412 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -680,7 +680,7 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode 
*inode,
  loff_t start, loff_t end)
 {
struct address_space *mapping = inode->i_mapping;
-   struct pagevec pvec;
+   struct folio_batch fbatch;
pgoff_t index = 0, last = ULONG_MAX;
size_t ndirties = 0;
int i;
@@ -694,23 +694,26 @@ static size_t nilfs_lookup_dirty_data_buffers(struct 
inode *inode,
index = start >> PAGE_SHIFT;
last = end >> PAGE_SHIFT;
}
-   pagevec_init();
+   folio_batch_init();
  repeat:
if (unlikely(index > last) ||
-   !pagevec_lookup_range_tag(, mapping, , last,
-   PAGECACHE_TAG_DIRTY))
+ !filemap_get_folios_tag(mapping, , last,
+ PAGECACHE_TAG_DIRTY, ))
return ndirties;
 
-   for (i = 0; i < pagevec_count(); i++) {
+   for (i = 0; i < folio_batch_count(); i++) {
struct buffer_head *bh, *head;
-   struct page *page = pvec.pages[i];
+   struct folio *folio = fbatch.folios[i];
 
-   lock_page(page);
-   if (!page_has_buffers(page))
-   create_empty_buffers(page, i_blocksize(inode), 0);
-   unlock_page(page);
+   folio_lock(folio);
+   head = folio_buffers(folio);
+   if (!head) {
+   create_empty_buffers(>page, i_blocksize(inode), 
0);
+   head = folio_buffers(folio);
+   }
+   folio_unlock(folio);
 
-   bh = head = page_buffers(page);
+   bh = head;
do {
if (!buffer_dirty(bh) || buffer_async_write(bh))
continue;
@@ -718,13 +721,13 @@ static size_t nilfs_lookup_dirty_data_buffers(struct 
inode *inode,
list_add_tail(>b_assoc_buffers, listp);
ndirties++;
if (unlikely(ndirties >= nlimit)) {
-   pagevec_release();
+   folio_batch_release();
cond_resched();
return ndirties;
}
} while (bh = bh->b_this_page, bh != head);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
goto repeat;
 }
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 23/23] filemap: Remove find_get_pages_range_tag()

2022-09-12 Thread Vishal Moola (Oracle)
All callers to find_get_pages_range_tag(), find_get_pages_tag(),
pagevec_lookup_range_tag(), and pagevec_lookup_tag() have been removed.

Signed-off-by: Vishal Moola (Oracle) 
---
 include/linux/pagemap.h | 10 ---
 include/linux/pagevec.h |  8 --
 mm/filemap.c| 60 -
 mm/swap.c   | 10 ---
 4 files changed, 88 deletions(-)

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 85cc96c82c2c..b8ea33751a66 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -742,16 +742,6 @@ unsigned find_get_pages_contig(struct address_space 
*mapping, pgoff_t start,
   unsigned int nr_pages, struct page **pages);
 unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start,
pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch);
-unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t 
*index,
-   pgoff_t end, xa_mark_t tag, unsigned int nr_pages,
-   struct page **pages);
-static inline unsigned find_get_pages_tag(struct address_space *mapping,
-   pgoff_t *index, xa_mark_t tag, unsigned int nr_pages,
-   struct page **pages)
-{
-   return find_get_pages_range_tag(mapping, index, (pgoff_t)-1, tag,
-   nr_pages, pages);
-}
 
 struct page *grab_cache_page_write_begin(struct address_space *mapping,
pgoff_t index);
diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h
index 215eb6c3bdc9..a520632297ac 100644
--- a/include/linux/pagevec.h
+++ b/include/linux/pagevec.h
@@ -26,14 +26,6 @@ struct pagevec {
 };
 
 void __pagevec_release(struct pagevec *pvec);
-unsigned pagevec_lookup_range_tag(struct pagevec *pvec,
-   struct address_space *mapping, pgoff_t *index, pgoff_t end,
-   xa_mark_t tag);
-static inline unsigned pagevec_lookup_tag(struct pagevec *pvec,
-   struct address_space *mapping, pgoff_t *index, xa_mark_t tag)
-{
-   return pagevec_lookup_range_tag(pvec, mapping, index, (pgoff_t)-1, tag);
-}
 
 static inline void pagevec_init(struct pagevec *pvec)
 {
diff --git a/mm/filemap.c b/mm/filemap.c
index 435fc53b3f2f..b986f246a6ae 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2309,66 +2309,6 @@ unsigned filemap_get_folios_tag(struct address_space 
*mapping, pgoff_t *start,
 }
 EXPORT_SYMBOL(filemap_get_folios_tag);
 
-/**
- * find_get_pages_range_tag - Find and return head pages matching @tag.
- * @mapping:   the address_space to search
- * @index: the starting page index
- * @end:   The final page index (inclusive)
- * @tag:   the tag index
- * @nr_pages:  the maximum number of pages
- * @pages: where the resulting pages are placed
- *
- * Like find_get_pages_range(), except we only return head pages which are
- * tagged with @tag.  @index is updated to the index immediately after the
- * last page we return, ready for the next iteration.
- *
- * Return: the number of pages which were found.
- */
-unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t 
*index,
-   pgoff_t end, xa_mark_t tag, unsigned int nr_pages,
-   struct page **pages)
-{
-   XA_STATE(xas, >i_pages, *index);
-   struct folio *folio;
-   unsigned ret = 0;
-
-   if (unlikely(!nr_pages))
-   return 0;
-
-   rcu_read_lock();
-   while ((folio = find_get_entry(, end, tag))) {
-   /*
-* Shadow entries should never be tagged, but this iteration
-* is lockless so there is a window for page reclaim to evict
-* a page we saw tagged.  Skip over it.
-*/
-   if (xa_is_value(folio))
-   continue;
-
-   pages[ret] = >page;
-   if (++ret == nr_pages) {
-   *index = folio->index + folio_nr_pages(folio);
-   goto out;
-   }
-   }
-
-   /*
-* We come here when we got to @end. We take care to not overflow the
-* index @index as it confuses some of the callers. This breaks the
-* iteration when there is a page at index -1 but that is already
-* broken anyway.
-*/
-   if (end == (pgoff_t)-1)
-   *index = (pgoff_t)-1;
-   else
-   *index = end + 1;
-out:
-   rcu_read_unlock();
-
-   return ret;
-}
-EXPORT_SYMBOL(find_get_pages_range_tag);
-
 /*
  * CD/DVDs are error prone. When a medium error occurs, the driver may fail
  * a _large_ part of the i/o request. Imagine the worst scenario:
diff --git a/mm/swap.c b/mm/swap.c
index 9cee7f6a3809..7b8c1c8024a1 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -1055,16 +1055,6 @@ void folio_batch_remove_exceptionals(struct folio_batch 
*fbatch)
fbatch->nr = j;
 }
 
-unsigned 

[f2fs-dev] [PATCH v2 00/23] Convert to filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
This patch series replaces find_get_pages_range_tag() with
filemap_get_folios_tag(). This also allows the removal of multiple
calls to compound_head() throughout.
It also makes a good chunk of the straightforward conversions to folios,
and takes the opportunity to introduce a function that grabs a folio
from the pagecache.

F2fs and Ceph have quite alot of work to be done regarding folios, so
for now those patches only have the changes necessary for the removal of
find_get_pages_range_tag(), and only support folios of size 1 (which is
all they use right now anyways).

I've run xfstests on btrfs, ext4, f2fs, and nilfs2, but more testing may be
beneficial. The page-writeback and filemap changes implicitly work. Testing
and review of the other changes (afs, ceph, cifs, gfs2) would be appreciated.
---
v2:
  Got Acked-By tags for nilfs and btrfs changes
  Fixed an error arising in f2fs
  - Reported-by: kernel test robot 
   
Vishal Moola (Oracle) (23):
  pagemap: Add filemap_grab_folio()
  filemap: Added filemap_get_folios_tag()
  filemap: Convert __filemap_fdatawait_range() to use
filemap_get_folios_tag()
  page-writeback: Convert write_cache_pages() to use
filemap_get_folios_tag()
  afs: Convert afs_writepages_region() to use filemap_get_folios_tag()
  btrfs: Convert btree_write_cache_pages() to use
filemap_get_folio_tag()
  btrfs: Convert extent_write_cache_pages() to use
filemap_get_folios_tag()
  ceph: Convert ceph_writepages_start() to use filemap_get_folios_tag()
  cifs: Convert wdata_alloc_and_fillpages() to use
filemap_get_folios_tag()
  ext4: Convert mpage_prepare_extent_to_map() to use
filemap_get_folios_tag()
  f2fs: Convert f2fs_fsync_node_pages() to use filemap_get_folios_tag()
  f2fs: Convert f2fs_flush_inline_data() to use filemap_get_folios_tag()
  f2fs: Convert f2fs_sync_node_pages() to use filemap_get_folios_tag()
  f2fs: Convert f2fs_write_cache_pages() to use filemap_get_folios_tag()
  f2fs: Convert last_fsync_dnode() to use filemap_get_folios_tag()
  f2fs: Convert f2fs_sync_meta_pages() to use filemap_get_folios_tag()
  gfs2: Convert gfs2_write_cache_jdata() to use filemap_get_folios_tag()
  nilfs2: Convert nilfs_lookup_dirty_data_buffers() to use
filemap_get_folios_tag()
  nilfs2: Convert nilfs_lookup_dirty_node_buffers() to use
filemap_get_folios_tag()
  nilfs2: Convert nilfs_btree_lookup_dirty_buffers() to use
filemap_get_folios_tag()
  nilfs2: Convert nilfs_copy_dirty_pages() to use
filemap_get_folios_tag()
  nilfs2: Convert nilfs_clear_dirty_pages() to use
filemap_get_folios_tag()
  filemap: Remove find_get_pages_range_tag()

 fs/afs/write.c  | 114 +
 fs/btrfs/extent_io.c|  57 +
 fs/ceph/addr.c  | 138 
 fs/cifs/file.c  |  33 +-
 fs/ext4/inode.c |  55 
 fs/f2fs/checkpoint.c|  49 +++---
 fs/f2fs/compress.c  |  13 ++--
 fs/f2fs/data.c  |  69 ++--
 fs/f2fs/f2fs.h  |   5 +-
 fs/f2fs/node.c  |  72 +++--
 fs/gfs2/aops.c  |  64 ++-
 fs/nilfs2/btree.c   |  14 ++--
 fs/nilfs2/page.c|  59 -
 fs/nilfs2/segment.c |  44 +++--
 include/linux/pagemap.h |  32 +++---
 include/linux/pagevec.h |   8 ---
 mm/filemap.c|  87 -
 mm/page-writeback.c |  44 +++--
 mm/swap.c   |  10 ---
 19 files changed, 507 insertions(+), 460 deletions(-)

-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 21/23] nilfs2: Convert nilfs_copy_dirty_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
Acked-by: Ryusuke Konishi 
---
 fs/nilfs2/page.c | 39 ---
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 3267e96c256c..5c96084e829f 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -240,42 +240,43 @@ static void nilfs_copy_page(struct page *dst, struct page 
*src, int copy_dirty)
 int nilfs_copy_dirty_pages(struct address_space *dmap,
   struct address_space *smap)
 {
-   struct pagevec pvec;
+   struct folio_batch fbatch;
unsigned int i;
pgoff_t index = 0;
int err = 0;
 
-   pagevec_init();
+   folio_batch_init();
 repeat:
-   if (!pagevec_lookup_tag(, smap, , PAGECACHE_TAG_DIRTY))
+   if (!filemap_get_folios_tag(smap, , (pgoff_t)-1,
+   PAGECACHE_TAG_DIRTY, ))
return 0;
 
-   for (i = 0; i < pagevec_count(); i++) {
-   struct page *page = pvec.pages[i], *dpage;
+   for (i = 0; i < folio_batch_count(); i++) {
+   struct folio *folio = fbatch.folios[i], *dfolio;
 
-   lock_page(page);
-   if (unlikely(!PageDirty(page)))
-   NILFS_PAGE_BUG(page, "inconsistent dirty state");
+   folio_lock(folio);
+   if (unlikely(!folio_test_dirty(folio)))
+   NILFS_PAGE_BUG(>page, "inconsistent dirty 
state");
 
-   dpage = grab_cache_page(dmap, page->index);
-   if (unlikely(!dpage)) {
+   dfolio = filemap_grab_folio(dmap, folio->index);
+   if (unlikely(!dfolio)) {
/* No empty page is added to the page cache */
err = -ENOMEM;
-   unlock_page(page);
+   folio_unlock(folio);
break;
}
-   if (unlikely(!page_has_buffers(page)))
-   NILFS_PAGE_BUG(page,
+   if (unlikely(!folio_buffers(folio)))
+   NILFS_PAGE_BUG(>page,
   "found empty page in dat page cache");
 
-   nilfs_copy_page(dpage, page, 1);
-   __set_page_dirty_nobuffers(dpage);
+   nilfs_copy_page(>page, >page, 1);
+   filemap_dirty_folio(folio_mapping(dfolio), dfolio);
 
-   unlock_page(dpage);
-   put_page(dpage);
-   unlock_page(page);
+   folio_unlock(dfolio);
+   folio_put(dfolio);
+   folio_unlock(folio);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
 
if (likely(!err))
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 20/23] nilfs2: Convert nilfs_btree_lookup_dirty_buffers() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Convert function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
Acked-by: Ryusuke Konishi 
---
 fs/nilfs2/btree.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 9f4d9432d38a..1e26f32a4e36 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -2143,7 +2143,7 @@ static void nilfs_btree_lookup_dirty_buffers(struct 
nilfs_bmap *btree,
struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
struct address_space *btcache = btnc_inode->i_mapping;
struct list_head lists[NILFS_BTREE_LEVEL_MAX];
-   struct pagevec pvec;
+   struct folio_batch fbatch;
struct buffer_head *bh, *head;
pgoff_t index = 0;
int level, i;
@@ -2153,19 +2153,19 @@ static void nilfs_btree_lookup_dirty_buffers(struct 
nilfs_bmap *btree,
 level++)
INIT_LIST_HEAD([level]);
 
-   pagevec_init();
+   folio_batch_init();
 
-   while (pagevec_lookup_tag(, btcache, ,
-   PAGECACHE_TAG_DIRTY)) {
-   for (i = 0; i < pagevec_count(); i++) {
-   bh = head = page_buffers(pvec.pages[i]);
+   while (filemap_get_folios_tag(btcache, , (pgoff_t)-1,
+   PAGECACHE_TAG_DIRTY, )) {
+   for (i = 0; i < folio_batch_count(); i++) {
+   bh = head = folio_buffers(fbatch.folios[i]);
do {
if (buffer_dirty(bh))
nilfs_btree_add_dirty_buffer(btree,
 lists, bh);
} while ((bh = bh->b_this_page) != head);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
 
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 04/23] page-writeback: Convert write_cache_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
---
 mm/page-writeback.c | 44 +++-
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 032a7bf8d259..087165357a5a 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2285,15 +2285,15 @@ int write_cache_pages(struct address_space *mapping,
int ret = 0;
int done = 0;
int error;
-   struct pagevec pvec;
-   int nr_pages;
+   struct folio_batch fbatch;
+   int nr_folios;
pgoff_t index;
pgoff_t end;/* Inclusive */
pgoff_t done_index;
int range_whole = 0;
xa_mark_t tag;
 
-   pagevec_init();
+   folio_batch_init();
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* prev offset */
end = -1;
@@ -2313,17 +2313,18 @@ int write_cache_pages(struct address_space *mapping,
while (!done && (index <= end)) {
int i;
 
-   nr_pages = pagevec_lookup_range_tag(, mapping, , end,
-   tag);
-   if (nr_pages == 0)
+   nr_folios = filemap_get_folios_tag(mapping, , end,
+   tag, );
+
+   if (nr_folios == 0)
break;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
 
-   done_index = page->index;
+   done_index = folio->index;
 
-   lock_page(page);
+   folio_lock(folio);
 
/*
 * Page truncated or invalidated. We can freely skip it
@@ -2333,30 +2334,30 @@ int write_cache_pages(struct address_space *mapping,
 * even if there is now a new, dirty page at the same
 * pagecache address.
 */
-   if (unlikely(page->mapping != mapping)) {
+   if (unlikely(folio->mapping != mapping)) {
 continue_unlock:
-   unlock_page(page);
+   folio_unlock(folio);
continue;
}
 
-   if (!PageDirty(page)) {
+   if (!folio_test_dirty(folio)) {
/* someone wrote it for us */
goto continue_unlock;
}
 
-   if (PageWriteback(page)) {
+   if (folio_test_writeback(folio)) {
if (wbc->sync_mode != WB_SYNC_NONE)
-   wait_on_page_writeback(page);
+   folio_wait_writeback(folio);
else
goto continue_unlock;
}
 
-   BUG_ON(PageWriteback(page));
-   if (!clear_page_dirty_for_io(page))
+   BUG_ON(folio_test_writeback(folio));
+   if (!folio_clear_dirty_for_io(folio))
goto continue_unlock;
 
trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
-   error = (*writepage)(page, wbc, data);
+   error = writepage(>page, wbc, data);
if (unlikely(error)) {
/*
 * Handle errors according to the type of
@@ -2371,11 +2372,12 @@ int write_cache_pages(struct address_space *mapping,
 * the first error.
 */
if (error == AOP_WRITEPAGE_ACTIVATE) {
-   unlock_page(page);
+   folio_unlock(folio);
error = 0;
} else if (wbc->sync_mode != WB_SYNC_ALL) {
ret = error;
-   done_index = page->index + 1;
+   done_index = folio->index +
+   folio_nr_pages(folio);
done = 1;
break;
}
@@ -2395,7 +2397,7 @@ int write_cache_pages(struct address_space *mapping,
break;
}
}
-   pagevec_release();
+   folio_batch_release();
 

[f2fs-dev] [PATCH v2 03/23] filemap: Convert __filemap_fdatawait_range() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted function to use folios. This is in preparation for the removal
of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
---
 mm/filemap.c | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 3ded72a65668..435fc53b3f2f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -503,28 +503,30 @@ static void __filemap_fdatawait_range(struct 
address_space *mapping,
 {
pgoff_t index = start_byte >> PAGE_SHIFT;
pgoff_t end = end_byte >> PAGE_SHIFT;
-   struct pagevec pvec;
-   int nr_pages;
+   struct folio_batch fbatch;
+   unsigned nr_folios;
 
if (end_byte < start_byte)
return;
 
-   pagevec_init();
+   folio_batch_init();
+
while (index <= end) {
unsigned i;
 
-   nr_pages = pagevec_lookup_range_tag(, mapping, ,
-   end, PAGECACHE_TAG_WRITEBACK);
-   if (!nr_pages)
+   nr_folios = filemap_get_folios_tag(mapping, , end,
+   PAGECACHE_TAG_WRITEBACK, );
+
+   if (!nr_folios)
break;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
 
-   wait_on_page_writeback(page);
-   ClearPageError(page);
+   folio_wait_writeback(folio);
+   folio_clear_error(folio);
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
 }
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 07/23] btrfs: Convert extent_write_cache_pages() to use filemap_get_folios_tag()

2022-09-12 Thread Vishal Moola (Oracle)
Converted function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag(). Now also supports large
folios.

Signed-off-by: Vishal Moola (Oracle) 
Acked-by: David Sterba 
---
 fs/btrfs/extent_io.c | 38 +++---
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index d1fa072bfdd0..80fe313f8461 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4972,8 +4972,8 @@ static int extent_write_cache_pages(struct address_space 
*mapping,
int ret = 0;
int done = 0;
int nr_to_write_done = 0;
-   struct pagevec pvec;
-   int nr_pages;
+   struct folio_batch fbatch;
+   unsigned int nr_folios;
pgoff_t index;
pgoff_t end;/* Inclusive */
pgoff_t done_index;
@@ -4993,7 +4993,7 @@ static int extent_write_cache_pages(struct address_space 
*mapping,
if (!igrab(inode))
return 0;
 
-   pagevec_init();
+   folio_batch_init();
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* Start from prev offset */
end = -1;
@@ -5031,14 +5031,14 @@ static int extent_write_cache_pages(struct 
address_space *mapping,
tag_pages_for_writeback(mapping, index, end);
done_index = index;
while (!done && !nr_to_write_done && (index <= end) &&
-   (nr_pages = pagevec_lookup_range_tag(, mapping,
-   , end, tag))) {
+   (nr_folios = filemap_get_folios_tag(mapping, ,
+   end, tag, ))) {
unsigned i;
 
-   for (i = 0; i < nr_pages; i++) {
-   struct page *page = pvec.pages[i];
+   for (i = 0; i < nr_folios; i++) {
+   struct folio *folio = fbatch.folios[i];
 
-   done_index = page->index + 1;
+   done_index = folio->index + folio_nr_pages(folio);
/*
 * At this point we hold neither the i_pages lock nor
 * the page lock: the page may be truncated or
@@ -5046,29 +5046,29 @@ static int extent_write_cache_pages(struct 
address_space *mapping,
 * or even swizzled back from swapper_space to
 * tmpfs file mapping
 */
-   if (!trylock_page(page)) {
+   if (!folio_trylock(folio)) {
submit_write_bio(epd, 0);
-   lock_page(page);
+   folio_lock(folio);
}
 
-   if (unlikely(page->mapping != mapping)) {
-   unlock_page(page);
+   if (unlikely(folio->mapping != mapping)) {
+   folio_unlock(folio);
continue;
}
 
if (wbc->sync_mode != WB_SYNC_NONE) {
-   if (PageWriteback(page))
+   if (folio_test_writeback(folio))
submit_write_bio(epd, 0);
-   wait_on_page_writeback(page);
+   folio_wait_writeback(folio);
}
 
-   if (PageWriteback(page) ||
-   !clear_page_dirty_for_io(page)) {
-   unlock_page(page);
+   if (folio_test_writeback(folio) ||
+   !folio_clear_dirty_for_io(folio)) {
+   folio_unlock(folio);
continue;
}
 
-   ret = __extent_writepage(page, wbc, epd);
+   ret = __extent_writepage(>page, wbc, epd);
if (ret < 0) {
done = 1;
break;
@@ -5081,7 +5081,7 @@ static int extent_write_cache_pages(struct address_space 
*mapping,
 */
nr_to_write_done = wbc->nr_to_write <= 0;
}
-   pagevec_release();
+   folio_batch_release();
cond_resched();
}
if (!scanned && !done) {
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 01/23] pagemap: Add filemap_grab_folio()

2022-09-12 Thread Vishal Moola (Oracle)
Add function filemap_grab_folio() to grab a folio from the page cache.
This function is meant to serve as a folio replacement for
grab_cache_page, and is used to facilitate the removal of
find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) 
---
 include/linux/pagemap.h | 20 
 1 file changed, 20 insertions(+)

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 0178b2040ea3..4d3092d6b2c0 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -547,6 +547,26 @@ static inline struct folio *filemap_lock_folio(struct 
address_space *mapping,
return __filemap_get_folio(mapping, index, FGP_LOCK, 0);
 }
 
+/**
+ * filemap_grab_folio - grab a folio from the page cache
+ * @mapping: The address space to search
+ * @index: The page index
+ *
+ * Looks up the page cache entry at @mapping & @index. If no folio is found,
+ * a new folio is created. The folio is locked, marked as accessed, and
+ * returned.
+ *
+ * Return: A found or created folio. NULL if no folio is found and failed to
+ * create a folio.
+ */
+static inline struct folio *filemap_grab_folio(struct address_space *mapping,
+   pgoff_t index)
+{
+   return __filemap_get_folio(mapping, index,
+   FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
+   mapping_gfp_mask(mapping));
+}
+
 /**
  * find_get_page - find and get a page reference
  * @mapping: the address_space to search
-- 
2.36.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH v2] f2fs: fix to disallow getting inner inode via f2fs_iget()

2022-09-12 Thread Jaegeuk Kim
On 09/08, Chao Yu wrote:
> On 2022/9/8 10:19, Jaegeuk Kim wrote:
> > On 09/08, Chao Yu wrote:
> > > On 2022/9/8 10:02, Jaegeuk Kim wrote:
> > > > On 08/31, Chao Yu wrote:
> > > > > From: Chao Yu 
> > > > > 
> > > > > Introduce f2fs_iget_inner() for f2fs_fill_super() to get inner inode:
> > > > > meta inode, node inode or compressed inode, and add 
> > > > > f2fs_check_nid_range()
> > > > > in f2fs_iget() to avoid getting inner inode from external interfaces.
> > > > 
> > > > So, we don't want to check the range of inner inode numbers? What'd be 
> > > > the
> > > > way to check it's okay?
> > > 
> > > For node_ino, meta_ino, root_ino, we have checked them in 
> > > sanity_check_raw_super()
> > > as below:
> > > 
> > >   /* check reserved ino info */
> > >   if (le32_to_cpu(raw_super->node_ino) != 1 ||
> > >   le32_to_cpu(raw_super->meta_ino) != 2 ||
> > >   le32_to_cpu(raw_super->root_ino) != 3) {
> > >   f2fs_info(sbi, "Invalid Fs Meta Ino: node(%u) meta(%u) 
> > > root(%u)",
> > > le32_to_cpu(raw_super->node_ino),
> > > le32_to_cpu(raw_super->meta_ino),
> > > le32_to_cpu(raw_super->root_ino));
> > >   return -EFSCORRUPTED;
> > >   }
> > > 
> > > compressed_ino should always be NM_I(sbi)->max_nid, it can be checked in
> > > f2fs_init_compress_inode()?
> > 
> > Hmm, I'm not sure whether we really need this patch, since it'd look better
> > to handle all the iget with single f2fs_iget?
> 
> Well, the main concern is previously f2fs_iget() won't check validation for 
> inner
> inode due to it will skip do_read_inode() - f2fs_check_nid_range(), so that 
> in a
> fuzzed image, caller may pass inner ino into f2fs_iget(), result in incorrect 
> use
> of inner inode. So I add f2fs_check_nid_range() in prior to f2fs_iget_inner() 
> in
> f2fs_iget() as below to detect and avoid this case.

FWIW, sanity_check_raw_super() checked the inode numbers.

> 
> > > > > +struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
> > > > > +{
> > > > > + int ret;
> > > > > +
> > > > > + ret = f2fs_check_nid_range(F2FS_SB(sb), ino);
> > > > > + if (ret)
> > > > > + return ERR_PTR(ret);
> > > > > +
> > > > > + return f2fs_iget_inner(sb, ino);


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH v2 18/23] nilfs2: Convert nilfs_lookup_dirty_data_buffers() to use filemap_get_folios_tag()

2022-09-12 Thread Ryusuke Konishi
On Tue, Sep 13, 2022 at 3:30 AM Vishal Moola (Oracle) wrote:
>
> Convert function to use folios throughout. This is in preparation for
> the removal of find_get_pages_range_tag().
>
> Signed-off-by: Vishal Moola (Oracle) 
> ---
>  fs/nilfs2/segment.c | 29 -
>  1 file changed, 16 insertions(+), 13 deletions(-)

Acked-by: Ryusuke Konishi 

Looks good.   Thank you for reflecting the previous comment.

Ryusuke Konishi


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH v2] f2fs: fix to disallow getting inner inode via f2fs_iget()

2022-09-12 Thread Chao Yu

On 2022/9/12 23:39, Jaegeuk Kim wrote:

On 09/08, Chao Yu wrote:

On 2022/9/8 10:19, Jaegeuk Kim wrote:

On 09/08, Chao Yu wrote:

On 2022/9/8 10:02, Jaegeuk Kim wrote:

On 08/31, Chao Yu wrote:

From: Chao Yu 

Introduce f2fs_iget_inner() for f2fs_fill_super() to get inner inode:
meta inode, node inode or compressed inode, and add f2fs_check_nid_range()
in f2fs_iget() to avoid getting inner inode from external interfaces.


So, we don't want to check the range of inner inode numbers? What'd be the
way to check it's okay?


For node_ino, meta_ino, root_ino, we have checked them in 
sanity_check_raw_super()
as below:

/* check reserved ino info */
if (le32_to_cpu(raw_super->node_ino) != 1 ||
le32_to_cpu(raw_super->meta_ino) != 2 ||
le32_to_cpu(raw_super->root_ino) != 3) {
f2fs_info(sbi, "Invalid Fs Meta Ino: node(%u) meta(%u) 
root(%u)",
  le32_to_cpu(raw_super->node_ino),
  le32_to_cpu(raw_super->meta_ino),
  le32_to_cpu(raw_super->root_ino));
return -EFSCORRUPTED;
}

compressed_ino should always be NM_I(sbi)->max_nid, it can be checked in
f2fs_init_compress_inode()?


Hmm, I'm not sure whether we really need this patch, since it'd look better
to handle all the iget with single f2fs_iget?


Well, the main concern is previously f2fs_iget() won't check validation for 
inner
inode due to it will skip do_read_inode() - f2fs_check_nid_range(), so that in a
fuzzed image, caller may pass inner ino into f2fs_iget(), result in incorrect 
use
of inner inode. So I add f2fs_check_nid_range() in prior to f2fs_iget_inner() in
f2fs_iget() as below to detect and avoid this case.


FWIW, sanity_check_raw_super() checked the inode numbers.


However, previously, f2fs_iget() will return inner inode to caller directly, if 
caller
passes meta_ino, node_ino or compress_ino to f2fs_iget()?

Thanks,






+struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
+{
+   int ret;
+
+   ret = f2fs_check_nid_range(F2FS_SB(sb), ino);
+   if (ret)
+   return ERR_PTR(ret);
+
+   return f2fs_iget_inner(sb, ino);



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2] f2fs: fix to do sanity check on destination blkaddr during recovery

2022-09-12 Thread Chao Yu
As Wenqing Liu reported in bugzilla:

https://bugzilla.kernel.org/show_bug.cgi?id=216456

loop5: detected capacity change from 0 to 131072
F2FS-fs (loop5): recover_inode: ino = 6, name = hln, inline = 1
F2FS-fs (loop5): recover_data: ino = 6 (i_size: recover) err = 0
F2FS-fs (loop5): recover_inode: ino = 6, name = hln, inline = 1
F2FS-fs (loop5): recover_data: ino = 6 (i_size: recover) err = 0
F2FS-fs (loop5): recover_inode: ino = 6, name = hln, inline = 1
F2FS-fs (loop5): recover_data: ino = 6 (i_size: recover) err = 0
F2FS-fs (loop5): Bitmap was wrongly set, blk:5634
[ cut here ]
WARNING: CPU: 3 PID: 1013 at fs/f2fs/segment.c:2198
RIP: 0010:update_sit_entry+0xa55/0x10b0 [f2fs]
Call Trace:
 
 f2fs_do_replace_block+0xa98/0x1890 [f2fs]
 f2fs_replace_block+0xeb/0x180 [f2fs]
 recover_data+0x1a69/0x6ae0 [f2fs]
 f2fs_recover_fsync_data+0x120d/0x1fc0 [f2fs]
 f2fs_fill_super+0x4665/0x61e0 [f2fs]
 mount_bdev+0x2cf/0x3b0
 legacy_get_tree+0xed/0x1d0
 vfs_get_tree+0x81/0x2b0
 path_mount+0x47e/0x19d0
 do_mount+0xce/0xf0
 __x64_sys_mount+0x12c/0x1a0
 do_syscall_64+0x38/0x90
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

If we enable CONFIG_F2FS_CHECK_FS config, it will trigger a kernel panic
instead of warning.

The root cause is: in fuzzed image, SIT table is inconsistent with inode
mapping table, result in triggering such warning during SIT table update.

This patch introduces a new flag DATA_GENERIC_ENHANCE_UPDATE, w/ this
flag, data block recovery flow can check destination blkaddr's validation
in SIT table, and skip f2fs_replace_block() to avoid inconsistent status.

Cc: 
Reported-by: Wenqing Liu 
Signed-off-by: Chao Yu 
---
v2:
- Cc stable kernel mailing list
- add reported-by tag
- update commit title
 fs/f2fs/checkpoint.c | 10 +-
 fs/f2fs/f2fs.h   |  4 
 fs/f2fs/recovery.c   |  8 
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index cf315e3d244c..c3119e4c890c 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -140,7 +140,7 @@ static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, 
block_t blkaddr,
unsigned int segno, offset;
bool exist;
 
-   if (type != DATA_GENERIC_ENHANCE && type != DATA_GENERIC_ENHANCE_READ)
+   if (type == DATA_GENERIC)
return true;
 
segno = GET_SEGNO(sbi, blkaddr);
@@ -148,6 +148,13 @@ static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, 
block_t blkaddr,
se = get_seg_entry(sbi, segno);
 
exist = f2fs_test_bit(offset, se->cur_valid_map);
+   if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) {
+   f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
+blkaddr, exist);
+   set_sbi_flag(sbi, SBI_NEED_FSCK);
+   return exist;
+   }
+
if (!exist && type == DATA_GENERIC_ENHANCE) {
f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
 blkaddr, exist);
@@ -185,6 +192,7 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
case DATA_GENERIC:
case DATA_GENERIC_ENHANCE:
case DATA_GENERIC_ENHANCE_READ:
+   case DATA_GENERIC_ENHANCE_UPDATE:
if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
blkaddr < MAIN_BLKADDR(sbi))) {
f2fs_warn(sbi, "access invalid blkaddr:%u",
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 80c0ae6196db..dee7b67a17a6 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -266,6 +266,10 @@ enum {
 * condition of read on truncated area
 * by extent_cache
 */
+   DATA_GENERIC_ENHANCE_UPDATE,/*
+* strong check on range and segment
+* bitmap for update case
+*/
META_GENERIC,
 };
 
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index dcd0a1e35095..8326003e6918 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -698,6 +698,14 @@ static int do_recover_data(struct f2fs_sb_info *sbi, 
struct inode *inode,
goto err;
}
 
+   if (f2fs_is_valid_blkaddr(sbi, dest,
+   DATA_GENERIC_ENHANCE_UPDATE)) {
+   f2fs_err(sbi, "Inconsistent dest blkaddr:%u, 
ino:%lu, ofs:%u",
+   dest, inode->i_ino, dn.ofs_in_node);
+   err = -EFSCORRUPTED;
+   goto err;
+   }
+
/* write dummy data page */
f2fs_replace_block(sbi, , src, dest,
ni.version, false, false);
-- 
2.25.1




[f2fs-dev] [PATCH] f2fs: fix to do sanity check on summary info

2022-09-12 Thread Chao Yu
As Wenqing Liu reported in bugzilla:

https://bugzilla.kernel.org/show_bug.cgi?id=216456

BUG: KASAN: use-after-free in recover_data+0x63ae/0x6ae0 [f2fs]
Read of size 4 at addr 8881464dcd80 by task mount/1013

CPU: 3 PID: 1013 Comm: mount Tainted: GW  6.0.0-rc4 #1
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014
Call Trace:
 dump_stack_lvl+0x45/0x5e
 print_report.cold+0xf3/0x68d
 kasan_report+0xa8/0x130
 recover_data+0x63ae/0x6ae0 [f2fs]
 f2fs_recover_fsync_data+0x120d/0x1fc0 [f2fs]
 f2fs_fill_super+0x4665/0x61e0 [f2fs]
 mount_bdev+0x2cf/0x3b0
 legacy_get_tree+0xed/0x1d0
 vfs_get_tree+0x81/0x2b0
 path_mount+0x47e/0x19d0
 do_mount+0xce/0xf0
 __x64_sys_mount+0x12c/0x1a0
 do_syscall_64+0x38/0x90
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

The root cause is: in fuzzed image, SSA table is corrupted: ofs_in_node
is larger than ADDRS_PER_PAGE(), result in out-of-range access on 4k-size
page.

- recover_data
 - do_recover_data
  - check_index_in_prev_nodes
   - f2fs_data_blkaddr

This patch adds sanity check on summary info in recovery and GC flow
in where the flows rely on them.

After patch:
[   29.310883] F2FS-fs (loop0): Inconsistent ofs_in_node:65286 in summary, 
ino:0, nid:6, max:1018

Cc: 
Reported-by: Wenqing Liu 
Signed-off-by: Chao Yu 
---
 fs/f2fs/gc.c   | 10 +-
 fs/f2fs/recovery.c | 15 ---
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index fd400d148afb..3a820e5cdaee 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1078,7 +1078,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct 
f2fs_summary *sum,
 {
struct page *node_page;
nid_t nid;
-   unsigned int ofs_in_node;
+   unsigned int ofs_in_node, max_addrs;
block_t source_blkaddr;
 
nid = le32_to_cpu(sum->nid);
@@ -1104,6 +1104,14 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct 
f2fs_summary *sum,
return false;
}
 
+   max_addrs = IS_INODE(node_page) ? DEF_ADDRS_PER_INODE :
+   DEF_ADDRS_PER_BLOCK;
+   if (ofs_in_node >= max_addrs) {
+   f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%u, 
nid:%u, max:%u",
+   ofs_in_node, dni->ino, dni->nid, max_addrs);
+   return false;
+   }
+
*nofs = ofs_of_node(node_page);
source_blkaddr = data_blkaddr(NULL, node_page, ofs_in_node);
f2fs_put_page(node_page, 1);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 8326003e6918..9b361fff30aa 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -474,7 +474,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info 
*sbi,
struct dnode_of_data tdn = *dn;
nid_t ino, nid;
struct inode *inode;
-   unsigned int offset;
+   unsigned int offset, ofs_in_node, max_addrs;
block_t bidx;
int i;
 
@@ -501,15 +501,24 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info 
*sbi,
 got_it:
/* Use the locked dnode page and inode */
nid = le32_to_cpu(sum.nid);
+   ofs_in_node = le16_to_cpu(sum.ofs_in_node);
+
+   max_addrs = ADDRS_PER_PAGE(dn->node_page, dn->inode);
+   if (ofs_in_node >= max_addrs) {
+   f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%u, 
nid:%u, max:%u",
+   ofs_in_node, ino, nid, max_addrs);
+   return -EFSCORRUPTED;
+   }
+
if (dn->inode->i_ino == nid) {
tdn.nid = nid;
if (!dn->inode_page_locked)
lock_page(dn->inode_page);
tdn.node_page = dn->inode_page;
-   tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
+   tdn.ofs_in_node = ofs_in_node;
goto truncate_out;
} else if (dn->nid == nid) {
-   tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
+   tdn.ofs_in_node = ofs_in_node;
goto truncate_out;
}
 
-- 
2.25.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH -next] f2fs: adding truncate page cache after being moved

2022-09-12 Thread Chao Yu

On 2022/9/13 11:05, Zhang Qilong wrote:

If we do not truncate source page cache, user can still
see the previous source data after being moved. We fix
it by adding truncating after __exchange_data_block.

Fixes:4dd6f977fc778 ("f2fs: support an ioctl to move a range of data blocks")
Signed-off-by: Zhang Qilong 
---
  fs/f2fs/file.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 771f1f7f3690..e3ff648aa496 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2789,6 +2789,10 @@ static int f2fs_move_file_range(struct file *file_in, 
loff_t pos_in,
}
f2fs_unlock_op(sbi);
  
+	filemap_invalidate_lock(src->i_mapping);


invalidate lock should cover __exchange_data_block()?


+   truncate_pagecache_range(src, pos_in, pos_in + len - 1);


truncate_pagecache_range() should be called before __exchange_data_block()?

Thanks,


+   filemap_invalidate_unlock(src->i_mapping);
+
if (src != dst)
f2fs_up_write(_I(dst)->i_gc_rwsem[WRITE]);
  out_src:



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] 答复: 答复: [PATCH -next] f2fs: adding truncate page cache after being moved

2022-09-12 Thread zhangqilong via Linux-f2fs-devel
> 
> On 2022/9/13 11:41, zhangqilong wrote:
> >> On 2022/9/13 11:05, Zhang Qilong wrote:
> >>> If we do not truncate source page cache, user can still see the
> >>> previous source data after being moved. We fix it by adding
> >>> truncating after __exchange_data_block.
> >>>
> >>> Fixes:4dd6f977fc778 ("f2fs: support an ioctl to move a range of data
> >>> blocks")
> >>> Signed-off-by: Zhang Qilong 
> >>> ---
> >>>fs/f2fs/file.c | 4 
> >>>1 file changed, 4 insertions(+)
> >>>
> >>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index
> >>> 771f1f7f3690..e3ff648aa496 100644
> >>> --- a/fs/f2fs/file.c
> >>> +++ b/fs/f2fs/file.c
> >>> @@ -2789,6 +2789,10 @@ static int f2fs_move_file_range(struct file
> >> *file_in, loff_t pos_in,
> >>>   }
> >>>   f2fs_unlock_op(sbi);
> >>>
> >>> + filemap_invalidate_lock(src->i_mapping);
> >>
> >> invalidate lock should cover __exchange_data_block()?
> >>
> >>> + truncate_pagecache_range(src, pos_in, pos_in + len - 1);
> >>
> >> truncate_pagecache_range() should be called before
> >> __exchange_data_block()?
> >
> > I have tried it, but it do not work. So I move the truncate operation
> > to the back of __exchange_data_block that it works well. I don't know
> > much enough, what do you think of this issue.
> 
> Can you describe details about the testcase?
> 
> Thanks,
> 

Process 1   process 2
-> open A
-> mmap
Read the data and save
-> ioctl with 
F2FS_IOC_MOVE_RANGE   A  ->  B

-> mmap
Read the data that offset is same with first time and save

Compare the consistency of the data that read twice.


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 1/2] f2fs: flush pending checkpoints when freezing super

2022-09-12 Thread Chao Yu

On 2022/8/25 4:02, Jaegeuk Kim wrote:

This avoids -EINVAL when trying to freeze f2fs.

Signed-off-by: Jaegeuk Kim 


Reviewed-by: Chao Yu 

Thanks,


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 2/2 v2] f2fs: complete checkpoints during remount

2022-09-12 Thread Chao Yu

On 2022/8/25 4:30, Jaegeuk Kim wrote:

Otherwise, pending checkpoints can contribute a race condition to give a
quota warning.

- Thread  - checkpoint thread
   add checkpoints to the list
do_remount()
  down_write(>s_umount);
  f2fs_remount()
   block_operations()
down_read_trylock(>s_umount) = 0
  up_write(>s_umount);
f2fs_quota_sync()
 dquot_writeback_dquots()
  WARN_ON_ONCE(!rwsem_is_locked(>s_umount));

Or,

do_remount()
  down_write(>s_umount);
  f2fs_remount()
   create a ckpt thread
   f2fs_enable_checkpoint() adds checkpoints
  wait for f2fs_sync_fs()
   trigger another pending checkpoint
block_operations()
 down_read_trylock(>s_umount) = 0
  up_write(>s_umount);
 f2fs_quota_sync()
  dquot_writeback_dquots()
   
WARN_ON_ONCE(!rwsem_is_locked(>s_umount));

Signed-off-by: Jaegeuk Kim 


Reviewed-by: Chao Yu 

Thanks,


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] 答复: [PATCH -next] f2fs: adding truncate page cache after being moved

2022-09-12 Thread zhangqilong via Linux-f2fs-devel
> On 2022/9/13 11:05, Zhang Qilong wrote:
> > If we do not truncate source page cache, user can still see the
> > previous source data after being moved. We fix it by adding truncating
> > after __exchange_data_block.
> >
> > Fixes:4dd6f977fc778 ("f2fs: support an ioctl to move a range of data
> > blocks")
> > Signed-off-by: Zhang Qilong 
> > ---
> >   fs/f2fs/file.c | 4 
> >   1 file changed, 4 insertions(+)
> >
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index
> > 771f1f7f3690..e3ff648aa496 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -2789,6 +2789,10 @@ static int f2fs_move_file_range(struct file
> *file_in, loff_t pos_in,
> > }
> > f2fs_unlock_op(sbi);
> >
> > +   filemap_invalidate_lock(src->i_mapping);
> 
> invalidate lock should cover __exchange_data_block()?
> 
> > +   truncate_pagecache_range(src, pos_in, pos_in + len - 1);
> 
> truncate_pagecache_range() should be called before
> __exchange_data_block()?

I have tried it, but it do not work. So I move the truncate operation to the 
back of
__exchange_data_block that it works well. I don't know much enough, what do you
think of this issue.

Thanks,

> 
> Thanks,
> 
> > +   filemap_invalidate_unlock(src->i_mapping);
> > +
> > if (src != dst)
> > f2fs_up_write(_I(dst)->i_gc_rwsem[WRITE]);
> >   out_src:

___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] 答复: [PATCH -next] f2fs: adding truncate page cache after being moved

2022-09-12 Thread Chao Yu

On 2022/9/13 11:41, zhangqilong wrote:

On 2022/9/13 11:05, Zhang Qilong wrote:

If we do not truncate source page cache, user can still see the
previous source data after being moved. We fix it by adding truncating
after __exchange_data_block.

Fixes:4dd6f977fc778 ("f2fs: support an ioctl to move a range of data
blocks")
Signed-off-by: Zhang Qilong 
---
   fs/f2fs/file.c | 4 
   1 file changed, 4 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index
771f1f7f3690..e3ff648aa496 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2789,6 +2789,10 @@ static int f2fs_move_file_range(struct file

*file_in, loff_t pos_in,

}
f2fs_unlock_op(sbi);

+   filemap_invalidate_lock(src->i_mapping);


invalidate lock should cover __exchange_data_block()?


+   truncate_pagecache_range(src, pos_in, pos_in + len - 1);


truncate_pagecache_range() should be called before
__exchange_data_block()?


I have tried it, but it do not work. So I move the truncate operation to the 
back of
__exchange_data_block that it works well. I don't know much enough, what do you
think of this issue.


Can you describe details about the testcase?

Thanks,



Thanks,



Thanks,


+   filemap_invalidate_unlock(src->i_mapping);
+
if (src != dst)
f2fs_up_write(_I(dst)->i_gc_rwsem[WRITE]);
   out_src:



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH v2] f2fs: fix to disallow getting inner inode via f2fs_iget()

2022-09-12 Thread Jaegeuk Kim
On 09/13, Chao Yu wrote:
> On 2022/9/12 23:39, Jaegeuk Kim wrote:
> > On 09/08, Chao Yu wrote:
> > > On 2022/9/8 10:19, Jaegeuk Kim wrote:
> > > > On 09/08, Chao Yu wrote:
> > > > > On 2022/9/8 10:02, Jaegeuk Kim wrote:
> > > > > > On 08/31, Chao Yu wrote:
> > > > > > > From: Chao Yu 
> > > > > > > 
> > > > > > > Introduce f2fs_iget_inner() for f2fs_fill_super() to get inner 
> > > > > > > inode:
> > > > > > > meta inode, node inode or compressed inode, and add 
> > > > > > > f2fs_check_nid_range()
> > > > > > > in f2fs_iget() to avoid getting inner inode from external 
> > > > > > > interfaces.
> > > > > > 
> > > > > > So, we don't want to check the range of inner inode numbers? What'd 
> > > > > > be the
> > > > > > way to check it's okay?
> > > > > 
> > > > > For node_ino, meta_ino, root_ino, we have checked them in 
> > > > > sanity_check_raw_super()
> > > > > as below:
> > > > > 
> > > > >   /* check reserved ino info */
> > > > >   if (le32_to_cpu(raw_super->node_ino) != 1 ||
> > > > >   le32_to_cpu(raw_super->meta_ino) != 2 ||
> > > > >   le32_to_cpu(raw_super->root_ino) != 3) {
> > > > >   f2fs_info(sbi, "Invalid Fs Meta Ino: node(%u) meta(%u) 
> > > > > root(%u)",
> > > > > le32_to_cpu(raw_super->node_ino),
> > > > > le32_to_cpu(raw_super->meta_ino),
> > > > > le32_to_cpu(raw_super->root_ino));
> > > > >   return -EFSCORRUPTED;
> > > > >   }
> > > > > 
> > > > > compressed_ino should always be NM_I(sbi)->max_nid, it can be checked 
> > > > > in
> > > > > f2fs_init_compress_inode()?
> > > > 
> > > > Hmm, I'm not sure whether we really need this patch, since it'd look 
> > > > better
> > > > to handle all the iget with single f2fs_iget?
> > > 
> > > Well, the main concern is previously f2fs_iget() won't check validation 
> > > for inner
> > > inode due to it will skip do_read_inode() - f2fs_check_nid_range(), so 
> > > that in a
> > > fuzzed image, caller may pass inner ino into f2fs_iget(), result in 
> > > incorrect use
> > > of inner inode. So I add f2fs_check_nid_range() in prior to 
> > > f2fs_iget_inner() in
> > > f2fs_iget() as below to detect and avoid this case.
> > 
> > FWIW, sanity_check_raw_super() checked the inode numbers.
> 
> However, previously, f2fs_iget() will return inner inode to caller directly, 
> if caller
> passes meta_ino, node_ino or compress_ino to f2fs_iget()?

Do you want to do sanity check on corrupted dentry? If so, how about checking
it in f2fs_iget instead?

if (is_meta_ino(ino)) {
if (!(inode->i_state & I_NEW) 
return -EFSCORRUPTED;
goto make_now;
}

> 
> Thanks,
> 
> > 
> > > 
> > > > > > > +struct inode *f2fs_iget(struct super_block *sb, unsigned long 
> > > > > > > ino)
> > > > > > > +{
> > > > > > > + int ret;
> > > > > > > +
> > > > > > > + ret = f2fs_check_nid_range(F2FS_SB(sb), ino);
> > > > > > > + if (ret)
> > > > > > > + return ERR_PTR(ret);
> > > > > > > +
> > > > > > > + return f2fs_iget_inner(sb, ino);


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH -next] f2fs: adding truncate page cache after being moved

2022-09-12 Thread Zhang Qilong via Linux-f2fs-devel
If we do not truncate source page cache, user can still
see the previous source data after being moved. We fix
it by adding truncating after __exchange_data_block.

Fixes:4dd6f977fc778 ("f2fs: support an ioctl to move a range of data blocks")
Signed-off-by: Zhang Qilong 
---
 fs/f2fs/file.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 771f1f7f3690..e3ff648aa496 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2789,6 +2789,10 @@ static int f2fs_move_file_range(struct file *file_in, 
loff_t pos_in,
}
f2fs_unlock_op(sbi);
 
+   filemap_invalidate_lock(src->i_mapping);
+   truncate_pagecache_range(src, pos_in, pos_in + len - 1);
+   filemap_invalidate_unlock(src->i_mapping);
+
if (src != dst)
f2fs_up_write(_I(dst)->i_gc_rwsem[WRITE]);
 out_src:
-- 
2.25.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH] f2fs: increase the limit for reserve_root

2022-09-12 Thread Chao Yu

On 2022/8/24 1:21, Jaegeuk Kim wrote:

This patch increases the threshold that limits the reserved root space from 0.2%
to 12.5% by using simple shift operation.

Typically Android sets 128MB, but if the storage capacity is 32GB, 0.2% which is
around 64MB becomes too small. Let's relax it.

Signed-off-by: Jaegeuk Kim 


Reviewed-by: Chao Yu 

Thanks,


___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH] f2fs: fix to detect obsolete inner inode during fill_super()

2022-09-12 Thread Chao Yu

On 2022/9/12 23:37, Jaegeuk Kim wrote:

On 09/08, Chao Yu wrote:

Sometimes we can get a cached meta_inode which has no aops yet. Let's set it
all the time to fix the below panic.

Unable to handle kernel NULL pointer dereference at virtual address 

Mem abort info:
   ESR = 0x8604
   EC = 0x21: IABT (current EL), IL = 32 bits
   SET = 0, FnV = 0
   EA = 0, S1PTW = 0
   FSC = 0x04: level 0 translation fault
user pgtable: 4k pages, 48-bit VAs, pgdp=000109ee4000
[] pgd=, p4d=
Internal error: Oops: 8604 [#1] PREEMPT SMP
Modules linked in:
CPU: 1 PID: 3045 Comm: syz-executor330 Not tainted 
6.0.0-rc2-syzkaller-16455-ga41a877bc12d #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
07/22/2022
pstate: 8045 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : 0x0
lr : folio_mark_dirty+0xbc/0x208 mm/page-writeback.c:2748
sp : 800012783970
x29: 800012783970 x28:  x27: 800012783b08
x26: 0001 x25: 0400 x24: 0001
x23: c736e000 x22: 0045 x21: 05ffc015
x20: ca7403b8 x19: fc00032ec600 x18: 0181
x17: 8c04d6bc x16: 8dbb8658 x15: 
x14:  x13:  x12: 
x11: ff80883e9814 x10:  x9 : 883e9814
x8 :  x7 :  x6 : 
x5 : cbb19000 x4 : cb3d2000 x3 : cbb18f80
x2 : fff0 x1 : fc00032ec600 x0 : ca7403b8
Call trace:
  0x0
  set_page_dirty+0x38/0xbc mm/folio-compat.c:62
  f2fs_update_meta_page+0x80/0xa8 fs/f2fs/segment.c:2369
  do_checkpoint+0x794/0xea8 fs/f2fs/checkpoint.c:1522
  f2fs_write_checkpoint+0x3b8/0x568 fs/f2fs/checkpoint.c:1679

The root cause is, quoted from Jaegeuk:

It turned out there is a bug in reiserfs which doesn't free the root
inode (ino=2). That leads f2fs to find an ino=2 with the previous
superblock point used by reiserfs. That stale inode has no valid
mapping that f2fs can use, result in kernel panic.

This patch adds sanity check in f2fs_iget() to avoid finding stale
inode during inner inode initialization.

Cc: sta...@vger.kernel.org
Reported-by: syzbot+775a3440817f74fdd...@syzkaller.appspotmail.com
Signed-off-by: Jaegeuk Kim 
Signed-off-by: Chao Yu 
---
  fs/f2fs/inode.c | 11 +++
  1 file changed, 11 insertions(+)

diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index ccb29034af59..df1a82fbfaf2 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -493,6 +493,17 @@ struct inode *f2fs_iget_inner(struct super_block *sb, 
unsigned long ino)
struct inode *inode;
int ret = 0;
  
+	if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi) ||

+   ino == F2FS_COMPRESS_INO(sbi)) {
+   inode = ilookup(sb, ino);
+   if (inode) {
+   iput(inode);
+   f2fs_err(sbi, "there is obsoleted inner inode %lu cached in 
hash table",
+   ino);
+   return ERR_PTR(-EFSCORRUPTED);


Well, this does not indicate f2fs is corrupted. I'd rather expect to fix
reiserfs instead of f2fs workaround which hides the bug.


Well, is there a fixing patch for reiserfs? If not, how about applying this
patch first, later, we can revert it after reiserfs has been fixed.

Thanks,




+   }
+   }
+
inode = iget_locked(sb, ino);
if (!inode)
return ERR_PTR(-ENOMEM);
--
2.25.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel