mirror of
https://github.com/samba-team/samba.git
synced 2025-02-24 13:57:43 +03:00
vfs_gpfs: add gpfs:clamp_invalid_times
The timestamp validation added as part of the fix for bug 15151 causes hard failures for certain clients that seem to use a temporary timestamp initially when creating files, changing in a later step. Clamp invalid timestamps to the allowed range 0..UINT32_MAX if "gpfs:clamp_invalid_times = yes" is set. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15151 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Christof Schmitt <cs@samba.org> Autobuild-User(master): Christof Schmitt <cs@samba.org> Autobuild-Date(master): Wed Feb 5 23:42:15 UTC 2025 on atb-devel-224
This commit is contained in:
parent
9bf92bd9fe
commit
0a48167044
@ -316,6 +316,35 @@
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>gpfs:clamp_invalid_times = [ yes | no ]</term>
|
||||
<listitem>
|
||||
<para>
|
||||
GPFS stores timestamps using 32-bit unsigned integers for the
|
||||
seconds component. When using gpfs:settimes = yes, this module
|
||||
validates times that clients attempt to set are within the
|
||||
supported GPFS range between 0 and UINT32_MAX. If a timestamp is
|
||||
outside of this range, the client request is rejected. To cope
|
||||
with clients setting eg temporary timestamps outside the valid
|
||||
range, this parameter can be used to clamp the client timestamp
|
||||
to the allowed range. Times before Thu Jan 1 12:00:00 AM UTC
|
||||
1970 (the UNIX epock) are then set to Thu Jan 1 12:00:00 AM UTC
|
||||
1970, times after Sun Feb 7 06:28:15 AM UTC 2106 will be set to
|
||||
Sun Feb 7 06:28:15 AM UTC 2106.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
<command>no(default)</command> - Fail request with invalid time.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<command>yes</command> - clamp invalid times to 0 or UINT32_MAX.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>gpfs:syncio = [yes|no]</term>
|
||||
<listitem>
|
||||
|
@ -55,6 +55,7 @@ struct gpfs_config_data {
|
||||
bool acl;
|
||||
bool settimes;
|
||||
bool recalls;
|
||||
bool clamp_invalid_times;
|
||||
struct {
|
||||
bool gpfs_fstat_x;
|
||||
} pathref_ok;
|
||||
@ -1588,19 +1589,29 @@ static NTSTATUS vfs_gpfs_fset_dos_attributes(struct vfs_handle_struct *handle,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static int timespec_to_gpfs_time(
|
||||
struct timespec ts, gpfs_timestruc_t *gt, int idx, int *flags)
|
||||
static int timespec_to_gpfs_time(struct gpfs_config_data *config,
|
||||
struct timespec ts,
|
||||
gpfs_timestruc_t *gt,
|
||||
int idx,
|
||||
int *flags)
|
||||
{
|
||||
if (is_omit_timespec(&ts)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ts.tv_sec < 0 || ts.tv_sec > UINT32_MAX) {
|
||||
DBG_NOTICE("GPFS uses 32-bit unsigned timestamps "
|
||||
"and cannot handle %jd.\n",
|
||||
(intmax_t)ts.tv_sec);
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
if (!config->clamp_invalid_times) {
|
||||
DBG_NOTICE("GPFS uses 32-bit unsigned timestamps "
|
||||
"and cannot handle %jd.\n",
|
||||
(intmax_t)ts.tv_sec);
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (ts.tv_sec < 0) {
|
||||
ts.tv_sec = 0;
|
||||
} else {
|
||||
ts.tv_sec = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
*flags |= 1 << idx;
|
||||
@ -1611,7 +1622,8 @@ static int timespec_to_gpfs_time(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smbd_gpfs_set_times(struct files_struct *fsp,
|
||||
static int smbd_gpfs_set_times(struct gpfs_config_data *config,
|
||||
struct files_struct *fsp,
|
||||
struct smb_file_time *ft)
|
||||
{
|
||||
gpfs_timestruc_t gpfs_times[4];
|
||||
@ -1619,18 +1631,22 @@ static int smbd_gpfs_set_times(struct files_struct *fsp,
|
||||
int rc;
|
||||
|
||||
ZERO_ARRAY(gpfs_times);
|
||||
rc = timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
|
||||
rc = timespec_to_gpfs_time(config, ft->atime, gpfs_times, 0, &flags);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
|
||||
rc = timespec_to_gpfs_time(config, ft->mtime, gpfs_times, 1, &flags);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* No good mapping from LastChangeTime to ctime, not storing */
|
||||
rc = timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
|
||||
rc = timespec_to_gpfs_time(config,
|
||||
ft->create_time,
|
||||
gpfs_times,
|
||||
3,
|
||||
&flags);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
@ -1696,7 +1712,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) {
|
||||
return smbd_gpfs_set_times(fsp, ft);
|
||||
return smbd_gpfs_set_times(config, fsp, ft);
|
||||
}
|
||||
|
||||
DBG_DEBUG("gpfs_set_times() not available or disabled, "
|
||||
@ -2048,6 +2064,9 @@ static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
|
||||
config->recalls = lp_parm_bool(SNUM(handle->conn), "gpfs",
|
||||
"recalls", true);
|
||||
|
||||
config->clamp_invalid_times = lp_parm_bool(SNUM(handle->conn), "gpfs",
|
||||
"clamp_invalid_times", false);
|
||||
|
||||
ret = vfs_gpfs_check_pathref(config, handle->conn);
|
||||
if (ret != 0) {
|
||||
DBG_ERR("vfs_gpfs_check_pathref() on [%s] failed\n",
|
||||
|
Loading…
x
Reference in New Issue
Block a user