[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.51.2.1 and 1.51.2.2

version 1.51.2.1, 2007/02/27 16:54:13 version 1.51.2.2, 2007/03/24 14:55:58
Line 81  int puffs_advlock(void *);
Line 81  int puffs_advlock(void *);
 int     puffs_strategy(void *);  int     puffs_strategy(void *);
 int     puffs_bmap(void *);  int     puffs_bmap(void *);
 int     puffs_mmap(void *);  int     puffs_mmap(void *);
   int     puffs_getpages(void *);
   
 int     puffs_spec_read(void *);  int     puffs_spec_read(void *);
 int     puffs_spec_write(void *);  int     puffs_spec_write(void *);
Line 284  const struct vnodeopv_entry_desc puffs_m
Line 285  const struct vnodeopv_entry_desc puffs_m
         { &vop_write_desc, puffs_write },               /* write */          { &vop_write_desc, puffs_write },               /* write */
         { &vop_fcntl_desc, puffs_fcntl },               /* fcntl */          { &vop_fcntl_desc, puffs_fcntl },               /* fcntl */
         { &vop_ioctl_desc, puffs_ioctl },               /* ioctl */          { &vop_ioctl_desc, puffs_ioctl },               /* ioctl */
         { &vop_fsync_desc, puffs_fsync },               /* fsync */  
         { &vop_seek_desc, puffs_seek },                 /* seek */          { &vop_seek_desc, puffs_seek },                 /* seek */
         { &vop_remove_desc, puffs_remove },             /* remove */          { &vop_remove_desc, puffs_remove },             /* remove */
         { &vop_link_desc, puffs_link },                 /* link */          { &vop_link_desc, puffs_link },                 /* link */
Line 298  const struct vnodeopv_entry_desc puffs_m
Line 298  const struct vnodeopv_entry_desc puffs_m
         { &vop_islocked_desc, puffs_islocked },         /* islocked */          { &vop_islocked_desc, puffs_islocked },         /* islocked */
         { &vop_pathconf_desc, puffs_pathconf },         /* pathconf */          { &vop_pathconf_desc, puffs_pathconf },         /* pathconf */
         { &vop_advlock_desc, puffs_advlock },           /* advlock */          { &vop_advlock_desc, puffs_advlock },           /* advlock */
         { &vop_getpages_desc, genfs_getpages },         /* getpages */          { &vop_getpages_desc, puffs_getpages },         /* getpages */
         { NULL, NULL }          { NULL, NULL }
 };  };
 const struct vnodeopv_desc puffs_msgop_opv_desc =  const struct vnodeopv_desc puffs_msgop_opv_desc =
Line 691  puffs_getattr(void *v)
Line 691  puffs_getattr(void *v)
                 struct lwp *a_l;                  struct lwp *a_l;
         } */ *ap = v;          } */ *ap = v;
         struct mount *mp;          struct mount *mp;
           struct vnode *vp;
           struct vattr *vap;
           struct puffs_node *pn;
         int error;          int error;
   
         PUFFS_VNREQ(getattr);          PUFFS_VNREQ(getattr);
   
         mp = ap->a_vp->v_mount;          vp = ap->a_vp;
           mp = vp->v_mount;
           vap = ap->a_vap;
   
         vattr_null(&getattr_arg.pvnr_va);          vattr_null(&getattr_arg.pvnr_va);
         puffs_credcvt(&getattr_arg.pvnr_cred, ap->a_cred);          puffs_credcvt(&getattr_arg.pvnr_cred, ap->a_cred);
Line 707  puffs_getattr(void *v)
Line 712  puffs_getattr(void *v)
          * around with VXLOCK and therefore breaks vn_lock().  Proper           * around with VXLOCK and therefore breaks vn_lock().  Proper
          * fix pending.           * fix pending.
          */           */
         error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_GETATTR,          error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount), PUFFS_VN_GETATTR,
             &getattr_arg, sizeof(getattr_arg), VPTOPNC(ap->a_vp),              &getattr_arg, sizeof(getattr_arg), VPTOPNC(vp),
             NULL /* XXXseeabove: should be LOCKEDVP(ap->a_vp) */, NULL);              NULL /* XXXseeabove: should be LOCKEDVP(vp) */, NULL);
         if (error)          if (error)
                 return error;                  return error;
   
         (void)memcpy(ap->a_vap, &getattr_arg.pvnr_va, sizeof(struct vattr));          (void) memcpy(vap, &getattr_arg.pvnr_va, sizeof(struct vattr));
           vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
   
         /*          pn = VPTOPP(vp);
          * fill in information userspace does not have          if (pn->pn_stat & PNODE_METACACHE_ATIME)
          * XXX: but would it be better to do fsid at the generic level?                  vap->va_atime = pn->pn_mc_atime;
          */          if (pn->pn_stat & PNODE_METACACHE_CTIME)
         ap->a_vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];                  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 (getattr_arg.pvnr_va.va_size != VNOVAL)
                           uvm_vnp_setsize(vp, getattr_arg.pvnr_va.va_size);
           }
   
         return 0;          return 0;
 }  }
Line 944  puffs_fsync(void *v)
Line 958  puffs_fsync(void *v)
                 off_t a_offhi;                  off_t a_offhi;
                 struct lwp *a_l;                  struct lwp *a_l;
         } */ *ap = v;          } */ *ap = v;
           struct vattr va;
         struct puffs_mount *pmp;          struct puffs_mount *pmp;
         struct puffs_vnreq_fsync *fsync_argp;          struct puffs_vnreq_fsync *fsync_argp;
         struct vnode *vp;          struct vnode *vp;
Line 956  puffs_fsync(void *v)
Line 971  puffs_fsync(void *v)
         pn = VPTOPP(vp);          pn = VPTOPP(vp);
         pmp = MPTOPUFFSMP(vp->v_mount);          pmp = MPTOPUFFSMP(vp->v_mount);
   
         pflags = PGO_CLEANIT;          /* flush out information from our metacache */
         if (ap->a_flags & FSYNC_WAIT)          if (pn->pn_stat & PNODE_METACACHE_MASK) {
                 pflags |= PGO_SYNCIO;                  vattr_null(&va);
                   if (pn->pn_stat & PNODE_METACACHE_ATIME)
                           va.va_atime = pn->pn_mc_atime;
                   if (pn->pn_stat & PNODE_METACACHE_CTIME)
                           va.va_ctime = pn->pn_mc_ctime;
                   if (pn->pn_stat & PNODE_METACACHE_MTIME)
                           va.va_mtime = pn->pn_mc_ctime;
                   if (pn->pn_stat & PNODE_METACACHE_SIZE)
                           va.va_size = pn->pn_mc_size;
   
                   error = VOP_SETATTR(vp, &va, FSCRED, NULL);
                   if (error)
                           return error;
   
                   pn->pn_stat &= ~PNODE_METACACHE_MASK;
           }
   
         /*          /*
          * flush pages to avoid being overly dirty           * flush pages to avoid being overly dirty
          */           */
           pflags = PGO_CLEANIT;
           if (ap->a_flags & FSYNC_WAIT)
                   pflags |= PGO_SYNCIO;
         simple_lock(&vp->v_interlock);          simple_lock(&vp->v_interlock);
         error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),          error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
             round_page(ap->a_offhi), pflags);              round_page(ap->a_offhi), pflags);
Line 1164  puffs_link(void *v)
Line 1197  puffs_link(void *v)
         error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_LINK,          error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_LINK,
             &link_arg, sizeof(link_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);              &link_arg, sizeof(link_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
   
           /*
            * XXX: stay in touch with the cache.  I don't like this, but
            * don't have a better solution either.  See also puffs_rename().
            */
           if (error == 0)
                   puffs_updatenode(ap->a_vp, PUFFS_UPDATECTIME);
   
         vput(ap->a_dvp);          vput(ap->a_dvp);
   
         return error;          return error;
Line 1275  puffs_rename(void *v)
Line 1315  puffs_rename(void *v)
             PUFFS_VN_RENAME, &rename_arg, sizeof(rename_arg),              PUFFS_VN_RENAME, &rename_arg, sizeof(rename_arg),
             VPTOPNC(ap->a_fdvp), NULL, NULL);              VPTOPNC(ap->a_fdvp), NULL, NULL);
   
           /*
            * XXX: stay in touch with the cache.  I don't like this, but
            * don't have a better solution either.  See also puffs_link().
            */
           if (error == 0)
                   puffs_updatenode(ap->a_fvp, PUFFS_UPDATECTIME);
   
  out:   out:
         if (ap->a_tvp != NULL)          if (ap->a_tvp != NULL)
                 vput(ap->a_tvp);                  vput(ap->a_tvp);
Line 1785  puffs_strategy(void *v)
Line 1832  puffs_strategy(void *v)
                 dowritefaf = 1;                  dowritefaf = 1;
   
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
         if (dowritefaf)  
                 KASSERT((bp->b_flags & B_READ) == 0);  
         if (curproc == uvm.pagedaemon_proc)          if (curproc == uvm.pagedaemon_proc)
                 KASSERT(dowritefaf);                  KASSERT(dowritefaf);
 #endif  #endif
   
         if (bp->b_flags & B_READ) {          tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);
   
           if ((bp->b_flags & (B_READ | B_ASYNC)) == (B_READ | B_ASYNC)) {
                   puffs_vntouser_bioread_async(pmp, VPTOPNC(vp), tomove,
                       bp->b_blkno << DEV_BSHIFT, bp, LOCKEDVP(vp), NULL);
           } else if (bp->b_flags & B_READ) {
                 argsize = sizeof(struct puffs_vnreq_read);                  argsize = sizeof(struct puffs_vnreq_read);
                 read_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);                  read_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
                 if (read_argp == NULL) {                  if (read_argp == NULL) {
Line 1799  puffs_strategy(void *v)
Line 1849  puffs_strategy(void *v)
                         goto out;                          goto out;
                 }                  }
   
                 tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);  
   
                 read_argp->pvnr_ioflag = 0;                  read_argp->pvnr_ioflag = 0;
                 read_argp->pvnr_resid = tomove;                  read_argp->pvnr_resid = tomove;
                 read_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;                  read_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
Line 1823  puffs_strategy(void *v)
Line 1871  puffs_strategy(void *v)
                 (void)memcpy(bp->b_data, read_argp->pvnr_data, moved);                  (void)memcpy(bp->b_data, read_argp->pvnr_data, moved);
                 bp->b_resid = bp->b_bcount - moved;                  bp->b_resid = bp->b_bcount - moved;
         } else {          } else {
                   /*
                    * make pages read-only before we write them if we want
                    * write caching info
                    */
                   if (PUFFS_WCACHEINFO(pmp)) {
                           struct uvm_object *uobj = &vp->v_uobj;
                           int npages = (bp->b_bcount + PAGE_SIZE-1) >> PAGE_SHIFT;
                           struct vm_page *vmp;
                           int i;
   
                           for (i = 0; i < npages; i++) {
                                   vmp= uvm_pageratop((vaddr_t)bp->b_data
                                       + (i << PAGE_SHIFT));
                                   DPRINTF(("puffs_strategy: write-protecting "
                                       "vp %p page %p, offset %" PRId64"\n",
                                       vp, vmp, vmp->offset));
                                   simple_lock(&uobj->vmobjlock);
                                   vmp->flags |= PG_RDONLY;
                                   pmap_page_protect(vmp, VM_PROT_READ);
                                   simple_unlock(&uobj->vmobjlock);
                           }
                   }
   
                 argsize = sizeof(struct puffs_vnreq_write) + bp->b_bcount;                  argsize = sizeof(struct puffs_vnreq_write) + bp->b_bcount;
                 write_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);                  write_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
                 if (write_argp == NULL) {                  if (write_argp == NULL) {
Line 1830  puffs_strategy(void *v)
Line 1901  puffs_strategy(void *v)
                         goto out;                          goto out;
                 }                  }
   
                 tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);  
   
                 write_argp->pvnr_ioflag = 0;                  write_argp->pvnr_ioflag = 0;
                 write_argp->pvnr_resid = tomove;                  write_argp->pvnr_resid = tomove;
                 write_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;                  write_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
Line 1877  puffs_strategy(void *v)
Line 1946  puffs_strategy(void *v)
                 bp->b_flags |= B_ERROR;                  bp->b_flags |= B_ERROR;
         }          }
   
         biodone(bp);          if ((bp->b_flags & (B_READ | B_ASYNC)) != (B_READ | B_ASYNC))
                   biodone(bp);
         return error;          return error;
 }  }
   
