コード例 #1
0
ファイル: node.c プロジェクト: ystk/debian-xfsdump
void *
node_map( nh_t nh )
{
    nix_t nix;
    u_char_t *p;
#ifdef NODECHK
    register u_char_t hkp;
    register u_char_t hdlgen;
    register u_char_t nodegen;
    register u_char_t nodeunq;
#endif /* NODECHK */

    ASSERT( nh != NH_NULL );

    /* convert the handle into an index
     */
#ifdef NODECHK
    hdlgen = HDLGETGEN( nh );
    nix = HDLGETNIX( nh );
#else /* NODECHK */
    nix = ( nix_t )nh;
#endif /* NODECHK */

    ASSERT( nix <= NIX_MAX );

    /* map in
     */
    p = 0; /* keep lint happy */
    win_map( NIX2OFF( nix ), ( void ** )&p );
    if (p == NULL)
        return NULL;

#ifdef NODECHK
    hkp = *( p + node_hdrp->nh_nodehkix );
    nodegen = HKPGETGEN( hkp );
    nodeunq = HKPGETUNQ( hkp );
    ASSERT( nodegen == hdlgen );
    ASSERT( nodeunq != NODEUNQFREE );
    ASSERT( nodeunq == NODEUNQALCD );
#endif /* NODECHK */

    return ( void * )p;
}
コード例 #2
0
ファイル: win.c プロジェクト: jkkm/xfsdump
void
win_map( segix_t segix, void **pp )
{
	off64_t segoff;
	win_t *winp;

	CRITICAL_BEGIN();

#ifdef TREE_DEBUG
	mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK,
	     "win_map(segix=%u,addr=%p)\n", segix, pp);
#endif
	/* resize the array if necessary */
	if ( segix >= tranp->t_segmaplen )
		win_segmap_resize( segix );

	/* see if segment already mapped. if ref cnt zero,
	 * remove from LRU list.
	 */
	winp = tranp->t_segmap[segix];
	if ( winp ) {
#ifdef TREE_DEBUG
		mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK,
		     "win_map(): requested segment already mapped\n");
#endif
		if ( winp->w_refcnt == 0 ) {
			ASSERT( tranp->t_lruheadp );
			ASSERT( tranp->t_lrutailp );
			if ( tranp->t_lruheadp == winp ) {
				if ( tranp->t_lrutailp == winp ) {
					tranp->t_lruheadp = 0;
					tranp->t_lrutailp = 0;
				} else {
					tranp->t_lruheadp = winp->w_nextp;
					tranp->t_lruheadp->w_prevp = 0;
				}
			} else {
				if ( tranp->t_lrutailp == winp ) {
					tranp->t_lrutailp = winp->w_prevp;
					tranp->t_lrutailp->w_nextp = 0;
				} else {
					winp->w_prevp->w_nextp = winp->w_nextp;
					winp->w_nextp->w_prevp = winp->w_prevp;
				}
			}
			winp->w_prevp = 0;
			winp->w_nextp = 0;
		} else {
			ASSERT( ! winp->w_prevp );
			ASSERT( ! winp->w_nextp );
		}
		winp->w_refcnt++;
		*pp = winp->w_p;
		CRITICAL_END();
		return;
	}

	/* Allocate a new descriptor if we haven't yet hit the maximum,
	 * otherwise reuse any descriptor on the LRU list.
	 */
	if ( tranp->t_wincnt < tranp->t_winmax ) {
#ifdef TREE_DEBUG
		mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK,
		     "win_map(): create a new window\n");
#endif
		winp = ( win_t * )calloc( 1, sizeof( win_t ));
		ASSERT( winp );
		tranp->t_wincnt++;
	} else if ( tranp->t_lruheadp ) {
		/* REFERENCED */
		intgen_t rval;
#ifdef TREE_DEBUG
		mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK,
		     "win_map(): get head from lru freelist & unmap\n");
