Implementing SMB_VFS_FCNTL in Samba

Jeremy Allison jra at samba.org
Wed Sep 25 20:06:48 UTC 2019


On Thu, Sep 26, 2019 at 12:09:34AM +0530, Anoop C S wrote:
> 
> Please find the attached patch in the above suggested direction. For
> now it is compile tested only. I will respond back afterwards with some
> basic testing results.

This looks much better - thanks !

Jeremy.

> From 82e126d1a51701dc812dd51025f37c4c34ee2495 Mon Sep 17 00:00:00 2001
> From: Anoop C S <anoopcs at redhat.com>
> Date: Sat, 21 Sep 2019 19:11:19 +0530
> Subject: [PATCH] s3: VFS: Add SMB_VFS_FCNTL()
> 
> Signed-off-by: Anoop C S <anoopcs at redhat.com>
> ---
>  examples/VFS/skel_opaque.c            |  8 +++++++
>  examples/VFS/skel_transparent.c       | 11 +++++++++
>  source3/include/proto.h               |  1 +
>  source3/include/smbprofile.h          |  1 +
>  source3/include/vfs.h                 |  7 ++++++
>  source3/include/vfs_macros.h          |  5 ++++
>  source3/lib/system.c                  | 14 +++++++++++
>  source3/modules/vfs_default.c         | 34 +++++++++++++++++++++++++++
>  source3/modules/vfs_not_implemented.c |  9 +++++++
>  source3/smbd/vfs.c                    | 15 ++++++++++++
>  10 files changed, 105 insertions(+)
> 
> diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
> index c03a42fee04..72714e7c2b6 100644
> --- a/examples/VFS/skel_opaque.c
> +++ b/examples/VFS/skel_opaque.c
> @@ -442,6 +442,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)
>  {
> @@ -1089,6 +1096,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,
> diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
> index 656c933338a..60e3d58ffc2 100644
> --- a/examples/VFS/skel_transparent.c
> +++ b/examples/VFS/skel_transparent.c
> @@ -547,6 +547,16 @@ 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;
> +
> +	arg = va_arg(cmd_arg, void *);
> +
> +	return SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
> +}
> +
>  static int skel_linux_setlease(struct vfs_handle_struct *handle,
>  			       struct files_struct *fsp, int leasetype)
>  {
> @@ -1374,6 +1384,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,
> diff --git a/source3/include/proto.h b/source3/include/proto.h
> index 0d02f38fc8b..d4267a84a65 100644
> --- a/source3/include/proto.h
> +++ b/source3/include/proto.h
> @@ -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);
> diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h
> index 489a613e3df..2ae3db40a73 100644
> --- a/source3/include/smbprofile.h
> +++ b/source3/include/smbprofile.h
> @@ -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) \
> diff --git a/source3/include/vfs.h b/source3/include/vfs.h
> index 47147821ffd..efec146e0ae 100644
> --- a/source3/include/vfs.h
> +++ b/source3/include/vfs.h
> @@ -281,6 +281,7 @@
>  /* Version 42 - Move change_to_user() -> change_to_user_and_service() */
>  /* 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 - Add SMB_VFS_FCNTL */
>  
>  #define SMB_VFS_INTERFACE_VERSION 42
>  
> @@ -807,6 +808,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,
> @@ -1340,6 +1343,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,
> @@ -1773,6 +1778,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,
> diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
> index 6d95d840e25..74ee6b84369 100644
> --- a/source3/include/vfs_macros.h
> +++ b/source3/include/vfs_macros.h
> @@ -286,6 +286,11 @@
>  #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) \
> diff --git a/source3/lib/system.c b/source3/lib/system.c
> index def8281fc43..679332255c0 100644
> --- a/source3/lib/system.c
> +++ b/source3/lib/system.c
> @@ -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.
>  ****************************************************************************/
> diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
> index f48a590e5e7..49bceda6c8d 100644
> --- a/source3/modules/vfs_default.c
> +++ b/source3/modules/vfs_default.c
> @@ -2609,6 +2609,39 @@ 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 *arg;
> +	int result;
> +
> +	START_PROFILE(syscall_fcntl);
> +
> +	arg = va_arg(cmd_arg, void *);
> +
> +	switch(cmd) {
> +	case F_SETLK:
> +	case F_SETLKW:
> +	case F_GETLK:
> +	case F_OFD_SETLK:
> +	case F_OFD_SETLKW:
> +	case F_OFD_GETLK:
> +	case F_GETOWN_EX:
> +	case F_SETOWN_EX:
> +	case F_GET_RW_HINT:
> +	case F_SET_RW_HINT:
> +	case F_GET_FILE_RW_HINT:
> +	case F_SET_FILE_RW_HINT:
> +		result = sys_fcntl_ptr(fsp->fh->fd, cmd, arg);
> +		break;
> +	default:
> +		result = sys_fcntl_int(fsp->fh->fd, cmd, *((int *)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;
> @@ -3500,6 +3533,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,
> diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
> index e0f36b9a632..d5b8079ae26 100644
> --- a/source3/modules/vfs_not_implemented.c
> +++ b/source3/modules/vfs_not_implemented.c
> @@ -440,6 +440,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)
>  {
> @@ -1093,6 +1101,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,
> diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
> index 20f3d34965f..1764be5e1cc 100644
> --- a/source3/smbd/vfs.c
> +++ b/source3/smbd/vfs.c
> @@ -2190,6 +2190,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)
>  {
> -- 
> 2.21.0
> 




More information about the samba-technical mailing list