Unverified Commit cad90c54 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3963 block: Add config to show info about opening a mounted device for write

Merge Pull Request from: @ci-robot 
 
PR sync from: Li Lingfeng <lilingfeng3@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/RBE3JOLJX7IWHDPHI6KGSB54YDINS2AD/ 
v1->v2:
  1) Replace BLK_DEV_DUMPINFO with BLK_DEV_WRITE_MOUNTED_QUIET, which is
     logically opposite;
  2) Make BLK_DEV_WRITE_MOUNTED_QUIET dependent on
     BLK_DEV_WRITE_MOUNTED, and decide whether to set bd_writers
     by BLK_DEV_WRITE_MOUNTED_QUIET;
  3) Move bdev_dump_info() into bdev_may_open();
  4) Add the cmdline interface to control whether to show info;
  5) Pass the state of "writes blocked" to part0 when mounting a
     partition.
v2->v3:
  Add restriction for modifying bd_writers.
v3->v4:
  1) Count bd_writers regardless of whether bdev_allow_write_mounted is
     set;
  2) Expand the meaning of bdev_allow_write_mounted;
  3) Add config option to detect writing to part0 while partitions
     mounted;
  4) Add bd_mounters to record the number of times that part0 or
     partition is mounted;
  5) Show info about opening a lower device for write while upper-layers
     mounted.
v4->v5:
  Move introduction of bd_mounters to patch1.
v5->v6:
  Delete redundant conflict judgment.
v6->v7:
  1) Replace BLK_DEV_WRITE_MOUNTED_QUIET with BLK_DEV_WRITE_MOUNTED_DUMP;
  2) Remove restriction for setting bdev_allow_write_mounted by cmdline.
v7->v8:
  1) Add detection of mounting part0 while partitions write opened;
  2) Add detection of writing partitions while part0 mounted;
  3) Add config in openeuler_defconfig.
v8->v9:
  1) Split bd_mounters into bd_mounted and part_mounters;
  2) Add part_writers;
  3) Count part_writers and part_mounters regardless of whether
     BLK_DEV_DETECT_WRITING_PART0 is set.
v9->v10:
  1) Split the logic of detecting writing lower device from bd_may_open();
  2) Fix the bug of initializing bdev_allow_write_mounted.

Li Lingfeng (6):
  block: Record writing and mounting regardless of whether
    bdev_allow_write_mounted is set
  block: Expand the meaning of bdev_allow_write_mounted
  block: Add config option to detect writing to part0 while partitions
    mounted
  block: Add config option to show info about opening a mounted device
    for write
  block: Show info about opening a lower device for write while
    upper-layers mounted
  add config about writing mounted devices in openeuler_defconfig


-- 
2.31.1
 
https://gitee.com/openeuler/kernel/issues/I8S3GW 
 
Link:https://gitee.com/openeuler/kernel/pulls/3963

 

Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents ea6de9f6 904ff472
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -901,6 +901,9 @@ CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEBUG_FS_ZONED=y
# CONFIG_BLK_SED_OPAL is not set
# CONFIG_BLK_INLINE_ENCRYPTION is not set
CONFIG_BLK_DEV_WRITE_MOUNTED=y
CONFIG_BLK_DEV_DETECT_WRITING_PART0=y
CONFIG_BLK_DEV_WRITE_MOUNTED_DUMP=y

#
# Partition Types
+3 −0
Original line number Diff line number Diff line
@@ -965,6 +965,9 @@ CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEBUG_FS_ZONED=y
# CONFIG_BLK_SED_OPAL is not set
# CONFIG_BLK_INLINE_ENCRYPTION is not set
CONFIG_BLK_DEV_WRITE_MOUNTED=y
CONFIG_BLK_DEV_DETECT_WRITING_PART0=y
CONFIG_BLK_DEV_WRITE_MOUNTED_DUMP=y

