From: Eric Bollengier Date: Wed, 15 Jul 2020 15:01:23 +0000 (+0200) Subject: Add GPFS ACL/XATTR Support X-Git-Tag: Release-11.3.2~1384 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=614a669eb159ca45b09d8bea2e576d0dd61f97a9;p=thirdparty%2Fbacula.git Add GPFS ACL/XATTR Support Author: Radosław Korzeniewski Date: Tue Jul 14 11:13:36 2020 +0000 regress: GPFS regression test scripts Author: Radosław Korzeniewski Date: Tue Jul 14 11:13:06 2020 +0000 gpfs: Fix for incorrect Default ACL handling Author: Radosław Korzeniewski Date: Tue Jul 14 10:32:30 2020 +0000 regress: WIP: GPFS regression Author: Radosław Korzeniewski Date: Mon Jul 13 12:29:17 2020 +0000 regress: GPFS regression tests Author: Radosław Korzeniewski Date: Mon Jul 13 08:54:38 2020 +0000 regress: Add gpfs regress test config variable Author: Radosław Korzeniewski Date: Fri Jul 10 14:22:36 2020 +0000 regress: Fix regress-utils.sh script Author: Radosław Korzeniewski Date: Fri Jul 10 13:45:46 2020 +0000 Fix broken configure for ACL/AFS detection Author: Radosław Korzeniewski Date: Fri Jul 10 12:25:48 2020 +0000 gpfs: GPFS ACL restore Author: Radosław Korzeniewski Date: Fri Jul 10 10:43:43 2020 +0000 gpfs: GPFS ACL restore Author: Radosław Korzeniewski Date: Thu Jul 9 14:27:09 2020 +0000 gpfs: General GPFS ACL backup ready Author: Radosław Korzeniewski Date: Thu Jul 9 10:15:57 2020 +0000 gpfs: Update build for GPFS/AFS dependency count Author: Radosław Korzeniewski Date: Thu Jun 25 03:24:30 2020 -0400 gpfs: Fix gpfslib loading routine Author: Radosław Korzeniewski Date: Wed Jun 24 10:47:53 2020 -0400 gpfs: GPFS support update build Author: Radosław Korzeniewski Date: Wed Jun 24 07:37:46 2020 -0400 gpfs: GPFS support Author: Radosław Korzeniewski Date: Wed Jun 24 07:10:31 2020 -0400 gpfs: Create GPFSLIB as a singleton Author: Radosław Korzeniewski Date: Wed Jun 24 03:35:48 2020 -0400 Fix compilation warning Author: Radosław Korzeniewski Date: Tue Jun 23 11:51:40 2020 -0400 gpfs: GPFS lib dynamic load Author: Radosław Korzeniewski Date: Mon Jun 22 16:46:03 2020 +0200 gpfs: gpfs acl Author: Radosław Korzeniewski Date: Mon Jun 22 09:59:26 2020 -0400 gpfs: gpfs acl Author: Radosław Korzeniewski Date: Thu Apr 9 10:01:14 2020 -0400 fstype: Update FS type handling functions Author: Radosław Korzeniewski Date: Wed Apr 8 13:36:11 2020 -0400 gpfs: Untested GPFS ACL routines Author: Radosław Korzeniewski Date: Wed Apr 8 11:53:33 2020 -0400 gpfs: Add GPFS libs detection Author: Radosław Korzeniewski Date: Wed Apr 8 11:52:21 2020 -0400 gpfs: Define GPFS streams --- diff --git a/bacula/src/filed/Makefile.in b/bacula/src/filed/Makefile.in index dffac2f32b..5fa00b7b2d 100644 --- a/bacula/src/filed/Makefile.in +++ b/bacula/src/filed/Makefile.in @@ -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 index 0000000000..40fac547bb --- /dev/null +++ b/bacula/src/filed/bacgpfs.c @@ -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 +#endif +#ifdef HAVE_SYS_STAT_H + #include +#endif +#ifdef HAVE_UNISTD_H + #include +#endif + +#ifdef HAVE_DLFCN_H + #include +#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 index 0000000000..201a19aa2a --- /dev/null +++ b/bacula/src/filed/bacgpfs.h @@ -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 +#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 diff --git a/bacula/src/filed/bacl.c b/bacula/src/filed/bacl.c index 3c386c42e9..70c1aa3433 100644 --- a/bacula/src/filed/bacl.c +++ b/bacula/src/filed/bacl.c @@ -81,10 +81,23 @@ #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; diff --git a/bacula/src/filed/bacl.h b/bacula/src/filed/bacl.h index 14b5717324..742667466c 100644 --- a/bacula/src/filed/bacl.h +++ b/bacula/src/filed/bacl.h @@ -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_ */ diff --git a/bacula/src/filed/bxattr.c b/bacula/src/filed/bxattr.c index d1a074af51..9a0af4f08f 100644 --- a/bacula/src/filed/bxattr.c +++ b/bacula/src/filed/bxattr.c @@ -102,6 +102,17 @@ /* check if XATTR support is enabled */ #if defined(HAVE_XATTR) +#if defined(HAVE_GPFS_XATTR) + #include + 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. diff --git a/bacula/src/filed/bxattr.h b/bacula/src/filed/bxattr.h index 931227c714..6cfbd2f7ed 100644 --- a/bacula/src/filed/bxattr.h +++ b/bacula/src/filed/bxattr.h @@ -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) @@ -45,23 +45,24 @@ * (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_ */ diff --git a/bacula/src/filed/filed.c b/bacula/src/filed/filed.c index e04c65ea3a..d4c742f0fa 100644 --- a/bacula/src/filed/filed.c +++ b/bacula/src/filed/filed.c @@ -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) { diff --git a/bacula/src/filed/filed.h b/bacula/src/filed/filed.h index c79980a828..a40bfeb601 100644 --- a/bacula/src/filed/filed.h +++ b/bacula/src/filed/filed.h @@ -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" diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 4ed410cf37..261c642305 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -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 diff --git a/bacula/src/findlib/fstype.c b/bacula/src/findlib/fstype.c index 8f746f5800..2a36a6a616 100644 --- a/bacula/src/findlib/fstype.c +++ b/bacula/src/findlib/fstype.c @@ -30,6 +30,13 @@ #include "find.h" #include #include +#if defined(HAVE_LINUX_OS) || defined(HAVE_FREEBSD_OS) || defined(HAVE_AIX_OS) + #include +#endif +#ifdef HAVE_DARWIN_OS + #include +#endif + #ifdef HAVE_SUN_OS #include #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 #include +/* + * 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 #include +/* + * 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 #include + +/* + * 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 #include +/* + * 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 #include +/* + * 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) { diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index b3b0ffb986..1a3f9bfe91 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -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); diff --git a/bacula/src/streams.h b/bacula/src/streams.h index b39dd5df87..75af69ec09 100644 --- a/bacula/src/streams.h +++ b/bacula/src/streams.h @@ -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 */ @@ -140,6 +140,9 @@ #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 */