Print this page
patch SEGOP_SWAPOUT-delete

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/vm/seg_vn.c
          +++ new/usr/src/uts/common/vm/seg_vn.c
↓ open down ↓ 80 lines elided ↑ open up ↑
  81   81  static void     segvn_free(struct seg *seg);
  82   82  static faultcode_t segvn_fault(struct hat *hat, struct seg *seg,
  83   83                      caddr_t addr, size_t len, enum fault_type type,
  84   84                      enum seg_rw rw);
  85   85  static faultcode_t segvn_faulta(struct seg *seg, caddr_t addr);
  86   86  static int      segvn_setprot(struct seg *seg, caddr_t addr,
  87   87                      size_t len, uint_t prot);
  88   88  static int      segvn_checkprot(struct seg *seg, caddr_t addr,
  89   89                      size_t len, uint_t prot);
  90   90  static int      segvn_kluster(struct seg *seg, caddr_t addr, ssize_t delta);
  91      -static size_t   segvn_swapout(struct seg *seg);
  92   91  static int      segvn_sync(struct seg *seg, caddr_t addr, size_t len,
  93   92                      int attr, uint_t flags);
  94   93  static size_t   segvn_incore(struct seg *seg, caddr_t addr, size_t len,
  95   94                      char *vec);
  96   95  static int      segvn_lockop(struct seg *seg, caddr_t addr, size_t len,
  97   96                      int attr, int op, ulong_t *lockmap, size_t pos);
  98   97  static int      segvn_getprot(struct seg *seg, caddr_t addr, size_t len,
  99   98                      uint_t *protv);
 100   99  static u_offset_t       segvn_getoffset(struct seg *seg, caddr_t addr);
 101  100  static int      segvn_gettype(struct seg *seg, caddr_t addr);
↓ open down ↓ 13 lines elided ↑ open up ↑
 115  114  
 116  115  struct  seg_ops segvn_ops = {
 117  116          segvn_dup,
 118  117          segvn_unmap,
 119  118          segvn_free,
 120  119          segvn_fault,
 121  120          segvn_faulta,
 122  121          segvn_setprot,
 123  122          segvn_checkprot,
 124  123          segvn_kluster,
 125      -        segvn_swapout,
 126  124          segvn_sync,
 127  125          segvn_incore,
 128  126          segvn_lockop,
 129  127          segvn_getprot,
 130  128          segvn_getoffset,
 131  129          segvn_gettype,
 132  130          segvn_getvp,
 133  131          segvn_advise,
 134  132          segvn_dump,
 135  133          segvn_pagelock,
↓ open down ↓ 6854 lines elided ↑ open up ↑
6990 6988          swap_xlate(ap, &vp1, &off1);
6991 6989          swap_xlate(oap, &vp2, &off2);
6992 6990  
6993 6991  
6994 6992          if (!VOP_CMP(vp1, vp2, NULL) || off1 - off2 != delta)
6995 6993                  return (-1);
6996 6994          return (0);
6997 6995  }
6998 6996  
6999 6997  /*
7000      - * Swap the pages of seg out to secondary storage, returning the
7001      - * number of bytes of storage freed.
7002      - *
7003      - * The basic idea is first to unload all translations and then to call
7004      - * VOP_PUTPAGE() for all newly-unmapped pages, to push them out to the
7005      - * swap device.  Pages to which other segments have mappings will remain
7006      - * mapped and won't be swapped.  Our caller (as_swapout) has already
7007      - * performed the unloading step.
7008      - *
7009      - * The value returned is intended to correlate well with the process's
7010      - * memory requirements.  However, there are some caveats:
7011      - * 1)   When given a shared segment as argument, this routine will
7012      - *      only succeed in swapping out pages for the last sharer of the
7013      - *      segment.  (Previous callers will only have decremented mapping
7014      - *      reference counts.)
7015      - * 2)   We assume that the hat layer maintains a large enough translation
7016      - *      cache to capture process reference patterns.
7017      - */
7018      -static size_t
7019      -segvn_swapout(struct seg *seg)
7020      -{
7021      -        struct segvn_data *svd = (struct segvn_data *)seg->s_data;
7022      -        struct anon_map *amp;
7023      -        pgcnt_t pgcnt = 0;
7024      -        pgcnt_t npages;
7025      -        pgcnt_t page;
7026      -        ulong_t anon_index;
7027      -
7028      -        ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
7029      -
7030      -        SEGVN_LOCK_ENTER(seg->s_as, &svd->lock, RW_READER);
7031      -        /*
7032      -         * Find pages unmapped by our caller and force them
7033      -         * out to the virtual swap device.
7034      -         */
7035      -        if ((amp = svd->amp) != NULL)
7036      -                anon_index = svd->anon_index;
7037      -        npages = seg->s_size >> PAGESHIFT;
7038      -        for (page = 0; page < npages; page++) {
7039      -                page_t *pp;
7040      -                struct anon *ap;
7041      -                struct vnode *vp;
7042      -                u_offset_t off;
7043      -                anon_sync_obj_t cookie;
7044      -
7045      -                /*
7046      -                 * Obtain <vp, off> pair for the page, then look it up.
7047      -                 *
7048      -                 * Note that this code is willing to consider regular
7049      -                 * pages as well as anon pages.  Is this appropriate here?
7050      -                 */
7051      -                ap = NULL;
7052      -                if (amp != NULL) {
7053      -                        ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
7054      -                        if (anon_array_try_enter(amp, anon_index + page,
7055      -                            &cookie)) {
7056      -                                ANON_LOCK_EXIT(&amp->a_rwlock);
7057      -                                continue;
7058      -                        }
7059      -                        ap = anon_get_ptr(amp->ahp, anon_index + page);
7060      -                        if (ap != NULL) {
7061      -                                swap_xlate(ap, &vp, &off);
7062      -                        } else {
7063      -                                vp = svd->vp;
7064      -                                off = svd->offset + ptob(page);
7065      -                        }
7066      -                        anon_array_exit(&cookie);
7067      -                        ANON_LOCK_EXIT(&amp->a_rwlock);
7068      -                } else {
7069      -                        vp = svd->vp;
7070      -                        off = svd->offset + ptob(page);
7071      -                }
7072      -                if (vp == NULL) {               /* untouched zfod page */
7073      -                        ASSERT(ap == NULL);
7074      -                        continue;
7075      -                }
7076      -
7077      -                pp = page_lookup_nowait(vp, off, SE_SHARED);
7078      -                if (pp == NULL)
7079      -                        continue;
7080      -
7081      -
7082      -                /*
7083      -                 * Examine the page to see whether it can be tossed out,
7084      -                 * keeping track of how many we've found.
7085      -                 */
7086      -                if (!page_tryupgrade(pp)) {
7087      -                        /*
7088      -                         * If the page has an i/o lock and no mappings,
7089      -                         * it's very likely that the page is being
7090      -                         * written out as a result of klustering.
7091      -                         * Assume this is so and take credit for it here.
7092      -                         */
7093      -                        if (!page_io_trylock(pp)) {
7094      -                                if (!hat_page_is_mapped(pp))
7095      -                                        pgcnt++;
7096      -                        } else {
7097      -                                page_io_unlock(pp);
7098      -                        }
7099      -                        page_unlock(pp);
7100      -                        continue;
7101      -                }
7102      -                ASSERT(!page_iolock_assert(pp));
7103      -
7104      -
7105      -                /*
7106      -                 * Skip if page is locked or has mappings.
7107      -                 * We don't need the page_struct_lock to look at lckcnt
7108      -                 * and cowcnt because the page is exclusive locked.
7109      -                 */
7110      -                if (pp->p_lckcnt != 0 || pp->p_cowcnt != 0 ||
7111      -                    hat_page_is_mapped(pp)) {
7112      -                        page_unlock(pp);
7113      -                        continue;
7114      -                }
7115      -
7116      -                /*
7117      -                 * dispose skips large pages so try to demote first.
7118      -                 */
7119      -                if (pp->p_szc != 0 && !page_try_demote_pages(pp)) {
7120      -                        page_unlock(pp);
7121      -                        /*
7122      -                         * XXX should skip the remaining page_t's of this
7123      -                         * large page.
7124      -                         */
7125      -                        continue;
7126      -                }
7127      -
7128      -                ASSERT(pp->p_szc == 0);
7129      -
7130      -                /*
7131      -                 * No longer mapped -- we can toss it out.  How
7132      -                 * we do so depends on whether or not it's dirty.
7133      -                 */
7134      -                if (hat_ismod(pp) && pp->p_vnode) {
7135      -                        /*
7136      -                         * We must clean the page before it can be
7137      -                         * freed.  Setting B_FREE will cause pvn_done
7138      -                         * to free the page when the i/o completes.
7139      -                         * XXX: This also causes it to be accounted
7140      -                         *      as a pageout instead of a swap: need
7141      -                         *      B_SWAPOUT bit to use instead of B_FREE.
7142      -                         *
7143      -                         * Hold the vnode before releasing the page lock
7144      -                         * to prevent it from being freed and re-used by
7145      -                         * some other thread.
7146      -                         */
7147      -                        VN_HOLD(vp);
7148      -                        page_unlock(pp);
7149      -
7150      -                        /*
7151      -                         * Queue all i/o requests for the pageout thread
7152      -                         * to avoid saturating the pageout devices.
7153      -                         */
7154      -                        if (!queue_io_request(vp, off))
7155      -                                VN_RELE(vp);
7156      -                } else {
7157      -                        /*
7158      -                         * The page was clean, free it.
7159      -                         *
7160      -                         * XXX: Can we ever encounter modified pages
7161      -                         *      with no associated vnode here?
7162      -                         */
7163      -                        ASSERT(pp->p_vnode != NULL);
7164      -                        /*LINTED: constant in conditional context*/
7165      -                        VN_DISPOSE(pp, B_FREE, 0, kcred);
7166      -                }
7167      -
7168      -                /*
7169      -                 * Credit now even if i/o is in progress.
7170      -                 */
7171      -                pgcnt++;
7172      -        }
7173      -        SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7174      -
7175      -        /*
7176      -         * Wakeup pageout to initiate i/o on all queued requests.
7177      -         */
7178      -        cv_signal_pageout();
7179      -        return (ptob(pgcnt));
7180      -}
7181      -
7182      -/*
7183 6998   * Synchronize primary storage cache with real object in virtual memory.
7184 6999   *
7185 7000   * XXX - Anonymous pages should not be sync'ed out at all.
7186 7001   */
7187 7002  static int
7188 7003  segvn_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags)
7189 7004  {
7190 7005          struct segvn_data *svd = (struct segvn_data *)seg->s_data;
7191 7006          struct vpage *vpp;
7192 7007          page_t *pp;
↓ open down ↓ 2939 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX