[Devel] [PATCH rh7] ploop: Introduce PLOOP_IOC_FITRIM

Kirill Tkhai ktkhai at virtuozzo.com
Fri Feb 21 17:38:17 MSK 2020


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 at 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




More information about the Devel mailing list