[BACK]Return to vfs_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/vfs_subr.c between version 1.357.4.9 and 1.358

version 1.357.4.9, 2010/01/11 00:02:09 version 1.358, 2008/12/07 20:58:46
Line 76 
Line 76 
  * change from a non-zero value to zero, again the interlock must be   * change from a non-zero value to zero, again the interlock must be
  * held.   * held.
  *   *
  * There's a flag bit, VC_XLOCK, embedded in v_usecount.   * Changing the usecount from a non-zero value to a non-zero value can
  * To raise v_usecount, if the VC_XLOCK bit is set in it, the interlock   * safely be done using atomic operations, without the interlock held.
  * must be held.  
  * To modify the VC_XLOCK bit, the interlock must be held.  
  * We always keep the usecount (v_usecount & VC_MASK) non-zero while the  
  * VC_XLOCK bit is set.  
  *  
  * Unless the VC_XLOCK bit is set, changing the usecount from a non-zero  
  * value to a non-zero value can safely be done using atomic operations,  
  * without the interlock held.  
  * Even if the VC_XLOCK bit is set, decreasing the usecount to a non-zero  
  * value can be done using atomic operations, without the interlock held.  
  */   */
   
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
Line 148  const int vttoif_tab[9] = {
Line 138  const int vttoif_tab[9] = {
 int doforce = 1;                /* 1 => permit forcible unmounting */  int doforce = 1;                /* 1 => permit forcible unmounting */
 int prtactive = 0;              /* 1 => print out reclaim of active vnodes */  int prtactive = 0;              /* 1 => print out reclaim of active vnodes */
   
 extern int dovfsusermount;      /* 1 => permit any user to mount filesystems */  
 extern int vfs_magiclinks;      /* 1 => expand "magic" symlinks */  
   
 static vnodelst_t vnode_free_list = TAILQ_HEAD_INITIALIZER(vnode_free_list);  static vnodelst_t vnode_free_list = TAILQ_HEAD_INITIALIZER(vnode_free_list);
 static vnodelst_t vnode_hold_list = TAILQ_HEAD_INITIALIZER(vnode_hold_list);  static vnodelst_t vnode_hold_list = TAILQ_HEAD_INITIALIZER(vnode_hold_list);
 static vnodelst_t vrele_list = TAILQ_HEAD_INITIALIZER(vrele_list);  static vnodelst_t vrele_list = TAILQ_HEAD_INITIALIZER(vrele_list);
Line 370  try_nextlist:
Line 357  try_nextlist:
         vp->v_freelisthd = NULL;          vp->v_freelisthd = NULL;
         mutex_exit(&vnode_free_list_lock);          mutex_exit(&vnode_free_list_lock);
   
         if (vp->v_usecount != 0) {  
                 /*  
                  * was referenced again before we got the interlock  
                  * Don't return to freelist - the holder of the last  
                  * reference will destroy it.  
                  */  
                 mutex_exit(&vp->v_interlock);  
                 mutex_enter(&vnode_free_list_lock);  
                 goto retry;  
         }  
   
         /*          /*
          * The vnode is still associated with a file system, so we must           * The vnode is still associated with a file system, so we must
          * clean it out before reusing it.  We need to add a reference           * clean it out before reusing it.  We need to add a reference
          * before doing this.  If the vnode gains another reference while           * before doing this.  If the vnode gains another reference while
          * being cleaned out then we lose - retry.           * being cleaned out then we lose - retry.
          */           */
         atomic_add_int(&vp->v_usecount, 1 + VC_XLOCK);          atomic_inc_uint(&vp->v_usecount);
         vclean(vp, DOCLOSE);          vclean(vp, DOCLOSE);
         KASSERT(vp->v_usecount >= 1 + VC_XLOCK);  
         atomic_add_int(&vp->v_usecount, -VC_XLOCK);  
         if (vp->v_usecount == 1) {          if (vp->v_usecount == 1) {
                 /* We're about to dirty it. */                  /* We're about to dirty it. */
                 vp->v_iflag &= ~VI_CLEAN;                  vp->v_iflag &= ~VI_CLEAN;
Line 1244  vtryget(vnode_t *vp)
Line 1218  vtryget(vnode_t *vp)
                 return false;                  return false;
         }          }
         for (use = vp->v_usecount;; use = next) {          for (use = vp->v_usecount;; use = next) {
                 if (use == 0 || __predict_false((use & VC_XLOCK) != 0)) {                  if (use == 0) {
                         /* Need interlock held if first reference. */                          /* Need interlock held if first reference. */
                         return false;                          return false;
                 }                  }
Line 1299  vget(vnode_t *vp, int flags)
Line 1273  vget(vnode_t *vp, int flags)
                 vrelel(vp, 0);                  vrelel(vp, 0);
                 return ENOENT;                  return ENOENT;
         }          }
   
         if ((vp->v_iflag & VI_INACTNOW) != 0) {  
                 /*  
                  * if it's being desactived, wait for it to complete.  
                  * Make sure to not return a clean vnode.  
                  */  
                  if ((flags & LK_NOWAIT) != 0) {  
                         vrelel(vp, 0);  
                         return EBUSY;  
                 }  
                 vwait(vp, VI_INACTNOW);  
                 if ((vp->v_iflag & VI_CLEAN) != 0) {  
                         vrelel(vp, 0);  
                         return ENOENT;  
                 }  
         }  
         if (flags & LK_TYPE_MASK) {          if (flags & LK_TYPE_MASK) {
                 error = vn_lock(vp, flags | LK_INTERLOCK);                  error = vn_lock(vp, flags | LK_INTERLOCK);
                 if (error != 0) {                  if (error != 0) {
Line 1341  vput(vnode_t *vp)
Line 1299  vput(vnode_t *vp)
   
 /*  /*
  * Try to drop reference on a vnode.  Abort if we are releasing the   * Try to drop reference on a vnode.  Abort if we are releasing the
  * last reference.  Note: this _must_ succeed if not the last reference.   * last reference.
  */   */
 static inline bool  static inline bool
 vtryrele(vnode_t *vp)  vtryrele(vnode_t *vp)
Line 1349  vtryrele(vnode_t *vp)
Line 1307  vtryrele(vnode_t *vp)
         u_int use, next;          u_int use, next;
   
         for (use = vp->v_usecount;; use = next) {          for (use = vp->v_usecount;; use = next) {
                 if (use == 1) {                  if (use == 1) {
                         return false;                          return false;
                 }                  }
                 KASSERT((use & VC_MASK) > 1);  
                 next = atomic_cas_uint(&vp->v_usecount, use, use - 1);                  next = atomic_cas_uint(&vp->v_usecount, use, use - 1);
                 if (__predict_true(next == use)) {                  if (__predict_true(next == use)) {
                         return true;                          return true;
Line 1374  vrelel(vnode_t *vp, int flags)
Line 1331  vrelel(vnode_t *vp, int flags)
         KASSERT((vp->v_iflag & VI_MARKER) == 0);          KASSERT((vp->v_iflag & VI_MARKER) == 0);
         KASSERT(vp->v_freelisthd == NULL);          KASSERT(vp->v_freelisthd == NULL);
   
         if (__predict_false(vp->v_op == dead_vnodeop_p &&          if (vp->v_op == dead_vnodeop_p && (vp->v_iflag & VI_CLEAN) == 0) {
             (vp->v_iflag & (VI_CLEAN|VI_XLOCK)) == 0)) {  
                 vpanic(vp, "dead but not clean");                  vpanic(vp, "dead but not clean");
         }          }
   
Line 1389  vrelel(vnode_t *vp, int flags)
Line 1345  vrelel(vnode_t *vp, int flags)
                 return;                  return;
         }          }
         if (vp->v_usecount <= 0 || vp->v_writecount != 0) {          if (vp->v_usecount <= 0 || vp->v_writecount != 0) {
                 vpanic(vp, "vrelel: bad ref count");                  vpanic(vp, "vput: bad ref count");
         }          }
   
         KASSERT((vp->v_iflag & VI_XLOCK) == 0);  
   
         /*          /*
          * If not clean, deactivate the vnode, but preserve           * If not clean, deactivate the vnode, but preserve
          * our reference across the call to VOP_INACTIVE().           * our reference across the call to VOP_INACTIVE().
Line 1411  vrelel(vnode_t *vp, int flags)
Line 1365  vrelel(vnode_t *vp, int flags)
                         /* The pagedaemon can't wait around; defer. */                          /* The pagedaemon can't wait around; defer. */
                         defer = true;                          defer = true;
                 } else if (curlwp == vrele_lwp) {                  } else if (curlwp == vrele_lwp) {
                         /*                          /* We have to try harder. */
                          * We have to try harder. But we can't sleep                          vp->v_iflag &= ~VI_INACTREDO;
                          * with VI_INACTNOW as vget() may be waiting on it.  
                          */  
                         vp->v_iflag &= ~(VI_INACTREDO|VI_INACTNOW);  
                         cv_broadcast(&vp->v_cv);  
                         error = vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK |                          error = vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK |
                             LK_RETRY);                              LK_RETRY);
                         if (error != 0) {                          if (error != 0) {
                                 /* XXX */                                  /* XXX */
                                 vpanic(vp, "vrele: unable to lock %p");                                  vpanic(vp, "vrele: unable to lock %p");
                         }                          }
                         mutex_enter(&vp->v_interlock);  
                         /*  
                          * if we did get another reference while  
                          * sleeping, don't try to inactivate it yet.  
                          */  
                         if (__predict_false(vtryrele(vp))) {  
                                 VOP_UNLOCK(vp, 0);  
                                 mutex_exit(&vp->v_interlock);  
                                 return;  
                         }  
                         vp->v_iflag |= VI_INACTNOW;  
                         mutex_exit(&vp->v_interlock);  
                         defer = false;                          defer = false;
                 } else if ((vp->v_iflag & VI_LAYER) != 0) {                  } else if ((vp->v_iflag & VI_LAYER) != 0) {
                         /*                          /*
Line 1470  vrelel(vnode_t *vp, int flags)
Line 1408  vrelel(vnode_t *vp, int flags)
                         if (++vrele_pending > (desiredvnodes >> 8))                          if (++vrele_pending > (desiredvnodes >> 8))
                                 cv_signal(&vrele_cv);                                  cv_signal(&vrele_cv);
                         mutex_exit(&vrele_lock);                          mutex_exit(&vrele_lock);
                         cv_broadcast(&vp->v_cv);  
                         mutex_exit(&vp->v_interlock);                          mutex_exit(&vp->v_interlock);
                         return;                          return;
                 }                  }
Line 1495  vrelel(vnode_t *vp, int flags)
Line 1432  vrelel(vnode_t *vp, int flags)
                 VOP_INACTIVE(vp, &recycle);                  VOP_INACTIVE(vp, &recycle);
                 mutex_enter(&vp->v_interlock);                  mutex_enter(&vp->v_interlock);
                 vp->v_iflag &= ~VI_INACTNOW;                  vp->v_iflag &= ~VI_INACTNOW;
                 cv_broadcast(&vp->v_cv);  
                 if (!recycle) {                  if (!recycle) {
                         if (vtryrele(vp)) {                          if (vtryrele(vp)) {
                                 mutex_exit(&vp->v_interlock);                                  mutex_exit(&vp->v_interlock);
Line 1902  vclean(vnode_t *vp, int flags)
Line 1838  vclean(vnode_t *vp, int flags)
         cache_purge(vp);          cache_purge(vp);
   
         /* Done with purge, notify sleepers of the grim news. */          /* Done with purge, notify sleepers of the grim news. */
         mutex_enter(&vp->v_interlock);  
         vp->v_op = dead_vnodeop_p;          vp->v_op = dead_vnodeop_p;
         vp->v_tag = VT_NON;          vp->v_tag = VT_NON;
           mutex_enter(&vp->v_interlock);
         vp->v_vnlock = &vp->v_lock;          vp->v_vnlock = &vp->v_lock;
         KNOTE(&vp->v_klist, NOTE_REVOKE);          KNOTE(&vp->v_klist, NOTE_REVOKE);
         vp->v_iflag &= ~(VI_XLOCK | VI_FREEING);          vp->v_iflag &= ~(VI_XLOCK | VI_FREEING);
Line 2051  vrevoke(vnode_t *vp)
Line 1987  vrevoke(vnode_t *vp)
         if ((vp->v_iflag & VI_CLEAN) != 0) {          if ((vp->v_iflag & VI_CLEAN) != 0) {
                 mutex_exit(&vp->v_interlock);                  mutex_exit(&vp->v_interlock);
                 return;                  return;
         } else if (vp->v_type != VBLK && vp->v_type != VCHR) {  
                 atomic_inc_uint(&vp->v_usecount);  
                 vclean(vp, DOCLOSE);  
                 vrelel(vp, 0);  
                 return;  
         } else {          } else {
                 dev = vp->v_rdev;                  dev = vp->v_rdev;
                 type = vp->v_type;                  type = vp->v_type;
Line 2091  vrevoke(vnode_t *vp)
Line 2022  vrevoke(vnode_t *vp)
 /*  /*
  * sysctl helper routine to return list of supported fstypes   * sysctl helper routine to return list of supported fstypes
  */   */
 static int  int
 sysctl_vfs_generic_fstypes(SYSCTLFN_ARGS)  sysctl_vfs_generic_fstypes(SYSCTLFN_ARGS)
 {  {
         char bf[sizeof(((struct statvfs *)NULL)->f_fstypename)];          char bf[sizeof(((struct statvfs *)NULL)->f_fstypename)];
Line 2147  sysctl_vfs_generic_fstypes(SYSCTLFN_ARGS
Line 2078  sysctl_vfs_generic_fstypes(SYSCTLFN_ARGS
         return (error);          return (error);
 }  }
   
 /*  
  * Top level filesystem related information gathering.  
  */  
 SYSCTL_SETUP(sysctl_vfs_setup, "sysctl vfs subtree setup")  
 {  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT,  
                        CTLTYPE_NODE, "vfs", NULL,  
                        NULL, 0, NULL, 0,  
                        CTL_VFS, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT,  
                        CTLTYPE_NODE, "generic",  
                        SYSCTL_DESCR("Non-specific vfs related information"),  
                        NULL, 0, NULL, 0,  
                        CTL_VFS, VFS_GENERIC, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "usermount",  
                        SYSCTL_DESCR("Whether unprivileged users may mount "  
                                     "filesystems"),  
                        NULL, 0, &dovfsusermount, 0,  
                        CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT,  
                        CTLTYPE_STRING, "fstypes",  
                        SYSCTL_DESCR("List of file systems present"),  
                        sysctl_vfs_generic_fstypes, 0, NULL, 0,  
                        CTL_VFS, VFS_GENERIC, CTL_CREATE, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "magiclinks",  
                        SYSCTL_DESCR("Whether \"magic\" symlinks are expanded"),  
                        NULL, 0, &vfs_magiclinks, 0,  
                        CTL_VFS, VFS_GENERIC, VFS_MAGICLINKS, CTL_EOL);  
 }  
   
   
 int kinfo_vdebug = 1;  int kinfo_vdebug = 1;
 int kinfo_vgetfailed;  int kinfo_vgetfailed;
Line 2250  sysctl_kern_vnode(SYSCTLFN_ARGS)
Line 2144  sysctl_kern_vnode(SYSCTLFN_ARGS)
                         }                          }
                         memcpy(&vbuf, vp, VNODESZ);                          memcpy(&vbuf, vp, VNODESZ);
                         mutex_exit(&mntvnode_lock);                          mutex_exit(&mntvnode_lock);
                         if ((error = copyout(&vp, bp, VPTRSZ)) ||                          if ((error = copyout(vp, bp, VPTRSZ)) ||
                            (error = copyout(&vbuf, bp + VPTRSZ, VNODESZ))) {                             (error = copyout(&vbuf, bp + VPTRSZ, VNODESZ))) {
                                 mutex_enter(&mntvnode_lock);                                  mutex_enter(&mntvnode_lock);
                                 (void)vunmark(mvp);                                  (void)vunmark(mvp);
Line 2546  void
Line 2440  void
 vattr_null(struct vattr *vap)  vattr_null(struct vattr *vap)
 {  {
   
         memset(vap, 0, sizeof(*vap));  
   
         vap->va_type = VNON;          vap->va_type = VNON;
   
         /*          /*
Line 2574  vattr_null(struct vattr *vap)
Line 2466  vattr_null(struct vattr *vap)
         vap->va_flags = VNOVAL;          vap->va_flags = VNOVAL;
         vap->va_rdev = VNOVAL;          vap->va_rdev = VNOVAL;
         vap->va_bytes = VNOVAL;          vap->va_bytes = VNOVAL;
           vap->va_vaflags = 0;
 }  }
   
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))

Legend:
Removed from v.1.357.4.9  
changed lines
  Added in v.1.358

CVSweb <webmaster@jp.NetBSD.org>