cvs commit: src/sys/coda coda_subr.c src/sys/fs/msdosfs msdosfs_vfsops.c src/sys/gnu/ext2fs ext2_vfsops.c src/sys/kern vfs_default.c vfs_mount.c vfs_subr.c src/sys/nfs4client nfs4_vfsops.c src/sys/nfsclient nfs_subs.c nfs_vfsops.c ...

Poul-Henning Kamp phk at FreeBSD.org
Sun Jul 4 01:52:37 PDT 2004


phk         2004-07-04 08:52:36 UTC

  FreeBSD src repository

  Modified files:
    sys/coda             coda_subr.c 
    sys/fs/msdosfs       msdosfs_vfsops.c 
    sys/gnu/ext2fs       ext2_vfsops.c 
    sys/kern             vfs_default.c vfs_mount.c vfs_subr.c 
    sys/nfs4client       nfs4_vfsops.c 
    sys/nfsclient        nfs_subs.c nfs_vfsops.c 
    sys/sys              mount.h 
    sys/ufs/ffs          ffs_snapshot.c ffs_vfsops.c 
    sys/ufs/ufs          ufs_quota.c 
  Log:
  When we traverse the vnodes on a mountpoint we need to look out for
  our cached 'next vnode' being removed from this mountpoint.  If we
  find that it was recycled, we restart our traversal from the start
  of the list.
  
  Code to do that is in all local disk filesystems (and a few other
  places) and looks roughly like this:
  
                  MNT_ILOCK(mp);
          loop:
                  for (vp = TAILQ_FIRST(&mp...);
                      (vp = nvp) != NULL;
                      nvp = TAILQ_NEXT(vp,...)) {
                          if (vp->v_mount != mp)
                                  goto loop;
                          MNT_IUNLOCK(mp);
                          ...
                          MNT_ILOCK(mp);
                  }
                  MNT_IUNLOCK(mp);
  
  The code which takes vnodes off a mountpoint looks like this:
  
          MNT_ILOCK(vp->v_mount);
          ...
          TAILQ_REMOVE(&vp->v_mount->mnt_nvnodelist, vp, v_nmntvnodes);
          ...
          MNT_IUNLOCK(vp->v_mount);
          ...
          vp->v_mount = something;
  
  (Take a moment and try to spot the locking error before you read on.)
  
  On a SMP system, one CPU could have removed nvp from our mountlist
  but not yet gotten to assign a new value to vp->v_mount while another
  CPU simultaneously get to the top of the traversal loop where it
  finds that (vp->v_mount != mp) is not true despite the fact that
  the vnode has indeed been removed from our mountpoint.
  
  Fix:
  
  Introduce the macro MNT_VNODE_FOREACH() to traverse the list of
  vnodes on a mountpoint while taking into account that vnodes may
  be removed from the list as we go.  This saves approx 65 lines of
  duplicated code.
  
  Split the insmntque() which potentially moves a vnode from one mount
  point to another into delmntque() and insmntque() which does just
  what the names say.
  
  Fix delmntque() to set vp->v_mount to NULL while holding the
  mountpoint lock.
  
  Revision  Changes    Path
  1.29      +2 -5      src/sys/coda/coda_subr.c
  1.122     +1 -9      src/sys/fs/msdosfs/msdosfs_vfsops.c
  1.123     +2 -14     src/sys/gnu/ext2fs/ext2_vfsops.c
  1.94      +1 -9      src/sys/kern/vfs_default.c
  1.130     +27 -0     src/sys/kern/vfs_mount.c
  1.496     +35 -38    src/sys/kern/vfs_subr.c
  1.7       +2 -11     src/sys/nfs4client/nfs4_vfsops.c
  1.130     +1 -5      src/sys/nfsclient/nfs_subs.c
  1.150     +2 -11     src/sys/nfsclient/nfs_vfsops.c
  1.163     +6 -0      src/sys/sys/mount.h
  1.83      +1 -8      src/sys/ufs/ffs/ffs_snapshot.c
  1.234     +2 -17     src/sys/ufs/ffs/ffs_vfsops.c
  1.72      +6 -22     src/sys/ufs/ufs/ufs_quota.c


More information about the cvs-all mailing list