vfs_streams_xattr: return a fake fd in streams_xattr_open()
authorRalph Boehme <slow@samba.org>
Thu, 11 May 2017 16:08:56 +0000 (18:08 +0200)
committerKarolin Seeger <kseeger@samba.org>
Mon, 14 Aug 2017 08:50:10 +0000 (10:50 +0200)
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

index 08ec385c1a2b98ab5d9de009a0058cb294ef5d0f..4cf457999620fa27f4d923c41c492b01cd8c595a 100644 (file)
@@ -397,14 +397,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));
 
@@ -433,44 +436,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->base_name, xattr_name, &ea);
@@ -542,16 +519,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;