[rh8,5/9] ext4: Provide a balloon nipple for management

Submitted by Konstantin Khorenko on March 3, 2021, 4:31 p.m.

Details

Message ID 20210303163118.294216-6-khorenko@virtuozzo.com
State New
Series "ext4: Port balloon code and other ext4 fixes"
Headers show

Commit Message

Konstantin Khorenko March 3, 2021, 4:31 p.m.
When the fs is mounted with active balloon someone will have to
inflate/blow off one. To make it possible there will be a special
ioctl for obtaining the fd.

Not very elegant solution maybe, but it's OK for PVC containers.

+++
ext4: fix file allocation check in ext4_open_balloon

Function alloc_file() doesn't return NULL (unlike in 2.6.32-x).
It returns error pointer. File structure allocation may fail before
file->f_ep_links is initialized, which may lead to crash in
eventpoll_release_file().

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

Fixes: 9cea7449aa589f325fff378e7256a3c2fc8f048d
"ext4: Provide a balloon nipple for management"

Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>

(cherry picked from vz7 commit 100feb098ab22c6b8b25861c3b2dfaa9c5db0b03)
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 fs/ext4/ext4.h  |  1 +
 fs/ext4/ioctl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/inode.c      |  1 +
 3 files changed, 61 insertions(+)

Patch hide | download patch | download mbox

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index e439695e4b30..e2efa056bfb1 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -665,6 +665,7 @@  enum {
 
 #define EXT4_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
 #define EXT4_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
+#define EXT4_IOC_OPEN_BALLOON		_IO('f', 42)
 #define EXT4_IOC_MFSYNC			_IO('f', 43)
 
 #define EXT4_IOC_SHUTDOWN _IOR ('X', 125, __u32)
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 6b305c0898dc..ecdc15881007 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -747,6 +747,59 @@  static int ext4_ioctl_check_project(struct inode *inode, struct fsxattr *fa)
 	return 0;
 }
 
+static int ext4_open_balloon(struct super_block *sb, struct vfsmount *mnt)
+{
+	struct inode *balloon_ino;
+	int err, fd;
+	struct file *filp;
+	struct dentry *de;
+	struct path path;
+	fmode_t mode;
+
+	balloon_ino = EXT4_SB(sb)->s_balloon_ino;
+	err = -ENOENT;
+	if (balloon_ino == NULL)
+		goto err;
+
+	err = fd = get_unused_fd_flags(0);
+	if (err < 0)
+		goto err_fd;
+
+	__iget(balloon_ino);
+	de = d_obtain_alias(balloon_ino);
+	err = PTR_ERR(de);
+	if (IS_ERR(de))
+		goto err_de;
+
+	path.dentry = de;
+	path.mnt = mntget(mnt);
+	err = mnt_want_write(path.mnt);
+	if (err)
+		mode = FMODE_READ;
+	else
+		mode = FMODE_READ | FMODE_WRITE;
+	filp = alloc_file(&path, mode, &ext4_file_operations);
+	if (mode & FMODE_WRITE)
+		mnt_drop_write(path.mnt);
+	if (IS_ERR(filp)) {
+		err = PTR_ERR(filp);
+		goto err_filp;
+	}
+
+	filp->f_flags |= O_LARGEFILE;
+	fd_install(fd, filp);
+	return fd;
+
+err_filp:
+	path_put(&path);
+err_de:
+	put_unused_fd(fd);
+err_fd:
+	/* nothing */
+err:
+	return err;
+}
+
 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
@@ -1240,6 +1293,12 @@  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		kfree(flags);
 		return err;
 	}
+	case EXT4_IOC_OPEN_BALLOON:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
+
+		return ext4_open_balloon(inode->i_sb, filp->f_path.mnt);
+
 	default:
 		return -ENOTTY;
 	}
diff --git a/fs/inode.c b/fs/inode.c
index ad98bee52a46..e79a5babb9ab 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -398,6 +398,7 @@  void __iget(struct inode *inode)
 {
 	atomic_inc(&inode->i_count);
 }
+EXPORT_SYMBOL(__iget);
 
 /*
  * get additional reference to inode; caller must already hold one.