All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: linux-fsdevel@vger.kernel.org
Cc: linux-xfs@vger.kernel.org, linux-ext4@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	Theodore Ts'o <tytso@mit.edu>, Christoph Hellwig <hch@lst.de>
Subject: [PATCH v2 09/12] fs: improve comments for writeback_single_inode()
Date: Fri,  8 Jan 2021 23:59:00 -0800	[thread overview]
Message-ID: <20210109075903.208222-10-ebiggers@kernel.org> (raw)
In-Reply-To: <20210109075903.208222-1-ebiggers@kernel.org>

From: Eric Biggers <ebiggers@google.com>

Some comments for writeback_single_inode() and
__writeback_single_inode() are outdated or not very helpful, especially
with regards to writeback list handling.  Update them.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 fs/fs-writeback.c | 57 +++++++++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index cee1df6e3bd43..e91980f493884 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1442,9 +1442,15 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
 }
 
 /*
- * 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
- * setting I_SYNC flag and calling inode_sync_complete() to clear it.
+ * Write out an inode and its dirty pages (or some of its dirty pages, depending
+ * on @wbc->nr_to_write), and clear the relevant dirty flags from i_state.
+ *
+ * This doesn't remove the inode from the writeback list it is on, except
+ * potentially to move it from b_dirty_time to b_dirty due to timestamp
+ * expiration.  The caller is otherwise responsible for writeback list handling.
+ *
+ * The caller is also responsible for setting the I_SYNC flag beforehand and
+ * calling inode_sync_complete() to clear it afterwards.
  */
 static int
 __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
@@ -1487,9 +1493,10 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 	}
 
 	/*
-	 * Some filesystems may redirty the inode during the writeback
-	 * due to delalloc, clear dirty metadata flags right before
-	 * write_inode()
+	 * Get and clear the dirty flags from i_state.  This needs to be done
+	 * after calling writepages because some filesystems may redirty the
+	 * inode during writepages due to delalloc.  It also needs to be done
+	 * after handling timestamp expiration, as that may dirty the inode too.
 	 */
 	spin_lock(&inode->i_lock);
 	dirty = inode->i_state & I_DIRTY;
@@ -1524,12 +1531,13 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 }
 
 /*
- * Write out an inode's dirty pages. Either the caller has an active reference
- * on the inode or the inode has I_WILL_FREE set.
+ * Write out an inode's dirty data and metadata on-demand, i.e. separately from
+ * the regular batched writeback done by the flusher threads in
+ * writeback_sb_inodes().  @wbc controls various aspects of the write, such as
+ * whether it is a data-integrity sync (%WB_SYNC_ALL) or not (%WB_SYNC_NONE).
  *
- * This function is designed to be called for writing back one inode which
- * we go e.g. from filesystem. Flusher thread uses __writeback_single_inode()
- * and does more profound writeback list handling in writeback_sb_inodes().
+ * To prevent the inode from going away, either the caller must have a reference
+ * to the inode, or the inode must have I_WILL_FREE or I_FREEING set.
  */
 static int writeback_single_inode(struct inode *inode,
 				  struct writeback_control *wbc)
