[PATCH 4/4] fsfreeze: add freeze fd ioctls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adds new ioctls (FS_FREEZE_FD, FS_THAW_FD, FS_ISFROZEN_FD) that operate on the
freeze file descriptor; these can be used to freeze/thaw the filesystem and
check the freeze state of the filesystem, thus avoiding the need to get new
file descriptors constantly.

Additionaly, the argument of the ioctl FIGETFREEZEFD can now be used to
indicate whether we want the filesystem frozen at fd creation time (a non-zero
value means "freeze", 0 means "leave as is").

Signed-off-by: Fernando Luis Vazquez Cao <fernando@xxxxxxxxxxxxx>
---

diff -urNp linux-3.0-orig/Documentation/ioctl/ioctl-number.txt linux-3.0/Documentation/ioctl/ioctl-number.txt
--- linux-3.0-orig/Documentation/ioctl/ioctl-number.txt	2011-07-22 11:17:23.000000000 +0900
+++ linux-3.0/Documentation/ioctl/ioctl-number.txt	2011-07-27 15:13:45.583998849 +0900
@@ -301,6 +301,8 @@ Code  Seq#(hex)	Include File		Comments
 					<mailto:rusty@xxxxxxxxxxxxxxx>
 0xAE	all	linux/kvm.h		Kernel-based Virtual Machine
 					<mailto:kvm@xxxxxxxxxxxxxxx>
+0xAF	00-03	Filesystem freeze	see fs/ioctl.c
+					<mailto:linux-fsdevel@xxxxxxxxxxxxxxx>
 0xB0	all	RATIO devices		in development:
 					<mailto:vgo@xxxxxxxx>
 0xB1	00-1F	PPPoX			<mailto:mostrows@xxxxxxxxxxxxxxxxx>
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 15:12:22.876000730 +0900
+++ linux-3.0/fs/ioctl.c	2011-07-27 15:46:57.923998173 +0900
@@ -528,14 +528,48 @@ static int ioctl_fsfreeze(struct file *f
 
 struct freeze_fd_data {
 	struct super_block *sb;
+	int thaw_pending;
 };
 
+static long freeze_fd_ioctl(struct file *filp,
+			    unsigned int ioctl, unsigned long arg)
+{
+	struct freeze_fd_data *fd_data = filp->private_data;
+	struct super_block *sb = fd_data->sb;
+	int error = 0;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	switch (ioctl) {
+	case FS_FREEZE_FD:
+		error = freeze_super(sb);
+		if (!error)
+			fd_data->thaw_pending++;
+		break;
+	case FS_THAW_FD:
+		error = thaw_super(sb);
+		if (!error)
+			fd_data->thaw_pending--;
+		break;
+	case FS_ISFROZEN_FD:
+		error = isfrozen_super(sb);
+		if (error >= 0)
+			return put_user(error, (int __user *)arg);
+		break;
+	default:
+		error = -EINVAL;
+	}
+	return error;
+}
+
 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);
+	if (fd_data->thaw_pending)
+		thaw_super(sb);
 	deactivate_super(sb);
 	kfree(fd_data);
 
@@ -544,19 +578,25 @@ static int freeze_fd_release(struct inod
 
 static struct file_operations freeze_fd_fops = {
 	.release	= freeze_fd_release,
+	.unlocked_ioctl	= freeze_fd_ioctl,
+	.compat_ioctl	= freeze_fd_ioctl,
 	.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;
+	int fd, ret, should_freeze;
 	struct file *file;
 	struct freeze_fd_data *fd_data;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+	ret = get_user(should_freeze, argp);
+	if (ret)
+		return ret;
+
 	/* If filesystem doesn't support freeze feature, return. */
 	if (sb->s_op->freeze_fs == NULL)
 		return -EOPNOTSUPP;
@@ -571,6 +611,7 @@ static int ioctl_get_freeze_fd(struct fi
 		goto err_free_fd_data;
 	fd = ret;
 	fd_data->sb = sb;
+	fd_data->thaw_pending = 0;
 	file = anon_inode_getfile("freeze-fd",
 				  &freeze_fd_fops, fd_data, O_RDWR);
 	if (IS_ERR(file)) {
@@ -580,12 +621,19 @@ static int ioctl_get_freeze_fd(struct fi
 
 	/* Increment the active counter to keep the superblock around
 	 * until the freeze fd is closed.
+	 *
+	 * When should_freeze is set freeze_super() is called which takes an
+	 * active reference to the superblock. However that reference could be
+	 * released through ioctl_fsthaw, so we still need to take our own here.
 	 */
 	atomic_inc(&sb->s_active);
 
-	ret = freeze_super(sb);
-	if (ret < 0)
-		goto err_deact_super;
+	if (should_freeze) {
+		ret = freeze_super(sb);
+		if (ret < 0)
+			goto err_deact_super;
+		fd_data->thaw_pending++;
+	}
 
 	fd_install(fd, file);
 
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 15:12:22.876000730 +0900
+++ linux-3.0/include/linux/fs.h	2011-07-27 15:13:45.587999047 +0900
@@ -328,6 +328,10 @@ struct inodes_stat_t {
 #define FIISFROZEN	_IOR('X', 122, int)	/* get sb freeze state */
 #define FIGETFREEZEFD	_IOWR('X', 123, int)
 
+#define FS_FREEZE_FD	_IOWR(0xAF, 1, int)
+#define FS_THAW_FD	_IOWR(0xAF, 2, int)
+#define FS_ISFROZEN_FD	_IOR(0xAF, 3, int)
+
 #define	FS_IOC_GETFLAGS			_IOR('f', 1, long)
 #define	FS_IOC_SETFLAGS			_IOW('f', 2, long)
 #define	FS_IOC_GETVERSION		_IOR('v', 1, 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


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux