[BACK]Return to genfs_io.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / genfs

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

Diff for /src/sys/miscfs/genfs/genfs_io.c between version 1.36 and 1.36.2.36

version 1.36, 2010/01/30 12:06:20 version 1.36.2.36, 2010/11/19 02:30:41
Line 33 
Line 33 
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "$NetBSD$");
   
   #include "opt_xip.h"
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/proc.h>  #include <sys/proc.h>
Line 48  __KERNEL_RCSID(0, "$NetBSD$");
Line 50  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/kauth.h>  #include <sys/kauth.h>
 #include <sys/fstrans.h>  #include <sys/fstrans.h>
 #include <sys/buf.h>  #include <sys/buf.h>
   #include <sys/once.h>
   
 #include <miscfs/genfs/genfs.h>  #include <miscfs/genfs/genfs.h>
 #include <miscfs/genfs/genfs_node.h>  #include <miscfs/genfs/genfs_node.h>
Line 56  __KERNEL_RCSID(0, "$NetBSD$");
Line 59  __KERNEL_RCSID(0, "$NetBSD$");
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
 #include <uvm/uvm_pager.h>  #include <uvm/uvm_pager.h>
   
   static int genfs_do_getpages(void *);
   #ifdef XIP
   static int genfs_do_getpages_xip(void *);
   static int genfs_do_getpages_xip1(struct vnode *, voff_t, struct vm_page **,
       int *, int, vm_prot_t, int, int);
   static int genfs_do_getpages_xip_io(struct vnode *, voff_t, struct vm_page **,
       int *, int, vm_prot_t, int, int);
   static int genfs_do_putpages_xip(struct vnode *, off_t, off_t, int,
       struct vm_page **);
   #endif
 static int genfs_do_directio(struct vmspace *, vaddr_t, size_t, struct vnode *,  static int genfs_do_directio(struct vmspace *, vaddr_t, size_t, struct vnode *,
     off_t, enum uio_rw);      off_t, enum uio_rw);
 static void genfs_dio_iodone(struct buf *);  static void genfs_dio_iodone(struct buf *);
   
 static int genfs_do_io(struct vnode *, off_t, vaddr_t, size_t, int, enum uio_rw,  static int genfs_do_io(struct vnode *, off_t, vaddr_t, size_t, int, enum uio_rw,
     void (*)(struct buf *));      void (*)(struct buf *));
 static inline void genfs_rel_pages(struct vm_page **, int);  static void genfs_rel_pages(struct vm_page **, int);
   static void genfs_markdirty(struct vnode *);
   
 int genfs_maxdio = MAXPHYS;  int genfs_maxdio = MAXPHYS;
   
 static inline void  static void
 genfs_rel_pages(struct vm_page **pgs, int npages)  genfs_rel_pages(struct vm_page **pgs, int npages)
 {  {
         int i;          int i;
Line 85  genfs_rel_pages(struct vm_page **pgs, in
Line 99  genfs_rel_pages(struct vm_page **pgs, in
         mutex_exit(&uvm_pageqlock);          mutex_exit(&uvm_pageqlock);
 }  }
   
   static void
   genfs_markdirty(struct vnode *vp)
   {
           struct genfs_node * const gp = VTOG(vp);
   
           KASSERT(mutex_owned(&vp->v_interlock));
           gp->g_dirtygen++;
           if ((vp->v_iflag & VI_ONWORKLST) == 0) {
                   vn_syncer_add_to_worklist(vp, filedelay);
           }
           if ((vp->v_iflag & (VI_WRMAP|VI_WRMAPDIRTY)) == VI_WRMAP) {
                   vp->v_iflag |= VI_WRMAPDIRTY;
           }
   }
   
 /*  /*
  * generic VM getpages routine.   * generic VM getpages routine.
  * Return PG_BUSY pages for the given range,   * Return PG_BUSY pages for the given range,
Line 94  genfs_rel_pages(struct vm_page **pgs, in
Line 123  genfs_rel_pages(struct vm_page **pgs, in
 int  int
 genfs_getpages(void *v)  genfs_getpages(void *v)
 {  {
   #ifdef XIP
           struct vop_getpages_args /* {
                   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;
           } */ * const ap = v;
   
           if ((ap->a_vp->v_vflag & VV_XIP) != 0)
                   return genfs_do_getpages_xip(v);
           else
   #endif
                   return genfs_do_getpages(v);
   }
   
   static int
   genfs_do_getpages(void *v)
   {
         struct vop_getpages_args /* {          struct vop_getpages_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 voff_t a_offset;                  voff_t a_offset;
Line 109  genfs_getpages(void *v)
Line 160  genfs_getpages(void *v)
         int i, error, npages;          int i, error, npages;
         const int flags = ap->a_flags;          const int flags = ap->a_flags;
         struct vnode * const vp = ap->a_vp;          struct vnode * const vp = ap->a_vp;
         struct genfs_node * const gp = VTOG(vp);  
         struct uvm_object * const uobj = &vp->v_uobj;          struct uvm_object * const uobj = &vp->v_uobj;
         kauth_cred_t const cred = curlwp->l_cred;               /* XXXUBC curlwp */          kauth_cred_t const cred = curlwp->l_cred;               /* XXXUBC curlwp */
         const bool async = (flags & PGO_SYNCIO) == 0;          const bool async = (flags & PGO_SYNCIO) == 0;
Line 117  genfs_getpages(void *v)
Line 167  genfs_getpages(void *v)
         bool has_trans = false;          bool has_trans = false;
         const bool overwrite = (flags & PGO_OVERWRITE) != 0;          const bool overwrite = (flags & PGO_OVERWRITE) != 0;
         const bool blockalloc = memwrite && (flags & PGO_NOBLOCKALLOC) == 0;          const bool blockalloc = memwrite && (flags & PGO_NOBLOCKALLOC) == 0;
           const bool glocked = (flags & PGO_GLOCKHELD) != 0;
         UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist);          UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist);
   
         UVMHIST_LOG(ubchist, "vp %p off 0x%x/%x count %d",          UVMHIST_LOG(ubchist, "vp %p off 0x%x/%x count %d",
Line 144  startover:
Line 195  startover:
 #if defined(DIAGNOSTIC)  #if defined(DIAGNOSTIC)
                 GOP_SIZE(vp, vp->v_writesize, &writeeof, GOP_SIZE_MEM);                  GOP_SIZE(vp, vp->v_writesize, &writeeof, GOP_SIZE_MEM);
                 if (newsize > round_page(writeeof)) {                  if (newsize > round_page(writeeof)) {
                         panic("%s: past eof", __func__);                          panic("%s: past eof: %" PRId64 " vs. %" PRId64,
                               __func__, newsize, round_page(writeeof));
                 }                  }
 #endif /* defined(DIAGNOSTIC) */  #endif /* defined(DIAGNOSTIC) */
         } else {          } else {
Line 186  startover:
Line 238  startover:
                 }                  }
         }          }
   
         if (memwrite) {  
                 gp->g_dirtygen++;  
                 if ((vp->v_iflag & VI_ONWORKLST) == 0) {  
                         vn_syncer_add_to_worklist(vp, filedelay);  
                 }  
                 if ((vp->v_iflag & (VI_WRMAP|VI_WRMAPDIRTY)) == VI_WRMAP) {  
                         vp->v_iflag |= VI_WRMAPDIRTY;  
                 }  
         }  
   
         /*          /*
          * For PGO_LOCKED requests, just return whatever's in memory.           * For PGO_LOCKED requests, just return whatever's in memory.
          */           */
Line 204  startover:
Line 246  startover:
                 int nfound;                  int nfound;
                 struct vm_page *pg;                  struct vm_page *pg;
   
                   KASSERT(!glocked);
                 npages = *ap->a_count;                  npages = *ap->a_count;
 #if defined(DEBUG)  #if defined(DEBUG)
                 for (i = 0; i < npages; i++) {                  for (i = 0; i < npages; i++) {
Line 228  startover:
Line 271  startover:
                         for (i = 0; i < npages; i++) {                          for (i = 0; i < npages; i++) {
                                 pg = ap->a_m[i];                                  pg = ap->a_m[i];
   
                                 if (pg != NULL || pg != PGO_DONTCARE) {                                  if (pg != NULL && pg != PGO_DONTCARE) {
                                         ap->a_m[i] = NULL;                                          ap->a_m[i] = NULL;
                                 }                                  }
                                   KASSERT(pg == NULL || pg == PGO_DONTCARE);
                         }                          }
                 } else {                  } else {
                         genfs_node_unlock(vp);                          genfs_node_unlock(vp);
                 }                  }
                 error = (ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0);                  error = (ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0);
                   if (error == 0 && memwrite) {
                           genfs_markdirty(vp);
                   }
                 goto out_err;                  goto out_err;
         }          }
         mutex_exit(&uobj->vmobjlock);          mutex_exit(&uobj->vmobjlock);
Line 293  startover:
Line 340  startover:
          * check if our idea of v_size is still valid.           * check if our idea of v_size is still valid.
          */           */
   
         if (blockalloc) {          KASSERT(!glocked || genfs_node_wrlocked(vp));
                 rw_enter(&gp->g_glock, RW_WRITER);          if (!glocked) {
         } else {                  if (blockalloc) {
                 rw_enter(&gp->g_glock, RW_READER);                          genfs_node_wrlock(vp);
                   } else {
                           genfs_node_rdlock(vp);
                   }
         }          }
         mutex_enter(&uobj->vmobjlock);          mutex_enter(&uobj->vmobjlock);
         if (vp->v_size < origvsize) {          if (vp->v_size < origvsize) {
                 genfs_node_unlock(vp);                  if (!glocked) {
                           genfs_node_unlock(vp);
                   }
                 if (pgs != pgs_onstack)                  if (pgs != pgs_onstack)
                         kmem_free(pgs, pgs_size);                          kmem_free(pgs, pgs_size);
                 goto startover;                  goto startover;
Line 308  startover:
Line 360  startover:
   
         if (uvn_findpages(uobj, origoffset, &npages, &pgs[ridx],          if (uvn_findpages(uobj, origoffset, &npages, &pgs[ridx],
             async ? UFP_NOWAIT : UFP_ALL) != orignmempages) {              async ? UFP_NOWAIT : UFP_ALL) != orignmempages) {
                 genfs_node_unlock(vp);                  if (!glocked) {
                           genfs_node_unlock(vp);
                   }
                 KASSERT(async != 0);                  KASSERT(async != 0);
                 genfs_rel_pages(&pgs[ridx], orignmempages);                  genfs_rel_pages(&pgs[ridx], orignmempages);
                 mutex_exit(&uobj->vmobjlock);                  mutex_exit(&uobj->vmobjlock);
Line 329  startover:
Line 383  startover:
                 }                  }
         }          }
         if (i == npages) {          if (i == npages) {
                 genfs_node_unlock(vp);                  if (!glocked) {
                           genfs_node_unlock(vp);
                   }
                 UVMHIST_LOG(ubchist, "returning cached pages", 0,0,0,0);                  UVMHIST_LOG(ubchist, "returning cached pages", 0,0,0,0);
                 npages += ridx;                  npages += ridx;
                 goto out;                  goto out;
Line 340  startover:
Line 396  startover:
          */           */
   
         if (overwrite) {          if (overwrite) {
                 genfs_node_unlock(vp);                  if (!glocked) {
                           genfs_node_unlock(vp);
                   }
                 UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0);                  UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0);
   
                 for (i = 0; i < npages; i++) {                  for (i = 0; i < npages; i++) {
Line 376  startover:
Line 434  startover:
                 npgs = npages;                  npgs = npages;
                 if (uvn_findpages(uobj, startoffset, &npgs, pgs,                  if (uvn_findpages(uobj, startoffset, &npgs, pgs,
                     async ? UFP_NOWAIT : UFP_ALL) != npages) {                      async ? UFP_NOWAIT : UFP_ALL) != npages) {
                         genfs_node_unlock(vp);                          if (!glocked) {
                                   genfs_node_unlock(vp);
                           }
                         KASSERT(async != 0);                          KASSERT(async != 0);
                         genfs_rel_pages(pgs, npages);                          genfs_rel_pages(pgs, npages);
                         mutex_exit(&uobj->vmobjlock);                          mutex_exit(&uobj->vmobjlock);
Line 574  loopdone:
Line 634  loopdone:
         nestiobuf_done(mbp, skipbytes, error);          nestiobuf_done(mbp, skipbytes, error);
         if (async) {          if (async) {
                 UVMHIST_LOG(ubchist, "returning 0 (async)",0,0,0,0);                  UVMHIST_LOG(ubchist, "returning 0 (async)",0,0,0,0);
                 genfs_node_unlock(vp);                  if (!glocked) {
                           genfs_node_unlock(vp);
                   }
                 error = 0;                  error = 0;
                 goto out_err_free;                  goto out_err_free;
         }          }
Line 625  loopdone:
Line 687  loopdone:
                         }                          }
                 }                  }
         }          }
         genfs_node_unlock(vp);          if (!glocked) {
                   genfs_node_unlock(vp);
           }
   
         putiobuf(mbp);          putiobuf(mbp);
     }      }
Line 696  out:
Line 760  out:
                 }                  }
         }          }
         mutex_exit(&uvm_pageqlock);          mutex_exit(&uvm_pageqlock);
           if (memwrite) {
                   genfs_markdirty(vp);
           }
         mutex_exit(&uobj->vmobjlock);          mutex_exit(&uobj->vmobjlock);
         if (ap->a_m != NULL) {          if (ap->a_m != NULL) {
                 memcpy(ap->a_m, &pgs[ridx],                  memcpy(ap->a_m, &pgs[ridx],
Line 708  out_err_free:
Line 775  out_err_free:
 out_err:  out_err:
         if (has_trans)          if (has_trans)
                 fstrans_done(vp->v_mount);                  fstrans_done(vp->v_mount);
         return (error);          return error;
 }  }
   
   #ifdef XIP
   /*
    * genfs_do_getpages_xip
    *      Return "direct pages" of XIP vnode.  The block addresses of XIP
    *      vnode pages are returned back to the VM fault handler as the
    *      actually mapped physical addresses.
    */
   static int
   genfs_do_getpages_xip(void *v)
   {
           struct vop_getpages_args /* {
                   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;
           } */ * const ap = v;
   
           UVMHIST_FUNC("genfs_do_getpages_xip"); UVMHIST_CALLED(ubchist);
   
           return genfs_do_getpages_xip1(
                   ap->a_vp,
                   ap->a_offset,
                   ap->a_m,
                   ap->a_count,
                   ap->a_centeridx,
                   ap->a_access_type,
                   ap->a_advice,
                   ap->a_flags);
   }
   
   static int
   genfs_do_getpages_xip1(
           struct vnode *vp,
           voff_t offset,
           struct vm_page **pps,
           int *npagesp,
           int centeridx,
           vm_prot_t access_type,
           int advice,
           int flags)
   {
   
           KASSERT((vp->v_vflag & VV_XIP) != 0);
   
           if ((flags & PGO_LOCKED) != 0) {
                   *npagesp = 0;
                   return 0;
           } else
                   return genfs_do_getpages_xip_io(
                           vp,
                           offset,
                           pps,
                           npagesp,
                           centeridx,
                           access_type,
                           advice,
                           flags);
   }
   
   static int
   genfs_do_getpages_xip_io(
           struct vnode *vp,
           voff_t offset,
           struct vm_page **pps,
           int *npagesp,
           int centeridx,
           vm_prot_t access_type,
           int advice,
           int flags)
   {
           struct uvm_object * const uobj = &vp->v_uobj;
   
           int error;
           off_t eof, sbkoff, ebkoff, off;
           int npages;
           int fs_bshift, fs_bsize, dev_bshift, dev_bsize;
           int i;
           struct vm_page *zero_page;
   
           UVMHIST_FUNC("genfs_do_getpages_xip_io"); UVMHIST_CALLED(ubchist);
   
           GOP_SIZE(vp, vp->v_size, &eof, GOP_SIZE_MEM);
           npages = MIN(*npagesp, round_page(eof - offset) >> PAGE_SHIFT);
   
           fs_bshift = vp->v_mount->mnt_fs_bshift;
           fs_bsize = 1 << fs_bshift;
           dev_bshift = vp->v_mount->mnt_dev_bshift;
           dev_bsize = 1 << dev_bshift;
   
           sbkoff = offset & ~(fs_bsize - 1);
           ebkoff = ((offset + PAGE_SIZE * npages) + (fs_bsize - 1)) &
               ~(fs_bsize - 1);
   
           zero_page = NULL;
   
           UVMHIST_LOG(ubchist, "xip npages=%d sbkoff=%lx ebkoff=%lx",
               npages, (long)sbkoff, (long)ebkoff, 0);
   
           KASSERT(mutex_owned(&uobj->vmobjlock));
           mutex_exit(&uobj->vmobjlock);
   
           off = offset;
           for (i = 0; i < npages; i++) {
                   daddr_t lbn, blkno;
                   int run;
                   struct vnode *devvp;
   
                   lbn = (off & ~(fs_bsize - 1)) >> fs_bshift;
   
                   error = VOP_BMAP(vp, lbn, &devvp, &blkno, &run);
                   KASSERT(error == 0);
                   UVMHIST_LOG(ubchist, "xip VOP_BMAP: lbn=%ld blkno=%ld run=%d",
                       (long)lbn, (long)blkno, run, 0);
   
                   /*
                    * XIP page metadata assignment
                    * - Unallocated block is redirected to the dedicated zero'ed
                    *   page.
                    */
                   if (blkno < 0) {
                           zero_page = uvm_page_zeropage_alloc();
                           KASSERT(zero_page != NULL);
                           pps[i] = zero_page;
                   } else {
                           daddr_t blk_off, fs_off;
   
                           blk_off = blkno << dev_bshift;
                           fs_off = off - (lbn << fs_bshift);
   
                           pps[i] = uvn_findpage_xip(devvp, &vp->v_uobj,
                               blk_off + fs_off);
                           KASSERT(pps[i] != NULL);
                   }
   
                   UVMHIST_LOG(ubchist, "xip pgs %d => phys_addr=0x%lx (%p)",
                           i,
                           (long)pps[i]->phys_addr,
                           pps[i],
                           0);
   
                   off += PAGE_SIZE;
           }
   
           mutex_enter(&uobj->vmobjlock);
   
           for (i = 0; i < npages; i++) {
                   struct vm_page *pg = pps[i];
   
                   KASSERT((pg->flags & PG_RDONLY) != 0);
                   if (pg == zero_page)
                           continue;
                   KASSERT((pg->flags & PG_BUSY) == 0);
                   KASSERT((pg->flags & PG_CLEAN) != 0);
                   KASSERT((pg->flags & PG_DEVICE) != 0);
                   pg->flags |= PG_BUSY;
                   pg->flags &= ~PG_FAKE;
                   pg->uobject = &vp->v_uobj;
           }
   
           mutex_exit(&uobj->vmobjlock);
   
           *npagesp = npages;
   
           return 0;
   }
   #endif
   
 /*  /*
  * generic VM putpages routine.   * generic VM putpages routine.
  * Write the given range of pages to backing store.   * Write the given range of pages to backing store.
Line 769  genfs_putpages(void *v)
Line 1007  genfs_putpages(void *v)
                 int a_flags;                  int a_flags;
         } */ * const ap = v;          } */ * const ap = v;
   
   #ifdef XIP
           if ((ap->a_vp->v_vflag & VV_XIP) != 0)
                   return genfs_do_putpages_xip(ap->a_vp, ap->a_offlo, ap->a_offhi,
                       ap->a_flags, NULL);
           else
   #endif
         return genfs_do_putpages(ap->a_vp, ap->a_offlo, ap->a_offhi,          return genfs_do_putpages(ap->a_vp, ap->a_offlo, ap->a_offhi,
             ap->a_flags, NULL);              ap->a_flags, NULL);
 }  }
