[rh7] ploop: Introduce PLOOP_IOC_FITRIM

Submitted by Kirill Tkhai on Feb. 21, 2020, 2:38 p.m.

Details

Message ID 158229588709.299010.11057859117811422769.stgit@localhost.localdomain
State New
Series "ploop: Introduce PLOOP_IOC_FITRIM"
Headers show

Commit Message

Kirill Tkhai Feb. 21, 2020, 2:38 p.m.
Similar to PLOOP_IOC_FREEZE, which freezes bdev and underlining fs,
this introduces ioctl() discarding unused blocks.

Usually, we need mount point to send FITRIM request, but in case of
secondary ploop we do not know mnt ns, where corresponding mount
is connected. Thus, we introduce such the ioctl.

Note, we introduce ext4_fitrim() and fake inode to avoid dependency
from ext4 module.

https://jira.sw.ru/browse/PSBM-101699

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/dev.c      |   63 ++++++++++++++++++++++++++++++++++++++++
 include/linux/ploop/ploop_if.h |    3 ++
 2 files changed, 66 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 3f70f674e112..3ac783161558 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -5211,6 +5211,66 @@  static int ploop_freeze(struct ploop_device *plo, struct block_device *bdev)
 	return 0;
 }
 
+/*
+ * This function could be implemented in fs/ext4/ioctl.c:
+ * simply extract code undex FITRIM case into a helper
+ * and use the helper here. But that would introduced a dependency
+ * between ploop module and ext4, that is not desired result.
+ * So, we introduce a crutch here...
+ */
+static int ext4_fitrim(struct super_block *sb, unsigned long arg)
+{
+	struct inode *inode = sb->s_root->d_inode;
+	struct file *file;
+	int ret;
+
+	file = kzalloc(sizeof(*file), GFP_KERNEL);
+	if (!file)
+		return -ENOMEM;
+
+	file->f_inode = inode;
+	ret = inode->i_fop->unlocked_ioctl(file, FITRIM, arg);
+
+	kfree(file);
+	return ret;
+}
+
+static int ploop_fitrim(struct ploop_device *plo, struct block_device *bdev,
+			unsigned long arg)
+{
+	struct super_block *sb;
+	int ret = 0;
+
+	if (!test_bit(PLOOP_S_RUNNING, &plo->state))
+		return -EINVAL;
+
+	if (plo->freeze_state != PLOOP_F_NORMAL)
+		return -EBUSY;
+
+	if (plo->dm_crypt_bdev)
+		bdev = plo->dm_crypt_bdev;
+
+	bdgrab(bdev);
+	/* Note, that in case of success sb->s_root is not NULL */
+	sb = get_super(bdev);
+	if (!sb) {
+		ret = -ENODEV;
+		goto bdput;
+	}
+
+	if (sb->s_magic != EXT4_SUPER_MAGIC) {
+		ret = -EPROTO;
+		goto put_super;
+	}
+
+	ret = ext4_fitrim(sb, arg);
+put_super:
+	drop_super(sb);
+bdput:
+	bdput(bdev);
+	return ret;
+}
+
 static int ploop_thaw(struct ploop_device *plo)
 {
 	struct block_device *bdev = plo->frozen_bdev;
@@ -5360,6 +5420,9 @@  static int ploop_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cm
 	case PLOOP_IOC_FREEZE:
 		err = ploop_freeze(plo, bdev);
 		break;
+	case PLOOP_IOC_FITRIM:
+		err = ploop_fitrim(plo, bdev, arg);
+		break;
 	case PLOOP_IOC_THAW:
 		err = ploop_thaw(plo);
 		break;
diff --git a/include/linux/ploop/ploop_if.h b/include/linux/ploop/ploop_if.h
index 852e04d50eb9..42fe28bba685 100644
--- a/include/linux/ploop/ploop_if.h
+++ b/include/linux/ploop/ploop_if.h
@@ -367,6 +367,9 @@  struct ploop_track_extent
 /* Unfreeze FS mounted over ploop */
 #define PLOOP_IOC_THAW		_IO(PLOOPCTLTYPE, 33)
 
+/* Trim EXT4 FS mounted over ploop */
+#define PLOOP_IOC_FITRIM	_IO(PLOOPCTLTYPE, 34)
+
 /* Events exposed via /sys/block/ploopN/pstate/event */
 #define PLOOP_EVENT_ABORTED	1
 #define PLOOP_EVENT_STOPPED	2

Comments

Kirill Tkhai Feb. 21, 2020, 2:39 p.m.
Konstantin, could you please review?

On 21.02.2020 17:38, Kirill Tkhai wrote:
> Similar to PLOOP_IOC_FREEZE, which freezes bdev and underlining fs,
> this introduces ioctl() discarding unused blocks.
> 
> Usually, we need mount point to send FITRIM request, but in case of
> secondary ploop we do not know mnt ns, where corresponding mount
> is connected. Thus, we introduce such the ioctl.
> 
> Note, we introduce ext4_fitrim() and fake inode to avoid dependency
> from ext4 module.
> 
> https://jira.sw.ru/browse/PSBM-101699
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  drivers/block/ploop/dev.c      |   63 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/ploop/ploop_if.h |    3 ++
>  2 files changed, 66 insertions(+)
> 
> diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
> index 3f70f674e112..3ac783161558 100644
> --- a/drivers/block/ploop/dev.c
> +++ b/drivers/block/ploop/dev.c
> @@ -5211,6 +5211,66 @@ static int ploop_freeze(struct ploop_device *plo, struct block_device *bdev)
>  	return 0;
>  }
>  
> +/*
> + * This function could be implemented in fs/ext4/ioctl.c:
> + * simply extract code undex FITRIM case into a helper
> + * and use the helper here. But that would introduced a dependency
> + * between ploop module and ext4, that is not desired result.
> + * So, we introduce a crutch here...
> + */
> +static int ext4_fitrim(struct super_block *sb, unsigned long arg)
> +{
> +	struct inode *inode = sb->s_root->d_inode;
> +	struct file *file;
> +	int ret;
> +
> +	file = kzalloc(sizeof(*file), GFP_KERNEL);
> +	if (!file)
> +		return -ENOMEM;
> +
> +	file->f_inode = inode;
> +	ret = inode->i_fop->unlocked_ioctl(file, FITRIM, arg);
> +
> +	kfree(file);
> +	return ret;
> +}
> +
> +static int ploop_fitrim(struct ploop_device *plo, struct block_device *bdev,
> +			unsigned long arg)
> +{
> +	struct super_block *sb;
> +	int ret = 0;
> +
> +	if (!test_bit(PLOOP_S_RUNNING, &plo->state))
> +		return -EINVAL;
> +
> +	if (plo->freeze_state != PLOOP_F_NORMAL)
> +		return -EBUSY;
> +
> +	if (plo->dm_crypt_bdev)
> +		bdev = plo->dm_crypt_bdev;
> +
> +	bdgrab(bdev);
> +	/* Note, that in case of success sb->s_root is not NULL */
> +	sb = get_super(bdev);
> +	if (!sb) {
> +		ret = -ENODEV;
> +		goto bdput;
> +	}
> +
> +	if (sb->s_magic != EXT4_SUPER_MAGIC) {
> +		ret = -EPROTO;
> +		goto put_super;
> +	}
> +
> +	ret = ext4_fitrim(sb, arg);
> +put_super:
> +	drop_super(sb);
> +bdput:
> +	bdput(bdev);
> +	return ret;
> +}
> +
>  static int ploop_thaw(struct ploop_device *plo)
>  {
>  	struct block_device *bdev = plo->frozen_bdev;
> @@ -5360,6 +5420,9 @@ static int ploop_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cm
>  	case PLOOP_IOC_FREEZE:
>  		err = ploop_freeze(plo, bdev);
>  		break;
> +	case PLOOP_IOC_FITRIM:
> +		err = ploop_fitrim(plo, bdev, arg);
> +		break;
>  	case PLOOP_IOC_THAW:
>  		err = ploop_thaw(plo);
>  		break;
> diff --git a/include/linux/ploop/ploop_if.h b/include/linux/ploop/ploop_if.h
> index 852e04d50eb9..42fe28bba685 100644
> --- a/include/linux/ploop/ploop_if.h
> +++ b/include/linux/ploop/ploop_if.h
> @@ -367,6 +367,9 @@ struct ploop_track_extent
>  /* Unfreeze FS mounted over ploop */
>  #define PLOOP_IOC_THAW		_IO(PLOOPCTLTYPE, 33)
>  
> +/* Trim EXT4 FS mounted over ploop */
> +#define PLOOP_IOC_FITRIM	_IO(PLOOPCTLTYPE, 34)
> +
>  /* Events exposed via /sys/block/ploopN/pstate/event */
>  #define PLOOP_EVENT_ABORTED	1
>  #define PLOOP_EVENT_STOPPED	2
> 
>