summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/include/smb.h17
-rw-r--r--source3/smbd/close.c4
-rw-r--r--source3/smbd/oplock.c30
4 files changed, 50 insertions, 2 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index ceea97bf56..f553f7625e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6898,6 +6898,7 @@ bool set_file_oplock(files_struct *fsp, int oplock_type);
void release_file_oplock(files_struct *fsp);
bool remove_oplock(files_struct *fsp);
bool downgrade_oplock(files_struct *fsp);
+bool should_notify_deferred_opens(void);
void reply_to_oplock_break_requests(files_struct *fsp);
void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,
void *private_data,
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 557489f211..bef0fd177b 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1689,9 +1689,26 @@ enum smbd_capability {
LEASE_CAPABILITY
};
+/*
+ * Kernel oplocks capability flags.
+ */
+
+/* Level 2 oplocks are supported natively by kernel oplocks. */
+#define KOPLOCKS_LEVEL2_SUPPORTED 0x1
+
+/* The kernel notifies deferred openers when they can retry the open. */
+#define KOPLOCKS_DEFERRED_OPEN_NOTIFICATION 0x2
+
+/* The kernel notifies smbds when an oplock break times out. */
+#define KOPLOCKS_TIMEOUT_NOTIFICATION 0x4
+
+/* The kernel notifies smbds when an oplock is broken. */
+#define KOPLOCKS_OPLOCK_BROKEN_NOTIFICATION 0x8
+
struct kernel_oplocks_ops;
struct kernel_oplocks {
const struct kernel_oplocks_ops *ops;
+ uint32_t flags;
void *private_data;
};
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 2fb8ec2bb5..e484fa8e01 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -134,6 +134,10 @@ static NTSTATUS close_filestruct(files_struct *fsp)
static void notify_deferred_opens(struct share_mode_lock *lck)
{
int i;
+
+ if (!should_notify_deferred_opens()) {
+ return;
+ }
for (i=0; i<lck->num_share_modes; i++) {
struct share_mode_entry *e = &lck->share_modes[i];
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 4c84fd41ed..a6ec9cfa2d 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -188,6 +188,15 @@ bool downgrade_oplock(files_struct *fsp)
return ret;
}
+/*
+ * Some kernel oplock implementations handle the notification themselves.
+ */
+bool should_notify_deferred_opens()
+{
+ return !(koplocks &&
+ (koplocks->flags & KOPLOCKS_DEFERRED_OPEN_NOTIFICATION));
+}
+
/****************************************************************************
Set up an oplock break message.
****************************************************************************/
@@ -306,6 +315,15 @@ static void oplock_timeout_handler(struct event_context *ctx,
static void add_oplock_timeout_handler(files_struct *fsp)
{
+ /*
+ * If kernel oplocks already notifies smbds when an oplock break times
+ * out, just return.
+ */
+ if (koplocks &&
+ (koplocks->flags & KOPLOCKS_TIMEOUT_NOTIFICATION)) {
+ return;
+ }
+
if (fsp->oplock_timeout != NULL) {
DEBUG(0, ("Logic problem -- have an oplock event hanging "
"around\n"));
@@ -491,8 +509,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
!(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) &&
- !koplocks && /* NOTE: we force levelII off for kernel oplocks -
- * this will change when it is supported */
+ !(koplocks && !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) &&
lp_level2_oplocks(SNUM(fsp->conn))) {
break_to_level2 = True;
}
@@ -613,6 +630,15 @@ void reply_to_oplock_break_requests(files_struct *fsp)
{
int i;
+ /*
+ * If kernel oplocks already notifies smbds when oplocks are
+ * broken/removed, just return.
+ */
+ if (koplocks &&
+ (koplocks->flags & KOPLOCKS_OPLOCK_BROKEN_NOTIFICATION)) {
+ return;
+ }
+
for (i=0; i<fsp->num_pending_break_messages; i++) {
struct share_mode_entry *e = &fsp->pending_break_messages[i];
char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];