From 5a052edf031d2c02b018743f0947a12b4df16c2d Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 14 Feb 2007 02:37:14 +0000 Subject: r21324: Add linux setlease to the vfs layer. Next round, as Volker points out, it should be abstracted a little higher up so other os'es can have an entry, but it will take a bit more work. Thanks to Chetan Shringarpure and Mathias Dietz. I didn't increment the vfs number again because the kernel change notify stuff hasn't been released yet anyway. (This used to be commit 9463211bf3b46ee408b88dfbf42d498e3839d4cc) --- source3/include/smbprofile.h | 4 ++++ source3/include/vfs.h | 6 +++++- source3/include/vfs_macros.h | 3 +++ source3/modules/vfs_default.c | 19 +++++++++++++++++++ source3/modules/vfs_full_audit.c | 18 ++++++++++++++++++ source3/modules/vfs_gpfs.c | 29 +++++++++++++++++++++++++++++ source3/profile/profile.c | 1 + source3/smbd/oplock_linux.c | 27 ++++++++++++++++++--------- 8 files changed, 97 insertions(+), 10 deletions(-) (limited to 'source3') diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index 48a44948dc..fa7c6e4a5a 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -168,6 +168,10 @@ enum profile_stats_values #define syscall_kernel_flock_count __profile_stats_value(PR_VALUE_SYSCALL_KERNEL_FLOCK, count) #define syscall_kernel_flock_time __profile_stats_value(PR_VALUE_SYSCALL_KERNEL_FLOCK, time) + PR_VALUE_SYSCALL_LINUX_SETLEASE, +#define syscall_linux_setlease_count __profile_stats_value(PR_VALUE_SYSCALL_LINUX_SETLEASE, count) +#define syscall_linux_setlease_time __profile_stats_value(PR_VALUE_SYSCALL_LINUX_SETLEASE, time) + PR_VALUE_SYSCALL_FCNTL_GETLOCK, #define syscall_fcntl_getlock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, count) #define syscall_fcntl_getlock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, time) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 322f08867f..4c2b559bea 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -65,7 +65,8 @@ /* Changed to version 17 as we removed redundant connection_struct parameters. --jpeach */ /* Changed to version 18 to add fsp parameter to the open call -- jpeach Also include kernel_flock call - jmcd */ -/* Changed to version 19, kernel change notify has been merged */ +/* Changed to version 19, kernel change notify has been merged + Also included linux setlease call - jmcd */ #define SMB_VFS_INTERFACE_VERSION 19 @@ -147,6 +148,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_FTRUNCATE, SMB_VFS_OP_LOCK, SMB_VFS_OP_KERNEL_FLOCK, + SMB_VFS_OP_LINUX_SETLEASE, SMB_VFS_OP_GETLOCK, SMB_VFS_OP_SYMLINK, SMB_VFS_OP_READLINK, @@ -271,6 +273,7 @@ struct vfs_ops { int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset); BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 share_mode); + int (*linux_setlease)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int leasetype); BOOL (*getlock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid); int (*symlink)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath); int (*readlink)(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz); @@ -393,6 +396,7 @@ struct vfs_ops { struct vfs_handle_struct *ftruncate; struct vfs_handle_struct *lock; struct vfs_handle_struct *kernel_flock; + struct vfs_handle_struct *linux_setlease; struct vfs_handle_struct *getlock; struct vfs_handle_struct *symlink; struct vfs_handle_struct *readlink; diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index d63afb13ea..f50da3a02b 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -71,6 +71,7 @@ #define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_KERNEL_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs.ops.kernel_flock((fsp)->conn->vfs.handles.kernel_flock, (fsp), (fd), (share_mode))) +#define SMB_VFS_LINUX_SETLEASE(fsp, fd, leasetype) ((fsp)->conn->vfs.ops.linux_setlease((fsp)->conn->vfs.handles.linux_setlease, (fsp), (fd), (leasetype))) #define SMB_VFS_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs.ops.getlock((fsp)->conn->vfs.handles.getlock, (fsp), (fd) ,(poffset), (pcount), (ptype), (ppid))) #define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (oldpath), (newpath))) #define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (path), (buf), (bufsiz))) @@ -185,6 +186,7 @@ #define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_OPAQUE_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.kernel_flock, (fsp), (fd), (share_mode))) +#define SMB_VFS_OPAQUE_LINUX_SETLEASE(fsp, fd, leasetype) ((fsp)->conn->vfs_opaque.ops.linux_setlease((fsp)->conn->vfs_opaque.handles.linux_setlease, (fsp), (fd), (leasetype))) #define SMB_VFS_OPAQUE_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs_opaque.ops.getlock((fsp)->conn->vfs_opaque.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid))) #define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (oldpath), (newpath))) #define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (path), (buf), (bufsiz))) @@ -300,6 +302,7 @@ #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, fd, share_mode)((handle)->vfs_next.ops.kernel_flock((handle)->vfs_next.handles.kernel_flock, (fsp), (fd), (share_mode))) +#define SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, fd, leasetype)((handle)->vfs_next.ops.linux_setlease((handle)->vfs_next.handles.linux_setlease, (fsp), (fd), (leasetype))) #define SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid) ((handle)->vfs_next.ops.getlock((handle)->vfs_next.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid))) #define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (oldpath), (newpath))) #define SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (path), (buf), (bufsiz))) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 6defa238b9..90fd30c604 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -783,6 +783,23 @@ static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd return result; } +static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp, int fd, + int leasetype) +{ + int result; + + START_PROFILE(syscall_linux_setlease); + + /* first set the signal handler */ + if(linux_set_lease_sighandler(fd) == -1) + return -1; + + result = linux_setlease(fd, leasetype); + + END_PROFILE(syscall_linux_setlease); + return result; +} + static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { int result; @@ -1227,6 +1244,8 @@ static vfs_op_tuple vfs_default_ops[] = { SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_kernel_flock), SMB_VFS_OP_KERNEL_FLOCK, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_linux_setlease), SMB_VFS_OP_LINUX_SETLEASE, + 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_full_audit.c b/source3/modules/vfs_full_audit.c index e632040dc1..6036e49fc1 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -160,6 +160,8 @@ static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, in static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 share_mode); +static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct *fsp, + int fd, int leasetype); static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid); static int smb_full_audit_symlink(vfs_handle_struct *handle, @@ -381,6 +383,8 @@ static vfs_op_tuple audit_op_tuples[] = { SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_kernel_flock), SMB_VFS_OP_KERNEL_FLOCK, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(smb_full_audit_linux_setlease), SMB_VFS_OP_LINUX_SETLEASE, + SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_symlink), SMB_VFS_OP_SYMLINK, @@ -549,6 +553,7 @@ static struct { { SMB_VFS_OP_FTRUNCATE, "ftruncate" }, { SMB_VFS_OP_LOCK, "lock" }, { SMB_VFS_OP_KERNEL_FLOCK, "kernel_flock" }, + { SMB_VFS_OP_LINUX_SETLEASE, "linux_setlease" }, { SMB_VFS_OP_GETLOCK, "getlock" }, { SMB_VFS_OP_SYMLINK, "symlink" }, { SMB_VFS_OP_READLINK, "readlink" }, @@ -1313,6 +1318,19 @@ static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle, return result; } +static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct *fsp, + int fd, int leasetype) +{ + int result; + + result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, fd, leasetype); + + do_log(SMB_VFS_OP_LINUX_SETLEASE, (result >= 0), handle, "%s", + fsp->fsp_name); + + return result; +} + static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid) { diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index c8bb848d0f..20c9f56a17 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -52,6 +52,31 @@ static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp, return 0; } +static int vfs_gpfs_setlease(vfs_handle_struct *handle, files_struct *fsp, + int fd, int leasetype) +{ + int ret; + + START_PROFILE(syscall_linux_setlease); + + if ( linux_set_lease_sighandler(fd) == -1) + return -1; + + ret = set_gpfs_lease(fd,leasetype); + + if ( ret < 0 ) { + /* This must have come from GPFS not being available */ + /* or some other error, hence call the default */ + ret = linux_setlease(fd, leasetype); + } + + END_PROFILE(syscall_linux_setlease); + + return ret; +} + + + static void gpfs_dumpacl(int level, struct gpfs_acl *gacl) { int i; @@ -592,6 +617,10 @@ static vfs_op_tuple gpfs_op_tuples[] = { SMB_VFS_OP_KERNEL_FLOCK, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfs_gpfs_setlease), + SMB_VFS_OP_LINUX_SETLEASE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(gpfsacl_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, diff --git a/source3/profile/profile.c b/source3/profile/profile.c index 8aaaee161d..fc22e07fa9 100644 --- a/source3/profile/profile.c +++ b/source3/profile/profile.c @@ -289,6 +289,7 @@ BOOL profile_setup(BOOL rdonly) "syscall_ftruncate", /* PR_VALUE_SYSCALL_FTRUNCATE */ "syscall_fcntl_lock", /* PR_VALUE_SYSCALL_FCNTL_LOCK */ "syscall_kernel_flock", /* PR_VALUE_SYSCALL_KERNEL_FLOCK */ + "syscall_linux_setlease", /* PR_VALUE_SYSCALL_LINUX_SETLEASE */ "syscall_fcntl_getlock", /* PR_VALUE_SYSCALL_FCNTL_GETLOCK */ "syscall_readlink", /* PR_VALUE_SYSCALL_READLINK */ "syscall_symlink", /* PR_VALUE_SYSCALL_SYMLINK */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 518283c587..14db98cde6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -102,20 +102,29 @@ static void set_capability(unsigned capability) } } +/* + Call to set the kernel lease signal handler +*/ +int linux_set_lease_sighandler(int fd) +{ + if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) { + DEBUG(3,("Failed to set signal handler for kernel lease\n")); + return -1; + } + + return 0; +} + /**************************************************************************** Call SETLEASE. If we get EACCES then we try setting up the right capability and - try again + try again. + Use the SMB_VFS_LINUX_SETLEASE instead of this call directly. ****************************************************************************/ -static int linux_setlease(int fd, int leasetype) +int linux_setlease(int fd, int leasetype) { int ret; - if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) { - DEBUG(3,("Failed to set signal handler for kernel lease\n")); - return -1; - } - ret = fcntl(fd, F_SETLEASE, leasetype); if (ret == -1 && errno == EACCES) { set_capability(CAP_LEASE); @@ -156,7 +165,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 ( SMB_VFS_LINUX_SETLEASE(fsp,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, @@ -194,7 +203,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) /* * Remove the kernel oplock on this file. */ - if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { + if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); -- cgit