Ejemplo n.º 1
0
/* ARGSUSED */
static int
segkmem_kluster(struct seg *seg, caddr_t addr, ssize_t delta)
{
	ASSERT(RW_LOCK_HELD(&seg->s_as->a_lock));

	if (seg->s_as != &kas)
		segkmem_badop();

	/*
	 * If it is one of segkp pages, call into segkp.
	 */
	if (segkp_bitmap && seg == &kvseg &&
	    BT_TEST(segkp_bitmap, btop((uintptr_t)(addr - seg->s_base))))
		return (SEGOP_KLUSTER(segkp, addr, delta));

	segkmem_badop();
	return (0);
}
Ejemplo n.º 2
0
/*
 * Find the largest contiguous block which contains `addr' for file offset
 * `offset' in it while living within the file system block sizes (`vp_off'
 * and `vp_len') and the address space limits for which no pages currently
 * exist and which map to consecutive file offsets.
 */
page_t *
pvn_read_kluster(
    struct vnode *vp,
    u_offset_t off,
    struct seg *seg,
    caddr_t addr,
    u_offset_t *offp,			/* return values */
    size_t *lenp,				/* return values */
    u_offset_t vp_off,
    size_t vp_len,
    int isra)
{
    ssize_t deltaf, deltab;
    page_t *pp;
    page_t *plist = NULL;
    spgcnt_t pagesavail;
    u_offset_t vp_end;

    ASSERT(off >= vp_off && off < vp_off + vp_len);

    /*
     * We only want to do klustering/read ahead if there
     * is more than minfree pages currently available.
     */
    pagesavail = freemem - minfree;

    if (pagesavail <= 0)
        if (isra)
            return ((page_t *)NULL);    /* ra case - give up */
        else
            pagesavail = 1;		    /* must return a page */

    /* We calculate in pages instead of bytes due to 32-bit overflows */
    if (pagesavail < (spgcnt_t)btopr(vp_len)) {
        /*
         * Don't have enough free memory for the
         * max request, try sizing down vp request.
         */
        deltab = (ssize_t)(off - vp_off);
        vp_len -= deltab;
        vp_off += deltab;
        if (pagesavail < btopr(vp_len)) {
            /*
             * Still not enough memory, just settle for
             * pagesavail which is at least 1.
             */
            vp_len = ptob(pagesavail);
        }
    }

    vp_end = vp_off + vp_len;
    ASSERT(off >= vp_off && off < vp_end);

    if (isra && SEGOP_KLUSTER(seg, addr, 0))
        return ((page_t *)NULL);	/* segment driver says no */

    if ((plist = page_create_va(vp, off,
                                PAGESIZE, PG_EXCL | PG_WAIT, seg, addr)) == NULL)
        return ((page_t *)NULL);

    if (vp_len <= PAGESIZE || pvn_nofodklust) {
        *offp = off;
        *lenp = MIN(vp_len, PAGESIZE);
    } else {
        /*
         * Scan back from front by incrementing "deltab" and
         * comparing "off" with "vp_off + deltab" to avoid
         * "signed" versus "unsigned" conversion problems.
         */
        for (deltab = PAGESIZE; off >= vp_off + deltab;
                deltab += PAGESIZE) {
            /*
             * Call back to the segment driver to verify that
             * the klustering/read ahead operation makes sense.
             */
            if (SEGOP_KLUSTER(seg, addr, -deltab))
                break;		/* page not eligible */
            if ((pp = page_create_va(vp, off - deltab,
                                     PAGESIZE, PG_EXCL, seg, addr - deltab))
                    == NULL)
                break;		/* already have the page */
            /*
             * Add page to front of page list.
             */
            page_add(&plist, pp);
        }
        deltab -= PAGESIZE;

        /* scan forward from front */
        for (deltaf = PAGESIZE; off + deltaf < vp_end;
                deltaf += PAGESIZE) {
            /*
             * Call back to the segment driver to verify that
             * the klustering/read ahead operation makes sense.
             */
            if (SEGOP_KLUSTER(seg, addr, deltaf))
                break;		/* page not file extension */
            if ((pp = page_create_va(vp, off + deltaf,
                                     PAGESIZE, PG_EXCL, seg, addr + deltaf))
                    == NULL)
                break;		/* already have page */

            /*
             * Add page to end of page list.
             */
            page_add(&plist, pp);
            plist = plist->p_next;
        }
        *offp = off = off - deltab;
        *lenp = deltab + deltaf;
        ASSERT(off >= vp_off);

        /*
         * If we ended up getting more than was actually
         * requested, retract the returned length to only
         * reflect what was requested.  This might happen
         * if we were allowed to kluster pages across a
         * span of (say) 5 frags, and frag size is less
         * than PAGESIZE.  We need a whole number of
         * pages to contain those frags, but the returned
         * size should only allow the returned range to
         * extend as far as the end of the frags.
         */
        if ((vp_off + vp_len) < (off + *lenp)) {
            ASSERT(vp_end > off);
            *lenp = vp_end - off;
        }
    }
    TRACE_3(TR_FAC_VM, TR_PVN_READ_KLUSTER,
            "pvn_read_kluster:seg %p addr %x isra %x",
            seg, addr, isra);
    return (plist);
}