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

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

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

(cherry picked from vz7 commit 100feb098ab22c6b8b25861c3b2dfaa9c5db0b03)
Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>

+++
ext4/balloon: Use proper O_ mode flags in balloon opening code

alloc_file() expects O_* mode flags, so provide them, not
internal FMODE_* ones.

mFixes: bee340a206d7 ("ext4: Provide a balloon nipple for management")
https://jira.sw.ru/browse/PSBM-129392

Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktk...@virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com>

Feature: fs/ext4: fast online shrink support

+++
ext4: Check alloc_file() results in ext4_open_balloon()

Check for pointer validity before its dereference.

Reported-by: Alexander Mikhalitsyn <alexander.mikhalit...@virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com>

Feature: fs/ext4: fast online shrink support
---
 fs/ext4/ext4.h  |  1 +
 fs/ext4/ioctl.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/inode.c      |  1 +
 3 files changed, 62 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 807cd5cbe379..8dcee4361714 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -726,6 +726,7 @@ enum {
 #define EXT4_IOC_CLEAR_ES_CACHE                _IO('f', 40)
 #define EXT4_IOC_GETSTATE              _IOW('f', 41, __u32)
 #define EXT4_IOC_GET_ES_CACHE          _IOWR('f', 42, struct fiemap)
+#define EXT4_IOC_OPEN_BALLOON          _IO('f', 42)
 #define EXT4_IOC_CHECKPOINT            _IOW('f', 43, __u32)
 #define EXT4_IOC_MFSYNC                        _IO('f', 43)
 #define EXT4_IOC_GETFSUUID             _IOR('f', 44, struct fsuuid)
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 73c57a66618a..08c5c053bf2d 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1272,6 +1272,59 @@ static int ext4_mfsync(unsigned long arg)
        return err;
 }
 
+static int ext4_open_balloon(struct super_block *sb, struct vfsmount *mnt)
+{
+       struct inode *balloon_ino;
+       int err, fd, ro;
+       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);
+       ro = mnt_want_write(path.mnt);
+       if (ro)
+               mode = O_RDONLY;
+       else
+               mode = O_RDWR;
+       filp = alloc_file(&path, mode, &ext4_file_operations);
+       if (!ro)
+               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;
+}
+
 static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long 
arg)
 {
        struct inode *inode = file_inode(filp);
@@ -1662,6 +1715,13 @@ static long __ext4_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
                return ext4_ioctl_getuuid(EXT4_SB(sb), (void __user *)arg);
        case EXT4_IOC_SETFSUUID:
                return ext4_ioctl_setuuid(filp, (const void __user *)arg);
+
+       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 2e4dfa4bf06a..4846b61502e1 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -441,6 +441,7 @@ void __iget(struct inode *inode)
 {
        atomic_inc(&inode->i_count);
 }
+EXPORT_SYMBOL(__iget);
 
 /*
  * get additional reference to inode; caller must already hold one.
-- 
2.43.5

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to