#endif
		ASSERT( tranp->t_lrutailp );
		winp = tranp->t_lruheadp;
		tranp->t_lruheadp = winp->w_nextp;
		if ( tranp->t_lruheadp ) {
			tranp->t_lruheadp->w_prevp = 0;
		} else {
			tranp->t_lrutailp = 0;
		}
		tranp->t_segmap[winp->w_segix] = NULL;
		rval = munmap( winp->w_p, tranp->t_segsz );
		ASSERT( ! rval );
		memset( ( void * )winp, 0, sizeof( win_t ));
	} else {
		ASSERT( tranp->t_wincnt == tranp->t_winmax );
		*pp = NULL;
		CRITICAL_END();
		mlog( MLOG_NORMAL | MLOG_WARNING, _(
		      "all map windows in use. Check virtual memory limits\n"));
		return;
	}

	/* calculate offset of segment
	 */
	segoff = segix * ( off64_t )tranp->t_segsz;

	/* map the window
	 */
	ASSERT( tranp->t_segsz >= 1 );
	ASSERT( tranp->t_firstoff
		<=
		OFF64MAX - segoff - ( off64_t )tranp->t_segsz + 1ll );
	ASSERT( ! ( tranp->t_segsz % pgsz ));
	ASSERT( ! ( ( tranp->t_firstoff + segoff ) % ( off64_t )pgsz ));
#ifdef TREE_DEBUG
	mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK,
	     "win_map(): mmap segment at %lld, size = %llu\n",
	    ( off64_t )( tranp->t_firstoff + segoff ), tranp->t_segsz);
#endif
	tranp->t_winmmaps++;
	winp->w_p = mmap_autogrow(
			    tranp->t_segsz,
			    tranp->t_fd,
			    ( off64_t )( tranp->t_firstoff + segoff ));
	if ( winp->w_p == (void *)-1 ) {
		int	error = errno;
		mlog( MLOG_NORMAL | MLOG_ERROR, _(
		      "win_map(): unable to map a node segment of size %d at %d: %s\n"),
		      tranp->t_segsz, tranp->t_firstoff + segoff,
		      strerror( error ));

		tranp->t_wincnt--;
		tranp->t_winmax--;
		CRITICAL_END();
		free(winp);

		if (error == ENOMEM && tranp->t_lruheadp) {
			mlog( MLOG_NORMAL | MLOG_ERROR,
		      		_("win_map(): try to select a different win_t\n"));
			win_map(segix, pp);
			return;
		}
		*pp = NULL;
		return;
	}
	winp->w_segix  = segix;
	ASSERT( winp->w_refcnt == 0 );
	winp->w_refcnt++;
	tranp->t_segmap[winp->w_segix] = winp;

	*pp = winp->w_p;

	CRITICAL_END();
}
コード例 #3
0
ファイル: node.c プロジェクト: ystk/debian-xfsdump
nh_t
node_alloc( void )
{
    nix_t nix;
    u_char_t *p;
    nh_t nh;
    register nix_t *linkagep;
#ifdef NODECHK
    register u_char_t *hkpp;
    register u_char_t gen;
    register u_char_t unq;
#endif /* NODECHK */

    /* if free list is depleted, map in a new window at the
     * end of backing store. put all nodes on free list.
     * initialize the gen count to the node index, and the unique
     * pattern to the free pattern.
     */
    if ( node_hdrp->nh_freenix == NIX_NULL ) {
        nix_t virgbegnix; /* abs. nix of first node in virg seg */
        nix_t virgendnix; /* abs. nix of next node after last */
        nix_t sacrcnt; /* how many virgins to put on free list */
        nix_t sacrnix;

        ASSERT( node_hdrp->nh_virgrelnix
                <
                ( nix_t )node_hdrp->nh_nodesperseg );
        virgbegnix = OFF2NIX( node_hdrp->nh_virgsegreloff )
                     +
                     node_hdrp->nh_virgrelnix;
        virgendnix =
            OFF2NIX( ( node_hdrp->nh_virgsegreloff
                       +
                       ( off64_t )node_hdrp->nh_segsz ) );
#ifdef TREE_DEBUG
        mlog(MLOG_DEBUG | MLOG_TREE,
             "node_alloc(): create freelist - "
             "virg_begin=%lld virg_end=%lld\n",
             virgbegnix, virgendnix);
#endif
        ASSERT( virgendnix > virgbegnix );
        sacrcnt = min( VIRGSACRMAX, virgendnix - virgbegnix );
        ASSERT( sacrcnt >= 1 );
        p = 0; /* keep lint happy */
        win_map( NIX2OFF( virgbegnix ), ( void ** )&p );
        if (p == NULL)
            return NH_NULL;
        node_hdrp->nh_freenix = virgbegnix;
        for ( sacrnix = virgbegnix
                        ;
                sacrnix < virgbegnix + sacrcnt - 1
                ;
                p += node_hdrp->nh_nodesz, sacrnix++ ) {
            linkagep = ( nix_t * )p;
            *linkagep = sacrnix + 1;
#ifdef NODECHK
            hkpp = p + node_hdrp->nh_nodehkix;
            gen = ( u_char_t )sacrnix;
            *hkpp = ( u_char_t )HKPMKHKP( ( size_t )gen,
                                          NODEUNQFREE );
#endif /* NODECHK */
        }
        linkagep = ( nix_t * )p;
        *linkagep = NIX_NULL;
#ifdef NODECHK
        hkpp = p + node_hdrp->nh_nodehkix;
        gen = ( u_char_t )sacrnix;
        *hkpp = HKPMKHKP( gen, NODEUNQFREE );
#endif /* NODECHK */
        node_hdrp->nh_virgrelnix += sacrcnt;
        win_unmap( node_hdrp->nh_virgsegreloff, ( void ** )&p );

        if ( node_hdrp->nh_virgrelnix
                >=
                ( nix_t )node_hdrp->nh_nodesperseg ) {
            intgen_t rval;
            ASSERT( node_hdrp->nh_virgrelnix
                    ==
                    ( nix_t )node_hdrp->nh_nodesperseg );
            ASSERT( node_hdrp->nh_virgsegreloff
                    <=
                    OFF64MAX - ( off64_t )node_hdrp->nh_segsz );
#ifdef TREE_DEBUG
            mlog(MLOG_DEBUG | MLOG_TREE,
                 "node_alloc(): runout of nodes for freelist in "
                 "this segment - nodes used = %lld\n",
                 node_hdrp->nh_virgrelnix);
#endif
            node_hdrp->nh_virgsegreloff +=
                ( off64_t )node_hdrp->nh_segsz;
            node_hdrp->nh_virgrelnix = 0;
            mlog( MLOG_DEBUG,
                  "pre-growing new node array segment at %lld "
                  "size %lld\n",
                  node_hdrp->nh_firstsegoff
                  +
                  node_hdrp->nh_virgsegreloff
                  +
                  ( off64_t )node_hdrp->nh_segsz,
                  ( off64_t )node_hdrp->nh_segsz );
            rval = ftruncate64( node_fd,
                                node_hdrp->nh_firstsegoff
                                +
                                node_hdrp->nh_virgsegreloff
                                +
                                ( off64_t )node_hdrp->nh_segsz );
            if ( rval ) {
                mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _(
                          "unable to autogrow node segment %llu: "
                          "%s (%d)\n"),
                      node_hdrp->nh_virgsegreloff
                      /
                      ( off64_t )node_hdrp->nh_segsz,
                      strerror( errno ),
                      errno );
            }
        }
    }

    /* map in window containing node at top of free list,
     * and adjust free list.
     */
    nix = node_hdrp->nh_freenix;
