[SCM] Samba Shared Repository - branch v3-2-test updated - release-3-2-0pre2-673-gdf8c100

Stefan Metzmacher metze at samba.org
Mon Apr 7 10:30:29 GMT 2008


The branch, v3-2-test has been updated
       via  df8c100c2b53575a0d425a2daf52e2d59904746a (commit)
       via  404a865a34c3a7c67131b3f99e92c11b2abe3e39 (commit)
       via  4130b873291d39e363184fe4e38dc1f24ebe5056 (commit)
       via  5df34634317633820993c9ef924d694a8fe1c4fe (commit)
       via  2eab212ea2e1bfd8fa716c2c89b2c042f7ba12ea (commit)
       via  6aaa2ce0eeb46f6735ec984a2e7aadde7a7f456d (commit)
      from  8b2d9ee8c54ed84f83fdecf04e656dd66b622abb (commit)

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


- Log -----------------------------------------------------------------
commit df8c100c2b53575a0d425a2daf52e2d59904746a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Apr 7 09:27:22 2008 +0200

    smbd: make it possible to change the write time delay for testing
    
    metze

commit 404a865a34c3a7c67131b3f99e92c11b2abe3e39
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Apr 7 09:21:19 2008 +0200

    smbd: make it possible to disable get_file_infos() on searches
    
    metze

commit 4130b873291d39e363184fe4e38dc1f24ebe5056
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Apr 1 11:40:23 2008 +0200

    locking: combine get_delete_on_close_flag() and get_write_time() into get_file_infos()
    
    This means we need to fetch the record only once.
    
    metze

commit 5df34634317633820993c9ef924d694a8fe1c4fe
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 12 18:26:43 2008 +0100

    selftest: samba3 passes BASE-DELAYWRITE
    
    metze

commit 2eab212ea2e1bfd8fa716c2c89b2c042f7ba12ea
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 12 15:39:38 2008 +0100

    smbd: implement the strange write time update logic
    
    We now never call file_ntimes() directly, every update
    is done via smb_set_file_time().
    
    This let samba3 pass the BASE-DELAYWRITE test.
    
    The write time is only updated 2 seconds after the
    first write() on any open handle to the current time
    (not the time of the first write).
    
    Each handle which had write requests updates the write
    time to the current time on close().
    
    If the write time is set explicit via setfileinfo or setpathinfo
    the write time is visible directly and a following close
    on the same handle doesn't update the write time.
    
    metze

commit 6aaa2ce0eeb46f6735ec984a2e7aadde7a7f456d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 12 15:32:47 2008 +0100

    locking: store the write time in the locking.tdb
    
    This is needed to implement the strange write time update
    logic later. We need to store 2 time timestamps to
    distinguish between the time the file system had before
    the first client opened the file and a forced timestamp update.
    
    metze

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

Summary of changes:
 source/include/local.h               |    3 +
 source/include/smb.h                 |   14 ++++-
 source/locking/locking.c             |  111 ++++++++++++++++++++++++++++------
 source/script/tests/test_posix_s3.sh |    2 +-
 source/smbd/close.c                  |   84 +++++++++++++++++++++++--
 source/smbd/dir.c                    |   14 ++++-
 source/smbd/dosmode.c                |   42 +++++++++----
 source/smbd/fileio.c                 |   66 +++++++++++++-------
 source/smbd/filename.c               |   18 ++++--
 source/smbd/files.c                  |   29 +--------
 source/smbd/nttrans.c                |    2 +-
 source/smbd/open.c                   |   15 +++--
 source/smbd/oplock.c                 |    9 ++-
 source/smbd/reply.c                  |   77 ++++++++++++++++--------
 source/smbd/trans2.c                 |  100 +++++++++++++++++-------------
 15 files changed, 409 insertions(+), 177 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/include/local.h b/source/include/local.h
index 6d32f4f..c125ded 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -233,6 +233,9 @@
 /* Number of microseconds to wait before a sharing violation. */
 #define SHARING_VIOLATION_USEC_WAIT 950000
 
+/* Number of microseconds to wait before a updating the write time (2 secs). */
+#define WRITE_TIME_UPDATE_USEC_DELAY 2000000
+
 #define MAX_LDAP_REPLICATION_SLEEP_TIME 5000 /* In milliseconds. */
 
 /* tdb hash size for the open database. */
diff --git a/source/include/smb.h b/source/include/smb.h
index 4d18dc5..d52d849 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -485,9 +485,13 @@ typedef struct files_struct {
 	struct timeval open_time;
 	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 pending_modtime_owner;
-	struct timespec pending_modtime;
-	struct timespec last_write_time;
+
+	bool update_write_time_triggered;
+	struct timed_event *update_write_time_event;
+	bool update_write_time_on_close;
+	struct timespec close_write_time;
+	bool write_time_forced;
+
 	int oplock_type;
 	int sent_oplock_break;
 	struct timed_event *oplock_timeout;
@@ -811,6 +815,8 @@ struct share_mode_lock {
 	struct share_mode_entry *share_modes;
 	UNIX_USER_TOKEN *delete_token;
 	bool delete_on_close;
+	struct timespec old_write_time;
+	struct timespec changed_write_time;
 	bool fresh;
 	bool modified;
 	struct db_record *record;
@@ -826,6 +832,8 @@ struct locking_data {
 		struct {
 			int num_share_mode_entries;
 			bool delete_on_close;
+			struct timespec old_write_time;
+			struct timespec changed_write_time;
 			uint32 delete_token_size; /* Only valid if either of
 						     the two previous fields
 						     are True. */
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 782e10f..5faebef 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -503,12 +503,20 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
 	data = (struct locking_data *)dbuf.dptr;
 
 	lck->delete_on_close = data->u.s.delete_on_close;
+	lck->old_write_time = data->u.s.old_write_time;
+	lck->changed_write_time = data->u.s.changed_write_time;
 	lck->num_share_modes = data->u.s.num_share_mode_entries;
 
-	DEBUG(10, ("parse_share_modes: delete_on_close: %d, "
-		   "num_share_modes: %d\n",
-		lck->delete_on_close,
-		lck->num_share_modes));
+	DEBUG(10, ("parse_share_modes: delete_on_close: %d, owrt: %s, "
+		   "cwrt: %s, tok: %u, num_share_modes: %d\n",
+		   lck->delete_on_close,
+		   timestring(debug_ctx(),
+			      convert_timespec_to_time_t(lck->old_write_time)),
+		   timestring(debug_ctx(),
+			      convert_timespec_to_time_t(
+				      lck->changed_write_time)),
+		   (unsigned int)data->u.s.delete_token_size,
+		   lck->num_share_modes));
 
 	if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
 		DEBUG(0, ("invalid number of share modes: %d\n",
@@ -659,11 +667,20 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
 	ZERO_STRUCTP(data);
 	data->u.s.num_share_mode_entries = lck->num_share_modes;
 	data->u.s.delete_on_close = lck->delete_on_close;
+	data->u.s.old_write_time = lck->old_write_time;
+	data->u.s.changed_write_time = lck->changed_write_time;
 	data->u.s.delete_token_size = delete_token_size;
-	DEBUG(10, ("unparse_share_modes: del: %d, tok = %u, num: %d\n",
-		data->u.s.delete_on_close,
-		(unsigned int)data->u.s.delete_token_size,
-		data->u.s.num_share_mode_entries));
+
+	DEBUG(10,("unparse_share_modes: del: %d, owrt: %s cwrt: %s, tok: %u, "
+		  "num: %d\n", data->u.s.delete_on_close,
+		  timestring(debug_ctx(),
+			     convert_timespec_to_time_t(lck->old_write_time)),
+		  timestring(debug_ctx(),
+			     convert_timespec_to_time_t(
+				     lck->changed_write_time)),
+		  (unsigned int)data->u.s.delete_token_size,
+		  data->u.s.num_share_mode_entries));
+
 	memcpy(result.dptr + sizeof(*data), lck->share_modes,
 	       sizeof(struct share_mode_entry)*lck->num_share_modes);
 	offset = sizeof(*data) +
@@ -739,7 +756,8 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck,
 				 struct file_id id,
 				 const char *servicepath,
 				 const char *fname,
-				 TDB_DATA share_mode_data)
+				 TDB_DATA share_mode_data,
+				 const struct timespec *old_write_time)
 {
 	/* Ensure we set every field here as the destructor must be
 	   valid even if parse_share_modes fails. */
@@ -751,13 +769,16 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck,
 	lck->share_modes = NULL;
 	lck->delete_token = NULL;
 	lck->delete_on_close = False;
+	ZERO_STRUCT(lck->old_write_time);
+	ZERO_STRUCT(lck->changed_write_time);
 	lck->fresh = False;
 	lck->modified = False;
 
 	lck->fresh = (share_mode_data.dptr == NULL);
 
 	if (lck->fresh) {
-		if (fname == NULL || servicepath == NULL) {
+		if (fname == NULL || servicepath == NULL
+		    || old_write_time == NULL) {
 			return False;
 		}
 		lck->filename = talloc_strdup(lck, fname);
@@ -766,6 +787,7 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck,
 			DEBUG(0, ("talloc failed\n"));
 			return False;
 		}
+		lck->old_write_time = *old_write_time;
 	} else {
 		if (!parse_share_modes(share_mode_data, lck)) {
 			DEBUG(0, ("Could not parse share modes\n"));
@@ -779,7 +801,8 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck,
 struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
 					    const struct file_id id,
 					    const char *servicepath,
-					    const char *fname)
+					    const char *fname,
+					    const struct timespec *old_write_time)
 {
 	struct share_mode_lock *lck;
 	struct file_id tmp;
@@ -797,7 +820,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
 	}
 
 	if (!fill_share_mode_lock(lck, id, servicepath, fname,
-				  lck->record->value)) {
+				  lck->record->value, old_write_time)) {
 		DEBUG(3, ("fill_share_mode_lock failed\n"));
 		TALLOC_FREE(lck);
 		return NULL;
@@ -829,7 +852,7 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	if (!fill_share_mode_lock(lck, id, servicepath, fname, data)) {
+	if (!fill_share_mode_lock(lck, id, servicepath, fname, data, NULL)) {
 		DEBUG(3, ("fill_share_mode_lock failed\n"));
 		TALLOC_FREE(lck);
 		return NULL;
@@ -917,17 +940,40 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
 	return True;
 }
 
-bool get_delete_on_close_flag(struct file_id id)
+void get_file_infos(struct file_id id,
+		    bool *delete_on_close,
+		    struct timespec *write_time)
 {
-	bool result;
 	struct share_mode_lock *lck;
-  
+
+	if (delete_on_close) {
+		*delete_on_close = false;
+	}
+
+	if (write_time) {
+		ZERO_STRUCTP(write_time);
+	}
+
 	if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) {
-		return False;
+		return;
+	}
+
+	if (delete_on_close) {
+		*delete_on_close = lck->delete_on_close;
+	}
+
+	if (write_time) {
+		struct timespec wt;
+
+		wt = lck->changed_write_time;
+		if (null_timespec(wt)) {
+			wt = lck->old_write_time;
+		}
+
+		*write_time = wt;
 	}
-	result = lck->delete_on_close;
+
 	TALLOC_FREE(lck);
-	return result;
 }
 
 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
@@ -1321,7 +1367,8 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKE
 		return True;
 	}
 
-	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+				  NULL);
 	if (lck == NULL) {
 		return False;
 	}
@@ -1361,6 +1408,30 @@ 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)
+{
+	struct share_mode_lock *lck;
+
+	DEBUG(5,("set_write_time: %s overwrite=%d id=%s\n",
+		 timestring(debug_ctx(),
+			    convert_timespec_to_time_t(write_time)),
+		 overwrite, 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)) {
+		lck->modified = True;
+		lck->changed_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/script/tests/test_posix_s3.sh b/source/script/tests/test_posix_s3.sh
index a40a041..c0983ad 100755
--- a/source/script/tests/test_posix_s3.sh
+++ b/source/script/tests/test_posix_s3.sh
@@ -46,7 +46,7 @@ unix="UNIX-INFO2"
 
 tests="$base $raw $rpc $unix"
 
-skipped="BASE-CHARSET BASE-DELAYWRITE BASE-TCONDEV"
+skipped="BASE-CHARSET BASE-TCONDEV"
 skipped="$skipped RAW-ACLS RAW-COMPOSITE RAW-CONTEXT"
 skipped="$skipped RAW-IOCTL"
 skipped="$skipped RAW-QFILEINFO RAW-QFSINFO"
diff --git a/source/smbd/close.c b/source/smbd/close.c
index b06c0d1..3afc037 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -246,7 +246,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 	 * This prevents race conditions with the file being created. JRA.
 	 */
 
-	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+				  NULL);
 
 	if (lck == NULL) {
 		DEBUG(0, ("close_remove_share_mode: Could not get share mode "
@@ -254,6 +255,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	if (fsp->write_time_forced) {
+		set_close_write_time(fsp, lck->changed_write_time);
+	}
+
 	if (!del_share_mode(lck, fsp)) {
 		DEBUG(0, ("close_remove_share_mode: Could not delete share "
 			  "entry for file %s\n", fsp->fsp_name));
@@ -316,6 +321,11 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 	DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
 		 "- deleting file.\n", fsp->fsp_name));
 
+	/*
+	 * Don't try to update the write time when we delete the file
+	 */
+	fsp->update_write_time_on_close = false;
+
 	if (!unix_token_equal(lck->delete_token, &current_user.ut)) {
 		/* Become the user who requested the delete. */
 
@@ -427,6 +437,66 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 	return status;
 }
 
+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))));
+
+	if (null_timespec(ts)) {
+		return;
+	}
+	/*
+	 * if the write time on close is explict set, then don't
+	 * need to fix it up to the value in the locking db
+	 */
+	fsp->write_time_forced = false;
+
+	fsp->update_write_time_on_close = true;
+	fsp->close_write_time = ts;
+}
+
+static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
+{
+	SMB_STRUCT_STAT sbuf;
+	struct timespec ts[2];
+	NTSTATUS status;
+
+	ZERO_STRUCT(sbuf);
+	ZERO_STRUCT(ts);
+
+	if (!fsp->update_write_time_on_close) {
+		return NT_STATUS_OK;
+	}
+
+	if (null_timespec(fsp->close_write_time)) {
+		fsp->close_write_time = timespec_current();
+	}
+
+	/* Ensure we have a valid stat struct for the source. */
+	if (fsp->fh->fd != -1) {
+		if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+			return map_nt_error_from_unix(errno);
+		}
+	} else {
+		if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) {
+			return map_nt_error_from_unix(errno);
+		}
+	}
+
+	if (!VALID_STAT(sbuf)) {
+		/* if it doesn't seem to be a real file */
+		return NT_STATUS_OK;
+	}
+
+	ts[1] = fsp->close_write_time;
+	status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name,
+				   &sbuf, ts, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
 /****************************************************************************
  Close a file.
 
@@ -441,6 +511,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
 	NTSTATUS saved_status1 = NT_STATUS_OK;
 	NTSTATUS saved_status2 = NT_STATUS_OK;
 	NTSTATUS saved_status3 = NT_STATUS_OK;
+	NTSTATUS saved_status4 = NT_STATUS_OK;
 	connection_struct *conn = fsp->conn;
 
 	if (fsp->aio_write_behind) {
@@ -495,11 +566,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
 	 * Ensure pending modtime is set after close.
 	 */
 
-	if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) {
-		set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
-	} else if (!null_timespec(fsp->last_write_time)) {
-		set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
-	}
+	saved_status4 = update_write_time_on_close(fsp);
 
 	if (NT_STATUS_IS_OK(status)) {
 		if (!NT_STATUS_IS_OK(saved_status1)) {
@@ -508,6 +575,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
 			status = saved_status2;
 		} else if (!NT_STATUS_IS_OK(saved_status3)) {
 			status = saved_status3;
+		} else if (!NT_STATUS_IS_OK(saved_status4)) {
+			status = saved_status4;
 		}
 	}
 
@@ -535,7 +604,8 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty
 	 * reference to a directory also.
 	 */
 
-	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+				  NULL);
 
 	if (lck == NULL) {
 		DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index ca6f8bf..6e02401 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -803,7 +803,8 @@ bool get_dir_entry(TALLOC_CTX *ctx,
 		SMB_OFF_T *size,
 		uint32 *mode,
 		time_t *date,
-		bool check_descend)
+		bool check_descend,
+		bool ask_sharemode)
 {
 	const char *dname = NULL;
 	bool found = False;
@@ -883,6 +884,17 @@ bool get_dir_entry(TALLOC_CTX *ctx,
 			*size = sbuf.st_size;
 			*date = sbuf.st_mtime;
 
+			if (ask_sharemode) {
+				struct timespec write_time_ts;
+				struct file_id fileid;
+
+				fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+				get_file_infos(fileid, NULL, &write_time_ts);
+				if (!null_timespec(write_time_ts)) {
+					*date = convert_timespec_to_time_t(write_time_ts);
+				}
+			}
+
 			DEBUG(3,("get_dir_entry mask=[%s] found %s "
 				"fname=%s (%s)\n",
 				mask,
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index a2e617c..0ac3873 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -571,6 +571,11 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
 	errno = 0;
 	ZERO_STRUCT(sbuf);
 
+	DEBUG(6, ("file_ntime: actime: %s",
+		  time_to_asc(convert_timespec_to_time_t(ts[0]))));
+	DEBUG(6, ("file_ntime: modtime: %s",
+		  time_to_asc(convert_timespec_to_time_t(ts[1]))));
+
 	/* Don't update the time on read-only shares */
 	/* We need this as set_filetime (which can be called on
 	   close and other paths) can end up calling this function
@@ -615,26 +620,35 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
  Change a filetime - possibly allowing DOS semantics.
 *******************************************************************/
 
-bool set_filetime(connection_struct *conn, const char *fname,
-		const struct timespec mtime)
+bool set_write_time_path(connection_struct *conn, const char *fname,
+			 struct file_id fileid, const struct timespec mtime,
+			 bool overwrite)
 {
-	struct timespec ts[2];
-
 	if (null_timespec(mtime)) {
-		return(True);
+		return true;
 	}
 
-	ts[1] = mtime; /* mtime. */
-	ts[0] = ts[1]; /* atime. */
-
-	if (file_ntimes(conn, fname, ts)) {
-		DEBUG(4,("set_filetime(%s) failed: %s\n",
-					fname,strerror(errno)));
-		return False;
+	if (!set_write_time(fileid, mtime, overwrite)) {
+		return false;
 	}
 
-	notify_fname(conn, NOTIFY_ACTION_MODIFIED,
-		FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+	/* in the overwrite case the caller should trigger the notify */
+	if (!overwrite) {
+		notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+			     FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+	}
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list