[BACK]Return to puffs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / puffs

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

Diff for /src/sys/fs/puffs/puffs_vnops.c between version 1.163 and 1.163.2.4

version 1.163, 2012/01/17 09:30:16 version 1.163.2.4, 2012/08/12 13:13:20
Line 40  __KERNEL_RCSID(0, "$NetBSD$");
Line 40  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/namei.h>  #include <sys/namei.h>
 #include <sys/vnode.h>  #include <sys/vnode.h>
 #include <sys/proc.h>  #include <sys/proc.h>
   #include <sys/kernel.h> /* For hz, hardclock_ticks */
   
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
   
Line 298  const struct vnodeopv_entry_desc puffs_m
Line 299  const struct vnodeopv_entry_desc puffs_m
 const struct vnodeopv_desc puffs_msgop_opv_desc =  const struct vnodeopv_desc puffs_msgop_opv_desc =
         { &puffs_msgop_p, puffs_msgop_entries };          { &puffs_msgop_p, puffs_msgop_entries };
   
   /*
    * for dosetattr / update_va
    */
   #define SETATTR_CHSIZE  0x01
   #define SETATTR_ASYNC   0x02
   
 #define ERROUT(err)                                                     \  #define ERROUT(err)                                                     \
 do {                                                                    \  do {                                                                    \
Line 408  static int callremove(struct puffs_mount
Line 414  static int callremove(struct puffs_mount
 static int callrmdir(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t,  static int callrmdir(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t,
                            struct componentname *);                             struct componentname *);
 static void callinactive(struct puffs_mount *, puffs_cookie_t, int);  static void callinactive(struct puffs_mount *, puffs_cookie_t, int);
 static void callreclaim(struct puffs_mount *, puffs_cookie_t);  static void callreclaim(struct puffs_mount *, puffs_cookie_t, int);
 static int  flushvncache(struct vnode *, off_t, off_t, bool);  static int  flushvncache(struct vnode *, off_t, off_t, bool);
   static void update_va(struct vnode *, struct vattr *, struct vattr *,
                         struct timespec *, struct timespec *, int);
   static void update_parent(struct vnode *, struct vnode *);
   
   
 #define PUFFS_ABORT_LOOKUP      1  #define PUFFS_ABORT_LOOKUP      1
Line 438  puffs_abortbutton(struct puffs_mount *pm
Line 447  puffs_abortbutton(struct puffs_mount *pm
         }          }
   
         callinactive(pmp, ck, 0);          callinactive(pmp, ck, 0);
         callreclaim(pmp, ck);          callreclaim(pmp, ck, 1);
 }  }
   
 /*  /*
Line 455  puffs_abortbutton(struct puffs_mount *pm
Line 464  puffs_abortbutton(struct puffs_mount *pm
  * don't want to think of the consequences for the time being.   * don't want to think of the consequences for the time being.
  */   */
   
   #define TTL_TO_TIMEOUT(ts) \
       (hardclock_ticks + (ts->tv_sec * hz) + (ts->tv_nsec * hz / 1000000000))
   #define TTL_VALID(ts) \
       ((ts != NULL) && !((ts->tv_sec == 0) && (ts->tv_nsec == 0)))
   #define TIMED_OUT(expire) \
       ((int)((unsigned int)hardclock_ticks - (unsigned int)expire) > 0)
 int  int
 puffs_vnop_lookup(void *v)  puffs_vnop_lookup(void *v)
 {  {
Line 467  puffs_vnop_lookup(void *v)
Line 482  puffs_vnop_lookup(void *v)
         PUFFS_MSG_VARS(vn, lookup);          PUFFS_MSG_VARS(vn, lookup);
         struct puffs_mount *pmp;          struct puffs_mount *pmp;
         struct componentname *cnp;          struct componentname *cnp;
         struct vnode *vp, *dvp;          struct vnode *vp, *dvp, *cvp;
         struct puffs_node *dpn;          struct puffs_node *dpn, *cpn;
         int isdot;          int isdot;
         int error;          int error;
   
         pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);          pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
         cnp = ap->a_cnp;          cnp = ap->a_cnp;
         dvp = ap->a_dvp;          dvp = ap->a_dvp;
           cvp = NULL;
           cpn = NULL;
         *ap->a_vpp = NULL;          *ap->a_vpp = NULL;
   
         /* r/o fs?  we check create later to handle EEXIST */          /* r/o fs?  we check create later to handle EEXIST */
Line 489  puffs_vnop_lookup(void *v)
Line 506  puffs_vnop_lookup(void *v)
             cnp->cn_nameptr, dvp, cnp->cn_nameiop));              cnp->cn_nameptr, dvp, cnp->cn_nameiop));
   
         /*          /*
            * If dotdot cache is enabled, unlock parent, lock ..
            * (grand-parent) and relock parent.
            */
           if (PUFFS_USE_DOTDOTCACHE(pmp) && (cnp->cn_flags & ISDOTDOT)) {
                   VOP_UNLOCK(dvp);
   
                   vp = VPTOPP(ap->a_dvp)->pn_parent;
                   vref(vp);
   
                   vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
   
                   *ap->a_vpp = vp;
                   return 0;
           }
   
           /*
          * Check if someone fed it into the cache           * Check if someone fed it into the cache
          */           */
         if (PUFFS_USE_NAMECACHE(pmp)) {          if (!isdot && PUFFS_USE_NAMECACHE(pmp)) {
                 error = cache_lookup(dvp, ap->a_vpp, cnp);                  error = cache_lookup(dvp, ap->a_vpp, cnp);
   
                   if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) {
                           cvp = *ap->a_vpp;
                           cpn = VPTOPP(cvp);
   
                           if (TIMED_OUT(cpn->pn_cn_timeout)) {
                                   cache_purge(cvp);
                                   /*
                                    * cached vnode (cvp) is still locked
                                    * so that we can reuse it upon a new
                                    * successful lookup.
                                    */
                                   *ap->a_vpp = NULL;
                                   error = -1;
                           }
                   }
   
                   /*
                    * Do not use negative caching, since the filesystem
                    * provides no TTL for it.
                    */
                   if ((error == ENOENT) && PUFFS_USE_FS_TTL(pmp))
                           error = -1;
   
                 if (error >= 0)                  if (error >= 0)
                         return error;                          return error;
         }          }