#
# Partition Types
+17 −0
Original line number Diff line number Diff line
@@ -249,6 +249,23 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
	  by falling back to the kernel crypto API when inline
	  encryption hardware is not present.

config BLK_DEV_DETECT_WRITING_PART0
	bool "Detect writing to part0 when partitions mounted"
	default n
	help
	  When partitions of a block device are mounted, writing to part0's
	  buffer cache is likely going to cause filesystem corruption on
	  each partition.
	  As a supplement to BLK_DEV_WRITE_MOUNTED, enabling this
	  to detect the scenario above.

config BLK_DEV_WRITE_MOUNTED_DUMP
	bool "Dump info when detecting conflict of opening block device"
	default n
	help
	  Enabling this to dump info when opening mounted block devices
	  for write or trying to mount write opened block devices.

source "block/partitions/Kconfig"

config BLK_MQ_PCI
+105 −18
Original line number Diff line number Diff line
@@ -30,8 +30,20 @@
#include "../fs/internal.h"
#include "blk.h"

#define OPEN_EXCLUSIVE "VFS: Open an exclusive opened block device for write"
#define OPEN_FOR_EXCLUSIVE "VFS: Open a write opened block device exclusively"
#define bdev_write_mounted_opt(opt) (bdev_allow_write_mounted & (1 << BLKDEV_##opt))
/* Should we allow writing to mounted block devices? */
static bool bdev_allow_write_mounted = IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED);
#define BLKDEV_ALLOW_WRITE_MOUNTED	0
/* Should we detect writing to part0 when partitions mounted  */
#define BLKDEV_DETECT_WRITING_PART0	1
/* Should we dump info when opening mounted block devices for write? */
#define BLKDEV_WRITE_MOUNTED_DUMP	2

static u8 bdev_allow_write_mounted =
	IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED) << BLKDEV_ALLOW_WRITE_MOUNTED |
	IS_ENABLED(CONFIG_BLK_DEV_DETECT_WRITING_PART0) << BLKDEV_DETECT_WRITING_PART0 |
	IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED_DUMP) << BLKDEV_WRITE_MOUNTED_DUMP;

struct bdev_inode {
	struct block_device bdev;
@@ -733,55 +745,127 @@ void blkdev_put_no_open(struct block_device *bdev)
	put_device(&bdev->bd_device);
}

static void blkdev_dump_conflict_opener(struct block_device *bdev, char *msg)
{
	char name[BDEVNAME_SIZE];
	struct task_struct *p = NULL;
	char comm_buf[TASK_COMM_LEN];
	pid_t p_pid;

	if (!bdev_write_mounted_opt(WRITE_MOUNTED_DUMP))
		return;
	rcu_read_lock();
	p = rcu_dereference(current->real_parent);
	task_lock(p);
	strncpy(comm_buf, p->comm, TASK_COMM_LEN);
	p_pid = p->pid;
	task_unlock(p);
	rcu_read_unlock();

	snprintf(name, sizeof(name), "%pg", bdev);
	pr_info_ratelimited("%s [%s]. current [%d %s]. parent [%d %s]\n",
			     msg, name,
			     current->pid, current->comm, p_pid, comm_buf);
}

static bool bdev_writes_blocked(struct block_device *bdev)
{
	return bdev->bd_writers == -1;
	if (bdev->bd_mounted)
		return true;
	if (bdev_write_mounted_opt(DETECT_WRITING_PART0))
		return bdev_is_partition(bdev) ? bdev_whole(bdev)->bd_mounted :
						 bdev->bd_disk->mount_partitions;

	return false;
}

static void bdev_block_writes(struct block_device *bdev)
{
	bdev->bd_writers = -1;
	bdev->bd_mounted = true;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->mount_partitions++;
}

static void bdev_unblock_writes(struct block_device *bdev)
{
	bdev->bd_writers = 0;
	bdev->bd_mounted = false;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->mount_partitions--;
}

