s3: VFS: Add SMB_VFS_FCNTL
authorAnoop C S <anoopcs@redhat.com>
Fri, 27 Sep 2019 05:49:37 +0000 (11:19 +0530)
committerRalph Boehme <slow@samba.org>
Tue, 8 Oct 2019 08:38:32 +0000 (08:38 +0000)
Signed-off-by: Anoop C S <anoopcs@redhat.com>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
13 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/proto.h
source3/include/smbprofile.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/lib/system.c
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_not_implemented.c
source3/modules/vfs_time_audit.c
source3/smbd/vfs.c
source3/wscript

index 59804675c8e56eec7891a98353c11fe9bf244fe8..be3773965e78747611fa669e3c654f785434b02f 100644 (file)
@@ -444,6 +444,13 @@ static int skel_kernel_flock(struct vfs_handle_struct *handle,
        return -1;
 }
 
+static int skel_fcntl(struct vfs_handle_struct *handle,
+                     struct files_struct *fsp, int cmd, va_list cmd_arg)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 static int skel_linux_setlease(struct vfs_handle_struct *handle,
                               struct files_struct *fsp, int leasetype)
 {
@@ -1091,6 +1098,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
        .fallocate_fn = skel_fallocate,
        .lock_fn = skel_lock,
        .kernel_flock_fn = skel_kernel_flock,
+       .fcntl_fn = skel_fcntl,
        .linux_setlease_fn = skel_linux_setlease,
        .getlock_fn = skel_getlock,
        .symlinkat_fn = skel_symlinkat,
index c73c2a2692b543c24212c3af3143a680d465071b..063af8f3aed69c0e2e918cfbb02a853a3fcce672 100644 (file)
@@ -552,6 +552,21 @@ static int skel_kernel_flock(struct vfs_handle_struct *handle,
        return SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode, access_mask);
 }
 
+static int skel_fcntl(struct vfs_handle_struct *handle,
+                     struct files_struct *fsp, int cmd, va_list cmd_arg)
+{
+       void *arg;
+       va_list dup_cmd_arg;
+       int result;
+
+       va_copy(dup_cmd_arg, cmd_arg);
+       arg = va_arg(dup_cmd_arg, void *);
+       result = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
+       va_end(dup_cmd_arg);
+
+       return result;
+}
+
 static int skel_linux_setlease(struct vfs_handle_struct *handle,
                               struct files_struct *fsp, int leasetype)
 {
@@ -1379,6 +1394,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
        .fallocate_fn = skel_fallocate,
        .lock_fn = skel_lock,
        .kernel_flock_fn = skel_kernel_flock,
+       .fcntl_fn = skel_fcntl,
        .linux_setlease_fn = skel_linux_setlease,
        .getlock_fn = skel_getlock,
        .symlinkat_fn = skel_symlinkat,
index 91a7c00fef293b8833bb77acd948625274947362..c98f7cfa351b8c5d96d8b1a67a7af77eeb9cb9be 100644 (file)
@@ -219,6 +219,7 @@ ssize_t sys_send(int s, const void *msg, size_t len, int flags);
 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
 int sys_fcntl_ptr(int fd, int cmd, void *arg);
 int sys_fcntl_long(int fd, int cmd, long arg);
+int sys_fcntl_int(int fd, int cmd, int arg);
 void update_stat_ex_mtime(struct stat_ex *dst, struct timespec write_ts);
 void update_stat_ex_itime(struct stat_ex *dst, struct timespec itime);
 void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time);
index cc54dea271092aec19e2f33f40033880da82334d..ea2a29a0758c319ad4b3f2b4a807883b5464fffa 100644 (file)
@@ -80,6 +80,7 @@ struct tevent_context;
        SMBPROFILE_STATS_BASIC(syscall_fallocate) \
        SMBPROFILE_STATS_BASIC(syscall_fcntl_lock) \
        SMBPROFILE_STATS_BASIC(syscall_kernel_flock) \
+       SMBPROFILE_STATS_BASIC(syscall_fcntl) \
        SMBPROFILE_STATS_BASIC(syscall_linux_setlease) \
        SMBPROFILE_STATS_BASIC(syscall_fcntl_getlock) \
        SMBPROFILE_STATS_BASIC(syscall_readlinkat) \
index 6ba653f56c74ed6fa32a808eaeba105326a82bb7..326687f5ee109ce62d8c9ed52ec2629213bf3faa 100644 (file)
 /* Version 42 - Move change_to_user_by_fsp() -> change_to_user_and_service_by_fsp() */
 /* Version 42 - Move [un]become_user*() -> [un]become_user_without_service*() */
 /* Version 42 - Move SMB_VFS_UNLINK -> SMB_VFS_UNLINKAT. */
+/* Version 42 - Add SMB_VFS_FCNTL */
 
 #define SMB_VFS_INTERFACE_VERSION 42
 
@@ -810,6 +811,8 @@ struct vfs_fn_pointers {
        bool (*lock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, off_t offset, off_t count, int type);
        int (*kernel_flock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp,
                               uint32_t share_mode, uint32_t access_mask);
+       int (*fcntl_fn)(struct vfs_handle_struct *handle,
+                       struct files_struct *fsp, int cmd, va_list cmd_arg);
        int (*linux_setlease_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int leasetype);
        bool (*getlock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid);
        int (*symlinkat_fn)(struct vfs_handle_struct *handle,
@@ -1345,6 +1348,8 @@ bool smb_vfs_call_lock(struct vfs_handle_struct *handle,
 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
                              struct files_struct *fsp, uint32_t share_mode,
                              uint32_t access_mask);
+int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
+                      struct files_struct *fsp, int cmd, ...);
 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
                                struct files_struct *fsp, int leasetype);
 bool smb_vfs_call_getlock(struct vfs_handle_struct *handle,
@@ -1780,6 +1785,8 @@ bool vfs_not_implemented_lock(vfs_handle_struct *handle, files_struct *fsp, int
 int vfs_not_implemented_kernel_flock(struct vfs_handle_struct *handle,
                                     struct files_struct *fsp,
                                     uint32_t share_mode, uint32_t access_mask);
+int vfs_not_implemented_fcntl(struct vfs_handle_struct *handle,
+                             struct files_struct *fsp, int cmd, va_list cmd_arg);
 int vfs_not_implemented_linux_setlease(struct vfs_handle_struct *handle,
                                       struct files_struct *fsp, int leasetype);
 bool vfs_not_implemented_getlock(vfs_handle_struct *handle, files_struct *fsp,
index 2979769e7d5d7990deb8b4f474b8411b6989b5ea..2dd59711e190b6f465ebc60d09987aff9416dda6 100644 (file)
 #define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode, access_mask)        \
        smb_vfs_call_kernel_flock((handle)->next, (fsp), (share_mode), (access_mask))
 
+#define SMB_VFS_FCNTL(fsp, cmd, ...) \
+       smb_vfs_call_fcntl((fsp)->conn->vfs_handles, (fsp), (cmd), (__VA_ARGS__))
+#define SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, ...) \
+       smb_vfs_call_fcntl((handle)->next, (fsp), (cmd), (__VA_ARGS__))
+
 #define SMB_VFS_LINUX_SETLEASE(fsp, leasetype) \
        smb_vfs_call_linux_setlease((fsp)->conn->vfs_handles, (fsp), (leasetype))
 #define SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype) \
index def8281fc437172c2573c24b29557e7a62665ac6..679332255c008aa3300ef5c7cef38d80d30d23b3 100644 (file)
@@ -108,6 +108,20 @@ int sys_fcntl_long(int fd, int cmd, long arg)
        return ret;
 }
 
+/*******************************************************************
+A fcntl wrapper that will deal with EINTR.
+********************************************************************/
+
+int sys_fcntl_int(int fd, int cmd, int arg)
+{
+       int ret;
+
+       do {
+               ret = fcntl(fd, cmd, arg);
+       } while (ret == -1 && errno == EINTR);
+       return ret;
+}
+
 /****************************************************************************
  Get/Set all the possible time fields from a stat struct as a timespec.
 ****************************************************************************/
index 738be3bf2d69af297357710fbf8444b0bd369176..9bf8005bcd7a31df5019c54eb80e9b2319716d30 100644 (file)
@@ -2615,6 +2615,51 @@ static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
        return 0;
 }
 
+static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
+                        va_list cmd_arg)
+{
+       void *argp;
+       va_list dup_cmd_arg;
+       int result;
+       int val;
+
+       START_PROFILE(syscall_fcntl);
+
+       va_copy(dup_cmd_arg, cmd_arg);
+
+       switch(cmd) {
+       case F_SETLK:
+       case F_SETLKW:
+       case F_GETLK:
+#if defined(HAVE_OFD_LOCKS)
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
+       case F_OFD_GETLK:
+#endif
+#if defined(HAVE_F_OWNER_EX)
+       case F_GETOWN_EX:
+       case F_SETOWN_EX:
+#endif
+#if defined(HAVE_RW_HINTS)
+       case F_GET_RW_HINT:
+       case F_SET_RW_HINT:
+       case F_GET_FILE_RW_HINT:
+       case F_SET_FILE_RW_HINT:
+#endif
+               argp = va_arg(dup_cmd_arg, void *);
+               result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
+               break;
+       default:
+               val = va_arg(dup_cmd_arg, int);
+               result = sys_fcntl_int(fsp->fh->fd, cmd, val);
+       }
+
+       va_end(dup_cmd_arg);
+
+       END_PROFILE(syscall_fcntl);
+       return result;
+}
+
 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
 {
        bool result;
@@ -3506,6 +3551,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .fallocate_fn = vfswrap_fallocate,
        .lock_fn = vfswrap_lock,
        .kernel_flock_fn = vfswrap_kernel_flock,
+       .fcntl_fn = vfswrap_fcntl,
        .linux_setlease_fn = vfswrap_linux_setlease,
        .getlock_fn = vfswrap_getlock,
        .symlinkat_fn = vfswrap_symlinkat,
index de591eb213688f6f42bd2a74bc2a5fabaf5af78d..757cd26d3f1952894a15b7ae528fbd4925e0a7f6 100644 (file)
@@ -151,6 +151,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_FALLOCATE,
        SMB_VFS_OP_LOCK,
        SMB_VFS_OP_KERNEL_FLOCK,
+       SMB_VFS_OP_FCNTL,
        SMB_VFS_OP_LINUX_SETLEASE,
        SMB_VFS_OP_GETLOCK,
        SMB_VFS_OP_SYMLINKAT,
@@ -1734,6 +1735,25 @@ static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle,
        return result;
 }
 