Line 1951  puffs_bmap(void *v)
Line 2021  puffs_bmap(void *v)
         return 0;          return 0;
 }  }
   
   /*
    * Handle getpages faults in puffs.  We let genfs_getpages() do most
    * of the dirty work, but we come in this route to do accounting tasks.
    * If the user server has specified functions for cache notifications
    * about reads and/or writes, we record which type of operation we got,
    * for which page range, and proceed to issue a FAF notification to the
    * server about it.
    */
   int
   puffs_getpages(void *v)
   {
           struct vop_getpages_args /* {
                   const struct vnodeop_desc *a_desc;
                   struct vnode *a_vp;
                   voff_t a_offset;
                   struct vm_page **a_m;
                   int *a_count;
                   int a_centeridx;
                   vm_prot_t a_access_type;
                   int a_advice;
                   int a_flags;
           } */ *ap = v;
           struct puffs_mount *pmp;
           struct vnode *vp;
           struct vm_page **pgs;
           struct puffs_park *ppark = NULL;
           struct puffs_cacheinfo *pcinfo = NULL;
           struct puffs_cacherun *pcrun;
           size_t runsizes;
           int i, npages, si, streakon;
           int error, locked, write;
   
           pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
           npages = *ap->a_count;
           pgs = ap->a_m;
           vp = ap->a_vp;
           locked = (ap->a_flags & PGO_LOCKED) != 0;
           write = (ap->a_access_type & VM_PROT_WRITE) != 0;
   
           /* ccg xnaht - gets Wuninitialized wrong */
           pcrun = NULL;
           runsizes = 0;
   
           if (write && PUFFS_WCACHEINFO(pmp)) {
                   /* allocate worst-case memory */
                   runsizes = ((npages / 2) + 1) * sizeof(struct puffs_cacherun);
                   pcinfo = malloc(sizeof(struct puffs_cacheinfo) + runsizes,
                       M_PUFFS, M_ZERO | locked ? M_NOWAIT : M_WAITOK);
   
                   /*
                    * can't block if we're locked and can't mess up caching
                    * information for fs server.  so come back later, please
                    */
                   if (pcinfo == NULL) {
                           error = ENOMEM;
                           goto out;
                   }
   
                   ppark = malloc(sizeof(struct puffs_park), M_PUFFS, M_NOWAIT);
                   if (ppark == NULL) {
                           error = ENOMEM;
                           goto out;
                   }
   
                   pcrun = pcinfo->pcache_runs;
           }
   
           error = genfs_getpages(v);
           if (error)
                   goto out;
   
           if (PUFFS_WCACHEINFO(pmp) == 0)
                   goto out;
   
           /*
            * Let's see whose fault it was and inform the user server of
            * possibly read/written pages.  Map pages from read faults
            * strictly read-only, since otherwise we might miss info on
            * when the page is actually write-faulted to.
            */
           if (!locked)
                   simple_lock(&vp->v_uobj.vmobjlock);
           for (i = 0, si = 0, streakon = 0; i < npages; i++) {
                   if (pgs[i] == NULL || pgs[i] == PGO_DONTCARE) {
                           if (streakon && write) {
                                   streakon = 0;
                                   pcrun[si].pcache_runend
                                       = trunc_page(pgs[i]->offset) + PAGE_MASK;
                                   si++;
                           }
                           continue;
                   }
                   if (streakon == 0 && write) {
                           streakon = 1;
                           pcrun[si].pcache_runstart = pgs[i]->offset;
                   }
   
                   if (!write)
                           pgs[i]->flags |= PG_RDONLY;
           }
           /* was the last page part of our streak? */
           if (streakon) {
                   pcrun[si].pcache_runend
                       = trunc_page(pgs[i-1]->offset) + PAGE_MASK;
                   si++;
           }
           if (!locked)
                   simple_unlock(&vp->v_uobj.vmobjlock);
   
           KASSERT(si <= (npages / 2) + 1);
   
           /* send results to userspace */
           if (write)
                   puffs_cacheop(pmp, ppark, pcinfo,
                       sizeof(struct puffs_cacheinfo) + runsizes, VPTOPNC(vp));
   
    out:
           if (error) {
                   if (pcinfo != NULL)
                           free(pcinfo, M_PUFFS);
                   if (ppark != NULL)
                           free(ppark, M_PUFFS);
           }
   
           return error;
   }
   
 int  int
 puffs_lock(void *v)  puffs_lock(void *v)

Legend:
Removed from v.1.51.2.1  
changed lines
  Added in v.1.51.2.2

CVSweb <webmaster@jp.NetBSD.org>