The branch, master has been updated
       via  fead05a4555 vfs_gpfs: deal with pathrefs fsps in 
smbd_gpfs_set_times()
       via  93a48399f42 lib/gpfswrap: add gpfs_set_times_path() wrapper
       via  1bbdb81899b vfs_gpfs: remove ENOSYS fallback from vfs_gpfs_fntimes()
       via  9a237e168a4 vfs_gpfs: pass fsp to smbd_gpfs_set_times()
       via  443608ee812 vfs_gpfs: deal with pathref fsps in vfs_gpfs_fntimes()
       via  882a466ea5f vfs_gpfs: add sys_proc_fd_path() fallback to 
vfs_gpfs_fset_dos_attributes()
       via  3679f54f178 vfs_gpfs: remove ENOSYS fallback from 
vfs_gpfs_fset_dos_attributes()
       via  fde1b981435 vfs_gpfs: add path based fallback for 
gpfswrap_fstat_x() on pathref handles
       via  730f8c49a9b vfs_gpfs: check for O_PATH support in gpfswrap_fstat_x()
       via  1a3ac7a940f vfs_gpfs: make vfs_gpfs_connect() a no-op on IPC shares
       via  070dce224bb vfs_gpfs: don't check for struct gpfs_config_data in 
vfs_gpfs_[l]stat()
       via  145e739c440 vfs_gpfs: call SMB_VFS_NEXT_CONNECT() before running 
some module initialization code
       via  bcd6bed7b86 smbd: avoid calling creating a pathref in 
smb_set_file_dosmode()
      from  5d53b848f60 wafsamba: always generate compile_commands.json again, 
but only when the samba dependencies changed

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit fead05a45556993b80a84fe9bb07b10debb4ae62
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Aug 5 12:08:00 2021 +0200

    vfs_gpfs: deal with pathrefs fsps in smbd_gpfs_set_times()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>
    
    Autobuild-User(master): Ralph Böhme <s...@samba.org>
    Autobuild-Date(master): Thu Aug 26 20:08:51 UTC 2021 on sn-devel-184

commit 93a48399f427d114df63b434e7fcddc62a1d9ce5
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Aug 5 12:05:16 2021 +0200

    lib/gpfswrap: add gpfs_set_times_path() wrapper
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 1bbdb81899be6c1da6fa9a63bf16a00401e09399
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Aug 13 11:55:16 2021 +0200

    vfs_gpfs: remove ENOSYS fallback from vfs_gpfs_fntimes()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 9a237e168a4bbd5665bd40d521506ca3a6825198
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Aug 5 11:58:58 2021 +0200

    vfs_gpfs: pass fsp to smbd_gpfs_set_times()
    
    No change in behaviour. Prepares for dealing with pathref fsps in
    smbd_gpfs_set_times().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 443608ee8122a2c17258db8dca9885bb524957af
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Aug 5 11:55:30 2021 +0200

    vfs_gpfs: deal with pathref fsps in vfs_gpfs_fntimes()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 882a466ea5f45e5e2197f2408ccd560383e13c3f
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 1 16:08:02 2021 +0200

    vfs_gpfs: add sys_proc_fd_path() fallback to vfs_gpfs_fset_dos_attributes()
    
    gpfs_set_winattrs() is a modifying operation, my expectation thus is that 
it is
    not allowed on pathref (O_PATH) handles even though a recent Linux kernel 
commit
    44a3b87444058b2cb055092cdebc63858707bf66 allowed calling utimensat() on 
pathref
    handles.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    RN: Some VFS operations on pathref (O_PATH) handles fail on GPFS
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 3679f54f178ba6ddb940cc66f701e9b3a1dd543d
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Aug 13 11:39:05 2021 +0200

    vfs_gpfs: remove ENOSYS fallback from vfs_gpfs_fset_dos_attributes()
    
    This API call has existed for a long time, so we can safely assume that this
    always works.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Pair-Programmed-With: Christof Schmitt <c...@samba.org>
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Signed-off-by: Christof Schmitt <c...@samba.org>

commit fde1b98143568fc816165502583f72e73b5d6b71
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 29 19:28:14 2021 +0200

    vfs_gpfs: add path based fallback for gpfswrap_fstat_x() on pathref handles
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 730f8c49a9bc8333f0b722ad65e4e587421c21ec
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 29 15:53:04 2021 +0200

    vfs_gpfs: check for O_PATH support in gpfswrap_fstat_x()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 1a3ac7a940fbb4ad8575ee3b0c56c9de2bf4b1f6
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Aug 6 12:05:44 2021 +0200

    vfs_gpfs: make vfs_gpfs_connect() a no-op on IPC shares
    
    We don't ever expect any filesystem IO operations to be called on an IPC 
shares,
    so there's no need to initialize the module here.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 070dce224bbe190266682c5e362bc2b0ed798ecc
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 11 16:23:24 2021 +0200

    vfs_gpfs: don't check for struct gpfs_config_data in vfs_gpfs_[l]stat()
    
    This is unused and the config object won't be avilable for IPC$ anymore 
with the
    next commit.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit 145e739c440d39651d4f3d30682035ab868488ba
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Aug 6 12:03:38 2021 +0200

    vfs_gpfs: call SMB_VFS_NEXT_CONNECT() before running some module 
initialization code
    
    No change in behaviour. Prepares for a subsequent commit that checks for 
IPC shares.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

commit bcd6bed7b8611654a7e9752b258541f89414b020
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Jul 30 15:17:44 2021 +0200

    smbd: avoid calling creating a pathref in smb_set_file_dosmode()
    
    We already have a fsp with a valid fsp->base_fsp if it's a stream.
    
    Also remove the struct smb_filename arg, it's not needed, the only caller
    already checks for a valid fsp.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14771
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Christof Schmitt <c...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/util/gpfswrap.c        |  14 +++
 lib/util/gpfswrap.h        |   1 +
 source3/modules/vfs_gpfs.c | 268 ++++++++++++++++++++++++++++++++++++++-------
 source3/smbd/trans2.c      |  67 +++++-------
 4 files changed, 269 insertions(+), 81 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/gpfswrap.c b/lib/util/gpfswrap.c
index c348ed7c5b8..5cf6d2148e7 100644
--- a/lib/util/gpfswrap.c
+++ b/lib/util/gpfswrap.c
@@ -39,6 +39,9 @@ static int (*gpfs_get_winattrs_fn)(int fd, struct 
gpfs_winattr *attrs);
 static int (*gpfs_ftruncate_fn)(int fd, gpfs_off64_t length);
 static int (*gpfs_lib_init_fn)(int flags);
 static int (*gpfs_set_times_fn)(int fd, int flags, gpfs_timestruc_t times[4]);
+static int (*gpfs_set_times_path_fn)(char *path,
+                                    int flags,
+                                    gpfs_timestruc_t times[4]);
 static int (*gpfs_quotactl_fn)(const char *pathname,
                               int cmd,
                               int id,
@@ -77,6 +80,7 @@ int gpfswrap_init(void)
        gpfs_ftruncate_fn             = dlsym(l, "gpfs_ftruncate");
        gpfs_lib_init_fn              = dlsym(l, "gpfs_lib_init");
        gpfs_set_times_fn             = dlsym(l, "gpfs_set_times");
+       gpfs_set_times_path_fn        = dlsym(l, "gpfs_set_times_path");
        gpfs_quotactl_fn              = dlsym(l, "gpfs_quotactl");
        gpfs_init_trace_fn            = dlsym(l, "gpfs_init_trace");
        gpfs_query_trace_fn           = dlsym(l, "gpfs_query_trace");
@@ -213,6 +217,16 @@ int gpfswrap_set_times(int fd, int flags, gpfs_timestruc_t 
times[4])
        return gpfs_set_times_fn(fd, flags, times);
 }
 
