From 17eba16bad9b20518a5d336bc751e749a587ec68 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Tue, 3 Feb 2009 15:40:23 -0800 Subject: s3 oplocks: Add capabilites flags field to the kernel_oplocks struct Here is a short description for each of the new capability flags: KOPLOCKS_LEVEL2_SUPPORTED: Level 2 oplocks are supported natively in the kernel. KOPLOCKS_DEFERRED_OPEN_NOTIFICATION: The kernel notifies deferred openers when they can retry the open. KOPLOCKS_TIMEOUT_NOTIFICATION: The kernel notifies smbds when an oplock break times out. KOPLOCKS_OPLOCK_BROKEN_NOTIFICATION: The kernel notifies smbds when an oplock is broken. --- source3/include/proto.h | 1 + source3/include/smb.h | 17 +++++++++++++++++ source3/smbd/close.c | 4 ++++ source3/smbd/oplock.c | 30 ++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 2 deletions(-) (limited to 'source3') 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; inum_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; inum_pending_break_messages; i++) { struct share_mode_entry *e = &fsp->pending_break_messages[i]; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; -- cgit