Line 509  puffs_vnop_lookup(void *v)
Line 566  puffs_vnop_lookup(void *v)
                 return 0;                  return 0;
         }          }
   
           if (cvp != NULL)
                   mutex_enter(&cpn->pn_sizemtx);
   
         PUFFS_MSG_ALLOC(vn, lookup);          PUFFS_MSG_ALLOC(vn, lookup);
         puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred,          puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred,
             cnp, PUFFS_USE_FULLPNBUF(pmp));              cnp, PUFFS_USE_FULLPNBUF(pmp));
Line 544  puffs_vnop_lookup(void *v)
Line 604  puffs_vnop_lookup(void *v)
   
                         /* save negative cache entry */                          /* save negative cache entry */
                         } else {                          } else {
                                 if ((cnp->cn_flags & MAKEENTRY)                                  if (PUFFS_USE_NAMECACHE(pmp) &&
                                     && PUFFS_USE_NAMECACHE(pmp))                                      !PUFFS_USE_FS_TTL(pmp))
                                         cache_enter(dvp, NULL, cnp);                                          cache_enter(dvp, NULL, cnp);
                         }                          }
                 }                  }
Line 564  puffs_vnop_lookup(void *v)
Line 624  puffs_vnop_lookup(void *v)
                 goto out;                  goto out;
         }          }
   
         error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, 1, &vp);          /*
            * Check if we looked up the cached vnode
            */
           vp = NULL;
           if (cvp && (VPTOPP(cvp)->pn_cookie == lookup_msg->pvnr_newnode)) {
                   int grace;
   
                   /*
                    * Bump grace time of this node so that it does not get
                    * reclaimed too fast. We try to increase a bit more the
                    * lifetime of busiest * nodes - with some limits.
                    */
                   grace = 10 * puffs_sopreq_expire_timeout;
                   cpn->pn_cn_grace = hardclock_ticks + grace;
                   vp = cvp;
           }
   
           /*
            * No cached vnode available, or the cached vnode does not
            * match the userland cookie anymore: is the node known?
            */
           if (vp == NULL) {
                   error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode,
                                              1, 1, &vp);
           }
   
         if (error == PUFFS_NOSUCHCOOKIE) {          if (error == PUFFS_NOSUCHCOOKIE) {
                 error = puffs_getvnode(dvp->v_mount,                  error = puffs_getvnode(dvp->v_mount,
                     lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,                      lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
                     lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp);                      lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp);
                 if (error) {                  if (error) {
                         puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),                          puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP,
                             lookup_msg->pvnr_newnode, ap->a_cnp);                              VPTOPNC(dvp), lookup_msg->pvnr_newnode,
                               ap->a_cnp);
                         goto out;                          goto out;
                 }                  }
   
                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);                  vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
         } else if (error) {          } else if (error) {
                 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),                  puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
Line 581  puffs_vnop_lookup(void *v)
Line 668  puffs_vnop_lookup(void *v)
                 goto out;                  goto out;
         }          }
   
           /*
            * Update cache and TTL
            */
           if (PUFFS_USE_FS_TTL(pmp)) {
                   struct timespec *va_ttl = &lookup_msg->pvnr_va_ttl;
                   struct timespec *cn_ttl = &lookup_msg->pvnr_cn_ttl;
                   update_va(vp, NULL, &lookup_msg->pvnr_va,
                             va_ttl, cn_ttl, SETATTR_CHSIZE);
           }
   
           KASSERT(lookup_msg->pvnr_newnode == VPTOPP(vp)->pn_cookie);
         *ap->a_vpp = vp;          *ap->a_vpp = vp;
   
         if ((cnp->cn_flags & MAKEENTRY) != 0 && PUFFS_USE_NAMECACHE(pmp))          if (PUFFS_USE_NAMECACHE(pmp))
                 cache_enter(dvp, vp, cnp);                  cache_enter(dvp, vp, cnp);
   
         /* XXX */          /* XXX */
Line 593  puffs_vnop_lookup(void *v)
Line 691  puffs_vnop_lookup(void *v)
                 cnp->cn_consume = MIN(lookup_msg->pvnr_cn.pkcn_consume,                  cnp->cn_consume = MIN(lookup_msg->pvnr_cn.pkcn_consume,
                     strlen(cnp->cn_nameptr) - cnp->cn_namelen);                      strlen(cnp->cn_nameptr) - cnp->cn_namelen);
   
           VPTOPP(vp)->pn_nlookup++;
   
           if (PUFFS_USE_DOTDOTCACHE(pmp) &&
               (VPTOPP(vp)->pn_parent != dvp))
                   update_parent(vp, dvp);
   
  out:   out:
           if (cvp != NULL) {
                   mutex_exit(&cpn->pn_sizemtx);
   
                   if (error || (cvp != vp))
                           vput(cvp);
           }
   
         if (cnp->cn_flags & ISDOTDOT)          if (cnp->cn_flags & ISDOTDOT)
                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);                  vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
   
