* [PATCH 1/4] fsfreeze: add vfs ioctl to check freeze state
2011-07-27 7:30 ` [RFC][PATCH 0/4] fsfreeze: new API Fernando Luis Vazquez Cao
@ 2011-07-27 7:32 ` Fernando Luis Vazquez Cao
2011-07-27 7:34 ` [PATCH 2/4] fsfreeze: add block device " Fernando Luis Vazquez Cao
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Fernando Luis Vazquez Cao @ 2011-07-27 7:32 UTC (permalink / raw)
To: Al Viro
Cc: Christoph Hellwig, Eric Sandeen, Josef Bacik, linux-fsdevel,
Ric Wheeler, James Bottomley, Theodore Ts'o
The FIISFROZEN ioctl can be use by HA and monitoring software to check
the freeze state of a mounted filesystem.
Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
---
diff -urNp linux-3.0-rc7-orig/fs/compat_ioctl.c linux-3.0-rc7/fs/compat_ioctl.c
--- linux-3.0-rc7-orig/fs/compat_ioctl.c 2011-05-19 13:06:34.000000000 +0900
+++ linux-3.0-rc7/fs/compat_ioctl.c 2011-07-20 15:33:40.615998033 +0900
@@ -883,6 +883,7 @@ COMPATIBLE_IOCTL(FIGETBSZ)
/* 'X' - originally XFS but some now in the VFS */
COMPATIBLE_IOCTL(FIFREEZE)
COMPATIBLE_IOCTL(FITHAW)
+COMPATIBLE_IOCTL(FIISFROZEN)
COMPATIBLE_IOCTL(KDGETKEYCODE)
COMPATIBLE_IOCTL(KDSETKEYCODE)
COMPATIBLE_IOCTL(KDGKBTYPE)
diff -urNp linux-3.0-rc7-orig/fs/ioctl.c linux-3.0-rc7/fs/ioctl.c
--- linux-3.0-rc7-orig/fs/ioctl.c 2011-05-19 13:06:34.000000000 +0900
+++ linux-3.0-rc7/fs/ioctl.c 2011-07-20 12:23:06.124003192 +0900
@@ -536,6 +536,16 @@ static int ioctl_fsthaw(struct file *fil
return thaw_super(sb);
}
+static int ioctl_fs_isfrozen(struct file *filp)
+{
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ return isfrozen_super(sb);
+}
+
/*
* When you add any new common ioctls to the switches above and below
* please update compat_sys_ioctl() too.
@@ -585,6 +595,12 @@ int do_vfs_ioctl(struct file *filp, unsi
error = ioctl_fsthaw(filp);
break;
+ case FIISFROZEN:
+ error = ioctl_fs_isfrozen(filp);
+ if (error >= 0)
+ return put_user(error, (int __user *)arg);
+ break;
+
case FS_IOC_FIEMAP:
return ioctl_fiemap(filp, arg);
diff -urNp linux-3.0-rc7-orig/fs/super.c linux-3.0-rc7/fs/super.c
--- linux-3.0-rc7-orig/fs/super.c 2011-07-12 09:55:50.804000002 +0900
+++ linux-3.0-rc7/fs/super.c 2011-07-19 17:45:56.816155171 +0900
@@ -1057,3 +1057,8 @@ out:
return 0;
}
EXPORT_SYMBOL(thaw_super);
+
+int isfrozen_super(struct super_block *sb)
+{
+ return sb->s_frozen > SB_UNFROZEN ? 1:0;
+}
diff -urNp linux-3.0-rc7-orig/include/linux/fs.h linux-3.0-rc7/include/linux/fs.h
--- linux-3.0-rc7-orig/include/linux/fs.h 2011-07-12 09:55:51.192000002 +0900
+++ linux-3.0-rc7/include/linux/fs.h 2011-07-20 12:27:59.443932676 +0900
@@ -324,6 +325,7 @@ struct inodes_stat_t {
#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
#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 FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
@@ -1882,6 +1884,7 @@ extern int fd_statfs(int, struct kstatfs
extern int statfs_by_dentry(struct dentry *, struct kstatfs *);
extern int freeze_super(struct super_block *super);
extern int thaw_super(struct super_block *super);
+extern int isfrozen_super(struct super_block *sb);
extern int current_umask(void);
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/4] fsfreeze: add block device ioctl to check freeze state
2011-07-27 7:30 ` [RFC][PATCH 0/4] fsfreeze: new API Fernando Luis Vazquez Cao
2011-07-27 7:32 ` [PATCH 1/4] fsfreeze: add vfs ioctl to check freeze state Fernando Luis Vazquez Cao
@ 2011-07-27 7:34 ` Fernando Luis Vazquez Cao
2011-07-27 7:35 ` [PATCH 3/4] fsfreeze: add ioctl to create a fd for freeze control Fernando Luis Vazquez Cao
2011-07-27 7:36 ` [PATCH 4/4] fsfreeze: add freeze fd ioctls Fernando Luis Vazquez Cao
3 siblings, 0 replies; 8+ messages in thread
From: Fernando Luis Vazquez Cao @ 2011-07-27 7:34 UTC (permalink / raw)
To: Al Viro
Cc: Christoph Hellwig, Eric Sandeen, Josef Bacik, linux-fsdevel,
Ric Wheeler, James Bottomley, Theodore Ts'o
The BLKISFROZEN ioctl can be use by HA and monitoring software to check
the freeze state of the filesystem sitting on top of a block device.
This will not work for filesystems that can handle multiple devices,
i.e. btrfs.
Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
---
diff -urNp linux-3.0-rc7-orig/block/compat_ioctl.c linux-3.0-rc7/block/compat_ioctl.c
--- linux-3.0-rc7-orig/block/compat_ioctl.c 2011-05-19 13:06:34.000000000 +0900
+++ linux-3.0-rc7/block/compat_ioctl.c 2011-07-20 15:20:31.439999983 +0900
@@ -757,6 +757,13 @@ long compat_blkdev_ioctl(struct file *fi
case BLKTRACETEARDOWN: /* compatible */
ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
return ret;
+ case BLKISFROZEN:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ ret = isfrozen_bdev(bdev);
+ if (ret >= 0)
+ return compat_put_int(arg, ret);
+ return ret;
default:
if (disk->fops->compat_ioctl)
ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
diff -urNp linux-3.0-rc7-orig/block/ioctl.c linux-3.0-rc7/block/ioctl.c
--- linux-3.0-rc7-orig/block/ioctl.c 2011-05-19 13:06:34.000000000 +0900
+++ linux-3.0-rc7/block/ioctl.c 2011-07-20 15:20:22.140020393 +0900
@@ -322,6 +322,13 @@ int blkdev_ioctl(struct block_device *bd
case BLKTRACETEARDOWN:
ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg);
break;
+ case BLKISFROZEN:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ ret = isfrozen_bdev(bdev);
+ if (ret >= 0)
+ return put_int(arg, ret);
+ return ret;
default:
ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
diff -urNp linux-3.0-rc7-orig/fs/block_dev.c linux-3.0-rc7/fs/block_dev.c
--- linux-3.0-rc7-orig/fs/block_dev.c 2011-07-12 09:55:49.656000005 +0900
+++ linux-3.0-rc7/fs/block_dev.c 2011-07-21 09:40:36.900005798 +0900
@@ -310,6 +310,25 @@ out:
}
EXPORT_SYMBOL(thaw_bdev);
+int isfrozen_bdev(struct block_device *bdev)
+{
+ int ret;
+ struct super_block *sb;
+
+ mutex_lock(&bdev->bd_fsfreeze_mutex);
+
+ ret = -EINVAL;
+ sb = get_active_super(bdev);
+ if (!sb)
+ goto out;
+ ret = isfrozen_super(sb);
+ deactivate_super(sb);
+out:
+ mutex_unlock(&bdev->bd_fsfreeze_mutex);
+
+ return ret;
+}
+
static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, blkdev_get_block, wbc);
diff -urNp linux-3.0-rc7-orig/include/linux/fs.h linux-3.0-rc7/include/linux/fs.h
--- linux-3.0-rc7-orig/include/linux/fs.h 2011-07-12 09:55:51.192000002 +0900
+++ linux-3.0-rc7/include/linux/fs.h 2011-07-20 12:27:59.443932676 +0900
@@ -317,6 +317,7 @@ struct inodes_stat_t {
#define BLKPBSZGET _IO(0x12,123)
#define BLKDISCARDZEROES _IO(0x12,124)
#define BLKSECDISCARD _IO(0x12,125)
+#define BLKISFROZEN _IOR(0x12,126, int) /* get file system freeze state */
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
@@ -2036,6 +2039,7 @@ extern int sync_blockdev(struct block_de
extern struct super_block *freeze_bdev(struct block_device *);
extern void emergency_thaw_all(void);
extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
+extern int isfrozen_bdev(struct block_device *bdev);
extern int fsync_bdev(struct block_device *);
#else
static inline void bd_forget(struct inode *inode) {}
@@ -2051,6 +2055,11 @@ static inline int thaw_bdev(struct block
{
return 0;
}
+
+static int isfrozen_bdev(struct block_device *bdev)
+{
+ return 0;
+}
#endif
extern int sync_filesystem(struct super_block *);
extern const struct file_operations def_blk_fops;
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/4] fsfreeze: add ioctl to create a fd for freeze control
2011-07-27 7:30 ` [RFC][PATCH 0/4] fsfreeze: new API Fernando Luis Vazquez Cao
2011-07-27 7:32 ` [PATCH 1/4] fsfreeze: add vfs ioctl to check freeze state Fernando Luis Vazquez Cao
2011-07-27 7:34 ` [PATCH 2/4] fsfreeze: add block device " Fernando Luis Vazquez Cao
@ 2011-07-27 7:35 ` Fernando Luis Vazquez Cao
2011-07-27 7:36 ` [PATCH 4/4] fsfreeze: add freeze fd ioctls Fernando Luis Vazquez Cao
3 siblings, 0 replies; 8+ messages in thread
From: Fernando Luis Vazquez Cao @ 2011-07-27 7:35 UTC (permalink / raw)
To: Al Viro
Cc: Christoph Hellwig, Eric Sandeen, Josef Bacik, linux-fsdevel,
Ric Wheeler, James Bottomley, Theodore Ts'o
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@oss.ntt.co.jp>
---
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)
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/4] fsfreeze: add freeze fd ioctls
2011-07-27 7:30 ` [RFC][PATCH 0/4] fsfreeze: new API Fernando Luis Vazquez Cao
` (2 preceding siblings ...)
2011-07-27 7:35 ` [PATCH 3/4] fsfreeze: add ioctl to create a fd for freeze control Fernando Luis Vazquez Cao
@ 2011-07-27 7:36 ` Fernando Luis Vazquez Cao
3 siblings, 0 replies; 8+ messages in thread
From: Fernando Luis Vazquez Cao @ 2011-07-27 7:36 UTC (permalink / raw)
To: Al Viro
Cc: Christoph Hellwig, Eric Sandeen, Josef Bacik, linux-fsdevel,
Ric Wheeler, James Bottomley, Theodore Ts'o
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@oss.ntt.co.jp>
---
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@rustcorp.com.au>
0xAE all linux/kvm.h Kernel-based Virtual Machine
<mailto:kvm@vger.kernel.org>
+0xAF 00-03 Filesystem freeze see fs/ioctl.c
+ <mailto:linux-fsdevel@vger.kernel.org>
0xB0 all RATIO devices in development:
<mailto:vgo@ratio.de>
0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
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)
^ permalink raw reply [flat|nested] 8+ messages in thread