[SCM] Samba Shared Repository - branch master updated

Ralph Böhme slow at samba.org
Thu Aug 26 20:09:01 UTC 2021


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 <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Thu Aug 26 20:08:51 UTC 2021 on sn-devel-184

commit 93a48399f427d114df63b434e7fcddc62a1d9ce5
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 1bbdb81899be6c1da6fa9a63bf16a00401e09399
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 9a237e168a4bbd5665bd40d521506ca3a6825198
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 443608ee8122a2c17258db8dca9885bb524957af
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 882a466ea5f45e5e2197f2408ccd560383e13c3f
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 3679f54f178ba6ddb940cc66f701e9b3a1dd543d
Author: Ralph Boehme <slow at 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 <cs at samba.org>
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Signed-off-by: Christof Schmitt <cs at samba.org>

commit fde1b98143568fc816165502583f72e73b5d6b71
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 730f8c49a9bc8333f0b722ad65e4e587421c21ec
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 1a3ac7a940fbb4ad8575ee3b0c56c9de2bf4b1f6
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 070dce224bbe190266682c5e362bc2b0ed798ecc
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit 145e739c440d39651d4f3d30682035ab868488ba
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>

commit bcd6bed7b8611654a7e9752b258541f89414b020
Author: Ralph Boehme <slow at 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 <slow at samba.org>
    Reviewed-by: Christof Schmitt <cs at 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



More information about the samba-cvs mailing list