]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
metaplugin: Add proper skip handling to Bacula.
authorRadosław Korzeniewski <radoslaw@korzeniewski.net>
Tue, 13 Apr 2021 13:07:29 +0000 (15:07 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:01 +0000 (09:03 +0100)
This extends a metaplugin protocol with a SKIP command
in metadta streams handling, so backend can decide later
if the file should be skipped or extracted.
It update metaplugin and Bacula for a proper SKIP
command handling, so both xacl's and metadata's will
be properly skipped for backend.

bacula/src/filed/restore.c
bacula/src/findlib/bfile.c
bacula/src/plugins/fd/pluginlib/metaplugin.cpp
bacula/src/plugins/fd/pluginlib/metaplugin.h
bacula/src/plugins/fd/pluginlib/ptcomm.cpp

index 44f4b2fe4c37814e8bb9620294118f5d599580d4..1899e623e80f77330df94f37e454de36a5cf0780 100644 (file)
@@ -896,6 +896,7 @@ void do_restore(JCR *jcr)
       case STREAM_XACL_HURD_DEFAULT:
       case STREAM_XACL_HURD_ACCESS:
       case STREAM_XACL_PLUGIN_ACL:
+         // here we can simply skip this stream if rctx.extract is false, right?
       case STREAM_XACL_GPFS_ACL_DEFAULT:
       case STREAM_XACL_GPFS_ACL_ACCESS:
          /*
@@ -929,6 +930,7 @@ void do_restore(JCR *jcr)
          break;
 
       case STREAM_XACL_PLUGIN_XATTR:
+         // here we can simply skip this stream if rctx.extract is false, right?
       case STREAM_XACL_HURD_XATTR:
       case STREAM_XACL_IRIX_XATTR:
       case STREAM_XACL_TRU64_XATTR:
@@ -1031,6 +1033,7 @@ void do_restore(JCR *jcr)
       case STREAM_PLUGIN_META_BLOB:
       case STREAM_PLUGIN_META_CATALOG:
          {
+            // here we can simply skip this stream if rctx.extract is false, right?
             if (!jcr->plugin) {
                Dmsg0(10, "No plugin related to metadata packet found, metadata restore failed!\n");
                goto get_out;
@@ -1050,11 +1053,19 @@ void do_restore(JCR *jcr)
             }
 
             int rc = plug_func(jcr->plugin)->metadataRestore(jcr->plugin_ctx, &mp);
-            if (rc != bRC_OK) {
+            switch (rc)
+            {
+            case bRC_Skip:
+               Dmsg0(200, "metadata:rctx.extract = false\n");
+               rctx.extract = false;
+               bclose(&rctx.bfd);
+               break;
+            case bRC_OK:
+               break;
+            default:
                Jmsg(jcr, M_ERROR, 0, _("Plugin metadataRestore call failed, err: %d\n"), rc);
                goto get_out;
             }
-
             break;
          }
 
index 23445c7ace2edb9463908822e7621e5e2e823e4f..47273a78fdf0828b9ee4c4d4e483768977c57532 100644 (file)
@@ -152,10 +152,6 @@ const char *stream_to_ascii(int stream)
          return _("Restore Object");
       case STREAM_PLUGIN_OBJECT:
          return _("Plugin Object");
-      case STREAM_PLUGIN_META_BLOB:
-         return _("Plugin metadata (binary)");
-      case STREAM_PLUGIN_META_CATALOG:
-         return _("Plugin metadata (catalog)");
       case STREAM_XACL_AIX_TEXT:
          return _("AIX ACL attribs");
       case STREAM_XACL_DARWIN_ACCESS:
@@ -216,6 +212,10 @@ const char *stream_to_ascii(int stream)
          return _("Linux Extended attribs");
       case STREAM_XACL_NETBSD_XATTR:
          return _("NetBSD Extended attribs");
+      case STREAM_PLUGIN_META_BLOB:
+         return _("Plugin Metadata Blob");
+      case STREAM_PLUGIN_META_CATALOG:
+         return _("Plugin Metadata Catalog");
       default:
          sprintf(buf, "%d", stream);
          return (const char *)buf;
index ce3175a644b78c81d8f42f84d06dbf8b02d5ab3e..467877a2abee91c1eb9c7fcb4f9525df0b559c9c 100644 (file)
@@ -165,6 +165,7 @@ METAPLUGIN::METAPLUGIN(bpContext *bpctx) :
       pluginobjectsent(false),
       readacl(false),
       readxattr(false),
+      skipextract(false),
       fname(PM_FNAME),
       lname(PM_FNAME),
       robjbuf(NULL),
@@ -2180,6 +2181,7 @@ bRC METAPLUGIN::createFile(bpContext *ctx, struct restore_pkt *rp)
    POOL_MEM cmd(PM_FNAME);
    char type;
 
+   skipextract = false;
    if (CORELOCALRESTORE && islocalpath(where)){
       DMSG0(ctx, DDEBUG, "createFile:Forwarding restore to Core\n");
       rp->create_status = CF_CORE;
@@ -2234,6 +2236,7 @@ bRC METAPLUGIN::createFile(bpContext *ctx, struct restore_pkt *rp)
          } else
          if (strcmp(cmd.c_str(), "SKIP") == 0){
             rp->create_status = CF_SKIP;
+            skipextract = true;
          } else
          if (strcmp(cmd.c_str(), "CORE") == 0){
             rp->create_status = CF_CORE;
@@ -2296,33 +2299,40 @@ void METAPLUGIN::setup_backend_command(bpContext *ctx, POOL_MEM &exepath)
  */
 bRC METAPLUGIN::handleXACLdata(bpContext *ctx, struct xacl_pkt *xacl)
 {
-   switch (xacl->func){
-      case BACL_BACKUP:
-         if (readacl){
-            DMSG0(ctx, DINFO, "bacl_backup\n");
-            xacl->count = acldatalen;
-            xacl->content = acldata.c_str();
-            readacl= false;
-         } else {
-            xacl->count = 0;
-         }
-         break;
-      case BACL_RESTORE:
-         DMSG0(ctx, DINFO, "bacl_restore\n");
-         return perform_write_acl(ctx, xacl);
-      case BXATTR_BACKUP:
-         if (readxattr){
-            DMSG0(ctx, DINFO, "bxattr_backup\n");
-            xacl->count = xattrdatalen;
-            xacl->content = xattrdata.c_str();
-            readxattr= false;
-         } else {
-            xacl->count = 0;
+   switch (xacl->func)
+   {
+   case BACL_BACKUP:
+      if (readacl){
+         DMSG0(ctx, DINFO, "bacl_backup\n");
+         xacl->count = acldatalen;
+         xacl->content = acldata.c_str();
+         readacl= false;
+      } else {
+         xacl->count = 0;
+      }
+      break;
+   case BACL_RESTORE:
+      DMSG0(ctx, DINFO, "bacl_restore\n");
+         if (!skipextract){
+            return perform_write_acl(ctx, xacl);
          }
          break;
-      case BXATTR_RESTORE:
-         DMSG0(ctx, DINFO, "bxattr_restore\n");
+   case BXATTR_BACKUP:
+      if (readxattr){
+         DMSG0(ctx, DINFO, "bxattr_backup\n");
+         xacl->count = xattrdatalen;
+         xacl->content = xattrdata.c_str();
+         readxattr= false;
+      } else {
+         xacl->count = 0;
+      }
+      break;
+   case BXATTR_RESTORE:
+      DMSG0(ctx, DINFO, "bxattr_restore\n");
+      if (!skipextract){
          return perform_write_xattr(ctx, xacl);
+      }
+      break;
    }
 
    return bRC_OK;
@@ -2427,25 +2437,45 @@ bRC METAPLUGIN::queryParameter(bpContext *ctx, struct query_pkt *qp)
  */
 bRC METAPLUGIN::metadataRestore(bpContext *ctx, struct meta_pkt *mp)
 {
-   POOL_MEM cmd(PM_FNAME);
+   if (!skipextract){
+      POOL_MEM cmd(PM_FNAME);
 
-   if (mp->buf != NULL && mp->buf_len > 0){
-      /* send command METADATA */
-      pm_strcpy(cmd, prepare_metadata_type(mp->type));
-      backend.ctx->write_command(ctx, cmd.c_str());
-      /* send metadata stream data */
-      DMSG1(ctx, DINFO, "writeMetadata: %i\n", mp->buf_len);
-      int rc = backend.ctx->write_data(ctx, (char*)mp->buf, mp->buf_len);
-      if (rc < 0){
-         /* got some error */
-         return bRC_Error;
-      }
-      /* signal end of metadata stream to restore and get ack */
-      if (!backend.ctx->send_ack(ctx)){
-         return bRC_Error;
+      if (mp->buf != NULL && mp->buf_len > 0){
+         /* send command METADATA */
+         pm_strcpy(cmd, prepare_metadata_type(mp->type));
+         backend.ctx->write_command(ctx, cmd.c_str());
+         /* send metadata stream data */
+         DMSG1(ctx, DINFO, "writeMetadata: %i\n", mp->buf_len);
+         int rc = backend.ctx->write_data(ctx, (char*)mp->buf, mp->buf_len);
+         if (rc < 0){
+            /* got some error */
+            return bRC_Error;
+         }
+
+         // signal end of metadata stream to restore and get ack
+         backend.ctx->signal_eod(ctx);
+
+         // check if backend accepted the file
+         if (backend.ctx->read_command(ctx, cmd) > 0) {
+            DMSG(ctx, DINFO, "metadataRestore:resp: %s\n", cmd.c_str());
+            if (bstrcmp(cmd.c_str(), "SKIP")) {
+               // SKIP!
+               skipextract = true;
+               return bRC_Skip;
+            }
+            if (!bstrcmp(cmd.c_str(), "OK")) {
+               DMSG(ctx, DERROR, "Wrong backend response to metadataRestore, got: %s\n", cmd.c_str());
+               JMSG(ctx, backend.ctx->jmsg_err_level(), "Wrong backend response to metadataRestore, got: %s\n", cmd.c_str());
+               return bRC_Error;
+            }
+         } else {
+            if (backend.ctx->is_error()) {
+               // raise up error from backend
+               return bRC_Error;
+            }
+         }
       }
    }
-
    return bRC_OK;
 }
 
index 6ebeff31a0b40226439aca87305e1725cd8ecbdb..a91bf7a3bb53f292e31c1f2fad5596d493ffa48f 100644 (file)
@@ -154,6 +154,7 @@ private:
    bool pluginobjectsent;        // set when startBackupFile handled plugin object and endBackupFile has to check for nextfile
    bool readacl;                 // got ACL data from backend
    bool readxattr;               // got XATTR data from backend
+   bool skipextract;             // got SKIP response from backend, so we should artificially skip it for backend
    COMMCTX<PTCOMM> backend;      // the backend context list for multiple backend execution for a single job
    POOL_MEM fname;               // current file name to backup (grabbed from backend)
    POOL_MEM lname;               // current LSTAT data if any
index 01096624046ab03d49dd79a6e382e87269ac223b..88f1cad59d26d051104fe0225d1853ab043d84ac 100644 (file)
@@ -791,7 +791,7 @@ bool PTCOMM::send_ack(bpContext *ctx)
 
    // check if backend response with OK
    if (bstrcmp(buf.c_str(), "OK")){
-      // great ACk confirmed
+      // great ACK confirmed
       return true;
    }