Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 197954
b: refs/heads/master
c: 18e9e51
h: refs/heads/master
v: v3
  • Loading branch information
Josef Bacik authored and Al Viro committed May 21, 2010
1 parent 2109045 commit 72d5efb
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 72 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e1e46bf1866317d4f86f66bf18d3f07317d9f9ee
refs/heads/master: 18e9e5104fcd9a973ffe3eed3816c87f2a1b6cd2
74 changes: 16 additions & 58 deletions trunk/fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,38 +245,14 @@ struct super_block *freeze_bdev(struct block_device *bdev)
sb = get_active_super(bdev);
if (!sb)
goto out;
down_write(&sb->s_umount);
if (sb->s_flags & MS_RDONLY) {
sb->s_frozen = SB_FREEZE_TRANS;
up_write(&sb->s_umount);
error = freeze_super(sb);
if (error) {
deactivate_super(sb);
bdev->bd_fsfreeze_count--;
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return sb;
}

sb->s_frozen = SB_FREEZE_WRITE;
smp_wmb();

sync_filesystem(sb);

sb->s_frozen = SB_FREEZE_TRANS;
smp_wmb();

sync_blockdev(sb->s_bdev);

if (sb->s_op->freeze_fs) {
error = sb->s_op->freeze_fs(sb);
if (error) {
printk(KERN_ERR
"VFS:Filesystem freeze failed\n");
sb->s_frozen = SB_UNFROZEN;
deactivate_locked_super(sb);
bdev->bd_fsfreeze_count--;
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return ERR_PTR(error);
}
return ERR_PTR(error);
}
up_write(&sb->s_umount);

deactivate_super(sb);
out:
sync_blockdev(bdev);
mutex_unlock(&bdev->bd_fsfreeze_mutex);
Expand All @@ -297,40 +273,22 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)

mutex_lock(&bdev->bd_fsfreeze_mutex);
if (!bdev->bd_fsfreeze_count)
goto out_unlock;
goto out;

error = 0;
if (--bdev->bd_fsfreeze_count > 0)
goto out_unlock;
goto out;

if (!sb)
goto out_unlock;

BUG_ON(sb->s_bdev != bdev);
down_write(&sb->s_umount);
if (sb->s_flags & MS_RDONLY)
goto out_unfrozen;

if (sb->s_op->unfreeze_fs) {
error = sb->s_op->unfreeze_fs(sb);
if (error) {
printk(KERN_ERR
"VFS:Filesystem thaw failed\n");
sb->s_frozen = SB_FREEZE_TRANS;
bdev->bd_fsfreeze_count++;
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return error;
}
}

out_unfrozen:
sb->s_frozen = SB_UNFROZEN;
smp_wmb();
wake_up(&sb->s_wait_unfrozen);
goto out;

if (sb)
deactivate_locked_super(sb);
out_unlock:
error = thaw_super(sb);
if (error) {
bdev->bd_fsfreeze_count++;
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return error;
}
out:
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return 0;
}
Expand Down
15 changes: 2 additions & 13 deletions trunk/fs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,15 +525,8 @@ static int ioctl_fsfreeze(struct file *filp)
if (sb->s_op->freeze_fs == NULL)
return -EOPNOTSUPP;

/* If a blockdevice-backed filesystem isn't specified, return. */
if (sb->s_bdev == NULL)
return -EINVAL;

/* Freeze */
sb = freeze_bdev(sb->s_bdev);
if (IS_ERR(sb))
return PTR_ERR(sb);
return 0;
return freeze_super(sb);
}

static int ioctl_fsthaw(struct file *filp)
Expand All @@ -543,12 +536,8 @@ static int ioctl_fsthaw(struct file *filp)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;

/* If a blockdevice-backed filesystem isn't specified, return EINVAL. */
if (sb->s_bdev == NULL)
return -EINVAL;

/* Thaw */
return thaw_bdev(sb->s_bdev, sb);
return thaw_super(sb);
}

/*
Expand Down
90 changes: 90 additions & 0 deletions trunk/fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,96 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void

EXPORT_SYMBOL_GPL(vfs_kern_mount);

/**
* freeze_super -- lock the filesystem and force it into a consistent state
* @super: the super to lock
*
* Syncs the super to make sure the filesystem is consistent and calls the fs's
* freeze_fs. Subsequent calls to this without first thawing the fs will return
* -EBUSY.
*/
int freeze_super(struct super_block *sb)
{
int ret;

atomic_inc(&sb->s_active);
down_write(&sb->s_umount);
if (sb->s_frozen) {
deactivate_locked_super(sb);
return -EBUSY;
}

if (sb->s_flags & MS_RDONLY) {
sb->s_frozen = SB_FREEZE_TRANS;
smp_wmb();
up_write(&sb->s_umount);
return 0;
}

sb->s_frozen = SB_FREEZE_WRITE;
smp_wmb();

sync_filesystem(sb);

sb->s_frozen = SB_FREEZE_TRANS;
smp_wmb();

sync_blockdev(sb->s_bdev);
if (sb->s_op->freeze_fs) {
ret = sb->s_op->freeze_fs(sb);
if (ret) {
printk(KERN_ERR
"VFS:Filesystem freeze failed\n");
sb->s_frozen = SB_UNFROZEN;
deactivate_locked_super(sb);
return ret;
}
}
up_write(&sb->s_umount);
return 0;
}
EXPORT_SYMBOL(freeze_super);

/**
* thaw_super -- unlock filesystem
* @sb: the super to thaw
*
* Unlocks the filesystem and marks it writeable again after freeze_super().
*/
int thaw_super(struct super_block *sb)
{
int error;

down_write(&sb->s_umount);
if (sb->s_frozen == SB_UNFROZEN) {
up_write(&sb->s_umount);
return -EINVAL;
}

if (sb->s_flags & MS_RDONLY)
goto out;

if (sb->s_op->unfreeze_fs) {
error = sb->s_op->unfreeze_fs(sb);
if (error) {
printk(KERN_ERR
"VFS:Filesystem thaw failed\n");
sb->s_frozen = SB_FREEZE_TRANS;
up_write(&sb->s_umount);
return error;
}
}

out:
sb->s_frozen = SB_UNFROZEN;
smp_wmb();
wake_up(&sb->s_wait_unfrozen);
deactivate_locked_super(sb);

return 0;
}
EXPORT_SYMBOL(thaw_super);

static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
{
int err;
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,8 @@ extern void drop_collected_mounts(struct vfsmount *);
extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
struct vfsmount *);
extern int vfs_statfs(struct dentry *, struct kstatfs *);
extern int freeze_super(struct super_block *super);
extern int thaw_super(struct super_block *super);

extern int current_umask(void);

Expand Down

0 comments on commit 72d5efb

Please sign in to comment.