+static int smb_full_audit_fcntl(struct vfs_handle_struct *handle,
+                               struct files_struct *fsp,
+                               int cmd, va_list cmd_arg)
+{
+       void *arg;
+       va_list dup_cmd_arg;
+       int result;
+
+       va_copy(dup_cmd_arg, cmd_arg);
+       arg = va_arg(dup_cmd_arg, void *);
+       result = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
+       va_end(dup_cmd_arg);
+
+       do_log(SMB_VFS_OP_FCNTL, (result >= 0), handle, "%s",
+              fsp_str_do_log(fsp));
+
+       return result;
+}
+
 static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
                                  int leasetype)
 {
@@ -2981,6 +3001,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
        .fallocate_fn = smb_full_audit_fallocate,
        .lock_fn = smb_full_audit_lock,
        .kernel_flock_fn = smb_full_audit_kernel_flock,
+       .fcntl_fn = smb_full_audit_fcntl,
        .linux_setlease_fn = smb_full_audit_linux_setlease,
        .getlock_fn = smb_full_audit_getlock,
        .symlinkat_fn = smb_full_audit_symlinkat,
index ffcba7bd8db4411400440b064a06b615487925b1..2b906b3cf281ee1d1af6a2b83ed44755db893ca1 100644 (file)
@@ -442,6 +442,14 @@ int vfs_not_implemented_kernel_flock(struct vfs_handle_struct *handle,
        return -1;
 }
 
+int vfs_not_implemented_fcntl(struct vfs_handle_struct *handle,
+                             struct files_struct *fsp, int cmd,
+                             va_list cmd_arg)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 int vfs_not_implemented_linux_setlease(struct vfs_handle_struct *handle,
                                       struct files_struct *fsp, int leasetype)
 {
@@ -1095,6 +1103,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
        .fallocate_fn = vfs_not_implemented_fallocate,
        .lock_fn = vfs_not_implemented_lock,
        .kernel_flock_fn = vfs_not_implemented_kernel_flock,
+       .fcntl_fn = vfs_not_implemented_fcntl,
        .linux_setlease_fn = vfs_not_implemented_linux_setlease,
        .getlock_fn = vfs_not_implemented_getlock,
        .symlinkat_fn = vfs_not_implemented_symlinkat,
index 213ea10b17f051b73ab2ca8c6621c9d0f308bd39..7fa6161945ac8978dbcf86d0724154c9c7e35a77 100644 (file)
@@ -1344,6 +1344,31 @@ static int smb_time_audit_kernel_flock(struct vfs_handle_struct *handle,
        return result;
 }
 
+static int smb_time_audit_fcntl(struct vfs_handle_struct *handle,
+                               struct files_struct *fsp,
+                               int cmd, va_list cmd_arg)
+{
+       void *arg;
+       va_list dup_cmd_arg;
+       int result;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       va_copy(dup_cmd_arg, cmd_arg);
+       arg = va_arg(dup_cmd_arg, void *);
+       clock_gettime_mono(&ts1);
+       result = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
+       clock_gettime_mono(&ts2);
+       va_end(dup_cmd_arg);
+
+       timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
+       if (timediff > audit_timeout) {
+               smb_time_audit_log_fsp("kernel_flock", timediff, fsp);
+       }
+
+       return result;
+}
+
 static int smb_time_audit_linux_setlease(vfs_handle_struct *handle,
                                         files_struct *fsp,
                                         int leasetype)
@@ -2866,6 +2891,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
        .fallocate_fn = smb_time_audit_fallocate,
        .lock_fn = smb_time_audit_lock,
        .kernel_flock_fn = smb_time_audit_kernel_flock,
+       .fcntl_fn = smb_time_audit_fcntl,
        .linux_setlease_fn = smb_time_audit_linux_setlease,
        .getlock_fn = smb_time_audit_getlock,
        .symlinkat_fn = smb_time_audit_symlinkat,
index b83cf1e4d559ba83c6db39ba8aef65916ec9809e..bef79e4c64e32f35ad34dcd6ab731669ccddb856 100644 (file)
@@ -2195,6 +2195,21 @@ int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
                                         access_mask);
 }
 