#ifdef TREE_DEBUG
    mlog(MLOG_DEBUG | MLOG_TREE,
         "node_alloc(): win_map(%llu) and get head from node freelist\n",
         NIX2OFF(nix));
#endif
    win_map( NIX2OFF( nix ), ( void ** )&p );
    if (p == NULL)
        return NH_NULL;
#ifdef NODECHK
    hkpp = p + node_hdrp->nh_nodehkix;
    unq = HKPGETUNQ( *hkpp );
    ASSERT( unq != NODEUNQALCD );
    ASSERT( unq == NODEUNQFREE );
#endif /* NODECHK */
    linkagep = ( nix_t * )p;
    node_hdrp->nh_freenix = *linkagep;

    /* clean the node
     */
    memset( ( void * )p, 0, node_hdrp->nh_nodesz );

    /* build a handle for node
     */
    ASSERT( nix <= NIX_MAX );
#ifdef NODECHK
    hkpp = p + ( int )node_hdrp->nh_nodehkix;
    gen = ( u_char_t )( HKPGETGEN( *p ) + ( u_char_t )1 );
    nh = HDLMKHDL( gen, nix );
    *hkpp = HKPMKHKP( gen, NODEUNQALCD );
#else /* NODECHK */
    nh = ( nh_t )nix;
#endif /* NODECHK */

    /* unmap window
     */
#ifdef TREE_DEBUG
    mlog(MLOG_DEBUG | MLOG_TREE,
         "node_alloc(): win_unmap(%llu)\n", NIX2OFF(nix));
#endif
    win_unmap( NIX2OFF( nix ), ( void ** )&p );

    return nh;
}