From patchwork Tue Jan 5 00:54:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997847 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF5F6C433DB for ; Tue, 5 Jan 2021 00:56:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9323F2253A for ; Tue, 5 Jan 2021 00:56:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727134AbhAEAzs (ORCPT ); Mon, 4 Jan 2021 19:55:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:37926 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726434AbhAEAzr (ORCPT ); Mon, 4 Jan 2021 19:55:47 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id D69D622573; Tue, 5 Jan 2021 00:55:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808107; bh=yfLor65DiiDuUyAFfmLknF94i9VyZ+d0RMnYmOcXc4A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bcHKHrhaoruYAQ5HHU5nfeR3wPqWWJRuX9SdUqzWXifBuynZRhAtxo2xi1I9ryELL jYk6KvnE5QMyEiyeHAI3hRYCQILCytEhaOfPVjfXreCFemcvnM/Nkq/iq5Q+RtkaZs FREWALhhzmJ/GUgLJp5mIG1Yxi6coO7FsXLWzisbVwJM+KeK7uPQyfmumSJ2f9w81e HW5IKeMMrfvPE1S+tMNafipk6MHE7F2WSksulFTT8sNGigCoztUjO6ThghPZs3+eWU kOgtkaqdduPXOiRgahNp8ljEYKSiIq2KPfLo4pr7ZLNHalGDepljvOaxQXxDFbKpsh Bo4e5vfoJCM7w== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig , stable@vger.kernel.org Subject: [PATCH 01/13] fs: avoid double-writing inodes on lazytime expiration Date: Mon, 4 Jan 2021 16:54:40 -0800 Message-Id: <20210105005452.92521-2-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers When lazytime is enabled and an inode with dirty timestamps is being expired, either due to dirtytime_expire_interval being exceeded or due to a sync or syncfs system call, we need to inform the filesystem that the inode is dirty so that the inode's timestamps can be copied out to the on-disk data structures. That's because if the filesystem supports lazytime, it will have ignored the ->dirty_inode(inode, I_DIRTY_TIME) notification when the timestamp was modified in memory. Currently this is accomplished by calling mark_inode_dirty_sync() from __writeback_single_inode(). However, this has the unfortunate side effect of also putting the inode the writeback list. That's not appropriate in this case, since the inode is already being written. That causes the inode to remain dirty after a sync. Normally that's just wasteful, as it causes the inode to be written twice. But when fscrypt is used this bug also partially breaks the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl, as the ioctl reports that files are still in-use when they aren't. For more details, see the original report at https://lore.kernel.org/r/20200306004555.GB225345@gmail.com Fix this by calling ->dirty_inode(inode, I_DIRTY_SYNC) directly instead of mark_inode_dirty_sync(). This fixes xfstest generic/580 when lazytime is enabled. A later patch will introduce a ->lazytime_expired method to cleanly separate out the lazytime expiration case, in particular for XFS which uses the VFS-level dirtiness tracking only for lazytime. But that's separate from fixing this bug. Also, note that XFS will incorrectly ignore the I_DIRTY_SYNC notification from __writeback_single_inode() both before and after this patch, as I_DIRTY_TIME was already cleared in i_state. Later patches will fix this separate bug. Fixes: 0ae45f63d4ef ("vfs: add support for a lazytime mount option") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- fs/fs-writeback.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) base-commit: e71ba9452f0b5b2e8dc8aa5445198cd9214a6a62 diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index acfb55834af23..081e335cdee47 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1509,11 +1509,22 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) spin_unlock(&inode->i_lock); - if (dirty & I_DIRTY_TIME) - mark_inode_dirty_sync(inode); /* Don't write the inode if only I_DIRTY_PAGES was set */ if (dirty & ~I_DIRTY_PAGES) { - int err = write_inode(inode, wbc); + int err; + + /* + * If the inode is being written due to a lazytime timestamp + * expiration, then the filesystem needs to be notified about it + * so that e.g. the filesystem can update on-disk fields and + * journal the timestamp update. Just calling write_inode() + * isn't enough. Don't call mark_inode_dirty_sync(), as that + * would put the inode back on the dirty list. + */ + if ((dirty & I_DIRTY_TIME) && inode->i_sb->s_op->dirty_inode) + inode->i_sb->s_op->dirty_inode(inode, I_DIRTY_SYNC); + + err = write_inode(inode, wbc); if (ret == 0) ret = err; } From patchwork Tue Jan 5 00:54:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997855 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DEBEC432C3 for ; Tue, 5 Jan 2021 00:56:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 502AF2256F for ; Tue, 5 Jan 2021 00:56:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727453AbhAEAz6 (ORCPT ); Mon, 4 Jan 2021 19:55:58 -0500 Received: from mail.kernel.org ([198.145.29.99]:37938 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726563AbhAEAzr (ORCPT ); Mon, 4 Jan 2021 19:55:47 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 37BF822581; Tue, 5 Jan 2021 00:55:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808107; bh=U6WXkB7J0EGF6Jkf3SnygA2+eyxb+PWLweu7YzuZvME=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cyhUiJG0iohmox3eBnb7ZvT/64QABTWCcVVqOf7ITvkMkTEu5lVVYROPs+dqoIlXT zqSWl59Y/qHHWnHAE8hsbsYLzXsH1PlviZyQC0MXq4sigqVueOoEtg/Tu2li2W4DvI vaLfjaL7HhSuNcnkr5JxLQO87QlhauH+YahAlEvbyvDwKIrQxeC0PHzjOaTzRxWe1P 3ASeMv1WQw19wbl9QxIYNLfbMYmxGIPMOTaTvEksLr4kSQvaNX27M1MfODnuaK1UGR QbpO1XUUKTHaP+uXuHYUb3S4XrF9OKR3QVJs1LGEj/FUHrv+3AViUp+fy1YBWDtCQn xoj2rU1YRXk6g== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 02/13] gfs2: don't worry about I_DIRTY_TIME in gfs2_fsync() Date: Mon, 4 Jan 2021 16:54:41 -0800 Message-Id: <20210105005452.92521-3-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers The I_DIRTY_TIME flag is primary used within the VFS, and there's no reason for ->fsync() implementations to do anything with it. This is because when !datasync, the VFS will expire dirty timestamps before calling ->fsync(). (See vfs_fsync_range().) This turns I_DIRTY_TIME into I_DIRTY_SYNC. Therefore, change gfs2_fsync() to not check for I_DIRTY_TIME. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- fs/gfs2/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index b39b339feddc9..7fe2497755a37 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -749,7 +749,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, { struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; - int sync_state = inode->i_state & I_DIRTY_ALL; + int sync_state = inode->i_state & I_DIRTY; struct gfs2_inode *ip = GFS2_I(inode); int ret = 0, ret1 = 0; @@ -762,7 +762,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, if (!gfs2_is_jdata(ip)) sync_state &= ~I_DIRTY_PAGES; if (datasync) - sync_state &= ~(I_DIRTY_SYNC | I_DIRTY_TIME); + sync_state &= ~I_DIRTY_SYNC; if (sync_state) { ret = sync_inode_metadata(inode, 1); From patchwork Tue Jan 5 00:54:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997851 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BC38C4332D for ; Tue, 5 Jan 2021 00:56:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 50EF2227C3 for ; Tue, 5 Jan 2021 00:56:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727254AbhAEAzt (ORCPT ); Mon, 4 Jan 2021 19:55:49 -0500 Received: from mail.kernel.org ([198.145.29.99]:37944 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726258AbhAEAzs (ORCPT ); Mon, 4 Jan 2021 19:55:48 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 879B722582; Tue, 5 Jan 2021 00:55:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808107; bh=moPvKfHUYW5Xbk7fp9PqSrbSDfWUFwePDygO+DUtRFo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=odLOb9jW7zdbgQ19pnxfQeV0LZCahNWh2pJHvvskuGhaoTAJINjva3sXgUpuQUx4C 9Q4jVEGDvC4JAbMDOb0ntyBgGZGYCD7D5RQ+uTFsyV3drMND3coDDlh3n+eJeaDR4P hil5l822YPp+3ttvEctfsdcoutR9fY1zMzcy5DOf6/m5irfC1tIlgTw7cCQNZnYr2n osSXWG3OuD+6/7zLbzpZ0kcTNtAhXkxI9E8LYaVMNzhVDRqwBsPc/DbKgZ8L/a763U fTbNyD1NhYvp7LInib3/VaOfA36sk0VY6JASj7UsjCeOh2iBGsxYCeMQqSIOQuqYJT QcZ5iZypbSAwA== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 03/13] fs: only specify I_DIRTY_TIME when needed in generic_update_time() Date: Mon, 4 Jan 2021 16:54:42 -0800 Message-Id: <20210105005452.92521-4-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers generic_update_time() always passes I_DIRTY_TIME to __mark_inode_dirty(), which doesn't really make sense because (a) generic_update_time() might be asked to do only an i_version update, not also a timestamps update; and (b) I_DIRTY_TIME is only supposed to be set in i_state if the filesystem has lazytime enabled, so using it unconditionally in generic_update_time() is inconsistent. As a result there is a weird edge case where if only an i_version update was requested (not also a timestamps update) but it is no longer needed (i.e. inode_maybe_inc_iversion() returns false), then I_DIRTY_TIME will be set in i_state even if the filesystem isn't mounted with lazytime. Fix this by only passing I_DIRTY_TIME to __mark_inode_dirty() if the timestamps were updated and the filesystem has lazytime enabled. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- fs/inode.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 6442d97d9a4ab..d0fa43d8e9d5c 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1743,24 +1743,26 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, int generic_update_time(struct inode *inode, struct timespec64 *time, int flags) { - int iflags = I_DIRTY_TIME; - bool dirty = false; - - if (flags & S_ATIME) - inode->i_atime = *time; - if (flags & S_VERSION) - dirty = inode_maybe_inc_iversion(inode, false); - if (flags & S_CTIME) - inode->i_ctime = *time; - if (flags & S_MTIME) - inode->i_mtime = *time; - if ((flags & (S_ATIME | S_CTIME | S_MTIME)) && - !(inode->i_sb->s_flags & SB_LAZYTIME)) - dirty = true; - - if (dirty) - iflags |= I_DIRTY_SYNC; - __mark_inode_dirty(inode, iflags); + int dirty_flags = 0; + + if (flags & (S_ATIME | S_CTIME | S_MTIME)) { + if (flags & S_ATIME) + inode->i_atime = *time; + if (flags & S_CTIME) + inode->i_ctime = *time; + if (flags & S_MTIME) + inode->i_mtime = *time; + + if (inode->i_sb->s_flags & SB_LAZYTIME) + dirty_flags |= I_DIRTY_TIME; + else + dirty_flags |= I_DIRTY_SYNC; + } + + if ((flags & S_VERSION) && inode_maybe_inc_iversion(inode, false)) + dirty_flags |= I_DIRTY_SYNC; + + __mark_inode_dirty(inode, dirty_flags); return 0; } EXPORT_SYMBOL(generic_update_time); From patchwork Tue Jan 5 00:54:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997849 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 343BCC433E6 for ; Tue, 5 Jan 2021 00:56:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E31B8227C3 for ; Tue, 5 Jan 2021 00:56:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727323AbhAEAzt (ORCPT ); Mon, 4 Jan 2021 19:55:49 -0500 Received: from mail.kernel.org ([198.145.29.99]:37952 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726434AbhAEAzs (ORCPT ); Mon, 4 Jan 2021 19:55:48 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id D625F2256F; Tue, 5 Jan 2021 00:55:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808108; bh=gBV7rjbDvtj1IoteKM7jbO9E67+Za0GVgMCAesn4G6k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ASJXzrsaVLLasAKCmNGQSKOsMzoHtyRTKBaHFlVXFQWcoZqc+MWcqkJo30DvIHloH AQT6fY5xNbAtk+zgP7jYSZLRrOAJ4ve0S6wO5OlKd7JqhskWjzWVlZfkpD3Cf4WlE+ 0N+puDoBQbAkS3G1vkyoVmd86/9RkrxKI5CoTed7Wx289cf491pErIMcw4G67tPHA8 a5J36fPKHrZkxGBc4tFW4r89vKZSAxjDy5WWIk1Ep3l1oUo0Kqtv4R55KrHvZRsO78 7NTU8xToN3ZsCH91q93mkbVXgUg7Yt4K6c7WBIk64cBmgCNGKKaSrWQCiH9ZKxWTSC EM9WBiVZRtw2w== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 04/13] fat: only specify I_DIRTY_TIME when needed in fat_update_time() Date: Mon, 4 Jan 2021 16:54:43 -0800 Message-Id: <20210105005452.92521-5-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers As was done for generic_update_time(), only pass I_DIRTY_TIME to __mark_inode_dirty() when the inode's timestamps were actually updated and lazytime is enabled. This avoids a weird edge case where I_DIRTY_TIME could be set in i_state when lazytime isn't enabled. Signed-off-by: Eric Biggers --- fs/fat/misc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/fat/misc.c b/fs/fat/misc.c index f1b2a1fc2a6a4..33e1e0c9fd634 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -329,21 +329,22 @@ EXPORT_SYMBOL_GPL(fat_truncate_time); int fat_update_time(struct inode *inode, struct timespec64 *now, int flags) { - int iflags = I_DIRTY_TIME; - bool dirty = false; + int dirty_flags = 0; if (inode->i_ino == MSDOS_ROOT_INO) return 0; - fat_truncate_time(inode, now, flags); - if (flags & S_VERSION) - dirty = inode_maybe_inc_iversion(inode, false); - if ((flags & (S_ATIME | S_CTIME | S_MTIME)) && - !(inode->i_sb->s_flags & SB_LAZYTIME)) - dirty = true; + if (flags & (S_ATIME | S_CTIME | S_MTIME)) { + fat_truncate_time(inode, now, flags); + if (inode->i_sb->s_flags & SB_LAZYTIME) + dirty_flags |= I_DIRTY_TIME; + else + dirty_flags |= I_DIRTY_SYNC; + } + + if ((flags & S_VERSION) && inode_maybe_inc_iversion(inode, false)) + dirty_flags |= I_DIRTY_SYNC; - if (dirty) - iflags |= I_DIRTY_SYNC; __mark_inode_dirty(inode, iflags); return 0; } From patchwork Tue Jan 5 00:54:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997871 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47328C4161F for ; Tue, 5 Jan 2021 00:56:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2CE4D22573 for ; Tue, 5 Jan 2021 00:56:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727485AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: from mail.kernel.org ([198.145.29.99]:38144 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726163AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3073022583; Tue, 5 Jan 2021 00:55:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808108; bh=WAClBs5Ob3X5/nQlX8DZm6OroHf7WCCbiACDxf5M2ho=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=C0Ghy59D3T6p16o0qRJhp5hBAinTsVREzKCRuF7Jexv31PEsxUz1Fkxdd/Mof9wSK fyfqBNgrAPiRUcsY3ifcjZVXzeinTyrayvQMhWzDvHJiH2r3CfCYhm3KrNTVDTZnBo bUJR6Loxr7pNTO0yjgTEhy1nARTJGZ8vaOjeEfZyRtTh0e//SbJcw1j7GDewwWhsAW 2pKs7GeBbCtgUdPQi6M79OUMkgyGH/n1tVqn9mhaFcMZyePjTyPKcgVDLU1ZshD7dp IbJNbhKZau1h/1qm5RFLnnA4oBezHm6HRZmWBOwaXMBkyuprg1GjTaH1+R65Lyez0x 2Wi5IaPeb84wg== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 05/13] fs: don't call ->dirty_inode for lazytime timestamp updates Date: Mon, 4 Jan 2021 16:54:44 -0800 Message-Id: <20210105005452.92521-6-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers There is no need to call ->dirty_inode for lazytime timestamp updates (i.e. for __mark_inode_dirty(I_DIRTY_TIME)), since by the definition of lazytime, filesystems must ignore these updates. Filesystems only need to care about the updated timestamps when they expire. Therefore, only call ->dirty_inode when I_DIRTY_INODE is set. Based on a patch from Christoph Hellwig: https://lore.kernel.org/r/20200325122825.1086872-4-hch@lst.de Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- fs/ext4/inode.c | 12 +----------- fs/f2fs/super.c | 3 --- fs/fs-writeback.c | 6 +++--- fs/gfs2/super.c | 2 -- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 27946882d4ce4..4cc6c7834312f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5933,26 +5933,16 @@ int __ext4_mark_inode_dirty(handle_t *handle, struct inode *inode, * If the inode is marked synchronous, we don't honour that here - doing * so would cause a commit on atime updates, which we don't bother doing. * We handle synchronous inodes at the highest possible level. - * - * If only the I_DIRTY_TIME flag is set, we can skip everything. If - * I_DIRTY_TIME and I_DIRTY_SYNC is set, the only inode fields we need - * to copy into the on-disk inode structure are the timestamp files. */ void ext4_dirty_inode(struct inode *inode, int flags) { handle_t *handle; - if (flags == I_DIRTY_TIME) - return; handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); if (IS_ERR(handle)) - goto out; - + return; ext4_mark_inode_dirty(handle, inode); - ext4_journal_stop(handle); -out: - return; } int ext4_change_inode_journal_flag(struct inode *inode, int val) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index b4a07fe62d1a5..cc98dc49f4a26 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1196,9 +1196,6 @@ static void f2fs_dirty_inode(struct inode *inode, int flags) inode->i_ino == F2FS_META_INO(sbi)) return; - if (flags == I_DIRTY_TIME) - return; - if (is_inode_flag_set(inode, FI_AUTO_RECOVER)) clear_inode_flag(inode, FI_AUTO_RECOVER); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 081e335cdee47..e3347fd6eb13a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -2264,16 +2264,16 @@ void __mark_inode_dirty(struct inode *inode, int flags) * Don't do this for I_DIRTY_PAGES - that doesn't actually * dirty the inode itself */ - if (flags & (I_DIRTY_INODE | I_DIRTY_TIME)) { + if (flags & I_DIRTY_INODE) { trace_writeback_dirty_inode_start(inode, flags); if (sb->s_op->dirty_inode) sb->s_op->dirty_inode(inode, flags); trace_writeback_dirty_inode(inode, flags); - } - if (flags & I_DIRTY_INODE) + flags &= ~I_DIRTY_TIME; + } dirtytime = flags & I_DIRTY_TIME; /* diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 2f56acc41c049..042b94288ff11 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -562,8 +562,6 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) int need_endtrans = 0; int ret; - if (!(flags & I_DIRTY_INODE)) - return; if (unlikely(gfs2_withdrawn(sdp))) return; if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { From patchwork Tue Jan 5 00:54:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997857 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 085C6C433E9 for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C94852253A for ; Tue, 5 Jan 2021 00:56:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727706AbhAEA4a (ORCPT ); Mon, 4 Jan 2021 19:56:30 -0500 Received: from mail.kernel.org ([198.145.29.99]:38146 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726300AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7EF6622597; Tue, 5 Jan 2021 00:55:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808108; bh=B3Emt5qB2uZqLRLG8UPggA6U0YAB7if9iFbujwsgEtM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kcKIh2C2h0ZA6sQb9/5a4jo57dRI1gFr+nnAqwgx0WF8ercDa72h65pmp3xBQqNBt PHdc/BfTzNbg7N5rZeIB9wH3sIQt4rojBNfOipI5vFrpqNzSfwmMPCzOZiynTibMWT qPKTGX4EoB+fcFap1ApNiflAALtI5jlR1T1xYXF641p4Y4LgIfGrKHNzxIosVL4Qea qClPYIhNsF1iP4jslUeXVTHZRs9fr/WxbvUUQFFk9SgDxNUY8DTlclSx1yF8hb6Xv0 0Mw3amjUyNtTKRKf4WKFbEb42i4la9OwlyYXq9Nb72cJ8HkRCxiVbw/yEKwtW9g8NZ 6n45MNQyj4grg== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 06/13] fs: pass only I_DIRTY_INODE flags to ->dirty_inode Date: Mon, 4 Jan 2021 16:54:45 -0800 Message-Id: <20210105005452.92521-7-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers ->dirty_inode is now only called when I_DIRTY_INODE (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) is set. However it may still be passed other dirty flags at the same time, provided that these other flags happened to be passed to __mark_inode_dirty() at the same time as I_DIRTY_INODE. This doesn't make sense because there is no reason for filesystems to care about these extra flags. Nor are filesystems notified about all updates to these other flags. Therefore, mask the flags before passing them to ->dirty_inode. Also properly document ->dirty_inode in vfs.rst. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- Documentation/filesystems/vfs.rst | 5 ++++- fs/fs-writeback.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index ca52c82e5bb54..287b80948a40b 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -270,7 +270,10 @@ or bottom half). ->alloc_inode. ``dirty_inode`` - this method is called by the VFS to mark an inode dirty. + this method is called by the VFS when an inode is marked dirty. + This is specifically for the inode itself being marked dirty, + not its data. If the update needs to be persisted by fdatasync(), + then I_DIRTY_DATASYNC will be set in the flags argument. ``write_inode`` this method is called when the VFS needs to write an inode to diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e3347fd6eb13a..f20daf4f5e19b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -2268,7 +2268,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) trace_writeback_dirty_inode_start(inode, flags); if (sb->s_op->dirty_inode) - sb->s_op->dirty_inode(inode, flags); + sb->s_op->dirty_inode(inode, flags & I_DIRTY_INODE); trace_writeback_dirty_inode(inode, flags); From patchwork Tue Jan 5 00:54:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997861 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5FE61C4332D for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4216522581 for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727677AbhAEA4a (ORCPT ); Mon, 4 Jan 2021 19:56:30 -0500 Received: from mail.kernel.org ([198.145.29.99]:38148 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726329AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id CD664225AA; Tue, 5 Jan 2021 00:55:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808109; bh=H1ms59/bip1WURh53Z2hT3TghGoA+Y1uZAJZTjqPVbA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jT5YHwMUgMCR7wlwaRdowKZM9R6gvPc5q8QsYcKqluLVv9qzVzb5ZLYpj+8BJinTA 1tYt5wwFZVp0RDAxpBlc63HhVpNF5Rk3zgXbvdiFBSWfIpLrDX8Mmfq1MVoz9YClb1 9Gr2aATxyaLdxZqNOHjdmFblPWbRTyzC/RA158eyh4sD8Aa3guZw/r8EudMGbINKUJ w+1wvYWfRCLiPz4E7Qnid8lt7OG7jDwfbEzObQJGnso821wgCnsJYkDVJxNx555AOD 74UKgJtYKhCO2Xw93w+7ZABhUKMlAxqRerT5DGy3IKUeXa5hwHmJYWfpjPMb/kOHAy 7Gqk1iDUurBeg== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 07/13] fs: correctly document the inode dirty flags Date: Mon, 4 Jan 2021 16:54:46 -0800 Message-Id: <20210105005452.92521-8-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers The documentation for I_DIRTY_SYNC and I_DIRTY_DATASYNC is a bit misleading, and I_DIRTY_TIME isn't documented at all. Fix this. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- include/linux/fs.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index fd47deea7c176..45a0303b2aeb6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2084,8 +2084,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, /* * Inode state bits. Protected by inode->i_lock * - * Three bits determine the dirty state of the inode, I_DIRTY_SYNC, - * I_DIRTY_DATASYNC and I_DIRTY_PAGES. + * Four bits determine the dirty state of the inode: I_DIRTY_SYNC, + * I_DIRTY_DATASYNC, I_DIRTY_PAGES, and I_DIRTY_TIME. * * Four bits define the lifetime of an inode. Initially, inodes are I_NEW, * until that flag is cleared. I_WILL_FREE, I_FREEING and I_CLEAR are set at @@ -2094,12 +2094,20 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * Two bits are used for locking and completion notification, I_NEW and I_SYNC. * * I_DIRTY_SYNC Inode is dirty, but doesn't have to be written on - * fdatasync(). i_atime is the usual cause. - * I_DIRTY_DATASYNC Data-related inode changes pending. We keep track of + * fdatasync() (unless I_DIRTY_DATASYNC is also set). + * Timestamp updates are the usual cause. + * I_DIRTY_DATASYNC Data-related inode changes pending. We keep track of * these changes separately from I_DIRTY_SYNC so that we * don't have to write inode on fdatasync() when only - * mtime has changed in it. + * e.g. the timestamps have changed. * I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean. + * I_DIRTY_TIME The inode itself only has dirty timestamps, and the + * lazytime mount option is enabled. We keep track of this + * separately from I_DIRTY_SYNC in order to implement + * lazytime. This gets cleared if I_DIRTY_INODE + * (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. I.e. + * either I_DIRTY_TIME *or* I_DIRTY_INODE can be set in + * i_state, but not both. I_DIRTY_PAGES may still be set. * I_NEW Serves as both a mutex and completion notification. * New inodes set I_NEW. If two processes both create * the same inode, one of them will release its inode and From patchwork Tue Jan 5 00:54:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997867 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 67EB1C43603 for ; Tue, 5 Jan 2021 00:56:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4756C2253A for ; Tue, 5 Jan 2021 00:56:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727584AbhAEA43 (ORCPT ); Mon, 4 Jan 2021 19:56:29 -0500 Received: from mail.kernel.org ([198.145.29.99]:38150 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726124AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 28656225A9; Tue, 5 Jan 2021 00:55:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808109; bh=Ad7xLAZQk7GaC9BkYrLopltjaA0micO7CKVPyWiuAIc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a9pN6k7eZWDzKxMNTAL16e24puJANBJqgUATkSeVAFTD1NZ47idpUHJlSPEqpBGkK UqoR0jDQJOR+ODkJotclMYzN9qCk1aAU0iTIOL/17YsRFdJzHij3FPqqu6srKMpgnK lcEM7vhAEfE+jrUnJyv5rdeTitXFHJKs6xmCvuKB/adz9aAiENsqhnSa3YyytLjVem nXDWtC3fxXJqwb4wXSh5nX2URUIYWMazymEm3+pfyQZcF2nmpB+fVPZM5uZW2d7Sz/ igWIQnJAFW8cLT0v2qBsM+KXzZWW25sbQYF2d1mkJqke9RyEBq3TuiZ0lSbTFEMlUi Zk5ZRbFXOQr8g== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 08/13] ext4: simplify i_state checks in __ext4_update_other_inode_time() Date: Mon, 4 Jan 2021 16:54:47 -0800 Message-Id: <20210105005452.92521-9-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers Since I_DIRTY_TIME and I_DIRTY_INODE are mutually exclusive in i_state, there's no need to check for I_DIRTY_TIME && !I_DIRTY_INODE. Just check for I_DIRTY_TIME. Signed-off-by: Eric Biggers --- fs/ext4/inode.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 4cc6c7834312f..9e34541715968 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4962,14 +4962,12 @@ static void __ext4_update_other_inode_time(struct super_block *sb, return; if ((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | - I_DIRTY_INODE)) || - ((inode->i_state & I_DIRTY_TIME) == 0)) + I_DIRTY_TIME)) != I_DIRTY_TIME) return; spin_lock(&inode->i_lock); - if (((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | - I_DIRTY_INODE)) == 0) && - (inode->i_state & I_DIRTY_TIME)) { + if ((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | + I_DIRTY_TIME)) != I_DIRTY_TIME) { struct ext4_inode_info *ei = EXT4_I(inode); inode->i_state &= ~I_DIRTY_TIME; From patchwork Tue Jan 5 00:54:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997873 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6683C43332 for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8509A22581 for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727649AbhAEA43 (ORCPT ); Mon, 4 Jan 2021 19:56:29 -0500 Received: from mail.kernel.org ([198.145.29.99]:38152 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726330AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 775A0225AB; Tue, 5 Jan 2021 00:55:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808109; bh=msnnxCLzPo2DYdIqcuEghPRawTGVOjAsHU3RAs/RXao=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hohi5mOdPwavJo+wbNII2B4bRm29y9bMy1xU4F+Jc0L/sOVNQ1trYDZZpnkX/WiPg TZokPX7i3KW5A6qMfqYlNo0CcI4aybTOLGBHD9wALvx1J8DilxPMxmG3OwPBUTAMAq 0Pbedq2YIJ2graQdydC7vnPV+w6iIgMnjZsfkqTsB/VMVQxPK6Htv4EA6AmuM1xkx5 PzYgNOn1ozvjDbtHlotxJRK4GJ78x9ldPbO601uaEuWL7bOkgs6ZlhoOzeSfPOQLR2 J2wtQdpijkV8cUN03mkDjecwwx0fXpzgLuJf2qx6Y35nJ4YPTU6rBdU5fH2Mfa91Mj tiXtmTpPToffA== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 09/13] fs: drop redundant checks from __writeback_single_inode() Date: Mon, 4 Jan 2021 16:54:48 -0800 Message-Id: <20210105005452.92521-10-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers I_DIRTY_TIME and I_DIRTY_INODE are mutually exclusive in i_state. So after seeing that I_DIRTY_TIME is set, there's no point in checking for I_DIRTY_INODE, as it must be clear. Separately, wbc->for_sync implies wbc->sync_mode == WB_SYNC_ALL. So there's no need to check for both. Just check for WB_SYNC_ALL. Signed-off-by: Eric Biggers --- fs/fs-writeback.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f20daf4f5e19b..3f5a589399afe 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1482,8 +1482,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) dirty = inode->i_state & I_DIRTY; if ((inode->i_state & I_DIRTY_TIME) && - ((dirty & I_DIRTY_INODE) || - wbc->sync_mode == WB_SYNC_ALL || wbc->for_sync || + (wbc->sync_mode == WB_SYNC_ALL || time_after(jiffies, inode->dirtied_time_when + dirtytime_expire_interval * HZ))) { dirty |= I_DIRTY_TIME; From patchwork Tue Jan 5 00:54:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997865 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03FABC4361A for ; Tue, 5 Jan 2021 00:56:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DCBC52256F for ; Tue, 5 Jan 2021 00:56:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727773AbhAEA4j (ORCPT ); Mon, 4 Jan 2021 19:56:39 -0500 Received: from mail.kernel.org ([198.145.29.99]:38154 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726397AbhAEA42 (ORCPT ); Mon, 4 Jan 2021 19:56:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id C5ED0225AC; Tue, 5 Jan 2021 00:55:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808110; bh=3+FH0Che1vvUp1b6v2ElJrJMrgmUrdCi08gAUpQUvaM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vKszdOoUHBXD4lFIk+ly6Zo/bQh1PREYUNt4Btl8oOXy4yCtVIQkPdYgJp5YWRZ8O 7ZVZrhZMUUDLrWnM36P2v8D5hJgH4CCNQdqBrybbQs5udOZJTMAaLWnVmjAylr0cXD Mtvagss0HxuRq9jevJnR6blxmewNJWpnzwYsnqWMdio9/TdmAFNpWoQ6E5ZPbWQJLu NEQ9lR8x5T1AuSXIIzc5SpY9ZbEICahdk95u0GuUrpO7hhx5e9bNxuSCEEu7ggVqfj dDnommsWbX4jY4koZ1KfmXM3BtX/IVnlxdoiM7iNExZyRU/xz4LtTsPaRmecwwm8yX AizzRzc68km7Q== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 10/13] fs: clean up __mark_inode_dirty() a bit Date: Mon, 4 Jan 2021 16:54:49 -0800 Message-Id: <20210105005452.92521-11-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers Improve some comments, and don't bother checking for the I_DIRTY_TIME flag in the case where we just cleared it. Also, warn if I_DIRTY_TIME and I_DIRTY_PAGES are passed to __mark_inode_dirty() at the same time, as this case isn't handled. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- fs/fs-writeback.c | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 3f5a589399afe..ed76112bd067b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -2227,23 +2227,24 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode) } /** - * __mark_inode_dirty - internal function + * __mark_inode_dirty - internal function to mark an inode dirty * * @inode: inode to mark - * @flags: what kind of dirty (i.e. I_DIRTY_SYNC) + * @flags: what kind of dirty, e.g. I_DIRTY_SYNC. This can be a combination of + * multiple I_DIRTY_* flags, except that I_DIRTY_TIME can't be combined + * with I_DIRTY_PAGES. * - * Mark an inode as dirty. Callers should use mark_inode_dirty or - * mark_inode_dirty_sync. + * Mark an inode as dirty. We notify the filesystem, then update the inode's + * dirty flags. Then, if needed we add the inode to the appropriate dirty list. * - * Put the inode on the super block's dirty list. + * Most callers should use mark_inode_dirty() or mark_inode_dirty_sync() + * instead of calling this directly. * - * CAREFUL! We mark it dirty unconditionally, but move it onto the - * dirty list only if it is hashed or if it refers to a blockdev. - * If it was not hashed, it will never be added to the dirty list - * even if it is later hashed, as it will have been marked dirty already. + * CAREFUL! We only add the inode to the dirty list if it is hashed or if it + * refers to a blockdev. Unhashed inodes will never be added to the dirty list + * even if they are later hashed, as they will have been marked dirty already. * - * In short, make sure you hash any inodes _before_ you start marking - * them dirty. + * In short, ensure you hash any inodes _before_ you start marking them dirty. * * Note that for blockdevs, inode->dirtied_when represents the dirtying time of * the block-special inode (/dev/hda1) itself. And the ->dirtied_when field of @@ -2255,25 +2256,34 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode) void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block *sb = inode->i_sb; - int dirtytime; + int dirtytime = 0; trace_writeback_mark_inode_dirty(inode, flags); - /* - * Don't do this for I_DIRTY_PAGES - that doesn't actually - * dirty the inode itself - */ if (flags & I_DIRTY_INODE) { + /* + * Notify the filesystem about the inode being dirtied, so that + * (if needed) it can update on-disk fields and journal the + * inode. This is only needed when the inode itself is being + * dirtied now. I.e. it's only needed for I_DIRTY_INODE, not + * for just I_DIRTY_PAGES or I_DIRTY_TIME. + */ trace_writeback_dirty_inode_start(inode, flags); - if (sb->s_op->dirty_inode) sb->s_op->dirty_inode(inode, flags & I_DIRTY_INODE); - trace_writeback_dirty_inode(inode, flags); + /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */ flags &= ~I_DIRTY_TIME; + } else { + /* + * Else it's either I_DIRTY_PAGES, I_DIRTY_TIME, or nothing. + * (We don't support setting both I_DIRTY_PAGES and I_DIRTY_TIME + * in one call to __mark_inode_dirty().) + */ + dirtytime = flags & I_DIRTY_TIME; + WARN_ON_ONCE(dirtytime && (flags != I_DIRTY_TIME)); } - dirtytime = flags & I_DIRTY_TIME; /* * Paired with smp_mb() in __writeback_single_inode() for the @@ -2296,6 +2306,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) inode_attach_wb(inode, NULL); + /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */ if (flags & I_DIRTY_INODE) inode->i_state &= ~I_DIRTY_TIME; inode->i_state |= flags; From patchwork Tue Jan 5 00:54:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997863 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00E7AC43217 for ; Tue, 5 Jan 2021 00:56:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C8ECE2256F for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727732AbhAEA4d (ORCPT ); Mon, 4 Jan 2021 19:56:33 -0500 Received: from mail.kernel.org ([198.145.29.99]:38156 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726163AbhAEA43 (ORCPT ); Mon, 4 Jan 2021 19:56:29 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2125022795; Tue, 5 Jan 2021 00:55:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808110; bh=91nSgZ2cvoIYG1Sebm39KD0W1P3OHtZXEBiBRQSeSKg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AiyfOoiEUs47PBjYYdnORuK5+uyNq9T8K8/rkbum//GtR0qLlsNmATSz0GknR9uxI hhBh+NHGfpYpkLHyjyml0/s2c9aJpOcQTCypFznxjYrQsk/HMBYos74Ei/IKLTNBnW EM7hmKuB0nw4oDbMf9dMWQvLDDomfah/68XFK+GDt/xQ6mE75eAzulS0S9MGGLuHaH YNyTtAWatP4RylXTOgeG/yp9/Q6IXq2gUeU/9I4uMZNtVOI2N0aVxEoVYyfLNFJdY4 mvzW2ghf4yJN1ajl6Si45GsVbN9q9fnJlz6sc8OjQ0DeHLAwmluvEtUpFCTFZXdiBF hNbeXGrt4lCJQ== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 11/13] fs: add a lazytime_expired method Date: Mon, 4 Jan 2021 16:54:50 -0800 Message-Id: <20210105005452.92521-12-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers Add a lazytime_expired method to 'struct super_operations'. Filesystems can implement this to be notified when an inode's lazytime timestamps have expired and need to be written to disk. This avoids any potential ambiguity with ->dirty_inode(inode, I_DIRTY_SYNC), which can also mean a generic dirtying of the inode, not just a lazytime timestamp expiration. In particular, this will be useful for XFS. If not implemented, then ->dirty_inode(inode, I_DIRTY_SYNC) continues to be called. Note that there are three cases where we have to make sure to call lazytime_expired(): - __writeback_single_inode(): inode is being written now - vfs_fsync_range(): inode is going to be synced - iput(): inode is going to be evicted In the latter two cases, the inode still needs to be put on the writeback list. So, we can't just replace the calls to mark_inode_dirty_sync() with lazytime_expired(). Instead, add a new flag I_DIRTY_TIME_EXPIRED which can be passed to __mark_inode_dirty(). It's like I_DIRTY_SYNC, except it causes the filesystem to be notified of a lazytime expiration rather than a generic I_DIRTY_SYNC. Signed-off-by: Eric Biggers --- Documentation/filesystems/locking.rst | 2 ++ Documentation/filesystems/vfs.rst | 10 ++++++++++ fs/fs-writeback.c | 27 ++++++++++++++++++++++----- fs/inode.c | 2 +- fs/sync.c | 2 +- include/linux/fs.h | 7 ++++++- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst index c0f2c7586531b..53088e2a93b69 100644 --- a/Documentation/filesystems/locking.rst +++ b/Documentation/filesystems/locking.rst @@ -150,6 +150,7 @@ prototypes:: void (*free_inode)(struct inode *); void (*destroy_inode)(struct inode *); void (*dirty_inode) (struct inode *, int flags); + void (*lazytime_expired) (struct inode *); int (*write_inode) (struct inode *, struct writeback_control *wbc); int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); @@ -175,6 +176,7 @@ alloc_inode: free_inode: called from RCU callback destroy_inode: dirty_inode: +lazytime_expired: write_inode: drop_inode: !!!inode->i_lock!!! evict_inode: diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index 287b80948a40b..02531b1421d01 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -231,6 +231,7 @@ filesystem. As of kernel 2.6.22, the following members are defined: void (*destroy_inode)(struct inode *); void (*dirty_inode) (struct inode *, int flags); + void (*lazytime_expired) (struct inode *); int (*write_inode) (struct inode *, int); void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); @@ -275,6 +276,15 @@ or bottom half). not its data. If the update needs to be persisted by fdatasync(), then I_DIRTY_DATASYNC will be set in the flags argument. +``lazytime_expired`` + when the lazytime mount option is enabled, this method is + called when an inode's in-memory updated timestamps have + expired and thus need to be written to disk. This happens + when the timestamps have been in memory for too long, when the + inode is going to be evicted, or when userspace triggers a + sync. If this method is not implemented, then + ->dirty_inode(inode, I_DIRTY_SYNC) is called instead. + ``write_inode`` this method is called when the VFS needs to write an inode to disc. The second parameter indicates whether the write should diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ed76112bd067b..f187fc3f854e4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1441,6 +1441,14 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, } } +static void lazytime_expired(struct inode *inode) +{ + if (inode->i_sb->s_op->lazytime_expired) + inode->i_sb->s_op->lazytime_expired(inode); + else if (inode->i_sb->s_op->dirty_inode) + inode->i_sb->s_op->dirty_inode(inode, I_DIRTY_SYNC); +} + /* * Write out an inode and its dirty pages. Do not update the writeback list * linkage. That is left to the caller. The caller is also responsible for @@ -1520,8 +1528,8 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) * isn't enough. Don't call mark_inode_dirty_sync(), as that * would put the inode back on the dirty list. */ - if ((dirty & I_DIRTY_TIME) && inode->i_sb->s_op->dirty_inode) - inode->i_sb->s_op->dirty_inode(inode, I_DIRTY_SYNC); + if (dirty & I_DIRTY_TIME) + lazytime_expired(inode); err = write_inode(inode, wbc); if (ret == 0) @@ -2231,8 +2239,9 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode) * * @inode: inode to mark * @flags: what kind of dirty, e.g. I_DIRTY_SYNC. This can be a combination of - * multiple I_DIRTY_* flags, except that I_DIRTY_TIME can't be combined - * with I_DIRTY_PAGES. + * multiple I_DIRTY_* flags, except that: + * - I_DIRTY_TIME can't be combined with I_DIRTY_PAGES + * - I_DIRTY_TIME_EXPIRED must be used by itself * * Mark an inode as dirty. We notify the filesystem, then update the inode's * dirty flags. Then, if needed we add the inode to the appropriate dirty list. @@ -2260,7 +2269,15 @@ void __mark_inode_dirty(struct inode *inode, int flags) trace_writeback_mark_inode_dirty(inode, flags); - if (flags & I_DIRTY_INODE) { + if (flags & I_DIRTY_TIME_EXPIRED) { + /* + * Notify the filesystem about a lazytime timestamp expiration. + * Afterwards, this case just turns into I_DIRTY_SYNC. + */ + WARN_ON_ONCE(flags & ~I_DIRTY_TIME_EXPIRED); + lazytime_expired(inode); + flags = I_DIRTY_SYNC; + } else if (flags & I_DIRTY_INODE) { /* * Notify the filesystem about the inode being dirtied, so that * (if needed) it can update on-disk fields and journal the diff --git a/fs/inode.c b/fs/inode.c index d0fa43d8e9d5c..039b201a4743a 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1673,7 +1673,7 @@ void iput(struct inode *inode) atomic_inc(&inode->i_count); spin_unlock(&inode->i_lock); trace_writeback_lazytime_iput(inode); - mark_inode_dirty_sync(inode); + __mark_inode_dirty(inode, I_DIRTY_TIME_EXPIRED); goto retry; } iput_final(inode); diff --git a/fs/sync.c b/fs/sync.c index 1373a610dc784..363071a3528e3 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -196,7 +196,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) if (!file->f_op->fsync) return -EINVAL; if (!datasync && (inode->i_state & I_DIRTY_TIME)) - mark_inode_dirty_sync(inode); + __mark_inode_dirty(inode, I_DIRTY_TIME_EXPIRED); return file->f_op->fsync(file, start, end, datasync); } EXPORT_SYMBOL(vfs_fsync_range); diff --git a/include/linux/fs.h b/include/linux/fs.h index 45a0303b2aeb6..8c5f5c5e62be4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1935,7 +1935,8 @@ struct super_operations { void (*destroy_inode)(struct inode *); void (*free_inode)(struct inode *); - void (*dirty_inode) (struct inode *, int flags); + void (*dirty_inode) (struct inode *, int flags); + void (*lazytime_expired)(struct inode *); int (*write_inode) (struct inode *, struct writeback_control *wbc); int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); @@ -2108,6 +2109,9 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. I.e. * either I_DIRTY_TIME *or* I_DIRTY_INODE can be set in * i_state, but not both. I_DIRTY_PAGES may still be set. + * I_DIRTY_TIME_EXPIRED Passed to __mark_inode_dirty() to indicate the intent to + * expire the inode's timestamps. Not stored in i_state. + * * I_NEW Serves as both a mutex and completion notification. * New inodes set I_NEW. If two processes both create * the same inode, one of them will release its inode and @@ -2173,6 +2177,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_DIO_WAKEUP (1 << __I_DIO_WAKEUP) #define I_LINKABLE (1 << 10) #define I_DIRTY_TIME (1 << 11) +#define I_DIRTY_TIME_EXPIRED (1 << 12) #define I_WB_SWITCH (1 << 13) #define I_OVL_INUSE (1 << 14) #define I_CREATING (1 << 15) From patchwork Tue Jan 5 00:54:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997869 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7396C4361B for ; Tue, 5 Jan 2021 00:56:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9006722573 for ; Tue, 5 Jan 2021 00:56:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727748AbhAEA4h (ORCPT ); Mon, 4 Jan 2021 19:56:37 -0500 Received: from mail.kernel.org ([198.145.29.99]:38158 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726168AbhAEA43 (ORCPT ); Mon, 4 Jan 2021 19:56:29 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 6F647227BF; Tue, 5 Jan 2021 00:55:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808110; bh=gNmDYe2Lw3Moz7fSm4TY9dr/5OhIQas+i4KMcztjpdA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Iue5bgzUAw8lnkQhxntcvGe1ceXoW5GSJWYIHh3cLSi/unfeetrDIk3AEiLSYzXXM YRQ0yms8cM/fhbIoNhu2BFHmIxs1KHKry2eno50f0+As0LpEMAFdE2jzEK6/I+t79x q1xCXE9vM0AMyX4uOGz6HuPfUF9wxnuqjDGTfduCP/T8y+CI8WNZF+C6o8JGDmDuRb 6XujVxKjL7yeDT5YHWoAHOi3U46i46aTw1Z6B/hNUFzMJq+9EuadYpNdInK2x1Ora2 NDZjswrQjIOKf9F0DW31SasqoFVgS7ALAcH8xEZ6GQAEgUhyFzB2AoBeG23brpfA7v i9mSTRbrzfsTA== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 12/13] xfs: remove a stale comment from xfs_file_aio_write_checks() Date: Mon, 4 Jan 2021 16:54:51 -0800 Message-Id: <20210105005452.92521-13-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers The comment in xfs_file_aio_write_checks() about calling file_modified() after dropping the ilock doesn't make sense, because the code that unconditionally acquires and drops the ilock was removed by commit 467f78992a07 ("xfs: reduce ilock hold times in xfs_file_aio_write_checks"). Remove this outdated comment. Signed-off-by: Eric Biggers Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 5b0f93f738372..4927c6653f15d 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -389,12 +389,6 @@ xfs_file_aio_write_checks( } else spin_unlock(&ip->i_flags_lock); - /* - * Updating the timestamps will grab the ilock again from - * xfs_fs_dirty_inode, so we have to call it after dropping the - * lock above. Eventually we should look into a way to avoid - * the pointless lock roundtrip. - */ return file_modified(file); } From patchwork Tue Jan 5 00:54:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 11997859 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 390B0C4332B for ; Tue, 5 Jan 2021 00:56:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F0AA322583 for ; Tue, 5 Jan 2021 00:56:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727711AbhAEA4a (ORCPT ); Mon, 4 Jan 2021 19:56:30 -0500 Received: from mail.kernel.org ([198.145.29.99]:38160 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727514AbhAEA43 (ORCPT ); Mon, 4 Jan 2021 19:56:29 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id BE7C122955; Tue, 5 Jan 2021 00:55:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1609808110; bh=SwwC2tQmuzx2ECIC/aYAUe8sOHWx78XkiAxTAUcoLvs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Srdu4HxF1Bb9lEnR7JzmGw/pdJjgAOcpxaS4Evh8wreQR3/eN7eUek7cPFXHkcOaX lP184SXS2dHBX1l/m6Xd4qXPeYU4JGmMqZHXpHz/62wMMlOf0dL21hMP0mh4xZFYrV 9JXvXG7cNpFUn1xaxZHWtAbrVZdWzyWRe2/n4Mz0NBqC0ZpRVkCsF4zucS4Bgq4luo SMClFaef9S/mS8BcRvOz3HVeAsvDIYQWYC6Gbxjt2fQ65CbGPeOopGXTTzKkT9UQTb l9n/P27mrwnTgHDHwtEkxO2GafO5eYYSKRVI3erirNDRVNH1/EGucH2wSlAOpnUTan rUAdXIJZ1qfcw== From: Eric Biggers To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-xfs@vger.kernel.org, Theodore Ts'o , Christoph Hellwig Subject: [PATCH 13/13] xfs: implement lazytime_expired Date: Mon, 4 Jan 2021 16:54:52 -0800 Message-Id: <20210105005452.92521-14-ebiggers@kernel.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210105005452.92521-1-ebiggers@kernel.org> References: <20210105005452.92521-1-ebiggers@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers Implement the new ->lazytime_expired method to get notified of lazytime timestamp expirations, instead of relying on ->dirty_inode(inode, I_DIRTY_SYNC) which is potentially ambiguous. This fixes a bug where XFS didn't write lazytime timestamps to disk upon a sync(), or after 24 hours (dirtytime_expire_interval * 2). This is because it only wrote the timestamps if I_DIRTY_TIME was set in i_state. But actually when an inode's timestamps expire without the inode being marked I_DIRTY_SYNC first, then ->dirty_inode isn't called until __writeback_single_inode() has already cleared I_DIRTY_TIME in i_state. The new ->lazytime_expired method is unambiguous, so it removes any need to check for I_DIRTY_TIME, which avoids this bug. I've written an xfstest which reproduces this bug. Fixes: c3b1b13190ae ("xfs: implement the lazytime mount option") Signed-off-by: Eric Biggers --- fs/xfs/xfs_super.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 813be879a5e51..0b7623907b264 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -666,19 +666,13 @@ xfs_fs_destroy_inode( } static void -xfs_fs_dirty_inode( - struct inode *inode, - int flag) +xfs_fs_lazytime_expired( + struct inode *inode) { struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; - if (!(inode->i_sb->s_flags & SB_LAZYTIME)) - return; - if (flag != I_DIRTY_SYNC || !(inode->i_state & I_DIRTY_TIME)) - return; - if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp)) return; xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -1108,7 +1102,7 @@ xfs_fs_free_cached_objects( static const struct super_operations xfs_super_operations = { .alloc_inode = xfs_fs_alloc_inode, .destroy_inode = xfs_fs_destroy_inode, - .dirty_inode = xfs_fs_dirty_inode, + .lazytime_expired = xfs_fs_lazytime_expired, .drop_inode = xfs_fs_drop_inode, .put_super = xfs_fs_put_super, .sync_fs = xfs_fs_sync_fs,