@@ -1544,23 +1552,23 @@ static int writeback_single_inode(struct inode *inode,
 		WARN_ON(inode->i_state & I_WILL_FREE);
 
 	if (inode->i_state & I_SYNC) {
-		if (wbc->sync_mode != WB_SYNC_ALL)
-			goto out;
 		/*
-		 * It's a data-integrity sync. We must wait. Since callers hold
-		 * inode reference or inode has I_WILL_FREE set, it cannot go
-		 * away under us.
+		 * Writeback is already running on the inode.  For WB_SYNC_NONE,
+		 * that's enough and we can just return.  For WB_SYNC_ALL, we
+		 * must wait for the existing writeback to complete, then do
+		 * writeback again if there's anything left.
 		 */
+		if (wbc->sync_mode != WB_SYNC_ALL)
+			goto out;
 		__inode_wait_for_writeback(inode);
 	}
 	WARN_ON(inode->i_state & I_SYNC);
 	/*
-	 * Skip inode if it is clean and we have no outstanding writeback in
-	 * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
-	 * function since flusher thread may be doing for example sync in
-	 * parallel and if we move the inode, it could get skipped. So here we
-	 * make sure inode is on some writeback list and leave it there unless
-	 * we have completely cleaned the inode.
+	 * If the inode is already fully clean, then there's nothing to do.
+	 *
+	 * For data-integrity syncs we also need to check whether any pages are
+	 * still under writeback, e.g. due to prior WB_SYNC_NONE writeback.  If
+	 * there are any such pages, we'll need to wait for them.
 	 */
 	if (!(inode->i_state & I_DIRTY_ALL) &&
 	    (wbc->sync_mode != WB_SYNC_ALL ||
@@ -1576,8 +1584,9 @@ static int writeback_single_inode(struct inode *inode,
 	wb = inode_to_wb_and_lock_list(inode);
 	spin_lock(&inode->i_lock);
 	/*
-	 * If inode is clean, remove it from writeback lists. Otherwise don't
-	 * touch it. See comment above for explanation.
+	 * If the inode is now fully clean, then it can be safely removed from
+	 * its writeback list (if any).  Otherwise the flusher threads are
+	 * responsible for the writeback lists.
 	 */
 	if (!(inode->i_state & I_DIRTY_ALL))
 		inode_io_list_del_locked(inode, wb);
-- 
2.30.0


WARNING: multiple messages have this Message-ID (diff)
From: Eric Biggers <ebiggers@kernel.org>
To: linux-fsdevel@vger.kernel.org
Cc: linux-xfs@vger.kernel.org, linux-ext4@vger.kernel.org,
	Theodore Ts'o <tytso@mit.edu>, Christoph Hellwig <hch@lst.de>,
	linux-f2fs-devel@lists.sourceforge.net
Subject: [f2fs-dev] [PATCH v2 09/12] fs: improve comments for writeback_single_inode()
Date: Fri,  8 Jan 2021 23:59:00 -0800	[thread overview]
Message-ID: <20210109075903.208222-10-ebiggers@kernel.org> (raw)
In-Reply-To: <20210109075903.208222-1-ebiggers@kernel.org>

From: Eric Biggers <ebiggers@google.com>

Some comments for writeback_single_inode() and
__writeback_single_inode() are outdated or not very helpful, especially
with regards to writeback list handling.  Update them.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 fs/fs-writeback.c | 57 +++++++++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index cee1df6e3bd43..e91980f493884 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1442,9 +1442,15 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
 }
 
 /*
- * 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
- * setting I_SYNC flag and calling inode_sync_complete() to clear it.
+ * Write out an inode and its dirty pages (or some of its dirty pages, depending
+ * on @wbc->nr_to_write), and clear the relevant dirty flags from i_state.
+ *
+ * This doesn't remove the inode from the writeback list it is on, except
+ * potentially to move it from b_dirty_time to b_dirty due to timestamp
+ * expiration.  The caller is otherwise responsible for writeback list handling.
+ *
+ * The caller is also responsible for setting the I_SYNC flag beforehand and
+ * calling inode_sync_complete() to clear it afterwards.
  */
 static int
 __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
@@ -1487,9 +1493,10 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 	}
 
 	/*
-	 * Some filesystems may redirty the inode during the writeback
-	 * due to delalloc, clear dirty metadata flags right before
-	 * write_inode()
+	 * Get and clear the dirty flags from i_state.  This needs to be done
+	 * after calling writepages because some filesystems may redirty the
+	 * inode during writepages due to delalloc.  It also needs to be done
+	 * after handling timestamp expiration, as that may dirty the inode too.
 	 */
 	spin_lock(&inode->i_lock);
 	dirty = inode->i_state & I_DIRTY;
@@ -1524,12 +1531,13 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 }
 
 /*
- * Write out an inode's dirty pages. Either the caller has an active reference
- * on the inode or the inode has I_WILL_FREE set.
+ * Write out an inode's dirty data and metadata on-demand, i.e. separately from
+ * the regular batched writeback done by the flusher threads in
+ * writeback_sb_inodes().  @wbc controls various aspects of the write, such as
+ * whether it is a data-integrity sync (%WB_SYNC_ALL) or not (%WB_SYNC_NONE).
  *
- * This function is designed to be called for writing back one inode which
- * we go e.g. from filesystem. Flusher thread uses __writeback_single_inode()
- * and does more profound writeback list handling in writeback_sb_inodes().
+ * To prevent the inode from going away, either the caller must have a reference
+ * to the inode, or the inode must have I_WILL_FREE or I_FREEING set.
  */
 static int writeback_single_inode(struct inode *inode,
 				  struct writeback_control *wbc)
@@ -1544,23 +1552,23 @@ static int writeback_single_inode(struct inode *inode,
 		WARN_ON(inode->i_state & I_WILL_FREE);
 
 	if (inode->i_state & I_SYNC) {
-		if (wbc->sync_mode != WB_SYNC_ALL)
-			goto out;
 		/*
-		 * It's a data-integrity sync. We must wait. Since callers hold
-		 * inode reference or inode has I_WILL_FREE set, it cannot go
-		 * away under us.
+		 * Writeback is already running on the inode.  For WB_SYNC_NONE,
+		 * that's enough and we can just return.  For WB_SYNC_ALL, we
+		 * must wait for the existing writeback to complete, then do
+		 * writeback again if there's anything left.
 		 */
+		if (wbc->sync_mode != WB_SYNC_ALL)
+			goto out;
 		__inode_wait_for_writeback(inode);
 	}
 	WARN_ON(inode->i_state & I_SYNC);
 	/*
-	 * Skip inode if it is clean and we have no outstanding writeback in
-	 * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
-	 * function since flusher thread may be doing for example sync in
-	 * parallel and if we move the inode, it could get skipped. So here we
-	 * make sure inode is on some writeback list and leave it there unless
-	 * we have completely cleaned the inode.
+	 * If the inode is already fully clean, then there's nothing to do.
+	 *
+	 * For data-integrity syncs we also need to check whether any pages are
+	 * still under writeback, e.g. due to prior WB_SYNC_NONE writeback.  If
+	 * there are any such pages, we'll need to wait for them.
 	 */
 	if (!(inode->i_state & I_DIRTY_ALL) &&
 	    (wbc->sync_mode != WB_SYNC_ALL ||
@@ -1576,8 +1584,9 @@ static int writeback_single_inode(struct inode *inode,
 	wb = inode_to_wb_and_lock_list(inode);
 	spin_lock(&inode->i_lock);
 	/*
-	 * If inode is clean, remove it from writeback lists. Otherwise don't
-	 * touch it. See comment above for explanation.
+	 * If the inode is now fully clean, then it can be safely removed from
+	 * its writeback list (if any).  Otherwise the flusher threads are
+	 * responsible for the writeback lists.
 	 */
 	if (!(inode->i_state & I_DIRTY_ALL))
 		inode_io_list_del_locked(inode, wb);
-- 
2.30.0



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

  parent reply	other threads:[~2021-01-09  8:01 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-09  7:58 [PATCH v2 00/12] lazytime fix and cleanups Eric Biggers
2021-01-09  7:58 ` [f2fs-dev] " Eric Biggers
2021-01-09  7:58 ` [PATCH v2 01/12] fs: fix lazytime expiration handling in __writeback_single_inode() Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 10:48   ` Christoph Hellwig
2021-01-11 10:48     ` [f2fs-dev] " Christoph Hellwig
2021-01-11 14:46   ` Jan Kara
2021-01-11 14:46     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 02/12] fs: correctly document the inode dirty flags Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 14:48   ` Jan Kara
2021-01-11 14:48     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 03/12] fs: only specify I_DIRTY_TIME when needed in generic_update_time() Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 14:50   ` Jan Kara
2021-01-11 14:50     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 04/12] fat: only specify I_DIRTY_TIME when needed in fat_update_time() Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 10:52   ` Christoph Hellwig
2021-01-11 10:52     ` [f2fs-dev] " Christoph Hellwig
2021-01-11 19:50     ` Eric Biggers
2021-01-11 19:50       ` [f2fs-dev] " Eric Biggers
2021-01-12  5:21       ` Dave Chinner
2021-01-12  5:21         ` [f2fs-dev] " Dave Chinner
2021-01-12 13:23       ` Christoph Hellwig
2021-01-12 13:23         ` [f2fs-dev] " Christoph Hellwig
2021-01-11 14:52   ` Jan Kara
2021-01-11 14:52     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 05/12] fs: don't call ->dirty_inode for lazytime timestamp updates Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 14:54   ` Jan Kara
2021-01-11 14:54     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 06/12] fs: pass only I_DIRTY_INODE flags to ->dirty_inode Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 14:56   ` Jan Kara
2021-01-11 14:56     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 07/12] fs: clean up __mark_inode_dirty() a bit Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 14:59   ` Jan Kara
2021-01-11 14:59     ` [f2fs-dev] " Jan Kara
2021-01-09  7:58 ` [PATCH v2 08/12] fs: drop redundant check from __writeback_single_inode() Eric Biggers
2021-01-09  7:58   ` [f2fs-dev] " Eric Biggers
2021-01-11 10:52   ` Christoph Hellwig
2021-01-11 10:52     ` [f2fs-dev] " Christoph Hellwig
2021-01-11 15:00   ` Jan Kara
2021-01-11 15:00     ` [f2fs-dev] " Jan Kara
2021-01-09  7:59 ` Eric Biggers [this message]
2021-01-09  7:59   ` [f2fs-dev] [PATCH v2 09/12] fs: improve comments for writeback_single_inode() Eric Biggers
2021-01-11 10:53   ` Christoph Hellwig
2021-01-11 10:53     ` [f2fs-dev] " Christoph Hellwig
2021-01-11 15:05   ` Jan Kara
2021-01-11 15:05     ` [f2fs-dev] " Jan Kara
2021-01-09  7:59 ` [PATCH v2 10/12] gfs2: don't worry about I_DIRTY_TIME in gfs2_fsync() Eric Biggers
2021-01-09  7:59   ` [f2fs-dev] " Eric Biggers
2021-01-11 15:06   ` Jan Kara
2021-01-11 15:06     ` [f2fs-dev] " Jan Kara
2021-01-09  7:59 ` [PATCH v2 11/12] ext4: simplify i_state checks in __ext4_update_other_inode_time() Eric Biggers
2021-01-09  7:59   ` [f2fs-dev] " Eric Biggers
2021-01-11 10:53   ` Christoph Hellwig
2021-01-11 10:53     ` [f2fs-dev] " Christoph Hellwig
2021-01-11 20:23     ` Eric Biggers
2021-01-11 20:23       ` [f2fs-dev] " Eric Biggers
2021-01-12 13:25       ` Christoph Hellwig
2021-01-12 13:25         ` [f2fs-dev] " Christoph Hellwig
2021-02-03  5:16         ` Theodore Ts'o
2021-02-03  5:16           ` [f2fs-dev] " Theodore Ts'o
2021-01-11 15:11   ` Jan Kara
2021-01-11 15:11     ` [f2fs-dev] " Jan Kara
2021-01-09  7:59 ` [PATCH v2 12/12] xfs: remove a stale comment from xfs_file_aio_write_checks() Eric Biggers
2021-01-09  7:59   ` [f2fs-dev] " Eric Biggers
2021-01-12 17:31   ` Darrick J. Wong
2021-01-12 17:31     ` [f2fs-dev] " Darrick J. Wong
2021-01-11 15:15 ` [PATCH v2 00/12] lazytime fix and cleanups Jan Kara
2021-01-11 15:15   ` [f2fs-dev] " Jan Kara
2021-01-11 20:44   ` Eric Biggers
2021-01-11 20:44     ` [f2fs-dev] " Eric Biggers
2021-02-03  5:11     ` Theodore Ts'o
2021-02-03  5:11       ` [f2fs-dev] " Theodore Ts'o
2021-02-03  5:22       ` Eric Biggers
2021-02-03  5:22         ` [f2fs-dev] " Eric Biggers
2021-02-03 15:49         ` Theodore Ts'o
2021-02-03 15:49           ` [f2fs-dev] " Theodore Ts'o

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210109075903.208222-10-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=hch@lst.de \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.