summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-11-27 18:34:56 +0100
committerJeremy Allison <jra@samba.org>2014-12-04 05:45:09 +0100
commit6b2f19a5e6e8b3eb2a44cd24408ba4f27cfb8745 (patch)
tree1472e1c6a0959a17f69d13cf162173a33e736265 /source3
parent14fac5dbc05823562760ac424522fb39817ec062 (diff)
s3:open_files.idl: add data structures for SMB2.1 and SMB3.0 leases.
Pair-Programmed-With: Volker Lendecke <vl@samba.org> Signed-off-by: Volker Lendecke <vl@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/librpc/idl/open_files.idl36
-rw-r--r--source3/librpc/wscript_build2
-rw-r--r--source3/locking/locking.c17
-rw-r--r--source3/locking/proto.h5
-rw-r--r--source3/locking/share_mode_lock.c12
-rw-r--r--source3/smbd/open.c10
-rw-r--r--source3/utils/status.c9
8 files changed, 83 insertions, 9 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 53d3edc60f..a6589dbac7 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -577,6 +577,7 @@ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
#define EXCLUSIVE_OPLOCK OPLOCK_EXCLUSIVE
#define BATCH_OPLOCK OPLOCK_BATCH
#define LEVEL_II_OPLOCK OPLOCK_LEVEL_II
+#define LEASE_OPLOCK 0x100
/* The following are Samba-private. */
#define INTERNAL_OPEN_ONLY 0x8
diff --git a/source3/librpc/idl/open_files.idl b/source3/librpc/idl/open_files.idl
index 42783018e2..0a9d5fd105 100644
--- a/source3/librpc/idl/open_files.idl
+++ b/source3/librpc/idl/open_files.idl
@@ -3,6 +3,8 @@
import "server_id.idl";
import "security.idl";
import "file_id.idl";
+import "smb2_lease_struct.idl";
+import "misc.idl";
[
pointer_default(unique)
@@ -10,10 +12,41 @@ import "file_id.idl";
interface open_files
{
+ typedef [public,flag(NDR_PAHEX)] struct {
+ GUID client_guid;
+ smb2_lease_key lease_key;
+ smb2_lease_state current_state;
+ /*
+ * 'breaking' indicates that we're waiting
+ * for a lease break ack from the client
+ * and breaking_to_requested and breaking_to_required
+ * have a meaning.
+ *
+ * breaking_to_requested is the value already sent to
+ * the client, the client needs to ack to this (or less).
+ *
+ * breaking_to_required is the internal value that needs to
+ * be reached before we can reset breaking = false, this
+ * may requires multiple roundtrips to the client, e.g.
+ * when the lease broken to a more reduced value, while
+ * the lease break is still in progress.
+ *
+ * The following can be assumed (if breaking == true):
+ *
+ * current_state > breaking_to_requested >= breaking_to_required
+ */
+ boolean8 breaking;
+ smb2_lease_state breaking_to_requested;
+ smb2_lease_state breaking_to_required;
+ uint16 lease_version;
+ uint16 epoch;
+ } share_mode_lease;
+
typedef [public] struct {
server_id pid;
hyper op_mid;
uint16 op_type;
+ uint32 lease_idx;
uint32 access_mask;
uint32 share_access;
uint32 private_options;
@@ -29,6 +62,7 @@ interface open_files
* to store this share_mode_entry on disk.
*/
[skip] boolean8 stale;
+ [skip] share_mode_lease *lease;
} share_mode_entry;
typedef [public] struct {
@@ -43,6 +77,8 @@ interface open_files
[string,charset(UTF8)] char *stream_name;
uint32 num_share_modes;
[size_is(num_share_modes)] share_mode_entry share_modes[];
+ uint32 num_leases;
+ [size_is(num_leases)] share_mode_lease leases[];
uint32 num_delete_tokens;
[size_is(num_delete_tokens)] delete_token delete_tokens[];
timespec old_write_time;
diff --git a/source3/librpc/wscript_build b/source3/librpc/wscript_build
index 38d9a81a55..5c83cf2e13 100644
--- a/source3/librpc/wscript_build
+++ b/source3/librpc/wscript_build
@@ -17,7 +17,7 @@ bld.SAMBA3_SUBSYSTEM('NDR_MESSAGING',
bld.SAMBA3_SUBSYSTEM('NDR_OPEN_FILES',
source='gen_ndr/ndr_open_files.c',
- public_deps='ndr NDR_SERVER_ID NDR_FILE_ID NDR_SECURITY'
+ public_deps='ndr NDR_SERVER_ID NDR_FILE_ID NDR_SECURITY NDR_SMB2_LEASE_STRUCT'
)
bld.SAMBA3_SUBSYSTEM('NDR_SMBXSRV',
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index a320068e6d..9194dd388e 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -608,6 +608,7 @@ bool is_valid_share_mode_entry(const struct share_mode_entry *e)
num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
+ num_props += (e->op_type == LEASE_OPLOCK);
if ((num_props > 1) && serverid_exists(&e->pid)) {
smb_panic("Invalid share mode entry");
@@ -693,11 +694,21 @@ void remove_stale_share_mode_entries(struct share_mode_data *d)
}
}
-bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
- uid_t uid, uint64_t mid, uint16 op_type)
+bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
+ uid_t uid, uint64_t mid, uint16_t op_type,
+ uint32_t lease_idx)
{
struct share_mode_data *d = lck->data;
struct share_mode_entry *tmp, *e;
+ struct share_mode_lease *lease = NULL;
+
+ if (lease_idx == UINT32_MAX) {
+ lease = NULL;
+ } else if (lease_idx >= d->num_leases) {
+ return false;
+ } else {
+ lease = &d->leases[lease_idx];
+ }
tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
d->num_share_modes+1);
@@ -716,6 +727,8 @@ bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
e->access_mask = fsp->access_mask;
e->op_mid = mid;
e->op_type = op_type;
+ e->lease_idx = lease_idx;
+ e->lease = lease;
e->time.tv_sec = fsp->open_time.tv_sec;
e->time.tv_usec = fsp->open_time.tv_usec;
e->id = fsp->file_id;
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 8eccff8370..6b60330fd8 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -166,8 +166,9 @@ void get_file_infos(struct file_id id,
struct timespec *write_time);
bool is_valid_share_mode_entry(const struct share_mode_entry *e);
bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx);
-bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
- uid_t uid, uint64_t mid, uint16 op_type);
+bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
+ uid_t uid, uint64_t mid, uint16_t op_type,
+ uint32_t lease_idx);
void remove_stale_share_mode_entries(struct share_mode_data *d);
bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp);
bool mark_share_mode_disconnected(struct share_mode_lock *lck,
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 6447c61740..2ae7c3373b 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -154,7 +154,17 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
*/
for (i=0; i<d->num_share_modes; i++) {
- d->share_modes[i].stale = false;
+ struct share_mode_entry *e = &d->share_modes[i];
+
+ e->stale = false;
+ e->lease = NULL;
+ if (e->op_type != LEASE_OPLOCK) {
+ continue;
+ }
+ if (e->lease_idx >= d->num_leases) {
+ continue;
+ }
+ e->lease = &d->leases[e->lease_idx];
}
d->modified = false;
d->fresh = false;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 1952823d37..c14d2ebf59 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1568,7 +1568,8 @@ static NTSTATUS grant_fsp_oplock_type(struct smb_request *req,
ok = set_share_mode(lck, fsp, get_current_uid(fsp->conn),
req ? req->mid : 0,
- fsp->oplock_type);
+ fsp->oplock_type,
+ UINT32_MAX);
if (!ok) {
return NT_STATUS_NO_MEMORY;
}
@@ -3080,6 +3081,7 @@ static NTSTATUS open_directory(connection_struct *conn,
NTSTATUS status;
struct timespec mtimespec;
int info = 0;
+ bool ok;
if (is_ntfs_stream_smb_fname(smb_dname)) {
DEBUG(2, ("open_directory: %s is a stream name!\n",
@@ -3336,8 +3338,10 @@ static NTSTATUS open_directory(connection_struct *conn,
return status;
}
- if (!set_share_mode(lck, fsp, get_current_uid(conn),
- req ? req->mid : 0, NO_OPLOCK)) {
+ ok = set_share_mode(lck, fsp, get_current_uid(conn),
+ req ? req->mid : 0, NO_OPLOCK,
+ UINT32_MAX);
+ if (!ok) {
TALLOC_FREE(lck);
fd_close(fsp);
file_free(req, fsp);
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 4e1dae78e8..cd6a988b2f 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -175,6 +175,15 @@ static int print_share_mode(const struct share_mode_entry *e,
d_printf("BATCH ");
} else if (e->op_type & LEVEL_II_OPLOCK) {
d_printf("LEVEL_II ");
+ } else if (e->op_type == LEASE_OPLOCK) {
+ uint32_t lstate = e->lease->current_state;
+ d_printf("LEASE(%s%s%s)%s%s%s ",
+ (lstate & SMB2_LEASE_READ)?"R":"",
+ (lstate & SMB2_LEASE_WRITE)?"W":"",
+ (lstate & SMB2_LEASE_HANDLE)?"H":"",
+ (lstate & SMB2_LEASE_READ)?"":" ",
+ (lstate & SMB2_LEASE_WRITE)?"":" ",
+ (lstate & SMB2_LEASE_HANDLE)?"":" ");
} else {
d_printf("NONE ");
}