From mboxrd@z Thu Jan 1 00:00:00 1970 From: Fernando Luis Vazquez Cao Subject: [PATCH 3/4] fsfreeze: add ioctl to create a fd for freeze control Date: Wed, 27 Jul 2011 16:35:20 +0900 Message-ID: <1311752120.2549.88.camel@nausicaa> References: <1311215535.2763.20.camel@nausicaa> <1311751806.2549.83.camel@nausicaa> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Cc: Christoph Hellwig , Eric Sandeen , Josef Bacik , linux-fsdevel@vger.kernel.org, Ric Wheeler , James Bottomley , Theodore Ts'o To: Al Viro Return-path: Received: from serv2.oss.ntt.co.jp ([222.151.198.100]:43496 "EHLO serv2.oss.ntt.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751878Ab1G0HfX (ORCPT ); Wed, 27 Jul 2011 03:35:23 -0400 In-Reply-To: <1311751806.2549.83.camel@nausicaa> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: Adds a new ioctl, FIGETFREEZEFD, which freezes the indicated filesystem and returns a file descriptor; as long as that file descriptor is held open, the filesystem remains open. Signed-off-by: Fernando Luis Vazquez Cao --- diff -urNp linux-3.0-orig/fs/compat_ioctl.c linux-3.0/fs/compat_ioctl.c --- linux-3.0-orig/fs/compat_ioctl.c 2011-07-27 11:32:10.188008559 +0900 +++ linux-3.0/fs/compat_ioctl.c 2011-07-27 11:34:42.844014535 +0900 @@ -882,6 +882,7 @@ COMPATIBLE_IOCTL(FIBMAP) COMPATIBLE_IOCTL(FIGETBSZ) /* 'X' - originally XFS but some now in the VFS */ COMPATIBLE_IOCTL(FIFREEZE) +COMPATIBLE_IOCTL(FIGETFREEZEFD) COMPATIBLE_IOCTL(FITHAW) COMPATIBLE_IOCTL(FIISFROZEN) COMPATIBLE_IOCTL(KDGETKEYCODE) diff -urNp linux-3.0-orig/fs/ioctl.c linux-3.0/fs/ioctl.c --- linux-3.0-orig/fs/ioctl.c 2011-07-27 11:32:10.188008559 +0900 +++ linux-3.0/fs/ioctl.c 2011-07-27 12:24:54.116004298 +0900 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -525,6 +526,80 @@ static int ioctl_fsfreeze(struct file *f return freeze_super(sb); } +struct freeze_fd_data { + struct super_block *sb; +}; + +static int freeze_fd_release(struct inode *inode, struct file *filp) +{ + struct freeze_fd_data *fd_data = filp->private_data; + struct super_block *sb = fd_data->sb; + + thaw_super(sb); + deactivate_super(sb); + kfree(fd_data); + + return 0; +} + +static struct file_operations freeze_fd_fops = { + .release = freeze_fd_release, + .llseek = noop_llseek, +}; + +static int ioctl_get_freeze_fd(struct file *filp, int __user *argp) +{ + struct super_block *sb = filp->f_path.dentry->d_inode->i_sb; + int fd, ret; + struct file *file; + struct freeze_fd_data *fd_data; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* If filesystem doesn't support freeze feature, return. */ + if (sb->s_op->freeze_fs == NULL) + return -EOPNOTSUPP; + + fd_data = kmalloc(sizeof(struct freeze_fd_data), GFP_KERNEL); + if (!fd_data) + return -ENOMEM; + + /* Get a file descriptor. */ + ret = get_unused_fd_flags(O_RDWR); + if (ret < 0) + goto err_free_fd_data; + fd = ret; + fd_data->sb = sb; + file = anon_inode_getfile("freeze-fd", + &freeze_fd_fops, fd_data, O_RDWR); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto err_put_fd; + } + + /* Increment the active counter to keep the superblock around + * until the freeze fd is closed. + */ + atomic_inc(&sb->s_active); + + ret = freeze_super(sb); + if (ret < 0) + goto err_deact_super; + + fd_install(fd, file); + + return fd; + +err_deact_super: + deactivate_super(sb); +err_put_fd: + put_unused_fd(fd); +err_free_fd_data: + kfree(fd_data); + return ret; +} + static int ioctl_fsthaw(struct file *filp) { struct super_block *sb = filp->f_path.dentry->d_inode->i_sb; @@ -591,6 +666,10 @@ int do_vfs_ioctl(struct file *filp, unsi error = ioctl_fsfreeze(filp); break; + case FIGETFREEZEFD: + error = ioctl_get_freeze_fd(filp, argp); + break; + case FITHAW: error = ioctl_fsthaw(filp); break; diff -urNp linux-3.0-orig/include/linux/fs.h linux-3.0/include/linux/fs.h --- linux-3.0-orig/include/linux/fs.h 2011-07-27 11:32:12.700001748 +0900 +++ linux-3.0/include/linux/fs.h 2011-07-27 11:57:14.832000721 +0900 @@ -326,6 +326,7 @@ struct inodes_stat_t { #define FITHAW _IOWR('X', 120, int) /* Thaw */ #define FITRIM _IOWR('X', 121, struct fstrim_range) /* Trim */ #define FIISFROZEN _IOR('X', 122, int) /* get sb freeze state */ +#define FIGETFREEZEFD _IOWR('X', 123, int) #define FS_IOC_GETFLAGS _IOR('f', 1, long) #define FS_IOC_SETFLAGS _IOW('f', 2, long)