From patchwork Mon Nov 22 06:41:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gang Li X-Patchwork-Id: 12631271 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B4B8C433EF for ; Mon, 22 Nov 2021 06:42:11 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 810D16B0071; Mon, 22 Nov 2021 01:41:55 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7C0276B0072; Mon, 22 Nov 2021 01:41:55 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6AFC36B0073; Mon, 22 Nov 2021 01:41:55 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0030.hostedemail.com [216.40.44.30]) by kanga.kvack.org (Postfix) with ESMTP id 5BC546B0071 for ; Mon, 22 Nov 2021 01:41:55 -0500 (EST) Received: from smtpin21.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 145D41851DD7D for ; Mon, 22 Nov 2021 06:41:45 +0000 (UTC) X-FDA: 78835620570.21.0D44702 Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) by imf08.hostedemail.com (Postfix) with ESMTP id 580793000243 for ; Mon, 22 Nov 2021 06:41:40 +0000 (UTC) Received: by mail-pj1-f49.google.com with SMTP id p18-20020a17090ad31200b001a78bb52876so16019485pju.3 for ; Sun, 21 Nov 2021 22:41:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=c6luE0x1Txd3w3w56rJ0UKpQXDWDNrMSolAkksUQvV0=; b=YPovlI/7m21B6tofIcXvrA5HXrkiOxOWOKnWCkf7gazJevBwI9qHo52/W9QzkDsWPh svgkwzNuxt2vu7mJU6LYzUGNPFd2Xl8tBJr1FeretoOlHIsbwWXrZRaNQ37y24ZUttli Ehfbfy78vHLSaaRtmWjBx50wKIvxWcX273RhKg98+R5JGInPUDiPPKToukP1Qh+WCGrf 7AiDdf+r6MtJ5R1okDBeYt8Bk5gb/xzNY2UgAT0rMbTzoPEDbz9JDvK/0EJl0TFPQIwG jNRkiEoRXaPiNFmBFZOEZbRkefNFwfNUbWSYkS1YSSzKSMdNjF8tyZLFWcYUNvto2Tm4 Qwpg== 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:mime-version :content-transfer-encoding; bh=c6luE0x1Txd3w3w56rJ0UKpQXDWDNrMSolAkksUQvV0=; b=O/zUY7ipGCiC0zwe3qCrQNRoKYl5Qm803h1y9sT3NukqEDpluqxtosR2TGb0ITLEQk lkuLcHx3I2X7F2pTBghOQPkaS6xQxcWGsMNhH0/2LjSVnwX2ryWcOERf4vq17vNz2G/T kGRnH6bEzO28SjOsduoDm5Q01OFr9u2PY4WVfb4hO5i00y+SL895w8c3fl3XeA7bJcWd wrZIHkc5hFVLGjkBs0kbPBaBUX0+UjnWUWza84hUtysuOCctz9kQhAwJpP/J8HLR5uxY 9QNeTTkhCpYeFmC77YSU8yohMrXYSmEznVCVfbZS2T+Beb7SurJxmp2qC0u5F0Zj8Zb/ 1Z1A== X-Gm-Message-State: AOAM533YKvAQAo0q8+uS6Jefj7Z9jiEqxHDmeq8aQuD8B71yFPq+cGQz zElBmutYMV24gcnQhWvfNEI6jw== X-Google-Smtp-Source: ABdhPJwTGOGQcC8UPl37F/VrxiCporykUGVd1cUX9tTfLcgzD63dKYMorXSxptvvgkyh1WhzRnkdPA== X-Received: by 2002:a17:90b:1c81:: with SMTP id oo1mr28274619pjb.5.1637563302669; Sun, 21 Nov 2021 22:41:42 -0800 (PST) Received: from C02FT5A6MD6R.bytedance.net ([61.120.150.76]) by smtp.gmail.com with ESMTPSA id e13sm5395304pgb.8.2021.11.21.22.41.39 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 21 Nov 2021 22:41:42 -0800 (PST) From: Gang Li To: Hugh Dickins , Andrew Morton , "Kirill A. Shutemov" Cc: Gang Li , linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH v1] shmem: change shrinklist_lock form spinlock to mutex and move iput into it Date: Mon, 22 Nov 2021 14:41:26 +0800 Message-Id: <20211122064126.76734-1-ligang.bdlg@bytedance.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 580793000243 X-Stat-Signature: ywejy6njso1mgaqi1jonbusrcxeht6f8 Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=bytedance-com.20210112.gappssmtp.com header.s=20210112 header.b="YPovlI/7"; spf=pass (imf08.hostedemail.com: domain of ligang.bdlg@bytedance.com designates 209.85.216.49 as permitted sender) smtp.mailfrom=ligang.bdlg@bytedance.com; dmarc=pass (policy=none) header.from=bytedance.com X-HE-Tag: 1637563300-266417 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: This patch fixes commit 779750d20b93 ("shmem: split huge pages beyond i_size under memory pressure"). iput out of sbinfo->shrinklist_lock will let shmem_evict_inode grab and delete the inode, which will berak the consistency between shrinklist_len and shrinklist. The simultaneous deletion of adjacent elements in the local list "list" by shmem_unused_huge_shrink and shmem_evict_inode will also break the list. iput must in lock or after lock, but shrinklist_lock is a spinlock which can not sleep and iput may sleep.[1] Fix it by changing shrinklist_lock from spinlock to mutex and moving iput into this lock. [1]. Link: http://lkml.kernel.org/r/20170131093141.GA15899@node.shutemov.name Fixes: 779750d20b93 ("shmem: split huge pages beyond i_size under memory pressure") Signed-off-by: Gang Li Reported-by: kernel test robot --- include/linux/shmem_fs.h | 2 +- mm/shmem.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 166158b6e917..65804fd264d0 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -41,7 +41,7 @@ struct shmem_sb_info { ino_t next_ino; /* The next per-sb inode number to use */ ino_t __percpu *ino_batch; /* The next per-cpu inode number to use */ struct mempolicy *mpol; /* default memory policy for mappings */ - spinlock_t shrinklist_lock; /* Protects shrinklist */ + struct mutex shrinklist_mutex;/* Protects shrinklist */ struct list_head shrinklist; /* List of shinkable inodes */ unsigned long shrinklist_len; /* Length of shrinklist */ }; diff --git a/mm/shmem.c b/mm/shmem.c index 18f93c2d68f1..2165a28631c5 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -559,7 +559,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, if (list_empty(&sbinfo->shrinklist)) return SHRINK_STOP; - spin_lock(&sbinfo->shrinklist_lock); + mutex_lock(&sbinfo->shrinklist_mutex); list_for_each_safe(pos, next, &sbinfo->shrinklist) { info = list_entry(pos, struct shmem_inode_info, shrinklist); @@ -586,7 +586,6 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, if (!--batch) break; } - spin_unlock(&sbinfo->shrinklist_lock); list_for_each_safe(pos, next, &to_remove) { info = list_entry(pos, struct shmem_inode_info, shrinklist); @@ -643,10 +642,9 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, iput(inode); } - spin_lock(&sbinfo->shrinklist_lock); list_splice_tail(&list, &sbinfo->shrinklist); sbinfo->shrinklist_len -= removed; - spin_unlock(&sbinfo->shrinklist_lock); + mutex_unlock(&sbinfo->shrinklist_mutex); return split; } @@ -1137,12 +1135,12 @@ static void shmem_evict_inode(struct inode *inode) inode->i_size = 0; shmem_truncate_range(inode, 0, (loff_t)-1); if (!list_empty(&info->shrinklist)) { - spin_lock(&sbinfo->shrinklist_lock); + mutex_lock(&sbinfo->shrinklist_mutex); if (!list_empty(&info->shrinklist)) { list_del_init(&info->shrinklist); sbinfo->shrinklist_len--; } - spin_unlock(&sbinfo->shrinklist_lock); + mutex_unlock(&sbinfo->shrinklist_mutex); } while (!list_empty(&info->swaplist)) { /* Wait while shmem_unuse() is scanning this inode... */ @@ -1954,7 +1952,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, * Part of the huge page is beyond i_size: subject * to shrink under memory pressure. */ - spin_lock(&sbinfo->shrinklist_lock); + mutex_lock(&sbinfo->shrinklist_mutex); /* * _careful to defend against unlocked access to * ->shrink_list in shmem_unused_huge_shrink() @@ -1964,7 +1962,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, &sbinfo->shrinklist); sbinfo->shrinklist_len++; } - spin_unlock(&sbinfo->shrinklist_lock); + mutex_unlock(&sbinfo->shrinklist_mutex); } /* @@ -3652,7 +3650,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) raw_spin_lock_init(&sbinfo->stat_lock); if (percpu_counter_init(&sbinfo->used_blocks, 0, GFP_KERNEL)) goto failed; - spin_lock_init(&sbinfo->shrinklist_lock); + mutex_init(&sbinfo->shrinklist_mutex); INIT_LIST_HEAD(&sbinfo->shrinklist); sb->s_maxbytes = MAX_LFS_FILESIZE;