From 4fe70bcee2ec8515f123d8c826631b54bbf793e7 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 9 Nov 2006 20:29:31 +0000 Subject: r19647: Add some GPFS support in a vfs mod. Also adds the kernel flock op to the vfs layer, since gpfs supports it. Thanks to Volker, Christian, Mathias, Chetan, and Peter. (This used to be commit 0620658890fa9c68a9848538728023192319c81a) --- source3/modules/gpfs.c | 231 ++++++++++++++++++++++++++++++++++++++++++ source3/modules/vfs_default.c | 11 ++ source3/modules/vfs_gpfs.c | 68 +++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 source3/modules/gpfs.c create mode 100644 source3/modules/vfs_gpfs.c (limited to 'source3/modules') diff --git a/source3/modules/gpfs.c b/source3/modules/gpfs.c new file mode 100644 index 0000000000..f63a85294b --- /dev/null +++ b/source3/modules/gpfs.c @@ -0,0 +1,231 @@ +/* + * Unix SMB/CIFS implementation. + * Provide a connection to GPFS specific features + * Copyright (C) Volker Lendecke 2005 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#ifdef HAVE_GPFS + +#include "gpfs_gpl.h" + +static void *libgpfs_handle = NULL; + +static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny); +static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType); +static int (*gpfs_getacl_fn)(char *pathname, int flags, void *acl); +static int (*gpfs_putacl_fn)(char *pathname, int flags, void *acl); + + +BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, + uint32 share_access) +{ + unsigned int allow = GPFS_SHARE_NONE; + unsigned int deny = GPFS_DENY_NONE; + int result; + + if (gpfs_set_share_fn == NULL) { + return False; + } + + if ((fsp == NULL) || (fsp->fh == NULL) || (fsp->fh->fd < 0)) { + /* No real file, don't disturb */ + return True; + } + + allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA| + DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0; + allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ? + GPFS_SHARE_READ : 0; + deny |= (share_access & (FILE_SHARE_WRITE|FILE_SHARE_DELETE)) ? + 0 : GPFS_DENY_WRITE; + deny |= (share_access & (FILE_SHARE_READ)) ? + 0 : GPFS_DENY_READ; + + DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n", + access_mask, allow, share_access, deny)); + + result = gpfs_set_share_fn(fsp->fh->fd, allow, deny); + if (result != 0) { + if (errno == ENOSYS) { + DEBUG(5, ("VFS module vfs_gpfs loaded, but no gpfs " + "support has been compiled into Samba. Allowing access\n")); + return True; + } else { + DEBUG(10, ("gpfs_set_share failed: %s\n", + strerror(errno))); + } + } + + return (result == 0); +} + +int set_gpfs_lease(int fd, int leasetype) +{ + int gpfs_type = GPFS_LEASE_NONE; + + if (gpfs_set_lease_fn == NULL) { + errno = EINVAL; + return -1; + } + + if (leasetype == F_RDLCK) { + gpfs_type = GPFS_LEASE_READ; + } + if (leasetype == F_WRLCK) { + gpfs_type = GPFS_LEASE_WRITE; + } + return gpfs_set_lease_fn(fd, gpfs_type); +} + +int smbd_gpfs_getacl(char *pathname, int flags, void *acl) +{ + if (gpfs_getacl_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_getacl_fn(pathname, flags, acl); +} + +int smbd_gpfs_putacl(char *pathname, int flags, void *acl) +{ + if (gpfs_putacl_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_putacl_fn(pathname, flags, acl); +} + +void init_gpfs(void) +{ + if (libgpfs_handle != NULL) { + return; + } + + libgpfs_handle = sys_dlopen("libgpfs_gpl.so", RTLD_LAZY); + + if (libgpfs_handle == NULL) { + DEBUG(10, ("sys_dlopen for libgpfs_gpl failed: %s\n", + strerror(errno))); + return; + } + + DEBUG(10, ("libgpfs_gpl.so loaded\n")); + + gpfs_set_share_fn = sys_dlsym(libgpfs_handle, "gpfs_set_share"); + if (gpfs_set_share_fn == NULL) { + DEBUG(3, ("libgpfs_gpl.so does not contain the symbol " + "'gpfs_set_share'\n")); + sys_dlclose(libgpfs_handle); + + /* leave libgpfs_handle != NULL around, no point + in trying twice */ + gpfs_set_share_fn = NULL; + gpfs_set_lease_fn = NULL; + gpfs_getacl_fn = NULL; + gpfs_putacl_fn = NULL; + return; + } + + gpfs_set_lease_fn = sys_dlsym(libgpfs_handle, "gpfs_set_lease"); + if (gpfs_set_lease_fn == NULL) { + DEBUG(3, ("libgpfs_gpl.so does not contain the symbol " + "'gpfs_set_lease'\n")); + sys_dlclose(libgpfs_handle); + + /* leave libgpfs_handle != NULL around, no point + in trying twice */ + gpfs_set_share_fn = NULL; + gpfs_set_lease_fn = NULL; + gpfs_getacl_fn = NULL; + gpfs_putacl_fn = NULL; + return; + } + + gpfs_getacl_fn = sys_dlsym(libgpfs_handle, "gpfs_getacl"); + if (gpfs_getacl_fn == NULL) { + DEBUG(3, ("libgpfs_gpl.so does not contain the symbol " + "'gpfs_getacl'\n")); + sys_dlclose(libgpfs_handle); + + /* leave libgpfs_handle != NULL around, no point + in trying twice */ + gpfs_set_share_fn = NULL; + gpfs_set_lease_fn = NULL; + gpfs_getacl_fn = NULL; + gpfs_putacl_fn = NULL; + return; + } + + gpfs_putacl_fn = sys_dlsym(libgpfs_handle, "gpfs_putacl"); + if (gpfs_putacl_fn == NULL) { + DEBUG(3, ("libgpfs_gpl.so does not contain the symbol " + "'gpfs_putacl'\n")); + sys_dlclose(libgpfs_handle); + + /* leave libgpfs_handle != NULL around, no point + in trying twice */ + gpfs_set_share_fn = NULL; + gpfs_set_lease_fn = NULL; + gpfs_getacl_fn = NULL; + gpfs_putacl_fn = NULL; + return; + } + +} + +#else + +int set_gpfs_lease(int snum, int leasetype) +{ + DEBUG(0, ("'VFS module smbgpfs loaded, without gpfs support compiled\n")); + + /* We need to indicate that no GPFS is around by returning ENOSYS, so + * that the normal linux kernel oplock code is called. */ + errno = ENOSYS; + return -1; +} + +BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, + uint32 share_access) +{ + DEBUG(0, ("VFS module - smbgpfs.so loaded, without gpfs support compiled\n")); + /* Don't disturb but complain */ + return True; +} + +int smbd_gpfs_getacl(char *pathname, int flags, void *acl) +{ + errno = ENOSYS; + return -1; +} + +int smbd_gpfs_putacl(char *pathname, int flags, void *acl) +{ + errno = ENOSYS; + return -1; +} + +void init_gpfs(void) +{ + return; +} + +#endif /* HAVE_GPFS */ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index ae565ae980..486a76ac88 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -764,6 +764,15 @@ static BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, i return result; } +static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp, int fd, + uint32 share_mode) +{ + START_PROFILE(syscall_kernel_flock); + kernel_flock(fd, share_mode); + END_PROFILE(syscall_kernel_flock); + return 0; +} + static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid) { BOOL result; @@ -1189,6 +1198,8 @@ static vfs_op_tuple vfs_default_ops[] = { SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_kernel_flock), SMB_VFS_OP_KERNEL_FLOCK, + SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_symlink), SMB_VFS_OP_SYMLINK, diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c new file mode 100644 index 0000000000..c5658ceb51 --- /dev/null +++ b/source3/modules/vfs_gpfs.c @@ -0,0 +1,68 @@ +/* + Unix SMB/CIFS implementation. + Wrap gpfs calls in vfs functions. + + Copyright (C) Christian Ambach 2006 + + Major code contributions by Chetan Shringarpure + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +*/ + +#include "includes.h" + + +static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp, + int fd, uint32 share_mode) +{ + + START_PROFILE(syscall_kernel_flock); + + kernel_flock(fsp->fh->fd, share_mode); + + if (!set_gpfs_sharemode(fsp, fsp->access_mask, fsp->share_access)) { + + return -1; + + } + + END_PROFILE(syscall_kernel_flock); + + return 0; +} + + +static vfs_op_tuple gpfs_op_tuples[] = { + + {SMB_VFS_OP(vfs_gpfs_kernel_flock), + SMB_VFS_OP_KERNEL_FLOCK, + SMB_VFS_LAYER_OPAQUE}, + + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} + +}; + + +NTSTATUS vfs_gpfs_init(void) +{ + init_gpfs(); + + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs", + gpfs_op_tuples); +} -- cgit