All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after force unmount
@ 2022-07-27  6:44 Daniil Lunev
  2022-07-27  6:44 ` [PATCH v5 1/2] fs/super: function to prevent re-use of block-device-based superblocks Daniil Lunev
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Daniil Lunev @ 2022-07-27  6:44 UTC (permalink / raw)
  To: Miklos Szeredi, Alexander Viro
  Cc: linux-fsdevel, fuse-devel, Christoph Hellwig, linux-kernel, Daniil Lunev

Force unmount of fuse severes the connection between FUSE driver and its
userspace counterpart. However, open file handles will prevent the
superblock from being reclaimed. An attempt to remount the filesystem at
the same endpoint will try re-using the superblock, if still present.
Since the superblock re-use path doesn't go through the fs-specific
superblock setup code, its state in FUSE case is already disfunctional,
and that will prevent the mount from succeeding.

Changes in v5:
- Update commit messages to specify that only block-device-based
  superblocks are affected
- Restrict retire_super call in FUSE to be issued for fuseblk only.

Changes in v4:
- Simplify condition according to Christoph Hellwig's comments.

Changes in v3:
- Back to state tracking from v1
- Use s_iflag to mark superblocked ignored
- Only unregister private bdi in retire, without freeing

Changes in v2:
- Remove super from list of superblocks instead of using a flag

Daniil Lunev (2):
  fs/super: function to prevent re-use of block-device-based superblocks
  FUSE: Retire block-device-based superblock on force unmount

 fs/fuse/inode.c    | 10 ++++++++--
 fs/super.c         | 32 ++++++++++++++++++++++++++++++--
 include/linux/fs.h |  2 ++
 3 files changed, 40 insertions(+), 4 deletions(-)

-- 
2.31.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v5 1/2] fs/super: function to prevent re-use of block-device-based superblocks
  2022-07-27  6:44 [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after force unmount Daniil Lunev
@ 2022-07-27  6:44 ` Daniil Lunev
  2022-07-27  6:44 ` [PATCH v5 2/2] FUSE: Retire block-device-based superblock on force unmount Daniil Lunev
  2022-07-27  9:31 ` [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after " Miklos Szeredi
  2 siblings, 0 replies; 4+ messages in thread
From: Daniil Lunev @ 2022-07-27  6:44 UTC (permalink / raw)
  To: Miklos Szeredi, Alexander Viro
  Cc: linux-fsdevel, fuse-devel, Christoph Hellwig, linux-kernel, Daniil Lunev

The function is to be called from filesystem-specific code to mark a
superblock to be ignored by superblock test and thus never re-used. The
function also unregisters bdi if the bdi is per-superblock to avoid
collision if a new superblock is created to represent the filesystem.
generic_shutdown_super() skips unregistering bdi for a retired
superlock as it assumes retire function has already done it.

This patch adds the functionality only for the block-device-based
supers, since the primary use case of the feature is to gracefully
handle force unmount of external devices, mounted with FUSE. This can be
further extended to cover all superblocks, if the need arises.

Signed-off-by: Daniil Lunev <dlunev@chromium.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---

Changes in v5:
- Commit message
- Extended retire_super comment to clarify behaviour.

Changes in v4:
- Simplify condition according to Christoph Hellwig's comments.

Changes in v3:
- Back to state tracking from v1
- Use s_iflag to mark superblocked ignored
- Only unregister private bdi in retire, without freeing

Changes in v2:
- Remove super from list of superblocks instead of using a flag

 fs/super.c         | 32 ++++++++++++++++++++++++++++++--
 include/linux/fs.h |  2 ++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/fs/super.c b/fs/super.c
index 60f57c7bc0a69..8565fffc9ae31 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -422,6 +422,34 @@ bool trylock_super(struct super_block *sb)
 	return false;
 }
 
+/**
+ *	retire_super	-	prevents superblock from being reused
+ *	@sb: superblock to retire
+ *
+ *	The function marks superblock to be ignored in superblock test, which
+ *	prevents it from being reused for any new mounts. If the superblock has
+ *	a private bdi, it also unregisters it, but doesn't reduce the refcount
+ *	of the superblock to prevent potential races. The refcount is reduced
+ *	by generic_shutdown_super(). The function can not be called concurrently
+ *	with generic_shutdown_super(). It is safe to call the function multiple
+ *	times, subsequent calls have no effect.
+ *
+ *	The marker will affect the re-use only for block-device-based
+ *	superblocks. Other superblocks will still get marked if this function is
+ *	used, but that will not affect their reusability.
+ */
+void retire_super(struct super_block *sb)
+{
+	down_write(&sb->s_umount);
+	if (sb->s_iflags & SB_I_PERSB_BDI) {
+		bdi_unregister(sb->s_bdi);
+		sb->s_iflags &= ~SB_I_PERSB_BDI;
+	}
+	sb->s_iflags |= SB_I_RETIRED;
+	up_write(&sb->s_umount);
+}
+EXPORT_SYMBOL(retire_super);
+
 /**
  *	generic_shutdown_super	-	common helper for ->kill_sb()
  *	@sb: superblock to kill
@@ -1216,7 +1244,7 @@ static int set_bdev_super_fc(struct super_block *s, struct fs_context *fc)
 
 static int test_bdev_super_fc(struct super_block *s, struct fs_context *fc)
 {
-	return s->s_bdev == fc->sget_key;
+	return !(s->s_iflags & SB_I_RETIRED) && s->s_bdev == fc->sget_key;
 }
 
 /**
@@ -1307,7 +1335,7 @@ EXPORT_SYMBOL(get_tree_bdev);
 
 static int test_bdev_super(struct super_block *s, void *data)
 {
-	return (void *)s->s_bdev == data;
+	return !(s->s_iflags & SB_I_RETIRED) && (void *)s->s_bdev == data;
 }
 
 struct dentry *mount_bdev(struct file_system_type *fs_type,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9ad5e3520fae5..246120ee05733 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1412,6 +1412,7 @@ extern int send_sigurg(struct fown_struct *fown);
 #define SB_I_SKIP_SYNC	0x00000100	/* Skip superblock at global sync */
 #define SB_I_PERSB_BDI	0x00000200	/* has a per-sb bdi */
 #define SB_I_TS_EXPIRY_WARNED 0x00000400 /* warned about timestamp range expiry */
+#define SB_I_RETIRED	0x00000800	/* superblock shouldn't be reused */
 
 /* Possible states of 'frozen' field */
 enum {
@@ -2432,6 +2433,7 @@ extern struct dentry *mount_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
 extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path);
+void retire_super(struct super_block *sb);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 2/2] FUSE: Retire block-device-based superblock on force unmount
  2022-07-27  6:44 [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after force unmount Daniil Lunev
  2022-07-27  6:44 ` [PATCH v5 1/2] fs/super: function to prevent re-use of block-device-based superblocks Daniil Lunev
@ 2022-07-27  6:44 ` Daniil Lunev
  2022-07-27  9:31 ` [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after " Miklos Szeredi
  2 siblings, 0 replies; 4+ messages in thread
From: Daniil Lunev @ 2022-07-27  6:44 UTC (permalink / raw)
  To: Miklos Szeredi, Alexander Viro
  Cc: linux-fsdevel, fuse-devel, Christoph Hellwig, linux-kernel, Daniil Lunev

Force unmount of FUSE severes the connection with the user space, even
if there are still open files. Subsequent remount tries to re-use the
superblock held by the open files, which is meaningless in the FUSE case
after disconnect - reused super block doesn't have userspace counterpart
attached to it and is incapable of doing any IO.

This patch adds the functionality only for the block-device-based
supers, since the primary use case of the feature is to gracefully
handle force unmount of external devices, mounted with FUSE. This can be
further extended to cover all superblocks, if the need arises.

Signed-off-by: Daniil Lunev <dlunev@chromium.org>
---

Changes in v5:
- Restrict retire_super call in FUSE to be issued for fuseblk only.
- Commit message

Changes in v2:
- Use an exported function instead of directly modifying superblock

 fs/fuse/inode.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 8c0665c5dff88..9e931f53794bb 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -476,8 +476,14 @@ static void fuse_umount_begin(struct super_block *sb)
 {
 	struct fuse_conn *fc = get_fuse_conn_super(sb);
 
-	if (!fc->no_force_umount)
-		fuse_abort_conn(fc);
+	if (fc->no_force_umount)
+		return;
+
+	fuse_abort_conn(fc);
+
+	// Only retire block-device-based superblocks.
+	if (sb->s_bdev != NULL)
+		retire_super(sb);
 }
 
 static void fuse_send_destroy(struct fuse_mount *fm)
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after force unmount
  2022-07-27  6:44 [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after force unmount Daniil Lunev
  2022-07-27  6:44 ` [PATCH v5 1/2] fs/super: function to prevent re-use of block-device-based superblocks Daniil Lunev
  2022-07-27  6:44 ` [PATCH v5 2/2] FUSE: Retire block-device-based superblock on force unmount Daniil Lunev
@ 2022-07-27  9:31 ` Miklos Szeredi
  2 siblings, 0 replies; 4+ messages in thread
From: Miklos Szeredi @ 2022-07-27  9:31 UTC (permalink / raw)
  To: Daniil Lunev
  Cc: Alexander Viro, linux-fsdevel, fuse-devel, Christoph Hellwig,
	linux-kernel

On Wed, 27 Jul 2022 at 08:44, Daniil Lunev <dlunev@chromium.org> wrote:
>
> Force unmount of fuse severes the connection between FUSE driver and its
> userspace counterpart. However, open file handles will prevent the
> superblock from being reclaimed. An attempt to remount the filesystem at
> the same endpoint will try re-using the superblock, if still present.
> Since the superblock re-use path doesn't go through the fs-specific
> superblock setup code, its state in FUSE case is already disfunctional,
> and that will prevent the mount from succeeding.

Applied, thanks.

Miklos

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-07-27  9:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-27  6:44 [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after force unmount Daniil Lunev
2022-07-27  6:44 ` [PATCH v5 1/2] fs/super: function to prevent re-use of block-device-based superblocks Daniil Lunev
2022-07-27  6:44 ` [PATCH v5 2/2] FUSE: Retire block-device-based superblock on force unmount Daniil Lunev
2022-07-27  9:31 ` [PATCH v5 0/2] Prevent re-use of FUSE block-device-based superblock after " Miklos Szeredi

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.