The Samba-Bugzilla – Attachment 13460 Details for
Bug 12791
kernel oplocks still have issues with named streams
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.7 cherry-picked from master
bug12791-v47.patch (text/plain), 55.54 KB, created by
Ralph Böhme
on 2017-08-11 08:19:36 UTC
(
hide
)
Description:
Patch for 4.7 cherry-picked from master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2017-08-11 08:19:36 UTC
Size:
55.54 KB
patch
obsolete
>From 83f9c39fc2891ac5960cde1c2a6d4b01fa2014d2 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 May 2017 07:59:20 +0200 >Subject: [PATCH 01/12] vfs_streams_xattr: invalidate stat info if xattr was > not found > >We stat the basefile so we leave valid stat info from the base file >behind, even though the xattr for the stream was not there. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit ec32f33ea6d50d9cb504400c3ef1e78643502e1a) >--- > source3/modules/vfs_streams_xattr.c | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index 5114c09..fc79935 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -269,6 +269,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, > smb_fname_base, io->xattr_name); > if (sbuf->st_ex_size == -1) { > TALLOC_FREE(smb_fname_base); >+ SET_STAT_INVALID(*sbuf); > return -1; > } > >@@ -322,6 +323,7 @@ static int streams_xattr_stat(vfs_handle_struct *handle, > smb_fname, > xattr_name); > if (smb_fname->st.st_ex_size == -1) { >+ SET_STAT_INVALID(smb_fname->st); > errno = ENOENT; > result = -1; > goto fail; >@@ -373,6 +375,7 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, > smb_fname, > xattr_name); > if (smb_fname->st.st_ex_size == -1) { >+ SET_STAT_INVALID(smb_fname->st); > errno = ENOENT; > result = -1; > goto fail; >-- >2.9.4 > > >From 9781b7a75cec6fa7d0272da8aed95ef483f9a153 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 May 2017 15:05:23 +0200 >Subject: [PATCH 02/12] vfs_streams_xattr: remove all uses of fd, use name > based functions > >We don't really need an fd in this module, all calls to the VFS xattr >API can just use the name based versions. > >This paves the way for removing the open of the basefile in >streams_xattr_open() in a later commit. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit ea906bb476516c05e7cbda478afd32acb443c03e) >--- > source3/modules/vfs_streams_xattr.c | 50 +++++++++++-------------------------- > 1 file changed, 15 insertions(+), 35 deletions(-) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index fc79935..90e9771 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -232,7 +232,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, > struct stream_io *io = (struct stream_io *) > VFS_FETCH_FSP_EXTENSION(handle, fsp); > >- DEBUG(10, ("streams_xattr_fstat called for %d\n", fsp->fh->fd)); >+ DBG_DEBUG("streams_xattr_fstat called for %s\n", fsp_str_dbg(io->fsp)); > > if (io == NULL || fsp->base_fsp == NULL) { > return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); >@@ -506,11 +506,11 @@ static int streams_xattr_open(vfs_handle_struct *handle, > DEBUG(10, ("creating or truncating attribute %s on file %s\n", > xattr_name, smb_fname->base_name)); > >- fsp->fh->fd = hostfd; >- ret = SMB_VFS_FSETXATTR(fsp, xattr_name, >- &null, sizeof(null), >- flags & O_EXCL ? XATTR_CREATE : 0); >- fsp->fh->fd = -1; >+ ret = SMB_VFS_SETXATTR(fsp->conn, >+ smb_fname, >+ xattr_name, >+ &null, sizeof(null), >+ flags & O_EXCL ? XATTR_CREATE : 0); > if (ret != 0) { > goto fail; > } >@@ -844,14 +844,7 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, > NTSTATUS status; > struct streaminfo_state state; > >- if ((fsp != NULL) && (fsp->fh->fd != -1)) { >- ret = SMB_VFS_FSTAT(fsp, &sbuf); >- } else { >- ret = vfs_stat_smb_basename(handle->conn, >- smb_fname, >- &sbuf); >- } >- >+ ret = vfs_stat_smb_basename(handle->conn, smb_fname, &sbuf); > if (ret == -1) { > return map_nt_error_from_unix(errno); > } >@@ -1003,16 +996,10 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, > > memcpy(ea.value.data + offset, data, n); > >- if (fsp->fh->fd != -1) { >- ret = SMB_VFS_FSETXATTR(fsp, >- sio->xattr_name, >- ea.value.data, ea.value.length, 0); >- } else { >- ret = SMB_VFS_SETXATTR(fsp->conn, >- fsp->fsp_name, >- sio->xattr_name, >- ea.value.data, ea.value.length, 0); >- } >+ ret = SMB_VFS_SETXATTR(fsp->conn, >+ fsp->fsp_name, >+ sio->xattr_name, >+ ea.value.data, ea.value.length, 0); > TALLOC_FREE(ea.value.data); > > if (ret == -1) { >@@ -1297,17 +1284,10 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, > ea.value.length = offset + 1; > ea.value.data[offset] = 0; > >- if (fsp->fh->fd != -1) { >- ret = SMB_VFS_FSETXATTR(fsp, >- sio->xattr_name, >- ea.value.data, ea.value.length, 0); >- } else { >- ret = SMB_VFS_SETXATTR(fsp->conn, >- fsp->fsp_name, >- sio->xattr_name, >- ea.value.data, ea.value.length, 0); >- } >- >+ ret = SMB_VFS_SETXATTR(fsp->conn, >+ fsp->fsp_name, >+ sio->xattr_name, >+ ea.value.data, ea.value.length, 0); > TALLOC_FREE(ea.value.data); > > if (ret == -1) { >-- >2.9.4 > > >From b84e854a2ebe9e1adf40db5ba9d58266bcfe358a Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 May 2017 17:36:15 +0200 >Subject: [PATCH 03/12] vfs_streams_xattr: remove fsp argument from > get_xattr_size() > >Still in the process of changing all handle based operations to use path >based operations. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 4cc59e6d011cd3804499ba82bb4071973aa9d494) >--- > source3/modules/vfs_streams_xattr.c | 9 ++++----- > 1 file changed, 4 insertions(+), 5 deletions(-) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index 90e9771..971a00c 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -78,7 +78,6 @@ static SMB_INO_T stream_inode(const SMB_STRUCT_STAT *sbuf, const char *sname) > } > > static ssize_t get_xattr_size(connection_struct *conn, >- files_struct *fsp, > const struct smb_filename *smb_fname, > const char *xattr_name) > { >@@ -86,7 +85,7 @@ static ssize_t get_xattr_size(connection_struct *conn, > struct ea_struct ea; > ssize_t result; > >- status = get_ea_value(talloc_tos(), conn, fsp, smb_fname, >+ status = get_ea_value(talloc_tos(), conn, NULL, smb_fname, > xattr_name, &ea); > > if (!NT_STATUS_IS_OK(status)) { >@@ -265,7 +264,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, > return -1; > } > >- sbuf->st_ex_size = get_xattr_size(handle->conn, fsp, >+ sbuf->st_ex_size = get_xattr_size(handle->conn, > smb_fname_base, io->xattr_name); > if (sbuf->st_ex_size == -1) { > TALLOC_FREE(smb_fname_base); >@@ -319,7 +318,7 @@ static int streams_xattr_stat(vfs_handle_struct *handle, > } > > /* Augment the base file's stat information before returning. */ >- smb_fname->st.st_ex_size = get_xattr_size(handle->conn, NULL, >+ smb_fname->st.st_ex_size = get_xattr_size(handle->conn, > smb_fname, > xattr_name); > if (smb_fname->st.st_ex_size == -1) { >@@ -371,7 +370,7 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, > } > > /* Augment the base file's stat information before returning. */ >- smb_fname->st.st_ex_size = get_xattr_size(handle->conn, NULL, >+ smb_fname->st.st_ex_size = get_xattr_size(handle->conn, > smb_fname, > xattr_name); > if (smb_fname->st.st_ex_size == -1) { >-- >2.9.4 > > >From 92c148c151660f01ae0c755dee7e14b95e6cea68 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 May 2017 17:38:00 +0200 >Subject: [PATCH 04/12] vfs_streams_xattr: always pass NULL as fsp arg to > get_ea_value() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 0ed3075ee7edfecde7455a2c64e9df882828343b) >--- > source3/modules/vfs_streams_xattr.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index 971a00c..5eb2b9b 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -747,7 +747,7 @@ static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle, > > status = get_ea_value(names, > handle->conn, >- fsp, >+ NULL, > smb_fname, > names[i], > &ea); >@@ -971,7 +971,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, > return -1; > } > >- status = get_ea_value(talloc_tos(), handle->conn, fsp, >+ status = get_ea_value(talloc_tos(), handle->conn, NULL, > smb_fname_base, sio->xattr_name, &ea); > if (!NT_STATUS_IS_OK(status)) { > return -1; >@@ -1041,7 +1041,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle, > return -1; > } > >- status = get_ea_value(talloc_tos(), handle->conn, fsp, >+ status = get_ea_value(talloc_tos(), handle->conn, NULL, > smb_fname_base, sio->xattr_name, &ea); > if (!NT_STATUS_IS_OK(status)) { > return -1; >@@ -1258,7 +1258,7 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, > return -1; > } > >- status = get_ea_value(talloc_tos(), handle->conn, fsp, >+ status = get_ea_value(talloc_tos(), handle->conn, NULL, > smb_fname_base, sio->xattr_name, &ea); > if (!NT_STATUS_IS_OK(status)) { > return -1; >-- >2.9.4 > > >From fbda3a1aef873b9216eeffce4d57434f4a65f88f Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 May 2017 18:05:18 +0200 >Subject: [PATCH 05/12] vfs_streams_xattr: implement all missing handle based > VFS functions > >Implement all missing handle based VFS function. If the call is on a >named stream, implement the appropriate action for the VFS function, in >most cases a no-op. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 9647af6bec62c9f61d541aad4a9b8f25fd5bc627) >--- > source3/modules/vfs_streams_xattr.c | 421 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 421 insertions(+) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index 5eb2b9b..988d2f1 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -26,6 +26,7 @@ > #include "system/filesys.h" > #include "../lib/crypto/md5.h" > #include "lib/util/tevent_unix.h" >+#include "librpc/gen_ndr/ioctl.h" > > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_VFS >@@ -1322,6 +1323,396 @@ static int streams_xattr_fallocate(struct vfs_handle_struct *handle, > return -1; > } > >+static int streams_xattr_fchown(vfs_handle_struct *handle, files_struct *fsp, >+ uid_t uid, gid_t gid) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid); >+ } >+ >+ return 0; >+} >+ >+static int streams_xattr_fchmod(vfs_handle_struct *handle, >+ files_struct *fsp, >+ mode_t mode) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode); >+ } >+ >+ return 0; >+} >+ >+static int streams_xattr_fsync(vfs_handle_struct *handle, files_struct *fsp) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FSYNC(handle, fsp); >+ } >+ >+ return 0; >+} >+ >+static ssize_t streams_xattr_fgetxattr(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ const char *name, >+ void *value, >+ size_t size) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size); >+ } >+ >+ errno = ENOTSUP; >+ return -1; >+} >+ >+static ssize_t streams_xattr_flistxattr(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ char *list, >+ size_t size) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size); >+ } >+ >+ errno = ENOTSUP; >+ return -1; >+} >+ >+static int streams_xattr_fremovexattr(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ const char *name) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name); >+ } >+ >+ errno = ENOTSUP; >+ return -1; >+} >+ >+static int streams_xattr_fsetxattr(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ const char *name, >+ const void *value, >+ size_t size, >+ int flags) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, >+ size, flags); >+ } >+ >+ errno = ENOTSUP; >+ return -1; >+} >+ >+static int streams_xattr_fchmod_acl(vfs_handle_struct *handle, >+ files_struct *fsp, >+ mode_t mode) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode); >+ } >+ >+ return 0; >+} >+ >+static SMB_ACL_T streams_xattr_sys_acl_get_fd(vfs_handle_struct *handle, >+ files_struct *fsp, >+ TALLOC_CTX *mem_ctx) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx); >+ } >+ >+ return SMB_VFS_NEXT_SYS_ACL_GET_FILE( >+ handle, fsp->base_fsp->fsp_name, >+ SMB_ACL_TYPE_ACCESS, mem_ctx); >+} >+ >+static int streams_xattr_sys_acl_set_fd(vfs_handle_struct *handle, >+ files_struct *fsp, >+ SMB_ACL_T theacl) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl); >+ } >+ >+ return 0; >+} >+ >+static int streams_xattr_sys_acl_blob_get_fd(vfs_handle_struct *handle, >+ files_struct *fsp, >+ TALLOC_CTX *mem_ctx, >+ char **blob_description, >+ DATA_BLOB *blob) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx, >+ blob_description, blob); >+ } >+ >+ return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE( >+ handle, fsp->base_fsp->fsp_name, mem_ctx, >+ blob_description, blob); >+} >+ >+static NTSTATUS streams_xattr_fget_nt_acl(vfs_handle_struct *handle, >+ files_struct *fsp, >+ uint32_t security_info, >+ TALLOC_CTX *mem_ctx, >+ struct security_descriptor **ppdesc) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, >+ mem_ctx, ppdesc); >+ } >+ >+ return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp->base_fsp->fsp_name, >+ security_info, mem_ctx, ppdesc); >+} >+ >+static NTSTATUS streams_xattr_fset_nt_acl(vfs_handle_struct *handle, >+ files_struct *fsp, >+ uint32_t security_info_sent, >+ const struct security_descriptor *psd) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, >+ security_info_sent, psd); >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+struct streams_xattr_fsync_state { >+ int ret; >+ struct vfs_aio_state vfs_aio_state; >+}; >+ >+static void streams_xattr_fsync_done(struct tevent_req *subreq); >+ >+static struct tevent_req *streams_xattr_fsync_send( >+ struct vfs_handle_struct *handle, >+ TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct files_struct *fsp) >+{ >+ struct tevent_req *req = NULL; >+ struct tevent_req *subreq = NULL; >+ struct streams_xattr_fsync_state *state = NULL; >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ req = tevent_req_create(mem_ctx, &state, >+ struct streams_xattr_fsync_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ >+ if (sio == NULL) { >+ subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp); >+ if (tevent_req_nomem(req, subreq)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, streams_xattr_fsync_done, req); >+ return req; >+ } >+ >+ /* >+ * There's no pathname based sync variant and we don't have access to >+ * the basefile handle, so we can't do anything here. >+ */ >+ >+ tevent_req_done(req); >+ return tevent_req_post(req, ev); >+} >+ >+static void streams_xattr_fsync_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct streams_xattr_fsync_state *state = tevent_req_data( >+ req, struct streams_xattr_fsync_state); >+ >+ state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state); >+ TALLOC_FREE(subreq); >+ if (state->ret != 0) { >+ tevent_req_error(req, errno); >+ return; >+ } >+ >+ tevent_req_done(req); >+} >+ >+static int streams_xattr_fsync_recv(struct tevent_req *req, >+ struct vfs_aio_state *vfs_aio_state) >+{ >+ struct streams_xattr_fsync_state *state = tevent_req_data( >+ req, struct streams_xattr_fsync_state); >+ >+ if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { >+ return -1; >+ } >+ >+ *vfs_aio_state = state->vfs_aio_state; >+ return state->ret; >+} >+ >+static bool streams_xattr_lock(vfs_handle_struct *handle, >+ files_struct *fsp, >+ int op, >+ off_t offset, >+ off_t count, >+ int type) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type); >+ } >+ >+ return true; >+} >+ >+static bool streams_xattr_getlock(vfs_handle_struct *handle, >+ files_struct *fsp, >+ off_t *poffset, >+ off_t *pcount, >+ int *ptype, >+ pid_t *ppid) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, >+ pcount, ptype, ppid); >+ } >+ >+ errno = ENOTSUP; >+ return false; >+} >+ >+static int streams_xattr_kernel_flock(vfs_handle_struct *handle, >+ files_struct *fsp, >+ uint32_t share_mode, >+ uint32_t access_mask) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, >+ share_mode, access_mask); >+ } >+ >+ return 0; >+} >+ >+static int streams_xattr_linux_setlease(vfs_handle_struct *handle, >+ files_struct *fsp, >+ int leasetype) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype); >+ } >+ >+ return 0; >+} >+ >+static bool streams_xattr_strict_lock_check(struct vfs_handle_struct *handle, >+ files_struct *fsp, >+ struct lock_struct *plock) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle, fsp, plock); >+ } >+ >+ return true; >+} >+ >+static NTSTATUS streams_xattr_get_compression(struct vfs_handle_struct *handle, >+ TALLOC_CTX *mem_ctx, >+ struct files_struct *fsp, >+ struct smb_filename *smb_fname, >+ uint16_t *_compression_fmt) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_GET_COMPRESSION(handle, mem_ctx, fsp, >+ smb_fname, _compression_fmt); >+ } >+ >+ *_compression_fmt = COMPRESSION_FORMAT_NONE; >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS streams_xattr_set_compression(struct vfs_handle_struct *handle, >+ TALLOC_CTX *mem_ctx, >+ struct files_struct *fsp, >+ uint16_t compression_fmt) >+{ >+ struct stream_io *sio = >+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ >+ if (sio == NULL) { >+ return SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp, >+ compression_fmt); >+ } >+ >+ return NT_STATUS_NOT_SUPPORTED; >+} > > static struct vfs_fn_pointers vfs_streams_xattr_fns = { > .fs_capabilities_fn = streams_xattr_fs_capabilities, >@@ -1341,6 +1732,36 @@ static struct vfs_fn_pointers vfs_streams_xattr_fns = { > .ftruncate_fn = streams_xattr_ftruncate, > .fallocate_fn = streams_xattr_fallocate, > .streaminfo_fn = streams_xattr_streaminfo, >+ >+ .fsync_send_fn = streams_xattr_fsync_send, >+ .fsync_recv_fn = streams_xattr_fsync_recv, >+ >+ .lock_fn = streams_xattr_lock, >+ .getlock_fn = streams_xattr_getlock, >+ .kernel_flock_fn = streams_xattr_kernel_flock, >+ .linux_setlease_fn = streams_xattr_linux_setlease, >+ .strict_lock_check_fn = streams_xattr_strict_lock_check, >+ >+ .get_compression_fn = streams_xattr_get_compression, >+ .set_compression_fn = streams_xattr_set_compression, >+ >+ .fchown_fn = streams_xattr_fchown, >+ .fchmod_fn = streams_xattr_fchmod, >+ .fsync_fn = streams_xattr_fsync, >+ >+ .fgetxattr_fn = streams_xattr_fgetxattr, >+ .flistxattr_fn = streams_xattr_flistxattr, >+ .fremovexattr_fn = streams_xattr_fremovexattr, >+ .fsetxattr_fn = streams_xattr_fsetxattr, >+ >+ .fchmod_acl_fn = streams_xattr_fchmod_acl, >+ >+ .sys_acl_get_fd_fn = streams_xattr_sys_acl_get_fd, >+ .sys_acl_blob_get_fd_fn = streams_xattr_sys_acl_blob_get_fd, >+ .sys_acl_set_fd_fn = streams_xattr_sys_acl_set_fd, >+ >+ .fget_nt_acl_fn = streams_xattr_fget_nt_acl, >+ .fset_nt_acl_fn = streams_xattr_fset_nt_acl, > }; > > NTSTATUS vfs_streams_xattr_init(TALLOC_CTX *); >-- >2.9.4 > > >From 698396a31f534b4ee7cebf190942273dfb9b33ab Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 May 2017 18:08:56 +0200 >Subject: [PATCH 06/12] vfs_streams_xattr: return a fake fd in > streams_xattr_open() > >The final step in changing vfs_streams_xattr to not call open() on the >basefile anymore. Instead, we just return a fake file fd based on >dup'ing a pipe fd. Previous commits ensured all calls to VFS API >functions use pathname based versions to do their work. > >This ensures we don't trigger kernel oplock breaks for client "open >stream" requests when needlessly opening the basefile. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 0a8559d4c9e4fc73c30a06b5f45f3b870afe4439) >--- > source3/modules/vfs_streams_xattr.c | 67 +++++++++++-------------------------- > 1 file changed, 20 insertions(+), 47 deletions(-) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index 988d2f1..bd3965c 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -399,14 +399,17 @@ static int streams_xattr_open(vfs_handle_struct *handle, > files_struct *fsp, int flags, mode_t mode) > { > NTSTATUS status; >- struct smb_filename *smb_fname_base = NULL; >- struct stream_io *sio; >+ struct streams_xattr_config *config = NULL; >+ struct stream_io *sio = NULL; > struct ea_struct ea; > char *xattr_name = NULL; >- int baseflags; >- int hostfd = -1; >+ int pipe_fds[2]; >+ int fakefd = -1; > int ret; > >+ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config, >+ return -1); >+ > DEBUG(10, ("streams_xattr_open called for %s with flags 0x%x\n", > smb_fname_str_dbg(smb_fname), flags)); > >@@ -435,44 +438,18 @@ static int streams_xattr_open(vfs_handle_struct *handle, > goto fail; > } > >- /* Create an smb_filename with stream_name == NULL. */ >- smb_fname_base = synthetic_smb_fname(talloc_tos(), >- smb_fname->base_name, >- NULL, >- NULL, >- smb_fname->flags); >- if (smb_fname_base == NULL) { >- errno = ENOMEM; >+ /* >+ * Return a valid fd, but ensure any attempt to use it returns an error >+ * (EPIPE). >+ */ >+ ret = pipe(pipe_fds); >+ if (ret != 0) { > goto fail; > } > >- /* >- * We use baseflags to turn off nasty side-effects when opening the >- * underlying file. >- */ >- baseflags = flags; >- baseflags &= ~O_TRUNC; >- baseflags &= ~O_EXCL; >- baseflags &= ~O_CREAT; >- >- hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp, >- baseflags, mode); >- >- /* It is legit to open a stream on a directory, but the base >- * fd has to be read-only. >- */ >- if ((hostfd == -1) && (errno == EISDIR)) { >- baseflags &= ~O_ACCMODE; >- baseflags |= O_RDONLY; >- hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp, baseflags, >- mode); >- } >- >- TALLOC_FREE(smb_fname_base); >- >- if (hostfd == -1) { >- goto fail; >- } >+ close(pipe_fds[1]); >+ pipe_fds[1] = -1; >+ fakefd = pipe_fds[0]; > > status = get_ea_value(talloc_tos(), handle->conn, NULL, > smb_fname, xattr_name, &ea); >@@ -544,16 +521,12 @@ static int streams_xattr_open(vfs_handle_struct *handle, > goto fail; > } > >- return hostfd; >+ return fakefd; > > fail: >- if (hostfd >= 0) { >- /* >- * BUGBUGBUG -- we would need to call fd_close_posix here, but >- * we don't have a full fsp yet >- */ >- fsp->fh->fd = hostfd; >- SMB_VFS_NEXT_CLOSE(handle, fsp); >+ if (fakefd >= 0) { >+ close(fakefd); >+ fakefd = -1; > } > > return -1; >-- >2.9.4 > > >From 41f536df630ec3089ca618f4316624c809288f5e Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 10 May 2017 11:38:06 +0200 >Subject: [PATCH 07/12] s4/torture: reproducer for kernel oplocks issue with > streams > >test_smb2_kernel_oplocks3() wouldn't have failed without the patches, >I'm just adding it to have at least one test that tests with 2 >clients. All other tests use just one client. > >test_smb2_kernel_oplocks4() is the reproducer. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >(cherry picked from commit a334fff8a8c779704ee04ae784024efb67a6e9c9) >--- > source4/torture/smb2/oplock.c | 161 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 161 insertions(+) > >diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c >index 858bdcf..7c59780 100644 >--- a/source4/torture/smb2/oplock.c >+++ b/source4/torture/smb2/oplock.c >@@ -4332,6 +4332,165 @@ done: > return ret; > } > >+/** >+ * 1. 1st client opens file with oplock >+ * 2. 2nd client opens file >+ * >+ * Verify 2 triggers an oplock break >+ **/ >+static bool test_smb2_kernel_oplocks3(struct torture_context *tctx, >+ struct smb2_tree *tree, >+ struct smb2_tree *tree2) >+{ >+ const char *fname = "test_kernel_oplock3.dat"; >+ NTSTATUS status; >+ bool ret = true; >+ struct smb2_create create; >+ struct smb2_handle h1 = {{0}}, h2 = {{0}}; >+ >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testfile(tree, fname, &h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "Error creating testfile\n"); >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ ZERO_STRUCT(break_info); >+ >+ /* 1 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n"); >+ >+ /* 2 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ >+ status = smb2_create(tree2, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h2 = create.out.file.handle; >+ >+ torture_wait_for_oplock_break(tctx); >+ torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n"); >+ >+done: >+ if (!smb2_util_handle_empty(h1)) { >+ smb2_util_close(tree, h1); >+ } >+ if (!smb2_util_handle_empty(h2)) { >+ smb2_util_close(tree, h2); >+ } >+ smb2_util_unlink(tree, fname); >+ return ret; >+} >+ >+/** >+ * 1) create testfile with stream >+ * 2) open file r/w with batch oplock, sharing read/delete >+ * 3) open stream on file for reading >+ * >+ * Verify 3) doesn't trigger an oplock break >+ **/ >+static bool test_smb2_kernel_oplocks4(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ const char *fname = "test_kernel_oplock4.dat"; >+ const char *sname = "test_kernel_oplock4.dat:foo"; >+ NTSTATUS status; >+ bool ret = true; >+ struct smb2_create create; >+ struct smb2_handle h1 = {{0}}, h2 = {{0}}; >+ >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ ZERO_STRUCT(break_info); >+ smb2_util_unlink(tree, fname); >+ >+ /* 1 */ >+ status = torture_smb2_testfile(tree, fname, &h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "Error creating testfile\n"); >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ /* 2 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n"); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h2 = create.out.file.handle; >+ >+ torture_wait_for_oplock_break(tctx); >+ if (break_info.count != 0) { >+ torture_warning(tctx, "Stream open caused oplock break\n"); >+ } >+ >+done: >+ if (!smb2_util_handle_empty(h1)) { >+ smb2_util_close(tree, h1); >+ } >+ if (!smb2_util_handle_empty(h2)) { >+ smb2_util_close(tree, h2); >+ } >+ smb2_util_unlink(tree, fname); >+ return ret; >+} >+ > struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) > { > struct torture_suite *suite = >@@ -4339,6 +4498,8 @@ struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) > > torture_suite_add_1smb2_test(suite, "kernel_oplocks1", test_smb2_kernel_oplocks1); > torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2); >+ torture_suite_add_2smb2_test(suite, "kernel_oplocks3", test_smb2_kernel_oplocks3); >+ torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4); > > suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests"); > >-- >2.9.4 > > >From c51b0294b59c3528c76ce4cd83aa4e69f7b2f702 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 18 May 2017 13:17:38 +0200 >Subject: [PATCH 08/12] s4/torture: additional tests for kernel-oplocks > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >(cherry picked from commit bbc225de83e7b0e5eaeb1b843532d1f0fca91a3c) >--- > source4/torture/smb2/oplock.c | 185 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 185 insertions(+) > >diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c >index 7c59780..e0db5ec 100644 >--- a/source4/torture/smb2/oplock.c >+++ b/source4/torture/smb2/oplock.c >@@ -4491,6 +4491,189 @@ done: > return ret; > } > >+/** >+ * 1) create testfile with stream >+ * 2) open stream r/w with batch oplock -> batch oplock granted >+ * 3) open stream r/o with batch oplock >+ * >+ * Verify 3) does trigger an oplock break >+ **/ >+static bool test_smb2_kernel_oplocks5(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ const char *fname = "test_kernel_oplock4.dat"; >+ const char *sname = "test_kernel_oplock4.dat:foo"; >+ NTSTATUS status; >+ bool ret = true; >+ struct smb2_create create; >+ struct smb2_handle h1 = {{0}}, h2 = {{0}}; >+ >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ ZERO_STRUCT(break_info); >+ smb2_util_unlink(tree, fname); >+ >+ /* 1 */ >+ status = torture_smb2_testfile(tree, fname, &h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "Error creating testfile\n"); >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ /* 2 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n"); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h2 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n"); >+ >+ torture_wait_for_oplock_break(tctx); >+ if (break_info.count != 1) { >+ torture_warning(tctx, "Stream open didn't cause oplock break\n"); >+ } >+ >+done: >+ if (!smb2_util_handle_empty(h1)) { >+ smb2_util_close(tree, h1); >+ } >+ if (!smb2_util_handle_empty(h2)) { >+ smb2_util_close(tree, h2); >+ } >+ smb2_util_unlink(tree, fname); >+ return ret; >+} >+ >+/** >+ * 1) create testfile with stream >+ * 2) 1st client opens stream r/w with batch oplock -> batch oplock granted >+ * 3) 2nd client opens stream r/o with batch oplock >+ * >+ * Verify 3) does trigger an oplock break >+ **/ >+static bool test_smb2_kernel_oplocks6(struct torture_context *tctx, >+ struct smb2_tree *tree, >+ struct smb2_tree *tree2) >+{ >+ const char *fname = "test_kernel_oplock6.dat"; >+ const char *sname = "test_kernel_oplock6.dat:foo"; >+ NTSTATUS status; >+ bool ret = true; >+ struct smb2_create create; >+ struct smb2_handle h1 = {{0}}, h2 = {{0}}; >+ >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testfile(tree, fname, &h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "Error creating testfile\n"); >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ ZERO_STRUCT(break_info); >+ >+ /* 1 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ smb2_util_close(tree, h1); >+ ZERO_STRUCT(h1); >+ >+ /* 2 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n"); >+ >+ /* 3 */ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_READ; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ >+ status = smb2_create(tree2, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h2 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n"); >+ >+ torture_wait_for_oplock_break(tctx); >+ torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n"); >+ >+done: >+ if (!smb2_util_handle_empty(h1)) { >+ smb2_util_close(tree, h1); >+ } >+ if (!smb2_util_handle_empty(h2)) { >+ smb2_util_close(tree, h2); >+ } >+ smb2_util_unlink(tree, fname); >+ return ret; >+} >+ > struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) > { > struct torture_suite *suite = >@@ -4500,6 +4683,8 @@ struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) > torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2); > torture_suite_add_2smb2_test(suite, "kernel_oplocks3", test_smb2_kernel_oplocks3); > torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4); >+ torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5); >+ torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6); > > suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests"); > >-- >2.9.4 > > >From a2cc8fb0d8c2bb12ef3f203bc85cbd430da07e09 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 23 May 2017 17:39:46 +0200 >Subject: [PATCH 09/12] vfs_fruit: use path based setxattr call in ad_fset() > >This allows later commits to remove opening of the basefile which >conflict with "kernel oplocks = yes". > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit aff6fc49f4ac244aef162200a37bd846719e1e4f) >--- > source3/modules/vfs_fruit.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 7c481cd..e15af83 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -1461,11 +1461,11 @@ static int ad_fset(struct adouble *ad, files_struct *fsp) > > switch (ad->ad_type) { > case ADOUBLE_META: >- rc = SMB_VFS_NEXT_FSETXATTR(ad->ad_handle, >- fsp, >- AFPINFO_EA_NETATALK, >- ad->ad_data, >- AD_DATASZ_XATTR, 0); >+ rc = SMB_VFS_NEXT_SETXATTR(ad->ad_handle, >+ fsp->fsp_name, >+ AFPINFO_EA_NETATALK, >+ ad->ad_data, >+ AD_DATASZ_XATTR, 0); > break; > > case ADOUBLE_RSRC: >-- >2.9.4 > > >From c26ba5d762b91192eacdfaa12513cce518d83dd0 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 23 May 2017 17:31:47 +0200 >Subject: [PATCH 10/12] vfs_fruit: don't open basefile in ad_open() and > simplify API > >We never need an fd on the basefile when operating on the metadata, as >we can always use path based syscalls. Opening the basefile conflicts >with "kernel oplocks" so just don't do it. > >Additional changes: > >- remove the adouble_type_t argument to ad_open(), the type is passed > and set when allocating a struct adouble with ad_alloc() > >- additionally pass an optional fsp to ad_open() (so the caller can pass > NULL). With this change we can move the fd inheritance from fsp to ad > into ad_open() itself where it belongs and remove it from the caller > ad_fget() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >(cherry picked from commit e92a39255e66f655e2758f0a71a01eaf258cf711) >--- > source3/modules/vfs_fruit.c | 122 +++++++++++++++++--------------------------- > 1 file changed, 47 insertions(+), 75 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index e15af83..1f2d489 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -863,13 +863,6 @@ exit: > return ealen; > } > >-static int ad_open_meta(const struct smb_filename *smb_fname, >- int flags, >- mode_t mode) >-{ >- return open(smb_fname->base_name, flags, mode); >-} >- > static int ad_open_rsrc_xattr(const struct smb_filename *smb_fname, > int flags, > mode_t mode) >@@ -923,34 +916,45 @@ static int ad_open_rsrc(vfs_handle_struct *handle, > return fd; > } > >+/* >+ * Here's the deal: for ADOUBLE_META we can do without an fd as we can issue >+ * path based xattr calls. For ADOUBLE_RSRC however we need a full-fledged fd >+ * for file IO on the ._ file. >+ */ > static int ad_open(vfs_handle_struct *handle, > struct adouble *ad, >+ files_struct *fsp, > const struct smb_filename *smb_fname, >- adouble_type_t t, > int flags, > mode_t mode) > { > int fd; > >- DBG_DEBUG("Path [%s] type [%s]\n", >- smb_fname->base_name, t == ADOUBLE_META ? "meta" : "rsrc"); >+ DBG_DEBUG("Path [%s] type [%s]\n", smb_fname->base_name, >+ ad->ad_type == ADOUBLE_META ? "meta" : "rsrc"); > >- if (t == ADOUBLE_META) { >- fd = ad_open_meta(smb_fname, flags, mode); >- } else { >- fd = ad_open_rsrc(handle, smb_fname, flags, mode); >+ if (ad->ad_type == ADOUBLE_META) { >+ return 0; > } > >- if (fd != -1) { >- ad->ad_opened = true; >- ad->ad_fd = fd; >+ if ((fsp != NULL) && (fsp->fh != NULL) && (fsp->fh->fd != -1)) { >+ ad->ad_fd = fsp->fh->fd; >+ ad->ad_opened = false; >+ return 0; >+ } >+ >+ fd = ad_open_rsrc(handle, smb_fname, flags, mode); >+ if (fd == -1) { >+ return -1; > } >+ ad->ad_opened = true; >+ ad->ad_fd = fd; > > DBG_DEBUG("Path [%s] type [%s] fd [%d]\n", > smb_fname->base_name, >- t == ADOUBLE_META ? "meta" : "rsrc", fd); >+ ad->ad_type == ADOUBLE_META ? "meta" : "rsrc", fd); > >- return fd; >+ return 0; > } > > static ssize_t ad_read_rsrc_xattr(struct adouble *ad) >@@ -1254,7 +1258,6 @@ static struct adouble *ad_get(TALLOC_CTX *ctx, vfs_handle_struct *handle, > int rc = 0; > ssize_t len; > struct adouble *ad = NULL; >- int fd; > int mode; > > DEBUG(10, ("ad_get(%s) called for %s\n", >@@ -1267,29 +1270,20 @@ static struct adouble *ad_get(TALLOC_CTX *ctx, vfs_handle_struct *handle, > goto exit; > } > >- /* >- * Here's the deal: for ADOUBLE_META we can do without an fd >- * as we can issue path based xattr calls. For ADOUBLE_RSRC >- * however we need a full-fledged fd for file IO on the ._ >- * file. >- */ >- if (type == ADOUBLE_RSRC) { >- /* Try rw first so we can use the fd in ad_convert() */ >- mode = O_RDWR; >- >- fd = ad_open(handle, ad, smb_fname, ADOUBLE_RSRC, mode, 0); >- if (fd == -1 && ((errno == EROFS) || (errno == EACCES))) { >- mode = O_RDONLY; >- fd = ad_open(handle, ad, smb_fname, >- ADOUBLE_RSRC, mode, 0); >- } >+ /* Try rw first so we can use the fd in ad_convert() */ >+ mode = O_RDWR; >+ >+ rc = ad_open(handle, ad, NULL, smb_fname, mode, 0); >+ if (rc == -1 && ((errno == EROFS) || (errno == EACCES))) { >+ mode = O_RDONLY; >+ rc = ad_open(handle, ad, NULL, smb_fname, mode, 0); >+ } >+ >+ if (rc == -1) { >+ DBG_DEBUG("ad_open [%s] error [%s]\n", >+ smb_fname->base_name, strerror(errno)); >+ goto exit; > >- if (fd == -1) { >- DBG_DEBUG("ad_open [%s] error [%s]\n", >- smb_fname->base_name, strerror(errno)); >- rc = -1; >- goto exit; >- } > } > > len = ad_read(ad, smb_fname); >@@ -1327,6 +1321,7 @@ static struct adouble *ad_fget(TALLOC_CTX *ctx, vfs_handle_struct *handle, > int rc = 0; > ssize_t len; > struct adouble *ad = NULL; >+ int mode; > > DBG_DEBUG("ad_get(%s) path [%s]\n", > type == ADOUBLE_META ? "meta" : "rsrc", >@@ -1338,40 +1333,17 @@ static struct adouble *ad_fget(TALLOC_CTX *ctx, vfs_handle_struct *handle, > goto exit; > } > >- if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) { >- ad->ad_fd = fsp->fh->fd; >- } else { >- /* >- * Here's the deal: for ADOUBLE_META we can do without an fd >- * as we can issue path based xattr calls. For ADOUBLE_RSRC >- * however we need a full-fledged fd for file IO on the ._ >- * file. >- */ >- int fd; >- int mode; >- >- if (type == ADOUBLE_RSRC) { >- /* Try rw first so we can use the fd in ad_convert() */ >- mode = O_RDWR; >- >- fd = ad_open(handle, ad, fsp->base_fsp->fsp_name, >- ADOUBLE_RSRC, mode, 0); >- if (fd == -1 && >- ((errno == EROFS) || (errno == EACCES))) >- { >- mode = O_RDONLY; >- fd = ad_open(handle, ad, >- fsp->base_fsp->fsp_name, ADOUBLE_RSRC, >- mode, 0); >- } >+ /* Try rw first so we can use the fd in ad_convert() */ >+ mode = O_RDWR; > >- if (fd == -1) { >- DBG_DEBUG("error opening AppleDouble for %s\n", >- fsp_str_dbg(fsp)); >- rc = -1; >- goto exit; >- } >- } >+ rc = ad_open(handle, ad, fsp, fsp->base_fsp->fsp_name, mode, 0); >+ if (rc == -1 && ((errno == EROFS) || (errno == EACCES))) { >+ mode = O_RDONLY; >+ rc = ad_open(handle, ad, fsp, fsp->base_fsp->fsp_name, mode, 0); >+ } >+ if (rc == -1) { >+ DBG_DEBUG("error opening AppleDouble [%s]\n", fsp_str_dbg(fsp)); >+ goto exit; > } > > len = ad_read(ad, fsp->base_fsp->fsp_name); >-- >2.9.4 > > >From fea1e351b255e8a00df757ca058e96576aee72a8 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 23 May 2017 17:44:16 +0200 >Subject: [PATCH 11/12] vfs_fruit: return fake pipe fd in > fruit_open_meta_netatalk() > >Do not open the basefile, that conflict with "kernel oplocks = yes". We >just return a fake file fd based on dup'ing a pipe fd and ensure all VFS >functions that go through vfs_fruit and work on the metadata stream can >deal with it. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 7583ee6e1c558067e4c7a7351085fcc0e4240366) >--- > source3/modules/vfs_fruit.c | 73 ++++++++++----------------------------------- > 1 file changed, 16 insertions(+), 57 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 1f2d489..205244d 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -2739,56 +2739,24 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle, > int flags, > mode_t mode) > { >- int rc = 0; >- struct smb_filename *smb_fname_base = NULL; >- int baseflags; >- int hostfd = -1; >+ int rc; >+ int fakefd = -1; > struct adouble *ad = NULL; >+ int fds[2]; > > DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); > >- /* Create an smb_filename with stream_name == NULL. */ >- smb_fname_base = synthetic_smb_fname(talloc_tos(), >- smb_fname->base_name, >- NULL, >- NULL, >- smb_fname->flags); >- >- if (smb_fname_base == NULL) { >- errno = ENOMEM; >- rc = -1; >- goto exit; >- } >- > /* >- * We use baseflags to turn off nasty side-effects when opening the >- * underlying file. >+ * Return a valid fd, but ensure any attempt to use it returns an error >+ * (EPIPE). All operations on the smb_fname or the fsp will use path >+ * based syscalls. > */ >- baseflags = flags; >- baseflags &= ~O_TRUNC; >- baseflags &= ~O_EXCL; >- baseflags &= ~O_CREAT; >- >- hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp, >- baseflags, mode); >- >- /* >- * It is legit to open a stream on a directory, but the base >- * fd has to be read-only. >- */ >- if ((hostfd == -1) && (errno == EISDIR)) { >- baseflags &= ~O_ACCMODE; >- baseflags |= O_RDONLY; >- hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp, >- baseflags, mode); >- } >- >- TALLOC_FREE(smb_fname_base); >- >- if (hostfd == -1) { >- rc = -1; >+ rc = pipe(fds); >+ if (rc != 0) { > goto exit; > } >+ fakefd = fds[0]; >+ close(fds[1]); > > if (flags & (O_CREAT | O_TRUNC)) { > /* >@@ -2801,10 +2769,7 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle, > goto exit; > } > >- fsp->fh->fd = hostfd; >- >- rc = ad_fset(ad, fsp); >- fsp->fh->fd = -1; >+ rc = ad_set(ad, fsp->fsp_name); > if (rc != 0) { > rc = -1; > goto exit; >@@ -2814,22 +2779,16 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle, > } > > exit: >- DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, hostfd)); >+ DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, fakefd)); > if (rc != 0) { > int saved_errno = errno; >- if (hostfd >= 0) { >- /* >- * BUGBUGBUG -- we would need to call >- * fd_close_posix here, but we don't have a >- * full fsp yet >- */ >- fsp->fh->fd = hostfd; >- SMB_VFS_NEXT_CLOSE(handle, fsp); >+ if (fakefd >= 0) { >+ close(fakefd); > } >- hostfd = -1; >+ fakefd = -1; > errno = saved_errno; > } >- return hostfd; >+ return fakefd; > } > > static int fruit_open_meta(vfs_handle_struct *handle, >-- >2.9.4 > > >From 2c8c4df64d848a431e1dd5da7612e39962fd0a24 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 24 May 2017 09:17:19 +0200 >Subject: [PATCH 12/12] vfs_fruit: factor out common code from ad_get() and > ad_fget() > >As a result of the previous changes ad_get() and ad_fget() do completey >the same, so factor out the common code to a new helper function. No >change in behaviour. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com> > >Autobuild-User(master): Volker Lendecke <vl@samba.org> >Autobuild-Date(master): Wed Aug 9 22:33:36 CEST 2017 on sn-devel-144 > >(cherry picked from commit d55c27abc5a7357f740c7065bbe12e7f36b57125) >--- > source3/modules/vfs_fruit.c | 91 +++++++++++++++------------------------------ > 1 file changed, 30 insertions(+), 61 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 205244d..09e0fcd 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -1241,25 +1241,21 @@ static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle, > return ad; > } > >-/** >- * Return AppleDouble data for a file >- * >- * @param[in] ctx talloc context >- * @param[in] handle vfs handle >- * @param[in] smb_fname pathname to file or directory >- * @param[in] type type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC >- * >- * @return talloced struct adouble or NULL on error >- **/ >-static struct adouble *ad_get(TALLOC_CTX *ctx, vfs_handle_struct *handle, >- const struct smb_filename *smb_fname, >- adouble_type_t type) >+static struct adouble *ad_get_internal(TALLOC_CTX *ctx, >+ vfs_handle_struct *handle, >+ files_struct *fsp, >+ const struct smb_filename *smb_fname, >+ adouble_type_t type) > { > int rc = 0; > ssize_t len; > struct adouble *ad = NULL; > int mode; > >+ if (fsp != NULL) { >+ smb_fname = fsp->base_fsp->fsp_name; >+ } >+ > DEBUG(10, ("ad_get(%s) called for %s\n", > type == ADOUBLE_META ? "meta" : "rsrc", > smb_fname->base_name)); >@@ -1273,12 +1269,11 @@ static struct adouble *ad_get(TALLOC_CTX *ctx, vfs_handle_struct *handle, > /* Try rw first so we can use the fd in ad_convert() */ > mode = O_RDWR; > >- rc = ad_open(handle, ad, NULL, smb_fname, mode, 0); >+ rc = ad_open(handle, ad, fsp, smb_fname, mode, 0); > if (rc == -1 && ((errno == EROFS) || (errno == EACCES))) { > mode = O_RDONLY; >- rc = ad_open(handle, ad, NULL, smb_fname, mode, 0); >+ rc = ad_open(handle, ad, fsp, smb_fname, mode, 0); > } >- > if (rc == -1) { > DBG_DEBUG("ad_open [%s] error [%s]\n", > smb_fname->base_name, strerror(errno)); >@@ -1310,6 +1305,24 @@ exit: > * > * @param[in] ctx talloc context > * @param[in] handle vfs handle >+ * @param[in] smb_fname pathname to file or directory >+ * @param[in] type type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC >+ * >+ * @return talloced struct adouble or NULL on error >+ **/ >+static struct adouble *ad_get(TALLOC_CTX *ctx, >+ vfs_handle_struct *handle, >+ const struct smb_filename *smb_fname, >+ adouble_type_t type) >+{ >+ return ad_get_internal(ctx, handle, NULL, smb_fname, type); >+} >+ >+/** >+ * Return AppleDouble data for a file >+ * >+ * @param[in] ctx talloc context >+ * @param[in] handle vfs handle > * @param[in] fsp fsp to use for IO > * @param[in] type type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC > * >@@ -1318,51 +1331,7 @@ exit: > static struct adouble *ad_fget(TALLOC_CTX *ctx, vfs_handle_struct *handle, > files_struct *fsp, adouble_type_t type) > { >- int rc = 0; >- ssize_t len; >- struct adouble *ad = NULL; >- int mode; >- >- DBG_DEBUG("ad_get(%s) path [%s]\n", >- type == ADOUBLE_META ? "meta" : "rsrc", >- fsp_str_dbg(fsp)); >- >- ad = ad_alloc(ctx, handle, type); >- if (ad == NULL) { >- rc = -1; >- goto exit; >- } >- >- /* Try rw first so we can use the fd in ad_convert() */ >- mode = O_RDWR; >- >- rc = ad_open(handle, ad, fsp, fsp->base_fsp->fsp_name, mode, 0); >- if (rc == -1 && ((errno == EROFS) || (errno == EACCES))) { >- mode = O_RDONLY; >- rc = ad_open(handle, ad, fsp, fsp->base_fsp->fsp_name, mode, 0); >- } >- if (rc == -1) { >- DBG_DEBUG("error opening AppleDouble [%s]\n", fsp_str_dbg(fsp)); >- goto exit; >- } >- >- len = ad_read(ad, fsp->base_fsp->fsp_name); >- if (len == -1) { >- DBG_DEBUG("error reading AppleDouble for %s\n", >- fsp_str_dbg(fsp)); >- rc = -1; >- goto exit; >- } >- >-exit: >- DBG_DEBUG("ad_get(%s) path [%s] rc [%d]\n", >- type == ADOUBLE_META ? "meta" : "rsrc", >- fsp_str_dbg(fsp), rc); >- >- if (rc != 0) { >- TALLOC_FREE(ad); >- } >- return ad; >+ return ad_get_internal(ctx, handle, fsp, NULL, type); > } > > /** >-- >2.9.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
vl
:
review+
Actions:
View
Attachments on
bug 12791
:
13459
| 13460