|
@@ -723,23 +723,33 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
|
|
/* If we are remounting RDONLY and current sb is read/write,
|
|
/* If we are remounting RDONLY and current sb is read/write,
|
|
make sure there are no rw files opened */
|
|
make sure there are no rw files opened */
|
|
if (remount_ro) {
|
|
if (remount_ro) {
|
|
- if (force)
|
|
|
|
|
|
+ if (force) {
|
|
mark_files_ro(sb);
|
|
mark_files_ro(sb);
|
|
- else if (!fs_may_remount_ro(sb))
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ retval = sb_prepare_remount_readonly(sb);
|
|
|
|
+ if (retval)
|
|
|
|
+ return retval;
|
|
|
|
+
|
|
|
|
+ retval = -EBUSY;
|
|
|
|
+ if (!fs_may_remount_ro(sb))
|
|
|
|
+ goto cancel_readonly;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (sb->s_op->remount_fs) {
|
|
if (sb->s_op->remount_fs) {
|
|
retval = sb->s_op->remount_fs(sb, &flags, data);
|
|
retval = sb->s_op->remount_fs(sb, &flags, data);
|
|
if (retval) {
|
|
if (retval) {
|
|
if (!force)
|
|
if (!force)
|
|
- return retval;
|
|
|
|
|
|
+ goto cancel_readonly;
|
|
/* If forced remount, go ahead despite any errors */
|
|
/* If forced remount, go ahead despite any errors */
|
|
WARN(1, "forced remount of a %s fs returned %i\n",
|
|
WARN(1, "forced remount of a %s fs returned %i\n",
|
|
sb->s_type->name, retval);
|
|
sb->s_type->name, retval);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
|
|
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
|
|
|
|
+ /* Needs to be ordered wrt mnt_is_readonly() */
|
|
|
|
+ smp_wmb();
|
|
|
|
+ sb->s_readonly_remount = 0;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Some filesystems modify their metadata via some other path than the
|
|
* Some filesystems modify their metadata via some other path than the
|
|
@@ -752,6 +762,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
|
|
if (remount_ro && sb->s_bdev)
|
|
if (remount_ro && sb->s_bdev)
|
|
invalidate_bdev(sb->s_bdev);
|
|
invalidate_bdev(sb->s_bdev);
|
|
return 0;
|
|
return 0;
|
|
|
|
+
|
|
|
|
+cancel_readonly:
|
|
|
|
+ sb->s_readonly_remount = 0;
|
|
|
|
+ return retval;
|
|
}
|
|
}
|
|
|
|
|
|
static void do_emergency_remount(struct work_struct *work)
|
|
static void do_emergency_remount(struct work_struct *work)
|