Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165874
b: refs/heads/master
c: 4504230
h: refs/heads/master
v: v3
  • Loading branch information
Christoph Hellwig authored and Al Viro committed Sep 24, 2009
1 parent 815a5e7 commit 3e010cf
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 62 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: 4fadd7bb20a1e7c774ed88dc703d8fbcd00ff917
refs/heads/master: 4504230a71566785a05d3e6b53fa1ee071b864eb
132 changes: 72 additions & 60 deletions trunk/fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,43 +230,54 @@ struct super_block *freeze_bdev(struct block_device *bdev)
int error = 0;

mutex_lock(&bdev->bd_fsfreeze_mutex);
if (bdev->bd_fsfreeze_count > 0) {
bdev->bd_fsfreeze_count++;
if (++bdev->bd_fsfreeze_count > 1) {
/*
* We don't even need to grab a reference - the first call
* to freeze_bdev grab an active reference and only the last
* thaw_bdev drops it.
*/
sb = get_super(bdev);
drop_super(sb);
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return sb;
}
bdev->bd_fsfreeze_count++;

sb = get_super(bdev);
if (sb && !(sb->s_flags & MS_RDONLY)) {
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;
drop_super(sb);
bdev->bd_fsfreeze_count--;
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return ERR_PTR(error);
}

sb = get_active_super(bdev);
if (!sb)
goto out;
if (sb->s_flags & MS_RDONLY) {
deactivate_locked_super(sb);
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);
}
}
up_write(&sb->s_umount);

out:
sync_blockdev(bdev);
mutex_unlock(&bdev->bd_fsfreeze_mutex);

return sb; /* thaw_bdev releases s->s_umount */
}
EXPORT_SYMBOL(freeze_bdev);
Expand All @@ -280,43 +291,44 @@ EXPORT_SYMBOL(freeze_bdev);
*/
int thaw_bdev(struct block_device *bdev, struct super_block *sb)
{
int error = 0;
int error = -EINVAL;

mutex_lock(&bdev->bd_fsfreeze_mutex);
if (!bdev->bd_fsfreeze_count) {
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return -EINVAL;
}

bdev->bd_fsfreeze_count--;
if (bdev->bd_fsfreeze_count > 0) {
if (sb)
drop_super(sb);
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return 0;
}

if (sb) {
BUG_ON(sb->s_bdev != bdev);
if (!(sb->s_flags & MS_RDONLY)) {
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;
}
}
sb->s_frozen = SB_UNFROZEN;
smp_wmb();
wake_up(&sb->s_wait_unfrozen);
if (!bdev->bd_fsfreeze_count)
goto out_unlock;

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

if (!sb)
goto out_unlock;

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

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;
}
drop_super(sb);
}

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

out_deactivate:
if (sb)
deactivate_locked_super(sb);
out_unlock:
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return 0;
}
Expand Down
48 changes: 47 additions & 1 deletion trunk/fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,48 @@ struct super_block * get_super(struct block_device *bdev)
}

EXPORT_SYMBOL(get_super);

/**
* get_active_super - get an active reference to the superblock of a device
* @bdev: device to get the superblock for
*
* Scans the superblock list and finds the superblock of the file system
* mounted on the device given. Returns the superblock with an active
* reference and s_umount held exclusively or %NULL if none was found.
*/
struct super_block *get_active_super(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)
continue;

sb->s_count++;
spin_unlock(&sb_lock);
down_write(&sb->s_umount);
if (sb->s_root) {
spin_lock(&sb_lock);
if (sb->s_count > S_BIAS) {
atomic_inc(&sb->s_active);
sb->s_count--;
spin_unlock(&sb_lock);
return sb;
}
spin_unlock(&sb_lock);
}
up_write(&sb->s_umount);
put_super(sb);
yield();
spin_lock(&sb_lock);
}
spin_unlock(&sb_lock);
return NULL;
}

struct super_block * user_get_super(dev_t dev)
{
Expand Down Expand Up @@ -527,11 +569,15 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
{
int retval;
int remount_rw;


if (sb->s_frozen != SB_UNFROZEN)
return -EBUSY;

#ifdef CONFIG_BLOCK
if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
return -EACCES;
#endif

if (flags & MS_RDONLY)
acct_auto_close(sb);
shrink_dcache_sb(sb);
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,7 @@ 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 struct super_block *get_super(struct block_device *);
extern struct super_block *get_active_super(struct block_device *bdev);
extern struct super_block *user_get_super(dev_t);
extern void drop_super(struct super_block *sb);

Expand Down

0 comments on commit 3e010cf

Please sign in to comment.