The branch, master has been updated via 469fdcd Efficient xattr handling for VxFS Signed-off-by: Abhidnya Joshi <abhidnya.jo...@veritas.com> from 8814b25 lib: replace: snprintf - Fix length calculation for hex/octal 64-bit values.
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 469fdcd66269f340a05e6a9e4a9de51a1f5d99b2 Author: Abhidnya Joshi <abhidnya.jo...@veritas.com> Date: Wed Jun 1 23:38:31 2016 -0700 Efficient xattr handling for VxFS Signed-off-by: Abhidnya Joshi <abhidnya.jo...@veritas.com> Reviewed-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Fri Jun 3 07:26:34 CEST 2016 on sn-devel-144 ----------------------------------------------------------------------- Summary of changes: source3/modules/lib_vxfs.c | 244 ++++++++++++++++++++++++++++++++++++++++++ source3/modules/vfs_vxfs.c | 149 +++++++++++++++++++++++--- source3/modules/vfs_vxfs.h | 34 ++++++ source3/modules/wscript_build | 2 +- 4 files changed, 415 insertions(+), 14 deletions(-) create mode 100644 source3/modules/lib_vxfs.c create mode 100644 source3/modules/vfs_vxfs.h Changeset truncated at 500 lines: diff --git a/source3/modules/lib_vxfs.c b/source3/modules/lib_vxfs.c new file mode 100644 index 0000000..0d5ea60 --- /dev/null +++ b/source3/modules/lib_vxfs.c @@ -0,0 +1,244 @@ +/* + Unix SMB/CIFS implementation. + Wrap VxFS xattr calls. + + Copyright (C) Veritas Technologies LLC <www.veritas.com> 2016 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smbd/smbd.h" +#include "system/filesys.h" +#include "string.h" + +/* + * Available under GPL at + * http://www.veritas.com/community/downloads/vxfsmisc-library + */ +#define LIBVXFS "/usr/lib64/vxfsmisc.so" + + +static int (*vxfs_setxattr_fd_func) (int fd, const char *name, + const void *value, size_t len, int flags); +static int (*vxfs_getxattr_fd_func) (int fd, const char *name, void *value, + size_t *len); +static int (*vxfs_removexattr_fd_func) (int fd, const char *name); +static int (*vxfs_listxattr_fd_func) (int fd, void *value, size_t *len); + +int vxfs_setxattr_fd(int fd, const char *name, const void *value, + size_t len, int flags) +{ + int ret = -1; + + if (vxfs_setxattr_fd_func == NULL) { + errno = ENOSYS; + return ret; + } + + DEBUG(10, ("Calling vxfs_setxattr_fd\n")); + ret = vxfs_setxattr_fd_func(fd, name, value, len, flags); + if (ret) { + errno = ret; + ret = -1; + } + + return ret; +} + +int vxfs_setxattr_path(const char *path, const char *name, const void *value, + size_t len, int flags, bool is_dir) +{ + int ret, fd = -1; + + if (is_dir) { + fd = open(path, O_RDONLY|O_DIRECTORY); + } else { + fd = open(path, O_WRONLY); + } + + if (fd == -1) { + DEBUG(10, ("error in vxfs_setxattr_path: %s\n", + strerror(errno))); + return -1; + } + + ret = vxfs_setxattr_fd(fd, name, value, len, flags); + + close(fd); + + return ret; +} + +int vxfs_getxattr_fd(int fd, const char *name, void *value, size_t len) +{ + int ret; + size_t size = len; + + if (vxfs_getxattr_fd_func == NULL) { + errno = ENOSYS; + return -1; + } + + DEBUG(10, ("Calling vxfs_getxattr_fd with %s\n", name)); + ret = vxfs_getxattr_fd_func(fd, name, value, &size); + if (ret) { + errno = ret; + if (ret == EFBIG) { + errno = ERANGE; + } + return -1; + } + + return size; +} + +int vxfs_getxattr_path(const char *path, const char *name, void *value, + size_t len) +{ + int ret, fd = -1; + + fd = open(path, O_RDONLY); + if (fd == -1) { + DEBUG(10, ("file not opened: vxfs_getxattr_path for %s\n", + path)); + return -1; + } + + ret = vxfs_getxattr_fd(fd, name, value, len); + close(fd); + + return ret; +} + +int vxfs_removexattr_fd(int fd, const char *name) +{ + int ret = 0; + + if (vxfs_removexattr_fd_func == NULL) { + errno = ENOSYS; + return -1; + } + + DEBUG(10, ("Calling vxfs_removexattr_fd with %s\n", name)); + ret = vxfs_removexattr_fd_func(fd, name); + if (ret) { + errno = ret; + ret = -1; + } + + return ret; +} + +int vxfs_removexattr_path(const char *path, const char *name, bool is_dir) +{ + int ret, fd = -1; + + if (is_dir) { + fd = open(path, O_RDONLY|O_DIRECTORY); + } else { + fd = open(path, O_WRONLY); + } + if (fd == -1) { + DEBUG(10, ("file not opened: vxfs_removexattr_path for %s\n", + path)); + return -1; + } + + ret = vxfs_removexattr_fd(fd, name); + close(fd); + + return ret; +} + +int vxfs_listxattr_fd(int fd, char *list, size_t size) +{ + int ret; + size_t len = size; + + if (vxfs_listxattr_fd_func == NULL) { + errno = ENOSYS; + return -1; + } + + ret = vxfs_listxattr_fd_func(fd, list, &len); + DEBUG(10, ("vxfs_listxattr_fd: returned ret = %d\n", ret)); + if (ret) { + errno = ret; + if (ret == EFBIG) { + errno = ERANGE; + } + return -1; + } + + return len; +} + +int vxfs_listxattr_path(const char *path, char *list, size_t size) +{ + int ret, fd = -1; + + fd = open(path, O_RDONLY); + if (fd == -1) { + DEBUG(10, ("file not opened: vxfs_listxattr_path for %s\n", + path)); + return -1; + } + + ret = vxfs_listxattr_fd(fd, list, size); + close(fd); + + return ret; +} + +static bool load_lib_vxfs_function(void *lib_handle, void *fn_ptr, + const char *fnc_name) +{ + void **vlib_handle = (void **)lib_handle; + void **fn_pointer = (void **)fn_ptr; + + *fn_pointer = dlsym(*vlib_handle, fnc_name); + if (*fn_pointer == NULL) { + DEBUG(10, ("Cannot find symbol for %s\n", fnc_name)); + return true; + } + + return false; +} + +void vxfs_init() +{ + static void *lib_handle = NULL; + + if (lib_handle != NULL ) { + return; + } + + lib_handle = dlopen(LIBVXFS, RTLD_LAZY); + if (lib_handle == NULL) { + DEBUG(10, ("Cannot get lib handle\n")); + return; + } + + DEBUG(10, ("Calling vxfs_init\n")); + load_lib_vxfs_function(&lib_handle, &vxfs_setxattr_fd_func, + "vxfs_nxattr_set"); + load_lib_vxfs_function(&lib_handle, &vxfs_getxattr_fd_func, + "vxfs_nxattr_get"); + load_lib_vxfs_function(&lib_handle, &vxfs_removexattr_fd_func, + "vxfs_nxattr_remove"); + load_lib_vxfs_function(&lib_handle, &vxfs_listxattr_fd_func, + "vxfs_nxattr_list"); + +} diff --git a/source3/modules/vfs_vxfs.c b/source3/modules/vfs_vxfs.c index bcd7ae3..feb3d49 100644 --- a/source3/modules/vfs_vxfs.c +++ b/source3/modules/vfs_vxfs.c @@ -1,9 +1,10 @@ /* Unix SMB/CIFS implementation. Wrap VxFS calls in vfs functions. -This module is for ACL handling. +This module is for ACL and XATTR handling. Copyright (C) Symantec Corporation <www.symantec.com> 2014 +Copyright (C) Veritas Technologies LLC <www.veritas.com> 2016 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "../libcli/security/security.h" #include "../librpc/gen_ndr/ndr_security.h" #include "system/filesys.h" +#include "vfs_vxfs.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -509,9 +511,42 @@ static int vxfs_sys_acl_set_file(vfs_handle_struct *handle, const char *name, static int vxfs_set_xattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags){ + struct smb_filename *smb_fname; + bool is_dir = false; + int ret = 0; DEBUG(10, ("In vxfs_set_xattr\n")); + smb_fname = synthetic_smb_fname(talloc_tos(), path, NULL, NULL, 0); + if (smb_fname == NULL) { + errno = ENOMEM; + return -1; + } + + if (SMB_VFS_NEXT_STAT(handle, smb_fname) != 0) { + TALLOC_FREE(smb_fname); + return -1; + } + + is_dir = S_ISDIR(smb_fname->st.st_ex_mode); + TALLOC_FREE(smb_fname); + + ret = vxfs_setxattr_path(path, name, value, size, flags, + is_dir); + if ((ret == 0) || + ((ret == -1) && (errno != ENOTSUP) && (errno != ENOSYS))) { + /* + * Now remve old style xattr if it exists + */ + SMB_VFS_NEXT_REMOVEXATTR(handle, path, name); + /* + * Do not bother about return value + */ + + return ret; + } + + DEBUG(10, ("Fallback to xattr\n")); if (strcmp(name, XATTR_NTACL_NAME) == 0) { return SMB_VFS_NEXT_SETXATTR(handle, path, XATTR_USER_NTACL, value, size, flags); @@ -529,9 +564,18 @@ static int vxfs_set_xattr(struct vfs_handle_struct *handle, const char *path, static int vxfs_fset_xattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags){ + int ret = 0; DEBUG(10, ("In vxfs_fset_xattr\n")); + ret = vxfs_setxattr_fd(fsp->fh->fd, name, value, size, flags); + if ((ret == 0) || + ((ret == -1) && (errno != ENOTSUP) && (errno != ENOSYS))) { + SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name); + return ret; + } + + DEBUG(10, ("Fallback to xattr")); if (strcmp(name, XATTR_NTACL_NAME) == 0) { return SMB_VFS_NEXT_FSETXATTR(handle, fsp, XATTR_USER_NTACL, value, size, flags); @@ -549,9 +593,16 @@ static int vxfs_fset_xattr(struct vfs_handle_struct *handle, static ssize_t vxfs_get_xattr(struct vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size){ + int ret; DEBUG(10, ("In vxfs_get_xattr\n")); + ret = vxfs_getxattr_path(path, name, value, size); + if ((ret != -1) || ((errno != ENOTSUP) && + (errno != ENOSYS) && (errno != ENODATA))) { + return ret; + } + DEBUG(10, ("Fallback to xattr\n")); if (strcmp(name, XATTR_NTACL_NAME) == 0) { return SMB_VFS_NEXT_GETXATTR(handle, path, XATTR_USER_NTACL, value, size); @@ -569,9 +620,17 @@ static ssize_t vxfs_get_xattr(struct vfs_handle_struct *handle, static ssize_t vxfs_fget_xattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size){ + int ret; DEBUG(10, ("In vxfs_fget_xattr\n")); + ret = vxfs_getxattr_fd(fsp->fh->fd, name, value, size); + if ((ret != -1) || ((errno != ENOTSUP) && + (errno != ENOSYS) && (errno != ENODATA))) { + return ret; + } + + DEBUG(10, ("Fallback to xattr\n")); if (strcmp(name, XATTR_NTACL_NAME) == 0) { return SMB_VFS_NEXT_FGETXATTR(handle, fsp, XATTR_USER_NTACL, value, size); @@ -588,38 +647,86 @@ static ssize_t vxfs_fget_xattr(struct vfs_handle_struct *handle, static int vxfs_remove_xattr(struct vfs_handle_struct *handle, const char *path, const char *name){ + struct smb_filename *smb_fname; + bool is_dir = false; + int ret = 0, ret_new = 0, old_errno; DEBUG(10, ("In vxfs_remove_xattr\n")); + /* Remove with old way */ if (strcmp(name, XATTR_NTACL_NAME) == 0) { - return SMB_VFS_NEXT_REMOVEXATTR(handle, path, XATTR_USER_NTACL); + ret = SMB_VFS_NEXT_REMOVEXATTR(handle, path, + XATTR_USER_NTACL); + } else { + if (strcasecmp(name, XATTR_USER_NTACL) != 0) { + ret = SMB_VFS_NEXT_REMOVEXATTR(handle, path, + name); + } } + old_errno = errno; - /* Clients can't see XATTR_USER_NTACL directly. */ - if (strcasecmp(name, XATTR_USER_NTACL) == 0) { - errno = ENOATTR; + /* Remove with new way */ + smb_fname = synthetic_smb_fname(talloc_tos(), path, NULL, NULL, 0); + if (smb_fname == NULL) { + errno = ENOMEM; + return -1; + } + + if (SMB_VFS_NEXT_STAT(handle, smb_fname) != 0) { + TALLOC_FREE(smb_fname); return -1; } - return SMB_VFS_NEXT_REMOVEXATTR(handle, path, name); + is_dir = S_ISDIR(smb_fname->st.st_ex_mode); + TALLOC_FREE(smb_fname); + /* + * If both fail, return failuer else return whichever succeeded + */ + ret_new = vxfs_removexattr_path(path, name, is_dir); + if (errno == ENOTSUP || errno == ENOSYS) { + errno = old_errno; + } + if ((ret_new != -1) && (ret == -1)) { + ret = ret_new; + } + + return ret; + } static int vxfs_fremove_xattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name){ + int ret = 0, ret_new = 0, old_errno; DEBUG(10, ("In vxfs_fremove_xattr\n")); + /* Remove with old way */ if (strcmp(name, XATTR_NTACL_NAME) == 0) { - return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, XATTR_USER_NTACL); + ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, + XATTR_USER_NTACL); + } else { + /* Clients can't remove XATTR_USER_NTACL directly. */ + if (strcasecmp(name, XATTR_USER_NTACL) != 0) { + ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, + name); + } } + old_errno = errno; - /* Clients can't remove XATTR_USER_NTACL directly. */ - if (strcasecmp(name, XATTR_USER_NTACL) == 0) { - errno = ENOATTR; - return -1; + /* Remove with new way */ + ret_new = vxfs_removexattr_fd(fsp->fh->fd, name); + /* + * If both fail, return failuer else return whichever succeeded + */ + if (errno == ENOTSUP || errno == ENOSYS) { + errno = old_errno; + } + if ((ret_new != -1) && (ret == -1)) { + ret = ret_new; } - return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name); + return ret; + } static size_t vxfs_filter_list(char *list, size_t size) @@ -645,6 +752,11 @@ static ssize_t vxfs_listxattr(vfs_handle_struct *handle, const char *path, { ssize_t result; + result = vxfs_listxattr_path(path, list, size); + if (result >= 0 || ((errno != ENOTSUP) && (errno != ENOSYS))) { + return result; + } + result = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size); if (result <= 0) { @@ -663,6 +775,11 @@ static ssize_t vxfs_flistxattr(struct vfs_handle_struct *handle, { ssize_t result; + result = vxfs_listxattr_fd(fsp->fh->fd, list, size); + if (result >= 0 || ((errno != ENOTSUP) && (errno != ENOSYS))) { + return result; + } + result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size); if (result <= 0) { @@ -679,19 +796,25 @@ static int vfs_vxfs_connect(struct vfs_handle_struct *handle, const char *service, const char *user) { - int ret = SMB_VFS_NEXT_CONNECT(handle, service, user); + int ret; -- Samba Shared Repository