+int gpfswrap_set_times_path(char *path, int flags, gpfs_timestruc_t times[4])
+{
+       if (gpfs_set_times_path_fn == NULL) {
+               errno = ENOSYS;
+               return -1;
+       }
+
+       return gpfs_set_times_path_fn(path, flags, times);
+}
+
 int gpfswrap_quotactl(const char *pathname, int cmd, int id, void *bufp)
 {
        if (gpfs_quotactl_fn == NULL) {
diff --git a/lib/util/gpfswrap.h b/lib/util/gpfswrap.h
index 138e6ec696e..764cf686d2e 100644
--- a/lib/util/gpfswrap.h
+++ b/lib/util/gpfswrap.h
@@ -44,6 +44,7 @@ int gpfswrap_get_winattrs(int fd, struct gpfs_winattr *attrs);
 int gpfswrap_ftruncate(int fd, gpfs_off64_t length);
 int gpfswrap_lib_init(int flags);
 int gpfswrap_set_times(int fd, int flags, gpfs_timestruc_t times[4]);
+int gpfswrap_set_times_path(char *path, int flags, gpfs_timestruc_t times[4]);
 int gpfswrap_quotactl(const char *pathname, int cmd, int id, void *bufp);
 int gpfswrap_init_trace(void);
 int gpfswrap_query_trace(void);
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index d74bc43db0e..4d1cfa6075a 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -55,6 +55,9 @@ struct gpfs_config_data {
        bool acl;
        bool settimes;
        bool recalls;
+       struct {
+               bool gpfs_fstat_x;
+       } pathref_ok;
 };
 
 struct gpfs_fsp_extension {
@@ -1471,6 +1474,9 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct 
vfs_handle_struct *handle,
                                             uint32_t *dosmode)
 {
        struct gpfs_config_data *config;
+       int fd = fsp_get_pathref_fd(fsp);
+       char buf[PATH_MAX];
+       const char *p = NULL;
        struct gpfs_iattr64 iattr = { };
        unsigned int litemask;
        struct timespec ts;
@@ -1486,7 +1492,22 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct 
vfs_handle_struct *handle,
                return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
        }
 
-       ret = gpfswrap_fstat_x(fsp_get_pathref_fd(fsp), &litemask, &iattr, 
sizeof(iattr));
+       if (fsp->fsp_flags.is_pathref && !config->pathref_ok.gpfs_fstat_x) {
+               if (fsp->fsp_flags.have_proc_fds) {
+                       p = sys_proc_fd_path(fd, buf, sizeof(buf));
+                       if (p == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               } else {
+                       p = fsp->fsp_name->base_name;
+               }
+       }
+
+       if (p != NULL) {
+               ret = gpfswrap_stat_x(p, &litemask, &iattr, sizeof(iattr));
+       } else {
+               ret = gpfswrap_fstat_x(fd, &litemask, &iattr, sizeof(iattr));
+       }
        if (ret == -1 && errno == ENOSYS) {
                return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
        }
@@ -1503,8 +1524,17 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct 
vfs_handle_struct *handle,
 
                set_effective_capability(DAC_OVERRIDE_CAPABILITY);
 
-               ret = gpfswrap_fstat_x(fsp_get_pathref_fd(fsp), &litemask,
-                                      &iattr, sizeof(iattr));
+               if (p != NULL) {
+                       ret = gpfswrap_stat_x(p,
+                                             &litemask,
+                                             &iattr,
+                                             sizeof(iattr));
+               } else {
+                       ret = gpfswrap_fstat_x(fd,
+                                              &litemask,
+                                              &iattr,
+                                              sizeof(iattr));
+               }
                if (ret == -1) {
                        saved_errno = errno;
                }
@@ -1554,16 +1584,48 @@ static NTSTATUS vfs_gpfs_fset_dos_attributes(struct 
vfs_handle_struct *handle,
        }
 
        attrs.winAttrs = vfs_gpfs_dosmode_to_winattrs(dosmode);
-       ret = gpfswrap_set_winattrs(fsp_get_io_fd(fsp),
-                                   GPFS_WINATTR_SET_ATTRS, &attrs);
 
-       if (ret == -1 && errno == ENOSYS) {
-               return SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, dosmode);
+       if (!fsp->fsp_flags.is_pathref) {
+               ret = gpfswrap_set_winattrs(fsp_get_io_fd(fsp),
+                                           GPFS_WINATTR_SET_ATTRS, &attrs);
+               if (ret == -1) {
+                       DBG_WARNING("Setting winattrs failed for %s: %s\n",
+                                   fsp_str_dbg(fsp), strerror(errno));
+                       return map_nt_error_from_unix(errno);
+               }
+               return NT_STATUS_OK;
        }
 
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ret = gpfswrap_set_winattrs_path(p,
+                                                GPFS_WINATTR_SET_ATTRS,
+                                                &attrs);
+               if (ret == -1) {
+                       DBG_WARNING("Setting winattrs failed for [%s][%s]: 
%s\n",
+                                   p, fsp_str_dbg(fsp), strerror(errno));
+                       return map_nt_error_from_unix(errno);
+               }
+               return NT_STATUS_OK;
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       ret = gpfswrap_set_winattrs_path(fsp->fsp_name->base_name,
+                                        GPFS_WINATTR_SET_ATTRS,
+                                        &attrs);
        if (ret == -1) {
-               DBG_WARNING("Setting winattrs failed for %s: %s\n",
-                           fsp->fsp_name->base_name, strerror(errno));
+               DBG_WARNING("Setting winattrs failed for [%s]: %s\n",
+                           fsp_str_dbg(fsp), strerror(errno));
                return map_nt_error_from_unix(errno);
        }
 
@@ -1616,11 +1678,6 @@ static int vfs_gpfs_stat(struct vfs_handle_struct 
*handle,
                         struct smb_filename *smb_fname)
 {
        int ret;
-       struct gpfs_config_data *config;
-
-       SMB_VFS_HANDLE_GET_DATA(handle, config,
-                               struct gpfs_config_data,
-                               return -1);
 
        ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
        if (ret == -1 && errno == EACCES) {
@@ -1635,11 +1692,6 @@ static int vfs_gpfs_lstat(struct vfs_handle_struct 
*handle,
                          struct smb_filename *smb_fname)
 {
        int ret;
-       struct gpfs_config_data *config;
-
-       SMB_VFS_HANDLE_GET_DATA(handle, config,
-                               struct gpfs_config_data,
-                               return -1);
 
        ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        if (ret == -1 && errno == EACCES) {
@@ -1662,7 +1714,8 @@ static void timespec_to_gpfs_time(struct timespec ts, 
gpfs_timestruc_t *gt,
        }
 }
 
-static int smbd_gpfs_set_times(int fd, char *path, struct smb_file_time *ft)
+static int smbd_gpfs_set_times(struct files_struct *fsp,
+                              struct smb_file_time *ft)
 {
        gpfs_timestruc_t gpfs_times[4];
        int flags = 0;
@@ -1679,14 +1732,45 @@ static int smbd_gpfs_set_times(int fd, char *path, 
struct smb_file_time *ft)
                return 0;
        }
 
-       rc = gpfswrap_set_times(fd, flags, gpfs_times);
+       if (!fsp->fsp_flags.is_pathref) {
+               rc = gpfswrap_set_times(fsp_get_io_fd(fsp), flags, gpfs_times);
+               if (rc != 0) {
+                       DBG_WARNING("gpfs_set_times(%s) failed: %s\n",
+                                   fsp_str_dbg(fsp), strerror(errno));
+               }
+               return rc;
+       }
+
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p == NULL) {
+                       return -1;
+               }
 
-       if (rc != 0 && errno != ENOSYS) {
-               DBG_WARNING("gpfs_set_times() returned with error %s for %s\n",
-                           strerror(errno),
-                           path);
+               rc = gpfswrap_set_times_path(buf, flags, gpfs_times);
+               if (rc != 0) {
+                       DBG_WARNING("gpfs_set_times_path(%s,%s) failed: %s\n",
+                                   fsp_str_dbg(fsp), p, strerror(errno));
+               }
+               return rc;
        }
 
+       /*
+        * This is no longer a handle based call.
+        */
+
+       rc = gpfswrap_set_times_path(fsp->fsp_name->base_name,
+                                    flags,
+                                    gpfs_times);
+       if (rc != 0) {
+               DBG_WARNING("gpfs_set_times_path(%s) failed: %s\n",
+                           fsp_str_dbg(fsp), strerror(errno));
+       }
        return rc;
 }
 
@@ -1706,12 +1790,7 @@ static int vfs_gpfs_fntimes(struct vfs_handle_struct 
*handle,
 
        /* Try to use gpfs_set_times if it is enabled and available */
        if (config->settimes) {
-               ret = smbd_gpfs_set_times(fsp_get_io_fd(fsp),
-                                         fsp->fsp_name->base_name,
-                                         ft);
-               if (ret == 0 || (ret == -1 && errno != ENOSYS)) {
-                       return ret;
-               }
+               return smbd_gpfs_set_times(fsp, ft);
        }
 
        DBG_DEBUG("gpfs_set_times() not available or disabled, "
@@ -1740,9 +1819,43 @@ static int vfs_gpfs_fntimes(struct vfs_handle_struct 
*handle,
        attrs.creationTime.tv_sec = ft->create_time.tv_sec;
        attrs.creationTime.tv_nsec = ft->create_time.tv_nsec;
 
-       ret = gpfswrap_set_winattrs(fsp_get_io_fd(fsp),
-                                   GPFS_WINATTR_SET_CREATION_TIME,
-                                   &attrs);
+       if (!fsp->fsp_flags.is_pathref) {
+               ret = gpfswrap_set_winattrs(fsp_get_io_fd(fsp),
+                                           GPFS_WINATTR_SET_CREATION_TIME,
+                                           &attrs);
+               if (ret == -1 && errno != ENOSYS) {
+                       DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
+                       return -1;
+               }
+               return ret;
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p == NULL) {
+                       return -1;
+               }
+
+               ret = gpfswrap_set_winattrs_path(p,
+                                                GPFS_WINATTR_SET_CREATION_TIME,
+                                                &attrs);
+               if (ret == -1 && errno != ENOSYS) {
+                       DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
+                       return -1;
+               }
+               return ret;
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       ret = gpfswrap_set_winattrs_path(fsp->fsp_name->base_name,
+                                        GPFS_WINATTR_SET_CREATION_TIME,
+                                        &attrs);
        if (ret == -1 && errno != ENOSYS) {
                DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
                return -1;
@@ -1866,6 +1979,68 @@ static ssize_t vfs_gpfs_sendfile(vfs_handle_struct 
*handle, int tofd,
        return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, hdr, offset, n);
 }
 
+#ifdef O_PATH
+static int vfs_gpfs_check_pathref_fstat_x(struct gpfs_config_data *config,
+                                         struct connection_struct *conn)
+{
+       struct gpfs_iattr64 iattr = {0};
+       unsigned int litemask;
+       int saved_errno;
+       int fd;
+       int ret;
+
+       fd = open(conn->connectpath, O_PATH);
+       if (fd == -1) {
+               DBG_ERR("openat() of share with O_PATH failed: %s\n",
+                       strerror(errno));
+               return -1;
+       }
+
+       ret = gpfswrap_fstat_x(fd, &litemask, &iattr, sizeof(iattr));
+       if (ret == 0) {
+               close(fd);
+               config->pathref_ok.gpfs_fstat_x = true;
+               return 0;
+       }
+
+       saved_errno = errno;
+       ret = close(fd);
+       if (ret != 0) {
+               DBG_ERR("close failed: %s\n", strerror(errno));
+               return -1;
+       }
+
+       if (saved_errno != EBADF) {
+               DBG_ERR("gpfswrap_fstat_x() of O_PATH handle failed: %s\n",
+                       strerror(saved_errno));
+               return -1;
+       }
+
+       return 0;
+}
+#endif
+
+static int vfs_gpfs_check_pathref(struct gpfs_config_data *config,
+                                 struct connection_struct *conn)
+{
+#ifndef O_PATH
+       /*
+        * This code path leaves all struct gpfs_config_data.pathref_ok members
+        * initialized to false.
+        */
+       return 0;
+#else
+       int ret;
+
+       ret = vfs_gpfs_check_pathref_fstat_x(config, conn);
+       if (ret != 0) {
+               return -1;
+       }
+
+       return 0;
+#endif
+}
+
 static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
                            const char *service, const char *user)
 {
@@ -1873,6 +2048,15 @@ static int vfs_gpfs_connect(struct vfs_handle_struct 
*handle,
        int ret;
        bool check_fstype;
 
+       ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
+       if (ret < 0) {
+               return ret;
+       }
+
+       if (IS_IPC(handle->conn)) {
+               return 0;
+       }
+
        gpfswrap_lib_init(0);
 
        config = talloc_zero(handle->conn, struct gpfs_config_data);
@@ -1882,16 +2066,10 @@ static int vfs_gpfs_connect(struct vfs_handle_struct 
*handle,
                return -1;
        }
 
-       ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
-       if (ret < 0) {
-               TALLOC_FREE(config);
-               return ret;
-       }
-
        check_fstype = lp_parm_bool(SNUM(handle->conn), "gpfs",
                                    "check_fstype", true);
 
-       if (check_fstype && !IS_IPC(handle->conn)) {
+       if (check_fstype) {
                const char *connectpath = handle->conn->connectpath;
                struct statfs buf = { 0 };
 
@@ -1952,6 +2130,14 @@ static int vfs_gpfs_connect(struct vfs_handle_struct 
*handle,
        config->recalls = lp_parm_bool(SNUM(handle->conn), "gpfs",
                                       "recalls", true);
 
+       ret = vfs_gpfs_check_pathref(config, handle->conn);
+       if (ret != 0) {
+               DBG_ERR("vfs_gpfs_check_pathref() on [%s] failed\n",
+                       handle->conn->connectpath);
+               TALLOC_FREE(config);
+               return -1;
+       }
+
        SMB_VFS_HANDLE_SET_DATA(handle, config,
                                NULL, struct gpfs_config_data,
                                return -1);
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index b9e2786eda6..a6bd232f679 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -6655,61 +6655,48 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
 
 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
                                     struct files_struct *fsp,
-                                    struct smb_filename *smb_fname,
                                     uint32_t dosmode)
 {
-       struct smb_filename *smb_fname_base;
-       NTSTATUS status;
+       struct files_struct *dos_fsp = NULL;
+       uint32_t current_dosmode;
+       int ret;
 
-       if (!VALID_STAT(smb_fname->st)) {
+       if (!VALID_STAT(fsp->fsp_name->st)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       /* Always operate on the base_name, even if a stream was passed in. */
-       status = synthetic_pathref(talloc_tos(),
-                                       conn->cwd_fsp,
-                                       smb_fname->base_name,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->twrp,
-                                       smb_fname->flags,
-                                       &smb_fname_base);
-
-       /* do we handle link as non error here ? */
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
+       dos_fsp = fsp->base_fsp != NULL ? fsp->base_fsp : fsp;
 
-       if (dosmode) {
-               if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
+       if (dosmode != 0) {
+               if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
                        dosmode |= FILE_ATTRIBUTE_DIRECTORY;
                } else {
                        dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
                }
        }
 
-       DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned 
int)dosmode));
+       DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
 
        /* check the mode isn't different, before changing it */
-       if ((dosmode != 0) && (dosmode != fdos_mode(fsp))) {
-               DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
-                         "0x%x\n", smb_fname_str_dbg(smb_fname_base),
-                         (unsigned int)dosmode));
-
-               if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
-                                   false)) {
-                       DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
-                                "%s failed (%s)\n",
-                                smb_fname_str_dbg(smb_fname_base),


-- 
Samba Shared Repository

Reply via email to