Print this page
OS-881 To workaround OS-580 add support to only invalidate mappings from a single process


7291                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7292                         return (EAGAIN);
7293                 }
7294         } else if (svd->type == MAP_SHARED && svd->amp != NULL &&
7295             svd->amp->a_softlockcnt > 0) {
7296                 /*
7297                  * Try to purge this amp's entries from pcache. It will
7298                  * succeed only if other segments that share the amp have no
7299                  * outstanding softlock's.
7300                  */
7301                 segvn_purge(seg);
7302                 if (svd->amp->a_softlockcnt > 0 || svd->softlockcnt > 0) {
7303                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7304                         return (EAGAIN);
7305                 }
7306         }
7307 
7308         vpp = svd->vpage;
7309         offset = svd->offset + (uintptr_t)(addr - seg->s_base);
7310         bflags = ((flags & MS_ASYNC) ? B_ASYNC : 0) |
7311             ((flags & MS_INVALIDATE) ? B_INVAL : 0);

7312 
7313         if (attr) {
7314                 pageprot = attr & ~(SHARED|PRIVATE);
7315                 segtype = (attr & SHARED) ? MAP_SHARED : MAP_PRIVATE;
7316 
7317                 /*
7318                  * We are done if the segment types don't match
7319                  * or if we have segment level protections and
7320                  * they don't match.
7321                  */
7322                 if (svd->type != segtype) {
7323                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7324                         return (0);
7325                 }
7326                 if (vpp == NULL) {
7327                         if (svd->prot != pageprot) {
7328                                 SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7329                                 return (0);
7330                         }
7331                         prot = svd->prot;
7332                 } else
7333                         vpp = &svd->vpage[seg_page(seg, addr)];
7334 
7335         } else if (svd->vp && svd->amp == NULL &&
7336             (flags & MS_INVALIDATE) == 0) {
7337 
7338                 /*
7339                  * No attributes, no anonymous pages and MS_INVALIDATE flag
7340                  * is not on, just use one big request.
7341                  */
7342                 err = VOP_PUTPAGE(svd->vp, (offset_t)offset, len,
7343                     bflags, svd->cred, NULL);
7344                 SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7345                 return (err);
7346         }
7347 
7348         if ((amp = svd->amp) != NULL)
7349                 anon_index = svd->anon_index + seg_page(seg, addr);
7350 
7351         for (eaddr = addr + len; addr < eaddr; addr += PAGESIZE) {
7352                 ap = NULL;
7353                 if (amp != NULL) {
7354                         ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
7355                         anon_array_enter(amp, anon_index, &cookie);
7356                         ap = anon_get_ptr(amp->ahp, anon_index++);
7357                         if (ap != NULL) {
7358                                 swap_xlate(ap, &vp, &off);
7359                         } else {
7360                                 vp = svd->vp;


7372                         continue;
7373 
7374                 if (attr) {
7375                         if (vpp) {
7376                                 prot = VPP_PROT(vpp);
7377                                 vpp++;
7378                         }
7379                         if (prot != pageprot) {
7380                                 continue;
7381                         }
7382                 }
7383 
7384                 /*
7385                  * See if any of these pages are locked --  if so, then we
7386                  * will have to truncate an invalidate request at the first
7387                  * locked one. We don't need the page_struct_lock to test
7388                  * as this is only advisory; even if we acquire it someone
7389                  * might race in and lock the page after we unlock and before
7390                  * we do the PUTPAGE, then PUTPAGE simply does nothing.
7391                  */
7392                 if (flags & MS_INVALIDATE) {
7393                         if ((pp = page_lookup(vp, off, SE_SHARED)) != NULL) {
7394                                 if (pp->p_lckcnt != 0 || pp->p_cowcnt != 0) {
7395                                         page_unlock(pp);
7396                                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7397                                         return (EBUSY);
7398                                 }
7399                                 if (ap != NULL && pp->p_szc != 0 &&
7400                                     page_tryupgrade(pp)) {
7401                                         if (pp->p_lckcnt == 0 &&
7402                                             pp->p_cowcnt == 0) {
7403                                                 /*
7404                                                  * swapfs VN_DISPOSE() won't
7405                                                  * invalidate large pages.
7406                                                  * Attempt to demote.
7407                                                  * XXX can't help it if it
7408                                                  * fails. But for swapfs
7409                                                  * pages it is no big deal.
7410                                                  */
7411                                                 (void) page_try_demote_pages(
7412                                                     pp);




7291                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7292                         return (EAGAIN);
7293                 }
7294         } else if (svd->type == MAP_SHARED && svd->amp != NULL &&
7295             svd->amp->a_softlockcnt > 0) {
7296                 /*
7297                  * Try to purge this amp's entries from pcache. It will
7298                  * succeed only if other segments that share the amp have no
7299                  * outstanding softlock's.
7300                  */
7301                 segvn_purge(seg);
7302                 if (svd->amp->a_softlockcnt > 0 || svd->softlockcnt > 0) {
7303                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7304                         return (EAGAIN);
7305                 }
7306         }
7307 
7308         vpp = svd->vpage;
7309         offset = svd->offset + (uintptr_t)(addr - seg->s_base);
7310         bflags = ((flags & MS_ASYNC) ? B_ASYNC : 0) |
7311             ((flags & MS_INVALIDATE) ? B_INVAL : 0) |
7312             ((flags & MS_INVALCURPROC) ? (B_INVALCURONLY | B_INVAL) : 0);
7313 
7314         if (attr) {
7315                 pageprot = attr & ~(SHARED|PRIVATE);
7316                 segtype = (attr & SHARED) ? MAP_SHARED : MAP_PRIVATE;
7317 
7318                 /*
7319                  * We are done if the segment types don't match
7320                  * or if we have segment level protections and
7321                  * they don't match.
7322                  */
7323                 if (svd->type != segtype) {
7324                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7325                         return (0);
7326                 }
7327                 if (vpp == NULL) {
7328                         if (svd->prot != pageprot) {
7329                                 SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7330                                 return (0);
7331                         }
7332                         prot = svd->prot;
7333                 } else
7334                         vpp = &svd->vpage[seg_page(seg, addr)];
7335 
7336         } else if (svd->vp && svd->amp == NULL &&
7337             (flags & (MS_INVALIDATE | MS_INVALCURPROC)) == 0) {
7338 
7339                 /*
7340                  * No attributes, no anonymous pages and MS_INVAL* flags
7341                  * are not on, just use one big request.
7342                  */
7343                 err = VOP_PUTPAGE(svd->vp, (offset_t)offset, len,
7344                     bflags, svd->cred, NULL);
7345                 SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7346                 return (err);
7347         }
7348 
7349         if ((amp = svd->amp) != NULL)
7350                 anon_index = svd->anon_index + seg_page(seg, addr);
7351 
7352         for (eaddr = addr + len; addr < eaddr; addr += PAGESIZE) {
7353                 ap = NULL;
7354                 if (amp != NULL) {
7355                         ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
7356                         anon_array_enter(amp, anon_index, &cookie);
7357                         ap = anon_get_ptr(amp->ahp, anon_index++);
7358                         if (ap != NULL) {
7359                                 swap_xlate(ap, &vp, &off);
7360                         } else {
7361                                 vp = svd->vp;


7373                         continue;
7374 
7375                 if (attr) {
7376                         if (vpp) {
7377                                 prot = VPP_PROT(vpp);
7378                                 vpp++;
7379                         }
7380                         if (prot != pageprot) {
7381                                 continue;
7382                         }
7383                 }
7384 
7385                 /*
7386                  * See if any of these pages are locked --  if so, then we
7387                  * will have to truncate an invalidate request at the first
7388                  * locked one. We don't need the page_struct_lock to test
7389                  * as this is only advisory; even if we acquire it someone
7390                  * might race in and lock the page after we unlock and before
7391                  * we do the PUTPAGE, then PUTPAGE simply does nothing.
7392                  */
7393                 if (flags & (MS_INVALIDATE | MS_INVALCURPROC)) {
7394                         if ((pp = page_lookup(vp, off, SE_SHARED)) != NULL) {
7395                                 if (pp->p_lckcnt != 0 || pp->p_cowcnt != 0) {
7396                                         page_unlock(pp);
7397                                         SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
7398                                         return (EBUSY);
7399                                 }
7400                                 if (ap != NULL && pp->p_szc != 0 &&
7401                                     page_tryupgrade(pp)) {
7402                                         if (pp->p_lckcnt == 0 &&
7403                                             pp->p_cowcnt == 0) {
7404                                                 /*
7405                                                  * swapfs VN_DISPOSE() won't
7406                                                  * invalidate large pages.
7407                                                  * Attempt to demote.
7408                                                  * XXX can't help it if it
7409                                                  * fails. But for swapfs
7410                                                  * pages it is no big deal.
7411                                                  */
7412                                                 (void) page_try_demote_pages(
7413                                                     pp);