Print this page
PVN_GETPAGE_{SZ,NUM} are misnamed and unnecessarily complicated
There is really no reason to not allow 8 pages all the time.  With the
current logic, we get the following:
Assuming 4kB pages (x86):
    _SZ  = ptob(8) /* 32kB */
    _NUM = 8
Assuming 8kB pages (sparc):
    _SZ  = ptob(8) /* 64kB */
    _NUM = 8
We'd have to deal with 16kB base pages in order for the _NUM #define to not
be 8 (it'd be 4 in that case).  So, in the spirit of simplicity, let's just
always grab 8 pages as there are no interesting systems with 16kB+ base pages.
Finally, the defines are poorly named.
const-ify make segment ops structures
There is no reason to keep the segment ops structures writable.
use NULL capable segop as a shorthand for no-capabilities
Instead of forcing every segment driver to implement a dummy "return 0"
function, handle NULL capable segop function pointer as "no copabilities
supported" shorthand.
patch lower-case-segops
use C99 initializers in segment ops structures
remove whole-process swapping
Long before Unix supported paging, it used process swapping to reclaim
memory.  The code is there and in theory it runs when we get *extremely* low
on memory.  In practice, it never runs since the definition of low-on-memory
is antiquated. (XXX: define what antiquated means)
You can check the number of swapout/swapin events with kstats:
$ kstat -p ::vm:swapin ::vm:swapout
remove xhat
The xhat infrastructure was added to support hardware such as the zulu
graphics card - hardware which had on-board MMUs.  The VM used the xhat code
to keep the CPU's and Zulu's page tables in-sync.  Since the only xhat user
was zulu (which is gone), we can safely remove it simplifying the whole VM
subsystem.
Assorted notes:
- AS_BUSY flag was used solely by xhat

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 ↓ 70 lines elided ↑ open up ↑
  71   71  #include <vm/page.h>
  72   72  #include <vm/vpage.h>
  73   73  #include <sys/proc.h>
  74   74  #include <sys/task.h>
  75   75  #include <sys/project.h>
  76   76  #include <sys/zone.h>
  77   77  #include <sys/shm_impl.h>
  78   78  
  79   79  /*
  80   80   * segvn_fault needs a temporary page list array.  To avoid calling kmem all
  81      - * the time, it creates a small (PVN_GETPAGE_NUM entry) array and uses it if
  82      - * it can.  In the rare case when this page list is not large enough, it
  83      - * goes and gets a large enough array from kmem.
  84      - *
  85      - * This small page list array covers either 8 pages or 64kB worth of pages -
  86      - * whichever is smaller.
       81 + * the time, it creates a small (FAULT_TMP_PAGES_NUM entry) array and uses
       82 + * it if it can.  In the rare case when this page list is not large enough,
       83 + * it goes and gets a large enough array from kmem.
  87   84   */
  88      -#define PVN_MAX_GETPAGE_SZ      0x10000
  89      -#define PVN_MAX_GETPAGE_NUM     0x8
  90      -
  91      -#if PVN_MAX_GETPAGE_SZ > PVN_MAX_GETPAGE_NUM * PAGESIZE
  92      -#define PVN_GETPAGE_SZ  ptob(PVN_MAX_GETPAGE_NUM)
  93      -#define PVN_GETPAGE_NUM PVN_MAX_GETPAGE_NUM
  94      -#else
  95      -#define PVN_GETPAGE_SZ  PVN_MAX_GETPAGE_SZ
  96      -#define PVN_GETPAGE_NUM btop(PVN_MAX_GETPAGE_SZ)
  97      -#endif
       85 +#define FAULT_TMP_PAGES_NUM     0x8
       86 +#define FAULT_TMP_PAGES_SZ      ptob(FAULT_TMP_PAGES_NUM)
  98   87  
  99   88  /*
 100   89   * Private seg op routines.
 101   90   */
 102   91  static int      segvn_dup(struct seg *seg, struct seg *newseg);
 103   92  static int      segvn_unmap(struct seg *seg, caddr_t addr, size_t len);
 104   93  static void     segvn_free(struct seg *seg);
 105   94  static faultcode_t segvn_fault(struct hat *hat, struct seg *seg,
 106   95                      caddr_t addr, size_t len, enum fault_type type,
 107   96                      enum seg_rw rw);
 108   97  static faultcode_t segvn_faulta(struct seg *seg, caddr_t addr);
 109   98  static int      segvn_setprot(struct seg *seg, caddr_t addr,
 110   99                      size_t len, uint_t prot);
 111  100  static int      segvn_checkprot(struct seg *seg, caddr_t addr,
 112  101                      size_t len, uint_t prot);
 113  102  static int      segvn_kluster(struct seg *seg, caddr_t addr, ssize_t delta);
 114      -static size_t   segvn_swapout(struct seg *seg);
 115  103  static int      segvn_sync(struct seg *seg, caddr_t addr, size_t len,
 116  104                      int attr, uint_t flags);
 117  105  static size_t   segvn_incore(struct seg *seg, caddr_t addr, size_t len,
 118  106                      char *vec);
 119  107  static int      segvn_lockop(struct seg *seg, caddr_t addr, size_t len,
 120  108                      int attr, int op, ulong_t *lockmap, size_t pos);
 121  109  static int      segvn_getprot(struct seg *seg, caddr_t addr, size_t len,
 122  110                      uint_t *protv);
 123  111  static u_offset_t       segvn_getoffset(struct seg *seg, caddr_t addr);
 124  112  static int      segvn_gettype(struct seg *seg, caddr_t addr);
↓ open down ↓ 2 lines elided ↑ open up ↑
 127  115  static int      segvn_advise(struct seg *seg, caddr_t addr, size_t len,
 128  116                      uint_t behav);
 129  117  static void     segvn_dump(struct seg *seg);
 130  118  static int      segvn_pagelock(struct seg *seg, caddr_t addr, size_t len,
 131  119                      struct page ***ppp, enum lock_type type, enum seg_rw rw);
 132  120  static int      segvn_setpagesize(struct seg *seg, caddr_t addr, size_t len,
 133  121                      uint_t szc);
 134  122  static int      segvn_getmemid(struct seg *seg, caddr_t addr,
 135  123                      memid_t *memidp);
 136  124  static lgrp_mem_policy_info_t   *segvn_getpolicy(struct seg *, caddr_t);
 137      -static int      segvn_capable(struct seg *seg, segcapability_t capable);
 138  125  static int      segvn_inherit(struct seg *, caddr_t, size_t, uint_t);
 139  126  
 140      -struct  seg_ops segvn_ops = {
 141      -        segvn_dup,
 142      -        segvn_unmap,
 143      -        segvn_free,
 144      -        segvn_fault,
 145      -        segvn_faulta,
 146      -        segvn_setprot,
 147      -        segvn_checkprot,
 148      -        segvn_kluster,
 149      -        segvn_swapout,
 150      -        segvn_sync,
 151      -        segvn_incore,
 152      -        segvn_lockop,
 153      -        segvn_getprot,
 154      -        segvn_getoffset,
 155      -        segvn_gettype,
 156      -        segvn_getvp,
 157      -        segvn_advise,
 158      -        segvn_dump,
 159      -        segvn_pagelock,
 160      -        segvn_setpagesize,
 161      -        segvn_getmemid,
 162      -        segvn_getpolicy,
 163      -        segvn_capable,
 164      -        segvn_inherit
      127 +const struct seg_ops segvn_ops = {
      128 +        .dup            = segvn_dup,
      129 +        .unmap          = segvn_unmap,
      130 +        .free           = segvn_free,
      131 +        .fault          = segvn_fault,
      132 +        .faulta         = segvn_faulta,
      133 +        .setprot        = segvn_setprot,
      134 +        .checkprot      = segvn_checkprot,
      135 +        .kluster        = segvn_kluster,
      136 +        .sync           = segvn_sync,
      137 +        .incore         = segvn_incore,
      138 +        .lockop         = segvn_lockop,
      139 +        .getprot        = segvn_getprot,
      140 +        .getoffset      = segvn_getoffset,
      141 +        .gettype        = segvn_gettype,
      142 +        .getvp          = segvn_getvp,
      143 +        .advise         = segvn_advise,
      144 +        .dump           = segvn_dump,
      145 +        .pagelock       = segvn_pagelock,
      146 +        .setpagesize    = segvn_setpagesize,
      147 +        .getmemid       = segvn_getmemid,
      148 +        .getpolicy      = segvn_getpolicy,
      149 +        .inherit        = segvn_inherit,
 165  150  };
 166  151  
 167  152  /*
 168  153   * Common zfod structures, provided as a shorthand for others to use.
 169  154   */
 170  155  static segvn_crargs_t zfod_segvn_crargs =
 171  156          SEGVN_ZFOD_ARGS(PROT_ZFOD, PROT_ALL);
 172  157  static segvn_crargs_t kzfod_segvn_crargs =
 173  158          SEGVN_ZFOD_ARGS(PROT_ZFOD & ~PROT_USER,
 174  159          PROT_ALL & ~PROT_USER);
↓ open down ↓ 3674 lines elided ↑ open up ↑
3849 3834          int ierr;
3850 3835          int vop_size_err = 0;
3851 3836          uint_t protchk, prot, vpprot;
3852 3837          ulong_t i;
3853 3838          int hat_flag = (type == F_SOFTLOCK) ? HAT_LOAD_LOCK : HAT_LOAD;
3854 3839          anon_sync_obj_t an_cookie;
3855 3840          enum seg_rw arw;
3856 3841          int alloc_failed = 0;
3857 3842          int adjszc_chk;
3858 3843          struct vattr va;
3859      -        int xhat = 0;
3860 3844          page_t *pplist;
3861 3845          pfn_t pfn;
3862 3846          int physcontig;
3863 3847          int upgrdfail;
3864 3848          int segvn_anypgsz_vnode = 0; /* for now map vnode with 2 page sizes */
3865 3849          int tron = (svd->tr_state == SEGVN_TR_ON);
3866 3850  
3867 3851          ASSERT(szc != 0);
3868 3852          ASSERT(vp != NULL);
3869 3853          ASSERT(brkcow == 0 || amp != NULL);
↓ open down ↓ 29 lines elided ↑ open up ↑
3899 3883                  case S_OTHER:
3900 3884                  default:
3901 3885                          protchk = PROT_READ | PROT_WRITE | PROT_EXEC;
3902 3886                          break;
3903 3887                  }
3904 3888          } else {
3905 3889                  prot = svd->prot;
3906 3890                  /* caller has already done segment level protection check. */
3907 3891          }
3908 3892  
3909      -        if (seg->s_as->a_hat != hat) {
3910      -                xhat = 1;
3911      -        }
3912      -
3913 3893          if (rw == S_WRITE && segtype == MAP_PRIVATE) {
3914 3894                  SEGVN_VMSTAT_FLTVNPAGES(2);
3915 3895                  arw = S_READ;
3916 3896          } else {
3917 3897                  arw = rw;
3918 3898          }
3919 3899  
3920 3900          ppa = kmem_alloc(ppasize, KM_SLEEP);
3921 3901  
3922 3902          VM_STAT_COND_ADD(amp != NULL, segvnvmstats.fltvnpages[3]);
↓ open down ↓ 335 lines elided ↑ open up ↑
4258 4238                                   */
4259 4239                                  if (pplist != NULL) {
4260 4240                                          page_free_replacement_page(pplist);
4261 4241                                          page_create_putback(pages);
4262 4242                                  }
4263 4243                                  if (PP_ISMIGRATE(ppa[0])) {
4264 4244                                          page_migrate(seg, a, ppa, pages);
4265 4245                                  }
4266 4246                                  SEGVN_UPDATE_MODBITS(ppa, pages, rw,
4267 4247                                      prot, vpprot);
4268      -                                if (!xhat) {
4269      -                                        hat_memload_array_region(hat, a, pgsz,
4270      -                                            ppa, prot & vpprot, hat_flag,
4271      -                                            svd->rcookie);
4272      -                                } else {
4273      -                                        /*
4274      -                                         * avoid large xhat mappings to FS
4275      -                                         * pages so that hat_page_demote()
4276      -                                         * doesn't need to check for xhat
4277      -                                         * large mappings.
4278      -                                         * Don't use regions with xhats.
4279      -                                         */
4280      -                                        for (i = 0; i < pages; i++) {
4281      -                                                hat_memload(hat,
4282      -                                                    a + (i << PAGESHIFT),
4283      -                                                    ppa[i], prot & vpprot,
4284      -                                                    hat_flag);
4285      -                                        }
4286      -                                }
     4248 +                                hat_memload_array_region(hat, a, pgsz,
     4249 +                                    ppa, prot & vpprot, hat_flag,
     4250 +                                    svd->rcookie);
4287 4251  
4288 4252                                  if (!(hat_flag & HAT_LOAD_LOCK)) {
4289 4253                                          for (i = 0; i < pages; i++) {
4290 4254                                                  page_unlock(ppa[i]);
4291 4255                                          }
4292 4256                                  }
4293 4257                                  if (amp != NULL) {
4294 4258                                          anon_array_exit(&an_cookie);
4295 4259                                          ANON_LOCK_EXIT(&amp->a_rwlock);
4296 4260                                  }
↓ open down ↓ 33 lines elided ↑ open up ↑
4330 4294                                          pszc = pszc1;
4331 4295                                          ierr = -2;
4332 4296                                          break;
4333 4297                                  }
4334 4298                          }
4335 4299  
4336 4300                          /*
4337 4301                           * check if we should use smallest mapping size.
4338 4302                           */
4339 4303                          upgrdfail = 0;
4340      -                        if (szc == 0 || xhat ||
     4304 +                        if (szc == 0 ||
4341 4305                              (pszc >= szc &&
4342 4306                              !IS_P2ALIGNED(pfn, pages)) ||
4343 4307                              (pszc < szc &&
4344 4308                              !segvn_full_szcpages(ppa, szc, &upgrdfail,
4345 4309                              &pszc))) {
4346 4310  
4347 4311                                  if (upgrdfail && type != F_SOFTLOCK) {
4348 4312                                          /*
4349 4313                                           * segvn_full_szcpages failed to lock
4350 4314                                           * all pages EXCL. Size down.
↓ open down ↓ 11 lines elided ↑ open up ↑
4362 4326                                          for (i = 0; i < pages; i++) {
4363 4327                                                  page_unlock(ppa[i]);
4364 4328                                          }
4365 4329                                          if (amp != NULL) {
4366 4330                                                  anon_array_exit(&an_cookie);
4367 4331                                                  ANON_LOCK_EXIT(&amp->a_rwlock);
4368 4332                                          }
4369 4333                                          ierr = -1;
4370 4334                                          break;
4371 4335                                  }
4372      -                                if (szc != 0 && !xhat && !upgrdfail) {
     4336 +                                if (szc != 0 && !upgrdfail) {
4373 4337                                          segvn_faultvnmpss_align_err5++;
4374 4338                                  }
4375 4339                                  SEGVN_VMSTAT_FLTVNPAGES(34);
4376 4340                                  if (pplist != NULL) {
4377 4341                                          page_free_replacement_page(pplist);
4378 4342                                          page_create_putback(pages);
4379 4343                                  }
4380 4344                                  SEGVN_UPDATE_MODBITS(ppa, pages, rw,
4381 4345                                      prot, vpprot);
4382 4346                                  if (upgrdfail && segvn_anypgsz_vnode) {
↓ open down ↓ 560 lines elided ↑ open up ↑
4943 4907  segvn_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len,
4944 4908      enum fault_type type, enum seg_rw rw)
4945 4909  {
4946 4910          struct segvn_data *svd = (struct segvn_data *)seg->s_data;
4947 4911          page_t **plp, **ppp, *pp;
4948 4912          u_offset_t off;
4949 4913          caddr_t a;
4950 4914          struct vpage *vpage;
4951 4915          uint_t vpprot, prot;
4952 4916          int err;
4953      -        page_t *pl[PVN_GETPAGE_NUM + 1];
     4917 +        page_t *pl[FAULT_TMP_PAGES_NUM + 1];
4954 4918          size_t plsz, pl_alloc_sz;
4955 4919          size_t page;
4956 4920          ulong_t anon_index;
4957 4921          struct anon_map *amp;
4958 4922          int dogetpage = 0;
4959 4923          caddr_t lpgaddr, lpgeaddr;
4960 4924          size_t pgsz;
4961 4925          anon_sync_obj_t cookie;
4962 4926          int brkcow = BREAK_COW_SHARE(rw, type, svd->type);
4963 4927  
↓ open down ↓ 418 lines elided ↑ open up ↑
5382 5346                          else
5383 5347                                  dogetpage = non_anon(amp->ahp, anon_index,
5384 5348                                      &vp_off, &vp_len);
5385 5349                          ANON_LOCK_EXIT(&amp->a_rwlock);
5386 5350                  }
5387 5351  
5388 5352                  if (dogetpage) {
5389 5353                          enum seg_rw arw;
5390 5354                          struct as *as = seg->s_as;
5391 5355  
5392      -                        if (len > ptob((sizeof (pl) / sizeof (pl[0])) - 1)) {
     5356 +                        if (len > FAULT_TMP_PAGES_SZ) {
5393 5357                                  /*
5394 5358                                   * Page list won't fit in local array,
5395 5359                                   * allocate one of the needed size.
5396 5360                                   */
5397 5361                                  pl_alloc_sz =
5398 5362                                      (btop(len) + 1) * sizeof (page_t *);
5399 5363                                  plp = kmem_alloc(pl_alloc_sz, KM_SLEEP);
5400 5364                                  plp[0] = NULL;
5401 5365                                  plsz = len;
5402 5366                          } else if (rw == S_WRITE && svd->type == MAP_PRIVATE ||
↓ open down ↓ 7 lines elided ↑ open up ↑
5410 5374                                   * (a) this is a COW fault, or
5411 5375                                   * (b) this is a software fault, or
5412 5376                                   * (c) next page is already mapped.
5413 5377                                   */
5414 5378                                  plsz = len;
5415 5379                          } else {
5416 5380                                  /*
5417 5381                                   * Ask VOP_GETPAGE to return adjacent pages
5418 5382                                   * within the segment.
5419 5383                                   */
5420      -                                plsz = MIN((size_t)PVN_GETPAGE_SZ, (size_t)
     5384 +                                plsz = MIN((size_t)FAULT_TMP_PAGES_SZ, (size_t)
5421 5385                                      ((seg->s_base + seg->s_size) - addr));
5422 5386                                  ASSERT((addr + plsz) <=
5423 5387                                      (seg->s_base + seg->s_size));
5424 5388                          }
5425 5389  
5426 5390                          /*
5427 5391                           * Need to get some non-anonymous pages.
5428 5392                           * We need to make only one call to GETPAGE to do
5429 5393                           * this to prevent certain deadlocking conditions
5430 5394                           * when we are doing locking.  In this case
↓ open down ↓ 646 lines elided ↑ open up ↑
6077 6041                   */
6078 6042                  hat_chgattr(seg->s_as->a_hat, addr, len, prot);
6079 6043          }
6080 6044  
6081 6045          SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
6082 6046  
6083 6047          return (0);
6084 6048  }
6085 6049  
6086 6050  /*
6087      - * segvn_setpagesize is called via SEGOP_SETPAGESIZE from as_setpagesize,
     6051 + * segvn_setpagesize is called via segop_setpagesize from as_setpagesize,
6088 6052   * to determine if the seg is capable of mapping the requested szc.
6089 6053   */
6090 6054  static int
6091 6055  segvn_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc)
6092 6056  {
6093 6057          struct segvn_data *svd = (struct segvn_data *)seg->s_data;
6094 6058          struct segvn_data *nsvd;
6095 6059          struct anon_map *amp = svd->amp;
6096 6060          struct seg *nseg;
6097 6061          caddr_t eaddr = addr + len, a;
↓ open down ↓ 967 lines elided ↑ open up ↑
7065 7029          swap_xlate(ap, &vp1, &off1);
7066 7030          swap_xlate(oap, &vp2, &off2);
7067 7031  
7068 7032  
7069 7033          if (!VOP_CMP(vp1, vp2, NULL) || off1 - off2 != delta)
7070 7034                  return (-1);
7071 7035          return (0);
7072 7036  }
7073 7037  
7074 7038  /*
7075      - * Swap the pages of seg out to secondary storage, returning the
7076      - * number of bytes of storage freed.
7077      - *
7078      - * The basic idea is first to unload all translations and then to call
7079      - * VOP_PUTPAGE() for all newly-unmapped pages, to push them out to the
7080      - * swap device.  Pages to which other segments have mappings will remain
7081      - * mapped and won't be swapped.  Our caller (as_swapout) has already
7082      - * performed the unloading step.
7083      - *
7084      - * The value returned is intended to correlate well with the process's
7085      - * memory requirements.  However, there are some caveats:
7086      - * 1)   When given a shared segment as argument, this routine will
7087      - *      only succeed in swapping out pages for the last sharer of the
7088      - *      segment.  (Previous callers will only have decremented mapping
7089      - *      reference counts.)
7090      - * 2)   We assume that the hat layer maintains a large enough translation
7091      - *      cache to capture process reference patterns.
7092      - */
7093      -static size_t
7094      -segvn_swapout(struct seg *seg)
7095      -{
7096      -        struct segvn_data *svd = (struct segvn_data *)seg->s_data;
7097      -        struct anon_map *amp;
7098      -        pgcnt_t pgcnt = 0;
7099      -        pgcnt_t npages;
7100      -        pgcnt_t page;
7101      -        ulong_t anon_index;
7102      -
7103      -        ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
7104      -
7105      -        SEGVN_LOCK_ENTER(seg->s_as, &svd->lock, RW_READER);
7106      -        /*
7107      -         * Find pages unmapped by our caller and force them
7108      -         * out to the virtual swap device.
7109      -         */
7110      -        if ((amp = svd->amp) != NULL)
7111      -                anon_index = svd->anon_index;
7112      -        npages = seg->s_size >> PAGESHIFT;
7113      -        for (page = 0; page < npages; page++) {
7114      -                page_t *pp;
7115      -                struct anon *ap;
7116      -                struct vnode *vp;
7117      -                u_offset_t off;
7118      -                anon_sync_obj_t cookie;
7119      -
7120      -                /*
7121      -                 * Obtain <vp, off> pair for the page, then look it up.
7122      -                 *
7123      -                 * Note that this code is willing to consider regular
7124      -                 * pages as well as anon pages.  Is this appropriate here?
7125      -                 */
7126      -                ap = NULL;
7127      -                if (amp != NULL) {
7128      -                        ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
7129      -                        if (anon_array_try_enter(amp, anon_index + page,
7130      -                            &cookie)) {
7131      -                                ANON_LOCK_EXIT(&amp->a_rwlock);
7132      -                                continue;
7133      -                        }
7134      -                        ap = anon_get_ptr(amp->ahp, anon_index + page);
7135      -                        if (ap != NULL) {
7136      -                                swap_xlate(ap, &vp, &off);
7137      -                        } else {
7138      -                                vp = svd->vp;
7139      -                                off = svd->offset + ptob(page);
7140      -                        }
7141      -                        anon_array_exit(&cookie);
7142      -                        ANON_LOCK_EXIT(&amp->a_rwlock);
7143      -                } else {
7144      -                        vp = svd->vp;
7145      -                        off = svd->offset + ptob(page);
7146      -                }
7147      -                if (vp == NULL) {               /* untouched zfod page */
7148      -                        ASSERT(ap == NULL);
7149      -                        continue;
7150      -                }
7151      -
7152      -                pp = page_lookup_nowait(vp, off, SE_SHARED);
7153      -                if (pp == NULL)
7154      -                        continue;
7155      -
7156      -
7157      -                /*
7158      -                 * Examine the page to see whether it can be tossed out,
7159      -                 * keeping track of how many we've found.
7160      -                 */
7161      -                if (!page_tryupgrade(pp)) {
7162      -                        /*
7163      -                         * If the page has an i/o lock and no mappings,
7164      -                         * it's very likely that the page is being
7165      -                         * written out as a result of klustering.
7166      -                         * Assume this is so and take credit for it here.
7167      -                         */
7168      -                        if (!page_io_trylock(pp)) {
7169      -                                if (!hat_page_is_mapped(pp))
7170      -                                        pgcnt++;
7171      -                        } else {
7172      -                                page_io_unlock(pp);
7173      -                        }
7174      -                        page_unlock(pp);
7175      -                        continue;
7176      -                }
7177      -                ASSERT(!page_iolock_assert(pp));
7178      -
7179      -
7180      -                /*
7181      -                 * Skip if page is locked or has mappings.
7182      -                 * We don't need the page_struct_lock to look at lckcnt
7183      -                 * and cowcnt because the page is exclusive locked.
7184      -                 */
7185      -                if (pp->p_lckcnt != 0 || pp->p_cowcnt != 0 ||
7186      -                    hat_page_is_mapped(pp)) {
7187      -                        page_unlock(pp);
7188      -                        continue;
7189      -                }
7190      -
7191      -                /*
7192      -                 * dispose skips large pages so try to demote first.
7193      -                 */
7194      -                if (pp->p_szc != 0 && !page_try_demote_pages(pp)) {
7195      -                        page_unlock(pp);
7196      -                        /*
7197      -                         * XXX should skip the remaining page_t's of this
7198      -                         * large page.
7199      -                         */
7200      -                        continue;
7201      -                }
7202      -
7203      -                ASSERT(pp->p_szc == 0);
7204      -
7205      -                /*
7206      -                 * No longer mapped -- we can toss it out.  How
7207      -                 * we do so depends on whether or not it's dirty.
7208      -                 */
7209      -                if (hat_ismod(pp) && pp->p_vnode) {
7210      -                        /*
7211      -                         * We must clean the page before it can be
7212      -                         * freed.  Setting B_FREE will cause pvn_done
7213      -                         * to free the page when the i/o completes.
7214      -                         * XXX: This also causes it to be accounted
7215      -                         *      as a pageout instead of a swap: need
7216      -                         *      B_SWAPOUT bit to use instead of B_FREE.
7217      -                         *
7218      -                         * Hold the vnode before releasing the page lock
7219      -                         * to prevent it from being freed and re-used by
7220      -                         * some other thread.
7221      -                         */
7222      -                        VN_HOLD(vp);
7223      -                        page_unlock(pp);
7224      -
7225      -                        /*
7226      -                         * Queue all i/o requests for the pageout thread
7227      -                         * to avoid saturating the pageout devices.
7228      -                         */
7229      -                        if (!queue_io_request(vp, off))
7230      -                                VN_RELE(vp);
7231      -                } else {
7232      -                        /*
7233      -                         * The page was clean, free it.
7234      -                         *
7235      -                         * XXX: Can we ever encounter modified pages
7236      -                         *      with no associated vnode here?
7237      -                         */
7238      -                        ASSERT(pp->p_vnode != NULL);
7239      -                        /*LINTED: constant in conditional context*/
7240      -                        VN_DISPOSE(pp, B_FREE, 0, kcred);
7241      -                }
7242      -
7243      -                /*
7244      -                 * Credit now even if i/o is in progress.
7245      -                 */
7246      -                pgcnt++;
7247      -        }
7248      -        SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7249      -
7250      -        /*
7251      -         * Wakeup pageout to initiate i/o on all queued requests.
7252      -         */
7253      -        cv_signal_pageout();
7254      -        return (ptob(pgcnt));
7255      -}
7256      -
7257      -/*
7258 7039   * Synchronize primary storage cache with real object in virtual memory.
7259 7040   *
7260 7041   * XXX - Anonymous pages should not be sync'ed out at all.
7261 7042   */
7262 7043  static int
7263 7044  segvn_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags)
7264 7045  {
7265 7046          struct segvn_data *svd = (struct segvn_data *)seg->s_data;
7266 7047          struct vpage *vpp;
7267 7048          page_t *pp;
↓ open down ↓ 2414 lines elided ↑ open up ↑
9682 9463                  }
9683 9464          } else {
9684 9465                  amp = svn_data->amp;
9685 9466                  anon_index = svn_data->anon_index + seg_page(seg, addr);
9686 9467                  vp = svn_data->vp;
9687 9468                  vn_off = svn_data->offset + (uintptr_t)(addr - seg->s_base);
9688 9469                  policy_info = lgrp_shm_policy_get(amp, anon_index, vp, vn_off);
9689 9470          }
9690 9471  
9691 9472          return (policy_info);
9692      -}
9693      -
9694      -/*ARGSUSED*/
9695      -static int
9696      -segvn_capable(struct seg *seg, segcapability_t capability)
9697      -{
9698      -        return (0);
9699 9473  }
9700 9474  
9701 9475  /*
9702 9476   * Bind text vnode segment to an amp. If we bind successfully mappings will be
9703 9477   * established to per vnode mapping per lgroup amp pages instead of to vnode
9704 9478   * pages. There's one amp per vnode text mapping per lgroup. Many processes
9705 9479   * may share the same text replication amp. If a suitable amp doesn't already
9706 9480   * exist in svntr hash table create a new one.  We may fail to bind to amp if
9707 9481   * segment is not eligible for text replication.  Code below first checks for
9708 9482   * these conditions. If binding is successful segment tr_state is set to on
↓ open down ↓ 606 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX