Commit 5084a69d authored by Anoop C S's avatar Anoop C S Committed by Ralph Böhme
Browse files

s3: VFS: Add SMB_VFS_FCNTL


Signed-off-by: Anoop C S's avatarAnoop C S <anoopcs@redhat.com>
Reviewed-by: Ralph Böhme's avatarRalph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison's avatarJeremy Allison <jra@samba.org>
parent c9d302f2
......@@ -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,
......
......@@ -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,
......
......@@ -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);
......
......@@ -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) \
......
......@@ -282,6 +282,7 @@
/* 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,
......
......@@ -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) \
......
......@@ -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.
****************************************************************************/
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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)
{
......
......@@ -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',
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment