tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

smbfs umount kernel panic fixes for review



Hi,

While playing with SMBFS/CIFS shares from a NetApp FAS6080C filer; i
encountered some kernel panics, mostly when trying to umount the
filesystem after use.

Looking into the code most problems seems to come from the
smbfs_unmount() function ...

The root vnode is unconditionnaly destroyed, preventing any further
use. If the filesystem is in use, the umount will fail, but any access
to the root vnode will make the kernel panic. Likewise, the mount
structure blindly loose its reference to the specific smbmount
structure. Same result ... panic.

The attached patch, should fix them.

Could someone with more FS knowledge check that this is correct ?

Thanks.

-- 
Nicolas Joly

Biological Software and Databanks.
Institut Pasteur, Paris.
Index: sys/fs/smbfs/smbfs_node.c
===================================================================
RCS file: /cvsroot/src/sys/fs/smbfs/smbfs_node.c,v
retrieving revision 1.40
diff -u -p -r1.40 smbfs_node.c
--- sys/fs/smbfs/smbfs_node.c   14 Mar 2009 21:04:24 -0000      1.40
+++ sys/fs/smbfs/smbfs_node.c   1 Jul 2009 14:26:57 -0000
@@ -244,8 +244,6 @@ smbfs_reclaim(void *v)
 
        SMBVDEBUG("%.*s,%d\n", (int) np->n_nmlen, np->n_name, vp->v_usecount);
 
-       KASSERT((np->n_flag & NOPEN) == 0);
-
        mutex_enter(&smp->sm_hashlock);
 
        dvp = (np->n_parent && (np->n_flag & NREFPARENT)) ?
Index: sys/fs/smbfs/smbfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/smbfs/smbfs_vfsops.c,v
retrieving revision 1.87
diff -u -p -r1.87 smbfs_vfsops.c
--- sys/fs/smbfs/smbfs_vfsops.c 17 Dec 2008 20:51:35 -0000      1.87
+++ sys/fs/smbfs/smbfs_vfsops.c 1 Jul 2009 14:26:57 -0000
@@ -231,17 +231,16 @@ smbfs_unmount(struct mount *mp, int mntf
        struct lwp *l = curlwp;
        struct smbmount *smp = VFSTOSMBFS(mp);
        struct smb_cred scred;
+       struct vnode *smbfs_rootvp = SMBTOV(smp->sm_root);
        int error, flags;
 
        SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
        flags = 0;
        if (mntflags & MNT_FORCE)
                flags |= FORCECLOSE;
-       /* Drop the extra reference to root vnode. */
-       if (smp->sm_root) {
-               vrele(SMBTOV(smp->sm_root));
-               smp->sm_root = NULL;
-       }
+
+       if (smbfs_rootvp->v_usecount > 1 && (mntflags & MNT_FORCE) == 0)
+               return EBUSY;
 
        /* Flush all vnodes.
         * Keep trying to flush the vnode list for the mount while 
@@ -252,8 +251,12 @@ smbfs_unmount(struct mount *mp, int mntf
         * sufficient in this case. */
        do {
                smp->sm_didrele = 0;
-               error = vflush(mp, NULLVP, flags);
+               error = vflush(mp, smbfs_rootvp, flags);
        } while (error == EBUSY && smp->sm_didrele != 0);
+       if (error)
+               return error;
+
+       vgone(smbfs_rootvp);
 
        smb_makescred(&scred, l, l->l_cred);
        smb_share_lock(smp->sm_share);
@@ -263,7 +266,7 @@ smbfs_unmount(struct mount *mp, int mntf
        hashdone(smp->sm_hash, HASH_LIST, smp->sm_hashlen);
        mutex_destroy(&smp->sm_hashlock);
        free(smp, M_SMBFSDATA);
-       return error;
+       return 0;
 }
 
 /*


Home | Main Index | Thread Index | Old Index