diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/configure.in | 13 | ||||
-rw-r--r-- | source3/param/loadparm.c | 4 | ||||
-rw-r--r-- | source3/smbd/gpfs.c | 159 | ||||
-rw-r--r-- | source3/smbd/open.c | 14 | ||||
-rw-r--r-- | source3/smbd/oplock_linux.c | 22 | ||||
-rw-r--r-- | source3/smbd/server.c | 2 |
7 files changed, 209 insertions, 7 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 9d00cb72a1..54dbecb764 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -403,7 +403,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ lib/sysquotas_xfs.o lib/sysquotas_4A.o \ smbd/change_trust_pw.o smbd/fake_file.o \ smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \ - $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \ + $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/gpfs.o smbd/statvfs.o \ $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ diff --git a/source3/configure.in b/source3/configure.in index ec1bdacad8..2b1f4d691f 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1159,6 +1159,19 @@ AC_CHECK_FUNCS(setbuffer shmget shm_open backtrace_symbols) AC_CHECK_HEADERS(libexc.h) AC_CHECK_LIB(exc, trace_back_stack) +echo -n "checking for GPFS 2.4 libs... " +save_LIBS="$LIBS" +LIBS="$LIBS -lgpfs" +AC_TRY_LINK([#include <gpfs.h>], + [gpfs_set_share(0,GPFS_SHARE_READ,GPFS_DENY_NONE)], + samba_cv_HAVE_GPFS_SET_SHARE=yes, + samba_cv_HAVE_GPFS_SET_SHARE=no) +echo $samba_cv_HAVE_GPFS_SET_SHARE +if test x"$samba_cv_HAVE_GPFS_SET_SHARE" = x"yes"; then + AC_DEFINE(HAVE_GPFS_SET_SHARE,1,[Whether GPFS 2.4 libs are available]) +fi +LIBS="$save_LIBS" + # syscall() is needed for smbwrapper. AC_CHECK_FUNCS(syscall) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 526bce9b60..3fa6dee5a2 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -433,6 +433,7 @@ typedef struct BOOL bProfileAcls; BOOL bMap_acl_inherit; BOOL bAfs_Share; + BOOL bGpfs_Share; BOOL bEASupport; BOOL bAclCheckPermissions; BOOL bAclMapFullControl; @@ -569,6 +570,7 @@ static service sDefault = { False, /* bProfileAcls */ False, /* bMap_acl_inherit */ False, /* bAfs_Share */ + False, /* bGpfs_Share */ False, /* bEASupport */ True, /* bAclCheckPermissions */ True, /* bAclMapFullControl */ @@ -967,6 +969,7 @@ static struct parm_struct parm_table[] = { {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_ADVANCED}, {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"afs share", P_BOOL, P_LOCAL, &sDefault.bAfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"gpfs share", P_BOOL, P_LOCAL, &sDefault.bGpfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED}, {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED}, @@ -2001,6 +2004,7 @@ FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile) FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls) FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit) FN_LOCAL_BOOL(lp_afs_share, bAfs_Share) +FN_LOCAL_BOOL(lp_gpfs_share, bGpfs_Share) FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions) FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl) FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl) diff --git a/source3/smbd/gpfs.c b/source3/smbd/gpfs.c new file mode 100644 index 0000000000..4a8b9eea6c --- /dev/null +++ b/source3/smbd/gpfs.c @@ -0,0 +1,159 @@ +/* + * 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_SET_SHARE + +#include "gpfs.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); + +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, ("'gpfs share = yes' set, but no gpfs " + "available. 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); +} + +void init_gpfs(void) +{ + if (libgpfs_handle != NULL) { + return; + } + + libgpfs_handle = sys_dlopen("libgpfs.so", RTLD_LAZY); + + if (libgpfs_handle == NULL) { + DEBUG(10, ("sys_dlopen for libgpfs.so failed: %s\n", + strerror(errno))); + return; + } + + DEBUG(10, ("libgpfs.so loaded\n")); + + gpfs_set_share_fn = sys_dlsym(libgpfs_handle, "gpfs_set_share"); + if (gpfs_set_share_fn == NULL) { + DEBUG(3, ("libgpfs.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_lease_fn = NULL; + return; + } + + gpfs_set_lease_fn = sys_dlsym(libgpfs_handle, "gpfs_set_lease"); + if (gpfs_set_lease_fn == NULL) { + DEBUG(3, ("libgpfs.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; + return; + } +} + +#else + +int set_gpfs_lease(int snum, int leasetype) +{ + DEBUG(0, ("'gpfs share = yes' set 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, ("'gpfs share = yes' set without gpfs support compiled\n")); + /* Don't disturb but complain */ + return True; +} + +void init_gpfs(void) +{ + return; +} + +#endif diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6c749fab9..2f82f04b63 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1599,6 +1599,20 @@ files_struct *open_file_ntcreate(connection_struct *conn, * deny mode is compatible with all current opens. */ + if (lp_gpfs_share(SNUM(fsp->conn)) && + !set_gpfs_sharemode(fsp, access_mask, share_access)) { + + /* GPFS does have share mode support, so the comment above wrt + * NFS being wrong is not correct here. */ + + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + talloc_free(lck); + fd_close(conn, fsp); + file_free(fsp); + return NULL; + } + /* * If requested, truncate the file. */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index ab0c08f7fc..0285bfce97 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -101,11 +101,11 @@ static void set_capability(unsigned capability) } /**************************************************************************** - Call SETLEASE. If we get EACCES then we try setting up the right capability and - try again + Call SETLEASE. If we get EACCES then we try setting up the right capability + and try again ****************************************************************************/ -static int linux_setlease(int fd, int leasetype) +static int linux_setlease(int snum, int fd, int leasetype) { int ret; @@ -114,7 +114,17 @@ static int linux_setlease(int fd, int leasetype) return -1; } - ret = fcntl(fd, F_SETLEASE, leasetype); + if (lp_gpfs_share(snum)) { + ret = set_gpfs_lease(fd, leasetype); + } else { + ret = fcntl(fd, F_SETLEASE, leasetype); + } + + if ((ret < 0) && (errno == ENOSYS)) { + /* This must have come from GPFS not being available */ + ret = fcntl(fd, F_SETLEASE, leasetype); + } + if (ret == -1 && errno == EACCES) { set_capability(CAP_LEASE); ret = fcntl(fd, F_SETLEASE, leasetype); @@ -154,7 +164,7 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) { + if (linux_setlease(SNUM(fsp->conn), fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fh->fd, @@ -188,7 +198,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { + if (linux_setlease(SNUM(fsp->conn), fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ff894e2460..56c9c72127 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -899,6 +899,8 @@ void build_options(BOOL screen); if (!print_backend_init()) exit(1); + init_gpfs(); + /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ |