Skip to content

Commit

Permalink
net/samba - fix issue with ntimes in vfs_default
Browse files Browse the repository at this point in the history
Perform two utimensat(2) calls as necessary in vfs_default.c.
This is a FreeBSD specific behavior. Remove sanity check
that prevents ntimes request that will change inode
birthtime when changing mtime in isolation. Since this
logic is now duplicated from vfs_ixnas, remove ntimes
hook from vfs_ixnas so that legacy configurations
and vfs_ixnas both use same utimensat() wrapper.
  • Loading branch information
anodos325 committed Jan 7, 2022
1 parent 1de19c2 commit abbc246
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 96 deletions.
2 changes: 1 addition & 1 deletion net/samba/Makefile
Expand Up @@ -3,7 +3,7 @@

PORTNAME= ${SAMBA4_BASENAME}
PORTVERSION= ${SAMBA4_VERSION}
PORTREVISION= 8
PORTREVISION= 9
CATEGORIES?= net
MASTER_SITES= SAMBA/samba/stable SAMBA/samba/rc
DISTNAME= ${SAMBA4_DISTNAME}
Expand Down
92 changes: 2 additions & 90 deletions net/samba/files/0001-add-ix-custom-vfs-modules.patch
Expand Up @@ -2204,10 +2204,10 @@ index 00000000000..dcade599317
+#endif /* !__SMB_LIBZFS_H */
diff --git a/source3/modules/vfs_ixnas.c b/source3/modules/vfs_ixnas.c
new file mode 100644
index 00000000000..7a15176a56a
index 00000000000..449ccd56856
--- /dev/null
+++ b/source3/modules/vfs_ixnas.c
@@ -0,0 +1,2591 @@
@@ -0,0 +1,2503 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * A dumping ground for FreeBSD-specific VFS functions. For testing case
Expand Down Expand Up @@ -4443,93 +4443,6 @@ index 00000000000..7a15176a56a
+ return result;
+}
+
+static bool is_robocopy_init(struct smb_file_time *ft)
+{
+ if (!null_timespec(ft->atime) ||
+ !null_timespec(ft->create_time)) {
+ return false;
+ }
+ if (ft->mtime.tv_sec == 315619200) {
+ return true;
+ }
+ return false;
+}
+
+static int ixnas_ntimes(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ struct smb_file_time *ft)
+{
+ int result = -1;
+ struct ixnas_config_data *config = NULL;
+
+ if (smb_fname->stream_name) {
+ errno = ENOENT;
+ return result;
+ }
+
+ SMB_VFS_HANDLE_GET_DATA(handle, config,
+ struct ixnas_config_data,
+ return -1);
+
+ if (config->dosattrib_xattr) {
+ return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
+ }
+
+ /*
+ * man utimensat(2)
+ * If times is non-NULL, it is assumed to point to an array of two
+ * timespec structures. The access time is set to the value of the
+ * second element. For filesystems that support file birth (creation) times,
+ * the birth time will be set to the value of the second element if the
+ * second element is older than the currently set birthtime. To set both
+ * a birth time and a modification tie, two calls are required. The first
+ * to set the birth time and the second to set the (presumabley newer).
+ */
+ if (ft != NULL) {
+ if (is_robocopy_init(ft)) {
+ return 0;
+ }
+ struct timespec ts[2];
+ if (is_omit_timespec(&ft->atime)) {
+ ft->atime= smb_fname->st.st_ex_atime;
+ }
+ if (is_omit_timespec(&ft->mtime)) {
+ ft->mtime = smb_fname->st.st_ex_mtime;
+ }
+ /* mtime and atime are unchanged */
+ if ((timespec_compare(&ft->atime,
+ &smb_fname->st.st_ex_atime) == 0) &&
+ (timespec_compare(&ft->mtime,
+ &smb_fname->st.st_ex_mtime) == 0)) {
+ return 0;
+ }
+ /*
+ * Perform two utimensat() calls if needed to set the specified
+ * timestamps.
+ */
+ if (is_omit_timespec(&ft->create_time)) {
+ ft->create_time = ft->mtime;
+ }
+ ts[0] = ft->atime;
+ ts[1] = ft->create_time;
+ result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
+ if (timespec_compare(&ft->mtime, &ft->create_time) != 0) {
+ ts[1] = ft->mtime;
+ result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
+ }
+ } else {
+ result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
+ }
+ out:
+ if (result != 0) {
+ DBG_ERR("%s: utimensat failed: %s\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno));
+ }
+ return result;
+}
+
+
+static bool set_zfs_parameters(struct vfs_handle_struct *handle,
+ const char *service, const char *user,
+ struct ixnas_config_data *config)
Expand Down Expand Up @@ -4759,7 +4672,6 @@ index 00000000000..7a15176a56a
+ /* zfs_acl_enabled = true */
+ .chmod_fn = ixnas_chmod,
+ .fchmod_fn = ixnas_fchmod,
+ .ntimes_fn = ixnas_ntimes,
+ .renameat_fn = ixnas_renameat,
+ .fget_nt_acl_fn = ixnas_fget_nt_acl,
+ .get_nt_acl_at_fn = ixnas_get_nt_acl,
Expand Down
22 changes: 17 additions & 5 deletions net/samba/files/smbd-core-changes.patch
Expand Up @@ -113,7 +113,7 @@ index d527f850628..1f8d5024da7 100644
struct files_struct *cwd_fsp; /* Working directory. */
bool tcon_done;
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index cf5e1cbc296..47002084ee7 100644
index cf5e1cbc296..a98cf31b8bd 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -40,6 +40,8 @@
Expand Down Expand Up @@ -202,18 +202,30 @@ index cf5e1cbc296..47002084ee7 100644

static int vfswrap_ntimes(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
@@ -2542,7 +2547,10 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
@@ -2542,11 +2547,21 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
}

#if defined(HAVE_UTIMENSAT)
- if (ft != NULL) {
+ if (ft != NULL && is_robocopy_init(ft)) {
+ return 0;
+ } else if ((ft != NULL) &&
+ (timespec_compare(&ft->mtime, &smb_fname->st.st_ex_btime) == 1)) {
+ } else if (ft != NULL) {
struct timespec ts[2];
+ bool has_btime = !is_omit_timespec(&ft->create_time);
+
ts[0] = ft->atime;
ts[1] = ft->mtime;
- ts[1] = ft->mtime;
+ ts[1] = has_btime ? ft->create_time : ft->mtime;
+
result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
+
+ if (has_btime) {
+ ts[1] = ft->mtime;
+ result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
+ }
} else {
result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
}
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index 14532395e8a..c73d5d9e0eb 100644
--- a/source3/modules/vfs_streams_xattr.c
Expand Down

0 comments on commit abbc246

Please sign in to comment.