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 <fernando@xxxxxxxxxxxxx> --- 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 <linux/uaccess.h> #include <linux/writeback.h> #include <linux/buffer_head.h> +#include <linux/anon_inodes.h> #include <linux/falloc.h> #include <asm/ioctls.h> @@ -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) -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html