All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] xfsrestore: fix fs uuid order check for incremental restores
@ 2015-08-26 16:27 Rich Johnston
  2015-08-26 21:31 ` Dave Chinner
  2015-08-26 22:53 ` Rich Johnston
  0 siblings, 2 replies; 13+ messages in thread
From: Rich Johnston @ 2015-08-26 16:27 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: fix-fs-uuid-order-check.patch --]
[-- Type: text/plain, Size: 17522 bytes --]

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>
---
 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@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] xfsrestore: fix fs uuid order check for incremental restores
  2015-08-26 16:27 [PATCH] xfsrestore: fix fs uuid order check for incremental restores Rich Johnston
@ 2015-08-26 21:31 ` Dave Chinner
  2015-08-26 22:53 ` Rich Johnston
  1 sibling, 0 replies; 13+ messages in thread
From: Dave Chinner @ 2015-08-26 21:31 UTC (permalink / raw)
  To: Rich Johnston; +Cc: xfs

On Wed, Aug 26, 2015 at 11:27:12AM -0500, Rich Johnston wrote:
> 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>
> ---
>  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) "

This patch has whitespace problems all through it (bad indenting,
all tabs converted to spaces, etc) and so it won't apply. Please fix
and resend.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] xfsrestore: fix fs uuid order check for incremental restores
  2015-08-26 16:27 [PATCH] xfsrestore: fix fs uuid order check for incremental restores Rich Johnston
  2015-08-26 21:31 ` Dave Chinner
@ 2015-08-26 22:53 ` Rich Johnston
  2015-09-01 19:36   ` Rich Johnston
  2015-09-02 13:21   ` [RESEND PATCH] " Brian Foster
  1 sibling, 2 replies; 13+ messages in thread
From: Rich Johnston @ 2015-08-26 22:53 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: fix-fs-uuid-order-check.patch --]
[-- Type: text/plain, Size: 15099 bytes --]

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>
---
 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@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] xfsrestore: fix fs uuid order check for incremental restores
  2015-08-26 22:53 ` Rich Johnston
@ 2015-09-01 19:36   ` Rich Johnston
  2015-09-02 13:21   ` [RESEND PATCH] " Brian Foster
  1 sibling, 0 replies; 13+ messages in thread
From: Rich Johnston @ 2015-09-01 19:36 UTC (permalink / raw)
  To: xfs

ping, Does anyone have time to review this please?

Thanks
--Rich

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RESEND PATCH] xfsrestore: fix fs uuid order check for incremental restores
  2015-08-26 22:53 ` Rich Johnston
  2015-09-01 19:36   ` Rich Johnston
@ 2015-09-02 13:21   ` Brian Foster
  2015-09-02 18:49     ` Rich Johnston
                       ` (2 more replies)
  1 sibling, 3 replies; 13+ messages in thread
From: Brian Foster @ 2015-09-02 13:21 UTC (permalink / raw)
  To: Rich Johnston; +Cc: xfs

On Tue, Sep 01, 2015 at 03:38:29PM -0500, Rich Johnston wrote:
> 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>
> ---

I'm not really familiar with xfsdump, but a few comments below...

>  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/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;
>  		}

Now that the above two cases don't return false, we can end up returning
true if these error cases persist throughout the loop. Perhaps we should
define 'bool ret = false,' return that variable everywhere and only set
it true when appropriate.

> -		result = search_invt( invfd, inarg, &objectfound, func );
> +		result = search_invt(fsidp, invfd, inarg, &objectfound, func);
>  		close(invfd);		
>  
>  		/* if error return BOOL_FALSE */
...
> @@ -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 ;
> +

This seems like kind of a loaded check. GET_REC_NOLOCK() looks like it
returns -1 if the read doesn't return the exact size of the buffer, so
we probably don't need to check that here. It also seems like we should
return an error if an error occurs rather than just continue on. How
about something like this?

			...
			if (fsidp) {
				ret = GET_REC_NOLOCK(fd, &ses,
						     sizeof(invt_session_t),
						     harr[j].sh_sess_off);
				if (ret < 0) {
					/* XXX: clean up here */
					return ret;
				}
				ret = uuid_compare(ses.s_fsid, *fsidp);
				if (ret)
					continue;
			}

> +			found = (* do_chkcriteria ) (fd, &harr[j], arg, buf);
>  			if (! found ) continue;
>  			
>  			/* we found what we need; just return */
...
> 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 );

Can we use NULL instead of 0 in these cases? Not sure the cast is really
necessary either..?.

Brian

>  	}
>  	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@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RESEND PATCH] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-02 13:21   ` [RESEND PATCH] " Brian Foster
@ 2015-09-02 18:49     ` Rich Johnston
  2015-09-03 14:07     ` [PATCH V2] " Rich Johnston
  2015-09-03 23:43     ` [PATCH V3] " Rich Johnston
  2 siblings, 0 replies; 13+ messages in thread
From: Rich Johnston @ 2015-09-02 18:49 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On 09/02/2015 08:21 AM, Brian Foster wrote:
> On Tue, Sep 01, 2015 at 03:38:29PM -0500, Rich Johnston wrote:
>> 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>
>> ---
>
> I'm not really familiar with xfsdump, but a few comments below...
>
>>   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/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;
>>   		}
>
> Now that the above two cases don't return false, we can end up returning
> true if these error cases persist throughout the loop.
Yes I missed that case.
> Perhaps we should
> define 'bool ret = false,' return that variable everywhere and only set
> it true when appropriate.
Good suggestion.
>
>> -		result = search_invt( invfd, inarg, &objectfound, func );
>> +		result = search_invt(fsidp, invfd, inarg, &objectfound, func);
>>   		close(invfd);		
>>
>>   		/* if error return BOOL_FALSE */
> ...
>> @@ -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 ;
>> +
>
> This seems like kind of a loaded check. GET_REC_NOLOCK() looks like it
> returns -1 if the read doesn't return the exact size of the buffer, so
> we probably don't need to check that here. It also seems like we should
> return an error if an error occurs rather than just continue on. How
> about something like this?
Sounds reasonable, would be more readable.
>
> 			...
> 			if (fsidp) {
> 				ret = GET_REC_NOLOCK(fd, &ses,
> 						     sizeof(invt_session_t),
> 						     harr[j].sh_sess_off);
> 				if (ret < 0) {
> 					/* XXX: clean up here */
> 					return ret;
> 				}
> 				ret = uuid_compare(ses.s_fsid, *fsidp);
> 				if (ret)
> 					continue;
> 			}
>
>> +			found = (* do_chkcriteria ) (fd, &harr[j], arg, buf);
>>   			if (! found ) continue;
>>   			
>>   			/* we found what we need; just return */
> ...
>> 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 );
>
> Can we use NULL instead of 0 in these cases? Not sure the cast is really
> necessary either..?.
I will check that out, if NULL works I will make that change.

Thanks for your time
--Rich
>
> Brian
>
>>   	}
>>   	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@oss.sgi.com
>> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V2] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-02 13:21   ` [RESEND PATCH] " Brian Foster
  2015-09-02 18:49     ` Rich Johnston
@ 2015-09-03 14:07     ` Rich Johnston
  2015-09-03 14:23       ` Rich Johnston
  2015-09-03 23:43     ` [PATCH V3] " Rich Johnston
  2 siblings, 1 reply; 13+ messages in thread
From: Rich Johnston @ 2015-09-03 14:07 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs-oss

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

To: <xfs@oss.sgi.com>
BCC: Rich Johnston <rjohnston@sgi.com>
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>
---
  dump/content.c        |    8 ++-
  inventory/inv_api.c   |  108 
++++++++++++++++++++++++++++++--------------------
  inventory/inv_mgr.c   |   48 +++++++++++++++-------
  inventory/inv_priv.h  |    7 +--
  inventory/inventory.h |    5 ++
  restore/content.c     |   17 +++++--
  6 files changed, 124 insertions(+), 69 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)
@@ -145,6 +146,7 @@ invmgr_query_all_sessions (
  	int result;
  	inv_oflag_t forwhat = INV_SEARCH_ONLY;
  	void *objectfound;
+	bool ret = false;
   	/* if on return, this is still null, the search failed */
  	*outarg = NULL; @@ -153,11 +155,11 @@ invmgr_query_all_sessions (
  	fd = fstab_getall( &arr, &cnt, &numfs, forwhat );
  	/* special case missing file: ok, outarg says zero */
  	if ( fd < 0 && errno == ENOENT ) {
-		return BOOL_TRUE;
+		return true;
  	}
  	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,26 +180,27 @@ 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 */
  		if (result < 0) {
-			return BOOL_FALSE;
+			return ret;
  		} else if ((result == 1) && *outarg) {
  			/* multiple entries found,  more info needed */
  			*outarg = NULL;
-			return BOOL_TRUE;
+			return true;
  		} else if (result == 1) {
  			*outarg = objectfound;
+			ret = true;
  		}
  	}
  	
  	/* return val indicates if there was an error or not. *buf
  	   says whether the search was successful */
-	return BOOL_TRUE;
+	return ret;
  }
   @@ -213,6 +216,7 @@ invmgr_query_all_sessions (
   intgen_t
  search_invt( +	uuid_t			*fsidp,
  	int 			invfd,
  	void 			*arg,  	void 			**buf,
@@ -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,35 @@ 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 */
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(NULL,
+						    &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(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,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@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH V2] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-03 14:07     ` [PATCH V2] " Rich Johnston
@ 2015-09-03 14:23       ` Rich Johnston
  0 siblings, 0 replies; 13+ messages in thread
From: Rich Johnston @ 2015-09-03 14:23 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs-oss

Please disregard, not what I meat to send.

--Rich

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-02 13:21   ` [RESEND PATCH] " Brian Foster
  2015-09-02 18:49     ` Rich Johnston
  2015-09-03 14:07     ` [PATCH V2] " Rich Johnston
@ 2015-09-03 23:43     ` Rich Johnston
  2015-09-08 12:47       ` Brian Foster
  2 siblings, 1 reply; 13+ messages in thread
From: Rich Johnston @ 2015-09-03 23:43 UTC (permalink / raw)
  To: bfoster; +Cc: xfs

