Restoring an incremental level 1 dump will fail with the following error if the fs uuid of the most recent level 0 dump in the inventory does not match level 1 dump we are restoring. xfsrestore: ERROR: selected dump not based on previously applied dump This can happen when you have multiple filesystems and you are restoring a level 1 or greater dump of filesystem FS1 but the most recent level 0 dump in the inventory was filesystem FS2 The fix is to ensure the fs uuid of the inventory entry and the dump to be restored match. Signed-off-by: Rich Johnston <rjohnston@xxxxxxx> --- dump/content.c | 8 ++- inventory/inv_api.c | 108 ++++++++++++++++++++++++++++++-------------------- inventory/inv_mgr.c | 32 ++++++++++---- inventory/inv_priv.h | 7 +-- inventory/inventory.h | 5 ++ restore/content.c | 17 +++++-- 6 files changed, 113 insertions(+), 64 deletions(-) Index: b/dump/content.c =================================================================== --- a/dump/content.c +++ b/dump/content.c @@ -872,7 +872,7 @@ content_init( intgen_t argc, sameinterruptedpr = BOOL_FALSE; interruptedpr = BOOL_FALSE; - ok = inv_get_session_byuuid( &baseuuid, &sessp ); + ok = inv_get_session_byuuid( &fsid, &baseuuid, &sessp ); if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not find specified base dump (%s) " @@ -983,7 +983,8 @@ content_init( intgen_t argc, "online inventory not available\n") ); return BOOL_FALSE; } - ok = inv_lastsession_level_lessthan( inv_idbt, + ok = inv_lastsession_level_lessthan( &fsid, + inv_idbt, ( u_char_t )sc_level, &sessp ); if ( ! ok ) { @@ -1022,7 +1023,8 @@ content_init( intgen_t argc, if ( inv_idbt != INV_TOKEN_NULL ) { /* REFERENCED */ bool_t ok1; - ok = inv_lastsession_level_equalto( inv_idbt, + ok = inv_lastsession_level_equalto( &fsid, + inv_idbt, ( u_char_t )sc_level, &sessp ); ok1 = inv_close( inv_idbt ); Index: b/inventory/inv_api.c =================================================================== --- a/inventory/inv_api.c +++ b/inventory/inv_api.c @@ -596,69 +596,78 @@ inv_free_session( /*----------------------------------------------------------------------*/ -/* inventory_lasttime_level_lessthan */ -/* */ -/* Given a token that refers to a file system, and a level, this returns*/ -/* the last time when a session of a lesser level was done. */ -/* */ -/* returns -1 on error. */ +/* inv_lasttime_level_lessthan */ +/* */ +/* Given a file system uuid, token that refers to a file system, and a */ +/* level, tm is populated with last time when a session of a lesser */ +/* level was done. */ +/* */ +/* Returns TRUE on success. */ /*----------------------------------------------------------------------*/ bool_t inv_lasttime_level_lessthan( - inv_idbtoken_t tok, - u_char level, - time32_t **tm ) + uuid_t *fsidp, + inv_idbtoken_t tok, + u_char level, + time32_t **tm ) { int rval; if ( tok != INV_TOKEN_NULL ) { - rval = search_invt( tok->d_invindex_fd, &level, (void **) tm, - (search_callback_t) tm_level_lessthan ); + rval = search_invt(fsidp, tok->d_invindex_fd, &level, + (void **) tm, + (search_callback_t) tm_level_lessthan); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } - return invmgr_query_all_sessions((void *) &level, /* in */ - (void **) tm, /* out */ + return invmgr_query_all_sessions(fsidp, /* fs uuid ptr*/ + (void *) &level, /* in */ + (void **) tm, /* out */ (search_callback_t) tm_level_lessthan); } - - - - /*----------------------------------------------------------------------*/ -/* */ -/* */ -/* */ +/* inv_lastsession_level_lessthan */ +/* */ +/* Given a file system uuid, token that refers to a file system, and a */ +/* level, ses is populated with a session of lesser than the level */ +/* passed in. */ +/* */ +/* Returns FALSE on an error, TRUE if not. If (*ses) is NULL, then the */ +/* search failed. */ /*----------------------------------------------------------------------*/ bool_t inv_lastsession_level_lessthan( - inv_idbtoken_t tok, + uuid_t *fsidp, + inv_idbtoken_t tok, u_char level, - inv_session_t **ses ) + inv_session_t **ses ) { int rval; if ( tok != INV_TOKEN_NULL ) { - rval = search_invt( tok->d_invindex_fd, &level, (void **) ses, - (search_callback_t) lastsess_level_lessthan ); + rval = search_invt(fsidp, tok->d_invindex_fd, &level, + (void **) ses, + (search_callback_t) lastsess_level_lessthan); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } - return invmgr_query_all_sessions((void *) &level, /* in */ + return invmgr_query_all_sessions(fsidp, /* fs uuid */ + (void *) &level, /* in */ (void **) ses, /* out */ (search_callback_t) lastsess_level_lessthan); } - - - /*----------------------------------------------------------------------*/ -/* */ -/* */ +/* inv_lastsession_level_equalto */ +/* */ +/* Given a file system uuid, token that refers to a file system, and a */ +/* level, this populates ses with last time when a session of a lesser */ +/* level was done. */ +/* */ /* Return FALSE on an error, TRUE if not. If (*ses) is NULL, then the */ /* search failed. */ /*----------------------------------------------------------------------*/ @@ -666,19 +675,22 @@ inv_lastsession_level_lessthan( bool_t inv_lastsession_level_equalto( + uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses ) { int rval; if ( tok != INV_TOKEN_NULL ) { - rval = search_invt( tok->d_invindex_fd, &level, (void **) ses, - (search_callback_t) lastsess_level_equalto ); + rval = search_invt(fsidp, tok->d_invindex_fd, &level, + (void **) ses, + (search_callback_t) lastsess_level_equalto); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } - return invmgr_query_all_sessions((void *) &level, /* in */ + return invmgr_query_all_sessions(fsidp, /* fs uuid */ + (void *) &level, /* in */ (void **) ses, /* out */ (search_callback_t) lastsess_level_equalto); @@ -688,35 +700,45 @@ inv_lastsession_level_equalto( /*----------------------------------------------------------------------*/ /* inv_getsession_byuuid */ /* */ +/* Given a file system uuid and a session uuid , ses is populated with */ +/* the session that contains the matching system uuid. */ +/* */ +/* Returns FALSE on an error, TRUE if the session was found. */ /*----------------------------------------------------------------------*/ bool_t inv_get_session_byuuid( + uuid_t *fsidp, uuid_t *sesid, inv_session_t **ses) { - return (invmgr_query_all_sessions((void *)sesid, /* in */ - (void **) ses, /* out */ - (search_callback_t) stobj_getsession_byuuid)); + return invmgr_query_all_sessions(fsidp, /* fs uuid */ + (void *) sesid, /* in */ + (void **) ses, /* out */ + (search_callback_t) stobj_getsession_byuuid); } - - /*----------------------------------------------------------------------*/ -/* inv_getsession_byuuid */ +/* inv_getsession_bylabel */ /* */ +/* Given a file system uuid and a session uuid, ses is populated with */ +/* the session that contains the matching system label. */ +/* */ +/* Returns FALSE on an error, TRUE if the session was found. */ /*----------------------------------------------------------------------*/ bool_t inv_get_session_bylabel( + uuid_t *fsidp, char *session_label, inv_session_t **ses) { - return (invmgr_query_all_sessions((void *)session_label, /* in */ - (void **) ses, /* out */ - (search_callback_t) stobj_getsession_bylabel)); + return invmgr_query_all_sessions(fsidp, /* fs uuid */ + (void *) session_label, /* in */ + (void **) ses, /* out */ + (search_callback_t) stobj_getsession_bylabel); } @@ -786,7 +808,7 @@ inv_delete_mediaobj( uuid_t *moid ) return BOOL_FALSE; } - if ( search_invt( invfd, NULL, (void **)&moid, + if ( search_invt( &arr[i].ft_uuid, invfd, NULL, (void **)&moid, (search_callback_t) stobj_delete_mobj ) < 0 ) return BOOL_FALSE; Index: b/inventory/inv_mgr.c =================================================================== --- a/inventory/inv_mgr.c +++ b/inventory/inv_mgr.c @@ -134,6 +134,7 @@ get_sesstoken( inv_idbtoken_t tok ) /*---------------------------------------------------------------------------*/ bool_t invmgr_query_all_sessions ( + uuid_t *fsidp, void *inarg, void **outarg, search_callback_t func) @@ -169,7 +170,7 @@ invmgr_query_all_sessions ( mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Cant get inv-name for uuid\n") ); - return BOOL_FALSE; + continue; } strcat( fname, INV_INVINDEX_PREFIX ); invfd = open( fname, INV_OFLAG(forwhat) ); @@ -178,9 +179,9 @@ invmgr_query_all_sessions ( "INV: Open failed on %s\n"), fname ); - return BOOL_FALSE; + continue; } - result = search_invt( invfd, inarg, &objectfound, func ); + result = search_invt(fsidp, invfd, inarg, &objectfound, func); close(invfd); /* if error return BOOL_FALSE */ @@ -213,6 +214,7 @@ invmgr_query_all_sessions ( intgen_t search_invt( + uuid_t *fsidp, int invfd, void *arg, void **buf, @@ -247,7 +249,7 @@ search_invt( /* we need to get all the invindex headers and seshdrs in reverse order */ for (i = nindices - 1; i >= 0; i--) { - int nsess; + int nsess, j; invt_sescounter_t *scnt = NULL; invt_seshdr_t *harr = NULL; bool_t found; @@ -272,19 +274,31 @@ search_invt( } free ( scnt ); - while ( nsess ) { + for (j = nsess - 1; j >= 0; j--) { + invt_session_t ses; + /* fd is kept locked until we return from the callback routine */ /* Check to see if this session has been pruned * by xfsinvutil before checking it. */ - if ( harr[nsess - 1].sh_pruned ) { - --nsess; + if (harr[j].sh_pruned) { continue; } - found = (* do_chkcriteria ) ( fd, &harr[ --nsess ], - arg, buf ); + + /* if we need to check the fs uuid's and they don't + * match or we fail to get the session record, + * then keep looking + */ + if (fsidp && + (GET_REC_NOLOCK(fd, &ses, sizeof(invt_session_t), + harr[j].sh_sess_off) == + sizeof(invt_session_t)) && + uuid_compare(ses.s_fsid, *fsidp)) + continue ; + + found = (* do_chkcriteria ) (fd, &harr[j], arg, buf); if (! found ) continue; /* we found what we need; just return */ Index: b/inventory/inv_priv.h =================================================================== --- a/inventory/inv_priv.h +++ b/inventory/inv_priv.h @@ -548,11 +548,12 @@ get_headerinfo( int fd, void **hdrs, voi size_t hdrsz, size_t cntsz, bool_t doblock ); bool_t -invmgr_query_all_sessions (void *inarg, void **outarg, search_callback_t func); +invmgr_query_all_sessions(uuid_t *fsidp, void *inarg, void **outarg, + search_callback_t func); intgen_t -search_invt( int invfd, void *arg, void **buf, - search_callback_t do_chkcriteria ); +search_invt(uuid_t *fsidp, int invfd, void *arg, void **buf, + search_callback_t do_chkcriteria); intgen_t invmgr_inv_print( int invfd, invt_pr_ctx_t *prctx); Index: b/inventory/inventory.h =================================================================== --- a/inventory/inventory.h +++ b/inventory/inventory.h @@ -247,18 +247,21 @@ inv_put_mediafile( */ extern bool_t inv_lasttime_level_lessthan( + uuid_t *fsidp, inv_idbtoken_t tok, u_char level, time32_t **time );/* out */ extern bool_t inv_lastsession_level_lessthan( + uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses );/* out */ extern bool_t inv_lastsession_level_equalto( + uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses );/* out */ @@ -266,11 +269,13 @@ inv_lastsession_level_equalto( /* Given a uuid of a session, return the session structure.*/ extern bool_t inv_get_session_byuuid( + uuid_t *fsidp, uuid_t *sesid, inv_session_t **ses); extern bool_t inv_get_session_bylabel( + uuid_t *fsidp, char *session_label, inv_session_t **ses); Index: b/restore/content.c =================================================================== --- a/restore/content.c +++ b/restore/content.c @@ -2179,8 +2179,9 @@ content_stream_restore( ix_t thrdix ) if ( ! drivep->d_isnamedpipepr && ! drivep->d_isunnamedpipepr ) { - ok = inv_get_session_byuuid( &grhdrp->gh_dumpid, - &sessp ); + ok = inv_get_session_byuuid((uuid_t *)0, + &grhdrp->gh_dumpid, + &sessp); if ( ok && sessp ) { mlog( MLOG_VERBOSE, _( "using online session inventory\n") ); @@ -3736,9 +3737,11 @@ Inv_validate_cmdline( void ) ok = BOOL_FALSE; sessp = 0; if ( tranp->t_reqdumpidvalpr ) { - ok = inv_get_session_byuuid( &tranp->t_reqdumpid, &sessp ); + ok = inv_get_session_byuuid((uuid_t *)0, &tranp->t_reqdumpid, + &sessp ); } else if ( tranp->t_reqdumplabvalpr ) { - ok = inv_get_session_bylabel( tranp->t_reqdumplab, &sessp ); + ok = inv_get_session_bylabel((uuid_t *)0, tranp->t_reqdumplab, + &sessp ); } rok = BOOL_FALSE; if ( ok && sessp ) { @@ -6812,11 +6815,13 @@ askinvforbaseof( uuid_t baseid, inv_sess /* get the base session */ if ( resumedpr ) { - ok = inv_lastsession_level_equalto( invtok, + ok = inv_lastsession_level_equalto( &sessp->s_fsid, + invtok, ( u_char_t )level, &basesessp ); } else { - ok = inv_lastsession_level_lessthan( invtok, + ok = inv_lastsession_level_lessthan( &sessp->s_fsid, + invtok, ( u_char_t )level, &basesessp ); } _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs