Author: kib
Date: Sat May 21 09:49:35 2016
New Revision: 300364
URL: https://svnweb.freebsd.org/changeset/base/300364

Log:
  Improve handling of rdev->si_mountpt on mount and unmount of FFS
  volumes.  Treat the field as a semaphore protecting availability of
  the device for mounting.  Do no access devvp->v_rdev without the vnode
  lock owned.
  
  Protect change of the devvp->v_bufobj bo_ops vector with the vnode
  lock.
  
  Reviewed by:  bde
  Sponsored by: The FreeBSD Foundation
  MFC after:    2 weeks

Modified:
  head/sys/ufs/ffs/ffs_vfsops.c

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c       Sat May 21 09:27:30 2016        
(r300363)
+++ head/sys/ufs/ffs/ffs_vfsops.c       Sat May 21 09:49:35 2016        
(r300364)
@@ -764,25 +764,31 @@ ffs_mountfs(devvp, mp, td)
        cred = td ? td->td_ucred : NOCRED;
        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
 
+       KASSERT(devvp->v_type == VCHR, ("reclaimed devvp"));
        dev = devvp->v_rdev;
-       dev_ref(dev);
+       if (atomic_cmpset_acq_ptr((uintptr_t *)&dev->si_mountpt, 0,
+           (uintptr_t)mp) == 0) {
+               VOP_UNLOCK(devvp, 0);
+               return (EBUSY);
+       }
        DROP_GIANT();
        g_topology_lock();
        error = g_vfs_open(devvp, &cp, "ffs", ronly ? 0 : 1);
        g_topology_unlock();
        PICKUP_GIANT();
+       if (error != 0) {
+               atomic_store_rel_ptr((uintptr_t *)&dev->si_mountpt, 0);
+               VOP_UNLOCK(devvp, 0);
+               return (error);
+       }
+       dev_ref(dev);
+       devvp->v_bufobj.bo_ops = &ffs_ops;
        VOP_UNLOCK(devvp, 0);
-       if (error)
-               goto out;
-       if (devvp->v_rdev->si_iosize_max != 0)
-               mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
+       if (dev->si_iosize_max != 0)
+               mp->mnt_iosize_max = dev->si_iosize_max;
        if (mp->mnt_iosize_max > MAXPHYS)
                mp->mnt_iosize_max = MAXPHYS;
 
-       devvp->v_bufobj.bo_ops = &ffs_ops;
-       if (devvp->v_type == VCHR)
-               devvp->v_rdev->si_mountpt = mp;
-
        fs = NULL;
        sblockloc = 0;
        /*
@@ -1083,8 +1089,6 @@ ffs_mountfs(devvp, mp, td)
 out:
        if (bp)
                brelse(bp);
-       if (devvp->v_type == VCHR && devvp->v_rdev != NULL)
-               devvp->v_rdev->si_mountpt = NULL;
        if (cp != NULL) {
                DROP_GIANT();
                g_topology_lock();
@@ -1102,6 +1106,7 @@ out:
                free(ump, M_UFSMNT);
                mp->mnt_data = NULL;
        }
+       atomic_store_rel_ptr((uintptr_t *)&dev->si_mountpt, 0);
        dev_rel(dev);
        return (error);
 }
@@ -1287,8 +1292,7 @@ ffs_unmount(mp, mntflags)
        g_vfs_close(ump->um_cp);
        g_topology_unlock();
        PICKUP_GIANT();
-       if (ump->um_devvp->v_type == VCHR && ump->um_devvp->v_rdev != NULL)
-               ump->um_devvp->v_rdev->si_mountpt = NULL;
+       atomic_store_rel_ptr((uintptr_t *)&ump->um_dev->si_mountpt, 0);
        vrele(ump->um_devvp);
        dev_rel(ump->um_dev);
        mtx_destroy(UFS_MTX(ump));
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to