+int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
+                      struct files_struct *fsp, int cmd, ...)
+{
+       int result;
+       va_list cmd_arg;
+
+       VFS_FIND(fcntl);
+
+       va_start(cmd_arg, cmd);
+       result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
+       va_end(cmd_arg);
+
+       return result;
+}
+
 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
                                struct files_struct *fsp, int leasetype)
 {
index d45222625c4935e676f38e22acc688cd6749f529..e29bf657b5e9e831fa45117b3b0bf9f1685aaddd 100644 (file)
@@ -1119,6 +1119,115 @@ err:
             execute=True,
             msg="Checking whether fcntl lock supports open file description locks")
 
+    conf.CHECK_CODE('''
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+int main(void)
+{
+        int sockfd, ret;
+        struct f_owner_ex owner, get_owner;
+
+        sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (sockfd == -1) {
+            goto err;
+        }
+
+        owner.type = F_OWNER_PID;
+        owner.pid = getpid();
+
+        ret = fcntl(sockfd, F_SETOWN_EX, &owner);
+        if (ret == -1) {
+            goto err;
+        }
+
+        ret = fcntl(sockfd, F_GETOWN_EX, &get_owner);
+        if (ret == -1) {
+            goto err;
+        }
+
+        if (get_owner.type != F_OWNER_PID) {
+            goto err;
+        }
+
+        if (get_owner.pid != getpid()) {
+            goto err;
+        }
+
+        close(sockfd);
+        exit(0);
+err:
+        close(sockfd);
+        exit(1);
+}''',
+            'HAVE_F_OWNER_EX',
+            addmain=False,
+            execute=True,
+            msg="Checking whether fcntl supports flags to send direct I/O availability signals")
+
+    conf.CHECK_CODE('''
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#define DATA "hinttest.fcntl"
+
+int main(void)
+{
+        uint64_t *hint, get_hint;
+        int fd;
+
+        fd = open(DATA, O_RDONLY | O_CREAT | O_EXCL);
+        if (fd == -1) {
+            goto err;
+        }
+
+        *hint = RWH_WRITE_LIFE_SHORT;
+        int ret = fcntl(fd, F_SET_RW_HINT, hint);
+        if (ret == -1) {
+            goto err;
+        }
+
+        ret = fcntl(fd, F_GET_RW_HINT, &get_hint);
+        if (ret == -1) {
+            goto err;
+        }
+
+        if (get_hint != RWH_WRITE_LIFE_SHORT) {
+            goto err;
+        }
+
+        *hint = RWH_WRITE_LIFE_EXTREME;
+        ret = fcntl(fd, F_SET_FILE_RW_HINT, hint);
+        if (ret == -1) {
+            goto err;
+        }
+
+        ret = fcntl(fd, F_GET_FILE_RW_HINT, &get_hint);
+        if (ret == -1) {
+            goto err;
+        }
+
+        if (get_hint != RWH_WRITE_LIFE_EXTREME) {
+            goto err;
+        }
+
+        close(fd);
+        unlink(DATA);
+        exit(0);
+err:
+        close(fd);
+        unlink(DATA);
+        exit(1);
+}''',
+            'HAVE_RW_HINTS',
+            addmain=False,
+            execute=True,
+            msg="Checking whether fcntl supports setting/geting hints")
+
     conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_mtim.tv_nsec',
                                 define='HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC') # Linux, Solaris
     conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_mtimensec',