if (s) {
up_write(&s->s_umount);
destroy_super(s);
+ s = NULL;
}
down_write(&old->s_umount);
+ if (unlikely(!(old->s_flags & MS_BORN))) {
+ deactivate_locked_super(old);
+ goto retry;
+ }
return old;
}
}
*/
void sync_supers(void)
{
- struct super_block *sb, *n;
+ struct super_block *sb, *p = NULL;
spin_lock(&sb_lock);
- list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+ list_for_each_entry(sb, &super_blocks, s_list) {
if (list_empty(&sb->s_instances))
continue;
if (sb->s_op->write_super && sb->s_dirt) {
up_read(&sb->s_umount);
spin_lock(&sb_lock);
- __put_super(sb);
+ if (p)
+ __put_super(p);
+ p = sb;
}
}
+ if (p)
+ __put_super(p);
spin_unlock(&sb_lock);
}
*/
void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
{
- struct super_block *sb, *n;
+ struct super_block *sb, *p = NULL;
spin_lock(&sb_lock);
- list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+ list_for_each_entry(sb, &super_blocks, s_list) {
if (list_empty(&sb->s_instances))
continue;
sb->s_count++;
up_read(&sb->s_umount);
spin_lock(&sb_lock);
- __put_super(sb);
+ if (p)
+ __put_super(p);
+ p = sb;
}
+ if (p)
+ __put_super(p);
spin_unlock(&sb_lock);
}
static void do_emergency_remount(struct work_struct *work)
{
- struct super_block *sb, *n;
+ struct super_block *sb, *p = NULL;
spin_lock(&sb_lock);
- list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+ list_for_each_entry(sb, &super_blocks, s_list) {
if (list_empty(&sb->s_instances))
continue;
sb->s_count++;
}
up_write(&sb->s_umount);
spin_lock(&sb_lock);
- __put_super(sb);
+ if (p)
+ __put_super(p);
+ p = sb;
}
+ if (p)
+ __put_super(p);
spin_unlock(&sb_lock);
kfree(work);
printk("Emergency Remount complete\n");
goto error_bdev;
}
+ /*
+ * s_umount nests inside bd_mutex during
+ * __invalidate_device(). close_bdev_exclusive()
+ * acquires bd_mutex and can't be called under
+ * s_umount. Drop s_umount temporarily. This is safe
+ * as we're holding an active reference.
+ */
+ up_write(&s->s_umount);
close_bdev_exclusive(bdev, mode);
+ down_write(&s->s_umount);
} else {
char b[BDEVNAME_SIZE];
goto out_free_secdata;
BUG_ON(!mnt->mnt_sb);
WARN_ON(!mnt->mnt_sb->s_bdi);
+ mnt->mnt_sb->s_flags |= MS_BORN;
error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
if (error)