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;

Reply via email to