From nobody Mon Jun 22 15:43:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48AFEC433EF for ; Mon, 21 Mar 2022 12:57:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347664AbiCUM6r (ORCPT ); Mon, 21 Mar 2022 08:58:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234755AbiCUM6m (ORCPT ); Mon, 21 Mar 2022 08:58:42 -0400 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01C2316BCD3; Mon, 21 Mar 2022 05:57:15 -0700 (PDT) Received: by mail-pg1-x532.google.com with SMTP id q19so10236241pgm.6; Mon, 21 Mar 2022 05:57:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SYe3vWXD+xIWU6PTjwthOrKekOMXUBPJFMRy3ElR/I0=; b=SVo7+zFUqDrNeId0pBxN9nIvZIuanA34beTKVwPXNLjv46t509ouPOyBNA8K9e5DO7 aB9yT+XiFbwb3qwHja+yC3qVtX0PyOmukIEkmEpsC3h8ZXc47Ad92o7ABFoI3/DP2D7s KC330AlPZJNwL7ryUsldLri7ZuflP07tgZfNo++XMz1tLe+a5bVVWF36wp2Sgc4gSyn5 0V/5++JzK93Db2b/i4MUYU80fJpPotgqfTa/32PkdN9oHJe17XtVXmhsvX0kNPxn9kb8 23BxgKyYGb3EASi+F963aQoyPQhtMbo603T3Yd9t1+aSYjEHYbUU79akXhRSqPBaEuk1 ZOHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SYe3vWXD+xIWU6PTjwthOrKekOMXUBPJFMRy3ElR/I0=; b=SQd7YwG7d653fvmJNNgw2nrfpXnDLDsmzwd3gHb+EN+NrrEuGBUbXcFs8XBPx/rY6p Ta80DSZdDMndiWH8FLNfyu8n9tUiojUMWcUwS/5SNXw/EJqBEQbr53ATt0p23u4hXlmq uNmVzq+PcTMtA9OD/uJyVuRXuXc1ab3y6HHKhleJlN3LNbH2axVJDQXCTtS4AfkB15oo yvHJ5/gQmmMzVH91VQASysEB5bBEbKAIGOM8PBQZbjJDGMGNteTUXxCYYnNb/8lSQDhX wwCMCHqmdrT64EVwWqhL++YFIFU7QgsHjLNCrVal62SB14IrXnMBXn1sGzsxZPz3vj4J jtfA== X-Gm-Message-State: AOAM531m0Y2DydzQoOwBNsjqAw2X3CIc1r+YCYQdm5o7Ku239+qXVtaE ksenvZkclQTW8PVLQMJzOd4= X-Google-Smtp-Source: ABdhPJzomCnfFzB4sdEnQGlgkHF4iaPfvgT92a4GpvIjN/6ucv0P3iHeD0si2NXAAnNVzzrf49SKkQ== X-Received: by 2002:a05:6a00:1381:b0:4fa:81ed:89a0 with SMTP id t1-20020a056a00138100b004fa81ed89a0mr10930191pfg.85.1647867435051; Mon, 21 Mar 2022 05:57:15 -0700 (PDT) Received: from carrot.localdomain (i114-180-38-233.s42.a014.ap.plala.or.jp. [114.180.38.233]) by smtp.gmail.com with ESMTPSA id gb5-20020a17090b060500b001c6d46f7e75sm8009046pjb.30.2022.03.21.05.57.12 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Mar 2022 05:57:13 -0700 (PDT) From: Ryusuke Konishi To: Andrew Morton Cc: linux-nilfs , Matthew Wilcox , David Hildenbrand , LKML , "linux-mm@kvack.org" Subject: [PATCH 1/3] nilfs2: fix lockdep warnings in page operations for btree nodes Date: Mon, 21 Mar 2022 21:57:05 +0900 Message-Id: <1647867427-30498-2-git-send-email-konishi.ryusuke@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1647867427-30498-1-git-send-email-konishi.ryusuke@gmail.com> References: <1647867427-30498-1-git-send-email-konishi.ryusuke@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" If CONFIG_LOCKDEP is enabled, nilfs2 hits lockdep warnings at inode_to_wb() during page/folio operations for btree nodes: WARNING: CPU: 0 PID: 6575 at include/linux/backing-dev.h:269 inode_to_wb i= nclude/linux/backing-dev.h:269 [inline] WARNING: CPU: 0 PID: 6575 at include/linux/backing-dev.h:269 folio_account= _dirtied mm/page-writeback.c:2460 [inline] WARNING: CPU: 0 PID: 6575 at include/linux/backing-dev.h:269 __folio_mark_= dirty+0xa7c/0xe30 mm/page-writeback.c:2509 Modules linked in: ... RIP: 0010:inode_to_wb include/linux/backing-dev.h:269 [inline] RIP: 0010:folio_account_dirtied mm/page-writeback.c:2460 [inline] RIP: 0010:__folio_mark_dirty+0xa7c/0xe30 mm/page-writeback.c:2509 ... Call Trace: __set_page_dirty include/linux/pagemap.h:834 [inline] mark_buffer_dirty+0x4e6/0x650 fs/buffer.c:1145 nilfs_btree_propagate_p fs/nilfs2/btree.c:1889 [inline] nilfs_btree_propagate+0x4ae/0xea0 fs/nilfs2/btree.c:2085 nilfs_bmap_propagate+0x73/0x170 fs/nilfs2/bmap.c:337 nilfs_collect_dat_data+0x45/0xd0 fs/nilfs2/segment.c:625 nilfs_segctor_apply_buffers+0x14a/0x470 fs/nilfs2/segment.c:1009 nilfs_segctor_scan_file+0x47a/0x700 fs/nilfs2/segment.c:1048 nilfs_segctor_collect_blocks fs/nilfs2/segment.c:1224 [inline] nilfs_segctor_collect fs/nilfs2/segment.c:1494 [inline] nilfs_segctor_do_construct+0x14f3/0x6c60 fs/nilfs2/segment.c:2036 nilfs_segctor_construct+0x7a7/0xb30 fs/nilfs2/segment.c:2372 nilfs_segctor_thread_construct fs/nilfs2/segment.c:2480 [inline] nilfs_segctor_thread+0x3c3/0xf90 fs/nilfs2/segment.c:2563 kthread+0x405/0x4f0 kernel/kthread.c:327 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295 This is because nilfs2 uses two page caches for each inode and inode->i_mapping never points to one of them, the btree node cache. This causes inode_to_wb(inode) to refer to a different page cache than the caller page/folio operations such like __folio_start_writeback(), __folio_end_writeback(), or __folio_mark_dirty() acquired the lock. This patch resolves the issue by allocating and using an additional inode to hold the page cache of btree nodes. The inode is attached one-to-one to the traditional nilfs2 inode if it requires a block mapping with b-tree. This setup change is in memory only and does not affect the disk format. Reported-by: syzbot+0d5b462a6f07447991b3@syzkaller.appspotmail.com Reported-by: syzbot+34ef28bb2aeb28724aa0@syzkaller.appspotmail.com Reported-by: Hao Sun Reported-by: David Hildenbrand Link: https://lore.kernel.org/r/YXrYvIo8YRnAOJCj@casper.infradead.org Link: https://lore.kernel.org/r/9a20b33d-b38f-b4a2-4742-c1eb5b8e4d6c@redhat= .com Signed-off-by: Ryusuke Konishi Tested-by: Ryusuke Konishi Cc: Matthew Wilcox --- fs/nilfs2/btnode.c | 23 ++++++++++-- fs/nilfs2/btnode.h | 1 + fs/nilfs2/btree.c | 27 ++++++++++---- fs/nilfs2/gcinode.c | 7 ++-- fs/nilfs2/inode.c | 104 +++++++++++++++++++++++++++++++++++++++++++++---= ---- fs/nilfs2/mdt.c | 7 ++-- fs/nilfs2/nilfs.h | 14 +++---- fs/nilfs2/page.c | 7 ++-- fs/nilfs2/segment.c | 9 +++-- fs/nilfs2/super.c | 5 +-- 10 files changed, 154 insertions(+), 50 deletions(-) diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 66bdaa2cf496..ca611ac09f7c 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c @@ -20,6 +20,23 @@ #include "page.h" #include "btnode.h" =20 + +/** + * nilfs_init_btnc_inode - initialize B-tree node cache inode + * @btnc_inode: inode to be initialized + * + * nilfs_init_btnc_inode() sets up an inode for B-tree node cache. + */ +void nilfs_init_btnc_inode(struct inode *btnc_inode) +{ + struct nilfs_inode_info *ii =3D NILFS_I(btnc_inode); + + btnc_inode->i_mode =3D S_IFREG; + ii->i_flags =3D 0; + memset(&ii->i_bmap_data, 0, sizeof(struct nilfs_bmap)); + mapping_set_gfp_mask(btnc_inode->i_mapping, GFP_NOFS); +} + void nilfs_btnode_cache_clear(struct address_space *btnc) { invalidate_mapping_pages(btnc, 0, -1); @@ -29,7 +46,7 @@ void nilfs_btnode_cache_clear(struct address_space *btnc) struct buffer_head * nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr) { - struct inode *inode =3D NILFS_BTNC_I(btnc); + struct inode *inode =3D btnc->host; struct buffer_head *bh; =20 bh =3D nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node)); @@ -57,7 +74,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc,= __u64 blocknr, struct buffer_head **pbh, sector_t *submit_ptr) { struct buffer_head *bh; - struct inode *inode =3D NILFS_BTNC_I(btnc); + struct inode *inode =3D btnc->host; struct page *page; int err; =20 @@ -157,7 +174,7 @@ int nilfs_btnode_prepare_change_key(struct address_spac= e *btnc, struct nilfs_btnode_chkey_ctxt *ctxt) { struct buffer_head *obh, *nbh; - struct inode *inode =3D NILFS_BTNC_I(btnc); + struct inode *inode =3D btnc->host; __u64 oldkey =3D ctxt->oldkey, newkey =3D ctxt->newkey; int err; =20 diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 11663650add7..bd5544e63a01 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h @@ -30,6 +30,7 @@ struct nilfs_btnode_chkey_ctxt { struct buffer_head *newbh; }; =20 +void nilfs_init_btnc_inode(struct inode *btnc_inode); void nilfs_btnode_cache_clear(struct address_space *); struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr); diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 3594eabe1419..f544c22fff78 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -58,7 +58,8 @@ static void nilfs_btree_free_path(struct nilfs_btree_path= *path) static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree, __u64 ptr, struct buffer_head **bhp) { - struct address_space *btnc =3D &NILFS_BMAP_I(btree)->i_btnode_cache; + struct inode *btnc_inode =3D NILFS_BMAP_I(btree)->i_assoc_inode; + struct address_space *btnc =3D btnc_inode->i_mapping; struct buffer_head *bh; =20 bh =3D nilfs_btnode_create_block(btnc, ptr); @@ -470,7 +471,8 @@ static int __nilfs_btree_get_block(const struct nilfs_b= map *btree, __u64 ptr, struct buffer_head **bhp, const struct nilfs_btree_readahead_info *ra) { - struct address_space *btnc =3D &NILFS_BMAP_I(btree)->i_btnode_cache; + struct inode *btnc_inode =3D NILFS_BMAP_I(btree)->i_assoc_inode; + struct address_space *btnc =3D btnc_inode->i_mapping; struct buffer_head *bh, *ra_bh; sector_t submit_ptr =3D 0; int ret; @@ -1741,6 +1743,10 @@ static int nilfs_btree_gather_data(struct nilfs_bmap= *btree, dat =3D nilfs_bmap_get_dat(btree); } =20 + ret =3D nilfs_attach_btree_node_cache(&NILFS_BMAP_I(btree)->vfs_inode); + if (ret < 0) + return ret; + ret =3D nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat); if (ret < 0) return ret; @@ -1913,7 +1919,7 @@ static int nilfs_btree_prepare_update_v(struct nilfs_= bmap *btree, path[level].bp_ctxt.newkey =3D path[level].bp_newreq.bpr_ptr; path[level].bp_ctxt.bh =3D path[level].bp_bh; ret =3D nilfs_btnode_prepare_change_key( - &NILFS_BMAP_I(btree)->i_btnode_cache, + NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping, &path[level].bp_ctxt); if (ret < 0) { nilfs_dat_abort_update(dat, @@ -1939,7 +1945,7 @@ static void nilfs_btree_commit_update_v(struct nilfs_= bmap *btree, =20 if (buffer_nilfs_node(path[level].bp_bh)) { nilfs_btnode_commit_change_key( - &NILFS_BMAP_I(btree)->i_btnode_cache, + NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping, &path[level].bp_ctxt); path[level].bp_bh =3D path[level].bp_ctxt.bh; } @@ -1958,7 +1964,7 @@ static void nilfs_btree_abort_update_v(struct nilfs_b= map *btree, &path[level].bp_newreq.bpr_req); if (buffer_nilfs_node(path[level].bp_bh)) nilfs_btnode_abort_change_key( - &NILFS_BMAP_I(btree)->i_btnode_cache, + NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping, &path[level].bp_ctxt); } =20 @@ -2134,7 +2140,8 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs= _bmap *btree, static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree, struct list_head *listp) { - struct address_space *btcache =3D &NILFS_BMAP_I(btree)->i_btnode_cache; + struct inode *btnc_inode =3D NILFS_BMAP_I(btree)->i_assoc_inode; + struct address_space *btcache =3D btnc_inode->i_mapping; struct list_head lists[NILFS_BTREE_LEVEL_MAX]; struct pagevec pvec; struct buffer_head *bh, *head; @@ -2188,12 +2195,12 @@ static int nilfs_btree_assign_p(struct nilfs_bmap *= btree, path[level].bp_ctxt.newkey =3D blocknr; path[level].bp_ctxt.bh =3D *bh; ret =3D nilfs_btnode_prepare_change_key( - &NILFS_BMAP_I(btree)->i_btnode_cache, + NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping, &path[level].bp_ctxt); if (ret < 0) return ret; nilfs_btnode_commit_change_key( - &NILFS_BMAP_I(btree)->i_btnode_cache, + NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping, &path[level].bp_ctxt); *bh =3D path[level].bp_ctxt.bh; } @@ -2398,6 +2405,10 @@ int nilfs_btree_init(struct nilfs_bmap *bmap) =20 if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), bmap->b_inode)) ret =3D -EIO; + else + ret =3D nilfs_attach_btree_node_cache( + &NILFS_BMAP_I(bmap)->vfs_inode); + return ret; } =20 diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index a8f5315f01e3..04fdd420eae7 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -126,9 +126,10 @@ int nilfs_gccache_submit_read_data(struct inode *inode= , sector_t blkoff, int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, __u64 vbn, struct buffer_head **out_bh) { + struct inode *btnc_inode =3D NILFS_I(inode)->i_assoc_inode; int ret; =20 - ret =3D nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, + ret =3D nilfs_btnode_submit_block(btnc_inode->i_mapping, vbn ? : pbn, pbn, REQ_OP_READ, 0, out_bh, &pbn); if (ret =3D=3D -EEXIST) /* internal code (cache hit) */ @@ -170,7 +171,7 @@ int nilfs_init_gcinode(struct inode *inode) ii->i_flags =3D 0; nilfs_bmap_init_gc(ii->i_bmap); =20 - return 0; + return nilfs_attach_btree_node_cache(inode); } =20 /** @@ -185,7 +186,7 @@ void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs) ii =3D list_first_entry(head, struct nilfs_inode_info, i_dirty); list_del_init(&ii->i_dirty); truncate_inode_pages(&ii->vfs_inode.i_data, 0); - nilfs_btnode_cache_clear(&ii->i_btnode_cache); + nilfs_btnode_cache_clear(ii->i_assoc_inode->i_mapping); iput(&ii->vfs_inode); } } diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index e3d807d5b83a..56b642159e25 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -29,12 +29,14 @@ * @cno: checkpoint number * @root: pointer on NILFS root object (mounted checkpoint) * @for_gc: inode for GC flag + * @for_btnc: inode for B-tree node cache flag */ struct nilfs_iget_args { u64 ino; __u64 cno; struct nilfs_root *root; - int for_gc; + bool for_gc; + bool for_btnc; }; =20 static int nilfs_iget_test(struct inode *inode, void *opaque); @@ -314,7 +316,8 @@ static int nilfs_insert_inode_locked(struct inode *inod= e, unsigned long ino) { struct nilfs_iget_args args =3D { - .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D 0 + .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D false, + .for_btnc =3D false }; =20 return insert_inode_locked4(inode, ino, nilfs_iget_test, &args); @@ -527,6 +530,13 @@ static int nilfs_iget_test(struct inode *inode, void *= opaque) return 0; =20 ii =3D NILFS_I(inode); + if (test_bit(NILFS_I_BTNC, &ii->i_state)) { + if (!args->for_btnc) + return 0; + } else if (args->for_btnc) { + return 0; + } + if (!test_bit(NILFS_I_GCINODE, &ii->i_state)) return !args->for_gc; =20 @@ -538,15 +548,15 @@ static int nilfs_iget_set(struct inode *inode, void *= opaque) struct nilfs_iget_args *args =3D opaque; =20 inode->i_ino =3D args->ino; - if (args->for_gc) { + NILFS_I(inode)->i_cno =3D args->cno; + NILFS_I(inode)->i_root =3D args->root; + if (args->root && args->ino =3D=3D NILFS_ROOT_INO) + nilfs_get_root(args->root); + + if (args->for_gc) NILFS_I(inode)->i_state =3D BIT(NILFS_I_GCINODE); - NILFS_I(inode)->i_cno =3D args->cno; - NILFS_I(inode)->i_root =3D NULL; - } else { - if (args->root && args->ino =3D=3D NILFS_ROOT_INO) - nilfs_get_root(args->root); - NILFS_I(inode)->i_root =3D args->root; - } + if (args->for_btnc) + NILFS_I(inode)->i_state |=3D BIT(NILFS_I_BTNC); return 0; } =20 @@ -554,7 +564,8 @@ struct inode *nilfs_ilookup(struct super_block *sb, str= uct nilfs_root *root, unsigned long ino) { struct nilfs_iget_args args =3D { - .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D 0 + .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D false, + .for_btnc =3D false }; =20 return ilookup5(sb, ino, nilfs_iget_test, &args); @@ -564,7 +575,8 @@ struct inode *nilfs_iget_locked(struct super_block *sb,= struct nilfs_root *root, unsigned long ino) { struct nilfs_iget_args args =3D { - .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D 0 + .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D false, + .for_btnc =3D false }; =20 return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args); @@ -595,7 +607,8 @@ struct inode *nilfs_iget_for_gc(struct super_block *sb,= unsigned long ino, __u64 cno) { struct nilfs_iget_args args =3D { - .ino =3D ino, .root =3D NULL, .cno =3D cno, .for_gc =3D 1 + .ino =3D ino, .root =3D NULL, .cno =3D cno, .for_gc =3D true, + .for_btnc =3D false }; struct inode *inode; int err; @@ -615,6 +628,68 @@ struct inode *nilfs_iget_for_gc(struct super_block *sb= , unsigned long ino, return inode; } =20 +/** + * nilfs_attach_btree_node_cache - attach a B-tree node cache to the inode + * @inode: inode object + * + * nilfs_attach_btree_node_cache() attaches a B-tree node cache to @inode, + * or does nothing if the inode already has it. This function allocates + * an additional inode to maintain page cache of B-tree nodes one-on-one. + * + * Return Value: On success, 0 is returned. On errors, one of the following + * negative error code is returned. + * + * %-ENOMEM - Insufficient memory available. + */ +int nilfs_attach_btree_node_cache(struct inode *inode) +{ + struct nilfs_inode_info *ii =3D NILFS_I(inode); + struct inode *btnc_inode; + struct nilfs_iget_args args; + + if (ii->i_assoc_inode) + return 0; + + args.ino =3D inode->i_ino; + args.root =3D ii->i_root; + args.cno =3D ii->i_cno; + args.for_gc =3D test_bit(NILFS_I_GCINODE, &ii->i_state) !=3D 0; + args.for_btnc =3D true; + + btnc_inode =3D iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test, + nilfs_iget_set, &args); + if (unlikely(!btnc_inode)) + return -ENOMEM; + if (btnc_inode->i_state & I_NEW) { + nilfs_init_btnc_inode(btnc_inode); + unlock_new_inode(btnc_inode); + } + NILFS_I(btnc_inode)->i_assoc_inode =3D inode; + NILFS_I(btnc_inode)->i_bmap =3D ii->i_bmap; + ii->i_assoc_inode =3D btnc_inode; + + return 0; +} + +/** + * nilfs_detach_btree_node_cache - detach the B-tree node cache from the i= node + * @inode: inode object + * + * nilfs_detach_btree_node_cache() detaches the B-tree node cache and its + * holder inode bound to @inode, or does nothing if @inode doesn't have it. + */ +void nilfs_detach_btree_node_cache(struct inode *inode) +{ + struct nilfs_inode_info *ii =3D NILFS_I(inode); + struct inode *btnc_inode =3D ii->i_assoc_inode; + + if (btnc_inode) { + NILFS_I(btnc_inode)->i_assoc_inode =3D NULL; + ii->i_assoc_inode =3D NULL; + iput(btnc_inode); + } +} + void nilfs_write_inode_common(struct inode *inode, struct nilfs_inode *raw_inode, int has_bmap) { @@ -762,7 +837,8 @@ static void nilfs_clear_inode(struct inode *inode) if (test_bit(NILFS_I_BMAP, &ii->i_state)) nilfs_bmap_clear(ii->i_bmap); =20 - nilfs_btnode_cache_clear(&ii->i_btnode_cache); + if (!test_bit(NILFS_I_BTNC, &ii->i_state)) + nilfs_detach_btree_node_cache(inode); =20 if (ii->i_root && inode->i_ino =3D=3D NILFS_ROOT_INO) nilfs_put_root(ii->i_root); diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 4b3d33cf0041..b26996420401 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -532,7 +532,7 @@ int nilfs_mdt_save_to_shadow_map(struct inode *inode) goto out; =20 ret =3D nilfs_copy_dirty_pages(&shadow->frozen_btnodes, - &ii->i_btnode_cache); + ii->i_assoc_inode->i_mapping); if (ret) goto out; =20 @@ -623,8 +623,9 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *in= ode) nilfs_clear_dirty_pages(inode->i_mapping, true); nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data); =20 - nilfs_clear_dirty_pages(&ii->i_btnode_cache, true); - nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes); + nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping, true); + nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping, + &shadow->frozen_btnodes); =20 nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); =20 diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index a7b81755c350..36b048db00b7 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -28,7 +28,7 @@ * @i_xattr: * @i_dir_start_lookup: page index of last successful search * @i_cno: checkpoint number for GC inode - * @i_btnode_cache: cached pages of b-tree nodes + * @i_assoc_inode: associated inode (B-tree node cache holder or back poin= ter) * @i_dirty: list for connecting dirty files * @xattr_sem: semaphore for extended attributes processing * @i_bh: buffer contains disk inode @@ -43,7 +43,7 @@ struct nilfs_inode_info { __u64 i_xattr; /* sector_t ??? */ __u32 i_dir_start_lookup; __u64 i_cno; /* check point number for GC inode */ - struct address_space i_btnode_cache; + struct inode *i_assoc_inode; struct list_head i_dirty; /* List for connecting dirty files */ =20 #ifdef CONFIG_NILFS_XATTR @@ -75,13 +75,6 @@ static inline struct nilfs_inode_info *NILFS_I(const str= uct inode *inode) return container_of(bmap, struct nilfs_inode_info, i_bmap_data); } =20 -static inline struct inode *NILFS_BTNC_I(struct address_space *btnc) -{ - struct nilfs_inode_info *ii =3D - container_of(btnc, struct nilfs_inode_info, i_btnode_cache); - return &ii->vfs_inode; -} - /* * Dynamic state flags of NILFS on-memory inode (i_state) */ @@ -98,6 +91,7 @@ enum { NILFS_I_INODE_SYNC, /* dsync is not allowed for inode */ 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 */ }; =20 /* @@ -267,6 +261,8 @@ struct inode *nilfs_iget(struct super_block *sb, struct= nilfs_root *root, unsigned long ino); extern struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino, __u64 cno); +int nilfs_attach_btree_node_cache(struct inode *inode); +void nilfs_detach_btree_node_cache(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 *); diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 063dd16d75b5..45e079295008 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -448,10 +448,9 @@ void nilfs_mapping_init(struct address_space *mapping,= struct inode *inode) /* * NILFS2 needs clear_page_dirty() in the following two cases: * - * 1) For B-tree node pages and data pages of the dat/gcdat, NILFS2 clears - * page dirty flags when it copies back pages from the shadow cache - * (gcdat->{i_mapping,i_btnode_cache}) to its original cache - * (dat->{i_mapping,i_btnode_cache}). + * 1) For B-tree node pages and data pages of DAT file, NILFS2 clears dirty + * flag of pages when it copies back pages from shadow cache to the + * original cache. * * 2) Some B-tree operations like insertion or deletion may dispose buffers * in dirty state, and this needs to cancel the dirty state of their pa= ges. diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 85a853334771..0afe0832c754 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -733,15 +733,18 @@ static void nilfs_lookup_dirty_node_buffers(struct in= ode *inode, struct list_head *listp) { struct nilfs_inode_info *ii =3D NILFS_I(inode); - struct address_space *mapping =3D &ii->i_btnode_cache; + struct inode *btnc_inode =3D ii->i_assoc_inode; struct pagevec pvec; struct buffer_head *bh, *head; unsigned int i; pgoff_t index =3D 0; =20 + if (!btnc_inode) + return; + pagevec_init(&pvec); =20 - while (pagevec_lookup_tag(&pvec, mapping, &index, + while (pagevec_lookup_tag(&pvec, btnc_inode->i_mapping, &index, PAGECACHE_TAG_DIRTY)) { for (i =3D 0; i < pagevec_count(&pvec); i++) { bh =3D head =3D page_buffers(pvec.pages[i]); @@ -2410,7 +2413,7 @@ static void nilfs_construction_timeout(struct timer_l= ist *t) continue; list_del_init(&ii->i_dirty); truncate_inode_pages(&ii->vfs_inode.i_data, 0); - nilfs_btnode_cache_clear(&ii->i_btnode_cache); + nilfs_btnode_cache_clear(ii->i_assoc_inode->i_mapping); iput(&ii->vfs_inode); } } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 63e5fa74016c..c4c6578185d5 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -157,7 +157,8 @@ struct inode *nilfs_alloc_inode(struct super_block *sb) ii->i_bh =3D NULL; ii->i_state =3D 0; ii->i_cno =3D 0; - nilfs_mapping_init(&ii->i_btnode_cache, &ii->vfs_inode); + ii->i_assoc_inode =3D NULL; + ii->i_bmap =3D &ii->i_bmap_data; return &ii->vfs_inode; } =20 @@ -1377,8 +1378,6 @@ static void nilfs_inode_init_once(void *obj) #ifdef CONFIG_NILFS_XATTR init_rwsem(&ii->xattr_sem); #endif - address_space_init_once(&ii->i_btnode_cache); - ii->i_bmap =3D &ii->i_bmap_data; inode_init_once(&ii->vfs_inode); } =20 --=20 1.8.3.1 From nobody Mon Jun 22 15:43:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F4EDC433EF for ; Mon, 21 Mar 2022 12:57:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347672AbiCUM6u (ORCPT ); Mon, 21 Mar 2022 08:58:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347653AbiCUM6o (ORCPT ); Mon, 21 Mar 2022 08:58:44 -0400 Received: from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com [IPv6:2607:f8b0:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1FE41042AF; Mon, 21 Mar 2022 05:57:18 -0700 (PDT) Received: by mail-pl1-x62c.google.com with SMTP id n15so12665957plh.2; Mon, 21 Mar 2022 05:57:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+jIABKwdmY8gnG/9wlJwvXAWsKsOiFrpdlbnusqYXuk=; b=kime+Zn5GGc0oeVEWh+Eepq2J60HcGOtJBbI4FhrsRBAqhbyUERvz97Or8kubiZbeB DSAMrfbGk/tMLt4zq++r8LEZDh+1Rq1NzjhFmBa0cgYa/NzWLO6tlPc/qEFZLOm8HlcQ UwTrZ2JXmh6fIyCpqyBkblbbt9ECgcAKkYtLHNxcYJyYNjbgrzmYy6I1AzQhA3w/NoYn L3Tdy79wA+1qHBMg13d6AyU6YgP6dQYwBM7KD7U1pvlusjj47vMJTQFxSdHfYirvz3Tq f4k1h/1fJXDVqTVw3eCfsBa1v39CU4yF6z9+4WPbMb0Iwk+o/xbxmFLUEgXI28QeCYvj peEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+jIABKwdmY8gnG/9wlJwvXAWsKsOiFrpdlbnusqYXuk=; b=MJGt3feTu1cv/N3p2lH7elRpjYthCJJh9GjLwBbhfNSg9kbUthNYgtw0j1FlPsk1Vl 1wCcqckxwOKnSR8AgSl3Xl3hSwtaJJ+AbIwJNbr5otMK4QwUdM1Ge5bMH0m68DPEaHZH tAjs3rOB+MzjoshkMcMO4b25ymH72hM/tUlJ8nhKr417/8arf8+2jOe6c3aKwry4Rs0d QtIPK2lCq1RJ4u+ClyzYP1NTMTmdbc6gjAN4Ahq/74WMR2s7WE6+P2UCnRuqVPbjDSR6 2nFerspmSrhw5mdaj/UujW91RgqEPxEfoznu4Zbo6lo/dZSA7yOwbVrGlRNkdSrhnTWx L60Q== X-Gm-Message-State: AOAM530Na/vlvEE2Zq/XDSQH5QXZCZpYBcLO7BAu68Zaz72wNNlzhwvv xUSdkyxdzPK2dirXHDxMw8clJ0E6A4o= X-Google-Smtp-Source: ABdhPJxwNZUx51KdnK+xRLJdkFjMdHmA19IdSRAgXd/8wWOHME3K0XTRquykfaX4oHWpij35VzwPRA== X-Received: by 2002:a17:902:e812:b0:154:1e0a:ca3b with SMTP id u18-20020a170902e81200b001541e0aca3bmr13024201plg.24.1647867437967; Mon, 21 Mar 2022 05:57:17 -0700 (PDT) Received: from carrot.localdomain (i114-180-38-233.s42.a014.ap.plala.or.jp. [114.180.38.233]) by smtp.gmail.com with ESMTPSA id gb5-20020a17090b060500b001c6d46f7e75sm8009046pjb.30.2022.03.21.05.57.15 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Mar 2022 05:57:16 -0700 (PDT) From: Ryusuke Konishi To: Andrew Morton Cc: linux-nilfs , Matthew Wilcox , David Hildenbrand , LKML , "linux-mm@kvack.org" Subject: [PATCH 2/3] nilfs2: fix lockdep warnings during disk space reclamation Date: Mon, 21 Mar 2022 21:57:06 +0900 Message-Id: <1647867427-30498-3-git-send-email-konishi.ryusuke@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1647867427-30498-1-git-send-email-konishi.ryusuke@gmail.com> References: <1647867427-30498-1-git-send-email-konishi.ryusuke@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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: 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. Signed-off-by: Ryusuke Konishi Tested-by: Ryusuke Konishi Cc: Matthew Wilcox --- 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(-) diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index dc51d3b7a7bf..3b55e239705f 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -497,7 +497,9 @@ int nilfs_dat_read(struct super_block *sb, size_t entry= _size, di =3D 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 =3D nilfs_mdt_setup_shadow_map(dat, &di->shadow); + if (err) + goto failed; =20 err =3D nilfs_read_inode_common(dat, raw_inode); if (err) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 56b642159e25..d63d4bbad9fe 100644 --- a/fs/nilfs2/inode.c +++ b/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; }; =20 static int nilfs_iget_test(struct inode *inode, void *opaque); @@ -317,7 +319,7 @@ static int nilfs_insert_inode_locked(struct inode *inod= e, { struct nilfs_iget_args args =3D { .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D false, - .for_btnc =3D false + .for_btnc =3D false, .for_shadow =3D false }; =20 return insert_inode_locked4(inode, ino, nilfs_iget_test, &args); @@ -536,6 +538,12 @@ static int nilfs_iget_test(struct inode *inode, void *= opaque) } 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; + } =20 if (!test_bit(NILFS_I_GCINODE, &ii->i_state)) return !args->for_gc; @@ -557,6 +565,8 @@ static int nilfs_iget_set(struct inode *inode, void *op= aque) NILFS_I(inode)->i_state =3D BIT(NILFS_I_GCINODE); if (args->for_btnc) NILFS_I(inode)->i_state |=3D BIT(NILFS_I_BTNC); + if (args->for_shadow) + NILFS_I(inode)->i_state |=3D BIT(NILFS_I_SHADOW); return 0; } =20 @@ -565,7 +575,7 @@ struct inode *nilfs_ilookup(struct super_block *sb, str= uct nilfs_root *root, { struct nilfs_iget_args args =3D { .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D false, - .for_btnc =3D false + .for_btnc =3D false, .for_shadow =3D false }; =20 return ilookup5(sb, ino, nilfs_iget_test, &args); @@ -576,7 +586,7 @@ struct inode *nilfs_iget_locked(struct super_block *sb,= struct nilfs_root *root, { struct nilfs_iget_args args =3D { .ino =3D ino, .root =3D root, .cno =3D 0, .for_gc =3D false, - .for_btnc =3D false + .for_btnc =3D false, .for_shadow =3D false }; =20 return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args); @@ -608,7 +618,7 @@ struct inode *nilfs_iget_for_gc(struct super_block *sb,= unsigned long ino, { struct nilfs_iget_args args =3D { .ino =3D ino, .root =3D NULL, .cno =3D cno, .for_gc =3D true, - .for_btnc =3D false + .for_btnc =3D false, .for_shadow =3D false }; struct inode *inode; int err; @@ -655,6 +665,7 @@ int nilfs_attach_btree_node_cache(struct inode *inode) args.cno =3D ii->i_cno; args.for_gc =3D test_bit(NILFS_I_GCINODE, &ii->i_state) !=3D 0; args.for_btnc =3D true; + args.for_shadow =3D test_bit(NILFS_I_SHADOW, &ii->i_state) !=3D 0; =20 btnc_inode =3D iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test, nilfs_iget_set, &args); @@ -690,6 +701,50 @@ void nilfs_detach_btree_node_cache(struct inode *inode) } } =20 +/** + * 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 return= ed + * in a pointer type. + * + * %-ENOMEM - Insufficient memory available. + */ +struct inode *nilfs_iget_for_shadow(struct inode *inode) +{ + struct nilfs_iget_args args =3D { + .ino =3D inode->i_ino, .root =3D NULL, .cno =3D 0, .for_gc =3D false, + .for_btnc =3D false, .for_shadow =3D true + }; + struct inode *s_inode; + int err; + + s_inode =3D 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 =3D 0; + memset(NILFS_I(s_inode)->i_bmap, 0, sizeof(struct nilfs_bmap)); + mapping_set_gfp_mask(s_inode->i_mapping, GFP_NOFS); + + err =3D 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) { diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index b26996420401..880b5e8cd3ec 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -470,9 +470,18 @@ int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask= , size_t objsz) void nilfs_mdt_clear(struct inode *inode) { struct nilfs_mdt_info *mdi =3D NILFS_MDT(inode); + struct nilfs_shadow_map *shadow =3D mdi->mi_shadow; =20 if (mdi->mi_palloc_cache) nilfs_palloc_destroy_cache(inode); + + if (shadow) { + struct inode *s_inode =3D shadow->inode; + + shadow->inode =3D NULL; + iput(s_inode); + mdi->mi_shadow =3D NULL; + } } =20 /** @@ -506,12 +515,15 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode, struct nilfs_shadow_map *shadow) { struct nilfs_mdt_info *mi =3D NILFS_MDT(inode); + struct inode *s_inode; =20 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 =3D nilfs_iget_for_shadow(inode); + if (IS_ERR(s_inode)) + return PTR_ERR(s_inode); + + shadow->inode =3D s_inode; mi->mi_shadow =3D shadow; return 0; } @@ -525,13 +537,14 @@ int nilfs_mdt_save_to_shadow_map(struct inode *inode) struct nilfs_mdt_info *mi =3D NILFS_MDT(inode); struct nilfs_inode_info *ii =3D NILFS_I(inode); struct nilfs_shadow_map *shadow =3D mi->mi_shadow; + struct inode *s_inode =3D shadow->inode; int ret; =20 - ret =3D nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping); + ret =3D nilfs_copy_dirty_pages(s_inode->i_mapping, inode->i_mapping); if (ret) goto out; =20 - ret =3D nilfs_copy_dirty_pages(&shadow->frozen_btnodes, + ret =3D nilfs_copy_dirty_pages(NILFS_I(s_inode)->i_assoc_inode->i_mapping, ii->i_assoc_inode->i_mapping); if (ret) goto out; @@ -548,7 +561,7 @@ int nilfs_mdt_freeze_buffer(struct inode *inode, struct= buffer_head *bh) struct page *page; int blkbits =3D inode->i_blkbits; =20 - page =3D grab_cache_page(&shadow->frozen_data, bh->b_page->index); + page =3D grab_cache_page(shadow->inode->i_mapping, bh->b_page->index); if (!page) return -ENOMEM; =20 @@ -580,7 +593,7 @@ struct buffer_head * struct page *page; int n; =20 - page =3D find_lock_page(&shadow->frozen_data, bh->b_page->index); + page =3D find_lock_page(shadow->inode->i_mapping, bh->b_page->index); if (page) { if (page_has_buffers(page)) { n =3D bh_offset(bh) >> inode->i_blkbits; @@ -621,11 +634,11 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *= inode) nilfs_palloc_clear_cache(inode); =20 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); =20 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); =20 nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); =20 @@ -640,10 +653,11 @@ void nilfs_mdt_clear_shadow_map(struct inode *inode) { struct nilfs_mdt_info *mi =3D NILFS_MDT(inode); struct nilfs_shadow_map *shadow =3D mi->mi_shadow; + struct inode *shadow_btnc_inode =3D NILFS_I(shadow->inode)->i_assoc_inode; =20 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); } diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index 8f86080a436d..9e23bab3ff12 100644 --- a/fs/nilfs2/mdt.h +++ b/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; }; =20 diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 36b048db00b7..1344f7d475d3 100644 --- a/fs/nilfs2/nilfs.h +++ b/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 */ }; =20 /* @@ -263,6 +264,7 @@ extern struct inode *nilfs_iget_for_gc(struct super_blo= ck *sb, 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 *); --=20 1.8.3.1 From nobody Mon Jun 22 15:43:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96301C433F5 for ; Mon, 21 Mar 2022 12:57:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347678AbiCUM6y (ORCPT ); Mon, 21 Mar 2022 08:58:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35498 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347660AbiCUM6q (ORCPT ); Mon, 21 Mar 2022 08:58:46 -0400 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 88D2916BF96; Mon, 21 Mar 2022 05:57:21 -0700 (PDT) Received: by mail-pj1-x1036.google.com with SMTP id kx5-20020a17090b228500b001c6ed9db871so3978445pjb.1; Mon, 21 Mar 2022 05:57:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=aGt0QOXNwCSbtFJRf/ayuNuD4ICQ9tLB6ZQAMSZA3fQ=; b=YOIqisPIdsOV4AXIAJlVXH7XAbldaJ4R2x9i2Or0eaf2szg9q8357OFBJJtaEd+hVI CejP+TuHCj+pB2qiM+u6XokNVAVvwj/aQJsEgY0C2JvhW+n3jpxhu6j5t7JF6QrUoyeE UPjykla2QOOjeDrX1G72k3NfzP5DUMENBpKD891lrsfg3H6mKeQvYKiCNLtLxmkLtfk/ 77LJJ/H+NnaZ0z/J2qj3MruVZ7PmWcObIFkSj+oSsJYzQvI6OfdcYjnQMN+8THfObjrv oA/yYttT+VirTpWtYXF3NqFKIW6k0sFjkHBJjVRSnsRUuddzfbTRYDJs5Ih+pVKry/tc C6+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=aGt0QOXNwCSbtFJRf/ayuNuD4ICQ9tLB6ZQAMSZA3fQ=; b=el5dUgReLvZTKaVKzqkQ86Mel3U67UO1wGQur2Rsw3GCed2GSudNBkXH9XPpj1gyTl qJ9WdrUQtoZVQz1Hvqi2yMgWS6YGgJ4jZQC9HfGwSq0ds+1TQ0zOoRfURa4iPhgDuDLw +p6hcNmThppxVo4uhCAcN8dwDP7C+JzqHnfvLziV5nApTv+OUaCV2QoPzT5RUgkcW25v QyHuR0fMHXsvF7IdsT3AZjQ183oGs5YxGzXox0MIxcwuvrU/YoTDBjbEojZJLJXBvWex zhriini2TbRQsxf8d377ByM0+d8YJbgaYVT1D8B+ctOlaGqHYFkNtq0U0EBE5RvyD/Tb 9Spw== X-Gm-Message-State: AOAM532+DTqAfk7v1mDyvY7LtAdYcS2yGuCHE28wi2i2IDFEjQLP5UxN yms9pj9N2gjyaHBxDetR9A8= X-Google-Smtp-Source: ABdhPJw+3d6nplioPzwdiaIc4hNRzAJmYdwwJ7vOcAz+jBjj0cPJ/YYPN9PLsUi3PtFs+z77IIq2Kw== X-Received: by 2002:a17:90a:d154:b0:1c6:64a5:a413 with SMTP id t20-20020a17090ad15400b001c664a5a413mr28068457pjw.6.1647867440860; Mon, 21 Mar 2022 05:57:20 -0700 (PDT) Received: from carrot.localdomain (i114-180-38-233.s42.a014.ap.plala.or.jp. [114.180.38.233]) by smtp.gmail.com with ESMTPSA id gb5-20020a17090b060500b001c6d46f7e75sm8009046pjb.30.2022.03.21.05.57.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Mar 2022 05:57:19 -0700 (PDT) From: Ryusuke Konishi To: Andrew Morton Cc: linux-nilfs , Matthew Wilcox , David Hildenbrand , LKML , "linux-mm@kvack.org" Subject: [PATCH 3/3] nilfs2: get rid of nilfs_mapping_init() Date: Mon, 21 Mar 2022 21:57:07 +0900 Message-Id: <1647867427-30498-4-git-send-email-konishi.ryusuke@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1647867427-30498-1-git-send-email-konishi.ryusuke@gmail.com> References: <1647867427-30498-1-git-send-email-konishi.ryusuke@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" After applying the lockdep warning fixes, nilfs_mapping_init() is no longer used, so delete it. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/page.c | 9 --------- fs/nilfs2/page.h | 1 - 2 files changed, 10 deletions(-) diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 45e079295008..a8e88cc38e16 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -436,15 +436,6 @@ unsigned int nilfs_page_count_clean_buffers(struct pag= e *page, return nc; } =20 -void nilfs_mapping_init(struct address_space *mapping, struct inode *inode) -{ - mapping->host =3D inode; - mapping->flags =3D 0; - mapping_set_gfp_mask(mapping, GFP_NOFS); - mapping->private_data =3D NULL; - mapping->a_ops =3D &empty_aops; -} - /* * NILFS2 needs clear_page_dirty() in the following two cases: * diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index 569263b23c0c..21ddcdd4d63e 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h @@ -43,7 +43,6 @@ struct buffer_head *nilfs_grab_buffer(struct inode *, str= uct address_space *, void nilfs_copy_back_pages(struct address_space *, struct address_space *); void nilfs_clear_dirty_page(struct page *, bool); void nilfs_clear_dirty_pages(struct address_space *, bool); -void nilfs_mapping_init(struct address_space *mapping, struct inode *inode= ); unsigned int nilfs_page_count_clean_buffers(struct page *, unsigned int, unsigned int); unsigned long nilfs_find_uncommitted_extent(struct inode *inode, --=20 1.8.3.1