[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Fri Sep 7 21:15:03 MDT 2012


The branch, master has been updated
       via  3fef8e2 selftest/Samba3: don't explicitly set 'server max protocol'
       via  196b7f3 docs-xml: change "server max protocol" to "SMB3"
       via  1c9c5c1 s3:param: change "server max protocol" to "SMB3"
       via  9576638 s3:smbd: add basic support for durable handle v2 request and reconnect
       via  267b976 s3:smbd: add basic support for durable handle request and reconnect
       via  f935ebd s3:smbd: initial durable handle support: special treatment of durable handles in close
       via  35260ae s3:vfs: add durable VFS operations
       via  eb1a05f s3:smbd: add disconnected checks to the open code.
       via  42afa59 s3:smbd: also close durable file handles in a tdis
       via  f0a5b79 s3:locking: add brl_mark_disconnected() and brl_reconnect_disconnected()
       via  9a81f8e s3:locking: add mark_share_mode_disconnected()
       via  bc29605 s3:smbXsrv_open: add smb2srv_open_recreate() to support durable handles
       via  5e63494 s3:smbXsrv.idl: add properties for durable handles to smbXsrv_open_global0
      from  c853b68 s3:quota: don't add the string '"' into the argument list

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 3fef8e207c92c7ef9274669cb4cb8b29c2164558
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 18 10:43:18 2012 +0200

    selftest/Samba3: don't explicitly set 'server max protocol'
    
    metze
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Sat Sep  8 05:15:00 CEST 2012 on sn-devel-104

commit 196b7f336e93048c2b55c20a2cdd7c903633d174
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sun Jun 3 23:09:33 2012 +0200

    docs-xml: change "server max protocol" to "SMB3"
    
    metze

commit 1c9c5c12761c2a18e7584fce3f40346321c021f6
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sun Jun 3 23:04:44 2012 +0200

    s3:param: change "server max protocol" to "SMB3"
    
    metze

commit 9576638dbacd24183b8715febf50d8be86aa950a
Author: Michael Adam <obnox at samba.org>
Date:   Fri Jun 15 13:37:26 2012 +0200

    s3:smbd: add basic support for durable handle v2 request and reconnect
    
    This does not yet cover persistent handle support which is also
    negotiated through these create request blobs.
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

commit 267b976d432f3c21cf1d8352183cd4b308fe726d
Author: Michael Adam <obnox at samba.org>
Date:   Fri Jun 8 17:54:19 2012 +0200

    s3:smbd: add basic support for durable handle request and reconnect
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    Pair-Programmed-With: Volker Lendecke <vl at samba.org>

commit f935ebdf7a2fd084930b33ba8d208d699b37300c
Author: Michael Adam <obnox at samba.org>
Date:   Fri Aug 3 16:47:57 2012 +0200

    s3:smbd: initial durable handle support: special treatment of durable handles in close
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

commit 35260ae89e2970712e2a141cd034b513076fc1ed
Author: Michael Adam <obnox at samba.org>
Date:   Tue Sep 4 18:04:11 2012 +0200

    s3:vfs: add durable VFS operations
    
    This allows a VFS module to implement durable handles in different ways.
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

commit eb1a05f783721247e9e01f4039f36c3d69b2dca7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Aug 4 15:30:11 2012 +0200

    s3:smbd: add disconnected checks to the open code.
    
    (delay_for_batch_oplocks, open_mode_check, and delay_for_exclusive_oplocks)
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>

commit 42afa596d5e58875944c5429fac4866a5614ebca
Author: Michael Adam <obnox at samba.org>
Date:   Fri Aug 3 16:38:38 2012 +0200

    s3:smbd: also close durable file handles in a tdis
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

commit f0a5b791ae4e64e42270edad7a961aa046efbaac
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Jun 30 21:48:43 2012 +0200

    s3:locking: add brl_mark_disconnected() and brl_reconnect_disconnected()
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>

commit 9a81f8ee1713317262f3fc773dae38cb51816149
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 3 16:31:32 2012 +0200

    s3:locking: add mark_share_mode_disconnected()
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>

commit bc296053cba15869d3417f6089bd2e7e96d42c09
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 18 12:46:15 2012 +0200

    s3:smbXsrv_open: add smb2srv_open_recreate() to support durable handles
    
    metze

commit 5e63494508ade5da00ad5ab9db139efe03d39c2e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 29 09:34:56 2012 +0200

    s3:smbXsrv.idl: add properties for durable handles to smbXsrv_open_global0
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>
    
    metze

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

Summary of changes:
 docs-xml/smbdotconf/protocol/servermaxprotocol.xml |    2 +-
 selftest/target/Samba3.pm                          |    1 -
 source3/include/vfs.h                              |   35 ++
 source3/include/vfs_macros.h                       |   25 ++
 source3/librpc/idl/smbXsrv.idl                     |    8 +
 source3/locking/brlock.c                           |  125 +++++++
 source3/locking/locking.c                          |   38 ++
 source3/locking/proto.h                            |    4 +
 source3/modules/vfs_default.c                      |   35 ++-
 source3/param/loadparm.c                           |    2 +-
 source3/smbd/close.c                               |   44 +++
 source3/smbd/files.c                               |   11 +-
 source3/smbd/globals.h                             |    6 +
 source3/smbd/open.c                                |   31 ++
 source3/smbd/smb2_create.c                         |  376 +++++++++++++++++---
 source3/smbd/smbXsrv_open.c                        |  205 +++++++++++-
 source3/smbd/vfs.c                                 |   34 ++
 17 files changed, 929 insertions(+), 53 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
index 68f2579..57e82d1 100644
--- a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
@@ -73,6 +73,6 @@
 <related>server min protocol</related>
 <synonym>max protocol</synonym>
 
-<value type="default">SMB2</value>
+<value type="default">SMB3</value>
 <value type="example">LANMAN1</value>
 </samba:parameter>
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index cb11827..943e922 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -901,7 +901,6 @@ sub provision($$$$$$)
 
 #	min receivefile size = 4000
 
-	server max protocol = SMB3
 	read only = no
 	server signing = auto
 
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 45895e7..3e4eefe 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -142,6 +142,7 @@
 /* Leave at 29 - not yet released. move to plain off_t - abartlet */
 /* Leave at 29 - not yet released. Remove sys_acl functions other than set and get - abartlet */
 /* Leave at 29 - not yet released. Added backup_intent bool to files_struct - JRA */
+/* Leave at 29 - not yet released. Add durable handle functions - metze/obnox */
 #define SMB_VFS_INTERFACE_VERSION 29
 
 /*
@@ -712,6 +713,24 @@ struct vfs_fn_pointers {
 			   SMB_STRUCT_STAT *sbuf);
 	int (*set_offline_fn)(struct vfs_handle_struct *handle,
 			   const struct smb_filename *fname);
+
+	/* durable handle operations */
+	NTSTATUS (*durable_cookie_fn)(struct vfs_handle_struct *handle,
+				      struct files_struct *fsp,
+				      TALLOC_CTX *mem_ctx,
+				      DATA_BLOB *cookie);
+	NTSTATUS (*durable_disconnect_fn)(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  const DATA_BLOB old_cookie,
+					  TALLOC_CTX *mem_ctx,
+					  DATA_BLOB *new_cookie);
+	NTSTATUS (*durable_reconnect_fn)(struct vfs_handle_struct *handle,
+					 struct smb_request *smb1req,
+					 struct smbXsrv_open *op,
+					 const DATA_BLOB old_cookie,
+					 TALLOC_CTX *mem_ctx,
+					 struct files_struct **fsp,
+					 DATA_BLOB *new_cookie);
 };
 
 /*
@@ -1108,6 +1127,22 @@ bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle,
 			     SMB_STRUCT_STAT *sbuf);
 int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
 			     const struct smb_filename *fname);
+NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
+				     struct files_struct *fsp,
+				     TALLOC_CTX *mem_ctx,
+				     DATA_BLOB *cookie);
+NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
+					 struct files_struct *fsp,
+					 const DATA_BLOB old_cookie,
+					 TALLOC_CTX *mem_ctx,
+					 DATA_BLOB *new_cookie);
+NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
+					struct smb_request *smb1req,
+					struct smbXsrv_open *op,
+					const DATA_BLOB old_cookie,
+					TALLOC_CTX *mem_ctx,
+					struct files_struct **fsp,
+					DATA_BLOB *new_cookie);
 
 NTSTATUS smb_register_vfs(int version, const char *name,
 			  const struct vfs_fn_pointers *fns);
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index e577e99..f077a6f 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -509,4 +509,29 @@
 #define SMB_VFS_NEXT_SET_OFFLINE(handle,fname) \
 	smb_vfs_call_set_offline((handle)->next, (fname))
 
+/* durable handle operations */
+
+#define SMB_VFS_DURABLE_COOKIE(fsp, mem_ctx, cookie) \
+	smb_vfs_call_durable_cookie((fsp)->conn->vfs_handles, \
+				    (fsp), (mem_ctx), (cookie))
+#define SMB_VFS_NEXT_DURABLE_COOKIE(handle, fsp, mem_ctx, cookie) \
+	smb_vfs_call_durable_cookie(((handle)->next, \
+				    (fsp), (mem_ctx), (cookie))
+
+#define SMB_VFS_DURABLE_DISCONNECT(fsp, old_cookie, mem_ctx, new_cookie) \
+	smb_vfs_call_durable_disconnect((fsp)->conn->vfs_handles, \
+					(fsp), (old_cookie), (mem_ctx), (new_cookie))
+#define SMB_VFS_NEXT_DURABLE_DISCONNECT(handle, fsp, old_cookie, mem_ctx, new_cookie) \
+	smb_vfs_call_durable_disconnect((handle)->next, \
+					(fsp), (old_cookie), (mem_ctx), (new_cookie))
+
+#define SMB_VFS_DURABLE_RECONNECT(conn, smb1req, op, old_cookie, mem_ctx, fsp, new_cookie) \
+	smb_vfs_call_durable_reconnect((conn)->vfs_handles, \
+				       (smb1req), (op), (old_cookie), \
+				       (mem_ctx), (fsp), (new_cookie))
+#define SMB_VFS_NEXT_DURABLE_RECONNECT(handle, smb1req, op, old_cookie, mem_ctx, fsp, new_cookie) \
+	smb_vfs_call_durable_reconnect((handle)->next, \
+					(smb1req), (op), (old_cookie), \
+					(mem_ctx), (fsp), (new_cookie))
+
 #endif /* _VFS_MACROS_H */
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 90572e5..2a6d7b3 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -1,5 +1,6 @@
 #include "idl_types.h"
 
+import "misc.idl";
 import "server_id.idl";
 import "security.idl";
 import "auth.idl";
@@ -267,12 +268,19 @@ interface smbXsrv
 		hyper					open_volatile_id;
 		dom_sid					open_owner;
 		NTTIME					open_time;
+		GUID					create_guid;
+		GUID					client_guid;
+		GUID					app_instance_id;
 		/*
 		 * TODO: for durable/resilient/persistent handles we need more
 		 *       things here. See [MS-SMB2] 3.3.1.10 Per Open
 		 *
 		 * NOTE: this is still version 0, which is not a stable format!
 		 */
+		NTTIME					disconnect_time;
+		uint32					durable_timeout_msec;
+		boolean8				durable;
+		DATA_BLOB				backend_cookie;
 	} smbXsrv_open_global0;
 
 	typedef union {
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index c03e451..b7abaa9 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -1522,6 +1522,131 @@ void brl_close_fnum(struct messaging_context *msg_ctx,
 	}
 }
 
+bool brl_mark_disconnected(struct files_struct *fsp)
+{
+	uint32_t tid = fsp->conn->cnum;
+	uint64_t smblctx = fsp->op->global->open_persistent_id;
+	uint64_t fnum = fsp->fnum;
+	unsigned int i;
+	struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
+	struct byte_range_lock *br_lck = NULL;
+
+	if (!fsp->op->global->durable) {
+		return false;
+	}
+
+	if (fsp->current_lock_count == 0) {
+		return true;
+	}
+
+	br_lck = brl_get_locks(talloc_tos(), fsp);
+	if (br_lck == NULL) {
+		return false;
+	}
+
+	for (i=0; i < br_lck->num_locks; i++) {
+		struct lock_struct *lock = &br_lck->lock_data[i];
+
+		/*
+		 * as this is a durable handle, we only expect locks
+		 * of the current file handle!
+		 */
+
+		if (lock->context.smblctx != smblctx) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		if (lock->context.tid != tid) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		if (!serverid_equal(&lock->context.pid, &self)) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		if (lock->fnum != fnum) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		server_id_set_disconnected(&lock->context.pid);
+		lock->context.tid = TID_FIELD_INVALID;
+		lock->fnum = FNUM_FIELD_INVALID;
+	}
+
+	br_lck->modified = true;
+	TALLOC_FREE(br_lck);
+	return true;
+}
+
+bool brl_reconnect_disconnected(struct files_struct *fsp)
+{
+	uint32_t tid = fsp->conn->cnum;
+	uint64_t smblctx = fsp->op->global->open_persistent_id;
+	uint64_t fnum = fsp->fnum;
+	unsigned int i;
+	struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
+	struct byte_range_lock *br_lck = NULL;
+
+	if (!fsp->op->global->durable) {
+		return false;
+	}
+
+	/* we want to validate ourself */
+	fsp->lockdb_clean = true;
+
+	br_lck = brl_get_locks(talloc_tos(), fsp);
+	if (br_lck == NULL) {
+		return false;
+	}
+
+	if (br_lck->num_locks == 0) {
+		TALLOC_FREE(br_lck);
+		return true;
+	}
+
+	for (i=0; i < br_lck->num_locks; i++) {
+		struct lock_struct *lock = &br_lck->lock_data[i];
+
+		/*
+		 * as this is a durable handle we only expect locks
+		 * of the current file handle!
+		 */
+
+		if (lock->context.smblctx != smblctx) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		if (lock->context.tid != TID_FIELD_INVALID) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		if (!server_id_is_disconnected(&lock->context.pid)) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		if (lock->fnum != FNUM_FIELD_INVALID) {
+			TALLOC_FREE(br_lck);
+			return false;
+		}
+
+		lock->context.pid = self;
+		lock->context.tid = tid;
+		lock->fnum = fnum;
+	}
+
+	fsp->current_lock_count = br_lck->num_locks;
+	br_lck->modified = true;
+	TALLOC_FREE(br_lck);
+	return true;
+}
+
 /****************************************************************************
  Ensure this set of lock entries is valid.
 ****************************************************************************/
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index d3ab7f3..a7fc50c 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -811,6 +811,44 @@ bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
 	return True;
 }
 
+bool mark_share_mode_disconnected(struct share_mode_lock *lck,
+				  struct files_struct *fsp)
+{
+	struct share_mode_entry entry, *e;
+
+	if (lck->data->num_share_modes != 1) {
+		return false;
+	}
+
+	if (fsp->op == NULL) {
+		return false;
+	}
+	if (!fsp->op->global->durable) {
+		return false;
+	}
+
+	/* Don't care about the pid owner being correct here - just a search. */
+	fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
+
+	e = find_share_mode_entry(lck->data, &entry);
+	if (e == NULL) {
+		return false;
+	}
+
+	DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
+
+	server_id_set_disconnected(&e->pid);
+
+	/*
+	 * On reopen the caller needs to check that
+	 * the client comes with the correct handle.
+	 */
+	e->share_file_id = fsp->op->global->open_persistent_id;
+
+	lck->data->modified = true;
+	return true;
+}
+
 void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
 			     struct server_id pid)
 {
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 74cf323..c170c73 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -79,6 +79,8 @@ bool brl_lock_cancel(struct byte_range_lock *br_lck,
 		struct blocking_lock_record *blr);
 bool brl_lock_cancel_default(struct byte_range_lock *br_lck,
 		struct lock_struct *plock);
+bool brl_mark_disconnected(struct files_struct *fsp);
+bool brl_reconnect_disconnected(struct files_struct *fsp);
 void brl_close_fnum(struct messaging_context *msg_ctx,
 		    struct byte_range_lock *br_lck);
 int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
@@ -175,6 +177,8 @@ void add_deferred_open(struct share_mode_lock *lck, uint64_t mid,
 		       struct timeval request_time,
 		       struct server_id pid, struct file_id id);
 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp);
+bool mark_share_mode_disconnected(struct share_mode_lock *lck,
+				  struct files_struct *fsp);
 void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
 			     struct server_id pid);
 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp);
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 42671a1..427e3af 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2227,6 +2227,34 @@ static int vfswrap_set_offline(struct vfs_handle_struct *handle,
 	return -1;
 }
 
+static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
+				       struct files_struct *fsp,
+				       TALLOC_CTX *mem_ctx,
+				       DATA_BLOB *cookie)
+{
+	return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
+					   struct files_struct *fsp,
+					   const DATA_BLOB old_cookie,
+					   TALLOC_CTX *mem_ctx,
+					   DATA_BLOB *new_cookie)
+{
+	return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
+					  struct smb_request *smb1req,
+					  struct smbXsrv_open *op,
+					  const DATA_BLOB old_cookie,
+					  TALLOC_CTX *mem_ctx,
+					  struct files_struct **fsp,
+					  DATA_BLOB *new_cookie)
+{
+	return NT_STATUS_NOT_SUPPORTED;
+}
+
 static struct vfs_fn_pointers vfs_default_fns = {
 	/* Disk operations */
 
@@ -2344,7 +2372,12 @@ static struct vfs_fn_pointers vfs_default_fns = {
 
 	/* offline operations */
 	.is_offline_fn = vfswrap_is_offline,
-	.set_offline_fn = vfswrap_set_offline
+	.set_offline_fn = vfswrap_set_offline,
+
+	/* durable handle operations */
+	.durable_cookie_fn = vfswrap_durable_cookie,
+	.durable_disconnect_fn = vfswrap_durable_disconnect,
+	.durable_reconnect_fn = vfswrap_durable_reconnect,
 };
 
 NTSTATUS vfs_default_init(void);
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 2c77691..5f00932 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -831,7 +831,7 @@ static void init_globals(bool reinit_globals)
 	Globals.max_log_size = 5000;
 	Globals.max_open_files = max_open_files();
 	Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
-	Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
+	Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
 	Globals.srv_minprotocol = PROTOCOL_LANMAN1;
 	Globals.security = SEC_USER;
 	Globals.bEncryptPasswords = true;
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 5143232..8bf481d 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -706,6 +706,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
 	NTSTATUS status = NT_STATUS_OK;
 	NTSTATUS tmp;
 	connection_struct *conn = fsp->conn;
+	bool is_durable = false;
 
 	if (fsp->num_aio_requests != 0) {
 
@@ -752,6 +753,49 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
 	tmp = close_filestruct(fsp);
 	status = ntstatus_keeperror(status, tmp);
 
+	if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
+		is_durable = fsp->op->global->durable;
+	}
+
+	if (close_type != SHUTDOWN_CLOSE) {
+		is_durable = false;
+	}
+
+	if (is_durable) {
+		DATA_BLOB new_cookie = data_blob_null;
+
+		tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
+					fsp->op->global->backend_cookie,
+					fsp->op,
+					&new_cookie);
+		if (NT_STATUS_IS_OK(tmp)) {
+			data_blob_free(&fsp->op->global->backend_cookie);
+			fsp->op->global->backend_cookie = new_cookie;
+
+			tmp = smbXsrv_open_update(fsp->op);
+		}
+		if (!NT_STATUS_IS_OK(tmp)) {
+			is_durable = false;
+		}
+	}
+
+	if (is_durable) {
+		/*
+		 * This is the case where we successfully disconnected
+		 * a durable handle and closed the underlying file.
+		 * In all other cases, we proceed with a genuine close.
+		 */
+		file_free(req, fsp);
+		return NT_STATUS_OK;
+	}
+
+	if (fsp->op != NULL) {
+		/*
+		 * Make sure the handle is not marked as durable anymore
+		 */
+		fsp->op->global->durable = false;
+	}
+
 	if (fsp->print_file) {
 		/* FIXME: return spool errors */
 		print_spool_end(fsp, close_type);
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 0550b31..ef229a4 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -151,9 +151,16 @@ void file_close_conn(connection_struct *conn)
 
 	for (fsp=conn->sconn->files; fsp; fsp=next) {
 		next = fsp->next;
-		if (fsp->conn == conn) {
-			close_file(NULL, fsp, SHUTDOWN_CLOSE);
+		if (fsp->conn != conn) {
+			continue;
+		}
+		if (fsp->op != NULL && fsp->op->global->durable) {
+			/*
+			 * A tree disconnect closes a durable handle


-- 
Samba Shared Repository


More information about the samba-cvs mailing list