linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kara <jack@suse.cz>
To: <linux-fsdevel@vger.kernel.org>
Cc: Dave Chinner <david@fromorbit.com>,
	Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>
Subject: [PATCH 11/13] fs: Make sb_start_write() return error on shutdown filesystem
Date: Wed,  7 Aug 2024 20:29:56 +0200	[thread overview]
Message-ID: <20240807183003.23562-11-jack@suse.cz> (raw)
In-Reply-To: <20240807180706.30713-1-jack@suse.cz>

Introduce new SB_I_SHUTDOWN flag that a filesystem can set when it is
forcefully shutting down (usually due to errors). Make sb_start_write()
return errors for such superblocks to avoid modifications to it which
reduces noise in the error logs and generally makes life somewhat easier
for filesystems. We teach all sb_start_write() callers to handle the
error.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/btrfs/block-group.c |  3 ++-
 fs/btrfs/defrag.c      |  6 +++++-
 fs/btrfs/volumes.c     | 13 +++++++++----
 fs/ext4/mmp.c          |  4 +++-
 fs/namespace.c         |  8 ++++++--
 fs/open.c              |  4 +++-
 fs/overlayfs/util.c    |  3 +--
 fs/quota/quota.c       |  4 ++--
 fs/xfs/xfs_ioctl.c     |  4 +++-
 include/linux/fs.h     | 16 ++++++++++++----
 10 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 498442d0c216..fdd833f1f7df 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -1800,7 +1800,8 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
 	if (!btrfs_should_reclaim(fs_info))
 		return;
 
-	sb_start_write(fs_info->sb);
+	if (sb_start_write(fs_info->sb) < 0)
+		return;
 
 	if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
 		sb_end_write(fs_info->sb);
diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
index f6dbda37a361..6d14c9be4060 100644
--- a/fs/btrfs/defrag.c
+++ b/fs/btrfs/defrag.c
@@ -274,7 +274,11 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
 	range.start = cur;
 	range.extent_thresh = defrag->extent_thresh;
 
-	sb_start_write(fs_info->sb);
+	ret = sb_start_write(fs_info->sb);
+	if (ret < 0) {
+		iput(inode);
+		goto cleanup;
+	}
 	ret = btrfs_defrag_file(inode, NULL, &range, defrag->transid,
 				       BTRFS_DEFRAG_BATCH);
 	sb_end_write(fs_info->sb);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index fcedc43ef291..f7b6b307c4bf 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4589,9 +4589,11 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
 static int balance_kthread(void *data)
 {
 	struct btrfs_fs_info *fs_info = data;
-	int ret = 0;
+	int ret;
 
-	sb_start_write(fs_info->sb);
+	ret = sb_start_write(fs_info->sb);
+	if (ret < 0)
+		return ret;
 	mutex_lock(&fs_info->balance_mutex);
 	if (fs_info->balance_ctl)
 		ret = btrfs_balance(fs_info, fs_info->balance_ctl, NULL);
@@ -8231,12 +8233,15 @@ static int relocating_repair_kthread(void *data)
 	struct btrfs_block_group *cache = data;
 	struct btrfs_fs_info *fs_info = cache->fs_info;
 	u64 target;
-	int ret = 0;
+	int ret;
 
 	target = cache->start;
 	btrfs_put_block_group(cache);
 
-	sb_start_write(fs_info->sb);
+	ret = sb_start_write(fs_info->sb);
+	if (ret < 0)
+		return ret;
+
 	if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
 		btrfs_info(fs_info,
 			   "zoned: skip relocating block group %llu to repair: EBUSY",
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
index bd946d0c71b7..96f69b6835f9 100644
--- a/fs/ext4/mmp.c
+++ b/fs/ext4/mmp.c
@@ -63,7 +63,9 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
 	 * We protect against freezing so that we don't create dirty buffers
 	 * on frozen filesystem.
 	 */
-	sb_start_write(sb);
+	err = sb_start_write(sb);
+	if (err < 0)
+		return err;
 	err = write_mmp_block_thawed(sb, bh);
 	sb_end_write(sb);
 	return err;
diff --git a/fs/namespace.c b/fs/namespace.c
index 1c5591673f96..43fad685531e 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -512,7 +512,9 @@ int mnt_want_write(struct vfsmount *m)
 {
 	int ret;
 
-	sb_start_write(m->mnt_sb);
+	ret = sb_start_write(m->mnt_sb);
+	if (ret)
+		return ret;
 	ret = mnt_get_write_access(m);
 	if (ret)
 		sb_end_write(m->mnt_sb);
@@ -556,7 +558,9 @@ int mnt_want_write_file(struct file *file)
 {
 	int ret;
 
-	sb_start_write(file_inode(file)->i_sb);
+	ret = sb_start_write(file_inode(file)->i_sb);
+	if (ret)
+		return ret;
 	ret = mnt_get_write_access_file(file);
 	if (ret)
 		sb_end_write(file_inode(file)->i_sb);
diff --git a/fs/open.c b/fs/open.c
index 4bce4ba776ab..8fe9f4968969 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -175,7 +175,9 @@ long do_ftruncate(struct file *file, loff_t length, int small)
 	/* Check IS_APPEND on real upper inode */
 	if (IS_APPEND(file_inode(file)))
 		return -EPERM;
-	sb_start_write(inode->i_sb);
+	error = sb_start_write(inode->i_sb);
+	if (error)
+		return error;
 	error = security_file_truncate(file);
 	if (!error)
 		error = do_truncate(file_mnt_idmap(file), dentry, length,
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index b53fa14506a9..f97bf2458c66 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -28,8 +28,7 @@ int ovl_get_write_access(struct dentry *dentry)
 int __must_check ovl_start_write(struct dentry *dentry)
 {
 	struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
-	sb_start_write(ovl_upper_mnt(ofs)->mnt_sb);
-	return 0;
+	return sb_start_write(ovl_upper_mnt(ofs)->mnt_sb);
 }
 
 int ovl_want_write(struct dentry *dentry)
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 0e41fb84060f..df9c4d08f135 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -896,8 +896,8 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 		else
 			up_read(&sb->s_umount);
 		/* Wait for sb to unfreeze */
-		sb_start_write(sb);
-		sb_end_write(sb);
+		if (sb_start_write(sb) == 0)
+			sb_end_write(sb);
 		put_super(sb);
 		goto retry;
 	}
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 4e933db75b12..5cf9e568324a 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1499,7 +1499,9 @@ xfs_file_ioctl(
 
 		trace_xfs_ioc_free_eofblocks(mp, &icw, _RET_IP_);
 
-		sb_start_write(mp->m_super);
+		error = sb_start_write(mp->m_super);
+		if (error)
+			return error;
 		error = xfs_blockgc_free_space(mp, &icw);
 		sb_end_write(mp->m_super);
 		return error;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 755a4c83a2bf..44ae86f46b12 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1190,6 +1190,9 @@ enum {
 	SB_I_TS_EXPIRY_WARNED,	/* warned about timestamp range expiry */
 	SB_I_RETIRED,		/* superblock shouldn't be reused */
 	SB_I_NOUMASK,		/* VFS does not apply umask */
+	SB_I_SHUTDOWN,		/* The filesystem has shutdown. Refuse
+				 * modification attempts with error as they are
+				 * a futile exercise. */
 };
 
 /* Possible states of 'frozen' field */
@@ -1823,9 +1826,12 @@ static inline void sb_end_intwrite(struct super_block *sb)
  *   -> i_mutex			(write path, truncate, directory ops, ...)
  *   -> s_umount		(freeze_super, thaw_super)
  */
-static inline void sb_start_write(struct super_block *sb)
+static inline int __must_check sb_start_write(struct super_block *sb)
 {
+	if (sb_test_iflag(sb, SB_I_SHUTDOWN))
+		return -EROFS;
 	__sb_start_write(sb, SB_FREEZE_WRITE);
+	return 0;
 }
 
 static inline bool __must_check sb_start_write_trylock(struct super_block *sb)
@@ -2891,8 +2897,7 @@ static inline int __must_check file_start_write(struct file *file)
 {
 	if (!S_ISREG(file_inode(file)->i_mode))
 		return 0;
-	sb_start_write(file_inode(file)->i_sb);
-	return 0;
+	return sb_start_write(file_inode(file)->i_sb);
 }
 
 static inline bool __must_check file_start_write_trylock(struct file *file)
@@ -2925,8 +2930,11 @@ static inline void file_end_write(struct file *file)
 static inline int __must_check kiocb_start_write(struct kiocb *iocb)
 {
 	struct inode *inode = file_inode(iocb->ki_filp);
+	int err;
 
-	sb_start_write(inode->i_sb);
+	err = sb_start_write(inode->i_sb);
+	if (err)
+		return err;
 	/*
 	 * Fool lockdep by telling it the lock got released so that it
 	 * doesn't complain about the held lock when we return to userspace.
-- 
2.35.3


  parent reply	other threads:[~2024-08-07 18:30 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-07 18:29 [PATCH RFC 0/13] fs: generic filesystem shutdown handling Jan Kara
2024-08-07 18:29 ` [PATCH 01/13] fs: Define bit numbers for SB_I_ flags Jan Kara
2024-08-07 18:29 ` [PATCH 02/13] fs: Convert fs_context use of SB_I_ flags to new constants Jan Kara
2024-08-07 18:29 ` [PATCH 03/13] fs: Convert mount_too_revealing() to new s_iflags handling functions Jan Kara
2024-08-07 18:29 ` [PATCH 04/13] fs: Convert remaining usage of SB_I_ flags Jan Kara
2024-08-07 18:29 ` [PATCH 05/13] fs: Drop old SB_I_ constants Jan Kara
2024-08-07 18:29 ` [PATCH 06/13] fs: Drop unnecessary underscore from _SB_I_ constants Jan Kara
2024-08-08 11:47   ` Amir Goldstein
2024-08-08 14:35     ` Darrick J. Wong
2024-08-08 14:50       ` Christian Brauner
2024-08-08 17:34         ` Jan Kara
2024-08-07 18:29 ` [PATCH 07/13] overlayfs: Make ovl_start_write() return error Jan Kara
2024-08-08 12:01   ` Amir Goldstein
2024-08-07 18:29 ` [PATCH 08/13] fs: Teach callers of kiocb_start_write() to handle errors Jan Kara
2024-08-07 18:29 ` [PATCH 09/13] fs: Teach callers of file_start_write() " Jan Kara
2024-08-07 18:29 ` [PATCH 10/13] fs: Add __must_check annotations to sb_start_write_trylock() and similar Jan Kara
2024-08-07 18:29 ` Jan Kara [this message]
2024-08-07 18:29 ` [PATCH 12/13] fs: Make sb_start_pagefault() return error on shutdown filesystem Jan Kara
2024-08-07 18:29 ` [PATCH 13/13] ext4: Replace EXT4_FLAGS_SHUTDOWN flag with a generic SB_I_SHUTDOWN Jan Kara
2024-08-07 23:18 ` [PATCH RFC 0/13] fs: generic filesystem shutdown handling Dave Chinner
2024-08-08 14:32   ` Jan Kara
2024-08-13 12:46     ` Christian Brauner
2024-08-14  0:09     ` Dave Chinner
2024-08-08 14:51   ` Darrick J. Wong
2024-08-09  2:30     ` Dave Chinner

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=20240807183003.23562-11-jack@suse.cz \
    --to=jack@suse.cz \
    --cc=brauner@kernel.org \
    --cc=david@fromorbit.com \
    --cc=linux-fsdevel@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).