static bool bdev_mount_blocked(struct block_device *bdev)
{
	if (bdev->bd_writers)
		return true;
	if (bdev_write_mounted_opt(DETECT_WRITING_PART0))
		return bdev_is_partition(bdev) ? bdev_whole(bdev)->bd_writers :
						 bdev->bd_disk->write_open_partitions;

	return false;
}

static void bdev_block_mount(struct block_device *bdev)
{
	bdev->bd_writers++;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->write_open_partitions++;
}

static void bdev_unblock_mount(struct block_device *bdev)
{
	bdev->bd_writers--;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->write_open_partitions--;
}

static void bdev_write_exclusive_dump(struct block_device *bdev, void *holder,
				      const struct blk_holder_ops *hops)
{
	bool may_claim;

	if (!bdev_write_mounted_opt(WRITE_MOUNTED_DUMP))
		return;

	mutex_lock(&bdev_lock);
	may_claim = bd_may_claim(bdev, holder, hops);
	mutex_unlock(&bdev_lock);

	if (!may_claim)
		blkdev_dump_conflict_opener(bdev, OPEN_EXCLUSIVE);
}

static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode)
{
	if (bdev_allow_write_mounted)
	if (bdev_write_mounted_opt(ALLOW_WRITE_MOUNTED) &&
	    !bdev_write_mounted_opt(WRITE_MOUNTED_DUMP))
		return true;
	/* Writes blocked? */
	if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev))
		return false;
	if (mode & BLK_OPEN_RESTRICT_WRITES && bdev->bd_writers > 0)
		return false;
		blkdev_dump_conflict_opener(bdev, OPEN_EXCLUSIVE);
	else if (mode & BLK_OPEN_RESTRICT_WRITES && bdev_mount_blocked(bdev))
		blkdev_dump_conflict_opener(bdev, OPEN_FOR_EXCLUSIVE);
	else
		return true;

	return bdev_write_mounted_opt(ALLOW_WRITE_MOUNTED);
}

static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode)
{
	if (bdev_allow_write_mounted)
		return;

	/* Claim exclusive or shared write access. */
	if (mode & BLK_OPEN_RESTRICT_WRITES)
		bdev_block_writes(bdev);
	else if (mode & BLK_OPEN_WRITE)
		bdev->bd_writers++;
		bdev_block_mount(bdev);
}

static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode)
{
	if (bdev_allow_write_mounted)
		return;

	/* Yield exclusive or shared write access. */
	if (mode & BLK_OPEN_RESTRICT_WRITES)
		bdev_unblock_writes(bdev);
	else if (mode & BLK_OPEN_WRITE)
		bdev->bd_writers--;
		bdev_unblock_mount(bdev);
}

/**
@@ -851,6 +935,9 @@ struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,

	disk_block_events(disk);

	if (mode & BLK_OPEN_WRITE)
		bdev_write_exclusive_dump(bdev, holder, hops);

	mutex_lock(&disk->open_mutex);
	ret = -ENXIO;
	if (!disk_live(disk))
@@ -1135,7 +1222,7 @@ void bdev_statx_dioalign(struct inode *inode, struct kstat *stat)

static int __init setup_bdev_allow_write_mounted(char *str)
{
	if (kstrtobool(str, &bdev_allow_write_mounted))
	if (kstrtou8(str, 0, &bdev_allow_write_mounted))
		pr_warn("Invalid option string for bdev_allow_write_mounted:"
			" '%s'\n", str);
	return 1;
+3 −0
Original line number Diff line number Diff line
@@ -69,6 +69,9 @@ struct block_device {
#ifdef CONFIG_FAIL_MAKE_REQUEST
	bool			bd_make_it_fail;
#endif
	/* State of mounting */
	bool			bd_mounted;
	/* The counter of write opened */
	int			bd_writers;
	/*
	 * keep this out-of-line as it's both big and not needed in the fast
Loading