Line 891  retry:
Line 1135  retry:
         dirtygen = gp->g_dirtygen;          dirtygen = gp->g_dirtygen;
         freeflag = pagedaemon ? PG_PAGEOUT : PG_RELEASED;          freeflag = pagedaemon ? PG_PAGEOUT : PG_RELEASED;
         if (by_list) {          if (by_list) {
                 curmp.uobject = uobj;                  curmp.flags = PG_MARKER;
                 curmp.offset = (voff_t)-1;                  endmp.flags = PG_MARKER;
                 curmp.flags = PG_BUSY;  
                 endmp.uobject = uobj;  
                 endmp.offset = (voff_t)-1;  
                 endmp.flags = PG_BUSY;  
                 pg = TAILQ_FIRST(&uobj->memq);                  pg = TAILQ_FIRST(&uobj->memq);
                 TAILQ_INSERT_TAIL(&uobj->memq, &endmp, listq.queue);                  TAILQ_INSERT_TAIL(&uobj->memq, &endmp, listq.queue);
         } else {          } else {
Line 909  retry:
Line 1149  retry:
                  * if the current page is not interesting, move on to the next.                   * if the current page is not interesting, move on to the next.
                  */                   */
   
                 KASSERT(pg == NULL || pg->uobject == uobj);                  KASSERT(pg == NULL || pg->uobject == uobj ||
                       (pg->flags & PG_MARKER) != 0);
                 KASSERT(pg == NULL ||                  KASSERT(pg == NULL ||
                     (pg->flags & (PG_RELEASED|PG_PAGEOUT)) == 0 ||                      (pg->flags & (PG_RELEASED|PG_PAGEOUT)) == 0 ||
                     (pg->flags & PG_BUSY) != 0);                      (pg->flags & (PG_BUSY|PG_MARKER)) != 0);
                 if (by_list) {                  if (by_list) {
                         if (pg == &endmp) {                          if (pg == &endmp) {
                                 break;                                  break;
                         }                          }
                           if (pg->flags & PG_MARKER) {
                                   pg = TAILQ_NEXT(pg, listq.queue);
                                   continue;
                           }
                         if (pg->offset < startoff || pg->offset >= endoff ||                          if (pg->offset < startoff || pg->offset >= endoff ||
                             pg->flags & (PG_RELEASED|PG_PAGEOUT)) {                              pg->flags & (PG_RELEASED|PG_PAGEOUT)) {
                                 if (pg->flags & (PG_RELEASED|PG_PAGEOUT)) {                                  if (pg->flags & (PG_RELEASED|PG_PAGEOUT)) {
Line 1186  retry:
Line 1431  retry:
             (vp->v_iflag & VI_ONWORKLST) != 0) {              (vp->v_iflag & VI_ONWORKLST) != 0) {
 #if defined(DEBUG)  #if defined(DEBUG)
                 TAILQ_FOREACH(pg, &uobj->memq, listq.queue) {                  TAILQ_FOREACH(pg, &uobj->memq, listq.queue) {
                           if ((pg->flags & PG_MARKER) != 0) {
                                   continue;
                           }
                         if ((pg->flags & PG_CLEAN) == 0) {                          if ((pg->flags & PG_CLEAN) == 0) {
                                 printf("%s: %p: !CLEAN\n", __func__, pg);                                  printf("%s: %p: !CLEAN\n", __func__, pg);
                         }                          }
Line 1230  skip_scan:
Line 1478  skip_scan:
         return (error);          return (error);
 }  }
   
   #ifdef XIP
   int
   genfs_do_putpages_xip(struct vnode *vp, off_t startoff, off_t endoff,
       int flags, struct vm_page **busypg)
   {
           struct uvm_object *uobj = &vp->v_uobj;
   #ifdef DIAGNOSTIC
           struct genfs_node * const gp = VTOG(vp);
   #endif
   
           UVMHIST_FUNC("genfs_do_putpages_xip"); UVMHIST_CALLED(ubchist);
   
           KASSERT(mutex_owned(&uobj->vmobjlock));
           KASSERT((vp->v_iflag & VI_ONWORKLST) == 0);
           KASSERT(vp->v_numoutput == 0);
           KASSERT(gp->g_dirtygen == 0);
   
           UVMHIST_LOG(ubchist, "vp %p pages %d off 0x%x len 0x%x",
               vp, uobj->uo_npages, startoff, endoff - startoff);
   
           /*
            * XIP pages are read-only, and never become dirty.  They're also never
            * queued.  PGO_DEACTIVATE and PGO_CLEANIT are meaningless for XIP
            * pages, so we ignore them.
            */
           if ((flags & PGO_FREE) == 0)
                   goto done;
   
           /*
            * For PGO_FREE (or (PGO_CLEANIT | PGO_FREE)), we invalidate MMU
            * mappings of both XIP pages and XIP zero pages.
            *
            * Zero page is freed when one of its mapped offset is freed, even if
            * one file (vnode) has many holes and mapping its zero page to all
            * of those hole pages.
            *
            * We don't know which pages are currently mapped in the given vnode,
            * because XIP pages are not added to vnode.  What we can do is to
            * locate pages by querying the filesystem as done in getpages.  Call
            * genfs_do_getpages_xip1().
            */
   
           off_t off, eof;
           struct vm_page *zero_page;
           bool put_zero_page;
   
           off = trunc_page(startoff);
           if (endoff == 0 || (flags & PGO_ALLPAGES))
                   GOP_SIZE(vp, vp->v_size, &eof, GOP_SIZE_MEM);
           else
                   eof = endoff;
   
           zero_page = uvm_pagelookup(uobj, 0);
           KASSERT(zero_page != NULL || uobj->uo_npages == 0);
           KASSERT(zero_page == NULL || uobj->uo_npages == 1);
           put_zero_page = false;
   
           while (off < eof) {
                   int npages, orignpages, error, i;
                   struct vm_page *pgs[maxpages], *pg;
   
                   npages = round_page(eof - off) >> PAGE_SHIFT;
                   if (npages > maxpages)
                           npages = maxpages;
   
                   orignpages = npages;
                   KASSERT(mutex_owned(&uobj->vmobjlock));
                   error = genfs_do_getpages_xip1(vp, off, pgs, &npages, 0,
                       VM_PROT_ALL, 0, 0);
                   KASSERT(error == 0);
                   KASSERT(npages == orignpages);
                   mutex_enter(&uobj->vmobjlock);
                   for (i = 0; i < npages; i++) {
                           pg = pgs[i];
                           if (pg == NULL || pg == PGO_DONTCARE)
                                   continue;
                           if (pg == uvm_page_zeropage)
                                   /* Do nothing for holes. */
                                   continue;
                           /*
                            * Freeing normal XIP pages; nothing to do.
                            */
                           pmap_page_protect(pg, VM_PROT_NONE);
                           KASSERT((pg->flags & PG_BUSY) != 0);
                           KASSERT((pg->flags & PG_RDONLY) != 0);
                           KASSERT((pg->flags & PG_CLEAN) != 0);
                           KASSERT((pg->flags & PG_FAKE) == 0);
                           KASSERT((pg->flags & PG_DEVICE) != 0);
                           pg->flags &= ~PG_BUSY;
                   }
                   off += npages << PAGE_SHIFT;
           }
   
           KASSERT(uobj->uo_npages == 0);
   
   done:
           KASSERT(mutex_owned(&uobj->vmobjlock));
           mutex_exit(&uobj->vmobjlock);
           return 0;
   }
   #endif
   
 int  int
 genfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)  genfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
 {  {
Line 1463  genfs_compat_getpages(void *v)
Line 1813  genfs_compat_getpages(void *v)
         orignpages = *ap->a_count;          orignpages = *ap->a_count;
         pgs = ap->a_m;          pgs = ap->a_m;
   
         if (memwrite && (vp->v_iflag & VI_ONWORKLST) == 0) {  
                 vn_syncer_add_to_worklist(vp, filedelay);  
         }  
         if (ap->a_flags & PGO_LOCKED) {          if (ap->a_flags & PGO_LOCKED) {
                 uvn_findpages(uobj, origoffset, ap->a_count, ap->a_m,                  uvn_findpages(uobj, origoffset, ap->a_count, ap->a_m,
                     UFP_NOWAIT|UFP_NOALLOC| (memwrite ? UFP_NORDONLY : 0));                      UFP_NOWAIT|UFP_NOALLOC| (memwrite ? UFP_NORDONLY : 0));
   
                 return (ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0);                  error = ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0;
                   if (error == 0 && memwrite) {
                           genfs_markdirty(vp);
                   }
                   return error;
         }          }
         if (origoffset + (ap->a_centeridx << PAGE_SHIFT) >= vp->v_size) {          if (origoffset + (ap->a_centeridx << PAGE_SHIFT) >= vp->v_size) {
                 mutex_exit(&uobj->vmobjlock);                  mutex_exit(&uobj->vmobjlock);
                 return (EINVAL);                  return EINVAL;
         }          }
         if ((ap->a_flags & PGO_SYNCIO) == 0) {          if ((ap->a_flags & PGO_SYNCIO) == 0) {
                 mutex_exit(&uobj->vmobjlock);                  mutex_exit(&uobj->vmobjlock);
Line 1523  genfs_compat_getpages(void *v)
Line 1874  genfs_compat_getpages(void *v)
                 uvm_page_unbusy(pgs, npages);                  uvm_page_unbusy(pgs, npages);
         }          }
         mutex_exit(&uvm_pageqlock);          mutex_exit(&uvm_pageqlock);
           if (error == 0 && memwrite) {
                   genfs_markdirty(vp);
           }
         mutex_exit(&uobj->vmobjlock);          mutex_exit(&uobj->vmobjlock);
         return (error);          return error;
 }  }
   
 int  int

Legend:
Removed from v.1.36  
changed lines
  Added in v.1.36.2.36

CVSweb <webmaster@jp.NetBSD.org>