Klemens Nanni
2017-07-05 23:31:26 UTC
While playing with the code I found this:
# mount
/dev/sd0a on / type ffs (local, wxallowed, softdep)
# mount -vuo async,nosoftdep /
/dev/sd0a on / type ffs (rw, asynchronous, ..., softdep, ...)
Now open some file before changing options, do the trick and write to it
again. You'll get one of those (two tests, same procedure):
panic: softdep_update_inodeblock: update failed
Stopped at Debugger+0x9: leave
TID PID UID PRFLAGS PFLAGS CPU COMMAND
* 78152 45181 0 0x100403 0x800000 0 vi
Debugger() at Debugger+0x9
panic() at panic+0xfe
softdep_update_inodeblock() at softdep_update_inodeblock+0x1dd
ffs_update() at ffs_update+0x26f
VOP_FSYNC() at VOP_FSYNC+0x3c
sys_fsync() at sys_fsync+0x86
syscall() at syscall+0x197
--- syscall (number 95) ---
end of kernel
end trace frame: 0x123887d7e1e0, count: 8
0x123887b044fa:
panic: softdep_fsync: pending ops
Stopped at Debugger+0x9: leave
TID PID UID PRFLAGS PFLAGS CPU COMMAND
*467375 72022 0 0x100003 0 0 vi
Debugger() at Debugger+0x9
panic() at panic+0xfe
softdep_fsync() at softdep_fsync+0x95
sys_fsync() at sys_fsync+0xa4
syscall() at syscall+0x197
--- syscall (number 95) ---
end of kernel
end trace frame: 0x19255b29e450, count: 10
0x19255b02051a:
Turns out softdep won't be disabled through this update since the
filesystem is mounted read/write (expected behaviour), however async
slips through the mutual exclusion checks and evetually gets set.
Note how the other way around gets catched safely:
# mount
/dev/sd0a on / type ffs (asynchronous, local, wxallowed)
# mount -vuo softdep,noasync /
/dev/sd0a on / type ffs (rw, local, wxallowed, ctime=...)
This diff makes ffs_mount() return EINVAL for now to prevent such panics
until the code has seen more more fixes and clean ups.
I'd like some advice on how to best approach this. If this is somewhat
acceptable I can continue with cleaning (and fixing) up more things.
Feedback? Comments?
Index: ffs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.166
diff -u -p -r1.166 ffs_vfsops.c
--- ffs_vfsops.c 29 May 2017 14:07:16 -0000 1.166
+++ ffs_vfsops.c 5 Jul 2017 23:28:18 -0000
@@ -245,6 +245,14 @@ ffs_mount(struct mount *mp, const char *
error = 0;
ronly = fs->fs_ronly;
+ /*
+ * Soft updates won't be set if read/write,
+ * so "async" will be illegal.
+ */
+ if (ronly == 0 && mp->mnt_flag & MNT_ASYNC &&
+ fs->fs_flags & FS_DOSOFTDEP)
+ error = EINVAL;
+
if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
/* Flush any dirty data */
mp->mnt_flag &= ~MNT_RDONLY;
# mount
/dev/sd0a on / type ffs (local, wxallowed, softdep)
# mount -vuo async,nosoftdep /
/dev/sd0a on / type ffs (rw, asynchronous, ..., softdep, ...)
Now open some file before changing options, do the trick and write to it
again. You'll get one of those (two tests, same procedure):
panic: softdep_update_inodeblock: update failed
Stopped at Debugger+0x9: leave
TID PID UID PRFLAGS PFLAGS CPU COMMAND
* 78152 45181 0 0x100403 0x800000 0 vi
Debugger() at Debugger+0x9
panic() at panic+0xfe
softdep_update_inodeblock() at softdep_update_inodeblock+0x1dd
ffs_update() at ffs_update+0x26f
VOP_FSYNC() at VOP_FSYNC+0x3c
sys_fsync() at sys_fsync+0x86
syscall() at syscall+0x197
--- syscall (number 95) ---
end of kernel
end trace frame: 0x123887d7e1e0, count: 8
0x123887b044fa:
panic: softdep_fsync: pending ops
Stopped at Debugger+0x9: leave
TID PID UID PRFLAGS PFLAGS CPU COMMAND
*467375 72022 0 0x100003 0 0 vi
Debugger() at Debugger+0x9
panic() at panic+0xfe
softdep_fsync() at softdep_fsync+0x95
sys_fsync() at sys_fsync+0xa4
syscall() at syscall+0x197
--- syscall (number 95) ---
end of kernel
end trace frame: 0x19255b29e450, count: 10
0x19255b02051a:
Turns out softdep won't be disabled through this update since the
filesystem is mounted read/write (expected behaviour), however async
slips through the mutual exclusion checks and evetually gets set.
Note how the other way around gets catched safely:
# mount
/dev/sd0a on / type ffs (asynchronous, local, wxallowed)
# mount -vuo softdep,noasync /
/dev/sd0a on / type ffs (rw, local, wxallowed, ctime=...)
This diff makes ffs_mount() return EINVAL for now to prevent such panics
until the code has seen more more fixes and clean ups.
I'd like some advice on how to best approach this. If this is somewhat
acceptable I can continue with cleaning (and fixing) up more things.
Feedback? Comments?
Index: ffs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.166
diff -u -p -r1.166 ffs_vfsops.c
--- ffs_vfsops.c 29 May 2017 14:07:16 -0000 1.166
+++ ffs_vfsops.c 5 Jul 2017 23:28:18 -0000
@@ -245,6 +245,14 @@ ffs_mount(struct mount *mp, const char *
error = 0;
ronly = fs->fs_ronly;
+ /*
+ * Soft updates won't be set if read/write,
+ * so "async" will be illegal.
+ */
+ if (ronly == 0 && mp->mnt_flag & MNT_ASYNC &&
+ fs->fs_flags & FS_DOSOFTDEP)
+ error = EINVAL;
+
if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
/* Flush any dirty data */
mp->mnt_flag &= ~MNT_RDONLY;