]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Add GPFS ACL/XATTR Support
authorEric Bollengier <eric@baculasystems.com>
Wed, 15 Jul 2020 15:01:23 +0000 (17:01 +0200)
committerEric Bollengier <eric@baculasystems.com>
Tue, 1 Mar 2022 14:36:17 +0000 (15:36 +0100)
Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Tue Jul 14 11:13:36 2020 +0000

    regress: GPFS regression test scripts

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Tue Jul 14 11:13:06 2020 +0000

    gpfs: Fix for incorrect Default ACL handling

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Tue Jul 14 10:32:30 2020 +0000

    regress: WIP: GPFS regression

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Mon Jul 13 12:29:17 2020 +0000

    regress: GPFS regression tests

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Mon Jul 13 08:54:38 2020 +0000

    regress: Add gpfs regress test config variable

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Fri Jul 10 14:22:36 2020 +0000

    regress: Fix regress-utils.sh script

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Fri Jul 10 13:45:46 2020 +0000

    Fix broken configure for ACL/AFS detection

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Fri Jul 10 12:25:48 2020 +0000

    gpfs: GPFS ACL restore

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Fri Jul 10 10:43:43 2020 +0000

    gpfs: GPFS ACL restore

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Thu Jul 9 14:27:09 2020 +0000

    gpfs: General GPFS ACL backup ready

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Thu Jul 9 10:15:57 2020 +0000

    gpfs: Update build for GPFS/AFS dependency count

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Thu Jun 25 03:24:30 2020 -0400

    gpfs: Fix gpfslib loading routine

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Jun 24 10:47:53 2020 -0400

    gpfs: GPFS support update build

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Jun 24 07:37:46 2020 -0400

    gpfs: GPFS support

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Jun 24 07:10:31 2020 -0400

    gpfs: Create GPFSLIB as a singleton

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Jun 24 03:35:48 2020 -0400

    Fix compilation warning

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Tue Jun 23 11:51:40 2020 -0400

    gpfs: GPFS lib dynamic load

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Mon Jun 22 16:46:03 2020 +0200

    gpfs: gpfs acl

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Mon Jun 22 09:59:26 2020 -0400

    gpfs: gpfs acl

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Thu Apr 9 10:01:14 2020 -0400

    fstype: Update FS type handling functions

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Apr 8 13:36:11 2020 -0400

    gpfs: Untested GPFS ACL routines

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Apr 8 11:53:33 2020 -0400

    gpfs: Add GPFS libs detection

Author: Radosław Korzeniewski <radekk@inteos.pl>
Date:   Wed Apr 8 11:52:21 2020 -0400

    gpfs: Define GPFS streams

13 files changed:
bacula/src/filed/Makefile.in
bacula/src/filed/bacgpfs.c [new file with mode: 0644]
bacula/src/filed/bacgpfs.h [new file with mode: 0644]
bacula/src/filed/bacl.c
bacula/src/filed/bacl.h
bacula/src/filed/bxattr.c
bacula/src/filed/bxattr.h
bacula/src/filed/filed.c
bacula/src/filed/filed.h
bacula/src/filed/restore.c
bacula/src/findlib/fstype.c
bacula/src/findlib/protos.h
bacula/src/streams.h

index dffac2f32b600b4eadb630b447e222c10aeee1d3..5fa00b7b2d223d142bb3adc8dd2e5ffacea68359 100644 (file)
@@ -25,6 +25,7 @@ GETTEXT_LIBS = @LIBINTL@
 
 AFS_CFLAGS = @AFS_CFLAGS@
 AFS_LIBS = @AFS_LIBS@
+GPFS_CFLAGS = @GPFS_CFLAGS@
 ACLOBJS = @ACLOBJS@
 XATTROBJS = @XATTROBJS@
 IOKITLIBS = @IOKITLIBS@
@@ -37,7 +38,7 @@ dummy:
 #
 SVRSRCS = filed.c authenticate.c backup.c crypto.c \
          win_efs.c estimate.c fdcollect.c \
-         fd_plugins.c accurate.c \
+         fd_plugins.c accurate.c bacgpfs.c \
          filed_conf.c runres_conf.c heartbeat.c hello.c job.c fd_snapshot.c \
          restore.c status.c verify.c verify_vol.c fdcallsdir.c suspend.c $(EXTRA_SRCS) \
          $(ACLOBJS) $(XATTROBJS)
@@ -50,7 +51,7 @@ JSONOBJS = bfdjson.o filed_conf.o runres_conf.o
 EXTRAOBJS = @OBJLIST@
 
 CAP_LIBS = @CAP_LIBS@
-FDLIBS = @FDLIBS@                # extra libs for File daemon
+FDLIBS = @FDLIBS@           # extra libs for File daemon
 ZLIBS = @ZLIBS@
 LZO_LIBS = @LZO_LIBS@
 LZO_INC= @LZO_INC@
@@ -74,9 +75,17 @@ all: Makefile @WIN32@ bacula-fd @STATIC_FD@ bfdjson
        @echo "==== Make of filed is good ===="
        @echo " "
 
-bacl.o: bacl.c
+bacgpfs.o: bacgpfs.c bacgpfs.h
        @echo "Compiling $<"
-       $(NO_ECHO)$(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(LZO_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $(AFS_CFLAGS) $<
+       $(NO_ECHO)$(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(LZO_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $(AFS_CFLAGS) $(GPFS_CFLAGS) $<
+
+bacl.o: bacl.c bacgpfs.o
+       @echo "Compiling $<"
+       $(NO_ECHO)$(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(LZO_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $(AFS_CFLAGS)$<
+
+bxattr.o: bxattr.c bacgpfs.o
+       @echo "Compiling $<"
+       $(NO_ECHO)$(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(LZO_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS)$<
 
 win32/winlib.a:
        @if test -f win32/Makefile -a "${GMAKE}" != "none"; then \
diff --git a/bacula/src/filed/bacgpfs.c b/bacula/src/filed/bacgpfs.c
new file mode 100644 (file)
index 0000000..40fac54
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2020 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+/*
+ * This is a Bacula support for GPFS.
+ * Author: Radoslaw Korzeniewski, radekk@inteos.pl, Inteos Sp. z o.o.
+ */
+
+#include "bacula.h"
+#include "filed.h"
+#ifdef HAVE_SYS_TYPES_H
+   #include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+   #include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+   #include <unistd.h>
+#endif
+
+#ifdef HAVE_DLFCN_H
+   #include <dlfcn.h>
+#endif
+
+
+#if defined(HAVE_LINUX_OS)
+   #define GPFSLIB_LIB        "libgpfs.so"
+   #define GPFSLIB_PATH       "/usr/lpp/mmfs/lib/libgpfs.so"
+#elif defined(HAVE_AIX_OS)
+   #define GPFSLIB_LIB        "libgpfs.a"
+   #define GPFSLIB_PATH       "/usr/lpp/mmfs/lib/libgpfs.a"
+#endif
+
+
+/**
+ * @brief
+ *
+ */
+void GPFSLIB::initialize()
+{
+#if defined(HAVE_GPFS_ACL) && defined(HAVE_DLFCN_H)
+#ifdef HAVE_LINUX_OS
+
+   /**
+    * @brief The static location of the library and search list
+    */
+   static const char * gpfslib_paths[] =
+   {
+#if defined(GPFSLIB_CUSTOM_PATH)
+      GPFSLIB_CUSTOM_PATH,
+#endif
+      GPFSLIB_PATH,
+      GPFSLIB_LIB,
+      NULL,
+   };
+
+   const char * gpfs_path;
+   bool still_search = true;
+   int path_indx = 0;
+   const char * _path = gpfslib_paths[path_indx];
+
+   // iterate through all library locations
+   while (still_search){
+      gpfs_path = _path;
+      Dmsg1(200, "Try to load GPFS library at: %s\n", gpfs_path);
+      handle = dlopen(gpfs_path, RTLD_NOW | RTLD_GLOBAL);
+      _path = gpfslib_paths[++path_indx];
+      still_search = handle == NULL && _path != NULL;
+   }
+
+   // check if dlopen was successful in some point
+   if (handle != NULL){
+      Dmsg1(200, "Loaded GPFS library: %s\n", gpfs_path);
+      // resolve required symbols
+
+      _gpfs_getacl = (_gpfs_getacl_func_t) dlsym(handle, GPFSLIB_SYM_GETACL);
+      // check symbol resolution
+      if (_gpfs_getacl != NULL){
+         _gpfs_putacl = (_gpfs_putacl_func_t) dlsym(handle, GPFSLIB_SYM_PUTACL);
+         // check symbol resolution
+         if (_gpfs_putacl != NULL){
+            Dmsg4(200, "Successfully mapped symbols: %s=%p %s=%p\n",
+                        GPFSLIB_SYM_GETACL, _gpfs_getacl,
+                        GPFSLIB_SYM_PUTACL, _gpfs_putacl);
+            return;
+         }
+      }
+
+      // error rollback all operations
+      release();
+
+   } else {
+      // show error if any
+#ifdef HAVE_DLERROR
+         char *err = dlerror();
+         if (err != NULL){
+            Dmsg2(1, "Error loading GPFS Library: %s, Err=%s\n", GPFSLIB_PATH, NPRT(err));
+         }
+#else
+         Dmsg1(1, "Error loading GPFS Library: %s!\n", GPFSLIB_PATH);
+#endif
+
+   }
+
+#endif
+#endif
+};
+
+/**
+ * @brief
+ *
+ */
+void GPFSLIB::release()
+{
+   if (handle != NULL){
+      int rc = 0;
+
+      _gpfs_getacl = NULL;
+      _gpfs_putacl = NULL;
+
+#ifdef HAVE_DLFCN_H
+      rc = dlclose(handle);
+#endif
+
+      if (rc != 0){
+
+#ifdef HAVE_DLERROR
+         char *err = dlerror();
+         if (err != NULL){
+            Dmsg1(1, "Error releasing GPFS Library, Err=%s\n", NPRT(err));
+         }
+#else
+         Dmsg0(1, "Error releasing GPFS Library!\n");
+#endif
+
+      }
+      handle = NULL;
+   }
+};
+
+/**
+ * @brief
+ *
+ * @param jcr
+ * @param ff_pkt
+ * @param acl_type
+ * @param content
+ * @param content_len
+ * @return bRC_GPFSLIB
+ */
+bRC_GPFSLIB GPFSLIB::_gpfs_backup_acl_data(JCR *jcr, FF_PKT *ff_pkt, unsigned char acl_type, POOLMEM *content, uint32_t &content_len)
+{
+#if defined(HAVE_GPFS_ACL)
+   int rc;
+
+   content_len = 0;
+   if (_gpfs_getacl != NULL){
+      /*
+      * first we have to check what space is required,
+      * this is achieved by forcing smal sized buffer
+      */
+      gpfs_opaque_acl_t acltmp;
+      acltmp.acl_buffer_len = sizeof(gpfs_opaque_acl_t);
+      acltmp.acl_type = acl_type;
+      rc = _gpfs_getacl(ff_pkt->fname, 0, &acltmp);
+
+      /*
+       * We expect that the first gpfs_getacl will return with error when it will have at least a single acl entry,
+       * and assume if there is no error then no acl entry available.
+       */
+      if (rc < 0){
+         berrno be;
+         gpfs_opaque_acl_t * aclp;
+         int acl_len;
+
+         switch (be.code()){
+            case ENOSPC:
+               // size of required buffer is at acltmp.acl_buffer_len
+               acl_len = acltmp.acl_buffer_len + sizeof(gpfs_opaque_acl_t);
+
+               // prepare required buffer
+               content = check_pool_memory_size(content, acl_len);
+
+               // fill required data
+               aclp = (gpfs_opaque_acl_t*)content;
+               aclp->acl_buffer_len = acl_len;
+               aclp->acl_version = 0;
+               aclp->acl_type = acl_type;
+
+               rc = _gpfs_getacl(ff_pkt->fname, 0, content);
+               if (rc < 0){
+                  // error reading acl
+                  berrno be;
+                  switch (be.code()){
+                     case ENOENT:
+                     case ENODATA:
+                        return bRC_GPFSLIB_ok;
+
+                     default:
+                        Mmsg2(jcr->errmsg, _("gpfs_getacl error on file \"%s\": ERR=%s\n"), ff_pkt->fname, be.bstrerror());
+                        Dmsg2(100, "gpfs_getacl error file=%s ERR=%s\n", ff_pkt->fname, be.bstrerror());
+                        return bRC_GPFSLIB_error;
+                  }
+               }
+               content_len = acl_len;
+               break;
+
+            case ENOENT:
+            case EINVAL:
+            case ENODATA:
+               return bRC_GPFSLIB_ok;
+
+            default:
+               // this is a real error, report
+               Mmsg2(jcr->errmsg, _("gpfs_getacl error on file \"%s\": ERR=%s\n"), ff_pkt->fname, be.bstrerror());
+               Dmsg2(100, "gpfs_getacl error file=%s ERR=%s\n", ff_pkt->fname, be.bstrerror());
+               return bRC_GPFSLIB_error;
+         }
+      }
+   }
+#endif
+
+   return bRC_GPFSLIB_ok;
+};
+
+/**
+ * @brief
+ *
+ * @param jcr
+ * @param stream
+ * @param content
+ * @param content_len
+ * @return bRC_GPFSLIB
+ */
+bRC_GPFSLIB GPFSLIB::_gpfs_restore_acl_data(JCR *jcr, int stream, POOLMEM *content, uint32_t content_len)
+{
+#if defined(HAVE_GPFS_ACL)
+   int rc;
+
+   if (_gpfs_putacl != NULL){
+      /* check input data */
+      if (jcr == NULL || content == NULL){
+         return bRC_GPFSLIB_fatal;
+      }
+
+      if (content_len > 0 && jcr->last_type != FT_LNK){
+         rc = _gpfs_putacl(jcr->last_fname, 0, content);
+         if (rc < 0){
+            // error saving acl
+            berrno be;
+            switch (be.code()){
+               case ENOSYS:
+
+                  return bRC_GPFSLIB_error;
+               default:
+                  // this is a real error, report
+                  Mmsg2(jcr->errmsg, _("gpfs_getacl error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
+                  Dmsg2(100, "gpfs_getacl error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
+                  return bRC_GPFSLIB_error;
+            }
+         }
+      }
+   }
+#endif
+
+   return bRC_GPFSLIB_ok;
+};
diff --git a/bacula/src/filed/bacgpfs.h b/bacula/src/filed/bacgpfs.h
new file mode 100644 (file)
index 0000000..201a19a
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2020 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+/*
+ * This is a Bacula support for GPFS.
+ * Author: Radoslaw Korzeniewski, radekk@inteos.pl, Inteos Sp. z o.o.
+ */
+
+#ifndef _BAC_GPFS_H_
+#define _BAC_GPFS_H_
+
+#if defined(HAVE_GPFS_ACL)
+   #include <gpfs.h>
+#endif
+
+#ifndef GPFS_ACL_TYPE_ACCESS
+#define GPFS_ACL_TYPE_ACCESS     1
+#endif
+#ifndef GPFS_ACL_TYPE_DEFAULT
+#define GPFS_ACL_TYPE_DEFAULT    2
+#endif
+#ifndef GPFS_ACL_TYPE_NFS4
+#define GPFS_ACL_TYPE_NFS4       3
+#endif
+
+#ifndef GPFS_SUPER_MAGIC
+#define GPFS_SUPER_MAGIC     0x47504653
+#endif
+
+
+/*
+ * Define a function pointer types for better pointer handling
+ */
+typedef int (*_gpfs_getacl_func_t)(char *pathname, int flags, void *aclP);
+typedef int (*_gpfs_putacl_func_t)(char *pathname, int flags, void *aclP);
+
+#define  GPFSLIB_SYM_GETACL      "gpfs_getacl"
+#define  GPFSLIB_SYM_PUTACL      "gpfs_putacl"
+
+enum bRC_GPFSLIB
+{
+   bRC_GPFSLIB_ok,
+   bRC_GPFSLIB_error,
+   bRC_GPFSLIB_fatal,
+};
+
+/**
+ * @brief
+ *
+ */
+class GPFSLIB : public SMARTALLOC
+{
+#if defined(HAVE_LINUX_OS) || defined(HAVE_AIX_OS)
+   _gpfs_getacl_func_t _gpfs_getacl;               // this is function pointer
+   _gpfs_putacl_func_t _gpfs_putacl;
+#else
+   void * _gpfs_getacl;
+   void * _gpfs_putacl;
+#endif
+
+   void *handle;                                                  // this is a dlopen handle
+
+   /**
+    * @brief Construct a new GPFSLIB object
+    *
+    */
+   GPFSLIB() : _gpfs_getacl(NULL), _gpfs_putacl(NULL), handle(NULL) {};
+#if __cplusplus > 201103L
+   GPFSLIB(const GPFSLIB&) = delete;
+#endif
+
+   void initialize();
+   void release();
+   bRC_GPFSLIB _gpfs_backup_acl_data(JCR *jcr, FF_PKT *ff_pkt, unsigned char acl_type, POOLMEM *content, uint32_t &content_len);
+   bRC_GPFSLIB _gpfs_restore_acl_data(JCR *jcr, int stream, POOLMEM *content, uint32_t content_len);
+
+public:
+
+   /**
+    * @brief Destroy the GPFSLIB object
+    *
+    */
+   ~GPFSLIB()
+   {
+      release();
+   };
+
+   /**
+    * @brief This is a main singleton method of the GPFSLIB class.
+    *    The Singleton is a class compound with an object instance instantinated in this
+    *    compilation section, see: https://en.wikipedia.org/wiki/Singleton_pattern
+    *
+    * @return GPFSLIB& a reference to the singleton object of GPFSLIB
+    */
+   static GPFSLIB& Get()
+   {
+      static GPFSLIB _singleton_instance;
+      return _singleton_instance;
+   };
+
+   /**
+    * @brief
+    *
+    */
+   static void Init() { Get().initialize(); };
+
+   /**
+    * @brief
+    *
+    */
+   static void Release() { Get().release(); };
+
+   /**
+    * @brief
+    *
+    * @param jcr
+    * @param ff_pkt
+    * @param acl_type
+    * @param content
+    * @param content_len
+    * @return bRC_GPFSLIB
+    */
+   static bRC_GPFSLIB gpfs_backup_acl_data(JCR *jcr, FF_PKT *ff_pkt, unsigned char acl_type, POOLMEM *content, uint32_t &content_len)
+   {
+      return Get()._gpfs_backup_acl_data(jcr, ff_pkt, acl_type, content, content_len);
+   };
+
+   /**
+    * @brief
+    *
+    * @param jcr
+    * @param stream
+    * @param content
+    * @param content_len
+    * @return bRC_GPFSLIB
+    */
+   static bRC_GPFSLIB gpfs_restore_acl_data(JCR *jcr, int stream, POOLMEM *content, uint32_t content_len)
+   {
+      return Get()._gpfs_restore_acl_data(jcr, stream, content, content_len);
+   };
+
+};
+
+#endif   /* _BAC_GPFS_H_ */
\ No newline at end of file
index 3c386c42e943172f0d3dc422ce6f9385c6b7aa35..70c1aa343346528b86a9a1cd0883f3020c42b04d 100644 (file)
 #include "bacula.h"
 #include "filed.h"
 #include "fd_plugins.h"
+#include "bacgpfs.h"
 
 /* check if ACL support is enabled */
 #if defined(HAVE_ACL)
 
+#if defined(HAVE_AFS_ACL)
+   static const bool have_afs_acl_flag = true;
+#else
+   static const bool have_afs_acl_flag = false;
+#endif
+
+#if defined(HAVE_GPFS_ACL)
+   static const bool have_gpfs_acl_flag = true;
+#else
+   static const bool have_gpfs_acl_flag = false;
+#endif
+
 /*
  * This is a constructor of the base BACL class which is OS independent
  *
@@ -226,8 +239,8 @@ bRC_BACL BACL::check_dev (JCR *jcr){
  * out:
  *    internal flags status set
  */
-void BACL::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev){
-
+void BACL::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev)
+{
    /* sanity check of input variables */
    if (jcr == NULL || jcr->last_fname == NULL){
       return;
@@ -235,16 +248,13 @@ void BACL::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev){
 
    if (current_dev != dev){
       flags = BACL_FLAG_NONE;
-#if defined(HAVE_AFS_ACL)
-      /* handle special fs: AFS */
-      if (fstype_equals(jcr->last_fname, "afs")){
+      if (have_afs_acl_flag && check_current_fs(jcr->last_fname, jcr->ff, "afs")){
          set_flag(BACL_FLAG_AFS);
+      } else if (have_gpfs_acl_flag && check_current_fs(jcr->last_fname, jcr->ff, GPFS_SUPER_MAGIC)){
+         set_flag(BACL_FLAG_GPFS);
       } else {
          set_flag(BACL_FLAG_NATIVE);
       }
-#else
-      set_flag(BACL_FLAG_NATIVE);
-#endif
       current_dev = dev;
    }
 };
@@ -285,7 +295,7 @@ bRC_BACL BACL::send_acl_stream(JCR *jcr, int stream){
    }
 
    /* send the buffer to the storage daemon */
-   Dmsg1(400, "Backing up ACL: %i\n", content_len);
+   Dmsg1(400, "Backing up ACL size: %i\n", content_len);
 #if 0
    POOL_MEM tmp(PM_FNAME);
    pm_memcpy(tmp, content, content_len);
@@ -308,7 +318,7 @@ bRC_BACL BACL::send_acl_stream(JCR *jcr, int stream){
       return bRC_BACL_fatal;
    }
 
-   Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
+   Dmsg1(200, "ACL of: %s successfully backed up!\n", jcr->last_fname);
    return bRC_BACL_ok;
 };
 
@@ -325,14 +335,10 @@ bRC_BACL BACL::send_acl_stream(JCR *jcr, int stream){
  */
 bRC_BACL BACL::backup_acl (JCR *jcr, FF_PKT *ff_pkt)
 {
-#if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL)
-   Jmsg(jcr, M_FATAL, 0, "ACL backup requested but not configured in Bacula.\n");
-   return bRC_BACL_fatal;
-#else
    /* sanity check of input variables and verify if engine is enabled */
    if (acl_ena && jcr != NULL && ff_pkt != NULL){
       /* acl engine enabled, proceed */
-      bRC_BACL rc;
+      bRC_BACL rc = bRC_BACL_ok;
 
       jcr->errmsg[0] = 0;
       /* check if we have a plugin generated backup */
@@ -354,7 +360,14 @@ bRC_BACL BACL::backup_acl (JCR *jcr, FF_PKT *ff_pkt)
          }
 #endif
 
-#if defined(HAVE_ACL)
+#if defined(HAVE_GPFS_ACL)
+         if (flags & BACL_FLAG_GPFS){
+            Dmsg0(400, "make GPFS ACL call\n");
+            rc = gpfs_backup_acl(jcr, ff_pkt);
+            goto bail_out;
+         }
+#endif
+
          if (flags & BACL_FLAG_NATIVE){
             Dmsg0(400, "make Native ACL call\n");
             rc = os_backup_acl(jcr, ff_pkt);
@@ -362,12 +375,13 @@ bRC_BACL BACL::backup_acl (JCR *jcr, FF_PKT *ff_pkt)
             /* skip acl backup */
             return bRC_BACL_ok;
          }
-#endif
       }
-#if defined(HAVE_AFS_ACL)
+#if defined(HAVE_AFS_ACL) || defined(HAVE_GPFS_ACL)
    bail_out:
 #endif
-      if (rc == bRC_BACL_error){
+
+      // TODO: This routine should be optimized
+      if (rc != bRC_BACL_ok){
          if (acl_nr_errors < ACL_MAX_ERROR_PRINT_PER_JOB){
             if (!jcr->errmsg[0]){
                Jmsg(jcr, M_WARNING, 0, "No OS ACL configured.\n");
@@ -380,8 +394,8 @@ bRC_BACL BACL::backup_acl (JCR *jcr, FF_PKT *ff_pkt)
       }
       return rc;
    }
+
    return bRC_BACL_ok;
-#endif
 };
 
 /*
@@ -399,10 +413,6 @@ bRC_BACL BACL::backup_acl (JCR *jcr, FF_PKT *ff_pkt)
  */
 bRC_BACL BACL::restore_acl (JCR *jcr, int stream, char *data, uint32_t length)
 {
-#if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL)
-   Jmsg(jcr, M_FATAL, 0, "ACL restore requested but not configured in Bacula.\n");
-   return bRC_BACL_fatal;
-#else
    /* sanity check of input variables and verify if engine is enabled */
    if (acl_ena && jcr != NULL && data != NULL){
       /* acl engine enabled, proceed */
@@ -427,8 +437,11 @@ bRC_BACL BACL::restore_acl (JCR *jcr, int stream, char *data, uint32_t length)
       set_content(data, length);
 
       switch (stream){
+         case STREAM_XACL_PLUGIN_ACL:
+            return restore_plugin_acl(jcr);
+
 #if defined(HAVE_AFS_ACL)
-         case STREAM_BACL_AFS_TEXT:
+         case STREAM_XACL_AFS_TEXT:
             if (flags & BACL_FLAG_AFS){
                return afs_restore_acl(jcr, stream);
             } else {
@@ -439,18 +452,33 @@ bRC_BACL BACL::restore_acl (JCR *jcr, int stream, char *data, uint32_t length)
                return bRC_BACL_ok;
             }
 #endif
-#if defined(HAVE_ACL)
+
+#if defined(HAVE_GPFS_ACL)
+         case STREAM_XACL_GPFS_ACL_ACCESS:
+         case STREAM_XACL_GPFS_ACL_DEFAULT:
+            if (flags & BACL_FLAG_GPFS){
+               return gpfs_restore_acl(jcr, stream);
+            } else {
+               /*
+                * Increment error count but don't log an error again for the same filesystem.
+                */
+               inc_acl_errors();
+               return bRC_BACL_ok;
+            }
+#endif
+
          case STREAM_UNIX_ACCESS_ACL:
          case STREAM_UNIX_DEFAULT_ACL:
             if (flags & BACL_FLAG_NATIVE){
                return os_restore_acl(jcr, stream, content, content_len);
             } else {
+               /*
+                * Increment error count but don't log an error again for the same filesystem.
+                */
                inc_acl_errors();
                return bRC_BACL_ok;
             }
             break;
-         case STREAM_XACL_PLUGIN_ACL:
-            return restore_plugin_acl(jcr);
          default:
             if (flags & BACL_FLAG_NATIVE){
                Dmsg0(400, "make Native ACL call\n");
@@ -465,21 +493,20 @@ bRC_BACL BACL::restore_acl (JCR *jcr, int stream, char *data, uint32_t length)
                   }
                }
             } else {
+               /*
+                * Increment error count but don't log an error again for the same filesystem.
+                */
                inc_acl_errors();
                return bRC_BACL_ok;
             }
             break;
-#else
-         default:
-            break;
-#endif
       }
       /* cannot find a valid stream to support */
       Qmsg2(jcr, M_WARNING, 0, _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"), jcr->last_fname, stream);
       return bRC_BACL_error;
    }
+
    return bRC_BACL_ok;
-#endif
 };
 
 /*
@@ -524,6 +551,48 @@ bRC_BACL BACL::generic_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
    return bRC_BACL_ok;
 };
 
+/*
+ * Performs a GPFS ACL backup using FS specific API.
+ *
+ * in:
+ *    jcr - Job Control Record
+ *    ff_pkt - file to backup control package
+ * out:
+ *    bRC_BACL_ok - backup of acl's was successful
+ *    bRC_BACL_fatal - was an error during acl backup
+ */
+bRC_BACL BACL::gpfs_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
+{
+   /* sanity check of input variables */
+   if (jcr == NULL || ff_pkt == NULL){
+      return bRC_BACL_inval;
+   }
+
+   if (GPFSLIB::gpfs_backup_acl_data(jcr, ff_pkt, GPFS_ACL_TYPE_ACCESS, content, content_len) == bRC_GPFSLIB_fatal){
+      return bRC_BACL_fatal;
+   }
+
+   if (content_len > 0){
+      if (send_acl_stream(jcr, STREAM_XACL_GPFS_ACL_ACCESS) == bRC_BACL_fatal){
+         return bRC_BACL_fatal;
+      }
+   }
+
+   if (ff_pkt->type == FT_DIREND){
+      if (GPFSLIB::gpfs_backup_acl_data(jcr, ff_pkt, GPFS_ACL_TYPE_DEFAULT, content, content_len) == bRC_GPFSLIB_fatal){
+         return bRC_BACL_fatal;
+      }
+      if (content_len > 0){
+         if (send_acl_stream(jcr, STREAM_XACL_GPFS_ACL_DEFAULT) == bRC_BACL_fatal){
+            return bRC_BACL_fatal;
+         }
+      }
+   }
+
+   return bRC_BACL_error;
+};
+
+
 /*
  * Performs a generic ACL restore using OS specific methods for
  * setting acl data on file.
@@ -537,8 +606,8 @@ bRC_BACL BACL::generic_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
  *    bRC_BACL_fatal - was a fatal error during acl restore or input data
  *                     is invalid
  */
-bRC_BACL BACL::generic_restore_acl (JCR *jcr, int stream){
-
+bRC_BACL BACL::generic_restore_acl (JCR *jcr, int stream)
+{
    unsigned int count;
 
    /* sanity check of input variables */
@@ -567,6 +636,78 @@ bRC_BACL BACL::generic_restore_acl (JCR *jcr, int stream){
    return bRC_BACL_error;
 };
 
+#if defined(HAVE_GPFS_ACL)
+/*
+ * Performs a GPFS ACL backup using FS specific API.
+ *
+ * in:
+ *    jcr - Job Control Record
+ *    ff_pkt - file to backup control package
+ * out:
+ *    bRC_BACL_ok - backup of acl's was successful
+ *    bRC_BACL_fatal - was an error during acl backup
+ */
+bRC_BACL BACL::gpfs_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
+{
+   /* sanity check of input variables */
+   if (jcr == NULL || ff_pkt == NULL){
+      return bRC_BACL_inval;
+   }
+
+   if (GPFSLIB::gpfs_backup_acl_data(jcr, ff_pkt, GPFS_ACL_TYPE_ACCESS, content, content_len) != bRC_GPFSLIB_ok){
+      return bRC_BACL_fatal;
+   }
+
+   if (content_len > 0){
+      if (send_acl_stream(jcr, STREAM_XACL_GPFS_ACL_ACCESS) == bRC_BACL_fatal){
+         return bRC_BACL_fatal;
+      }
+   }
+
+   if (ff_pkt->type == FT_DIREND){
+      if (GPFSLIB::gpfs_backup_acl_data(jcr, ff_pkt, GPFS_ACL_TYPE_DEFAULT, content, content_len) != bRC_GPFSLIB_ok){
+         return bRC_BACL_fatal;
+      }
+
+      if (content_len > 0){
+         if (send_acl_stream(jcr, STREAM_XACL_GPFS_ACL_DEFAULT) == bRC_BACL_fatal){
+            return bRC_BACL_fatal;
+         }
+      }
+   }
+
+   return bRC_BACL_ok;
+};
+
+/*
+ * Performs a GPFS ACL restore using FS specific API.
+ *
+ * in:
+ *    jcr - Job Control Record
+ *    stream - a stream number to restore
+ * out:
+ *    bRC_BACL_ok - restore of acl's was successful
+ *    bRC_BACL_error - was an error during acl restore
+ *    bRC_BACL_fatal - was a fatal error during acl restore or input data
+ *                     is invalid
+ */
+bRC_BACL BACL::gpfs_restore_acl (JCR *jcr, int stream)
+{
+   /* sanity check of input variables */
+   if (jcr == NULL){
+      return bRC_BACL_inval;
+   }
+
+   if (GPFSLIB::gpfs_restore_acl_data(jcr, stream, content, content_len) != bRC_GPFSLIB_ok){
+      /* error */
+      return bRC_BACL_error;
+   }
+
+   return bRC_BACL_ok;
+};
+#endif
+
+
 /*
  * Perform a generic ACL backup using a plugin. It calls the plugin API to
  * get required acl data from plugin.
@@ -672,8 +813,8 @@ long pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow);
  *    bRC_BACL_ok - backup finish without problems
  *    bRC_BACL_error - when you can't backup acl data because some error
  */
-bRC_BACL BACL::afs_backup_acl (JCR *jcr, FF_PKT *ff_pkt){
-
+bRC_BACL BACL::afs_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
+{
    int rc;
    struct ViceIoctl vip;
    char data[BUFSIZ];
@@ -715,8 +856,8 @@ bRC_BACL BACL::afs_backup_acl (JCR *jcr, FF_PKT *ff_pkt){
  *    bRC_BACL_ok - backup finish without problems
  *    bRC_BACL_error - when you can't backup acl data because some error
  */
-bRC_BACL BACL::afs_restore_acl (JCR *jcr, int stream){
-
+bRC_BACL BACL::afs_restore_acl (JCR *jcr, int stream)
+{
    int rc;
    struct ViceIoctl vip;
 
index 14b5717324594a4583d7e70cfc640df6cd6913f4..742667466c2838a0480e9ff4baf20b93a7728226 100644 (file)
@@ -25,8 +25,8 @@
  *
  */
 
-#ifndef __BACL_H_
-#define __BACL_H_
+#ifndef _BACL_H_
+#define _BACL_H_
 
 /* check if ACL support is enabled */
 #if defined(HAVE_ACL)
@@ -67,6 +67,7 @@ typedef enum {
 #define BACL_FLAG_NATIVE      0x01
 #define BACL_FLAG_AFS         0x02
 #define BACL_FLAG_PLUGIN      0x04
+#define BACL_FLAG_GPFS        0x08
 
 /*
  * Ensure we have none
@@ -78,9 +79,9 @@ typedef enum {
 /*
  * Basic ACL class which is a foundation for any other OS specific implementation.
  *
- * This class cannot be used directly as it is an abstraction class with a lot 
- * of virtual methods laying around. As a basic class it has all public API 
- * available for backup and restore functionality. As a bonus it handles all 
+ * This class cannot be used directly as it is an abstraction class with a lot
+ * of virtual methods laying around. As a basic class it has all public API
+ * available for backup and restore functionality. As a bonus it handles all
  * ACL generic functions and OS independent API, i.e. for AFS ACL or Plugins ACL
  * (future functionality).
  */
@@ -108,7 +109,7 @@ private:
     *    bRC_BACL_ok - backup performed without problems
     *    any other - some error occurred
     */
-   virtual bRC_BACL os_backup_acl (JCR *jcr, FF_PKT *ff_pkt){return bRC_BACL_fatal;};
+   virtual bRC_BACL os_backup_acl (JCR *jcr, FF_PKT *ff_pkt) { return bRC_BACL_fatal; };
 
    /**
     * Perform OS specific ACL restore. Runtime is called only when stream is supported by OS.
@@ -119,7 +120,7 @@ private:
     *    bRC_BACL_ok - backup performed without problems
     *    any other - some error occurred
     */
-   virtual bRC_BACL os_restore_acl (JCR *jcr, int stream, char *content, uint32_t length){return bRC_BACL_fatal;};
+   virtual bRC_BACL os_restore_acl (JCR *jcr, int stream, char *content, uint32_t length) { return bRC_BACL_fatal; };
 
    /**
     * Low level OS specific runtime to get ACL data from file. The ACL data is set in internal content buffer.
@@ -131,7 +132,7 @@ private:
     *    bRC_BACL_ok -
     *    bRC_BACL_error/fatal - an error or fatal error occurred
     */
-   virtual bRC_BACL os_get_acl (JCR *jcr, BACL_type bacltype){return bRC_BACL_fatal;};
+   virtual bRC_BACL os_get_acl (JCR *jcr, BACL_type bacltype) { return bRC_BACL_fatal; };
 
    /**
     * Low level OS specific runtime to set ACL data on file.
@@ -145,11 +146,12 @@ private:
     *    bRC_BACL_ok -
     *    bRC_BACL_error/fatal - an error or fatal error occurred
     */
-   virtual bRC_BACL os_set_acl (JCR *jcr, BACL_type bacltype, char *content, uint32_t length){return bRC_BACL_fatal;};
+   virtual bRC_BACL os_set_acl (JCR *jcr, BACL_type bacltype, char *content, uint32_t length) { return bRC_BACL_fatal; };
 
    void inc_acl_errors(){ acl_nr_errors++;};
    bRC_BACL check_dev (JCR *jcr);
    void check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev);
+   // bRC_BACL gpfs_backup_acl_data(JCR *jcr, FF_PKT *ff_pkt, unsigned char acl_type);
 
 public:
    BACL ();
@@ -186,10 +188,12 @@ public:
    bRC_BACL afs_restore_acl (JCR *jcr, int stream);
    bRC_BACL backup_plugin_acl (JCR *jcr, FF_PKT *ff_pkt);
    bRC_BACL restore_plugin_acl (JCR *jcr);
+   bRC_BACL gpfs_backup_acl (JCR *jcr, FF_PKT *ff_pkt);
+   bRC_BACL gpfs_restore_acl (JCR *jcr, int stream);
 };
 
 void *new_bacl();
 
 #endif /* HAVE_ACL */
 
-#endif /* __BACL_H_ */
+#endif /* _BACL_H_ */
index d1a074af5108094ecf9e23d6069e8f3548627754..9a0af4f08f541fbe0a301382d637f95314d8d819 100644 (file)
 /* check if XATTR support is enabled */
 #if defined(HAVE_XATTR)
 
+#if defined(HAVE_GPFS_XATTR)
+   #include <gpfs.h>
+   static const bool have_gpfs_xattr_flag = true;
+#else
+   static const bool have_gpfs_xattr_flag = false;
+#endif
+
+#ifndef GPFS_SUPER_MAGIC
+#define GPFS_SUPER_MAGIC     0x47504653
+#endif
+
 /*
  * This is a constructor of the base BXATTR class which is OS independent
  *
@@ -204,7 +215,8 @@ POOLMEM * BXATTR::set_content(char *data, int len){
  *    bRC_BXATTR_skip - cannot verify device - no file found
  *    bRC_BXATTR_inval - invalid input data
  */
-bRC_BXATTR BXATTR::check_dev (JCR *jcr){
+bRC_BXATTR BXATTR::check_dev (JCR *jcr)
+{
 
    int lst;
    struct stat st;
@@ -245,7 +257,14 @@ bRC_BXATTR BXATTR::check_dev (JCR *jcr){
  * out:
  *    internal flags status set
  */
-void BXATTR::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev){
+void BXATTR::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev)
+{
+
+#if defined(HAVE_GPFS_XATTR)
+   static const bool have_gpfs_xattr_flag = true;
+#else
+   static const bool have_gpfs_xattr_flag = false;
+#endif
 
    /* sanity check of input variables */
    if (jcr == NULL || jcr->last_fname == NULL){
@@ -254,7 +273,12 @@ void BXATTR::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev){
 
    if (current_dev != dev){
       flags = BXATTR_FLAG_NONE;
-      set_flag(BXATTR_FLAG_NATIVE);
+      jcr->ff->last_fstype = 0;
+      if (have_gpfs_xattr_flag && check_current_fs(jcr->last_fname, jcr->ff, GPFS_SUPER_MAGIC)){
+         set_flag(BXATTR_FLAG_GPFS);
+      } else {
+         set_flag(BXATTR_FLAG_NATIVE);
+      }
       current_dev = dev;
       /* We can check for some specific ACLs depending on the FS type */
       if (!fstype(ff, current_fs, sizeof(current_fs))) {
@@ -275,8 +299,8 @@ void BXATTR::check_dev (JCR *jcr, FF_PKT *ff, uint32_t dev){
  *    bRC_BXATTR_fatal - when we can't send data to the SD
  *    bRC_BXATTR_ok - send finish without errors
  */
-bRC_BXATTR BXATTR::send_xattr_stream(JCR *jcr, int stream){
-
+bRC_BXATTR BXATTR::send_xattr_stream(JCR *jcr, int stream)
+{
    BSOCK * sd;
    POOLMEM * msgsave;
 #ifdef FD_NO_SEND_TEST
@@ -300,11 +324,6 @@ bRC_BXATTR BXATTR::send_xattr_stream(JCR *jcr, int stream){
 
    /* send the buffer to the storage daemon */
    Dmsg1(400, "Backing up XATTR: %i\n", content_len);
-#if 0
-   POOL_MEM tmp(PM_FNAME);
-   pm_memcpy(tmp, content, content_len);
-   Dmsg2(400, "Backing up XATTR: (%i) <%s>\n", strlen(tmp.addr()), tmp.c_str());
-#endif
    msgsave = sd->msg;
    sd->msg = content;
    sd->msglen = content_len;
@@ -336,9 +355,9 @@ bRC_BXATTR BXATTR::send_xattr_stream(JCR *jcr, int stream){
  *    bRC_BXATTR_ok - backup finish without problems
  *    bRC_BXATTR_error - when you can't backup xattr data because some error
  */
-bRC_BXATTR BXATTR::backup_xattr (JCR *jcr, FF_PKT *ff_pkt){
-
-#if !defined(HAVE_XATTR)
+bRC_BXATTR BXATTR::backup_xattr (JCR *jcr, FF_PKT *ff_pkt)
+{
+#if !defined(HAVE_XATTR) && !defined(HAVE_GPFS_XATTR)
    Jmsg(jcr, M_FATAL, 0, "XATTR backup requested but not configured in Bacula.\n");
    return bRC_BXATTR_fatal;
 #else
@@ -359,6 +378,15 @@ bRC_BXATTR BXATTR::backup_xattr (JCR *jcr, FF_PKT *ff_pkt){
 
          check_dev(jcr, ff_pkt, ff_pkt->statp.st_dev);
 
+#if defined(HAVE_GPFS_XATTR)
+         if (flags & BXATTR_FLAG_GPFS){
+            Dmsg0(400, "make GPFS XATTR call\n");
+            rc = gpfs_backup_xattr(jcr, ff_pkt);
+            goto bail_out;
+         }
+#endif
+
+#if defined(HAVE_XATTR)
          if (flags & BXATTR_FLAG_NATIVE){
             Dmsg0(400, "make Native XATTR call\n");
             rc = os_backup_xattr(jcr, ff_pkt);
@@ -366,9 +394,13 @@ bRC_BXATTR BXATTR::backup_xattr (JCR *jcr, FF_PKT *ff_pkt){
             /* skip xattr backup */
             return bRC_BXATTR_ok;
          }
-
+#endif
       }
 
+#ifdef HAVE_GPFS_XATTR
+   bail_out:
+#endif
+
       if (rc == bRC_BXATTR_error){
          if (xattr_nr_errors < XATTR_MAX_ERROR_PRINT_PER_JOB){
             if (!jcr->errmsg[0]){
@@ -431,6 +463,12 @@ bRC_BXATTR BXATTR::restore_xattr (JCR *jcr, int stream, char *data, uint32_t len
       switch (stream){
          case STREAM_XACL_PLUGIN_XATTR:
             return restore_plugin_xattr(jcr);
+
+#if defined(HAVE_GPFS_XATTR)
+         case STREAM_XACL_GPFS_XATTR:
+            return gpfs_restore_xattr(jcr, stream);
+#endif
+
          default:
             if (flags & BXATTR_FLAG_NATIVE){
                for (a = 0; xattr_streams[a] > 0; a++){
@@ -440,6 +478,9 @@ bRC_BXATTR BXATTR::restore_xattr (JCR *jcr, int stream, char *data, uint32_t len
                   }
                }
             } else {
+               /*
+                * Increment error count but don't log an error again for the same filesystem.
+                */
                inc_xattr_errors();
                return bRC_BXATTR_ok;
             }
@@ -512,8 +553,8 @@ bool BXATTR::check_xattr_skiplists (JCR *jcr, FF_PKT *ff_pkt, char * name){
  *    bRC_BXATTR_error/fatal - an error or fatal error occurred
  *    bRC_BXATTR_inval - input variables was invalid
  */
-bRC_BXATTR BXATTR::generic_backup_xattr (JCR *jcr, FF_PKT *ff_pkt){
-
+bRC_BXATTR BXATTR::generic_backup_xattr (JCR *jcr, FF_PKT *ff_pkt)
+{
    bRC_BXATTR rc;
    POOLMEM *xlist;
    uint32_t xlen;
@@ -628,6 +669,22 @@ bailout:
    return rc;
 };
 
+/*
+ * Performs GPFS XATTR backup using FS specific API.
+ *
+ * in:
+ *    jcr - Job Control Record
+ *    ff_pkt - file to backup control package
+ * out:
+ *    bRC_BXATTR_ok - xattr backup ok or no xattr to backup found
+ *    bRC_BXATTR_error/fatal - an error or fatal error occurred
+ *    bRC_BXATTR_inval - input variables was invalid
+ */
+bRC_BXATTR BXATTR::gpfs_backup_xattr (JCR *jcr, FF_PKT *ff_pkt)
+{
+   return bRC_BXATTR_error;
+}
+
 /*
  * Performs a generic XATTR restore using OS specific methods for
  * setting XATTR data on file.
@@ -641,8 +698,8 @@ bailout:
  *    bRC_BXATTR_fatal - was a fatal error during xattr restore
  *    bRC_BXATTR_inval - input variables was invalid
  */
-bRC_BXATTR BXATTR::generic_restore_xattr (JCR *jcr, int stream){
-
+bRC_BXATTR BXATTR::generic_restore_xattr (JCR *jcr, int stream)
+{
    bRC_BXATTR rc = bRC_BXATTR_ok;
    alist *xattr_list;
    BXATTR_xattr *xattr;
@@ -687,6 +744,24 @@ bailout:
    return rc;
 };
 
+/*
+ * Performs a GPFS XATTR restore using FS specific API.
+ *
+ * in:
+ *    jcr - Job Control Record
+ *    stream - a stream number to restore
+ * out:
+ *    bRC_BXATTR_ok - restore of acl's was successful
+ *    bRC_BXATTR_error - was an error during xattr restore
+ *    bRC_BXATTR_fatal - was a fatal error during xattr restore
+ *    bRC_BXATTR_inval - input variables was invalid
+ */
+bRC_BXATTR BXATTR::gpfs_restore_xattr (JCR *jcr, int stream)
+{
+
+   return bRC_BXATTR_error;
+}
+
 /*
  * Perform a generic XATTR backup using a plugin. It calls the plugin API to
  * get required xattr data from plugin.
index 931227c7147e566bb3d338b56f72b82e971cc51e..6cfbd2f7ed8240af9b5db194d98d3ed31e6e1be8 100644 (file)
@@ -25,8 +25,8 @@
  *
  */
 
-#ifndef __BXATTR_H_
-#define __BXATTR_H_
+#ifndef _BXATTR_H_
+#define _BXATTR_H_
 
 /* check if XATTR support is enabled */
 #if defined(HAVE_XATTR)
  * (greater or equal to zero).
  */
 enum bRC_BXATTR {
-   bRC_BXATTR_inval = -3,       // input data invalid
-   bRC_BXATTR_fatal = -2,       // a fatal error
-   bRC_BXATTR_error = -1,       // standard error
-   bRC_BXATTR_ok    = 0,        // success
-   bRC_BXATTR_skip  = 1,        // processing should skip current runtime
-   bRC_BXATTR_cont  = 2         // processing should skip current element
-                                // and continue with next one
+   bRC_BXATTR_inval           = -3, // input data invalid
+   bRC_BXATTR_fatal           = -2, // a fatal error
+   bRC_BXATTR_error           = -1, // standard error
+   bRC_BXATTR_ok              = 0,  // success
+   bRC_BXATTR_skip            = 1,  // processing should skip current runtime
+   bRC_BXATTR_cont            = 2   // processing should skip current element
+                                    // and continue with next one
 };
 
 /*
  * Flags which control what XATTR engine
  * to use for backup/restore
  */
-#define BXATTR_FLAG_NONE        0
-#define BXATTR_FLAG_NATIVE      0x01
-#define BXATTR_FLAG_AFS         0x02
-#define BXATTR_FLAG_PLUGIN      0x04
+#define BXATTR_FLAG_NONE         0
+#define BXATTR_FLAG_NATIVE       0x01
+#define BXATTR_FLAG_AFS          0x02
+#define BXATTR_FLAG_PLUGIN       0x04
+#define BXATTR_FLAG_GPFS         0x08
 
 /*
  * Extended attribute (xattr) list element.
@@ -225,10 +226,12 @@ public:
    bRC_BXATTR generic_restore_xattr (JCR *jcr, int stream);
    bRC_BXATTR backup_plugin_xattr (JCR *jcr, FF_PKT *ff_pkt);
    bRC_BXATTR restore_plugin_xattr (JCR *jcr);
+   bRC_BXATTR gpfs_backup_xattr (JCR *jcr, FF_PKT *ff_pkt);
+   bRC_BXATTR gpfs_restore_xattr (JCR *jcr, int stream);
 };
 
 void *new_bxattr();
 
 #endif /* HAVE_XATTR */
 
-#endif /* __BXATTR_H_ */
+#endif /* _BXATTR_H_ */
index e04c65ea3ac9ce7667f7f47e420014b990fd56a4..d4c742f0fad0788913904a19ed5742ce3c4cd268 100644 (file)
@@ -281,6 +281,7 @@ int main (int argc, char *argv[])
    events_send_msg(NULL, "FD0001",
                    EVENTS_TYPE_DAEMON, "*Daemon*",
                    (intptr_t)get_first_port_host_order(me->FDaddrs), "Filed startup");
+   GPFSLIB::Init();
 
    server_tid = pthread_self();
 
@@ -759,7 +760,7 @@ static bool check_resources()
          }
       }
    }
-   
+
    UnlockRes();
 
    if (OK) {
index c79980a828a7d12787b330ccff3bdf1aca0eeb94..a40bfeb601739f8f357afea9ace3a29df6599884 100644 (file)
@@ -46,6 +46,7 @@
 #include  "fd_plugins.h"
 #include  "fd_snapshot.h"
 #include  "findlib/find.h"
+#include  "bacgpfs.h"
 #include  "bacl.h"
 #include  "bxattr.h"
 #include  "jcr.h"
index 4ed410cf378b08d03aba3554b1be85f4a374dda6..261c642305494498fe0dcf629a266a5c28455613 100644 (file)
@@ -309,6 +309,8 @@ static inline bool pop_delayed_data_streams(r_ctx &rctx)
       case STREAM_XACL_HURD_DEFAULT:
       case STREAM_XACL_HURD_ACCESS:
       case STREAM_XACL_PLUGIN_ACL:
+      case STREAM_XACL_GPFS_ACL_DEFAULT:
+      case STREAM_XACL_GPFS_ACL_ACCESS:
          if (!do_restore_acl(jcr, rds->stream, rds->content, rds->content_length)) {
             goto get_out;
          }
@@ -894,6 +896,8 @@ void do_restore(JCR *jcr)
       case STREAM_XACL_HURD_DEFAULT:
       case STREAM_XACL_HURD_ACCESS:
       case STREAM_XACL_PLUGIN_ACL:
+      case STREAM_XACL_GPFS_ACL_DEFAULT:
+      case STREAM_XACL_GPFS_ACL_ACCESS:
          /*
           * Do not restore ACLs when
           * a) The current file is not extracted
index 8f746f58008f1fb111c5a42f9b99928dd953d044..2a36a6a6162a024101b4698179f6fed4555ab0a1 100644 (file)
 #include "find.h"
 #include <sys/types.h>
 #include <sys/stat.h>
+#if defined(HAVE_LINUX_OS) || defined(HAVE_FREEBSD_OS) || defined(HAVE_AIX_OS)
+  #include <paths.h>
+#endif
+#ifdef HAVE_DARWIN_OS
+  #include <sys/paths.h>
+#endif
+
 #ifdef HAVE_SUN_OS
   #include <sys/mnttab.h>
 #endif
@@ -85,7 +92,6 @@ void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
    }
 }
 
-
 /*
  * These functions should be implemented for each OS
  *
@@ -99,6 +105,19 @@ void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
 #include <sys/param.h>
 #include <sys/mount.h>
 
+/*
+ * simple return fs type magic number or zero when error
+ */
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   struct statfs st;
+
+   if (statfs(fname, &st) == 0) {
+      return st.f_type;
+   }
+   return 0;
+}
+
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 {
    char *fname = ff_pkt->fname;
@@ -122,6 +141,19 @@ bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 #define statvfs statfs
 #endif
 
+/*
+ * simple return fs type magic number or zero when error
+ */
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   struct statvfs st;
+
+   if (statvfs(fname, &st) == 0) {
+      return st.f_type;
+   }
+   return 0;
+}
+
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 {
    char *fname = ff_pkt->fname;
@@ -142,6 +174,23 @@ bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 #include <sys/types.h>
 #include <sys/statvfs.h>
 
+/*
+ * TODO: RPK: is HP-UX version really working as I cannot find required API in HP-UX docs.
+ */
+
+/*
+ * simple return fs type magic number or zero when error
+ */
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   struct statfs st;
+
+   if (statfs(fname, &st) == 0) {
+      return st.f_fsid;
+   }
+   return 0;
+}
+
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 {
    char *fname = ff_pkt->fname;
@@ -162,14 +211,27 @@ bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 #include <sys/vfs.h>
 #include <mntent.h>
 
+
+/*
+ * simple return fs type magic number or zero when error
+ */
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   struct statfs st;
+
+   if (statfs(fname, &st) == 0) {
+      return st.f_type;
+   }
+   return 0;
+}
+
 /*
  * Linux statfs() does not return the filesystem name type.  It
  *  only returns a binary fstype, so we must look up the type name
  *  in mtab.
  */
-bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
+bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
 {
-   char *fname = ff_pkt->fname; /* fname is a better here than snap_fname */
    struct statfs st;
    const char *fstype;
    if (!fname) {
@@ -295,6 +357,19 @@ bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 #include <sys/types.h>
 #include <sys/stat.h>
 
+/*
+ * simple return fs type magic number
+ */
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   struct statvfs st;
+
+   if (statvfs(fname, &st) == 0) {
+      return st.f_fsid;
+   }
+   return 0;
+}
+
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 {
    /* Solaris has the filesystem type name in the lstat packet */
@@ -307,11 +382,28 @@ bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 #include <sys/stat.h>
 #include <sys/mount.h>
 
+/*
+ * TODO: RPK: Tru64 is already dead!
+ */
+
+/*
+ * simple return fs type magic number
+ */
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   struct statfs st;
+
+   if (statfs((char *)fname, &st) == 0){
+      return st.f_type;
+   }
+   return 0;
+}
+
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 {
    char *fname = ff_pkt->fname;
    struct statfs st;
-   if (statfs((char *)fname, &st) == 0) {
+   if (statfs((char *)fname, &st) == 0){
       switch (st.f_type) {
       /* Known good values */
       case 0xa:         bstrncpy(fs, "advfs", fslen); return true;        /* Tru64 AdvFS */
@@ -358,9 +450,14 @@ bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 
 #else    /* No recognised OS */
 
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
+{
+   Dmsg0(10, "!!! fstypeid() not implemented for this OS. !!!\n");
+   return 0;
+}
+
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
 {
-   char *fname = ff_pkt->fname;
    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
    return false;
 }
@@ -461,6 +558,51 @@ bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
    return true;
 } 
 
+/*
+ * Parameter wrapper for fstype
+ */
+bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
+{
+   return fstype(ff_pkt->fname, ff_pkt, fs, fslen);
+}
+
+/*
+ * compares current fstype from FF_PKT for required fstype_name
+ */
+bool check_current_fs(char *fname, FF_PKT *ff, const char *fstype_name)
+{
+   if (fstype_name != NULL){
+      // read current fs name and compare it to required
+      char fsname[NAME_MAX];
+      if (fstype(fname, ff, fsname, NAME_MAX)){
+         return bstrcmp(fsname, fstype_name);
+      }
+   }
+   return false;
+};
+
+/*
+ * compares current fstype from FF_PKT for required fstype_magic
+ */
+bool check_current_fs(char *fname, FF_PKT *ff, uint32_t fstype_magic)
+{
+   uint32_t fsid;
+
+   if (fstype_magic > 0){
+      // get fsid for file
+      if (ff->last_fstype != 0){
+         fsid = ff->last_fstype;
+      } else {
+         fsid = fstypeid(fname, ff);
+         ff->last_fstype = fsid;
+      }
+      if (fsid != 0){
+         return fsid == fstype_magic;
+      }
+   }
+   return false;
+}
+
 #ifdef TEST_PROGRAM
 int main(int argc, char **argv)
 {
index b3b0ffb986f63e3d25f51bc4663e59124bd161e3..1a3f9bfe91e1f3d9033f730a7e6a42bf9d595764 100644 (file)
@@ -82,7 +82,10 @@ bool path_list_add(JCR *jcr, uint32_t len, char *fname);
 
 /* from fstype.c */
 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
-bool fstype_equals(const char *fname, const char *fstype_name);
+bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen);
+uint32_t fstypeid(char *fname, FF_PKT *ff_pkt);
+bool check_current_fs(char *fname, FF_PKT *ff, const char *fstype_name);
+bool check_current_fs(char *fname, FF_PKT *ff, uint32_t fstype_magic);
 
 /* from drivetype.c */
 bool drivetype(const char *fname, char *fs, int fslen);
index b39dd5df87cfba1ed45f95f2dd58592cf00e7298..75af69ec0901510c4f83e8aa305d12d29d225e73 100644 (file)
@@ -42,7 +42,7 @@
 #define STREAMBITS_TYPE               11         /* type bit size */
 #define STREAMMASK_TYPE               (~((~0uL)<< STREAMBITS_TYPE) << STREAMBASE_TYPE)
 /*
- * Note additional base, bits, and masks can be defined for new     
+ * Note additional base, bits, and masks can be defined for new
  *  ranges or subranges of stream attributes.
  */
 
@@ -91,9 +91,9 @@
 #define STREAM_PLUGIN_DATA                 27    /* Plugin specific data */
 #define STREAM_RESTORE_OBJECT              28    /* Plugin restore object */
 /*
- * Non-gzip compressed streams. Those streams can handle arbitrary 
- *  compression algorithm data as an additional header is stored 
- *  at the beginning of the stream. See comp_stream_header definition 
+ * Non-gzip compressed streams. Those streams can handle arbitrary
+ *  compression algorithm data as an additional header is stored
+ *  at the beginning of the stream. See comp_stream_header definition
  *  in ch.h for more details.
  */
 #define STREAM_COMPRESSED_DATA                 29    /* Compressed file data */
 #define STREAM_XACL_HURD_DEFAULT      1018    /* GNU HURD acl_t string of acl_to_text (POSIX acl) for default acls */
 #define STREAM_XACL_HURD_ACCESS       1019    /* GNU HURD acl_t string of acl_to_text (POSIX acl) for access acls */
 #define STREAM_XACL_PLUGIN_ACL        1020    /* Plugin ACL data for plugin specific acls */
+#define STREAM_XACL_GPFS_ACL_DEFAULT  1021    /* GPFS Default ACL data using gpfs_getacl()/gpfs_putacl() */
+#define STREAM_XACL_GPFS_ACL_ACCESS   1022    /* GPFS Access ACL data using gpfs_getacl()/gpfs_putacl() */
+#define STREAM_XACL_GPFS_XATTR        1987    /* GPFS XATTR data using gpfs_fgetattrs()/gpfs_fputattrs() */
 #define STREAM_XACL_PLUGIN_XATTR      1988    /* Plugin XATTR data for plugin specific xattrs */
 #define STREAM_XACL_HURD_XATTR        1989    /* GNU HURD extended attributes */
 #define STREAM_XACL_IRIX_XATTR        1990    /* IRIX extended attributes */