]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: implement modern write time update logic
authorRalph Boehme <slow@samba.org>
Mon, 10 Mar 2025 15:31:13 +0000 (16:31 +0100)
committerRalph Boehme <slow@samba.org>
Thu, 27 Mar 2025 06:37:31 +0000 (06:37 +0000)
The gist of this is:

1. A write or other modifications as per MS-FSA "2.1.4.17 Algorithm for Noting
that a File Has Been Modified" immediately update the file times, there's no
delayed update.

2. Setting a timestamp on a handle only disables further timestamp updates via
that handle. Modifications via other handles must still update the timestamps.

This can not be implemented by storing the sticky writetime in the
share_mode_data record for performance reasons, as from 2 it follows that the
record would have to be checked and updated for every write on all handles.

Instead, writes on handles with sticky writetime in effect, record the current
timestamp before the modification and reset the filesystem timestamp to the
recorded value after doing the modification.

For reference, these are the relevant pieces from MS-FSA:

2.1.1.6 Abstract Date Model: Per Open

- UserSetModificationTime: A Boolean that is TRUE if a user has explicitly set
File.LastModificationTime through this Open.

- UserSetChangeTime: A Boolean that is TRUE if a user has explicitly set
File.LastChangeTime through this Open.

- UserSetAccessTime: A Boolean that is TRUE if a user has explicitly set
File.LastAccessTime through this Open.

2.1.4.17 Algorithm for Noting That a File Has Been Modified

The inputs for this algorithm are as follows:
- Open: The Open through which the file was modified.

The pseudocode for the algorithm is as follows:

The object store SHOULD<43>:

- If Open.UserSetModificationTime is FALSE, set Open.File.LastModificationTime
to the current system time.

- If Open.UserSetChangeTime is FALSE, set Open.File.LastChangeTime to the
current system time.

- If Open.UserSetAccessTime is FALSE, set Open.File.LastAccessTime to the
current system time.

- Set Open.File.FileAttributes.FILE_ATTRIBUTE_ARCHIVE to TRUE.

This then gets used for eg writes:

2.1.5.4 Server Requests a Write

...

- The object store MUST note that the file has been modified as specified in
section 2.1.4.17 with Open equal to Open.

...

Note the following differences between Windows behaviour and current
MS-FSA, these are documentation bugs that will be fixed in later
releases as discussed here:

https://lists.samba.org/archive/cifs-protocol/2025-March/004453.html

* When processing FileEndOfFileInformation timestamps must be updated
if new size equals current size

* When processing FileAllocationInformation timestamps must be updated
if new size equals current size

* When processing FileAllocationInformation,
  If (the new allocation size is less than the existing allocation)
    Set the modification time (which will also updates the change time)
  Else
    Update the LastChangeTime

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13594

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Thu Mar 27 06:37:31 UTC 2025 on atb-devel-224

25 files changed:
selftest/knownfail.d/samba3.base.delaywrite [deleted file]
source3/include/vfs.h
source3/librpc/idl/open_files.idl
source3/locking/locking.c
source3/locking/proto.h
source3/locking/share_mode_lock.c
source3/locking/share_mode_lock.h
source3/smbd/close.c
source3/smbd/dir.c
source3/smbd/dir.h
source3/smbd/dosmode.c
source3/smbd/durable.c
source3/smbd/fileio.c
source3/smbd/files.c
source3/smbd/globals.h
source3/smbd/open.c
source3/smbd/proto.h
source3/smbd/smb1_aio.c
source3/smbd/smb1_reply.c
source3/smbd/smb1_trans2.c
source3/smbd/smb2_aio.c
source3/smbd/smb2_flush.c
source3/smbd/smb2_getinfo.c
source3/smbd/smb2_query_directory.c
source3/smbd/smb2_trans2.c

diff --git a/selftest/knownfail.d/samba3.base.delaywrite b/selftest/knownfail.d/samba3.base.delaywrite
deleted file mode 100644 (file)
index 97a81aa..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-^samba3.base.delaywrite.finfo update on close\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time\(fileserver_smb1\)
-^samba3.base.delaywrite.update of write time and SMBwrite truncate\(fileserver_smb1\)
-^samba3.base.delaywrite.update of write time and SMBwrite truncate expand\(fileserver_smb1\)
-^samba3.base.delaywrite.update of write time using SET_END_OF_FILE\(fileserver_smb1\)
-^samba3.base.delaywrite.update of write time using SET_ALLOCATION_SIZE\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time using 2 connections\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 3\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 3a\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 3b\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 3c\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 4\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 5\(fileserver_smb1\)
-^samba3.base.delaywrite.delayed update of write time 6\(fileserver_smb1\)
-^samba3.smb2.timestamps.delayed-write-vs-seteof\(.*\)
-^samba3.smb2.timestamps.delayed-write-vs-flush\(.*\)
-^samba3.smb2.timestamps.delayed-write-vs-setbasic\(.*\)
-^samba3.smb2.timestamps.delayed-2write\(.*\)
-^samba3.base.delaywrite.modern_write_time_update-1\(fileserver_smb1\)
-^samba3.smb2.timestamps.modern_write_time_update-1\(.*\)
-^samba3.smb2.timestamps.modern_write_time_update-2\(.*\)
index 581148fa053bb28767ee1f2dde82a3876999825e..d7ac7f0fbafadd8b7fb7ebc16a1942527f42d695 100644 (file)
@@ -443,8 +443,6 @@ typedef struct files_struct {
                bool is_fsa : 1;     /* See below */
                bool have_proc_fds : 1;
                bool kernel_share_modes_taken : 1;
-               bool update_write_time_triggered : 1;
-               bool update_write_time_on_close : 1;
                bool write_time_forced : 1;
                bool can_lock : 1;
                bool can_read : 1;
@@ -466,7 +464,7 @@ typedef struct files_struct {
                bool posix_append : 1;
        } fsp_flags;
 
-       struct tevent_timer *update_write_time_event;
+       /* Only used for SMB1 close with explicit time */
        struct timespec close_write_time;
 
        int oplock_type;
index 401b0ec092fdc7a48edab435674aefb7f65d58cf..2b5a03589d1ef3c2c5944f7936121a5958465c76 100644 (file)
@@ -70,8 +70,6 @@ interface open_files
                [string,charset(UTF8)] char *stream_name;
                uint32 num_delete_tokens;
                [size_is(num_delete_tokens)] delete_token delete_tokens[];
-               NTTIME old_write_time;
-               NTTIME changed_write_time;
                [skip] boolean8 not_stored;
                [skip] boolean8 modified;
                [ignore] file_id id; /* In memory key used to lookup cache. */
@@ -111,10 +109,7 @@ interface open_files
                [string,charset(UTF8)] char *base_name;
                hyper initial_allocation_size;
                hyper position_information;
-               boolean8 update_write_time_triggered;
-               boolean8 update_write_time_on_close;
                boolean8 write_time_forced;
-               NTTIME close_write_time;
                vfs_default_durable_stat stat_info;
        } vfs_default_durable_cookie;
 
index fefbf88f20a76ad92c81c913fb4195d44a548e86..62f3e2e80379812d2455df70d6d812b965f8b79f 100644 (file)
@@ -641,8 +641,7 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
 
 void get_file_infos(struct file_id id,
                    uint32_t name_hash,
-                   bool *delete_on_close,
-                   struct timespec *write_time)
+                   bool *delete_on_close)
 {
        struct share_mode_lock *lck;
 
@@ -650,10 +649,6 @@ void get_file_infos(struct file_id id,
                *delete_on_close = false;
        }
 
-       if (write_time) {
-               *write_time = make_omit_timespec();
-       }
-
        if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
                return;
        }
@@ -662,10 +657,6 @@ void get_file_infos(struct file_id id,
                *delete_on_close = is_delete_on_close_set(lck, name_hash);
        }
 
-       if (write_time) {
-               *write_time = get_share_mode_write_time(lck);
-       }
-
        TALLOC_FREE(lck);
 }
 
@@ -1095,144 +1086,6 @@ bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
        return find_delete_on_close_token(d, name_hash) != NULL;
 }
 
-struct set_sticky_write_time_state {
-       struct file_id fileid;
-       struct timespec write_time;
-       bool ok;
-};
-
-static void set_sticky_write_time_fn(struct share_mode_lock *lck,
-                                    void *private_data)
-{
-       struct set_sticky_write_time_state *state = private_data;
-       struct share_mode_data *d = NULL;
-       struct file_id_buf ftmp;
-       struct timeval_buf tbuf;
-       NTSTATUS status;
-
-       status = share_mode_lock_access_private_data(lck, &d);
-       if (!NT_STATUS_IS_OK(status)) {
-               /* Any error recovery possible here ? */
-               DBG_ERR("share_mode_lock_access_private_data() failed for "
-                       "%s id=%s - %s\n",
-                       timespec_string_buf(&state->write_time, true, &tbuf),
-                       file_id_str_buf(state->fileid, &ftmp),
-                       nt_errstr(status));
-               return;
-       }
-
-       share_mode_set_changed_write_time(lck, state->write_time);
-
-       state->ok = true;
-}
-
-bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
-{
-       struct set_sticky_write_time_state state = {
-               .fileid = fileid,
-               .write_time = write_time,
-       };
-       struct file_id_buf ftmp;
-       struct timeval_buf tbuf;
-       NTSTATUS status;
-
-       status = share_mode_do_locked_vfs_denied(fileid,
-                                                set_sticky_write_time_fn,
-                                                &state);
-       if (!NT_STATUS_IS_OK(status)) {
-               /* Any error recovery possible here ? */
-               DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
-                       "%s id=%s - %s\n",
-                       timespec_string_buf(&write_time, true, &tbuf),
-                       file_id_str_buf(fileid, &ftmp),
-                       nt_errstr(status));
-               return false;
-       }
-
-       return state.ok;
-}
-
-struct set_write_time_state {
-       struct file_id fileid;
-       struct timespec write_time;
-       bool ok;
-};
-
-static void set_write_time_fn(struct share_mode_lock *lck,
-                             void *private_data)
-{
-       struct set_write_time_state *state = private_data;
-       struct share_mode_data *d = NULL;
-       struct file_id_buf idbuf;
-       struct timeval_buf tbuf;
-       NTSTATUS status;
-
-       status = share_mode_lock_access_private_data(lck, &d);
-       if (!NT_STATUS_IS_OK(status)) {
-               /* Any error recovery possible here ? */
-               DBG_ERR("share_mode_lock_access_private_data() failed for "
-                       "%s id=%s - %s\n",
-                       timespec_string_buf(&state->write_time, true, &tbuf),
-                       file_id_str_buf(state->fileid, &idbuf),
-                       nt_errstr(status));
-               return;
-       }
-
-       share_mode_set_old_write_time(lck, state->write_time);
-
-       state->ok = true;
-}
-
-bool set_write_time(struct file_id fileid, struct timespec write_time)
-{
-       struct set_write_time_state state = {
-               .fileid = fileid,
-               .write_time = write_time,
-       };
-       struct file_id_buf idbuf;
-       struct timeval_buf tbuf;
-       NTSTATUS status;
-
-       status = share_mode_do_locked_vfs_denied(fileid,
-                                                set_write_time_fn,
-                                                &state);
-       if (!NT_STATUS_IS_OK(status)) {
-               DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
-                       "%s id=%s - %s\n",
-                       timespec_string_buf(&write_time, true, &tbuf),
-                       file_id_str_buf(fileid, &idbuf),
-                       nt_errstr(status));
-               return false;
-       }
-
-       return state.ok;
-}
-
-struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
-{
-       struct share_mode_data *d = NULL;
-       NTSTATUS status;
-
-       status = share_mode_lock_access_private_data(lck, &d);
-       if (!NT_STATUS_IS_OK(status)) {
-               struct file_id id = share_mode_lock_file_id(lck);
-               struct file_id_buf id_buf;
-               struct timespec ts_zero = {};
-               /* Any error recovery possible here ? */
-               DBG_ERR("share_mode_lock_access_private_data() failed for "
-                       "%s - %s\n",
-                       file_id_str_buf(id, &id_buf),
-                       nt_errstr(status));
-               smb_panic(__location__);
-               return ts_zero;
-       }
-
-       if (!null_nttime(d->changed_write_time)) {
-               return nt_time_to_full_timespec(d->changed_write_time);
-       }
-       return nt_time_to_full_timespec(d->old_write_time);
-}
-
 struct file_has_open_streams_state {
        bool found_one;
        bool ok;
index adfe5fede8f933c3f7a8cf09e2ca94a5bc674cb3..524d1d6d145aa9a04411cc224b0eea9c8876c90b 100644 (file)
@@ -137,8 +137,7 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
                        const struct smb_filename *smb_fname);
 void get_file_infos(struct file_id id,
                    uint32_t name_hash,
-                   bool *delete_on_close,
-                   struct timespec *write_time);
+                   bool *delete_on_close);
 bool is_valid_share_mode_entry(const struct share_mode_entry *e);
 bool share_entry_stale_pid(struct share_mode_entry *e);
 NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
@@ -159,9 +158,6 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
                        const struct security_token *nt_tok,
                        const struct security_unix_token *tok);
 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash);
-bool set_sticky_write_time(struct file_id fileid, struct timespec write_time);
-bool set_write_time(struct file_id fileid, struct timespec write_time);
-struct timespec get_share_mode_write_time(struct share_mode_lock *lck);
 bool file_has_open_streams(files_struct *fsp);
 bool share_mode_forall_leases(
        struct share_mode_lock *lck,
index 8ccb3bdeaecf319549463632a986595ae731418a..0bd4cbba711a2c9da942a2f4dc99042714312eec 100644 (file)
@@ -707,13 +707,11 @@ static NTSTATUS share_mode_data_store(struct share_mode_data *d)
 
 static struct share_mode_data *fresh_share_mode_lock(
        TALLOC_CTX *mem_ctx, const char *servicepath,
-       const struct smb_filename *smb_fname,
-       const struct timespec *old_write_time)
+       const struct smb_filename *smb_fname)
 {
        struct share_mode_data *d;
 
-       if ((servicepath == NULL) || (smb_fname == NULL) ||
-           (old_write_time == NULL)) {
+       if ((servicepath == NULL) || (smb_fname == NULL)) {
                return NULL;
        }
 
@@ -737,7 +735,6 @@ static struct share_mode_data *fresh_share_mode_lock(
        if (d->servicepath == NULL) {
                goto fail;
        }
-       d->old_write_time = full_timespec_to_nt_time(old_write_time);
        d->flags = SHARE_MODE_SHARE_DELETE |
                SHARE_MODE_SHARE_WRITE |
                SHARE_MODE_SHARE_READ;
@@ -800,7 +797,6 @@ struct get_static_share_mode_data_state {
        struct file_id id;
        const char *servicepath;
        const struct smb_filename *smb_fname;
-       const struct timespec *old_write_time;
        NTSTATUS status;
 };
 
@@ -835,8 +831,7 @@ static void get_static_share_mode_data_fn(
                d = fresh_share_mode_lock(
                        state->mem_ctx,
                        state->servicepath,
-                       state->smb_fname,
-                       state->old_write_time);
+                       state->smb_fname);
                if (d == NULL) {
                        state->status = NT_STATUS_NO_MEMORY;
                        return;
@@ -860,15 +855,13 @@ static void get_static_share_mode_data_fn(
 static NTSTATUS get_static_share_mode_data(
        struct file_id id,
        const char *servicepath,
-       const struct smb_filename *smb_fname,
-       const struct timespec *old_write_time)
+       const struct smb_filename *smb_fname)
 {
        struct get_static_share_mode_data_state state = {
                .mem_ctx = lock_ctx,
                .id = id,
                .servicepath = servicepath,
                .smb_fname = smb_fname,
-               .old_write_time = old_write_time,
        };
        NTSTATUS status;
 
@@ -923,7 +916,6 @@ static NTSTATUS get_share_mode_lock_internal(
        struct file_id id,
        const char *servicepath,
        const struct smb_filename *smb_fname,
-       const struct timespec *old_write_time,
        struct share_mode_lock *lck)
 {
        NTSTATUS status;
@@ -973,8 +965,7 @@ static NTSTATUS get_share_mode_lock_internal(
        status = get_static_share_mode_data(
                id,
                servicepath,
-               smb_fname,
-               old_write_time);
+               smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_DEBUG("get_static_share_mode_data failed: %s\n",
                          nt_errstr(status));
@@ -1081,7 +1072,6 @@ struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
        status = get_share_mode_lock_internal(id,
                                              NULL, /* servicepath */
                                              NULL, /* smb_fname */
-                                             NULL, /* old_write_time */
                                              lck);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_GET_SHARE_MODE_LOCK(status,
@@ -1240,48 +1230,6 @@ static struct share_mode_data *_share_mode_lock_assert_private_data(
        return d;
 }
 
-NTTIME share_mode_changed_write_time(struct share_mode_lock *lck)
-{
-       struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
-       return d->changed_write_time;
-}
-
-void share_mode_set_changed_write_time(struct share_mode_lock *lck, struct timespec write_time)
-{
-       struct file_id fileid = share_mode_lock_file_id(lck);
-       struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
-       struct file_id_buf ftmp;
-       struct timeval_buf tbuf;
-       NTTIME nt = full_timespec_to_nt_time(&write_time);
-
-       DBG_INFO("%s id=%s\n",
-                timespec_string_buf(&write_time, true, &tbuf),
-                file_id_str_buf(fileid, &ftmp));
-
-       if (d->changed_write_time != nt) {
-               d->modified = true;
-               d->changed_write_time = nt;
-       }
-}
-
-void share_mode_set_old_write_time(struct share_mode_lock *lck, struct timespec write_time)
-{
-       struct file_id fileid = share_mode_lock_file_id(lck);
-       struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
-       struct file_id_buf ftmp;
-       struct timeval_buf tbuf;
-       NTTIME nt = full_timespec_to_nt_time(&write_time);
-
-       DBG_INFO("%s id=%s\n",
-                timespec_string_buf(&write_time, true, &tbuf),
-                file_id_str_buf(fileid, &ftmp));
-
-       if (d->changed_write_time != nt) {
-               d->modified = true;
-               d->old_write_time = nt;
-       }
-}
-
 const char *share_mode_servicepath(struct share_mode_lock *lck)
 {
        struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
@@ -3178,7 +3126,6 @@ static void share_mode_do_locked_vfs_denied_fn(struct g_lock_lock_cb_state *glck
        state->status = get_share_mode_lock_internal(state->id,
                                                     NULL,  /* servicepath */
                                                     NULL,  /* smb_fname */
-                                                    NULL,  /* old_write_time */
                                                     &lck);
        if (!NT_STATUS_IS_OK(state->status)) {
                DBG_GET_SHARE_MODE_LOCK(state->status,
@@ -3289,7 +3236,6 @@ NTSTATUS _share_mode_do_locked_vfs_allowed(
        status = get_share_mode_lock_internal(id,
                                              NULL,  /* servicepath */
                                              NULL,  /* smb_fname */
-                                             NULL,  /* old_write_time */
                                              &lck);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_GET_SHARE_MODE_LOCK(status,
@@ -3315,7 +3261,6 @@ struct share_mode_entry_prepare_lock_state {
        struct file_id id;
        const char *servicepath;
        const struct smb_filename *smb_fname;
-       const struct timespec *old_write_time;
        share_mode_entry_prepare_lock_fn_t fn;
        void *private_data;
        const char *location;
@@ -3337,7 +3282,6 @@ static void share_mode_entry_prepare_lock_fn(struct g_lock_lock_cb_state *glck,
        state->status = get_share_mode_lock_internal(state->id,
                                                     state->servicepath,
                                                     state->smb_fname,
-                                                    state->old_write_time,
                                                     state->lck);
        if (!NT_STATUS_IS_OK(state->status)) {
                /* no DBG_GET_SHARE_MODE_LOCK here! */
@@ -3375,7 +3319,6 @@ NTSTATUS _share_mode_entry_prepare_lock(
        struct file_id id,
        const char *servicepath,
        const struct smb_filename *smb_fname,
-       const struct timespec *old_write_time,
        share_mode_entry_prepare_lock_fn_t fn,
        void *private_data,
        const char *location)
@@ -3384,7 +3327,6 @@ NTSTATUS _share_mode_entry_prepare_lock(
                .id = id,
                .servicepath = servicepath,
                .smb_fname = smb_fname,
-               .old_write_time = old_write_time,
                .fn = fn,
                .private_data = private_data,
                .location = location,
@@ -3468,7 +3410,6 @@ static void share_mode_entry_prepare_unlock_relock_fn(struct g_lock_lock_cb_stat
        state->status = get_share_mode_lock_internal(state->id,
                                                     NULL,  /* servicepath */
                                                     NULL,  /* smb_fname */
-                                                    NULL,  /* old_write_time */
                                                     state->lck);
        if (!NT_STATUS_IS_OK(state->status)) {
                /* no DBG_GET_SHARE_MODE_LOCK here! */
index 97a7a847f541e290c538f32fee4d01342a25adc3..0a2696d38a2f5ef09342558e42712940b8b53f32 100644 (file)
@@ -111,9 +111,6 @@ bool share_mode_forall_entries(
                   void *private_data),
        void *private_data);
 
-NTTIME share_mode_changed_write_time(struct share_mode_lock *lck);
-void share_mode_set_changed_write_time(struct share_mode_lock *lck, struct timespec write_time);
-void share_mode_set_old_write_time(struct share_mode_lock *lck, struct timespec write_time);
 const char *share_mode_servicepath(struct share_mode_lock *lck);
 char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck);
 char *share_mode_data_dump(
@@ -179,20 +176,19 @@ NTSTATUS _share_mode_entry_prepare_lock(
        struct file_id id,
        const char *servicepath,
        const struct smb_filename *smb_fname,
-       const struct timespec *old_write_time,
        share_mode_entry_prepare_lock_fn_t fn,
        void *private_data,
        const char *location);
 #define share_mode_entry_prepare_lock_add(__prepare_state, __id, \
-               __servicepath, __smb_fname, __old_write_time, \
+               __servicepath, __smb_fname, \
                __fn, __private_data) \
        _share_mode_entry_prepare_lock(__prepare_state, __id, \
-               __servicepath, __smb_fname, __old_write_time, \
+               __servicepath, __smb_fname, \
                __fn, __private_data, __location__);
 #define share_mode_entry_prepare_lock_del(__prepare_state, __id, \
                __fn, __private_data) \
        _share_mode_entry_prepare_lock(__prepare_state, __id, \
-               NULL, NULL, NULL, \
+               NULL, NULL, \
                __fn, __private_data, __location__);
 
 typedef void (*share_mode_entry_prepare_unlock_fn_t)(
index bf013e5e5d6f6b4583ad7487b458af57d0fd053a..290cae428c0d90b6dc5f5e2806e74cadb18f66c4 100644 (file)
@@ -334,28 +334,6 @@ static void close_share_mode_lock_prepare(struct share_mode_lock *lck,
                }
        }
 
-       if (fsp->fsp_flags.write_time_forced) {
-               NTTIME mtime = share_mode_changed_write_time(lck);
-               struct timespec ts = nt_time_to_full_timespec(mtime);
-
-               DBG_DEBUG("write time forced for %s %s\n",
-                         state->object_type, fsp_str_dbg(fsp));
-               set_close_write_time(fsp, ts);
-       } else if (fsp->fsp_flags.update_write_time_on_close) {
-               /* Someone had a pending write. */
-               if (is_omit_timespec(&fsp->close_write_time)) {
-                       DBG_DEBUG("update to current time for %s %s\n",
-                                 state->object_type, fsp_str_dbg(fsp));
-                       /* Update to current time due to "normal" write. */
-                       set_close_write_time(fsp, timespec_current());
-               } else {
-                       DBG_DEBUG("write time pending for %s %s\n",
-                                 state->object_type, fsp_str_dbg(fsp));
-                       /* Update to time set on close call. */
-                       set_close_write_time(fsp, fsp->close_write_time);
-               }
-       }
-
        if (fsp->fsp_flags.initial_delete_on_close &&
                        !is_delete_on_close_set(lck, fsp->name_hash)) {
                /* Initial delete on close was set and no one else
@@ -447,11 +425,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
        struct smb_filename *base_fname = NULL;
        int ret;
 
-       /* Ensure any pending write time updates are done. */
-       if (fsp->update_write_time_event) {
-               fsp_flush_write_time_update(fsp);
-       }
-
        /*
         * Lock the share entries, and determine if we should delete
         * on close. If so delete whilst the lock is still in effect.
@@ -497,11 +470,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
        DBG_INFO("%s. Delete on close was set - deleting file.\n",
                 fsp_str_dbg(fsp));
 
-       /*
-        * Don't try to update the write time when we delete the file
-        */
-       fsp->fsp_flags.update_write_time_on_close = false;
-
        if (lck_state.got_tokens &&
            !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
        {
@@ -682,6 +650,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
        return status;
 }
 
+/*
+ * This is now only used for SMB1 closes that send an
+ * explicit write time.
+ */
 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
 {
        DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
@@ -690,33 +662,13 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts)
                return;
        }
        fsp->fsp_flags.write_time_forced = false;
-       fsp->fsp_flags.update_write_time_on_close = true;
        fsp->close_write_time = ts;
 }
 
-static void update_write_time_on_close_share_mode_fn(struct share_mode_lock *lck,
-                                                    void *private_data)
-{
-       struct files_struct *fsp =
-               talloc_get_type_abort(private_data,
-               struct files_struct);
-       NTTIME share_mtime = share_mode_changed_write_time(lck);
-
-       /*
-        * On close if we're changing the real file time we
-        * must update it in the open file db too.
-        */
-       share_mode_set_old_write_time(lck, fsp->close_write_time);
-
-       /*
-        * Close write times overwrite sticky write times
-        * so we must replace any sticky write time here.
-        */
-       if (!null_nttime(share_mtime)) {
-               share_mode_set_changed_write_time(lck, fsp->close_write_time);
-       }
-}
-
+/*
+ * This is now only used for SMB1 closes that send an
+ * explicit write time.
+ */
 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
 {
        struct smb_file_time ft;
@@ -724,12 +676,8 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
 
        init_smb_file_time(&ft);
 
-       if (!(fsp->fsp_flags.update_write_time_on_close)) {
-               return NT_STATUS_OK;
-       }
-
        if (is_omit_timespec(&fsp->close_write_time)) {
-               fsp->close_write_time = timespec_current();
+               return NT_STATUS_OK;
        }
 
        /* Ensure we have a valid stat struct for the source. */
@@ -743,19 +691,8 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
                return NT_STATUS_OK;
        }
 
-       /*
-        * We're being called after close_remove_share_mode() inside
-        * close_normal_file() so it's quite normal to not have an
-        * existing share. So just ignore the result of
-        * share_mode_do_locked_vfs_denied()...
-        */
-       share_mode_do_locked_vfs_denied(fsp->file_id,
-                                       update_write_time_on_close_share_mode_fn,
-                                       fsp);
-
        ft.mtime = fsp->close_write_time;
-       /* As this is a close based update, we are not directly changing the
-          file attributes from a client call, but indirectly from a write. */
+
        status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("update_write_time_on_close: smb_set_file_time "
index f934ae740190b9779fe2f3a29c7e51271aa3becf..31a840bd6581e7a6efe615e8b97465231ca10e0e 100644 (file)
@@ -512,7 +512,6 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
                           const char *mask,
                           uint32_t dirtype,
                           bool dont_descend,
-                          bool ask_sharemode,
                           bool get_dosmode_in,
                           bool (*match_fn)(TALLOC_CTX *ctx,
                                            void *private_data,
@@ -643,7 +642,6 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 
                        mode = dos_mode_msdfs(conn, dname, &smb_fname->st);
                        get_dosmode = false;
-                       ask_sharemode = false;
                        goto done;
                }
 
@@ -651,7 +649,6 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
                        /*
                         * Posix always wants to see symlinks.
                         */
-                       ask_sharemode = false;
                        goto done;
                }
 
@@ -708,19 +705,6 @@ done:
                        continue;
                }
 
-               if (ask_sharemode && !S_ISDIR(smb_fname->st.st_ex_mode)) {
-                       struct timespec write_time_ts;
-                       struct file_id fileid;
-
-                       fileid = vfs_file_id_from_sbuf(conn,
-                                                      &smb_fname->st);
-                       get_file_infos(fileid, 0, NULL, &write_time_ts);
-                       if (!is_omit_timespec(&write_time_ts)) {
-                               update_stat_ex_mtime(&smb_fname->st,
-                                                    write_time_ts);
-                       }
-               }
-
                if (toplevel_dotdot) {
                        /*
                         * Ensure posix fileid and sids are hidden
index 5cfe9e37f136d01dc7ed500bc81dbbe12e5de1e8..753a2c1fb9b78166d70655674439419e1266c423 100644 (file)
@@ -81,7 +81,6 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
                           const char *mask,
                           uint32_t dirtype,
                           bool dont_descend,
-                          bool ask_sharemode,
                           bool get_dosmode,
                           bool (*match_fn)(TALLOC_CTX *ctx,
                                            void *private_data,
index ee80f79889181d8acdf9ab38351c5737a27d97d6..c7ff427d7e3068eefa609785338e3184501cd95c 100644 (file)
@@ -1275,19 +1275,13 @@ done:
  returned on all future write time queries and set on close.
 ******************************************************************/
 
-bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
+void set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
 {
-       bool ok;
-
        if (is_omit_timespec(&mtime)) {
-               return true;
+               return;
        }
 
        fsp->fsp_flags.write_time_forced = true;
-       TALLOC_FREE(fsp->update_write_time_event);
-
-       ok = set_sticky_write_time(fsp->file_id, mtime);
-       return ok;
 }
 
 /******************************************************************
index 91d6de20f5bb7fd577485f3b08a9a1668c343a7a..737ff5dfe2ead2420b72344a9e197aeac21f86fe 100644 (file)
@@ -98,13 +98,7 @@ NTSTATUS vfs_default_durable_cookie(struct files_struct *fsp,
        cookie.base_name = fsp->fsp_name->base_name;
        cookie.initial_allocation_size = fsp->initial_allocation_size;
        cookie.position_information = fh_get_position_information(fsp->fh);
-       cookie.update_write_time_triggered =
-               fsp->fsp_flags.update_write_time_triggered;
-       cookie.update_write_time_on_close =
-               fsp->fsp_flags.update_write_time_on_close;
        cookie.write_time_forced = fsp->fsp_flags.write_time_forced;
-       cookie.close_write_time = full_timespec_to_nt_time(
-               &fsp->close_write_time);
 
        cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev;
        cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino;
@@ -198,37 +192,12 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       /* Ensure any pending write time updates are done. */
-       if (fsp->update_write_time_event) {
-               fsp_flush_write_time_update(fsp);
-       }
-
        /*
         * The above checks are done in mark_share_mode_disconnected() too
         * but we want to avoid getting the lock if possible
         */
        lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
        if (lck != NULL) {
-               struct smb_file_time ft;
-
-               init_smb_file_time(&ft);
-
-               if (fsp->fsp_flags.write_time_forced) {
-                       NTTIME mtime = share_mode_changed_write_time(lck);
-                       ft.mtime = nt_time_to_full_timespec(mtime);
-               } else if (fsp->fsp_flags.update_write_time_on_close) {
-                       if (is_omit_timespec(&fsp->close_write_time)) {
-                               ft.mtime = timespec_current();
-                       } else {
-                               ft.mtime = fsp->close_write_time;
-                       }
-               }
-
-               if (!is_omit_timespec(&ft.mtime)) {
-                       round_timespec(conn->ts_res, &ft.mtime);
-                       file_ntimes(conn, fsp, &ft);
-               }
-
                ok = mark_share_mode_disconnected(lck, fsp);
                if (!ok) {
                        TALLOC_FREE(lck);
@@ -257,13 +226,7 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
        cookie.base_name = fsp_str_dbg(fsp);
        cookie.initial_allocation_size = fsp->initial_allocation_size;
        cookie.position_information = fh_get_position_information(fsp->fh);
-       cookie.update_write_time_triggered =
-               fsp->fsp_flags.update_write_time_triggered;
-       cookie.update_write_time_on_close =
-               fsp->fsp_flags.update_write_time_on_close;
        cookie.write_time_forced = fsp->fsp_flags.write_time_forced;
-       cookie.close_write_time = full_timespec_to_nt_time(
-               &fsp->close_write_time);
 
        cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev;
        cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino;
@@ -762,13 +725,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
 
        fsp->initial_allocation_size = cookie.initial_allocation_size;
        fh_set_position_information(fsp->fh, cookie.position_information);
-       fsp->fsp_flags.update_write_time_triggered =
-               cookie.update_write_time_triggered;
-       fsp->fsp_flags.update_write_time_on_close =
-               cookie.update_write_time_on_close;
        fsp->fsp_flags.write_time_forced = cookie.write_time_forced;
-       fsp->close_write_time = nt_time_to_full_timespec(
-               cookie.close_write_time);
 
        status = fsp_set_smb_fname(fsp, smb_fname);
        if (!NT_STATUS_IS_OK(status)) {
index c043d9724cb872d716cf051f437217ae4e0d7c59..80c621000ff8b784fb0fd636695091f33c9ffcd3 100644 (file)
@@ -118,85 +118,19 @@ static ssize_t real_write_file(struct smb_request *req,
        return ret;
 }
 
-void fsp_flush_write_time_update(struct files_struct *fsp)
-{
-       /*
-        * Note this won't expect any impersonation!
-        * So don't call any SMB_VFS operations here!
-        */
-
-       DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp)));
-
-       trigger_write_time_update_immediate(fsp);
-}
-
-static void update_write_time_handler(struct tevent_context *ctx,
-                                     struct tevent_timer *te,
-                                     struct timeval now,
-                                     void *private_data)
-{
-       files_struct *fsp = (files_struct *)private_data;
-       fsp_flush_write_time_update(fsp);
-}
-
 /*********************************************************
- Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
- in the future.
+ Immediately update write time
 *********************************************************/
 
-void trigger_write_time_update(struct files_struct *fsp)
-{
-       int delay;
-
-       if (fsp->fsp_flags.posix_open) {
-               /* Don't use delayed writes on POSIX files. */
-               return;
-       }
-
-       if (fsp->fsp_flags.write_time_forced) {
-               /* No point - "sticky" write times
-                * in effect.
-                */
-               return;
-       }
-
-       /* We need to remember someone did a write
-        * and update to current time on close. */
-
-       fsp->fsp_flags.update_write_time_on_close = true;
-
-       if (fsp->fsp_flags.update_write_time_triggered) {
-               /*
-                * We only update the write time after 2 seconds
-                * on the first normal write. After that
-                * no other writes affect this until close.
-                */
-               return;
-       }
-       fsp->fsp_flags.update_write_time_triggered = true;
-
-       delay = lp_parm_int(SNUM(fsp->conn),
-                           "smbd", "writetimeupdatedelay",
-                           WRITE_TIME_UPDATE_USEC_DELAY);
-
-       DEBUG(5, ("Update write time %d usec later on %s\n",
-                 delay, fsp_str_dbg(fsp)));
-
-       /* trigger the update 2 seconds later */
-       fsp->update_write_time_event =
-               tevent_add_timer(fsp->conn->sconn->ev_ctx, NULL,
-                                timeval_current_ofs_usec(delay),
-                                update_write_time_handler, fsp);
-}
-
-void trigger_write_time_update_immediate(struct files_struct *fsp)
+void trigger_write_time_update_immediate(struct files_struct *fsp,
+                                        bool update_mtime,
+                                        bool update_ctime)
 {
        struct smb_file_time ft;
 
        init_smb_file_time(&ft);
 
        if (fsp->fsp_flags.posix_open) {
-               /* Don't use delayed writes on POSIX files. */
                return;
        }
 
@@ -208,34 +142,101 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
                 return;
         }
 
-       TALLOC_FREE(fsp->update_write_time_event);
        DEBUG(5, ("Update write time immediate on %s\n",
                  fsp_str_dbg(fsp)));
 
-       /* After an immediate update, reset the trigger. */
-       fsp->fsp_flags.update_write_time_triggered = true;
-        fsp->fsp_flags.update_write_time_on_close = false;
-
-       ft.mtime = timespec_current();
-
-       /* Update the time in the open file db. */
-       (void)set_write_time(fsp->file_id, ft.mtime);
+       if (update_mtime) {
+               /*
+                * Changing mtime would also update ctime and so implicitly
+                * handle the update_ctime=true case.
+                */
+               ft.mtime = timespec_current();
+       } else if (update_ctime && !update_mtime) {
+               /*
+                * The only way to update ctime is by changing *something* in
+                * the inode, atime being the only file metadata I could come up
+                * with we can fiddle with to achieve this.
+                */
+               ft.atime.tv_nsec = UTIME_NOW;
+       }
 
        /* Now set on disk - takes care of notify. */
        (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
 }
 
-void mark_file_modified(files_struct *fsp)
+/*
+ * If this is a sticky-write time handle, refresh the current mtime
+ * so we can restore it after a modification.
+ */
+void prepare_file_modified(files_struct *fsp,
+                          struct file_modified_state *state)
+{
+       int ret;
+
+       if (!fsp->fsp_flags.write_time_forced) {
+               return;
+       }
+
+       ZERO_STRUCTP(state);
+
+       ret = SMB_VFS_FSTAT(fsp, &state->st);
+       if (ret != 0) {
+               DBG_ERR("Prepare [%s] failed: %s\n",
+                       fsp_str_dbg(fsp), strerror(errno));
+               return;
+       }
+
+       state->valid = true;
+       return;
+}
+
+void mark_file_modified(files_struct *fsp,
+                       bool modified,
+                       struct file_modified_state *modified_state)
 {
        int dosmode;
+       NTSTATUS status;
+
+       if (fsp->fsp_flags.write_time_forced &&
+           modified_state->valid)
+       {
+               struct smb_file_time ft;
+
+               init_smb_file_time(&ft);
+               ft.mtime = modified_state->st.st_ex_mtime;
 
-       trigger_write_time_update(fsp);
+               /*
+                * Pave over the "cached" stat info mtime in the fsp,
+                * vfs_default checks this and if the existing time matches what
+                * we're trying to set, it skips setting the time. file_ntimes()
+                * will fill the value with what we've set.
+                */
+               fsp->fsp_name->st.st_ex_mtime = (struct timespec){};
+
+               status = smb_set_file_time(fsp->conn,
+                                          fsp,
+                                          fsp->fsp_name,
+                                          &ft,
+                                          false);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DBG_ERR("smb_set_file_time [%s] failed: %s\n",
+                               fsp_str_dbg(fsp), nt_errstr(status));
+               }
+       }
 
        if (fsp->fsp_flags.modified) {
                return;
        }
 
-       fsp->fsp_flags.modified = true;
+       /*
+        * The modified fsp_flag triggers a directory lease breaks when closing
+        * the handle and this must only happen after writing to a
+        * file. Modifying a file by other means that affect the file state
+        * causing directory lease breaks is handled in the corresponding
+        * functions explicitly by calling notify_fname() with
+        * NOTIFY_ACTION_DIRLEASE_BREAK.
+        */
+       fsp->fsp_flags.modified = modified;
 
        if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
              MAP_ARCHIVE(fsp->conn))) {
@@ -260,6 +261,7 @@ ssize_t write_file(struct smb_request *req,
                        off_t pos,
                        size_t n)
 {
+       struct file_modified_state state;
        ssize_t total_written = 0;
 
        if (fsp->print_file) {
@@ -279,21 +281,16 @@ ssize_t write_file(struct smb_request *req,
                return -1;
        }
 
-       mark_file_modified(fsp);
-
-       /*
-        * If this file is level II oplocked then we need
-        * to grab the shared memory lock and inform all
-        * other files with a level II lock that they need
-        * to flush their read caches. We keep the lock over
-        * the shared memory area whilst doing this.
-        */
-
        /* This should actually be improved to span the write. */
        contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
        contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
 
+       prepare_file_modified(fsp, &state);
+
        total_written = real_write_file(req, fsp, data, pos, n);
+       if (total_written != -1) {
+               mark_file_modified(fsp, true, &state);
+       }
        return total_written;
 }
 
index ea8542b6ba4f0d6572fc4eb381cf0015ccea557d..4f344063d49d74c112e324b2749ca1562ab4a747 100644 (file)
@@ -2305,9 +2305,6 @@ void fsp_unbind_smb(struct smb_request *req, files_struct *fsp)
                TALLOC_FREE(fsp->notify);
        }
 
-       /* Ensure this event will never fire. */
-       TALLOC_FREE(fsp->update_write_time_event);
-
        if (fsp->op != NULL) {
                fsp->op->compat = NULL;
        }
index 759f7a5823a903982212c36e18435b384f48d737..7ce107ee9fccfc83d71165892dc20343549459cd 100644 (file)
@@ -124,7 +124,6 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                               files_struct *fsp,
                               struct smb_filename *smb_fname,
                               bool delete_pending,
-                              struct timespec write_time_ts,
                               struct ea_list *ea_list,
                               uint16_t flags2,
                               unsigned int max_data_bytes,
@@ -171,7 +170,6 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                               int info_level,
                               int requires_resume_key,
                               bool dont_descend,
-                              bool ask_sharemode,
                               bool get_dosmode,
                               uint8_t align,
                               bool do_pad,
@@ -834,6 +832,11 @@ void smbd_init_globals(void);
  The buffer we keep around whilst an aio request is in process.
 *****************************************************************************/
 
+struct file_modified_state {
+       bool valid;
+       struct stat_ex st;
+};
+
 struct aio_extra {
        files_struct *fsp;
        struct smb_request *smbreq;
@@ -842,6 +845,7 @@ struct aio_extra {
        size_t nbyte;
        off_t offset;
        bool write_through;
+       struct file_modified_state modified_state;
 };
 
 #define SMBD_TMPNAME_PREFIX ".::TMPNAME:"
index 771734f6203c50f23c1ff34ae6f86379349ad480..a9e68bad468b19d75549b01b89dc1367c1f6ec84 100644 (file)
@@ -414,7 +414,7 @@ NTSTATUS check_parent_access_fsp(struct files_struct *fsp,
                goto out;
        }
 
-       get_file_infos(fsp->file_id, name_hash, &delete_on_close_set, NULL);
+       get_file_infos(fsp->file_id, name_hash, &delete_on_close_set);
        if (delete_on_close_set) {
                status = NT_STATUS_DELETE_PENDING;
                goto out;
@@ -3452,7 +3452,6 @@ struct open_ntcreate_lock_state {
        bool first_open_attempt;
        bool keep_locked;
        NTSTATUS status;
-       struct timespec write_time;
        share_mode_entry_prepare_unlock_fn_t cleanup_fn;
 };
 
@@ -3483,8 +3482,6 @@ static void open_ntcreate_lock_add_entry(struct share_mode_lock *lck,
                return;
        }
 
-       state->write_time = get_share_mode_write_time(lck);
-
        /*
         * keep the g_lock while existing the tdb chainlock,
         * we we're asked to, which mean we'll keep
@@ -3597,7 +3594,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
        uint32_t open_access_mask = access_mask;
        NTSTATUS status;
        SMB_STRUCT_STAT saved_stat = smb_fname->st;
-       struct timespec old_write_time;
        bool setup_poll = false;
        NTSTATUS ulstatus;
 
@@ -4069,8 +4065,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       old_write_time = smb_fname->st.st_ex_mtime;
-
        /*
         * Deal with the race condition where two smbd's detect the
         * file doesn't exist and do the create at the same time. One
@@ -4126,7 +4120,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                                                   fsp->file_id,
                                                   conn->connectpath,
                                                   smb_fname,
-                                                  &old_write_time,
                                                   open_ntcreate_lock_add_entry,
                                                   &lck_state);
        if (!NT_STATUS_IS_OK(status)) {
@@ -4332,15 +4325,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                }
        }
 
-       /*
-        * Deal with other opens having a modified write time.
-        */
-       if (fsp_getinfo_ask_sharemode(fsp) &&
-           !is_omit_timespec(&lck_state.write_time))
-       {
-               update_stat_ex_mtime(&fsp->fsp_name->st, lck_state.write_time);
-       }
-
        status = NT_STATUS_OK;
 
 unlock:
@@ -4884,7 +4868,6 @@ static NTSTATUS open_directory(connection_struct *conn,
        struct open_ntcreate_lock_state lck_state = {};
        bool keep_locked = false;
        NTSTATUS status;
-       struct timespec mtimespec;
        int info = 0;
        uint32_t need_fd_access;
        NTSTATUS ulstatus;
@@ -5102,15 +5085,6 @@ static NTSTATUS open_directory(connection_struct *conn,
                fsp->fsp_flags.posix_open = true;
        }
 
-       /* Don't store old timestamps for directory
-          handles in the internal database. We don't
-          update them in there if new objects
-          are created in the directory. Currently
-          we only update timestamps on file writes.
-          See bug #9870.
-       */
-       mtimespec = make_omit_timespec();
-
        /*
         * Obviously for FILE_LIST_DIRECTORY we need to reopen to get an fd
         * usable for reading a directory. SMB2_FLUSH may be called on
@@ -5209,7 +5183,6 @@ static NTSTATUS open_directory(connection_struct *conn,
                                                   fsp->file_id,
                                                   conn->connectpath,
                                                   smb_dname,
-                                                  &mtimespec,
                                                   open_ntcreate_lock_add_entry,
                                                   &lck_state);
        if (!NT_STATUS_IS_OK(status)) {
@@ -5246,13 +5219,6 @@ static NTSTATUS open_directory(connection_struct *conn,
                }
        }
 
-       /*
-        * Deal with other opens having a modified write time.
-        */
-       if (!is_omit_timespec(&lck_state.write_time)) {
-               update_stat_ex_mtime(&fsp->fsp_name->st, lck_state.write_time);
-       }
-
        if (pinfo) {
                *pinfo = info;
        }
index ad70e4161ae176bb173ea811cda5ac94b9c5befd..2bb4d6006f8793186b9a5b9ae0cbf94a33b47634 100644 (file)
@@ -220,7 +220,7 @@ NTSTATUS file_set_sparse(connection_struct *conn,
 int file_ntimes(connection_struct *conn,
                files_struct *fsp,
                struct smb_file_time *ft);
-bool set_sticky_write_time_fsp(struct files_struct *fsp,
+void set_sticky_write_time_fsp(struct files_struct *fsp,
                               struct timespec mtime);
 
 NTSTATUS fget_ea_dos_attribute(struct files_struct *fsp,
@@ -270,10 +270,15 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, uint32_t dosmode);
 /* The following definitions come from smbd/fileio.c  */
 
 ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n);
-void fsp_flush_write_time_update(struct files_struct *fsp);
-void trigger_write_time_update(struct files_struct *fsp);
-void trigger_write_time_update_immediate(struct files_struct *fsp);
-void mark_file_modified(files_struct *fsp);
+void trigger_write_time_update_immediate(struct files_struct *fsp,
+                                        bool update_mtime,
+                                        bool update_ctime);
+struct file_modified_state;
+void prepare_file_modified(files_struct *fsp,
+                          struct file_modified_state *state);
+void mark_file_modified(files_struct *fsp,
+                       bool modified,
+                       struct file_modified_state *state);
 ssize_t write_file(struct smb_request *req,
                        files_struct *fsp,
                        const char *data,
index a242c4112aad4c30a3e9cfcc2a8e968f79734528..94f88d5710b04b8169b2521e4294e92dab58bb49 100644 (file)
@@ -259,6 +259,7 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
 
        aio_ex->nbyte = numtowrite;
        aio_ex->offset = startpos;
+       prepare_file_modified(fsp, &aio_ex->modified_state);
 
        req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
                                data, numtowrite, startpos,
@@ -335,7 +336,7 @@ static void aio_pwrite_smb1_done(struct tevent_req *req)
                return;
        }
 
-       mark_file_modified(fsp);
+       mark_file_modified(fsp, true, &aio_ex->modified_state);
 
        if (fsp->fsp_flags.aio_write_behind) {
 
index bcfdf96c633071f58d667cb486c2cb41391de0f3..bba77119c16acdfd57ec4a9084617472874e387f 100644 (file)
@@ -803,7 +803,6 @@ void reply_getatr(struct smb_request *req)
                struct files_struct *dirfsp = NULL;
                uint32_t ucf_flags = ucf_flags_from_smb_request(req);
                NTTIME twrp = 0;
-               bool ask_sharemode;
 
                if (ucf_flags & UCF_GMT_PATHNAME) {
                        extract_snapshot_token(fname, &twrp);
@@ -839,19 +838,6 @@ void reply_getatr(struct smb_request *req)
                mode = fdos_mode(smb_fname->fsp);
                size = smb_fname->st.st_ex_size;
 
-               ask_sharemode = fsp_search_ask_sharemode(smb_fname->fsp);
-               if (ask_sharemode) {
-                       struct timespec write_time_ts;
-                       struct file_id fileid;
-
-                       ZERO_STRUCT(write_time_ts);
-                       fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-                       get_file_infos(fileid, 0, NULL, &write_time_ts);
-                       if (!is_omit_timespec(&write_time_ts)) {
-                               update_stat_ex_mtime(&smb_fname->st, write_time_ts);
-                       }
-               }
-
                mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
                if (mode & FILE_ATTRIBUTE_DIRECTORY) {
                        size = 0;
@@ -1227,8 +1213,7 @@ static bool get_dir_entry(TALLOC_CTX *ctx,
                          off_t *_size,
                          uint32_t *_mode,
                          struct timespec *_date,
-                         bool check_descend,
-                         bool ask_sharemode)
+                         bool check_descend)
 {
        char *fname = NULL;
        struct smb_filename *smb_fname = NULL;
@@ -1241,7 +1226,6 @@ again:
                                   mask,
                                   dirtype,
                                   check_descend,
-                                  ask_sharemode,
                                   true,
                                   smbd_dirptr_8_3_match_fn,
                                   conn,
@@ -1491,8 +1475,7 @@ void reply_search(struct smb_request *req)
                                        &size,
                                        &mode,
                                        &date,
-                                       check_descend,
-                                       false);
+                                       check_descend);
                                TALLOC_FREE(fname);
                                if (!ok) {
                                        goto SearchEmpty;
@@ -1542,7 +1525,6 @@ void reply_search(struct smb_request *req)
                unsigned int i;
                size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
                size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
-               bool ask_sharemode;
 
                maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
 
@@ -1552,8 +1534,6 @@ void reply_search(struct smb_request *req)
                        check_descend = True;
                }
 
-               ask_sharemode = fsp_search_ask_sharemode(fsp);
-
                for (i=numentries;(i<maxentries) && !finished;i++) {
                        finished = !get_dir_entry(ctx,
                                                  conn,
@@ -1564,8 +1544,7 @@ void reply_search(struct smb_request *req)
                                                  &size,
                                                  &mode,
                                                  &date,
-                                                 check_descend,
-                                                 ask_sharemode);
+                                                 check_descend);
                        if (!finished) {
                                char buf[DIR_STRUCT_SIZE];
                                memcpy(buf,status,21);
@@ -4342,9 +4321,12 @@ void reply_write(struct smb_request *req)
         */
 
        if(numtowrite == 0) {
+               struct file_modified_state state;
+
                /*
                 * This is actually an allocate call, and set EOF. JRA.
                 */
+               prepare_file_modified(fsp, &state);
                nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
                if (nwritten < 0) {
                        reply_nterror(req, NT_STATUS_DISK_FULL);
@@ -4355,7 +4337,7 @@ void reply_write(struct smb_request *req)
                        reply_nterror(req, NT_STATUS_DISK_FULL);
                        goto out;
                }
-               trigger_write_time_update_immediate(fsp);
+               mark_file_modified(fsp, true, &state);
        } else {
                nwritten = write_file(req,fsp,data,startpos,numtowrite);
        }
@@ -4781,10 +4763,6 @@ static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
        }
        sync_file(conn, fsp, True /* write through */);
 
-       if (fsp->fsp_flags.modified) {
-               trigger_write_time_update_immediate(fsp);
-       }
-
        return NULL;
 }
 
@@ -4823,9 +4801,6 @@ void reply_flush(struct smb_request *req)
                        END_PROFILE(SMBflush);
                        return;
                }
-               if (fsp->fsp_flags.modified) {
-                       trigger_write_time_update_immediate(fsp);
-               }
        }
 
        reply_smb1_outbuf(req, 0, 0);
@@ -6977,10 +6952,6 @@ void reply_setattrE(struct smb_request *req)
                goto out;
        }
 
-       if (fsp->fsp_flags.modified) {
-               trigger_write_time_update_immediate(fsp);
-       }
-
        DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
               " createtime=%u\n",
                fsp_fnum_dbg(fsp),
index 8301e7f60a93e2280bd39062eb3cd1996c7425bc..2e8362a82e953ac7aa54d19229355eeb4e24ee6e 100644 (file)
@@ -777,7 +777,6 @@ static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                int info_level,
                                bool requires_resume_key,
                                bool dont_descend,
-                               bool ask_sharemode,
                                char **ppdata,
                                char *base_data,
                                char *end_data,
@@ -795,7 +794,7 @@ static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
 
        return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
                                         path_mask, dirtype, info_level,
-                                        requires_resume_key, dont_descend, ask_sharemode,
+                                        requires_resume_key, dont_descend,
                                         true, align, do_pad,
                                         ppdata, base_data, end_data,
                                         space_remaining,
@@ -842,7 +841,6 @@ static void call_trans2findfirst(connection_struct *conn,
        int space_remaining;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
-       bool ask_sharemode;
        struct smbXsrv_connection *xconn = req->xconn;
        struct smbd_server_connection *sconn = req->sconn;
        uint32_t ucf_flags = ucf_flags_from_smb_request(req);
@@ -1107,8 +1105,6 @@ static void call_trans2findfirst(connection_struct *conn,
        space_remaining = max_data_bytes;
        out_of_space = False;
 
-       ask_sharemode = fsp_search_ask_sharemode(fsp);
-
        for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
 
                ntstatus = get_lanman2_dir_entry(talloc_tos(),
@@ -1120,7 +1116,6 @@ static void call_trans2findfirst(connection_struct *conn,
                                                 info_level,
                                                 requires_resume_key,
                                                 dont_descend,
-                                                ask_sharemode,
                                                 &p,
                                                 pdata,
                                                 data_end,
@@ -1286,7 +1281,6 @@ static void call_trans2findnext(connection_struct *conn,
        int space_remaining;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
-       bool ask_sharemode;
        TALLOC_CTX *ctx = talloc_tos();
        struct smbd_server_connection *sconn = req->sconn;
        bool backup_priv = false;
@@ -1571,8 +1565,6 @@ static void call_trans2findnext(connection_struct *conn,
                }
        } /* end if resume_name && !continue_bit */
 
-       ask_sharemode = fsp_search_ask_sharemode(fsp);
-
        for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
 
                ntstatus = get_lanman2_dir_entry(ctx,
@@ -1584,7 +1576,6 @@ static void call_trans2findnext(connection_struct *conn,
                                                 info_level,
                                                 requires_resume_key,
                                                 dont_descend,
-                                                ask_sharemode,
                                                 &p,
                                                 pdata,
                                                 data_end,
@@ -2045,7 +2036,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                     struct smb_filename *smb_fname,
                                     struct files_struct *fsp,
                                     bool delete_pending,
-                                    struct timespec write_time_ts,
                                     char **pparams, int total_params,
                                     char **ppdata, int total_data,
                                     unsigned int max_data_bytes)
@@ -2122,7 +2112,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        status = smbd_do_qfilepathinfo(conn, req, req, info_level,
                                       fsp, smb_fname,
-                                      delete_pending, write_time_ts,
+                                      delete_pending,
                                       ea_list,
                                       req->flags2, max_data_bytes,
                                       &fixed_portion,
@@ -2570,7 +2560,6 @@ static void call_trans2qpathinfo(
        struct smb_filename *smb_fname = NULL;
        struct smb_filename *smb_fname_rel = NULL;
        bool delete_pending = False;
-       struct timespec write_time_ts = { .tv_sec = 0, };
        struct files_struct *dirfsp = NULL;
        files_struct *fsp = NULL;
        char *fname = NULL;
@@ -2678,8 +2667,7 @@ static void call_trans2qpathinfo(
 
                get_file_infos(base_fsp->file_id,
                               base_fsp->name_hash,
-                              &delete_pending,
-                              NULL);
+                              &delete_pending);
                if (delete_pending) {
                        reply_nterror(req, NT_STATUS_DELETE_PENDING);
                        return;
@@ -2689,8 +2677,7 @@ static void call_trans2qpathinfo(
        if (fsp_getinfo_ask_sharemode(fsp)) {
                get_file_infos(fsp->file_id,
                               fsp->name_hash,
-                              &delete_pending,
-                              &write_time_ts);
+                              &delete_pending);
        }
 
        if (delete_pending) {
@@ -2778,7 +2765,6 @@ static void call_trans2qpathinfo(
                smb_fname,
                fsp,
                false,
-               write_time_ts,
                pparams,
                total_params,
                ppdata,
@@ -2874,7 +2860,6 @@ static void call_trans2qfileinfo(
        uint16_t info_level;
        struct smb_filename *smb_fname = NULL;
        bool delete_pending = False;
-       struct timespec write_time_ts = { .tv_sec = 0, };
        files_struct *fsp = NULL;
        struct file_id fileid;
        bool info_level_handled;
@@ -2956,8 +2941,7 @@ static void call_trans2qfileinfo(
                        fileid = vfs_file_id_from_sbuf(
                                conn, &smb_fname->st);
                        get_file_infos(fileid, fsp->name_hash,
-                                      &delete_pending,
-                                      &write_time_ts);
+                                      &delete_pending);
                }
        } else {
                /*
@@ -2974,8 +2958,7 @@ static void call_trans2qfileinfo(
                        fileid = vfs_file_id_from_sbuf(
                                conn, &smb_fname->st);
                        get_file_infos(fileid, fsp->name_hash,
-                                      &delete_pending,
-                                      &write_time_ts);
+                                      &delete_pending);
                }
        }
 
@@ -3028,7 +3011,6 @@ static void call_trans2qfileinfo(
                smb_fname,
                fsp,
                delete_pending,
-               write_time_ts,
                pparams,
                total_params,
                ppdata,
@@ -3932,9 +3914,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
        gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
        NTSTATUS status = NT_STATUS_OK;
-       files_struct *all_fsps = NULL;
        bool modify_mtime = true;
-       struct file_id id;
        SMB_STRUCT_STAT sbuf;
 
        if (!CAN_WRITE(conn)) {
@@ -4115,17 +4095,6 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                return status;
        }
 
-       id = vfs_file_id_from_sbuf(conn, &sbuf);
-       for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
-                       all_fsps = file_find_di_next(all_fsps, true)) {
-               /*
-                * We're setting the time explicitly for UNIX.
-                * Cancel any pending changes over all handles.
-                */
-               all_fsps->fsp_flags.update_write_time_on_close = false;
-               TALLOC_FREE(all_fsps->update_write_time_event);
-       }
-
        /*
         * Override the "setting_write_time"
         * parameter here as it almost does what
index 85e17ab551b9a2f443aa7fa38217fc491a31e374..703de0ecb8d61243ada3e831e660cb602ece0b75 100644 (file)
@@ -526,6 +526,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 
        aio_ex->nbyte = in_data.length;
        aio_ex->offset = in_offset;
+       prepare_file_modified(fsp, &aio_ex->modified_state);
 
        req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
                                in_data.data, in_data.length, in_offset,
@@ -586,7 +587,7 @@ static void aio_pwrite_smb2_done(struct tevent_req *req)
        DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten,
                   (nwritten == -1) ? strerror(err) : "no error"));
 
-       mark_file_modified(fsp);
+       mark_file_modified(fsp, true, &aio_ex->modified_state);
 
         status = smb2_write_complete_nosync(subreq, nwritten, err);
 
index 35f545ae3bdee44c231daabee8b9ac265b07b074..cf75b4bed650eaf67367158a2ef85dd5f3ab7dcf 100644 (file)
@@ -226,8 +226,6 @@ static void smbd_smb2_flush_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
-       struct smbd_smb2_flush_state *state = tevent_req_data(
-               req, struct smbd_smb2_flush_state);
        int ret;
        struct vfs_aio_state vfs_aio_state;
 
@@ -237,9 +235,6 @@ static void smbd_smb2_flush_done(struct tevent_req *subreq)
                tevent_req_nterror(req, map_nt_error_from_unix(vfs_aio_state.error));
                return;
        }
-       if (state->fsp->fsp_flags.modified) {
-               trigger_write_time_update_immediate(state->fsp);
-       }
        tevent_req_done(req);
 }
 
index 7264263a1211f2af8eb925165d9562bcd176eadf..cb8d8073d4ebabc545f91bfc89fdb15866e5c130 100644 (file)
@@ -295,11 +295,9 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
                char *data = NULL;
                unsigned int data_size = 0;
                bool delete_pending = false;
-               struct timespec write_time_ts;
                struct file_id fileid;
                size_t fixed_portion;
 
-               ZERO_STRUCT(write_time_ts);
 
                /*
                 * MS-SMB2 3.3.5.20.1 "Handling SMB2_0_INFO_FILE"
@@ -388,8 +386,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
                                fileid = vfs_file_id_from_sbuf(
                                        conn, &fsp->fsp_name->st);
                                get_file_infos(fileid, fsp->name_hash,
-                                              &delete_pending,
-                                              &write_time_ts);
+                                              &delete_pending);
                        }
                } else {
                        /*
@@ -408,8 +405,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
                                fileid = vfs_file_id_from_sbuf(
                                        conn, &fsp->fsp_name->st);
                                get_file_infos(fileid, fsp->name_hash,
-                                              &delete_pending,
-                                              &write_time_ts);
+                                              &delete_pending);
                        }
                }
 
@@ -419,7 +415,6 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
                                               fsp,
                                               fsp->fsp_name,
                                               delete_pending,
-                                              write_time_ts,
                                               NULL,
                                               STR_UNICODE,
                                               in_output_buffer_length,
index 9b1c7b0cbca7c43b864ca4085b114c05649c37eb..ba8b690e1d73a23958868cd0e17e77c8b4bc531d 100644 (file)
@@ -199,15 +199,6 @@ static void smbd_smb2_request_find_done(struct tevent_req *subreq)
        }
 }
 
-static struct tevent_req *fetch_write_time_send(TALLOC_CTX *mem_ctx,
-                                               struct tevent_context *ev,
-                                               connection_struct *conn,
-                                               struct file_id id,
-                                               int info_level,
-                                               char *entry_marshall_buf,
-                                               bool *stop);
-static NTSTATUS fetch_write_time_recv(struct tevent_req *req);
-
 static struct tevent_req *fetch_dos_mode_send(
        TALLOC_CTX *mem_ctx,
        struct tevent_context *ev,
@@ -221,7 +212,6 @@ static NTSTATUS fetch_dos_mode_recv(struct tevent_req *req);
 struct smbd_smb2_query_directory_state {
        struct tevent_context *ev;
        struct smbd_smb2_request *smb2req;
-       uint64_t async_sharemode_count;
        uint32_t find_async_delay_usec;
        DATA_BLOB out_output_buffer;
        struct smb_request *smbreq;
@@ -237,9 +227,7 @@ struct smbd_smb2_query_directory_state {
        uint32_t num;
        uint32_t dirtype;
        bool dont_descend;
-       bool ask_sharemode;
        bool async_dosmode;
-       bool async_ask_sharemode;
        int last_entry_off;
        size_t max_async_dosmode_active;
        uint32_t async_dosmode_active;
@@ -247,7 +235,6 @@ struct smbd_smb2_query_directory_state {
 };
 
 static bool smb2_query_directory_next_entry(struct tevent_req *req);
-static void smb2_query_directory_fetch_write_time_done(struct tevent_req *subreq);
 static void smb2_query_directory_dos_mode_done(struct tevent_req *subreq);
 static void smb2_query_directory_waited(struct tevent_req *subreq);
 
@@ -480,16 +467,9 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
         * handling in future.
         */
        if (state->info_level != SMB_FIND_FILE_NAMES_INFO) {
-               state->ask_sharemode = fsp_search_ask_sharemode(fsp);
-
                state->async_dosmode = lp_smbd_async_dosmode(SNUM(conn));
        }
 
-       if (state->ask_sharemode && lp_clustering()) {
-               state->ask_sharemode = false;
-               state->async_ask_sharemode = true;
-       }
-
        if (state->async_dosmode) {
                size_t max_threads;
 
@@ -505,7 +485,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (state->async_dosmode || state->async_ask_sharemode) {
+       if (state->async_dosmode) {
                /*
                 * Should we only set async_internal
                 * if we're not the last request in
@@ -562,7 +542,6 @@ static bool smb2_query_directory_next_entry(struct tevent_req *req)
                                           state->info_level,
                                           false, /* requires_resume_key */
                                           state->dont_descend,
-                                          state->ask_sharemode,
                                           get_dosmode,
                                           8, /* align to 8 bytes */
                                           false, /* no padding */
@@ -599,29 +578,6 @@ static bool smb2_query_directory_next_entry(struct tevent_req *req)
                return true;
        }
 
-       if (state->async_ask_sharemode &&
-           !S_ISDIR(smb_fname->st.st_ex_mode))
-       {
-               struct tevent_req *subreq = NULL;
-               char *buf = state->base_data + state->last_entry_off;
-
-               subreq = fetch_write_time_send(state,
-                                              state->ev,
-                                              state->dirfsp->conn,
-                                              file_id,
-                                              state->info_level,
-                                              buf,
-                                              &stop);
-               if (tevent_req_nomem(subreq, req)) {
-                       return true;
-               }
-               tevent_req_set_callback(
-                       subreq,
-                       smb2_query_directory_fetch_write_time_done,
-                       req);
-               state->async_sharemode_count++;
-       }
-
        if (state->async_dosmode) {
                struct tevent_req *subreq = NULL;
                uint8_t *buf = NULL;
@@ -666,12 +622,6 @@ last_entry_done:
 
        state->done = true;
 
-       if (state->async_sharemode_count > 0) {
-               DBG_DEBUG("Stopping after %"PRIu64" async mtime "
-                         "updates\n", state->async_sharemode_count);
-               return true;
-       }
-
        if (state->async_dosmode_active > 0) {
                return true;
        }
@@ -705,33 +655,6 @@ last_entry_done:
 
 static void smb2_query_directory_check_next_entry(struct tevent_req *req);
 
-static void smb2_query_directory_fetch_write_time_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct smbd_smb2_query_directory_state *state = tevent_req_data(
-               req, struct smbd_smb2_query_directory_state);
-       NTSTATUS status;
-       bool ok;
-
-       /*
-        * Make sure we run as the user again
-        */
-       ok = change_to_user_and_service_by_fsp(state->dirfsp);
-       SMB_ASSERT(ok);
-
-       state->async_sharemode_count--;
-
-       status = fetch_write_time_recv(subreq);
-       TALLOC_FREE(subreq);
-       if (tevent_req_nterror(req, status)) {
-               return;
-       }
-
-       smb2_query_directory_check_next_entry(req);
-       return;
-}
-
 static void smb2_query_directory_dos_mode_done(struct tevent_req *subreq)
 {
        struct tevent_req *req =
@@ -774,9 +697,7 @@ static void smb2_query_directory_check_next_entry(struct tevent_req *req)
                return;
        }
 
-       if (state->async_sharemode_count > 0 ||
-           state->async_dosmode_active > 0)
-       {
+       if (state->async_dosmode_active > 0) {
                return;
        }
 
@@ -836,119 +757,6 @@ static NTSTATUS smbd_smb2_query_directory_recv(struct tevent_req *req,
        return NT_STATUS_OK;
 }
 
-struct fetch_write_time_state {
-       connection_struct *conn;
-       struct file_id id;
-       int info_level;
-       char *entry_marshall_buf;
-};
-
-static void fetch_write_time_done(struct tevent_req *subreq);
-
-static struct tevent_req *fetch_write_time_send(TALLOC_CTX *mem_ctx,
-                                               struct tevent_context *ev,
-                                               connection_struct *conn,
-                                               struct file_id id,
-                                               int info_level,
-                                               char *entry_marshall_buf,
-                                               bool *stop)
-{
-       struct tevent_req *req = NULL;
-       struct fetch_write_time_state *state = NULL;
-       struct tevent_req *subreq = NULL;
-       bool req_queued;
-
-       *stop = false;
-
-       req = tevent_req_create(mem_ctx, &state, struct fetch_write_time_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       *state = (struct fetch_write_time_state) {
-               .conn = conn,
-               .id = id,
-               .info_level = info_level,
-               .entry_marshall_buf = entry_marshall_buf,
-       };
-
-       subreq = fetch_share_mode_send(state, ev, id, &req_queued);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-       tevent_req_set_callback(subreq, fetch_write_time_done, req);
-
-       if (req_queued) {
-               *stop = true;
-       }
-       return req;
-}
-
-static void fetch_write_time_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct fetch_write_time_state *state = tevent_req_data(
-               req, struct fetch_write_time_state);
-       struct timespec write_time;
-       struct share_mode_lock *lck = NULL;
-       NTSTATUS status;
-       size_t off;
-
-       status = fetch_share_mode_recv(subreq, state, &lck);
-       TALLOC_FREE(subreq);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-               tevent_req_done(req);
-               return;
-       }
-       if (tevent_req_nterror(req, status)) {
-               return;
-       }
-
-       write_time = get_share_mode_write_time(lck);
-       TALLOC_FREE(lck);
-
-       if (is_omit_timespec(&write_time)) {
-               tevent_req_done(req);
-               return;
-       }
-
-       switch (state->info_level) {
-       case SMB_FIND_FILE_DIRECTORY_INFO:
-       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
-       case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
-       case SMB_FIND_ID_FULL_DIRECTORY_INFO:
-       case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
-               off = 24;
-               break;
-
-       default:
-               DBG_ERR("Unsupported info_level [%d]\n", state->info_level);
-               tevent_req_nterror(req, NT_STATUS_INVALID_LEVEL);
-               return;
-       }
-
-       put_long_date_full_timespec(state->conn->ts_res,
-                              state->entry_marshall_buf + off,
-                              &write_time);
-
-       tevent_req_done(req);
-       return;
-}
-
-static NTSTATUS fetch_write_time_recv(struct tevent_req *req)
-{
-       NTSTATUS status;
-
-       if (tevent_req_is_nterror(req, &status)) {
-               tevent_req_received(req);
-               return status;
-       }
-
-       tevent_req_received(req);
-       return NT_STATUS_OK;
-}
-
 struct fetch_dos_mode_state {
        struct files_struct *dir_fsp;
        struct smb_filename *smb_fname;
index 80f81ffe777c08264426ca6939a2f38359597601..6d9d0f1cabe866637b11df24a4b7789a91091a89 100644 (file)
@@ -1766,7 +1766,6 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                               int info_level,
                               int requires_resume_key,
                               bool dont_descend,
-                              bool ask_sharemode,
                               bool get_dosmode,
                               uint8_t align,
                               bool do_pad,
@@ -1817,7 +1816,6 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                                   mask,
                                   dirtype,
                                   dont_descend,
-                                  ask_sharemode,
                                   get_dosmode,
                                   smbd_dirptr_lanman2_match_fn,
                                   &state,
@@ -2964,7 +2962,6 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                               files_struct *fsp,
                               struct smb_filename *smb_fname,
                               bool delete_pending,
-                              struct timespec write_time_ts,
                               struct ea_list *ea_list,
                               uint16_t flags2,
                               unsigned int max_data_bytes,
@@ -3046,12 +3043,6 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
        dstart = pdata;
        dend = dstart + data_size - 1;
 
-       if (!is_omit_timespec(&write_time_ts) &&
-           !INFO_LEVEL_IS_UNIX(info_level))
-       {
-               update_stat_ex_mtime(psbuf, write_time_ts);
-       }
-
        create_time_ts = get_create_timespec(conn, fsp, smb_fname);
        mtime_ts = psbuf->st_ex_mtime;
        atime_ts = psbuf->st_ex_atime;
@@ -3978,6 +3969,7 @@ NTSTATUS smb_set_file_size(connection_struct *conn,
                           bool fail_after_createfile)
 {
        NTSTATUS status = NT_STATUS_OK;
+       struct file_modified_state state;
        files_struct *new_fsp = NULL;
 
        if (!VALID_STAT(*psbuf)) {
@@ -3989,13 +3981,11 @@ NTSTATUS smb_set_file_size(connection_struct *conn,
                 get_file_size_stat(psbuf));
 
        if (size == get_file_size_stat(psbuf)) {
-               if (fsp == NULL) {
-                       return NT_STATUS_OK;
-               }
-               if (!fsp->fsp_flags.modified) {
-                       return NT_STATUS_OK;
-               }
-               trigger_write_time_update_immediate(fsp);
+               /*
+                * MS-FSA 2.1.5.15.4 FileEndOfFileInformation tells us not to
+                * update the timestamps, but Windows Server 2022 does it.
+                */
+               trigger_write_time_update_immediate(fsp, true, false);
                return NT_STATUS_OK;
        }
 
@@ -4012,10 +4002,11 @@ NTSTATUS smb_set_file_size(connection_struct *conn,
                        return status;
                }
 
+               prepare_file_modified(fsp, &state);
                if (vfs_set_filelen(fsp, size) == -1) {
                        return map_nt_error_from_unix(errno);
                }
-               trigger_write_time_update_immediate(fsp);
+               mark_file_modified(fsp, false, &state);
                return NT_STATUS_OK;
        }
 
@@ -4051,13 +4042,14 @@ NTSTATUS smb_set_file_size(connection_struct *conn,
                return NT_STATUS_INVALID_LEVEL;
        }
 
+       prepare_file_modified(fsp, &state);
        if (vfs_set_filelen(new_fsp, size) == -1) {
                status = map_nt_error_from_unix(errno);
                close_file_free(req, &new_fsp, NORMAL_CLOSE);
                return status;
        }
+       mark_file_modified(fsp, false, &state);
 
-       trigger_write_time_update_immediate(new_fsp);
        close_file_free(req, &new_fsp, NORMAL_CLOSE);
        return NT_STATUS_OK;
 }
@@ -4885,9 +4877,6 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
                return status;
        }
 
-       if (fsp->fsp_flags.modified) {
-               trigger_write_time_update_immediate(fsp);
-       }
        return NT_STATUS_OK;
 }
 
@@ -4929,9 +4918,6 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                return status;
        }
 
-       if (fsp->fsp_flags.modified) {
-               trigger_write_time_update_immediate(fsp);
-       }
        return NT_STATUS_OK;
 }
 
@@ -4980,18 +4966,13 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 
                /* Only change if needed. */
                if (allocation_size !=
-                   SMB_VFS_GET_ALLOC_SIZE(conn, new_fsp, &new_fsp->fsp_name->st))
+                   SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &fsp->fsp_name->st))
                {
                        if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
                                return map_nt_error_from_unix(errno);
                        }
                }
-               /* But always update the time. */
-               /*
-                * This is equivalent to a write. Ensure it's seen immediately
-                * if there are no pending writes.
-                */
-               trigger_write_time_update_immediate(fsp);
+               trigger_write_time_update_immediate(fsp, false, true);
                return NT_STATUS_OK;
        }
 
@@ -5033,12 +5014,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                }
        }
 
-       /* Changing the allocation size should set the last mod time. */
-       /*
-        * This is equivalent to a write. Ensure it's seen immediately
-        * if there are no pending writes.
-        */
-       trigger_write_time_update_immediate(new_fsp);
+       trigger_write_time_update_immediate(new_fsp, false, true);
        close_file_free(req, &new_fsp, NORMAL_CLOSE);
        return NT_STATUS_OK;
 }