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.

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);
↓ open down ↓ 4810 lines elided ↑ open up ↑
4918 4907  segvn_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len,
4919 4908      enum fault_type type, enum seg_rw rw)
4920 4909  {
4921 4910          struct segvn_data *svd = (struct segvn_data *)seg->s_data;
4922 4911          page_t **plp, **ppp, *pp;
4923 4912          u_offset_t off;
4924 4913          caddr_t a;
4925 4914          struct vpage *vpage;
4926 4915          uint_t vpprot, prot;
4927 4916          int err;
4928      -        page_t *pl[PVN_GETPAGE_NUM + 1];
     4917 +        page_t *pl[FAULT_TMP_PAGES_NUM + 1];
4929 4918          size_t plsz, pl_alloc_sz;
4930 4919          size_t page;
4931 4920          ulong_t anon_index;
4932 4921          struct anon_map *amp;
4933 4922          int dogetpage = 0;
4934 4923          caddr_t lpgaddr, lpgeaddr;
4935 4924          size_t pgsz;
4936 4925          anon_sync_obj_t cookie;
4937 4926          int brkcow = BREAK_COW_SHARE(rw, type, svd->type);
4938 4927  
↓ open down ↓ 418 lines elided ↑ open up ↑
5357 5346                          else
5358 5347                                  dogetpage = non_anon(amp->ahp, anon_index,
5359 5348                                      &vp_off, &vp_len);
5360 5349                          ANON_LOCK_EXIT(&amp->a_rwlock);
5361 5350                  }
5362 5351  
5363 5352                  if (dogetpage) {
5364 5353                          enum seg_rw arw;
5365 5354                          struct as *as = seg->s_as;
5366 5355  
5367      -                        if (len > ptob((sizeof (pl) / sizeof (pl[0])) - 1)) {
     5356 +                        if (len > FAULT_TMP_PAGES_SZ) {
5368 5357                                  /*
5369 5358                                   * Page list won't fit in local array,
5370 5359                                   * allocate one of the needed size.
5371 5360                                   */
5372 5361                                  pl_alloc_sz =
5373 5362                                      (btop(len) + 1) * sizeof (page_t *);
5374 5363                                  plp = kmem_alloc(pl_alloc_sz, KM_SLEEP);
5375 5364                                  plp[0] = NULL;
5376 5365                                  plsz = len;
5377 5366                          } else if (rw == S_WRITE && svd->type == MAP_PRIVATE ||
↓ open down ↓ 7 lines elided ↑ open up ↑
5385 5374                                   * (a) this is a COW fault, or
5386 5375                                   * (b) this is a software fault, or
5387 5376                                   * (c) next page is already mapped.
5388 5377                                   */
5389 5378                                  plsz = len;
5390 5379                          } else {
5391 5380                                  /*
5392 5381                                   * Ask VOP_GETPAGE to return adjacent pages
5393 5382                                   * within the segment.
5394 5383                                   */
5395      -                                plsz = MIN((size_t)PVN_GETPAGE_SZ, (size_t)
     5384 +                                plsz = MIN((size_t)FAULT_TMP_PAGES_SZ, (size_t)
5396 5385                                      ((seg->s_base + seg->s_size) - addr));
5397 5386                                  ASSERT((addr + plsz) <=
5398 5387                                      (seg->s_base + seg->s_size));
5399 5388                          }
5400 5389  
5401 5390                          /*
5402 5391                           * Need to get some non-anonymous pages.
5403 5392                           * We need to make only one call to GETPAGE to do
5404 5393                           * this to prevent certain deadlocking conditions
5405 5394                           * when we are doing locking.  In this case
↓ open down ↓ 4694 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX