aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Johnston <rjohnston@sgi.com>2015-10-14 11:50:23 +1100
committerDave Chinner <david@fromorbit.com>2015-10-14 11:50:23 +1100
commitbe93e5205b4d2d4a40cc2aaeb192412f1f6871de (patch)
tree5689fa198f12d889d80cd6f51b0a8b78ae5b712a
parent33ff057dedd266c2d02a23b1dda979e7c8bacdcc (diff)
downloadxfsdump-dev-be93e5205b4d2d4a40cc2aaeb192412f1f6871de.tar.gz
xfsrestore: fix fs uuid order check for incremental restores
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@sgi.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--dump/content.c16
-rw-r--r--inventory/inv_api.c130
-rw-r--r--inventory/inv_mgr.c53
-rw-r--r--inventory/inv_priv.h7
-rw-r--r--inventory/inventory.h21
-rw-r--r--restore/content.c23
6 files changed, 151 insertions, 99 deletions
diff --git a/dump/content.c b/dump/content.c
index ac190219..5f7b4d91 100644
--- 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,9 +983,10 @@ content_init( intgen_t argc,
"online inventory not available\n") );
return BOOL_FALSE;
}
- ok = inv_lastsession_level_lessthan( inv_idbt,
- ( u_char_t )sc_level,
- &sessp );
+ ok = inv_lastsession_level_lessthan(&fsid,
+ inv_idbt,
+ (u_char_t)sc_level,
+ &sessp);
if ( ! ok ) {
sessp = 0;
}
@@ -1022,9 +1023,10 @@ content_init( intgen_t argc,
if ( inv_idbt != INV_TOKEN_NULL ) {
/* REFERENCED */
bool_t ok1;
- ok = inv_lastsession_level_equalto( inv_idbt,
- ( u_char_t )sc_level,
- &sessp );
+ ok = inv_lastsession_level_equalto(&fsid,
+ inv_idbt,
+ (u_char_t)sc_level,
+ &sessp);
ok1 = inv_close( inv_idbt );
ASSERT( ok1 );
if ( ! ok ) {
diff --git a/inventory/inv_api.c b/inventory/inv_api.c
index b48c6d3e..65102e6d 100644
--- 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 */
- (search_callback_t) tm_level_lessthan);
+ 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 */
- (void **) ses, /* out */
- (search_callback_t) lastsess_level_lessthan);
+ 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,21 +675,24 @@ inv_lastsession_level_lessthan(
bool_t
inv_lastsession_level_equalto(
- inv_idbtoken_t tok,
+ 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 */
- (void **) ses, /* out */
- (search_callback_t) lastsess_level_equalto);
+ 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 *sesid,
- inv_session_t **ses)
+ 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(
- char *session_label,
- inv_session_t **ses)
+ 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,8 +808,8 @@ inv_delete_mediaobj( uuid_t *moid )
return BOOL_FALSE;
}
- if ( search_invt( invfd, NULL, (void **)&moid,
- (search_callback_t) stobj_delete_mobj )
+ if (search_invt(&arr[i].ft_uuid, invfd, NULL, (void **)&moid,
+ (search_callback_t)stobj_delete_mobj)
< 0 )
return BOOL_FALSE;
/* we have to delete the session, etc */
diff --git a/inventory/inv_mgr.c b/inventory/inv_mgr.c
index b9851c33..1f4a4256 100644
--- a/inventory/inv_mgr.c
+++ b/inventory/inv_mgr.c
@@ -134,8 +134,9 @@ get_sesstoken( inv_idbtoken_t tok )
/*---------------------------------------------------------------------------*/
bool_t
invmgr_query_all_sessions (
- void *inarg,
- void **outarg,
+ uuid_t *fsidp,
+ void *inarg,
+ void **outarg,
search_callback_t func)
{
invt_counter_t *cnt;
@@ -145,6 +146,7 @@ invmgr_query_all_sessions (
int result;
inv_oflag_t forwhat = INV_SEARCH_ONLY;
void *objectfound;
+ bool_t ret = BOOL_FALSE;
/* if on return, this is still null, the search failed */
*outarg = NULL;
@@ -157,7 +159,7 @@ invmgr_query_all_sessions (
}
if ( fd < 0 || numfs <= 0 ) {
mlog( MLOG_NORMAL | MLOG_INV, _("INV: Error in fstab\n") );
- return BOOL_FALSE;
+ return ret;
}
close( fd );
@@ -169,7 +171,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 +180,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 */
@@ -192,12 +194,13 @@ invmgr_query_all_sessions (
return BOOL_TRUE;
} else if (result == 1) {
*outarg = objectfound;
+ ret = BOOL_TRUE;
}
}
/* return val indicates if there was an error or not. *buf
says whether the search was successful */
- return BOOL_TRUE;
+ return ret;
}
@@ -213,10 +216,11 @@ invmgr_query_all_sessions (
intgen_t
search_invt(
- int invfd,
- void *arg,
- void **buf,
- search_callback_t do_chkcriteria )
+ uuid_t *fsidp,
+ int invfd,
+ void *arg,
+ void **buf,
+ search_callback_t do_chkcriteria)
{
int fd, i;
@@ -247,7 +251,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 +276,34 @@ 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) {
+ int ret = GET_REC_NOLOCK(fd, &ses,
+ sizeof(invt_session_t),
+ harr[j].sh_sess_off);
+ if (ret < 0)
+ return ret;
+ if (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 */
diff --git a/inventory/inv_priv.h b/inventory/inv_priv.h
index 487f6783..8817b5e8 100644
--- a/inventory/inv_priv.h
+++ b/inventory/inv_priv.h
@@ -548,11 +548,12 @@ get_headerinfo( int fd, void **hdrs, void **cnt,
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);
diff --git a/inventory/inventory.h b/inventory/inventory.h
index 0da8b25b..32156dd1 100644
--- a/inventory/inventory.h
+++ b/inventory/inventory.h
@@ -247,32 +247,37 @@ inv_put_mediafile(
*/
extern bool_t
inv_lasttime_level_lessthan(
+ uuid_t *fsidp,
inv_idbtoken_t tok,
- u_char level,
- time32_t **time );/* out */
+ 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 */
+ 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 */
+ inv_session_t **ses); /* out */
/* Given a uuid of a session, return the session structure.*/
extern bool_t
inv_get_session_byuuid(
- uuid_t *sesid,
- inv_session_t **ses);
+ uuid_t *fsidp,
+ uuid_t *sesid,
+ inv_session_t **ses);
extern bool_t
inv_get_session_bylabel(
- char *session_label,
- inv_session_t **ses);
+ uuid_t *fsidp,
+ char *session_label,
+ inv_session_t **ses);
/* on return, *ses is NULL */
diff --git a/restore/content.c b/restore/content.c
index cfcf94de..f2d361b4 100644
--- 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(NULL,
+ &grhdrp->gh_dumpid,
+ &sessp);
if ( ok && sessp ) {
mlog( MLOG_VERBOSE, _(
"using online session inventory\n") );
@@ -3736,9 +3737,9 @@ 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(NULL, &tranp->t_reqdumpid, &sessp);
} else if ( tranp->t_reqdumplabvalpr ) {
- ok = inv_get_session_bylabel( tranp->t_reqdumplab, &sessp );
+ ok = inv_get_session_bylabel(NULL, tranp->t_reqdumplab, &sessp);
}
rok = BOOL_FALSE;
if ( ok && sessp ) {
@@ -6812,13 +6813,15 @@ askinvforbaseof( uuid_t baseid, inv_session_t *sessp )
/* get the base session
*/
if ( resumedpr ) {
- ok = inv_lastsession_level_equalto( invtok,
- ( u_char_t )level,
- &basesessp );
+ ok = inv_lastsession_level_equalto(&sessp->s_fsid,
+ invtok,
+ (u_char_t)level,
+ &basesessp);
} else {
- ok = inv_lastsession_level_lessthan( invtok,
- ( u_char_t )level,
- &basesessp );
+ ok = inv_lastsession_level_lessthan(&sessp->s_fsid,
+ invtok,
+ (u_char_t)level,
+ &basesessp);
}
if ( ! ok ) {
mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _(