Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp1888549pxk; Sat, 19 Sep 2020 05:40:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwCkBV6a4Knokm1GhJNb4udetgNLB94QWTV/Z0nKLDRfOvqY6wzm2T8LD8vme70F3Ktq/Qj X-Received: by 2002:a05:6402:3192:: with SMTP id di18mr43678790edb.116.1600519249215; Sat, 19 Sep 2020 05:40:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600519249; cv=none; d=google.com; s=arc-20160816; b=vrDmpJVx+dHWffgVnJDRxV4EWqxAMmFRlEfCGD3QX4b+jFilLgK3PBePwu0Jz7hT69 rgWoQPKnOXRqnf7qlSj63R+iNzN66x+d74iJTfDc6UVKOa3US1+6p2G7WszeUsvbjuwc y1vq+XivFKgfkLSJ/Hm/b3BK7QKif8RoYZJG+GG6VpMU481ADmC15NDSHSJ1bf3VVEsh hvCMLsftMzcsSsS2jQbXYVPJ398brNYCVKc64EwfjfZh6l3IKgnjLdfQVzOdPZNH+gQB NdV7EaXp+S+uypvK9To8dJEGEaMNmH8rAGFpjBoV/ya5C3Ox5GeMA5yewpehxC4ev3vF VI0w== 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:date:message-id:subject:from:cc:to; bh=b5hDInKefkRGfP3kr6P2silOsUwJy+qDTR5QICdseVk=; b=XMz4YCTwokba7lGuFodBCE6ztpDFz5Y+/nodRBTixSWEd62tO7D2BEJDT0EWP7OldD EN0aexVGgbSMFO1UEuGl+MKTllc5Ig7bZ7HgV/nSSsfjX7E1vqGyBLCBiK7wADBMt0QX VIqoKgwPLZwWZkXQ5BEYKzpbg0w6DOd2A0yFIp12jDsg0fymakj//cy0cSi16jwJvv3n AFrJgko9gycarw1Qd3eNJLhYrvJxYOlSnotpQGDGYT26dVCWdcfqzPgVa/7/68p1i0Su T9FzYbq5TrCwjVM/vNdxqm4+Y9utehdJGUUMWUGScdwxfC8mxgr4dYHrii/Y8+Tcw4+K KxVg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w3si3979225edv.488.2020.09.19.05.40.07; Sat, 19 Sep 2020 05:40:49 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726269AbgISMkE (ORCPT + 99 others); Sat, 19 Sep 2020 08:40:04 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:13777 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726170AbgISMkE (ORCPT ); Sat, 19 Sep 2020 08:40:04 -0400 Received: from DGGEMS409-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id B636F85729F8BB661D98; Sat, 19 Sep 2020 20:40:01 +0800 (CST) Received: from [10.174.178.61] (10.174.178.61) by DGGEMS409-HUB.china.huawei.com (10.3.19.209) with Microsoft SMTP Server id 14.3.487.0; Sat, 19 Sep 2020 20:39:52 +0800 To: , , , CC: , From: Haotian Li Subject: [PATCH] ext4: fix data-races problem at inode->i_disksize Message-ID: Date: Sat, 19 Sep 2020 20:39:52 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset="gbk" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.174.178.61] X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org We find some data-race problems at inode->i_disksize by using KSCAN in kernel 4.18. The same problem can also be found at commit dce8e237100f ("ext4: fix a data race at inode->i_disksize"). BUG: KCSAN: data-race in ext4_da_write_end / ext4_writepages write to 0xffff8ee8ed62cea8 of 8 bytes by task 3908 on cpu 0: mpage_map_and_submit_extent [inline] ext4_writepages+0x170c/0x1b90 do_writepages+0x70/0x170 __filemap_fdatawrite_range+0x199/0x1f0 file_write_and_wait_range+0x80/0xc0 ext4_sync_file+0x26f/0x860 vfs_fsync_range+0x7a/0x130 vfs_fsync [inline] do_fsync+0x4c/0x80 __do_sys_fsync [inline] __se_sys_fsync [inline] __x64_sys_fsync+0x2c/0x40 do_syscall_64+0xb5/0x340 entry_SYSCALL_64_after_hwframe+0x65/0xca 0xffffffffffffffff read to 0xffff8ee8ed62cea8 of 8 bytes by task 3907 on cpu 3: ext4_da_write_end+0xd3/0x7d0 generic_perform_write+0x1c6/0x2c0 __generic_file_write_iter+0x2aa/0x2f0 ext4_file_write_iter+0x197/0x820 call_write_iter [inline] new_sync_write+0x2ae/0x350 __vfs_write+0xa5/0xc0 vfs_write+0x119/0x2e0 ksys_write+0x83/0x120 __do_sys_write [inline] __se_sys_write [inline] __x64_sys_write+0x4d/0x60 do_syscall_64+0xb5/0x340 entry_SYSCALL_64_after_hwframe+0x65/0xca 0xffffffffffffffff We find two solutions to solve this problem. 1) Just the same as commit dce8e237100f ("ext4: fix a data race at inode->i_disksize"), Add READ_ONCE or WRITE_ONCE on inode->i_disksize directly. It is helpful to avoid current KCSAN problem. However, some other code using inode->i_disksize without READ_ONCE or WRITE_ONCE may also have KCSAN problem. So, we try to use the second solution. 2) Add 'volatile' keyword at inode->i_disksize. We think this solution may be helpful to deal with the date-race problem on inode->i_disksize. Reported-by: Wenhao Zhang Signed-off-by: Haotian Li --- fs/ext4/ext4.h | 4 ++-- fs/ext4/inode.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 523e00d7b392..354a9d1371af 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1036,7 +1036,7 @@ struct ext4_inode_info { * a truncate is in progress. The only things which change i_disksize * are ext4_get_block (growth) and ext4_truncate (shrinkth). */ - loff_t i_disksize; + volatile loff_t i_disksize; /* * i_data_sem is for serialising ext4_truncate() against @@ -3128,7 +3128,7 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) !inode_is_locked(inode)); down_write(&EXT4_I(inode)->i_data_sem); if (newsize > EXT4_I(inode)->i_disksize) - WRITE_ONCE(EXT4_I(inode)->i_disksize, newsize); + EXT4_I(inode)->i_disksize = newsize; up_write(&EXT4_I(inode)->i_data_sem); } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index bf596467c234..7c89d07dead3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2476,7 +2476,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, * truncate are avoided by checking i_size under i_data_sem. */ disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT; - if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) { + if (disksize > EXT4_I(inode)->i_disksize) { int err2; loff_t i_size; @@ -5015,7 +5015,7 @@ static int ext4_do_update_inode(handle_t *handle, raw_inode->i_file_acl_high = cpu_to_le16(ei->i_file_acl >> 32); raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); - if (READ_ONCE(ei->i_disksize) != ext4_isize(inode->i_sb, raw_inode)) { + if (ei->i_disksize != ext4_isize(inode->i_sb, raw_inode)) { ext4_isize_set(raw_inode, ei->i_disksize); need_datasync = 1; } -- 2.19.1