From: Andrew Morton <akpm@linux-foundation.org>
To: willy@infradead.org,sunhao.th@gmail.com,david@redhat.com,konishi.ryusuke@gmail.com,akpm@linux-foundation.org,patches@lists.linux.dev,linux-mm@kvack.org,mm-commits@vger.kernel.org,torvalds@linux-foundation.org,akpm@linux-foundation.org
Subject: [patch 04/16] nilfs2: fix lockdep warnings during disk space reclamation
Date: Fri, 01 Apr 2022 11:28:21 -0700 [thread overview]
Message-ID: <20220401182822.4D6A2C2BBE4@smtp.kernel.org> (raw)
In-Reply-To: <20220401112740.351496714b370467a92207a6@linux-foundation.org>
From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Subject: nilfs2: fix lockdep warnings during disk space reclamation
During disk space reclamation, nilfs2 still emits the following lockdep
warning due to page/folio operations on shadowed page caches that nilfs2
uses to get a snapshot of DAT file in memory:
WARNING: CPU: 0 PID: 2643 at include/linux/backing-dev.h:272 __folio_mark_dirty+0x645/0x670
...
RIP: 0010:__folio_mark_dirty+0x645/0x670
...
Call Trace:
<TASK>
filemap_dirty_folio+0x74/0xd0
__set_page_dirty_nobuffers+0x85/0xb0
nilfs_copy_dirty_pages+0x288/0x510 [nilfs2]
nilfs_mdt_save_to_shadow_map+0x50/0xe0 [nilfs2]
nilfs_clean_segments+0xee/0x5d0 [nilfs2]
nilfs_ioctl_clean_segments.isra.19+0xb08/0xf40 [nilfs2]
nilfs_ioctl+0xc52/0xfb0 [nilfs2]
__x64_sys_ioctl+0x11d/0x170
do_syscall_64+0x3a/0x80
entry_SYSCALL_64_after_hwframe+0x44/0xae
This fixes the remaining warning by using inode objects to hold those
page caches.
Link: https://lkml.kernel.org/r/1647867427-30498-3-git-send-email-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Hao Sun <sunhao.th@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
fs/nilfs2/dat.c | 4 ++
fs/nilfs2/inode.c | 63 +++++++++++++++++++++++++++++++++++++++++---
fs/nilfs2/mdt.c | 38 ++++++++++++++++++--------
fs/nilfs2/mdt.h | 6 +---
fs/nilfs2/nilfs.h | 2 +
5 files changed, 92 insertions(+), 21 deletions(-)
--- a/fs/nilfs2/dat.c~nilfs2-fix-lockdep-warnings-during-disk-space-reclamation
+++ a/fs/nilfs2/dat.c
@@ -497,7 +497,9 @@ int nilfs_dat_read(struct super_block *s
di = NILFS_DAT_I(dat);
lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
nilfs_palloc_setup_cache(dat, &di->palloc_cache);
- nilfs_mdt_setup_shadow_map(dat, &di->shadow);
+ err = nilfs_mdt_setup_shadow_map(dat, &di->shadow);
+ if (err)
+ goto failed;
err = nilfs_read_inode_common(dat, raw_inode);
if (err)
--- a/fs/nilfs2/inode.c~nilfs2-fix-lockdep-warnings-during-disk-space-reclamation
+++ a/fs/nilfs2/inode.c
@@ -30,6 +30,7 @@
* @root: pointer on NILFS root object (mounted checkpoint)
* @for_gc: inode for GC flag
* @for_btnc: inode for B-tree node cache flag
+ * @for_shadow: inode for shadowed page cache flag
*/
struct nilfs_iget_args {
u64 ino;
@@ -37,6 +38,7 @@ struct nilfs_iget_args {
struct nilfs_root *root;
bool for_gc;
bool for_btnc;
+ bool for_shadow;
};
static int nilfs_iget_test(struct inode *inode, void *opaque);
@@ -315,7 +317,7 @@ static int nilfs_insert_inode_locked(str
{
struct nilfs_iget_args args = {
.ino = ino, .root = root, .cno = 0, .for_gc = false,
- .for_btnc = false
+ .for_btnc = false, .for_shadow = false
};
return insert_inode_locked4(inode, ino, nilfs_iget_test, &args);
@@ -534,6 +536,12 @@ static int nilfs_iget_test(struct inode
} else if (args->for_btnc) {
return 0;
}
+ if (test_bit(NILFS_I_SHADOW, &ii->i_state)) {
+ if (!args->for_shadow)
+ return 0;
+ } else if (args->for_shadow) {
+ return 0;
+ }
if (!test_bit(NILFS_I_GCINODE, &ii->i_state))
return !args->for_gc;
@@ -555,6 +563,8 @@ static int nilfs_iget_set(struct inode *
NILFS_I(inode)->i_state = BIT(NILFS_I_GCINODE);
if (args->for_btnc)
NILFS_I(inode)->i_state |= BIT(NILFS_I_BTNC);
+ if (args->for_shadow)
+ NILFS_I(inode)->i_state |= BIT(NILFS_I_SHADOW);
return 0;
}
@@ -563,7 +573,7 @@ struct inode *nilfs_ilookup(struct super
{
struct nilfs_iget_args args = {
.ino = ino, .root = root, .cno = 0, .for_gc = false,
- .for_btnc = false
+ .for_btnc = false, .for_shadow = false
};
return ilookup5(sb, ino, nilfs_iget_test, &args);
@@ -574,7 +584,7 @@ struct inode *nilfs_iget_locked(struct s
{
struct nilfs_iget_args args = {
.ino = ino, .root = root, .cno = 0, .for_gc = false,
- .for_btnc = false
+ .for_btnc = false, .for_shadow = false
};
return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
@@ -606,7 +616,7 @@ struct inode *nilfs_iget_for_gc(struct s
{
struct nilfs_iget_args args = {
.ino = ino, .root = NULL, .cno = cno, .for_gc = true,
- .for_btnc = false
+ .for_btnc = false, .for_shadow = false
};
struct inode *inode;
int err;
@@ -653,6 +663,7 @@ int nilfs_attach_btree_node_cache(struct
args.cno = ii->i_cno;
args.for_gc = test_bit(NILFS_I_GCINODE, &ii->i_state) != 0;
args.for_btnc = true;
+ args.for_shadow = test_bit(NILFS_I_SHADOW, &ii->i_state) != 0;
btnc_inode = iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test,
nilfs_iget_set, &args);
@@ -688,6 +699,50 @@ void nilfs_detach_btree_node_cache(struc
}
}
+/**
+ * nilfs_iget_for_shadow - obtain inode for shadow mapping
+ * @inode: inode object that uses shadow mapping
+ *
+ * nilfs_iget_for_shadow() allocates a pair of inodes that holds page
+ * caches for shadow mapping. The page cache for data pages is set up
+ * in one inode and the one for b-tree node pages is set up in the
+ * other inode, which is attached to the former inode.
+ *
+ * Return Value: On success, a pointer to the inode for data pages is
+ * returned. On errors, one of the following negative error code is returned
+ * in a pointer type.
+ *
+ * %-ENOMEM - Insufficient memory available.
+ */
+struct inode *nilfs_iget_for_shadow(struct inode *inode)
+{
+ struct nilfs_iget_args args = {
+ .ino = inode->i_ino, .root = NULL, .cno = 0, .for_gc = false,
+ .for_btnc = false, .for_shadow = true
+ };
+ struct inode *s_inode;
+ int err;
+
+ s_inode = iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test,
+ nilfs_iget_set, &args);
+ if (unlikely(!s_inode))
+ return ERR_PTR(-ENOMEM);
+ if (!(s_inode->i_state & I_NEW))
+ return inode;
+
+ NILFS_I(s_inode)->i_flags = 0;
+ memset(NILFS_I(s_inode)->i_bmap, 0, sizeof(struct nilfs_bmap));
+ mapping_set_gfp_mask(s_inode->i_mapping, GFP_NOFS);
+
+ err = nilfs_attach_btree_node_cache(s_inode);
+ if (unlikely(err)) {
+ iget_failed(s_inode);
+ return ERR_PTR(err);
+ }
+ unlock_new_inode(s_inode);
+ return s_inode;
+}
+
void nilfs_write_inode_common(struct inode *inode,
struct nilfs_inode *raw_inode, int has_bmap)
{
--- a/fs/nilfs2/mdt.c~nilfs2-fix-lockdep-warnings-during-disk-space-reclamation
+++ a/fs/nilfs2/mdt.c
@@ -471,9 +471,18 @@ int nilfs_mdt_init(struct inode *inode,
void nilfs_mdt_clear(struct inode *inode)
{
struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
+ struct nilfs_shadow_map *shadow = mdi->mi_shadow;
if (mdi->mi_palloc_cache)
nilfs_palloc_destroy_cache(inode);
+
+ if (shadow) {
+ struct inode *s_inode = shadow->inode;
+
+ shadow->inode = NULL;
+ iput(s_inode);
+ mdi->mi_shadow = NULL;
+ }
}
/**
@@ -507,12 +516,15 @@ int nilfs_mdt_setup_shadow_map(struct in
struct nilfs_shadow_map *shadow)
{
struct nilfs_mdt_info *mi = NILFS_MDT(inode);
+ struct inode *s_inode;
INIT_LIST_HEAD(&shadow->frozen_buffers);
- address_space_init_once(&shadow->frozen_data);
- nilfs_mapping_init(&shadow->frozen_data, inode);
- address_space_init_once(&shadow->frozen_btnodes);
- nilfs_mapping_init(&shadow->frozen_btnodes, inode);
+
+ s_inode = nilfs_iget_for_shadow(inode);
+ if (IS_ERR(s_inode))
+ return PTR_ERR(s_inode);
+
+ shadow->inode = s_inode;
mi->mi_shadow = shadow;
return 0;
}
@@ -526,13 +538,14 @@ int nilfs_mdt_save_to_shadow_map(struct
struct nilfs_mdt_info *mi = NILFS_MDT(inode);
struct nilfs_inode_info *ii = NILFS_I(inode);
struct nilfs_shadow_map *shadow = mi->mi_shadow;
+ struct inode *s_inode = shadow->inode;
int ret;
- ret = nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping);
+ ret = nilfs_copy_dirty_pages(s_inode->i_mapping, inode->i_mapping);
if (ret)
goto out;
- ret = nilfs_copy_dirty_pages(&shadow->frozen_btnodes,
+ ret = nilfs_copy_dirty_pages(NILFS_I(s_inode)->i_assoc_inode->i_mapping,
ii->i_assoc_inode->i_mapping);
if (ret)
goto out;
@@ -549,7 +562,7 @@ int nilfs_mdt_freeze_buffer(struct inode
struct page *page;
int blkbits = inode->i_blkbits;
- page = grab_cache_page(&shadow->frozen_data, bh->b_page->index);
+ page = grab_cache_page(shadow->inode->i_mapping, bh->b_page->index);
if (!page)
return -ENOMEM;
@@ -581,7 +594,7 @@ nilfs_mdt_get_frozen_buffer(struct inode
struct page *page;
int n;
- page = find_lock_page(&shadow->frozen_data, bh->b_page->index);
+ page = find_lock_page(shadow->inode->i_mapping, bh->b_page->index);
if (page) {
if (page_has_buffers(page)) {
n = bh_offset(bh) >> inode->i_blkbits;
@@ -622,11 +635,11 @@ void nilfs_mdt_restore_from_shadow_map(s
nilfs_palloc_clear_cache(inode);
nilfs_clear_dirty_pages(inode->i_mapping, true);
- nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data);
+ nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping);
nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping, true);
nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping,
- &shadow->frozen_btnodes);
+ NILFS_I(shadow->inode)->i_assoc_inode->i_mapping);
nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store);
@@ -641,10 +654,11 @@ void nilfs_mdt_clear_shadow_map(struct i
{
struct nilfs_mdt_info *mi = NILFS_MDT(inode);
struct nilfs_shadow_map *shadow = mi->mi_shadow;
+ struct inode *shadow_btnc_inode = NILFS_I(shadow->inode)->i_assoc_inode;
down_write(&mi->mi_sem);
nilfs_release_frozen_buffers(shadow);
- truncate_inode_pages(&shadow->frozen_data, 0);
- truncate_inode_pages(&shadow->frozen_btnodes, 0);
+ truncate_inode_pages(shadow->inode->i_mapping, 0);
+ truncate_inode_pages(shadow_btnc_inode->i_mapping, 0);
up_write(&mi->mi_sem);
}
--- a/fs/nilfs2/mdt.h~nilfs2-fix-lockdep-warnings-during-disk-space-reclamation
+++ a/fs/nilfs2/mdt.h
@@ -18,14 +18,12 @@
/**
* struct nilfs_shadow_map - shadow mapping of meta data file
* @bmap_store: shadow copy of bmap state
- * @frozen_data: shadowed dirty data pages
- * @frozen_btnodes: shadowed dirty b-tree nodes' pages
+ * @inode: holder of page caches used in shadow mapping
* @frozen_buffers: list of frozen buffers
*/
struct nilfs_shadow_map {
struct nilfs_bmap_store bmap_store;
- struct address_space frozen_data;
- struct address_space frozen_btnodes;
+ struct inode *inode;
struct list_head frozen_buffers;
};
--- a/fs/nilfs2/nilfs.h~nilfs2-fix-lockdep-warnings-during-disk-space-reclamation
+++ a/fs/nilfs2/nilfs.h
@@ -92,6 +92,7 @@ enum {
NILFS_I_BMAP, /* has bmap and btnode_cache */
NILFS_I_GCINODE, /* inode for GC, on memory only */
NILFS_I_BTNC, /* inode for btree node cache */
+ NILFS_I_SHADOW, /* inode for shadowed page cache */
};
/*
@@ -263,6 +264,7 @@ extern struct inode *nilfs_iget_for_gc(s
unsigned long ino, __u64 cno);
int nilfs_attach_btree_node_cache(struct inode *inode);
void nilfs_detach_btree_node_cache(struct inode *inode);
+struct inode *nilfs_iget_for_shadow(struct inode *inode);
extern void nilfs_update_inode(struct inode *, struct buffer_head *, int);
extern void nilfs_truncate(struct inode *);
extern void nilfs_evict_inode(struct inode *);
_
next prev parent reply other threads:[~2022-04-01 18:32 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-01 18:27 incoming Andrew Morton
2022-04-01 18:28 ` [patch 01/16] Revert "mm: madvise: skip unmapped vma holes passed to process_madvise" Andrew Morton
2022-04-01 18:28 ` [patch 02/16] ocfs2: fix crash when mount with quota enabled Andrew Morton
2022-04-01 18:28 ` [patch 03/16] nilfs2: fix lockdep warnings in page operations for btree nodes Andrew Morton
2022-04-01 18:28 ` Andrew Morton [this message]
2022-04-01 18:28 ` [patch 05/16] nilfs2: get rid of nilfs_mapping_init() Andrew Morton
2022-04-01 18:28 ` [patch 06/16] mm/munlock: add lru_add_drain() to fix memcg_stat_test Andrew Morton
2022-04-01 18:28 ` [patch 07/16] mm/munlock: update Documentation/vm/unevictable-lru.rst Andrew Morton
2022-04-01 18:28 ` [patch 08/16] mm/munlock: protect the per-CPU pagevec by a local_lock_t Andrew Morton
2022-04-01 18:28 ` [patch 09/16] mm: kfence: fix objcgs vector allocation Andrew Morton
2022-04-01 18:28 ` [patch 10/16] mailmap: update Kirill's email Andrew Morton
2022-04-01 18:28 ` [patch 11/16] mm,hwpoison: unmap poisoned page before invalidation Andrew Morton
2022-04-01 18:28 ` [patch 12/16] mm, kasan: fix __GFP_BITS_SHIFT definition breaking LOCKDEP Andrew Morton
2022-04-01 18:28 ` [patch 13/16] tools/vm/page_owner_sort.c: remove -c option Andrew Morton
2022-04-01 18:28 ` [patch 14/16] doc/vm/page_owner.rst: remove content related to " Andrew Morton
2022-04-01 18:28 ` [patch 15/16] mm/kmemleak: reset tag when compare object pointer Andrew Morton
2022-04-01 18:28 ` [patch 16/16] mm/damon: prevent activated scheme from sleeping by deactivated schemes Andrew Morton
[not found] <l>
2022-04-01 18:21 ` [patch 04/16] nilfs2: fix lockdep warnings during disk space reclamation Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220401182822.4D6A2C2BBE4@smtp.kernel.org \
--to=akpm@linux-foundation.org \
--cc=david@redhat.com \
--cc=konishi.ryusuke@gmail.com \
--cc=linux-mm@kvack.org \
--cc=mm-commits@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=sunhao.th@gmail.com \
--cc=torvalds@linux-foundation.org \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).