LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC PATCH 1/3] Implement generic freeze feature
@ 2008-04-01 12:17 Takashi Sato
0 siblings, 0 replies; 12+ messages in thread
From: Takashi Sato @ 2008-04-01 12:17 UTC (permalink / raw)
To: David Chinner; +Cc: linux-ext4, xfs, linux-fsdevel, dm-devel, linux-kernel
The ioctls for the generic freeze feature are below.
o Freeze the filesystem
int ioctl(int fd, int FIFREEZE, arg)
fd: The file descriptor of the mountpoint
FIFREEZE: request code for the freeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
o Unfreeze the filesystem
int ioctl(int fd, int FITHAW, arg)
fd: The file descriptor of the mountpoint
FITHAW: request code for unfreeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com>
Signed-off-by: Masayuki Hamaguchi <m-hamaguchi@ys.jp.nec.com>
---
fs/block_dev.c | 3 +++
fs/buffer.c | 25 +++++++++++++++++++++++++
fs/ioctl.c | 35 +++++++++++++++++++++++++++++++++++
fs/super.c | 32 +++++++++++++++++++++++++++++++-
include/linux/fs.h | 7 +++++++
5 files changed, 101 insertions(+), 1 deletion(-)
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25-rc7.org/fs/block_dev.c linux-2.6.25-rc7-freeze/fs/block_
dev.c
--- linux-2.6.25-rc7.org/fs/block_dev.c 2008-03-26 10:38:14.000000000 +0900
+++ linux-2.6.25-rc7-freeze/fs/block_dev.c 2008-03-27 09:26:36.000000000 +0900
@@ -284,6 +284,9 @@ static void init_once(struct kmem_cache
INIT_LIST_HEAD(&bdev->bd_holder_list);
#endif
inode_init_once(&ei->vfs_inode);
+
+ /* Initialize semaphore for freeze. */
+ sema_init(&bdev->bd_freeze_sem, 1);
}
static inline void __bd_forget(struct inode *inode)
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25-rc7.org/fs/buffer.c linux-2.6.25-rc7-freeze/fs/buffer.c
--- linux-2.6.25-rc7.org/fs/buffer.c 2008-03-26 10:38:14.000000000 +0900
+++ linux-2.6.25-rc7-freeze/fs/buffer.c 2008-03-26 20:32:23.000000000 +0900
@@ -201,6 +201,19 @@ struct super_block *freeze_bdev(struct b
{
struct super_block *sb;
+ down(&bdev->bd_freeze_sem);
+ sb = get_super_without_lock(bdev);
+
+ /* If super_block has been already frozen, return. */
+ if (sb && sb->s_frozen != SB_UNFROZEN) {
+ put_super(sb);
+ up(&bdev->bd_freeze_sem);
+ return sb;
+ }
+
+ if (sb)
+ put_super(sb);
+
down(&bdev->bd_mount_sem);
sb = get_super(bdev);
if (sb && !(sb->s_flags & MS_RDONLY)) {
@@ -219,6 +232,9 @@ struct super_block *freeze_bdev(struct b
}
sync_blockdev(bdev);
+
+ up(&bdev->bd_freeze_sem);
+
return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
}
EXPORT_SYMBOL(freeze_bdev);
@@ -232,6 +248,13 @@ EXPORT_SYMBOL(freeze_bdev);
*/
void thaw_bdev(struct block_device *bdev, struct super_block *sb)
{
+ down(&bdev->bd_freeze_sem);
+
+ if (sb && sb->s_frozen == SB_UNFROZEN) {
+ up(&bdev->bd_freeze_sem);
+ return;
+ }
+
if (sb) {
BUG_ON(sb->s_bdev != bdev);
@@ -244,6 +267,8 @@ void thaw_bdev(struct block_device *bdev
}
up(&bdev->bd_mount_sem);
+
+ up(&bdev->bd_freeze_sem);
}
EXPORT_SYMBOL(thaw_bdev);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25-rc7.org/fs/ioctl.c linux-2.6.25-rc7-freeze/fs/ioctl.c
--- linux-2.6.25-rc7.org/fs/ioctl.c 2008-03-26 10:38:14.000000000 +0900
+++ linux-2.6.25-rc7-freeze/fs/ioctl.c 2008-03-26 20:22:17.000000000 +0900
@@ -13,6 +13,7 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include <linux/buffer_head.h>
#include <asm/ioctls.h>
@@ -181,6 +182,40 @@ int do_vfs_ioctl(struct file *filp, unsi
} else
error = -ENOTTY;
break;
+
+ case FIFREEZE: {
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ error = -EPERM;
+ break;
+ }
+
+ /* If filesystem doesn't support freeze feature, return. */
+ if (sb->s_op->write_super_lockfs == NULL) {
+ error = -EINVAL;
+ break;
+ }
+
+ /* Freeze. */
+ freeze_bdev(sb->s_bdev);
+
+ break;
+ }
+
+ case FITHAW: {
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ error = -EPERM;
+ break;
+ }
+
+ /* Thaw. */
+ thaw_bdev(sb->s_bdev, sb);
+ break;
+ }
+
default:
if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25-rc7.org/fs/super.c linux-2.6.25-rc7-freeze/fs/super.c
--- linux-2.6.25-rc7.org/fs/super.c 2008-03-26 10:38:14.000000000 +0900
+++ linux-2.6.25-rc7-freeze/fs/super.c 2008-03-26 20:23:21.000000000 +0900
@@ -154,7 +154,7 @@ int __put_super_and_need_restart(struct
* Drops a temporary reference, frees superblock if there's no
* references left.
*/
-static void put_super(struct super_block *sb)
+void put_super(struct super_block *sb)
{
spin_lock(&sb_lock);
__put_super(sb);
@@ -507,6 +507,36 @@ rescan:
EXPORT_SYMBOL(get_super);
+/*
+ * get_super_without_lock - Get super_block from block_device without lock.
+ * @bdev: block device struct
+ *
+ * Scan the superblock list and finds the superblock of the file system
+ * mounted on the block device given. This doesn't lock anyone.
+ * %NULL is returned if no match is found.
+ */
+struct super_block *get_super_without_lock(struct block_device *bdev)
+{
+ struct super_block *sb;
+
+ if (!bdev)
+ return NULL;
+
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_bdev == bdev) {
+ if (sb->s_root) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ return sb;
+ }
+ }
+ }
+ spin_unlock(&sb_lock);
+ return NULL;
+}
+EXPORT_SYMBOL(get_super_without_lock);
+
struct super_block * user_get_super(dev_t dev)
{
struct super_block *sb;
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25-rc7.org/include/linux/fs.h linux-2.6.25-rc7-freeze/inclu
de/linux/fs.h
--- linux-2.6.25-rc7.org/include/linux/fs.h 2008-03-26 10:38:14.000000000 +0900
+++ linux-2.6.25-rc7-freeze/include/linux/fs.h 2008-03-26 20:27:44.000000000 +0900
@@ -223,6 +223,8 @@ extern int dir_notify_enable;
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
+#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
+#define FITHAW _IOWR('X', 120, int) /* Thaw */
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
@@ -548,6 +550,9 @@ struct block_device {
* care to not mess up bd_private for that case.
*/
unsigned long bd_private;
+
+ /* Semaphore for freeze */
+ struct semaphore bd_freeze_sem;
};
/*
@@ -1926,7 +1931,9 @@ extern int do_vfs_ioctl(struct file *fil
extern void get_filesystem(struct file_system_type *fs);
extern void put_filesystem(struct file_system_type *fs);
extern struct file_system_type *get_fs_type(const char *name);
+extern void put_super(struct super_block *sb);
extern struct super_block *get_super(struct block_device *);
+extern struct super_block *get_super_without_lock(struct block_device *);
extern struct super_block *user_get_super(dev_t);
extern void drop_super(struct super_block *sb);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-05-25 19:32 ` Christoph Hellwig
@ 2008-05-27 10:20 ` Takashi Sato
0 siblings, 0 replies; 12+ messages in thread
From: Takashi Sato @ 2008-05-27 10:20 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-ext4, xfs, dm-devel, linux-fsdevel, linux-kernel
Hi,
>> + if (test_and_set_bit(BD_FREEZE_OP, &bdev->bd_state))
>> + return ERR_PTR(-EBUSY);
>> +
>> + sb = get_super_without_lock(bdev);
>> +
>> + /* If super_block has been already frozen, return. */
>> + if (sb && sb->s_frozen != SB_UNFROZEN) {
>> + put_super(sb);
>> + clear_bit(BD_FREEZE_OP, &bdev->bd_state);
>> + return sb;
>> + }
>
> The BD_FREEZE_OP flag in the block_device already prevents multiple
> freezes for a singe block device, so there is no need for this
> additional check and the get_super_without_lock helper.
I think the above check is needed because BD_FREEZE_OP is used to
guarantee that the following two operations are done atomically.
1. Check if the filesystem has already been frozen.
(sb->s_frozen != SB_UNFROZEN)
2. Do the filesystem specific freeze operation
(write_super_lockfs)
The freeze operation can be done again for the frozen filesystem
unless the filesystem is checked.
And if write_super_lockfs doesn't consider that the filesystem
has already been frozen, a problem might occur.
>> down(&bdev->bd_mount_sem);
>
> And with that flag bd_mount_sem is also obsolete for preventing the
> multiple freeze operations.
bd_mount_sem is needed because it is used to guarantee that the freeze
operation never run while mounting (get_sb_bdev()).
> We still need investigate what
> synchronization we need vs unmount which also takes bd_mount_sem without
> every having document what it exactly protects.
And s_umount (semaphore) is acquired in get_user() (called by freeze_bdev())
to guarantee that unmount never run while the filesystem is frozen.
Cheers, Takashi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-05-22 8:50 Takashi Sato
@ 2008-05-25 19:32 ` Christoph Hellwig
2008-05-27 10:20 ` Takashi Sato
0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2008-05-25 19:32 UTC (permalink / raw)
To: Takashi Sato; +Cc: linux-ext4, xfs, dm-devel, linux-fsdevel, linux-kernel
> + if (test_and_set_bit(BD_FREEZE_OP, &bdev->bd_state))
> + return ERR_PTR(-EBUSY);
> +
> + sb = get_super_without_lock(bdev);
> +
> + /* If super_block has been already frozen, return. */
> + if (sb && sb->s_frozen != SB_UNFROZEN) {
> + put_super(sb);
> + clear_bit(BD_FREEZE_OP, &bdev->bd_state);
> + return sb;
> + }
The BD_FREEZE_OP flag in the block_device already prevents multiple
freezes for a singe block device, so there is no need for this
additional check and the get_super_without_lock helper.
> down(&bdev->bd_mount_sem);
And with that flag bd_mount_sem is also obsolete for preventing the
multiple freeze operations. We still need investigate what
synchronization we need vs unmount which also takes bd_mount_sem without
every having document what it exactly protects.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 1/3] Implement generic freeze feature
@ 2008-05-22 8:50 Takashi Sato
2008-05-25 19:32 ` Christoph Hellwig
0 siblings, 1 reply; 12+ messages in thread
From: Takashi Sato @ 2008-05-22 8:50 UTC (permalink / raw)
To: linux-ext4, xfs, dm-devel, linux-fsdevel; +Cc: linux-kernel
I have modified to set the suitable error number (EOPNOTSUPP)
in case the filesystem doesn't support the freeze feature.
This was pointed out by Andreas Dilger.
The ioctls for the generic freeze feature are below.
o Freeze the filesystem
int ioctl(int fd, int FIFREEZE, arg)
fd: The file descriptor of the mountpoint
FIFREEZE: request code for the freeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
o Unfreeze the filesystem
int ioctl(int fd, int FITHAW, arg)
fd: The file descriptor of the mountpoint
FITHAW: request code for unfreeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com>
Signed-off-by: Masayuki Hamaguchi <m-hamaguchi@ys.jp.nec.com>
---
fs/buffer.c | 30 ++++++++++++++++++++++++
fs/ioctl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
fs/super.c | 32 +++++++++++++++++++++++++-
include/linux/buffer_head.h | 2 -
include/linux/fs.h | 14 +++++++++++
5 files changed, 128 insertions(+), 3 deletions(-)
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc3.org/fs/buffer.c linux-2.6.26-rc3-freeze/fs/buffer.c
--- linux-2.6.26-rc3.org/fs/buffer.c 2008-05-19 06:36:41.000000000 +0900
+++ linux-2.6.26-rc3-freeze/fs/buffer.c 2008-05-19 21:03:29.000000000 +0900
@@ -201,6 +201,21 @@ struct super_block *freeze_bdev(struct b
{
struct super_block *sb;
+ if (test_and_set_bit(BD_FREEZE_OP, &bdev->bd_state))
+ return ERR_PTR(-EBUSY);
+
+ sb = get_super_without_lock(bdev);
+
+ /* If super_block has been already frozen, return. */
+ if (sb && sb->s_frozen != SB_UNFROZEN) {
+ put_super(sb);
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+ return sb;
+ }
+
+ if (sb)
+ put_super(sb);
+
down(&bdev->bd_mount_sem);
sb = get_super(bdev);
if (sb && !(sb->s_flags & MS_RDONLY)) {
@@ -219,6 +234,8 @@ struct super_block *freeze_bdev(struct b
}
sync_blockdev(bdev);
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+
return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
}
EXPORT_SYMBOL(freeze_bdev);
@@ -230,8 +247,17 @@ EXPORT_SYMBOL(freeze_bdev);
*
* Unlocks the filesystem and marks it writeable again after freeze_bdev().
*/
-void thaw_bdev(struct block_device *bdev, struct super_block *sb)
+int thaw_bdev(struct block_device *bdev, struct super_block *sb)
{
+
+ if (test_and_set_bit(BD_FREEZE_OP, &bdev->bd_state))
+ return -EBUSY;
+
+ if (sb && sb->s_frozen == SB_UNFROZEN) {
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+ return 0;
+ }
+
if (sb) {
BUG_ON(sb->s_bdev != bdev);
@@ -244,6 +270,8 @@ void thaw_bdev(struct block_device *bdev
}
up(&bdev->bd_mount_sem);
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+ return 0;
}
EXPORT_SYMBOL(thaw_bdev);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc3.org/fs/ioctl.c linux-2.6.26-rc3-freeze/fs/ioctl.c
--- linux-2.6.26-rc3.org/fs/ioctl.c 2008-05-19 06:36:41.000000000 +0900
+++ linux-2.6.26-rc3-freeze/fs/ioctl.c 2008-05-21 11:43:39.000000000 +0900
@@ -13,6 +13,7 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include <linux/buffer_head.h>
#include <asm/ioctls.h>
@@ -141,6 +142,49 @@ static int ioctl_fioasync(unsigned int f
}
/*
+ * ioctl_freeze - Freeze the filesystem.
+ *
+ * @filp: target file
+ *
+ * Call freeze_bdev() to freeze the filesystem.
+ */
+static int ioctl_freeze(struct file *filp)
+{
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /* If filesystem doesn't support freeze feature, return. */
+ if (sb->s_op->write_super_lockfs == NULL)
+ return -EOPNOTSUPP;
+
+ /* Freeze */
+ sb = freeze_bdev(sb->s_bdev);
+ if (IS_ERR(sb))
+ return PTR_ERR(sb);
+ return 0;
+}
+
+/*
+ * ioctl_thaw - Thaw the filesystem.
+ *
+ * @filp: target file
+ *
+ * Call thaw_bdev() to thaw the filesystem.
+ */
+static int ioctl_thaw(struct file *filp)
+{
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /* Thaw */
+ return thaw_bdev(sb->s_bdev, sb);
+}
+
+/*
* When you add any new common ioctls to the switches above and below
* please update compat_sys_ioctl() too.
*
@@ -181,6 +225,15 @@ int do_vfs_ioctl(struct file *filp, unsi
} else
error = -ENOTTY;
break;
+
+ case FIFREEZE:
+ error = ioctl_freeze(filp);
+ break;
+
+ case FITHAW:
+ error = ioctl_thaw(filp);
+ break;
+
default:
if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc3.org/fs/super.c linux-2.6.26-rc3-freeze/fs/super.c
--- linux-2.6.26-rc3.org/fs/super.c 2008-05-19 06:36:41.000000000 +0900
+++ linux-2.6.26-rc3-freeze/fs/super.c 2008-05-19 21:03:29.000000000 +0900
@@ -156,7 +156,7 @@ int __put_super_and_need_restart(struct
* Drops a temporary reference, frees superblock if there's no
* references left.
*/
-static void put_super(struct super_block *sb)
+void put_super(struct super_block *sb)
{
spin_lock(&sb_lock);
__put_super(sb);
@@ -509,6 +509,36 @@ rescan:
EXPORT_SYMBOL(get_super);
+/*
+ * get_super_without_lock - Get super_block from block_device without lock.
+ * @bdev: block device struct
+ *
+ * Scan the superblock list and finds the superblock of the file system
+ * mounted on the block device given. This doesn't lock anyone.
+ * %NULL is returned if no match is found.
+ */
+struct super_block *get_super_without_lock(struct block_device *bdev)
+{
+ struct super_block *sb;
+
+ if (!bdev)
+ return NULL;
+
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_bdev == bdev) {
+ if (sb->s_root) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ return sb;
+ }
+ }
+ }
+ spin_unlock(&sb_lock);
+ return NULL;
+}
+EXPORT_SYMBOL(get_super_without_lock);
+
struct super_block * user_get_super(dev_t dev)
{
struct super_block *sb;
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc3.org/include/linux/buffer_head.h linux-2.6.26-rc3-fre
eze/include/linux/buffer_head.h
--- linux-2.6.26-rc3.org/include/linux/buffer_head.h 2008-05-19 06:36:41.000000000 +0900
+++ linux-2.6.26-rc3-freeze/include/linux/buffer_head.h 2008-05-19 21:03:29.000000000 +0900
@@ -171,7 +171,7 @@ void __wait_on_buffer(struct buffer_head
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
int fsync_bdev(struct block_device *);
struct super_block *freeze_bdev(struct block_device *);
-void thaw_bdev(struct block_device *, struct super_block *);
+int thaw_bdev(struct block_device *, struct super_block *);
int fsync_super(struct super_block *);
int fsync_no_super(struct block_device *);
struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc3.org/include/linux/fs.h linux-2.6.26-rc3-freeze/inclu
de/linux/fs.h
--- linux-2.6.26-rc3.org/include/linux/fs.h 2008-05-19 06:36:41.000000000 +0900
+++ linux-2.6.26-rc3-freeze/include/linux/fs.h 2008-05-19 21:03:29.000000000 +0900
@@ -223,6 +223,8 @@ extern int dir_notify_enable;
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
+#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
+#define FITHAW _IOWR('X', 120, int) /* Thaw */
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
@@ -494,6 +496,13 @@ int pagecache_write_end(struct file *, s
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata);
+/*
+ * Bits in block_device.bd_state.
+ */
+enum bd_state {
+ BD_FREEZE_OP /* In freeze operation */
+};
+
struct backing_dev_info;
struct address_space {
struct inode *host; /* owner: inode, block_device */
@@ -547,6 +556,9 @@ struct block_device {
* care to not mess up bd_private for that case.
*/
unsigned long bd_private;
+
+ /* State of the block device. (Used by freeze feature) */
+ unsigned long bd_state;
};
/*
@@ -1964,7 +1976,9 @@ extern int do_vfs_ioctl(struct file *fil
extern void get_filesystem(struct file_system_type *fs);
extern void put_filesystem(struct file_system_type *fs);
extern struct file_system_type *get_fs_type(const char *name);
+extern void put_super(struct super_block *sb);
extern struct super_block *get_super(struct block_device *);
+extern struct super_block *get_super_without_lock(struct block_device *);
extern struct super_block *user_get_super(dev_t);
extern void drop_super(struct super_block *sb);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-05-20 3:57 ` Andreas Dilger
@ 2008-05-21 1:23 ` Takashi Sato
0 siblings, 0 replies; 12+ messages in thread
From: Takashi Sato @ 2008-05-21 1:23 UTC (permalink / raw)
To: Andreas Dilger; +Cc: linux-ext4, xfs, dm-devel, linux-fsdevel, linux-kernel
Hi,
Andreas Dilger wrote:
>> +static int ioctl_freeze(struct file *filp)
>> +{
>> + struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
>> +
>> + if (!capable(CAP_SYS_ADMIN))
>> + return -EPERM;
>> +
>> + /* If filesystem doesn't support freeze feature, return. */
>> + if (sb->s_op->write_super_lockfs == NULL)
>> + return -EINVAL;
>
> Should this be EINVAL, or EOPNOTSUPP? Usually EINVAL means there is
> something wrong with the passed ioctl parameters (e.g. bad value),
> while EOPNOTSUPP is "operation not supported" and makes more sense.
Sounds good.
I will send new patch-set which is rebased to 2.6.26-rc3 and includes
this fix, in this weekend.
Cheers, Takashi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-05-14 8:06 Takashi Sato
@ 2008-05-20 3:57 ` Andreas Dilger
2008-05-21 1:23 ` Takashi Sato
0 siblings, 1 reply; 12+ messages in thread
From: Andreas Dilger @ 2008-05-20 3:57 UTC (permalink / raw)
To: Takashi Sato; +Cc: linux-ext4, xfs, dm-devel, linux-fsdevel, linux-kernel
On May 14, 2008 17:06 +0900, Takashi Sato wrote:
> +static int ioctl_freeze(struct file *filp)
> +{
> + struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
> +
> + if (!capable(CAP_SYS_ADMIN))
> + return -EPERM;
> +
> + /* If filesystem doesn't support freeze feature, return. */
> + if (sb->s_op->write_super_lockfs == NULL)
> + return -EINVAL;
Should this be EINVAL, or EOPNOTSUPP? Usually EINVAL means there is
something wrong with the passed ioctl parameters (e.g. bad value),
while EOPNOTSUPP is "operation not supported" and makes more sense.
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 1/3] Implement generic freeze feature
@ 2008-05-14 8:06 Takashi Sato
2008-05-20 3:57 ` Andreas Dilger
0 siblings, 1 reply; 12+ messages in thread
From: Takashi Sato @ 2008-05-14 8:06 UTC (permalink / raw)
To: linux-ext4, xfs, dm-devel, linux-fsdevel; +Cc: linux-kernel
I have modified the following two points from the previous version.
These are suggested by Christoph Hellwig.
o Two helper functions for ioctls (ioctl_freeze and ioctl_thaw) are
added for the readability.
o The semaphore for the freeze operation is replaced with new bit
flag (bd_state) for the efficiency of the locking.
The ioctls for the generic freeze feature are below.
o Freeze the filesystem
int ioctl(int fd, int FIFREEZE, arg)
fd: The file descriptor of the mountpoint
FIFREEZE: request code for the freeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
o Unfreeze the filesystem
int ioctl(int fd, int FITHAW, arg)
fd: The file descriptor of the mountpoint
FITHAW: request code for unfreeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com>
Signed-off-by: Masayuki Hamaguchi <m-hamaguchi@ys.jp.nec.com>
---
fs/block_dev.c | 3 +++
fs/buffer.c | 25 +++++++++++++++++++++++++
fs/ioctl.c | 35 +++++++++++++++++++++++++++++++++++
fs/super.c | 32 +++++++++++++++++++++++++++++++-
include/linux/fs.h | 7 +++++++
5 files changed, 101 insertions(+), 1 deletion(-)
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc2.org/fs/buffer.c linux-2.6.26-rc2-bit/fs/buffer.c
--- linux-2.6.26-rc2.org/fs/buffer.c 2008-05-12 09:09:41.000000000 +0900
+++ linux-2.6.26-rc2-bit/fs/buffer.c 2008-05-12 11:20:19.000000000 +0900
@@ -201,6 +201,21 @@ struct super_block *freeze_bdev(struct b
{
struct super_block *sb;
+ if (test_and_set_bit(BD_FREEZE_OP, &bdev->bd_state))
+ return ERR_PTR(-EBUSY);
+
+ sb = get_super_without_lock(bdev);
+
+ /* If super_block has been already frozen, return. */
+ if (sb && sb->s_frozen != SB_UNFROZEN) {
+ put_super(sb);
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+ return sb;
+ }
+
+ if (sb)
+ put_super(sb);
+
down(&bdev->bd_mount_sem);
sb = get_super(bdev);
if (sb && !(sb->s_flags & MS_RDONLY)) {
@@ -219,6 +234,8 @@ struct super_block *freeze_bdev(struct b
}
sync_blockdev(bdev);
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+
return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
}
EXPORT_SYMBOL(freeze_bdev);
@@ -230,8 +247,17 @@ EXPORT_SYMBOL(freeze_bdev);
*
* Unlocks the filesystem and marks it writeable again after freeze_bdev().
*/
-void thaw_bdev(struct block_device *bdev, struct super_block *sb)
+int thaw_bdev(struct block_device *bdev, struct super_block *sb)
{
+
+ if (test_and_set_bit(BD_FREEZE_OP, &bdev->bd_state))
+ return -EBUSY;
+
+ if (sb && sb->s_frozen == SB_UNFROZEN) {
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+ return 0;
+ }
+
if (sb) {
BUG_ON(sb->s_bdev != bdev);
@@ -244,6 +270,8 @@ void thaw_bdev(struct block_device *bdev
}
up(&bdev->bd_mount_sem);
+ clear_bit(BD_FREEZE_OP, &bdev->bd_state);
+ return 0;
}
EXPORT_SYMBOL(thaw_bdev);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc2.org/fs/ioctl.c linux-2.6.26-rc2-bit/fs/ioctl.c
--- linux-2.6.26-rc2.org/fs/ioctl.c 2008-05-12 09:09:41.000000000 +0900
+++ linux-2.6.26-rc2-bit/fs/ioctl.c 2008-05-13 14:33:33.000000000 +0900
@@ -13,6 +13,7 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include <linux/buffer_head.h>
#include <asm/ioctls.h>
@@ -141,6 +142,49 @@ static int ioctl_fioasync(unsigned int f
}
/*
+ * ioctl_freeze - Freeze the filesystem.
+ *
+ * @filp: target file
+ *
+ * Call freeze_bdev() to freeze the filesystem.
+ */
+static int ioctl_freeze(struct file *filp)
+{
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /* If filesystem doesn't support freeze feature, return. */
+ if (sb->s_op->write_super_lockfs == NULL)
+ return -EINVAL;
+
+ /* Freeze */
+ sb = freeze_bdev(sb->s_bdev);
+ if (IS_ERR(sb))
+ return PTR_ERR(sb);
+ return 0;
+}
+
+/*
+ * ioctl_thaw - Thaw the filesystem.
+ *
+ * @filp: target file
+ *
+ * Call thaw_bdev() to thaw the filesystem.
+ */
+static int ioctl_thaw(struct file *filp)
+{
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /* Thaw */
+ return thaw_bdev(sb->s_bdev, sb);
+}
+
+/*
* When you add any new common ioctls to the switches above and below
* please update compat_sys_ioctl() too.
*
@@ -181,6 +225,15 @@ int do_vfs_ioctl(struct file *filp, unsi
} else
error = -ENOTTY;
break;
+
+ case FIFREEZE:
+ error = ioctl_freeze(filp);
+ break;
+
+ case FITHAW:
+ error = ioctl_thaw(filp);
+ break;
+
default:
if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc2.org/fs/super.c linux-2.6.26-rc2-bit/fs/super.c
--- linux-2.6.26-rc2.org/fs/super.c 2008-05-12 09:09:41.000000000 +0900
+++ linux-2.6.26-rc2-bit/fs/super.c 2008-05-12 11:20:19.000000000 +0900
@@ -156,7 +156,7 @@ int __put_super_and_need_restart(struct
* Drops a temporary reference, frees superblock if there's no
* references left.
*/
-static void put_super(struct super_block *sb)
+void put_super(struct super_block *sb)
{
spin_lock(&sb_lock);
__put_super(sb);
@@ -509,6 +509,36 @@ rescan:
EXPORT_SYMBOL(get_super);
+/*
+ * get_super_without_lock - Get super_block from block_device without lock.
+ * @bdev: block device struct
+ *
+ * Scan the superblock list and finds the superblock of the file system
+ * mounted on the block device given. This doesn't lock anyone.
+ * %NULL is returned if no match is found.
+ */
+struct super_block *get_super_without_lock(struct block_device *bdev)
+{
+ struct super_block *sb;
+
+ if (!bdev)
+ return NULL;
+
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_bdev == bdev) {
+ if (sb->s_root) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ return sb;
+ }
+ }
+ }
+ spin_unlock(&sb_lock);
+ return NULL;
+}
+EXPORT_SYMBOL(get_super_without_lock);
+
struct super_block * user_get_super(dev_t dev)
{
struct super_block *sb;
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc2.org/include/linux/buffer_head.h linux-2.6.26-rc2-bit
/include/linux/buffer_head.h
--- linux-2.6.26-rc2.org/include/linux/buffer_head.h 2008-05-12 09:09:41.000000000 +0900
+++ linux-2.6.26-rc2-bit/include/linux/buffer_head.h 2008-05-12 11:20:19.000000000 +0900
@@ -171,7 +171,7 @@ void __wait_on_buffer(struct buffer_head
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
int fsync_bdev(struct block_device *);
struct super_block *freeze_bdev(struct block_device *);
-void thaw_bdev(struct block_device *, struct super_block *);
+int thaw_bdev(struct block_device *, struct super_block *);
int fsync_super(struct super_block *);
int fsync_no_super(struct block_device *);
struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.26-rc2.org/include/linux/fs.h linux-2.6.26-rc2-bit/include/
linux/fs.h
--- linux-2.6.26-rc2.org/include/linux/fs.h 2008-05-12 09:09:41.000000000 +0900
+++ linux-2.6.26-rc2-bit/include/linux/fs.h 2008-05-12 11:20:19.000000000 +0900
@@ -223,6 +223,8 @@ extern int dir_notify_enable;
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
+#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
+#define FITHAW _IOWR('X', 120, int) /* Thaw */
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
@@ -494,6 +496,13 @@ int pagecache_write_end(struct file *, s
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata);
+/*
+ * Bits in block_device.bd_state.
+ */
+enum bd_state {
+ BD_FREEZE_OP /* In freeze operation */
+};
+
struct backing_dev_info;
struct address_space {
struct inode *host; /* owner: inode, block_device */
@@ -547,6 +556,9 @@ struct block_device {
* care to not mess up bd_private for that case.
*/
unsigned long bd_private;
+
+ /* State of the block device. (Used by freeze feature) */
+ unsigned long bd_state;
};
/*
@@ -1964,7 +1976,9 @@ extern int do_vfs_ioctl(struct file *fil
extern void get_filesystem(struct file_system_type *fs);
extern void put_filesystem(struct file_system_type *fs);
extern struct file_system_type *get_fs_type(const char *name);
+extern void put_super(struct super_block *sb);
extern struct super_block *get_super(struct block_device *);
+extern struct super_block *get_super_without_lock(struct block_device *);
extern struct super_block *user_get_super(dev_t);
extern void drop_super(struct super_block *sb);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-04-28 13:03 ` Christoph Hellwig
@ 2008-04-30 1:10 ` Takashi Sato
0 siblings, 0 replies; 12+ messages in thread
From: Takashi Sato @ 2008-04-30 1:10 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-kernel, linux-fsdevel, dm-devel, xfs, linux-ext4
Hi,
>> bd_mount_sem can protect against only freezes and cannot protect against
>> unfreezes. If multiple unfreezes run in parallel, the multiple up() for
>> bd_mount_sem might occur incorrectly.
>
> Indeed. The bit flag would fix that because unfreeze could then check
> for the bit beeing set first. So that's probably the easiest way to go.
I think the bit flag is more efficient than the semaphore.
So I will consider whether it can be used for the freeze feature.
Cheers, Takashi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-04-28 12:59 ` Takashi Sato
@ 2008-04-28 13:03 ` Christoph Hellwig
2008-04-30 1:10 ` Takashi Sato
0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2008-04-28 13:03 UTC (permalink / raw)
To: Takashi Sato
Cc: Christoph Hellwig, linux-ext4, xfs, dm-devel, linux-fsdevel,
linux-kernel
On Mon, Apr 28, 2008 at 09:59:55PM +0900, Takashi Sato wrote:
>> I think the protection against double freezes would be better done by
>> using a trylock on bd_mount_sem.
>
> bd_mount_sem can protect against only freezes and cannot protect against
> unfreezes. If multiple unfreezes run in parallel, the multiple up() for
> bd_mount_sem might occur incorrectly.
Indeed. The bit flag would fix that because unfreeze could then check
for the bit beeing set first. So that's probably the easiest way to go.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-04-28 10:37 ` Christoph Hellwig
@ 2008-04-28 12:59 ` Takashi Sato
2008-04-28 13:03 ` Christoph Hellwig
0 siblings, 1 reply; 12+ messages in thread
From: Takashi Sato @ 2008-04-28 12:59 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-ext4, xfs, dm-devel, linux-fsdevel, linux-kernel
Hi,
> On Mon, Apr 28, 2008 at 07:31:23PM +0900, Takashi Sato wrote:
>> + /* Initialize semaphore for freeze. */
>> + sema_init(&bdev->bd_freeze_sem, 1);
>
> The freezing process is already protected by bd_mount_sem, so I don't
> think there's need for another one.
>
[...]
>> down(&bdev->bd_mount_sem);
>> sb = get_super(bdev);
>
> I think the protection against double freezes would be better done by
> using a trylock on bd_mount_sem.
bd_mount_sem can protect against only freezes and cannot protect against
unfreezes. If multiple unfreezes run in parallel, the multiple up() for
bd_mount_sem might occur incorrectly.
> In fact after that it could be changed
> from a semaphore to a simple test_and_set_bit.
I will consider using test_and_set_bit.
>> error = -ENOTTY;
>> break;
>> +
>> + case FIFREEZE: {
>
> This would be better to split intot a small helper ala ioctl_fibmap()
>
>> + case FITHAW: {
>
> Same here.
OK. I will split small helper functions.
Cheers, Takashi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/3] Implement generic freeze feature
2008-04-28 10:31 Takashi Sato
@ 2008-04-28 10:37 ` Christoph Hellwig
2008-04-28 12:59 ` Takashi Sato
0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2008-04-28 10:37 UTC (permalink / raw)
To: Takashi Sato; +Cc: linux-ext4, xfs, dm-devel, linux-fsdevel, linux-kernel
On Mon, Apr 28, 2008 at 07:31:23PM +0900, Takashi Sato wrote:
> + /* Initialize semaphore for freeze. */
> + sema_init(&bdev->bd_freeze_sem, 1);
The freezing process is already protected by bd_mount_sem, so I don't
think there's need for another one.
> --- linux-2.6.25.org/fs/buffer.c 2008-04-17 11:49:44.000000000 +0900
> +++ linux-2.6.25-freeze/fs/buffer.c 2008-04-24 20:43:28.000000000 +0900
> @@ -201,6 +201,19 @@ struct super_block *freeze_bdev(struct b
> {
> struct super_block *sb;
>
> + down(&bdev->bd_freeze_sem);
> + sb = get_super_without_lock(bdev);
> +
> + /* If super_block has been already frozen, return. */
> + if (sb && sb->s_frozen != SB_UNFROZEN) {
> + put_super(sb);
> + up(&bdev->bd_freeze_sem);
> + return sb;
> + }
> +
> + if (sb)
> + put_super(sb);
> +
> down(&bdev->bd_mount_sem);
> sb = get_super(bdev);
I think the protection against double freezes would be better done by
using a trylock on bd_mount_sem. In fact after that it could be changed
from a semaphore to a simple test_and_set_bit.
> error = -ENOTTY;
> break;
> +
> + case FIFREEZE: {
This would be better to split intot a small helper ala ioctl_fibmap()
> + case FITHAW: {
Same here.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 1/3] Implement generic freeze feature
@ 2008-04-28 10:31 Takashi Sato
2008-04-28 10:37 ` Christoph Hellwig
0 siblings, 1 reply; 12+ messages in thread
From: Takashi Sato @ 2008-04-28 10:31 UTC (permalink / raw)
To: linux-ext4, xfs, dm-devel, linux-fsdevel; +Cc: linux-kernel
The ioctls for the generic freeze feature are below.
o Freeze the filesystem
int ioctl(int fd, int FIFREEZE, arg)
fd: The file descriptor of the mountpoint
FIFREEZE: request code for the freeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
o Unfreeze the filesystem
int ioctl(int fd, int FITHAW, arg)
fd: The file descriptor of the mountpoint
FITHAW: request code for unfreeze
arg: Ignored
Return value: 0 if the operation succeeds. Otherwise, -1
Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com>
Signed-off-by: Masayuki Hamaguchi <m-hamaguchi@ys.jp.nec.com>
---
fs/block_dev.c | 3 +++
fs/buffer.c | 25 +++++++++++++++++++++++++
fs/ioctl.c | 35 +++++++++++++++++++++++++++++++++++
fs/super.c | 32 +++++++++++++++++++++++++++++++-
include/linux/fs.h | 7 +++++++
5 files changed, 101 insertions(+), 1 deletion(-)
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25.org/fs/block_dev.c linux-2.6.25-freeze/fs/block_dev.c
--- linux-2.6.25.org/fs/block_dev.c 2008-04-17 11:49:44.000000000 +0900
+++ linux-2.6.25-freeze/fs/block_dev.c 2008-04-24 20:43:28.000000000 +0900
@@ -284,6 +284,9 @@ static void init_once(struct kmem_cache
INIT_LIST_HEAD(&bdev->bd_holder_list);
#endif
inode_init_once(&ei->vfs_inode);
+
+ /* Initialize semaphore for freeze. */
+ sema_init(&bdev->bd_freeze_sem, 1);
}
static inline void __bd_forget(struct inode *inode)
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25.org/fs/buffer.c linux-2.6.25-freeze/fs/buffer.c
--- linux-2.6.25.org/fs/buffer.c 2008-04-17 11:49:44.000000000 +0900
+++ linux-2.6.25-freeze/fs/buffer.c 2008-04-24 20:43:28.000000000 +0900
@@ -201,6 +201,19 @@ struct super_block *freeze_bdev(struct b
{
struct super_block *sb;
+ down(&bdev->bd_freeze_sem);
+ sb = get_super_without_lock(bdev);
+
+ /* If super_block has been already frozen, return. */
+ if (sb && sb->s_frozen != SB_UNFROZEN) {
+ put_super(sb);
+ up(&bdev->bd_freeze_sem);
+ return sb;
+ }
+
+ if (sb)
+ put_super(sb);
+
down(&bdev->bd_mount_sem);
sb = get_super(bdev);
if (sb && !(sb->s_flags & MS_RDONLY)) {
@@ -219,6 +232,9 @@ struct super_block *freeze_bdev(struct b
}
sync_blockdev(bdev);
+
+ up(&bdev->bd_freeze_sem);
+
return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
}
EXPORT_SYMBOL(freeze_bdev);
@@ -232,6 +248,13 @@ EXPORT_SYMBOL(freeze_bdev);
*/
void thaw_bdev(struct block_device *bdev, struct super_block *sb)
{
+ down(&bdev->bd_freeze_sem);
+
+ if (sb && sb->s_frozen == SB_UNFROZEN) {
+ up(&bdev->bd_freeze_sem);
+ return;
+ }
+
if (sb) {
BUG_ON(sb->s_bdev != bdev);
@@ -244,6 +267,8 @@ void thaw_bdev(struct block_device *bdev
}
up(&bdev->bd_mount_sem);
+
+ up(&bdev->bd_freeze_sem);
}
EXPORT_SYMBOL(thaw_bdev);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25.org/fs/ioctl.c linux-2.6.25-freeze/fs/ioctl.c
--- linux-2.6.25.org/fs/ioctl.c 2008-04-17 11:49:44.000000000 +0900
+++ linux-2.6.25-freeze/fs/ioctl.c 2008-04-24 20:43:28.000000000 +0900
@@ -13,6 +13,7 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include <linux/buffer_head.h>
#include <asm/ioctls.h>
@@ -181,6 +182,40 @@ int do_vfs_ioctl(struct file *filp, unsi
} else
error = -ENOTTY;
break;
+
+ case FIFREEZE: {
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ error = -EPERM;
+ break;
+ }
+
+ /* If filesystem doesn't support freeze feature, return. */
+ if (sb->s_op->write_super_lockfs == NULL) {
+ error = -EINVAL;
+ break;
+ }
+
+ /* Freeze. */
+ freeze_bdev(sb->s_bdev);
+
+ break;
+ }
+
+ case FITHAW: {
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ error = -EPERM;
+ break;
+ }
+
+ /* Thaw. */
+ thaw_bdev(sb->s_bdev, sb);
+ break;
+ }
+
default:
if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25.org/fs/super.c linux-2.6.25-freeze/fs/super.c
--- linux-2.6.25.org/fs/super.c 2008-04-17 11:49:44.000000000 +0900
+++ linux-2.6.25-freeze/fs/super.c 2008-04-24 20:43:28.000000000 +0900
@@ -154,7 +154,7 @@ int __put_super_and_need_restart(struct
* Drops a temporary reference, frees superblock if there's no
* references left.
*/
-static void put_super(struct super_block *sb)
+void put_super(struct super_block *sb)
{
spin_lock(&sb_lock);
__put_super(sb);
@@ -507,6 +507,36 @@ rescan:
EXPORT_SYMBOL(get_super);
+/*
+ * get_super_without_lock - Get super_block from block_device without lock.
+ * @bdev: block device struct
+ *
+ * Scan the superblock list and finds the superblock of the file system
+ * mounted on the block device given. This doesn't lock anyone.
+ * %NULL is returned if no match is found.
+ */
+struct super_block *get_super_without_lock(struct block_device *bdev)
+{
+ struct super_block *sb;
+
+ if (!bdev)
+ return NULL;
+
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_bdev == bdev) {
+ if (sb->s_root) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ return sb;
+ }
+ }
+ }
+ spin_unlock(&sb_lock);
+ return NULL;
+}
+EXPORT_SYMBOL(get_super_without_lock);
+
struct super_block * user_get_super(dev_t dev)
{
struct super_block *sb;
diff -uprN -X /home/sho/pub/MC/freeze-set/dontdiff linux-2.6.25.org/include/linux/fs.h linux-2.6.25-freeze/include/linux
/fs.h
--- linux-2.6.25.org/include/linux/fs.h 2008-04-17 11:49:44.000000000 +0900
+++ linux-2.6.25-freeze/include/linux/fs.h 2008-04-24 20:43:28.000000000 +0900
@@ -223,6 +223,8 @@ extern int dir_notify_enable;
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
+#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
+#define FITHAW _IOWR('X', 120, int) /* Thaw */
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
@@ -548,6 +550,9 @@ struct block_device {
* care to not mess up bd_private for that case.
*/
unsigned long bd_private;
+
+ /* Semaphore for freeze */
+ struct semaphore bd_freeze_sem;
};
/*
@@ -1926,7 +1931,9 @@ extern int do_vfs_ioctl(struct file *fil
extern void get_filesystem(struct file_system_type *fs);
extern void put_filesystem(struct file_system_type *fs);
extern struct file_system_type *get_fs_type(const char *name);
+extern void put_super(struct super_block *sb);
extern struct super_block *get_super(struct block_device *);
+extern struct super_block *get_super_without_lock(struct block_device *);
extern struct super_block *user_get_super(dev_t);
extern void drop_super(struct super_block *sb);
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-05-27 10:20 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-01 12:17 [RFC PATCH 1/3] Implement generic freeze feature Takashi Sato
2008-04-28 10:31 Takashi Sato
2008-04-28 10:37 ` Christoph Hellwig
2008-04-28 12:59 ` Takashi Sato
2008-04-28 13:03 ` Christoph Hellwig
2008-04-30 1:10 ` Takashi Sato
2008-05-14 8:06 Takashi Sato
2008-05-20 3:57 ` Andreas Dilger
2008-05-21 1:23 ` Takashi Sato
2008-05-22 8:50 Takashi Sato
2008-05-25 19:32 ` Christoph Hellwig
2008-05-27 10:20 ` Takashi Sato
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).