static xfs_ino_t inomap_iter( void *contextp, intgen_t statemask ) { xfs_ino_t ino, endino; seg_t *segp; seg_addr_t *addrp = (seg_addr_t *)contextp; for ( ; addrp->hnkoff <= inomap.lastseg.hnkoff; addrp->hnkoff++, addrp->segoff = 0, addrp->inooff = 0 ) { for ( ; addrp->segoff <= inomap_lastseg(addrp->hnkoff); addrp->segoff++, addrp->inooff = 0 ) { segp = inomap_addr2seg( addrp ); ino = segp->base + addrp->inooff; endino = segp->base + INOPERSEG; for ( ; ino < endino ; ino++, addrp->inooff++ ) { intgen_t st; st = SEG_GET_BITS( segp, ino ); if ( statemask & ( 1 << st )) { addrp->inooff++; /* for next call */ return ino; } } } } return INO64MAX; }
/* map_getset - locates and gets the state of the specified ino, * and optionally sets the state to a new value. */ static intgen_t map_getset( xfs_ino_t ino, intgen_t newstate, bool_t setflag ) { hnk_t *hnkp; seg_t *segp; if ( ino > last_ino_added ) { return MAP_INO_UNUSED; } for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { if ( ino > hnkp->maxino ) { continue; } for ( segp = hnkp->seg; segp < hnkp->seg + SEGPERHNK ; segp++ ){ if ( hnkp == tailhnkp && segp > lastsegp ) { return MAP_INO_UNUSED; } if ( ino < segp->base ) { return MAP_INO_UNUSED; } if ( ino < segp->base + INOPERSEG ) { intgen_t state; SEG_GET_BITS( segp, ino, state ); if ( setflag ) { SEG_SET_BITS( segp, ino, newstate ); } return state; } } return MAP_INO_UNUSED; } return MAP_INO_UNUSED; }
intgen_t inomap_get_state( void *contextp, xfs_ino_t ino ) { seg_addr_t *addrp; seg_addr_t addr; seg_t *segp; addrp = contextp ? (seg_addr_t *)contextp : &addr; if ( !inomap_find_seg( addrp, ino ) ) return MAP_INO_UNUSED; segp = inomap_addr2seg( addrp ); return SEG_GET_BITS( segp, ino ); }
/* calls the callback for all inos with an inomap state included * in the state mask. stops iteration when inos exhaused or cb * returns FALSE. */ void inomap_cbiter( intgen_t statemask, bool_t ( * cbfunc )( void *ctxp, xfs_ino_t ino ), void *ctxp ) { hnk_t *hnkp; seg_t *segp; /* step through all hunks, segs, and inos */ for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { for ( segp = hnkp->seg ; segp < hnkp->seg + SEGPERHNK ; segp++ ) { xfs_ino_t ino; if ( hnkp == tailhnkp && segp > lastsegp ) { return; } for ( ino = segp->base ; ino < segp->base + INOPERSEG ; ino++ ) { intgen_t state; if ( ino > last_ino_added ) { return; } SEG_GET_BITS( segp, ino, state ); if ( statemask & ( 1 << state )) { bool_t ok; ok = ( cbfunc )( ctxp, ino ); if ( ! ok ) { return; } } } } } }
static intgen_t inomap_set_state( void *contextp, xfs_ino_t ino, intgen_t state ) { intgen_t oldstate; seg_addr_t *addrp; seg_addr_t addr; seg_t *segp; addrp = contextp ? (seg_addr_t *)contextp : &addr; if ( !inomap_find_seg( addrp, ino ) ) return MAP_INO_UNUSED; segp = inomap_addr2seg( addrp ); oldstate = SEG_GET_BITS( segp, ino ); SEG_SET_BITS( segp, ino, state ); return oldstate; }
/* mark all included non-dirs as MAP_NDR_NOREST */ void inomap_sanitize( void ) { hnk_t *hnkp; seg_t *segp; /* step through all hunks, segs, and inos */ for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { for ( segp = hnkp->seg ; segp < hnkp->seg + SEGPERHNK ; segp++ ) { xfs_ino_t ino; if ( hnkp == tailhnkp && segp > lastsegp ) { return; } for ( ino = segp->base ; ino < segp->base + INOPERSEG ; ino++ ) { intgen_t state; if ( ino > last_ino_added ) { return; } SEG_GET_BITS( segp, ino, state ); if ( state == MAP_NDR_CHANGE ) { state = MAP_NDR_NOREST; SEG_SET_BITS( segp, ino, state ); } } } } }
/* called to ask if any inos in the given range need to be restored. * range is inclusive */ bool_t inomap_rst_needed( xfs_ino_t firstino, xfs_ino_t lastino ) { hnk_t *hnkp; seg_t *segp; /* if inomap not restored/resynced, just say yes */ if ( ! roothnkp ) { return BOOL_TRUE; } /* may be completely out of range */ if ( firstino > last_ino_added ) { return BOOL_FALSE; } /* find the hunk/seg containing first ino or any ino beyond */ for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { if ( firstino > hnkp->maxino ) { continue; } for ( segp = hnkp->seg; segp < hnkp->seg + SEGPERHNK ; segp++ ){ if ( hnkp == tailhnkp && segp > lastsegp ) { return BOOL_FALSE; } if ( firstino < segp->base + INOPERSEG ) { goto begin; } } } return BOOL_FALSE; begin: /* search until at least one ino is needed or until beyond last ino */ for ( ; ; ) { xfs_ino_t ino; if ( segp->base > lastino ) { return BOOL_FALSE; } for ( ino = segp->base ; ino < segp->base + INOPERSEG ; ino++ ){ intgen_t state; if ( ino < firstino ) { continue; } if ( ino > lastino ) { return BOOL_FALSE; } SEG_GET_BITS( segp, ino, state ); if ( state == MAP_NDR_CHANGE ) { return BOOL_TRUE; } } segp++; if ( hnkp == tailhnkp && segp > lastsegp ) { return BOOL_FALSE; } if ( segp >= hnkp->seg + SEGPERHNK ) { hnkp = hnkp->nextp; if ( ! hnkp ) { return BOOL_FALSE; } segp = hnkp->seg; } } /* NOTREACHED */ }