[SCM] Samba Shared Repository - branch v3-devel updated - release-3-2-0pre2-4042-g6f20585

Jeremy Allison jra at samba.org
Sat Sep 6 02:01:58 GMT 2008


The branch, v3-devel has been updated
       via  6f20585419046c4aca1f7d6c863cf79eb6ae53b0 (commit)
      from  0bae1ef3de8fda5e1e2d641b14a408e627396912 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-devel


- Log -----------------------------------------------------------------
commit 6f20585419046c4aca1f7d6c863cf79eb6ae53b0
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Sep 5 19:00:48 2008 -0700

    Write times code update.
    
    Ok, here's the fix for the write times breakage
    with the new tests in S4 smbtorture.
    
    The key is keeping in the share mode struct
    the "old_file_time" as the real write time,
    set by all the write and allocation calls,
    and the "changed_write_time" as the "sticky"
    write time - set by the SET_FILE_TIME calls.
    
    We can set them independently (although I
    kept the optimization of not setting the
    "old_file_time" is a "changed_write_time"
    was already set, as we'll never see it.
    
    This allows us to update the write time
    immediately on the SMBwrite truncate case,
    SET_END_OF_FILE and SET_ALLOCATION_SIZE calls,
    whilst still have the 2 second delay on the
    "normal" SMBwrite, SMBwriteX calls.
    
    I think in a subsequent patch I'd like to
    change the name of these from "old_file_time"
    to "write_time" and "changed_write_time" to
    "sticky_write_time" to make this clearer.
    
    I think I also fixed a bug in Metze's original
    code in that once a write timestamp had been
    set from a "normal" SMBwriteX call the fsp->update_write_time_triggered
    variable was set and then never reset - thus
    meaning the write timestamp would never get
    updated again on subsequent SMBwriteX's.
    
    The new code checks the update_write_time_event
    event instead, and doesn't update is there's
    an event already scheduled.
    
    Metze especially, please check this over for
    your understanding.
    
    Jeremy.

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

Summary of changes:
 source/include/proto.h   |   14 ++++++------
 source/include/smb.h     |    1 -
 source/locking/locking.c |   33 ++++++++++++++++++++++++----
 source/smbd/dosmode.c    |   52 ++++++++++++++++++++++++++++-----------------
 source/smbd/fileio.c     |   47 ++++++++++++++++++++++++++++++++++-------
 source/smbd/reply.c      |    6 +++-
 source/smbd/trans2.c     |   12 ++++++----
 7 files changed, 117 insertions(+), 48 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/include/proto.h b/source/include/proto.h
index 291afac..e94a217 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -5306,8 +5306,8 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok
 void set_delete_on_close_lck(struct share_mode_lock *lck, bool delete_on_close, UNIX_USER_TOKEN *tok);
 bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKEN *tok);
 bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, bool delete_on_close);
-bool set_write_time(struct file_id fileid, struct timespec write_time,
-		    bool overwrite);
+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);
 int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
 				 const char *, void *),
 		      void *private_data);
@@ -9616,11 +9616,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 		     const char *parent_dir,
 		     bool newfile);
 int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2]);
-bool set_write_time_path(connection_struct *conn, const char *fname,
-			 struct file_id fileid, const struct timespec mtime,
-			 bool overwrite);
-bool set_write_time_fsp(struct files_struct *fsp, const struct timespec mtime,
-			bool overwrite);
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+			 struct file_id fileid, const struct timespec mtime);
+bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime);
+bool update_write_time(struct files_struct *fsp);
 
 /* The following definitions come from smbd/error.c  */
 
@@ -9665,6 +9664,7 @@ bool directory_has_default_acl(connection_struct *conn, const char *fname);
 
 ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n);
 void trigger_write_time_update(struct files_struct *fsp);
+void trigger_write_time_update_immediate(struct files_struct *fsp);
 ssize_t write_file(struct smb_request *req,
 			files_struct *fsp,
 			const char *data,
diff --git a/source/include/smb.h b/source/include/smb.h
index c8c4f8c..d450eb5 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -456,7 +456,6 @@ typedef struct files_struct {
 	uint32 access_mask;		/* NTCreateX access bits (FILE_READ_DATA etc.) */
 	uint32 share_access;		/* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */
 
-	bool update_write_time_triggered;
 	struct timed_event *update_write_time_event;
 	bool update_write_time_on_close;
 	struct timespec close_write_time;
diff --git a/source/locking/locking.c b/source/locking/locking.c
index ca61a88..f1f9278 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -1405,22 +1405,21 @@ bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct
 	return True;
 }
 
-bool set_write_time(struct file_id fileid, struct timespec write_time,
-		    bool overwrite)
+bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
 {
 	struct share_mode_lock *lck;
 
-	DEBUG(5,("set_write_time: %s overwrite=%d id=%s\n",
+	DEBUG(5,("set_sticky_write_time: %s id=%s\n",
 		 timestring(debug_ctx(),
 			    convert_timespec_to_time_t(write_time)),
-		 overwrite, file_id_string_tos(&fileid)));
+		 file_id_string_tos(&fileid)));
 
 	lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL);
 	if (lck == NULL) {
 		return False;
 	}
 
-	if (overwrite || null_timespec(lck->changed_write_time)) {
+	if (timespec_compare(&lck->changed_write_time, &write_time) != 0) {
 		lck->modified = True;
 		lck->changed_write_time = write_time;
 	}
@@ -1429,6 +1428,30 @@ bool set_write_time(struct file_id fileid, struct timespec write_time,
 	return True;
 }
 
+bool set_write_time(struct file_id fileid, struct timespec write_time)
+{
+	struct share_mode_lock *lck;
+
+	DEBUG(5,("set_sticky_write_time: %s id=%s\n",
+		 timestring(debug_ctx(),
+			    convert_timespec_to_time_t(write_time)),
+		 file_id_string_tos(&fileid)));
+
+	lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL);
+	if (lck == NULL) {
+		return False;
+	}
+
+	if (timespec_compare(&lck->old_write_time, &write_time) != 0) {
+		lck->modified = True;
+		lck->old_write_time = write_time;
+	}
+
+	TALLOC_FREE(lck);
+	return True;
+}
+
+
 struct forall_state {
 	void (*fn)(const struct share_mode_entry *entry,
 		   const char *sharepath,
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 0ac3873..88c6a51 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -616,39 +616,51 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
 	return ret;
 }
 
-/*******************************************************************
- Change a filetime - possibly allowing DOS semantics.
-*******************************************************************/
+/******************************************************************
+ Force a "sticky" write time on a pathname. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
 
-bool set_write_time_path(connection_struct *conn, const char *fname,
-			 struct file_id fileid, const struct timespec mtime,
-			 bool overwrite)
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+			 struct file_id fileid, const struct timespec mtime)
 {
 	if (null_timespec(mtime)) {
 		return true;
 	}
 
-	if (!set_write_time(fileid, mtime, overwrite)) {
+	if (!set_sticky_write_time(fileid, mtime)) {
 		return false;
 	}
 
-	/* in the overwrite case the caller should trigger the notify */
-	if (!overwrite) {
-		notify_fname(conn, NOTIFY_ACTION_MODIFIED,
-			     FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
-	}
-
 	return true;
 }
 
-bool set_write_time_fsp(struct files_struct *fsp, const struct timespec mtime,
-			bool overwrite)
+/******************************************************************
+ Force a "sticky" write time on an fsp. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
+
+bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
 {
-	if (overwrite) {
-		fsp->write_time_forced = true;
-		TALLOC_FREE(fsp->update_write_time_event);
+	fsp->write_time_forced = true;
+	TALLOC_FREE(fsp->update_write_time_event);
+
+	return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
+			fsp->file_id, mtime);
+}
+
+/******************************************************************
+ Update a write time immediately, without the 2 second delay.
+******************************************************************/
+
+bool update_write_time(struct files_struct *fsp)
+{
+	if (!set_write_time(fsp->file_id, timespec_current())) {
+		return false;
 	}
 
-	return set_write_time_path(fsp->conn, fsp->fsp_name, fsp->file_id,
-				   mtime, overwrite);
+	notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
+			FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
+
+	return true;
 }
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index 64cea7f..63850f2 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -176,28 +176,38 @@ static void update_write_time_handler(struct event_context *ctx,
 				      const struct timeval *now,
 				      void *private_data)
 {
-       files_struct *fsp = (files_struct *)private_data;
+	files_struct *fsp = (files_struct *)private_data;
 
-       /* Remove the timed event handler. */
-       TALLOC_FREE(fsp->update_write_time_event);
-       DEBUG(5, ("Update write time on %s\n", fsp->fsp_name));
+	/* Remove the timed event handler. */
+	TALLOC_FREE(fsp->update_write_time_event);
+	DEBUG(5, ("Update write time on %s\n", fsp->fsp_name));
 
-       /* change the write time if not already changed by someoneelse */
-       set_write_time_fsp(fsp, timespec_current(), false);
+	/* change the write time if not already changed by someone else */
+	update_write_time(fsp);
 }
 
+/*********************************************************
+ Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
+ in the future.
+*********************************************************/
+
 void trigger_write_time_update(struct files_struct *fsp)
 {
 	int delay;
 
 	if (fsp->write_time_forced) {
+		/* No point - "sticky" write times
+		 * in effect.
+		 */
 		return;
 	}
 
-	if (fsp->update_write_time_triggered) {
+	if (fsp->update_write_time_event) {
+		/*
+		 * No point - an event is already scheduled.
+		 */
 		return;
 	}
-	fsp->update_write_time_triggered = true;
 
 	delay = lp_parm_int(SNUM(fsp->conn),
 			    "smbd", "writetimeupdatedelay",
@@ -212,6 +222,27 @@ void trigger_write_time_update(struct files_struct *fsp)
 				update_write_time_handler, fsp);
 }
 
+void trigger_write_time_update_immediate(struct files_struct *fsp)
+{
+        if (fsp->write_time_forced) {
+		/*
+		 * No point - "sticky" write times
+		 * in effect.
+		 */
+                return;
+        }
+
+        if (fsp->update_write_time_event) {
+		/*
+		 * No point - an event is already scheduled.
+		 */
+                return;
+        }
+
+        fsp->update_write_time_on_close = true;
+	update_write_time(fsp);
+}
+
 /****************************************************************************
  Write to a file.
 ****************************************************************************/
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 16f8a5b..6933533 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -3810,9 +3810,11 @@ void reply_write(struct smb_request *req)
 			END_PROFILE(SMBwrite);
 			return;
 		}
-	} else
+		trigger_write_time_update_immediate(fsp);
+	} else {
 		nwritten = write_file(req,fsp,data,startpos,numtowrite);
-  
+	}
+
 	status = sync_file(conn, fsp, False);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(5,("reply_write: sync_file for %s returned %s\n",
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 881b29c..8d839b6 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -4900,11 +4900,11 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
 			  time_to_asc(convert_timespec_to_time_t(ts[1])) ));
 
 		if (fsp != NULL) {
-			set_write_time_fsp(fsp, ts[1], true);
+			set_sticky_write_time_fsp(fsp, ts[1]);
 		} else {
-			set_write_time_path(conn, fname,
+			set_sticky_write_time_path(conn, fname,
 					    vfs_file_id_from_sbuf(conn, psbuf),
-					    ts[1], true);
+					    ts[1]);
 		}
 	}
 
@@ -4988,6 +4988,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
 		if (vfs_set_filelen(fsp, size) == -1) {
 			return map_nt_error_from_unix(errno);
 		}
+		trigger_write_time_update_immediate(fsp);
 		return NT_STATUS_OK;
 	}
 
@@ -5011,6 +5012,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
 		return status;
 	}
 
+	trigger_write_time_update_immediate(new_fsp);
 	close_file(new_fsp,NORMAL_CLOSE);
 	return NT_STATUS_OK;
 }
@@ -5737,7 +5739,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 		 * This is equivalent to a write. Ensure it's seen immediately
 		 * if there are no pending writes.
 		 */
-		trigger_write_time_update(fsp);
+		trigger_write_time_update_immediate(fsp);
 		return NT_STATUS_OK;
 	}
 
@@ -5771,7 +5773,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 	 * This is equivalent to a write. Ensure it's seen immediately
 	 * if there are no pending writes.
 	 */
-	trigger_write_time_update(new_fsp);
+	trigger_write_time_update_immediate(new_fsp);
 
 	close_file(new_fsp,NORMAL_CLOSE);
 	return NT_STATUS_OK;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list