[-- Attachment #1: xfsrestore-fix-fs-uuid-order-check-for-incremental-restores.patch --]
[-- Type: text/plain, Size: 17505 bytes --]

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>
---

Changelog
V2 wrong file sent

V3
 Address review comments from Brian:

 fix invmgr_query_all_sessions() returning true if these error cases
 persist throughout the loop

 make if check more readable and less overloaded in search_inv() and
 return an error if GET_REC_NOLOCK() fails

 use NULL instead of (uuid_t *)0 in Inv_validate_cmdline()

 remove any spaces around braces of code that was changed

 dump/content.c        |   16 +++---
 inventory/inv_api.c   |  130 +++++++++++++++++++++++++++++---------------------
 inventory/inv_mgr.c   |   55 ++++++++++++++-------
 inventory/inv_priv.h  |    7 +-
 inventory/inventory.h |   21 +++++---
 restore/content.c     |   23 +++++---
 6 files changed, 152 insertions(+), 100 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,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 ) {
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 */
-			       (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 */
Index: b/inventory/inv_mgr.c
===================================================================
--- 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,26 +180,27 @@ 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 */
 		if (result < 0) {
-			return BOOL_FALSE;
+			return ret;
 		} else if ((result == 1) && *outarg) {
 			/* multiple entries found,  more info needed */
 			*outarg = NULL;
 			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 */
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,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 */
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(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_sess
 	/* 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, _(

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH V3] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-03 23:43     ` [PATCH V3] " Rich Johnston
@ 2015-09-08 12:47       ` Brian Foster
  2015-09-11 17:01         ` Rich Johnston
  2015-09-11 17:14         ` [PATCH V4] " Rich Johnston
  0 siblings, 2 replies; 13+ messages in thread
From: Brian Foster @ 2015-09-08 12:47 UTC (permalink / raw)
  To: Rich Johnston; +Cc: xfs

On Thu, Sep 03, 2015 at 06:43:46PM -0500, Rich Johnston wrote:
> 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>
> ---
> 
> Changelog
> V2 wrong file sent
> 
> V3
>  Address review comments from Brian:
> 
>  fix invmgr_query_all_sessions() returning true if these error cases
>  persist throughout the loop
> 
>  make if check more readable and less overloaded in search_inv() and
>  return an error if GET_REC_NOLOCK() fails
> 
>  use NULL instead of (uuid_t *)0 in Inv_validate_cmdline()
> 
>  remove any spaces around braces of code that was changed
> 
>  dump/content.c        |   16 +++---
>  inventory/inv_api.c   |  130 +++++++++++++++++++++++++++++---------------------
>  inventory/inv_mgr.c   |   55 ++++++++++++++-------
>  inventory/inv_priv.h  |    7 +-
>  inventory/inventory.h |   21 +++++---
>  restore/content.c     |   23 +++++---
>  6 files changed, 152 insertions(+), 100 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,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 ) {
> 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 */
> -			       (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 */

This doesn't compile because of a missing comma after fsidp above.

> +					 (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 */
> Index: b/inventory/inv_mgr.c
> ===================================================================
> --- 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,26 +180,27 @@ 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 */
>  		if (result < 0) {
> -			return BOOL_FALSE;
> +			return ret;

Should this always return false? It's now possible to return true if an
error occurs after we've found one object.

The rest seems Ok to me.

Brian

>  		} else if ((result == 1) && *outarg) {
>  			/* multiple entries found,  more info needed */
>  			*outarg = NULL;
>  			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 */
> 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,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 */
> 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(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_sess
>  	/* 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, _(
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH V3] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-08 12:47       ` Brian Foster
@ 2015-09-11 17:01         ` Rich Johnston
  2015-09-11 17:14         ` [PATCH V4] " Rich Johnston
  1 sibling, 0 replies; 13+ messages in thread
From: Rich Johnston @ 2015-09-11 17:01 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On 09/08/2015 07:47 AM, Brian Foster wrote:
> On Thu, Sep 03, 2015 at 06:43:46PM -0500, Rich Johnston wrote:
>> 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.

...

>> Index: b/inventory/inv_api.c
>> ===================================================================
>> --- a/inventory/inv_api.c
>> +++ b/inventory/inv_api.c
>> @@ -596,69 +596,78 @@ inv_free_session(

...

>>
>> -	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 */
>
> This doesn't compile because of a missing comma after fsidp above.
>
My mistake, happened while cleaning up whitespace.
...

>> Index: b/inventory/inv_mgr.c
>> ===================================================================
>> --- a/inventory/inv_mgr.c
>> +++ b/inventory/inv_mgr.c

...

>> @@ -178,26 +180,27 @@ 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 */
>>   		if (result < 0) {
>> -			return BOOL_FALSE;
>> +			return ret;
>
> Should this always return false? It's now possible to return true if an
> error occurs after we've found one object.

*nod* Thanks I missed that one.

I'll have a V4 out shortly.

--Rich
>
> The rest seems Ok to me.
>
> Brian
>

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V4] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-08 12:47       ` Brian Foster
  2015-09-11 17:01         ` Rich Johnston
@ 2015-09-11 17:14         ` Rich Johnston
  2015-09-11 19:22           ` Brian Foster
  1 sibling, 1 reply; 13+ messages in thread
From: Rich Johnston @ 2015-09-11 17:14 UTC (permalink / raw)
  To: bfoster; +Cc: xfs

[-- Attachment #1: xfsrestore-fix-fs-uuid-order-check-for-incremental-restores-v4.patch --]
[-- Type: text/plain, Size: 17571 bytes --]

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>
---

Changelog
V2 wrong file sent

V3
 Address review comments from Brian:

 fix invmgr_query_all_sessions() returning true if these error cases
 persist throughout the loop

 make if check more readable and less overloaded in search_inv() and
 return an error if GET_REC_NOLOCK() fails

 use NULL instead of (uuid_t *)0 in Inv_validate_cmdline()

 remove any spaces around braces of code that was changed

V4
 fix compile error introduced when I removed any spaces around braces of
 code that was changed and cleaning up whitespace.

 we should be returning BOOL_FALSE on any errors. I missed one.

 dump/content.c        |   16 +++---
 inventory/inv_api.c   |  130 +++++++++++++++++++++++++++++---------------------
 inventory/inv_mgr.c   |   53 +++++++++++++-------
 inventory/inv_priv.h  |    7 +-
 inventory/inventory.h |   21 +++++---
 restore/content.c     |   23 +++++---
 6 files changed, 151 insertions(+), 99 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,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 ) {
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 */
-			       (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 */
Index: b/inventory/inv_mgr.c
===================================================================
--- 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 */
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,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 */
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(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_sess
 	/* 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, _(

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH V4] xfsrestore: fix fs uuid order check for incremental restores
  2015-09-11 17:14         ` [PATCH V4] " Rich Johnston
@ 2015-09-11 19:22           ` Brian Foster
  0 siblings, 0 replies; 13+ messages in thread
From: Brian Foster @ 2015-09-11 19:22 UTC (permalink / raw)
  To: Rich Johnston; +Cc: xfs

On Fri, Sep 11, 2015 at 12:14:50PM -0500, Rich Johnston wrote:
> 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>
> ---

Looks fine to me:

Reviewed-by: Brian Foster <bfoster@redhat.com>

> 
> Changelog
> V2 wrong file sent
> 
> V3
>  Address review comments from Brian:
> 
>  fix invmgr_query_all_sessions() returning true if these error cases
>  persist throughout the loop
> 
>  make if check more readable and less overloaded in search_inv() and
>  return an error if GET_REC_NOLOCK() fails
> 
>  use NULL instead of (uuid_t *)0 in Inv_validate_cmdline()
> 
>  remove any spaces around braces of code that was changed
> 
> V4
>  fix compile error introduced when I removed any spaces around braces of
>  code that was changed and cleaning up whitespace.
> 
>  we should be returning BOOL_FALSE on any errors. I missed one.
> 
>  dump/content.c        |   16 +++---
>  inventory/inv_api.c   |  130 +++++++++++++++++++++++++++++---------------------
>  inventory/inv_mgr.c   |   53 +++++++++++++-------
>  inventory/inv_priv.h  |    7 +-
>  inventory/inventory.h |   21 +++++---
>  restore/content.c     |   23 +++++---
>  6 files changed, 151 insertions(+), 99 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,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 ) {
> 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 */
> -			       (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 */
> Index: b/inventory/inv_mgr.c
> ===================================================================
> --- 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 */
> 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,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 */
> 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(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_sess
>  	/* 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, _(
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-09-11 19:22 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-26 16:27 [PATCH] xfsrestore: fix fs uuid order check for incremental restores Rich Johnston
2015-08-26 21:31 ` Dave Chinner
2015-08-26 22:53 ` Rich Johnston
2015-09-01 19:36   ` Rich Johnston
2015-09-02 13:21   ` [RESEND PATCH] " Brian Foster
2015-09-02 18:49     ` Rich Johnston
2015-09-03 14:07     ` [PATCH V2] " Rich Johnston
2015-09-03 14:23       ` Rich Johnston
2015-09-03 23:43     ` [PATCH V3] " Rich Johnston
2015-09-08 12:47       ` Brian Foster
2015-09-11 17:01         ` Rich Johnston
2015-09-11 17:14         ` [PATCH V4] " Rich Johnston
2015-09-11 19:22           ` Brian Foster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.