/* ARGSUSED */ static intgen_t cb_add( void *arg1, jdm_fshandle_t *fshandlep, intgen_t fsfd, xfs_bstat_t *statp ) { register time32_t mtime = statp->bs_mtime.tv_sec; register time32_t ctime = statp->bs_ctime.tv_sec; register time32_t ltime = max( mtime, ctime ); register mode_t mode = statp->bs_mode & S_IFMT; xfs_off_t estimated_size = 0; xfs_ino_t ino = statp->bs_ino; bool_t changed; bool_t resumed; ( *inomap_statdonep )++; /* skip if no links */ if ( statp->bs_nlink == 0 ) { return 0; } /* if no portion of this ino is in the resume range, * then only dump it if it has changed since the interrupted * dump. * * otherwise, if some or all of this ino is in the resume range, * and has changed since the base dump upon which the original * increment was based, dump it if it has changed since that * original base dump. */ if ( cb_resume && ! cb_inoinresumerange( ino )) { if ( ltime >= cb_resumetime ) { changed = BOOL_TRUE; } else { changed = BOOL_FALSE; } } else if ( cb_last ) { if ( ltime >= cb_lasttime ) { changed = BOOL_TRUE; } else { changed = BOOL_FALSE; } } else { changed = BOOL_TRUE; } /* this is redundant: make sure any ino partially dumped * is completed. */ if ( cb_resume && cb_inoresumed( ino )) { resumed = BOOL_TRUE; } else { resumed = BOOL_FALSE; } if ( changed ) { if ( mode == S_IFDIR ) { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_CHANGE ); cb_dircnt++; } else { estimated_size = estimate_dump_space( statp ); /* skip if size is greater than prune size */ if ( maxdumpfilesize > 0 && estimated_size > maxdumpfilesize ) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: maximum size exceeded\n", statp->bs_ino, statp->bs_uid, estimated_size ); inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_filesize++; return 0; } if (allowexcludefiles_pr && statp->bs_xflags & XFS_XFLAG_NODUMP) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: skip flag set\n", statp->bs_ino, statp->bs_uid, estimated_size ); inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_skipattr++; return 0; } else if (allowexcludefiles_pr && (statp->bs_xflags & XFS_XFLAG_HASATTR)) { int rval; attr_multiop_t attrop; static char *skip_attr_name = "SGI_XFSDUMP_SKIP_FILE"; static int deprecated_msg_issued = 0; attrop.am_attrname = skip_attr_name; attrop.am_attrvalue = NULL; attrop.am_length = 0; attrop.am_error = 0; attrop.am_flags = 0; attrop.am_opcode = ATTR_OP_GET; rval = jdm_attr_multi( fshandlep, statp, (char *)&attrop, 1, 0 ); if ( !rval && (!attrop.am_error || attrop.am_error == E2BIG || attrop.am_error == ERANGE) ) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: skip attribute set\n", statp->bs_ino, statp->bs_uid, estimated_size ); if ( !deprecated_msg_issued ) { deprecated_msg_issued = 1; mlog( MLOG_SILENT | MLOG_WARNING, "excluding files using %s attribute is deprecated\n", skip_attr_name ); } inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_skipattr++; return 0; } } inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_CHANGE ); cb_nondircnt++; cb_datasz += estimated_size; cb_hdrsz += ( EXTENTHDR_SZ * (statp->bs_extents + 1) ); } } else if ( resumed ) { ASSERT( mode != S_IFDIR ); ASSERT( changed ); } else { if ( mode == S_IFDIR ) { *cb_pruneneededp = BOOL_TRUE; inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_SUPPRT ); cb_dircnt++; } else { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); } } return 0; }
/* ARGSUSED */ static intgen_t cb_startpt( void *arg1, jdm_fshandle_t *fshandlep, intgen_t fsfd, xfs_bstat_t *statp ) { register intgen_t state; off64_t estimate; off64_t old_accum = cb_accum; off64_t qty; /* amount of a SPLIT file to skip */ action_t action; ( *inomap_statdonep )++; /* skip if no links */ if ( statp->bs_nlink == 0 ) { return 0; } /* skip if not in inomap or not a non-dir */ state = inomap_get_state( cb_inomap_contextp, statp->bs_ino ); if ( state != MAP_NDR_CHANGE ) { return 0; } ASSERT( cb_startptix < cb_startptcnt ); estimate = estimate_dump_space( statp ); cb_accum += estimate + ( EXTENTHDR_SZ * (statp->bs_extents + 1) ); /* loop until no new start points found. loop is necessary * to handle the pathological case of a huge file so big it * spans several streams. */ action = ( action_t )HOLD; /* irrelevant, but demanded by lint */ do { /* decide what to do: hold, bump, or split. there are * 8 valid cases to consider: * 1) accum prior to this file is way too short of the * target, and accum incl. this file is also shy: HOLD; * 2) accum prior to this file is way too short of the * target, and accum incl. this file is close to but * still short of target: HOLD; * 3) accum prior to this file is way too short of the * target, and accum incl. this file is a little beyond * the target: HOLD; * 4) accum prior to this file is way too short of the * target, and accum incl. this file is way beyond * the target: SPLIT; * 5) accum prior to this file is close to target, and * accum incl. this file is still short of target: HOLD; * 6) accum prior to this file is close to target, and * accum incl. this file is a little beyond the target, * and excluding this file would be less short of target * than including it would be beyond the target: BUMP; * 7) accum prior to this file is close to target, and * accum incl. this file is a little beyond the target, * and including this file would be less beyond target * than excluding it would be short of target: HOLD; * 8) accum prior to this file is close to target, and * accum incl. this file is would be way beyond the * target: HOLD. */ if ( cb_target - old_accum >= TOO_SHY ) { if ( cb_target - cb_accum >= TOO_SHY ) { action = ( action_t )HOLD; } else if ( cb_accum <= cb_target ) { action = ( action_t )HOLD; } else if ( cb_accum - cb_target < TOO_BOLD ) { action = ( action_t )HOLD; } else { action = ( action_t )SPLIT; } } else { if ( cb_target - cb_accum >= TOO_SHY ) { action = ( action_t )YELL; } else if ( cb_accum < cb_target ) { action = ( action_t )HOLD; } else if ( cb_accum - cb_target < TOO_BOLD ) { if ( cb_accum - cb_target >= cb_target - old_accum ) { action = ( action_t )BUMP; } else { action = ( action_t )HOLD; } } else { action = ( action_t )BUMP; } } /* perform the action selected above */ switch ( action ) { case ( action_t )HOLD: break; case ( action_t )BUMP: cb_startptp->sp_ino = statp->bs_ino; cb_startptp->sp_offset = 0; cb_startptix++; cb_startptp++; cb_target += cb_incr; if ( cb_startptix == cb_startptcnt ) { return 1; /* done; abort the iteration */ } break; case ( action_t )SPLIT: cb_startptp->sp_ino = statp->bs_ino; qty = ( cb_target - old_accum ) & ~( off64_t )( BBSIZE - 1 ); cb_startptp->sp_offset = quantity2offset( fshandlep, statp, qty ); cb_startptix++; cb_startptp++; cb_target += cb_incr; if ( cb_startptix == cb_startptcnt ) { return 1; /* done; abort the iteration */ } break; default: ASSERT( 0 ); return 1; } } while ( action == ( action_t )BUMP || action == ( action_t )SPLIT ); return 0; }
/* ARGSUSED */ static intgen_t cb_add( void *arg1, jdm_fshandle_t *fshandlep, intgen_t fsfd, xfs_bstat_t *statp ) { register time32_t mtime = statp->bs_mtime.tv_sec; register time32_t ctime = statp->bs_ctime.tv_sec; register time32_t ltime = max( mtime, ctime ); register mode_t mode = statp->bs_mode & S_IFMT; xfs_off_t estimated_size = 0; xfs_ino_t ino = statp->bs_ino; bool_t changed; bool_t resumed; ( *inomap_statdonep )++; /* skip if no links */ if ( statp->bs_nlink == 0 ) { return 0; } /* if no portion of this ino is in the resume range, * then only dump it if it has changed since the interrupted * dump. * * otherwise, if some or all of this ino is in the resume range, * and has changed since the base dump upon which the original * increment was based, dump it if it has changed since that * original base dump. */ if ( cb_resume && ! cb_inoinresumerange( ino )) { if ( ltime >= cb_resumetime ) { changed = BOOL_TRUE; } else { changed = BOOL_FALSE; } } else if ( cb_last ) { if ( ltime >= cb_lasttime ) { changed = BOOL_TRUE; } else { changed = BOOL_FALSE; } } else { changed = BOOL_TRUE; } /* this is redundant: make sure any ino partially dumped * is completed. */ if ( cb_resume && cb_inoresumed( ino )) { resumed = BOOL_TRUE; } else { resumed = BOOL_FALSE; } if ( changed ) { if ( mode == S_IFDIR ) { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_CHANGE ); cb_dircnt++; } else { estimated_size = estimate_dump_space( statp ); /* skip if size is greater than prune size. quota * files are exempt from the check. */ if ( maxdumpfilesize > 0 && estimated_size > maxdumpfilesize && !is_quota_file(statp->bs_ino) ) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: maximum size exceeded\n", statp->bs_ino, statp->bs_uid, estimated_size ); inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_filesize++; return 0; } if (allowexcludefiles_pr && statp->bs_xflags & XFS_XFLAG_NODUMP) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: skip flag set\n", statp->bs_ino, statp->bs_uid, estimated_size ); inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_skipattr++; return 0; } inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_CHANGE ); cb_nondircnt++; cb_datasz += estimated_size; cb_hdrsz += ( EXTENTHDR_SZ * (statp->bs_extents + 1) ); } } else if ( resumed ) { ASSERT( mode != S_IFDIR ); ASSERT( changed ); } else { if ( mode == S_IFDIR ) { if ( cb_skip_unchanged_dirs ) { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_NOCHNG ); } else { *cb_pruneneededp = BOOL_TRUE; inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_SUPPRT ); cb_dircnt++; } } else { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); } } return 0; }