Line 658  puffs_vnop_create(void *v)
Line 769  puffs_vnop_create(void *v)
   
         error = puffs_newnode(mp, dvp, ap->a_vpp,          error = puffs_newnode(mp, dvp, ap->a_vpp,
             create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0);              create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0);
         if (error)          if (error) {
                 puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie,                  puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie,
                     create_msg->pvnr_newnode, cnp);                      create_msg->pvnr_newnode, cnp);
                   goto out;
           }
   
           if (PUFFS_USE_FS_TTL(pmp)) {
                   struct timespec *va_ttl = &create_msg->pvnr_va_ttl;
                   struct timespec *cn_ttl = &create_msg->pvnr_cn_ttl;
                   struct vattr *rvap = &create_msg->pvnr_va;
   
                   update_va(*ap->a_vpp, NULL, rvap,
                             va_ttl, cn_ttl, SETATTR_CHSIZE);
           }
   
           VPTOPP(*ap->a_vpp)->pn_nlookup++;
   
           if (PUFFS_USE_DOTDOTCACHE(pmp) &&
               (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
                   update_parent(*ap->a_vpp, dvp);
   
  out:   out:
         vput(dvp);          vput(dvp);
Line 704  puffs_vnop_mknod(void *v)
Line 832  puffs_vnop_mknod(void *v)
         error = puffs_newnode(mp, dvp, ap->a_vpp,          error = puffs_newnode(mp, dvp, ap->a_vpp,
             mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type,              mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type,
             ap->a_vap->va_rdev);              ap->a_vap->va_rdev);
         if (error)          if (error) {
                 puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie,                  puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie,
                     mknod_msg->pvnr_newnode, cnp);                      mknod_msg->pvnr_newnode, cnp);
                   goto out;
           }
   
           if (PUFFS_USE_FS_TTL(pmp)) {
                   struct timespec *va_ttl = &mknod_msg->pvnr_va_ttl;
                   struct timespec *cn_ttl = &mknod_msg->pvnr_cn_ttl;
                   struct vattr *rvap = &mknod_msg->pvnr_va;
   
                   update_va(*ap->a_vpp, NULL, rvap,
                              va_ttl, cn_ttl, SETATTR_CHSIZE);
           }
   
           VPTOPP(*ap->a_vpp)->pn_nlookup++;
   
           if (PUFFS_USE_DOTDOTCACHE(pmp) &&
               (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
                   update_parent(*ap->a_vpp, dvp);
   
  out:   out:
         vput(dvp);          vput(dvp);
Line 822  puffs_vnop_access(void *v)
Line 967  puffs_vnop_access(void *v)
         return error;          return error;
 }  }
   
   static void
   update_va(struct vnode *vp, struct vattr *vap, struct vattr *rvap,
             struct timespec *va_ttl, struct timespec *cn_ttl, int flags)
   {
           struct puffs_node *pn = VPTOPP(vp);
   
           if (TTL_VALID(cn_ttl)) {
                   pn->pn_cn_timeout = TTL_TO_TIMEOUT(cn_ttl);
                   pn->pn_cn_grace = MAX(pn->pn_cn_timeout, pn->pn_cn_grace);
           }
   
           /*
            * Don't listen to the file server regarding special device
            * size info, the file server doesn't know anything about them.
            */
           if (vp->v_type == VBLK || vp->v_type == VCHR)
                   rvap->va_size = vp->v_size;
   
           /* Ditto for blocksize (ufs comment: this doesn't belong here) */
           if (vp->v_type == VBLK)
                   rvap->va_blocksize = BLKDEV_IOSIZE;
           else if (vp->v_type == VCHR)
                   rvap->va_blocksize = MAXBSIZE;
   
           if (vap != NULL) {
                   (void) memcpy(vap, rvap, sizeof(struct vattr));
                   vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
   
                   if (pn->pn_stat & PNODE_METACACHE_ATIME)
                           vap->va_atime = pn->pn_mc_atime;
                   if (pn->pn_stat & PNODE_METACACHE_CTIME)
                           vap->va_ctime = pn->pn_mc_ctime;
                   if (pn->pn_stat & PNODE_METACACHE_MTIME)
                           vap->va_mtime = pn->pn_mc_mtime;
                   if (pn->pn_stat & PNODE_METACACHE_SIZE)
                           vap->va_size = pn->pn_mc_size;
           }
   
           if (!(pn->pn_stat & PNODE_METACACHE_SIZE) && (flags & SETATTR_CHSIZE)) {
                   if (rvap->va_size != VNOVAL
                       && vp->v_type != VBLK && vp->v_type != VCHR) {
                           uvm_vnp_setsize(vp, rvap->va_size);
                           pn->pn_serversize = rvap->va_size;
                   }
           }
   
           if ((va_ttl != NULL) && TTL_VALID(va_ttl)) {
                   if (pn->pn_va_cache == NULL)
                           pn->pn_va_cache = pool_get(&puffs_vapool, PR_WAITOK);
   
                   (void)memcpy(pn->pn_va_cache, rvap, sizeof(*rvap));
   
                   pn->pn_va_timeout = TTL_TO_TIMEOUT(va_ttl);
           }
   }
   
   static void
   update_parent(struct vnode *vp, struct vnode *dvp)
   {
           struct puffs_node *pn = VPTOPP(vp);
   
           if (pn->pn_parent != NULL) {
                   KASSERT(pn->pn_parent != dvp);
                   vrele(pn->pn_parent);
           }
   
           vref(dvp);
           pn->pn_parent = dvp;
   }
   
 int  int
 puffs_vnop_getattr(void *v)  puffs_vnop_getattr(void *v)
 {  {
Line 837  puffs_vnop_getattr(void *v)
Line 1052  puffs_vnop_getattr(void *v)
         struct puffs_mount *pmp = MPTOPUFFSMP(mp);          struct puffs_mount *pmp = MPTOPUFFSMP(mp);
         struct vattr *vap, *rvap;          struct vattr *vap, *rvap;
         struct puffs_node *pn = VPTOPP(vp);          struct puffs_node *pn = VPTOPP(vp);
           struct timespec *va_ttl = NULL;
         int error = 0;          int error = 0;
   
         /*          /*
Line 857  puffs_vnop_getattr(void *v)
Line 1073  puffs_vnop_getattr(void *v)
         REFPN(pn);          REFPN(pn);
         vap = ap->a_vap;          vap = ap->a_vap;
   
           if (PUFFS_USE_FS_TTL(pmp)) {
                   if (!TIMED_OUT(pn->pn_va_timeout)) {
                           update_va(vp, vap, pn->pn_va_cache,
                                     NULL, NULL, SETATTR_CHSIZE);
                           goto out2;
                   }
           }
   
         PUFFS_MSG_ALLOC(vn, getattr);          PUFFS_MSG_ALLOC(vn, getattr);
         vattr_null(&getattr_msg->pvnr_va);          vattr_null(&getattr_msg->pvnr_va);
         puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);          puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);
Line 869  puffs_vnop_getattr(void *v)
Line 1093  puffs_vnop_getattr(void *v)
                 goto out;                  goto out;
   
         rvap = &getattr_msg->pvnr_va;          rvap = &getattr_msg->pvnr_va;
         /*  
          * Don't listen to the file server regarding special device  
          * size info, the file server doesn't know anything about them.  
          */  
         if (vp->v_type == VBLK || vp->v_type == VCHR)  
                 rvap->va_size = vp->v_size;  
   
         /* Ditto for blocksize (ufs comment: this doesn't belong here) */          if (PUFFS_USE_FS_TTL(pmp))
         if (vp->v_type == VBLK)                  va_ttl = &getattr_msg->pvnr_va_ttl;
                 rvap->va_blocksize = BLKDEV_IOSIZE;  
         else if (vp->v_type == VCHR)  
                 rvap->va_blocksize = MAXBSIZE;  
   
         (void) memcpy(vap, rvap, sizeof(struct vattr));  
         vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];  
   
         if (pn->pn_stat & PNODE_METACACHE_ATIME)          update_va(vp, vap, rvap, va_ttl, NULL, SETATTR_CHSIZE);
                 vap->va_atime = pn->pn_mc_atime;  
         if (pn->pn_stat & PNODE_METACACHE_CTIME)  
                 vap->va_ctime = pn->pn_mc_ctime;  
         if (pn->pn_stat & PNODE_METACACHE_MTIME)  
                 vap->va_mtime = pn->pn_mc_mtime;  
         if (pn->pn_stat & PNODE_METACACHE_SIZE) {  
                 vap->va_size = pn->pn_mc_size;  
         } else {  
                 if (rvap->va_size != VNOVAL  
                     && vp->v_type != VBLK && vp->v_type != VCHR) {  
                         uvm_vnp_setsize(vp, rvap->va_size);  
                         pn->pn_serversize = rvap->va_size;  
                 }  
         }  
   
  out:   out:
         puffs_releasenode(pn);  
         PUFFS_MSG_RELEASE(getattr);          PUFFS_MSG_RELEASE(getattr);
   
    out2:
           puffs_releasenode(pn);
   
         mutex_exit(&pn->pn_sizemtx);          mutex_exit(&pn->pn_sizemtx);
   
         return error;          return error;
 }  }
   
 #define SETATTR_CHSIZE  0x01  
 #define SETATTR_ASYNC   0x02  
 static int  static int
 dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)  dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)
 {  {
Line 954  dosetattr(struct vnode *vp, struct vattr
Line 1152  dosetattr(struct vnode *vp, struct vattr
                 pn->pn_stat &= ~PNODE_METACACHE_MASK;                  pn->pn_stat &= ~PNODE_METACACHE_MASK;
         }          }
   
           /*
            * Flush attribute cache so that another thread do
            * not get a stale value during the operation.
            */
           if (PUFFS_USE_FS_TTL(pmp))
                   pn->pn_va_timeout = 0;
   
         PUFFS_MSG_ALLOC(vn, setattr);          PUFFS_MSG_ALLOC(vn, setattr);
         (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));          (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
         puffs_credcvt(&setattr_msg->pvnr_cred, cred);          puffs_credcvt(&setattr_msg->pvnr_cred, cred);
Line 965  dosetattr(struct vnode *vp, struct vattr
Line 1170  dosetattr(struct vnode *vp, struct vattr
         puffs_msg_enqueue(pmp, park_setattr);          puffs_msg_enqueue(pmp, park_setattr);
         if ((flags & SETATTR_ASYNC) == 0)          if ((flags & SETATTR_ASYNC) == 0)
                 error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);                  error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);
   
           if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) {
                   struct timespec *va_ttl = &setattr_msg->pvnr_va_ttl;
                   struct vattr *rvap = &setattr_msg->pvnr_va;
   
                   update_va(vp, NULL, rvap, va_ttl, NULL, flags);
           }
   
         PUFFS_MSG_RELEASE(setattr);          PUFFS_MSG_RELEASE(setattr);
         if ((flags & SETATTR_ASYNC) == 0) {          if ((flags & SETATTR_ASYNC) == 0) {
                 error = checkerr(pmp, error, __func__);                  error = checkerr(pmp, error, __func__);
Line 1046  puffs_vnop_inactive(void *v)
Line 1259  puffs_vnop_inactive(void *v)
         struct vnode *vp = ap->a_vp;          struct vnode *vp = ap->a_vp;
         struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);          struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
         struct puffs_node *pnode;          struct puffs_node *pnode;
           bool recycle = false;
         int error;          int error;
   
         pnode = vp->v_data;          pnode = vp->v_data;
Line 1069  puffs_vnop_inactive(void *v)
Line 1283  puffs_vnop_inactive(void *v)
          */           */
         if (pnode->pn_stat & PNODE_NOREFS) {          if (pnode->pn_stat & PNODE_NOREFS) {
                 pnode->pn_stat |= PNODE_DYING;                  pnode->pn_stat |= PNODE_DYING;
                 *ap->a_recycle = true;                  recycle = true;
         }          }
   
           /*
            * Handle node TTL.
            * If grace has already timed out, make it reclaimed.
            * Otherwise, we queue its expiration by sop thread, so
            * that it does not remain for ages in the freelist,
            * holding memory in userspace, while we will have
            * to look it up again anyway.
            */
           if (PUFFS_USE_FS_TTL(pmp) && !(vp->v_vflag & VV_ROOT) && !recycle) {
                   bool incache = !TIMED_OUT(pnode->pn_cn_timeout);
                   bool ingrace = !TIMED_OUT(pnode->pn_cn_grace);
                   bool reclaimqueued = pnode->pn_stat & PNODE_SOPEXP;
   
                   if (!incache && !ingrace && !reclaimqueued) {
                           pnode->pn_stat |= PNODE_DYING;
                           recycle = true;
                   }
   
                   if (!recycle && !reclaimqueued) {
                           struct puffs_sopreq *psopr;
                           int at = MAX(pnode->pn_cn_grace, pnode->pn_cn_timeout);
   
                           KASSERT(curlwp != uvm.pagedaemon_lwp);
                           psopr = kmem_alloc(sizeof(*psopr), KM_SLEEP);
                           psopr->psopr_ck = VPTOPNC(pnode->pn_vp);
                           psopr->psopr_sopreq = PUFFS_SOPREQ_EXPIRE;
                           psopr->psopr_at = at;
   
                           mutex_enter(&pmp->pmp_sopmtx);
   
                           /*
                            * If thread has disapeared, just give up. The
                            * fs is being unmounted and the node will be
                            * be reclaimed anyway.
                            *
                            * Otherwise, we queue the request but do not
                            * immediatly signal the thread, as the node
                            * has not been expired yet.
                            */
                           if (pmp->pmp_sopthrcount == 0) {
                                   kmem_free(psopr, sizeof(*psopr));
                           } else {
                                   TAILQ_INSERT_TAIL(&pmp->pmp_sopnodereqs,
                                       psopr, psopr_entries);
                                   pnode->pn_stat |= PNODE_SOPEXP;
                           }
   
                           mutex_exit(&pmp->pmp_sopmtx);
                   }
           }
   
           *ap->a_recycle = recycle;
   
         mutex_exit(&pnode->pn_sizemtx);          mutex_exit(&pnode->pn_sizemtx);
         VOP_UNLOCK(vp);          VOP_UNLOCK(vp);
   
Line 1079  puffs_vnop_inactive(void *v)
Line 1346  puffs_vnop_inactive(void *v)
 }  }
   
 static void  static void
 callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck)  callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck, int nlookup)
 {  {
         PUFFS_MSG_VARS(vn, reclaim);          PUFFS_MSG_VARS(vn, reclaim);
   
Line 1087  callreclaim(struct puffs_mount *pmp, puf
Line 1354  callreclaim(struct puffs_mount *pmp, puf
                 return;                  return;
   
         PUFFS_MSG_ALLOC(vn, reclaim);          PUFFS_MSG_ALLOC(vn, reclaim);
           reclaim_msg->pvnr_nlookup = nlookup;
         puffs_msg_setfaf(park_reclaim);          puffs_msg_setfaf(park_reclaim);
         puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);          puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);
   
         puffs_msg_enqueue(pmp, park_reclaim);          puffs_msg_enqueue(pmp, park_reclaim);
         PUFFS_MSG_RELEASE(reclaim);          PUFFS_MSG_RELEASE(reclaim);
           return;
 }  }
   
 /*  /*
Line 1131  puffs_vnop_reclaim(void *v)
Line 1400  puffs_vnop_reclaim(void *v)
          */           */
         mutex_enter(&pmp->pmp_lock);          mutex_enter(&pmp->pmp_lock);
         LIST_REMOVE(pnode, pn_hashent);          LIST_REMOVE(pnode, pn_hashent);
           if (PUFFS_USE_NAMECACHE(pmp))
                   cache_purge(vp);
         mutex_exit(&pmp->pmp_lock);          mutex_exit(&pmp->pmp_lock);
   
         if (notifyserver)          if (notifyserver) {
                 callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp));                  int nlookup = VPTOPP(vp)->pn_nlookup;
   
                   callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp), nlookup);
           }
   
           if (PUFFS_USE_DOTDOTCACHE(pmp)) {
                   if (__predict_true(VPTOPP(vp)->pn_parent != NULL))
                           vrele(VPTOPP(vp)->pn_parent);
                   else
                           KASSERT(vp->v_vflag & VV_ROOT);
           }
   
         puffs_putvnode(vp);          puffs_putvnode(vp);
         vp->v_data = NULL;          vp->v_data = NULL;
