Received: by 2002:ac0:e350:0:0:0:0:0 with SMTP id g16csp287185imn; Wed, 3 Aug 2022 03:58:27 -0700 (PDT) X-Google-Smtp-Source: AA6agR7J3bg2kmaH6JtV+zzb4Wy8HjwWI0FtiwfgJqylyjTTfw0pNB+qIXzMtF6y80D/8goWBUfP X-Received: by 2002:a17:902:d50a:b0:16e:e1c1:dfa7 with SMTP id b10-20020a170902d50a00b0016ee1c1dfa7mr15825439plg.160.1659524297548; Wed, 03 Aug 2022 03:58:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659524297; cv=none; d=google.com; s=arc-20160816; b=Ui//V+oewJJckq2sHPeskeG7kYcTewcC/FGsWTGASAMJJttn0cjPhVXWJ+/VokIvz4 26iBZqXmfZnEPTJJHcqlyjc2DncPRD/+xafUcW7LD6jKJVDGoEAyAV1XpMa5JGMs1Btq y9h4dDNV0ZDJiLl74tUUIlW6x4zcoWVnAyrAs4nBmX35cWq7aJrZM7WKS7gE9C4N0D/x K7AJHiA8zh3XH+JQXFW6Z2QTS2SomPwjcxbRlAaTWeCGRglen7cHkIRHNqzkquwAR/0/ nHo66P/SSUKKyNehwVPTXI2V/QxDPHPj/tCNTyfmMNsjx4FBl8KED9KCEwFs5hkeuCb0 yjOw== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=doXYw7E5VLvw7n6vVIR09pFS1doVs35mgegqvhxvfjA=; b=T+vHgU6bvcbeXah0HEZBGyPIPKVhGUoSMxpaY1Oq8BgM3AQRKw0/xx5jZp7MoV6cHb aUN39F30HgUIoiRv4LLgV6CrsjQhTsBRxj7XcdVORwj6AUXkAcpfBpS9tBY9p4s03Io8 iw5elGD9VFDSVXln0I7d+NwdSe+ZWfqiNs2OuwJQCWO6/+g9psHvc+oyoF1lwvsuI6b8 yl/4uB765MCGmfNZmFnCpvavoNmVNqFWDT67nL3s5VTiA+zx1WJ1JGSlFH6UTv1CyZ9A m8Hs5LHjj/iiLZA43geE/VnHveS6NRUZIewSDbAKpHlb+LNkr85vMh1pblodgeLKGWcT zqpg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SsYspZvx; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g130-20020a636b88000000b0040cb27906cbsi16980842pgc.464.2022.08.03.03.57.51; Wed, 03 Aug 2022 03:58:17 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-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=@redhat.com header.s=mimecast20190719 header.b=SsYspZvx; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232663AbiHCKxs (ORCPT + 99 others); Wed, 3 Aug 2022 06:53:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235626AbiHCKxr (ORCPT ); Wed, 3 Aug 2022 06:53:47 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 093721C922 for ; Wed, 3 Aug 2022 03:53:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659524025; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=doXYw7E5VLvw7n6vVIR09pFS1doVs35mgegqvhxvfjA=; b=SsYspZvx7DsZZqR1tAtWGBJJzsuOrHMP0KNSxhz7wCdM0uj8rS6Daq4PEcunzUMjuasOKC YH4162p5tQccgJYOfX7+XERpOiCm1k4pFy2dhhW1TUyGlb2Xr6AiFbbV1WbW1oSBOp31E/ RjWlFmdAcx7k5lFn1+SKPchRoTwJKhY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-655-ck28BSQ-PAaolYdadZAu1Q-1; Wed, 03 Aug 2022 06:53:43 -0400 X-MC-Unique: ck28BSQ-PAaolYdadZAu1Q-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 625F0185A7B2; Wed, 3 Aug 2022 10:53:43 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.40.194.92]) by smtp.corp.redhat.com (Postfix) with ESMTP id 35CC91121314; Wed, 3 Aug 2022 10:53:42 +0000 (UTC) From: Lukas Czerner To: linux-ext4@vger.kernel.org Cc: jlayton@kernel.org, tytso@mit.edu, linux-fsdevel@vger.kernel.org, Dave Chinner , Christoph Hellwig , Jan Kara Subject: [PATCH v2 2/3] fs: record I_DIRTY_TIME even if inode already has I_DIRTY_INODE Date: Wed, 3 Aug 2022 12:53:39 +0200 Message-Id: <20220803105340.17377-2-lczerner@redhat.com> In-Reply-To: <20220803105340.17377-1-lczerner@redhat.com> References: <20220803105340.17377-1-lczerner@redhat.com> MIME-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, SPF_HELO_NONE,SPF_NONE 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-ext4@vger.kernel.org Currently the I_DIRTY_TIME will never get set if the inode already has I_DIRTY_INODE with assumption that it supersedes I_DIRTY_TIME. That's true, however ext4 will only update the on-disk inode in ->dirty_inode(), not on actual writeback. As a result if the inode already has I_DIRTY_INODE state by the time we get to __mark_inode_dirty() only with I_DIRTY_TIME, the time was already filled into on-disk inode and will not get updated until the next I_DIRTY_INODE update, which might never come if we crash or get a power failure. The problem can be reproduced on ext4 by running xfstest generic/622 with -o iversion mount option. Fix it by allowing I_DIRTY_TIME to be set even if the inode already has I_DIRTY_INODE. Also make sure that the case is properly handled in writeback_single_inode() as well. Additionally changes in xfs_fs_dirty_inode() was made to accommodate for I_DIRTY_TIME in flag. Thanks Jan Kara for suggestions on how to make this work properly. Cc: Dave Chinner Cc: Christoph Hellwig Signed-off-by: Lukas Czerner Suggested-by: Jan Kara --- v2: Reworked according to suggestions from Jan fs/fs-writeback.c | 34 ++++++++++++++++++++++------------ fs/xfs/xfs_super.c | 3 ++- include/linux/fs.h | 6 +++--- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 05221366a16d..638dbf143727 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1718,9 +1718,14 @@ static int writeback_single_inode(struct inode *inode, */ if (!(inode->i_state & I_DIRTY_ALL)) inode_cgwb_move_to_attached(inode, wb); - else if (!(inode->i_state & I_SYNC_QUEUED) && - (inode->i_state & I_DIRTY)) - redirty_tail_locked(inode, wb); + else if (!(inode->i_state & I_SYNC_QUEUED)) { + if ((inode->i_state & I_DIRTY)) + redirty_tail_locked(inode, wb); + else if (inode->i_state & I_DIRTY_TIME) { + inode->dirtied_when = jiffies; + inode_io_list_move_locked(inode, wb, &wb->b_dirty_time); + } + } spin_unlock(&wb->list_lock); inode_sync_complete(inode); @@ -2369,6 +2374,17 @@ void __mark_inode_dirty(struct inode *inode, int flags) trace_writeback_mark_inode_dirty(inode, flags); if (flags & I_DIRTY_INODE) { + + /* Inode timestamp update will piggback on this dirtying */ + if (inode->i_state & I_DIRTY_TIME) { + spin_lock(&inode->i_lock); + if (inode->i_state & I_DIRTY_TIME) { + inode->i_state &= ~I_DIRTY_TIME; + flags |= I_DIRTY_TIME; + } + spin_unlock(&inode->i_lock); + } + /* * Notify the filesystem about the inode being dirtied, so that * (if needed) it can update on-disk fields and journal the @@ -2378,7 +2394,8 @@ 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 & I_DIRTY_INODE); + sb->s_op->dirty_inode(inode, + flags & (I_DIRTY_INODE | I_DIRTY_TIME)); trace_writeback_dirty_inode(inode, flags); /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */ @@ -2399,21 +2416,15 @@ void __mark_inode_dirty(struct inode *inode, int flags) */ smp_mb(); - if (((inode->i_state & flags) == flags) || - (dirtytime && (inode->i_state & I_DIRTY_INODE))) + if ((inode->i_state & flags) == flags) return; spin_lock(&inode->i_lock); - if (dirtytime && (inode->i_state & I_DIRTY_INODE)) - goto out_unlock_inode; if ((inode->i_state & flags) != flags) { const int was_dirty = inode->i_state & I_DIRTY; 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; /* @@ -2486,7 +2497,6 @@ void __mark_inode_dirty(struct inode *inode, int flags) out_unlock: if (wb) spin_unlock(&wb->list_lock); -out_unlock_inode: spin_unlock(&inode->i_lock); } EXPORT_SYMBOL(__mark_inode_dirty); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index aa977c7ea370..cff05a4771b5 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -658,7 +658,8 @@ xfs_fs_dirty_inode( if (!(inode->i_sb->s_flags & SB_LAZYTIME)) return; - if (flag != I_DIRTY_SYNC || !(inode->i_state & I_DIRTY_TIME)) + if ((flag & ~I_DIRTY_TIME) != I_DIRTY_SYNC || + !((inode->i_state | flag) & I_DIRTY_TIME)) return; if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp)) diff --git a/include/linux/fs.h b/include/linux/fs.h index 9ad5e3520fae..2243797badf2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2245,9 +2245,9 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * 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_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. But + * I_DIRTY_TIME can still be set if I_DIRTY_SYNC is already + * in place. * 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 -- 2.37.1