From patchwork Mon Oct 24 11:29:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg KH X-Patchwork-Id: 10063 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp624037wru; Mon, 24 Oct 2022 12:49:50 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4jVMD3wxF3tiuOfkpEMd9kIVsFFtoCVgNoPXVkJUX4WG5z1euy/zuyVNVVZYo21iI/0Ytw X-Received: by 2002:a17:907:7213:b0:791:8aa5:5635 with SMTP id dr19-20020a170907721300b007918aa55635mr29814609ejc.348.1666640979435; Mon, 24 Oct 2022 12:49:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666640979; cv=none; d=google.com; s=arc-20160816; b=GEQwYxQqibS6ARiAkMZlbvBH7tGakX5YjJR5yNNoiTXV4zcXKJOCKSVNTJ270Sn5Ob nIISIhghVXDOGQNbGJDDBJXSQ9Ls1Ny16JHXGeDSHp9AJu3PovDsws3V2OXC6qiXHxpt DdkmI+bU2BjNMRrJ92VMLQudkZsVzo8uFUm1phUGGn9IpRNpz231gDOBo5TBe5VNITUH DTeH5CLklP3LjpvxpKn5PqkU9MYiIzGLKK87ERJSAVDuZtQ54ktA4Uk27/JOHyGcbjrD qaWtWnYpXC6ZXxZuaoaHy35iSXS+uLnkLO6vy+DKJjzYHFYDZyfH4pqALnYkLli7cBcp X2Vw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=mCv75nrMpqijLTIy+iYSS5H7aLkK3tRB+aawVwM5RCM=; b=BujDGBRXGboPl6KfpgCW/zbg5NMIK1LpI4Wb54gEgR0vTrg+D+W5n/DQemmjRHz0l/ PuGFONUhCoSqpl9aTh6zb4AjJcgzyQIW0/f0TQBub7FwE6/WIxfkRoN6g0LWrgY0/Fwn 6wr3I8C8ORelUxrBDURBixPpPpv8XXoyr6/j/rruUjT+VMxtJ3tPDy5w7b4o4VH68hgL korOKliWL8ENe2B0oc7A5DEMaTAiyluE+pMeys+l677+8OvSmJ4HnpQMWbhRteeotqYE 0K+6SEbY5TIzSQ6x4k7J+mwFi+zDDn4DBFDz0VBCxfexiJSBZNu/Z1NUK6NSlJwYy3ZG rUCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="TzzG///r"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id dt4-20020a170907728400b0078d5d4a6b64si661753ejc.662.2022.10.24.12.49.15; Mon, 24 Oct 2022 12:49:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="TzzG///r"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232346AbiJXTo5 (ORCPT + 99 others); Mon, 24 Oct 2022 15:44:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46216 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233422AbiJXTmO (ORCPT ); Mon, 24 Oct 2022 15:42:14 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C60AF3C8DC; Mon, 24 Oct 2022 11:11:56 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 2CC2EB811AF; Mon, 24 Oct 2022 11:49:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 755B6C433C1; Mon, 24 Oct 2022 11:48:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1666612138; bh=NxgZ+UFijl6OL8pOEGlvJusFXy8NFC1qyy7SRIQqfrw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TzzG///rkzAeONTbr9lvj2Da0gkYTdqXep2mFS4CkiyfffFqPDPFPp6E3/aMVR5fH ZjecGCRebHJNLKVgkzP6KbfW8zhOtKVthg9e0aT31a5MDDSGmsZkZQW7xk2aNgQVre sZWl5tZ0xPIx/5Q/fhxkx7n8m4MbNBuCt3OcKWpc= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ryusuke Konishi , Matthew Wilcox , David Hildenbrand , Hao Sun , Andrew Morton , Linus Torvalds Subject: [PATCH 4.14 067/210] nilfs2: fix lockdep warnings during disk space reclamation Date: Mon, 24 Oct 2022 13:29:44 +0200 Message-Id: <20221024112959.230524710@linuxfoundation.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221024112956.797777597@linuxfoundation.org> References: <20221024112956.797777597@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747599731158229301?= X-GMAIL-MSGID: =?utf-8?q?1747599731158229301?= From: Ryusuke Konishi commit 6e211930f79aa45d422009a5f2e5467d2369ffe5 upstream. 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 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 Tested-by: Ryusuke Konishi Cc: Matthew Wilcox Cc: David Hildenbrand Cc: Hao Sun Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- 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 +++ b/fs/nilfs2/dat.c @@ -506,7 +506,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 +++ b/fs/nilfs2/inode.c @@ -38,6 +38,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; @@ -45,6 +46,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); @@ -334,7 +336,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); @@ -570,6 +572,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; @@ -591,6 +599,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; } @@ -599,7 +609,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); @@ -610,7 +620,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); @@ -642,7 +652,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; @@ -689,6 +699,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); @@ -724,6 +735,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 +++ b/fs/nilfs2/mdt.c @@ -478,9 +478,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; + } } /** @@ -514,12 +523,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; } @@ -533,13 +545,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; @@ -556,7 +569,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; @@ -588,7 +601,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; @@ -629,11 +642,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); @@ -648,10 +661,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 +++ b/fs/nilfs2/mdt.h @@ -27,14 +27,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 +++ b/fs/nilfs2/nilfs.h @@ -101,6 +101,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 */ }; /* @@ -273,6 +274,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 *);