Line 1340  flushvncache(struct vnode *vp, off_t off
Line 1621  flushvncache(struct vnode *vp, off_t off
         pflags = PGO_CLEANIT;          pflags = PGO_CLEANIT;
         if (wait)          if (wait)
                 pflags |= PGO_SYNCIO;                  pflags |= PGO_SYNCIO;
   
         mutex_enter(vp->v_interlock);          mutex_enter(vp->v_interlock);
         return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags);          return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags);
 }  }
Line 1550  puffs_vnop_mkdir(void *v)
Line 1832  puffs_vnop_mkdir(void *v)
   
         error = puffs_newnode(mp, dvp, ap->a_vpp,          error = puffs_newnode(mp, dvp, ap->a_vpp,
             mkdir_msg->pvnr_newnode, cnp, VDIR, 0);              mkdir_msg->pvnr_newnode, cnp, VDIR, 0);
         if (error)          if (error) {
                 puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,                  puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,
                     mkdir_msg->pvnr_newnode, cnp);                      mkdir_msg->pvnr_newnode, cnp);
                   goto out;
           }
   
           if (PUFFS_USE_FS_TTL(pmp)) {
                   struct timespec *va_ttl = &mkdir_msg->pvnr_va_ttl;
                   struct timespec *cn_ttl = &mkdir_msg->pvnr_cn_ttl;
                   struct vattr *rvap = &mkdir_msg->pvnr_va;
   
                   update_va(*ap->a_vpp, NULL, rvap,
                             va_ttl, cn_ttl, SETATTR_CHSIZE);
           }
   
           VPTOPP(*ap->a_vpp)->pn_nlookup++;
   
           if (PUFFS_USE_DOTDOTCACHE(pmp) &&
               (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
                   update_parent(*ap->a_vpp, dvp);
   
  out:   out:
         vput(dvp);          vput(dvp);
Line 1703  puffs_vnop_symlink(void *v)
Line 2002  puffs_vnop_symlink(void *v)
   
         error = puffs_newnode(mp, dvp, ap->a_vpp,          error = puffs_newnode(mp, dvp, ap->a_vpp,
             symlink_msg->pvnr_newnode, cnp, VLNK, 0);              symlink_msg->pvnr_newnode, cnp, VLNK, 0);
         if (error)          if (error) {
                 puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,                  puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,
                     symlink_msg->pvnr_newnode, cnp);                      symlink_msg->pvnr_newnode, cnp);
                   goto out;
           }
   
           if (PUFFS_USE_FS_TTL(pmp)) {
                   struct timespec *va_ttl = &symlink_msg->pvnr_va_ttl;
                   struct timespec *cn_ttl = &symlink_msg->pvnr_cn_ttl;
                   struct vattr *rvap = &symlink_msg->pvnr_va;
   
                   update_va(*ap->a_vpp, NULL, rvap,
                             va_ttl, cn_ttl, SETATTR_CHSIZE);
           }
   
           VPTOPP(*ap->a_vpp)->pn_nlookup++;
   
           if (PUFFS_USE_DOTDOTCACHE(pmp) &&
               (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
                   update_parent(*ap->a_vpp, dvp);
   
  out:   out:
         vput(dvp);          vput(dvp);
Line 1804  puffs_vnop_rename(void *v)
Line 2120  puffs_vnop_rename(void *v)
          * XXX: stay in touch with the cache.  I don't like this, but           * XXX: stay in touch with the cache.  I don't like this, but
          * don't have a better solution either.  See also puffs_link().           * don't have a better solution either.  See also puffs_link().
          */           */
         if (error == 0)          if (error == 0) {
                 puffs_updatenode(fpn, PUFFS_UPDATECTIME, 0);                  puffs_updatenode(fpn, PUFFS_UPDATECTIME, 0);
   
                   if (PUFFS_USE_DOTDOTCACHE(pmp) &&
                       (VPTOPP(fvp)->pn_parent != tdvp))
                           update_parent(fvp, tdvp);
           }
   
   
  out:   out:
         if (doabort)          if (doabort)
                 VOP_ABORTOP(tdvp, ap->a_tcnp);                  VOP_ABORTOP(tdvp, ap->a_tcnp);
Line 1862  puffs_vnop_read(void *v)
Line 2184  puffs_vnop_read(void *v)
                 const int advice = IO_ADV_DECODE(ap->a_ioflag);                  const int advice = IO_ADV_DECODE(ap->a_ioflag);
   
                 while (uio->uio_resid > 0) {                  while (uio->uio_resid > 0) {
                           if (vp->v_size <= uio->uio_offset) {
                                   break;
                           }
                         bytelen = MIN(uio->uio_resid,                          bytelen = MIN(uio->uio_resid,
                             vp->v_size - uio->uio_offset);                              vp->v_size - uio->uio_offset);
                         if (bytelen == 0)                          if (bytelen == 0)

Legend:
Removed from v.1.163  
changed lines
  Added in v.1.163.2.4

CVSweb <webmaster@jp.NetBSD.org>