Commit 7214dd4e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.thaw' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs thaw updates from Al Viro:
 "An ancient series that has fallen through the cracks in the previous
  cycle"

* 'work.thaw' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  buffer.c: call thaw_super during emergency thaw
  vfs: factor sb iteration out of do_emergency_remount
parents 19e8a2f8 08fdc8a0
...@@ -494,35 +494,12 @@ static int osync_buffers_list(spinlock_t *lock, struct list_head *list) ...@@ -494,35 +494,12 @@ static int osync_buffers_list(spinlock_t *lock, struct list_head *list)
return err; return err;
} }
static void do_thaw_one(struct super_block *sb, void *unused) void emergency_thaw_bdev(struct super_block *sb)
{ {
while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb)) while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
printk(KERN_WARNING "Emergency Thaw on %pg\n", sb->s_bdev); printk(KERN_WARNING "Emergency Thaw on %pg\n", sb->s_bdev);
} }
static void do_thaw_all(struct work_struct *work)
{
iterate_supers(do_thaw_one, NULL);
kfree(work);
printk(KERN_WARNING "Emergency Thaw complete\n");
}
/**
* emergency_thaw_all -- forcibly thaw every frozen filesystem
*
* Used for emergency unfreeze of all filesystems via SysRq
*/
void emergency_thaw_all(void)
{
struct work_struct *work;
work = kmalloc(sizeof(*work), GFP_ATOMIC);
if (work) {
INIT_WORK(work, do_thaw_all);
schedule_work(work);
}
}
/** /**
* sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers
* @mapping: the mapping which wants those buffers written * @mapping: the mapping which wants those buffers written
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/user_namespace.h> #include <linux/user_namespace.h>
#include "internal.h" #include "internal.h"
static int thaw_super_locked(struct super_block *sb);
static LIST_HEAD(super_blocks); static LIST_HEAD(super_blocks);
static DEFINE_SPINLOCK(sb_lock); static DEFINE_SPINLOCK(sb_lock);
...@@ -574,6 +575,28 @@ void drop_super_exclusive(struct super_block *sb) ...@@ -574,6 +575,28 @@ void drop_super_exclusive(struct super_block *sb)
} }
EXPORT_SYMBOL(drop_super_exclusive); EXPORT_SYMBOL(drop_super_exclusive);
static void __iterate_supers(void (*f)(struct super_block *))
{
struct super_block *sb, *p = NULL;
spin_lock(&sb_lock);
list_for_each_entry(sb, &super_blocks, s_list) {
if (hlist_unhashed(&sb->s_instances))
continue;
sb->s_count++;
spin_unlock(&sb_lock);
f(sb);
spin_lock(&sb_lock);
if (p)
__put_super(p);
p = sb;
}
if (p)
__put_super(p);
spin_unlock(&sb_lock);
}
/** /**
* iterate_supers - call function for all active superblocks * iterate_supers - call function for all active superblocks
* @f: function to call * @f: function to call
...@@ -881,33 +904,22 @@ int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force) ...@@ -881,33 +904,22 @@ int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
return retval; return retval;
} }
static void do_emergency_remount(struct work_struct *work) static void do_emergency_remount_callback(struct super_block *sb)
{ {
struct super_block *sb, *p = NULL; down_write(&sb->s_umount);
if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) &&
spin_lock(&sb_lock); !sb_rdonly(sb)) {
list_for_each_entry(sb, &super_blocks, s_list) { /*
if (hlist_unhashed(&sb->s_instances)) * What lock protects sb->s_flags??
continue; */
sb->s_count++; do_remount_sb(sb, SB_RDONLY, NULL, 1);
spin_unlock(&sb_lock);
down_write(&sb->s_umount);
if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) &&
!sb_rdonly(sb)) {
/*
* What lock protects sb->s_flags??
*/
do_remount_sb(sb, SB_RDONLY, NULL, 1);
}
up_write(&sb->s_umount);
spin_lock(&sb_lock);
if (p)
__put_super(p);
p = sb;
} }
if (p) up_write(&sb->s_umount);
__put_super(p); }
spin_unlock(&sb_lock);
static void do_emergency_remount(struct work_struct *work)
{
__iterate_supers(do_emergency_remount_callback);
kfree(work); kfree(work);
printk("Emergency Remount complete\n"); printk("Emergency Remount complete\n");
} }
...@@ -923,6 +935,40 @@ void emergency_remount(void) ...@@ -923,6 +935,40 @@ void emergency_remount(void)
} }
} }
static void do_thaw_all_callback(struct super_block *sb)
{
down_write(&sb->s_umount);
if (sb->s_root && sb->s_flags & MS_BORN) {
emergency_thaw_bdev(sb);
thaw_super_locked(sb);
} else {
up_write(&sb->s_umount);
}
}
static void do_thaw_all(struct work_struct *work)
{
__iterate_supers(do_thaw_all_callback);
kfree(work);
printk(KERN_WARNING "Emergency Thaw complete\n");
}
/**
* emergency_thaw_all -- forcibly thaw every frozen filesystem
*
* Used for emergency unfreeze of all filesystems via SysRq
*/
void emergency_thaw_all(void)
{
struct work_struct *work;
work = kmalloc(sizeof(*work), GFP_ATOMIC);
if (work) {
INIT_WORK(work, do_thaw_all);
schedule_work(work);
}
}
/* /*
* Unnamed block devices are dummy devices used by virtual * Unnamed block devices are dummy devices used by virtual
* filesystems which don't use real block-devices. -- jrs * filesystems which don't use real block-devices. -- jrs
...@@ -1492,11 +1538,10 @@ EXPORT_SYMBOL(freeze_super); ...@@ -1492,11 +1538,10 @@ EXPORT_SYMBOL(freeze_super);
* *
* Unlocks the filesystem and marks it writeable again after freeze_super(). * Unlocks the filesystem and marks it writeable again after freeze_super().
*/ */
int thaw_super(struct super_block *sb) static int thaw_super_locked(struct super_block *sb)
{ {
int error; int error;
down_write(&sb->s_umount);
if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) { if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) {
up_write(&sb->s_umount); up_write(&sb->s_umount);
return -EINVAL; return -EINVAL;
...@@ -1527,4 +1572,10 @@ int thaw_super(struct super_block *sb) ...@@ -1527,4 +1572,10 @@ int thaw_super(struct super_block *sb)
deactivate_locked_super(sb); deactivate_locked_super(sb);
return 0; return 0;
} }
int thaw_super(struct super_block *sb)
{
down_write(&sb->s_umount);
return thaw_super_locked(sb);
}
EXPORT_SYMBOL(thaw_super); EXPORT_SYMBOL(thaw_super);
...@@ -2445,6 +2445,7 @@ extern int sync_blockdev(struct block_device *bdev); ...@@ -2445,6 +2445,7 @@ extern int sync_blockdev(struct block_device *bdev);
extern void kill_bdev(struct block_device *); extern void kill_bdev(struct block_device *);
extern struct super_block *freeze_bdev(struct block_device *); extern struct super_block *freeze_bdev(struct block_device *);
extern void emergency_thaw_all(void); extern void emergency_thaw_all(void);
extern void emergency_thaw_bdev(struct super_block *sb);
extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
extern int fsync_bdev(struct block_device *); extern int fsync_bdev(struct block_device *);
...@@ -2470,6 +2471,11 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb) ...@@ -2470,6 +2471,11 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
return 0; return 0;
} }
static inline int emergency_thaw_bdev(struct super_block *sb)
{
return 0;
}
static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg) static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg)
{ {
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment