Latest leases patchset - getting there !

Stefan (metze) Metzmacher metze at samba.org
Fri Dec 5 06:45:38 MST 2014


Am 05.12.2014 um 09:43 schrieb Stefan (metze) Metzmacher:
> Hi Jeremy,
> 
>> New turbo enhanced version :-).
>>
>> With leases you can have multiple RH
>> lease handles, and if one of them renames
>> the file you must break to a R lease,
>> *and wait for the client response before
>> doing the rename*.
>>
>> This means that I had to make SMB2 setinfo
>> async for the SMB2_FILE_RENAME_INFORMATION_INTERNAL
>> call.
>>
>> Full patch that goes on top of master attached,
>> includes enhanced smb2.lease.v2_rename test
>> that shows the above behavior (we pass it :-).
>>
>> Please review and push (or comment :-).
> 
> Thanks for the patches!
> 
> There're one thing which needs be fixed...
> defer_rename_done needs to call
> change_to_user(req->tcon->compat, req->session->compat->vuid)
> and
> set_current_server(req->tcon->compat, 0, true)
> similar to smbd_smb2_request_check_tcon().

Ok, here's an updated patchset that implements this
and also verifies that we can open with the lease after the 2nd rename.

metze
-------------- next part --------------
From 8805e055acf9b3a7a8129904efbbe784be34efa3 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 4 Dec 2014 10:13:47 -0800
Subject: [PATCH 1/6] s3: leases: Add leases_db_rename() to cope with renaming
 a leased file.

Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/locking/leases_db.c | 22 ++++++++++++++++++++++
 source3/locking/leases_db.h |  6 +++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/source3/locking/leases_db.c b/source3/locking/leases_db.c
index 67c93ff..7e000aa 100644
--- a/source3/locking/leases_db.c
+++ b/source3/locking/leases_db.c
@@ -385,3 +385,25 @@ NTSTATUS leases_db_parse(const struct GUID *client_guid,
 	}
 	return state.status;
 }
+
+NTSTATUS leases_db_rename(const struct GUID *client_guid,
+		       const struct smb2_lease_key *lease_key,
+		       const struct file_id *id,
+		       const char *filename_new,
+		       const char *stream_name_new)
+{
+	NTSTATUS status;
+
+	status = leases_db_del(client_guid,
+				lease_key,
+				id);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return leases_db_add(client_guid,
+				lease_key,
+				id,
+				filename_new,
+				stream_name_new);
+}
diff --git a/source3/locking/leases_db.h b/source3/locking/leases_db.h
index f570356..906a99b 100644
--- a/source3/locking/leases_db.h
+++ b/source3/locking/leases_db.h
@@ -42,5 +42,9 @@ NTSTATUS leases_db_parse(const struct GUID *client_guid,
 					const char *stream_name,
 					void *private_data),
 			 void *private_data);
-
+NTSTATUS leases_db_rename(const struct GUID *client_guid,
+			const struct smb2_lease_key *lease_key,
+			const struct file_id *id,
+			const char *filename_new,
+			const char *stream_name_new);
 #endif /* _LEASES_DB_H_ */
-- 
1.9.1


From 9c2d263593df8e3a1ded4a1ee68ba418f44cac67 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 4 Dec 2014 10:14:23 -0800
Subject: [PATCH 2/6] s3: leases : Cope with renaming leased open files.

Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/locking/locking.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index d144f5c..dd73f68 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -471,7 +471,7 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
 	size_t sn_len;
 	size_t msg_len;
 	char *frm = NULL;
-	int i;
+	uint32_t i;
 	bool strip_two_chars = false;
 	bool has_stream = smb_fname_dst->stream_name != NULL;
 	struct server_id self_pid = messaging_server_id(msg_ctx);
@@ -565,6 +565,29 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
 				   (uint8 *)frm, msg_len);
 	}
 
+	for (i=0; i<d->num_leases; i++) {
+		/* Update the filename in leases_db. */
+		NTSTATUS status;
+		struct share_mode_lease *l;
+
+		l = &d->leases[i];
+
+		status = leases_db_rename(&l->client_guid,
+					&l->lease_key,
+					&id,
+					d->base_name,
+					d->stream_name);
+		if (!NT_STATUS_IS_OK(status)) {
+			/* Any error recovery possible here ? */
+			DEBUG(1,("Failed to rename lease key for "
+				"renamed file %s:%s. %s\n",
+				d->base_name,
+				d->stream_name,
+				nt_errstr(status)));
+			continue;
+		}
+	}
+
 	return True;
 }
 
-- 
1.9.1


From 05666e9652888973638059041a2574e5f394a44f Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 4 Dec 2014 21:13:33 -0800
Subject: [PATCH 3/6] s3: leases: Make aio_add_req_to_fsp() public.

We're going to need this to stop handle closures with
outstanding async SMB2 renames causing a crash.

Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/aio.c   | 2 +-
 source3/smbd/proto.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 56b4cfc..e2306a9 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -115,7 +115,7 @@ static int aio_del_req_from_fsp(struct aio_req_fsp_link *lnk)
 	return 0;
 }
 
-static bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
+bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
 {
 	size_t array_len;
 	struct aio_req_fsp_link *lnk;
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index e40a77b..3798555 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -91,6 +91,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 				DATA_BLOB in_data,
 				bool write_through);
 bool cancel_smb2_aio(struct smb_request *smbreq);
+bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req);
 
 /* The following definitions come from smbd/blocking.c  */
 
-- 
1.9.1


From 82bf28e9257db7076effd87ef48b8ab9de00c1b2 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 4 Dec 2014 21:15:24 -0800
Subject: [PATCH 4/6] s3: leases: send_break_message() public.

We're going to need this to allow async SMB2
setinfo renames to send lease break messages
as well as the open code.

Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/open.c  | 2 +-
 source3/smbd/proto.h | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index c6b67f4..8f19a36 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1244,7 +1244,7 @@ static NTSTATUS open_mode_check(connection_struct *conn,
  * our client.
  */
 
-static NTSTATUS send_break_message(struct messaging_context *msg_ctx,
+NTSTATUS send_break_message(struct messaging_context *msg_ctx,
 				   const struct share_mode_entry *exclusive,
 				   uint16_t break_to)
 {
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 3798555..9980d03 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -616,6 +616,9 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
 				    const char *fname,
 				    SMB_STRUCT_STAT *psbuf);
 bool is_stat_open(uint32 access_mask);
+NTSTATUS send_break_message(struct messaging_context *msg_ctx,
+				const struct share_mode_entry *exclusive,
+				uint16_t break_to);
 struct deferred_open_record;
 bool is_deferred_open_async(const struct deferred_open_record *rec);
 NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
-- 
1.9.1


From 9f134b73b17045436b99ce9d82bc29393a71e395 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 4 Dec 2014 21:19:32 -0800
Subject: [PATCH 5/6] s3: leases: Make SMB2 setinfo
 SMB2_FILE_RENAME_INFORMATION_INTERNAL async.

If there are any RH leases we must break them to read
and must wait for the client response before doing the rename.

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

Signed-off-by: Jeremy Allison <jra at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/smb2_setinfo.c | 218 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 218 insertions(+)

diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index d95bd3d..e6981d1 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -25,6 +25,9 @@
 #include "../libcli/smb/smb_common.h"
 #include "trans2.h"
 #include "../lib/util/tevent_ntstatus.h"
+#include "../librpc/gen_ndr/open_files.h"
+#include "source3/lib/dbwrap/dbwrap_watch.h"
+#include "messages.h"
 
 static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
 						 struct tevent_context *ev,
@@ -156,6 +159,186 @@ static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq)
 	}
 }
 
+struct defer_rename_state {
+	struct tevent_req *req;
+	struct smbd_smb2_request *smb2req;
+	struct tevent_context *ev;
+	struct files_struct *fsp;
+	char *data;
+	int data_size;
+};
+
+static void defer_rename_done(struct tevent_req *subreq);
+
+static struct tevent_req *delay_rename_for_lease_break(struct tevent_req *req,
+				struct smbd_smb2_request *smb2req,
+				struct tevent_context *ev,
+				struct files_struct *fsp,
+				struct share_mode_lock *lck,
+				char *data,
+				int data_size)
+
+{
+	struct tevent_req *subreq;
+	uint32_t i;
+	struct share_mode_data *d = lck->data;
+	struct defer_rename_state *rename_state;
+	bool delay = false;
+	struct timeval timeout;
+
+	if (fsp->oplock_type != LEASE_OPLOCK) {
+		return NULL;
+	}
+
+	for (i=0; i<d->num_share_modes; i++) {
+		struct share_mode_entry *e = &d->share_modes[i];
+		struct share_mode_lease *l = NULL;
+		uint32_t e_lease_type = get_lease_type(d, e);
+		uint32_t break_to;
+
+		if (e->op_type != LEASE_OPLOCK) {
+			continue;
+		}
+
+		l = &d->leases[e->lease_idx];
+
+		if (smb2_lease_equal(fsp_client_guid(fsp),
+				&fsp->lease->lease.lease_key,
+				&l->client_guid,
+				&l->lease_key)) {
+			continue;
+		}
+
+		if (share_mode_stale_pid(d, i)) {
+			continue;
+		}
+
+		if (!(e_lease_type & SMB2_LEASE_HANDLE)) {
+			continue;
+		}
+
+		delay = true;
+		break_to = (e_lease_type & ~SMB2_LEASE_HANDLE);
+
+		send_break_message(fsp->conn->sconn->msg_ctx, e, break_to);
+	}
+
+	if (!delay) {
+		return NULL;
+	}
+
+	/* Setup a watch on this record. */
+	rename_state = talloc_zero(req, struct defer_rename_state);
+	if (rename_state == NULL) {
+		return NULL;
+	}
+
+	rename_state->req = req;
+	rename_state->smb2req = smb2req;
+	rename_state->ev = ev;
+	rename_state->fsp = fsp;
+	rename_state->data = data;
+	rename_state->data_size = data_size;
+
+	subreq = dbwrap_record_watch_send(
+				rename_state,
+				ev,
+				lck->data->record,
+				fsp->conn->sconn->msg_ctx);
+
+	if (subreq == NULL) {
+		exit_server("Could not watch share mode record for rename\n");
+	}
+
+	tevent_req_set_callback(subreq, defer_rename_done, rename_state);
+
+	timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
+	if (!tevent_req_set_endtime(subreq,
+			ev,
+			timeval_sum(&smb2req->request_time, &timeout))) {
+		exit_server("Could not set rename timeout\n");
+	}
+
+	return subreq;
+}
+
+static void defer_rename_done(struct tevent_req *subreq)
+{
+	struct defer_rename_state *state = tevent_req_callback_data(
+		subreq, struct defer_rename_state);
+	NTSTATUS status;
+	struct share_mode_lock *lck;
+	int ret_size = 0;
+	bool ok;
+
+	status = dbwrap_record_watch_recv(subreq, state->req, NULL);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(5, ("dbwrap_record_watch_recv returned %s\n",
+			nt_errstr(status)));
+		tevent_req_nterror(state->req, status);
+		return;
+	}
+
+	/*
+	 * Make sure we run as the user again
+	 */
+	ok = change_to_user(state->smb2req->tcon->compat,
+			    state->smb2req->session->compat->vuid);
+	if (!ok) {
+		tevent_req_nterror(state->req, NT_STATUS_ACCESS_DENIED);
+		return;
+	}
+
+	/* should we pass FLAG_CASELESS_PATHNAMES here? */
+	ok = set_current_service(state->smb2req->tcon->compat, 0, true);
+	if (!ok) {
+		tevent_req_nterror(state->req, NT_STATUS_ACCESS_DENIED);
+		return;
+	}
+
+	/* Do we still need to wait ? */
+	lck = get_existing_share_mode_lock(state->req, state->fsp->file_id);
+	if (lck == NULL) {
+		tevent_req_nterror(state->req, NT_STATUS_UNSUCCESSFUL);
+		return;
+	}
+	subreq = delay_rename_for_lease_break(state->req,
+				state->smb2req,
+				state->ev,
+				state->fsp,
+				lck,
+				state->data,
+				state->data_size);
+	if (subreq) {
+		/* Yep - keep waiting. */
+		TALLOC_FREE(state);
+		TALLOC_FREE(lck);
+		return;
+	}
+
+	/* Do the rename under the lock. */
+	status = smbd_do_setfilepathinfo(state->fsp->conn,
+				state->smb2req->smb1req,
+				state,
+				SMB2_FILE_RENAME_INFORMATION_INTERNAL,
+				state->fsp,
+				state->fsp->fsp_name,
+				&state->data,
+				state->data_size,
+				&ret_size);
+
+	TALLOC_FREE(lck);
+	SAFE_FREE(state->data);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(state->req, status);
+		return;
+	}
+
+	tevent_req_done(state->req);
+}
+
 struct smbd_smb2_setinfo_state {
 	struct smbd_smb2_request *smb2req;
 };
@@ -173,6 +356,7 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
 	struct smbd_smb2_setinfo_state *state = NULL;
 	struct smb_request *smbreq = NULL;
 	connection_struct *conn = smb2req->tcon->compat;
+	struct share_mode_lock *lck = NULL;
 	NTSTATUS status;
 
 	req = tevent_req_create(mem_ctx, &state,
@@ -284,6 +468,39 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
 			memcpy(data, in_input_buffer.data, data_size);
 		}
 
+		if (file_info_level == SMB2_FILE_RENAME_INFORMATION_INTERNAL) {
+			struct tevent_req *subreq;
+
+			lck = get_existing_share_mode_lock(mem_ctx,
+							fsp->file_id);
+			if (lck == NULL) {
+				tevent_req_nterror(req,
+					NT_STATUS_UNSUCCESSFUL);
+				return tevent_req_post(req, ev);
+			}
+
+			subreq = delay_rename_for_lease_break(req,
+							smb2req,
+							ev,
+							fsp,
+							lck,
+							data,
+							data_size);
+			if (subreq) {
+				/* Wait for lease break response. */
+
+				/* Ensure we can't be closed in flight. */
+				if (!aio_add_req_to_fsp(fsp, req)) {
+					TALLOC_FREE(lck);
+					tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+					return tevent_req_post(req, ev);
+				}
+
+				TALLOC_FREE(lck);
+				return req;
+			}
+		}
+
 		status = smbd_do_setfilepathinfo(conn, smbreq, state,
 						 file_info_level,
 						 fsp,
@@ -291,6 +508,7 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
 						 &data,
 						 data_size,
 						 &ret_size);
+		TALLOC_FREE(lck);
 		SAFE_FREE(data);
 		if (!NT_STATUS_IS_OK(status)) {
 			if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
-- 
1.9.1


From 5f7d92cb54585b451420eca73addaeffb99d4939 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 4 Dec 2014 21:29:47 -0800
Subject: [PATCH 6/6] s4: torture: leases. Simple lease_v2 rename test
 "v2_rename".

Proves that renaming files can break handle leases.

With the previous patches we now pass this.

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

Signed-off-by: Jeremy Allison <jra at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/torture/smb2/lease.c | 134 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c
index 9d14aeb..c1b6420 100644
--- a/source4/torture/smb2/lease.c
+++ b/source4/torture/smb2/lease.c
@@ -3483,6 +3483,139 @@ static bool test_lease_timeout(struct torture_context *tctx,
 	return ret;
 }
 
+static bool test_lease_v2_rename(struct torture_context *tctx,
+				 struct smb2_tree *tree)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	struct smb2_create io;
+	struct smb2_lease ls1;
+	struct smb2_lease ls2;
+	struct smb2_handle h, h1, h2;
+	union smb_setfileinfo sinfo;
+	const char *fname = "lease_v2_rename_src.dat";
+	const char *fname_dst = "lease_v2_rename_dst.dat";
+	bool ret = true;
+	NTSTATUS status;
+	uint32_t caps;
+	enum protocol_types protocol;
+
+	caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
+	if (!(caps & SMB2_CAP_LEASING)) {
+		torture_skip(tctx, "leases are not supported");
+	}
+
+	protocol = smbXcli_conn_protocol(tree->session->transport->conn);
+	if (protocol < PROTOCOL_SMB3_00) {
+		torture_skip(tctx, "v2 leases are not supported");
+	}
+
+	smb2_util_unlink(tree, fname);
+	smb2_util_unlink(tree, fname_dst);
+
+	tree->session->transport->lease.handler	= torture_lease_handler;
+	tree->session->transport->lease.private_data = tree;
+	tree->session->transport->oplock.handler = torture_oplock_handler;
+	tree->session->transport->oplock.private_data = tree;
+
+	ZERO_STRUCT(break_info);
+
+	ZERO_STRUCT(io);
+	smb2_lease_v2_create_share(&io, &ls1, false, fname,
+				   smb2_util_share_access("RWD"),
+				   LEASE1, NULL,
+				   smb2_util_lease_state("RHW"),
+				   0x4711);
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h = io.out.file.handle;
+	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+	ls1.lease_epoch += 1;
+	CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
+
+	/* Now rename - what happens ? */
+        ZERO_STRUCT(sinfo);
+	sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+	sinfo.rename_information.in.file.handle = h;
+	sinfo.rename_information.in.overwrite = true;
+	sinfo.rename_information.in.new_name = fname_dst;
+	status = smb2_setinfo_file(tree, &sinfo);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* No lease break. */
+	CHECK_NO_BREAK(tctx);
+
+	/* Check we can open another handle on the new name. */
+	smb2_lease_v2_create_share(&io, &ls1, false, fname_dst,
+				   smb2_util_share_access("RWD"),
+				   LEASE1, NULL,
+				   smb2_util_lease_state(""),
+				   ls1.lease_epoch);
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h1 = io.out.file.handle;
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
+	smb2_util_close(tree, h1);
+
+	/* Try another lease key. */
+	smb2_lease_v2_create_share(&io, &ls2, false, fname_dst,
+				   smb2_util_share_access("RWD"),
+				   LEASE2, NULL,
+				   smb2_util_lease_state("RWH"),
+				   0x44);
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h2 = io.out.file.handle;
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	ls2.lease_epoch += 1;
+	CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch );
+	CHECK_BREAK_INFO_V2(tree->session->transport,
+			    "RWH", "RH", LEASE1, ls1.lease_epoch + 1);
+	ls1.lease_epoch += 1;
+	ZERO_STRUCT(break_info);
+
+	/* Now rename back. */
+	ZERO_STRUCT(sinfo);
+	sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+	sinfo.rename_information.in.file.handle = h;
+	sinfo.rename_information.in.overwrite = true;
+	sinfo.rename_information.in.new_name = fname;
+	status = smb2_setinfo_file(tree, &sinfo);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Breaks to R on LEASE2. */
+	CHECK_BREAK_INFO_V2(tree->session->transport,
+			    "RH", "R", LEASE2, ls2.lease_epoch + 1);
+	ls2.lease_epoch += 1;
+
+	/* Check we can open another handle on the current name. */
+	smb2_lease_v2_create_share(&io, &ls1, false, fname,
+				   smb2_util_share_access("RWD"),
+				   LEASE1, NULL,
+				   smb2_util_lease_state(""),
+				   ls1.lease_epoch);
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h1 = io.out.file.handle;
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0, ls1.lease_epoch);
+	smb2_util_close(tree, h1);
+
+done:
+
+	smb2_util_close(tree, h);
+	smb2_util_close(tree, h1);
+	smb2_util_close(tree, h2);
+
+	smb2_util_unlink(tree, fname);
+	smb2_util_unlink(tree, fname_dst);
+
+	smb2_util_unlink(tree, fname);
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+
 static bool test_lease_dynamic_share(struct torture_context *tctx,
 				   struct smb2_tree *tree1a)
 {
@@ -3704,6 +3837,7 @@ struct torture_suite *torture_smb2_lease_init(void)
 	torture_suite_add_1smb2_test(suite, "v2_epoch3", test_lease_v2_epoch3);
 	torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1);
 	torture_suite_add_1smb2_test(suite, "v2_complex2", test_lease_v2_complex2);
+	torture_suite_add_1smb2_test(suite, "v2_rename", test_lease_v2_rename);
 	torture_suite_add_1smb2_test(suite, "dynamic_share", test_lease_dynamic_share);
 	torture_suite_add_1smb2_test(suite, "timeout", test_lease_timeout);
 
-- 
1.9.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20141205/15814eb5/attachment.pgp>


More information about the samba-technical mailing list