Print this page
5384 pvn_getpages may assert in valid scenarios

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/vm/vm_pvn.c
          +++ new/usr/src/uts/common/vm/vm_pvn.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1986, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  23   24   */
  24   25  
  25   26  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  26   27  /*        All Rights Reserved   */
  27   28  
  28   29  /*
  29   30   * University Copyright- Copyright (c) 1982, 1986, 1988
  30   31   * The Regents of the University of California
  31   32   * All Rights Reserved
  32   33   *
↓ open down ↓ 1050 lines elided ↑ open up ↑
1083 1084          if ((zbytes + (vplen & MAXBOFFSET)) > MAXBSIZE)
1084 1085                  panic("pvn_vptrunc zbytes");
1085 1086          addr = segmap_getmapflt(segkmap, vp, vplen,
1086 1087              MAX(zbytes, PAGESIZE - (vplen & PAGEOFFSET)), 1, S_WRITE);
1087 1088          (void) kzero(addr + (vplen & MAXBOFFSET),
1088 1089              MAX(zbytes, PAGESIZE - (vplen & PAGEOFFSET)));
1089 1090          (void) segmap_release(segkmap, addr, SM_WRITE | SM_ASYNC);
1090 1091  }
1091 1092  
1092 1093  /*
1093      - * Handles common work of the VOP_GETPAGE routines when more than
1094      - * one page must be returned by calling a file system specific operation
1095      - * to do most of the work.  Must be called with the vp already locked
1096      - * by the VOP_GETPAGE routine.
     1094 + * Handles common work of the VOP_GETPAGE routines by iterating page by page
     1095 + * calling the getpage helper for each.
1097 1096   */
1098 1097  int
1099 1098  pvn_getpages(
1100 1099          int (*getpage)(vnode_t *, u_offset_t, size_t, uint_t *, page_t *[],
1101 1100                  size_t, struct seg *, caddr_t, enum seg_rw, cred_t *),
1102 1101          struct vnode *vp,
1103 1102          u_offset_t off,
1104 1103          size_t len,
1105 1104          uint_t *protp,
1106 1105          page_t *pl[],
↓ open down ↓ 1 lines elided ↑ open up ↑
1108 1107          struct seg *seg,
1109 1108          caddr_t addr,
1110 1109          enum seg_rw rw,
1111 1110          struct cred *cred)
1112 1111  {
1113 1112          page_t **ppp;
1114 1113          u_offset_t o, eoff;
1115 1114          size_t sz, xlen;
1116 1115          int err;
1117 1116  
1118      -        ASSERT(plsz >= len);            /* insure that we have enough space */
     1117 +        /* ensure that we have enough space */
     1118 +        ASSERT(pl == NULL || plsz >= len);
1119 1119  
1120 1120          /*
1121 1121           * Loop one page at a time and let getapage function fill
1122 1122           * in the next page in array.  We only allow one page to be
1123 1123           * returned at a time (except for the last page) so that we
1124 1124           * don't have any problems with duplicates and other such
1125 1125           * painful problems.  This is a very simple minded algorithm,
1126 1126           * but it does the job correctly.  We hope that the cost of a
1127 1127           * getapage call for a resident page that we might have been
1128 1128           * able to get from an earlier call doesn't cost too much.
1129 1129           */
1130 1130          ppp = pl;
1131      -        sz = PAGESIZE;
     1131 +        sz = (pl != NULL) ? PAGESIZE : 0;
1132 1132          eoff = off + len;
1133 1133          xlen = len;
1134 1134          for (o = off; o < eoff; o += PAGESIZE, addr += PAGESIZE,
1135 1135              xlen -= PAGESIZE) {
1136      -                if (o + PAGESIZE >= eoff) {
     1136 +                if (o + PAGESIZE >= eoff && pl != NULL) {
1137 1137                          /*
1138 1138                           * Last time through - allow the all of
1139 1139                           * what's left of the pl[] array to be used.
1140 1140                           */
1141 1141                          sz = plsz - (o - off);
1142 1142                  }
1143 1143                  err = (*getpage)(vp, o, xlen, protp, ppp, sz, seg, addr,
1144 1144                      rw, cred);
1145 1145                  if (err) {
1146 1146                          /*
↓ open down ↓ 73 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX