[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Fri Jun 3 05:27:03 UTC 2016
The branch, master has been updated
via 469fdcd Efficient xattr handling for VxFS Signed-off-by: Abhidnya Joshi <Abhidnya.Joshi at 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.Joshi at veritas.com>
Date: Wed Jun 1 23:38:31 2016 -0700
Efficient xattr handling for VxFS Signed-off-by: Abhidnya Joshi <Abhidnya.Joshi at veritas.com>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Autobuild-User(master): Jeremy Allison <jra at 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
More information about the samba-cvs
mailing list