s3 oplocks: Add capabilites flags field to the kernel_oplocks struct
authorTim Prouty <tprouty@samba.org>
Tue, 3 Feb 2009 23:40:23 +0000 (15:40 -0800)
committerTim Prouty <tprouty@samba.org>
Tue, 10 Feb 2009 07:47:45 +0000 (23:47 -0800)
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
source3/include/smb.h
source3/smbd/close.c
source3/smbd/oplock.c

index ceea97bf56c795362eb503ba8de67893a58850a8..f553f7625ece77a7d9cebbeaa05e43373989648e 100644 (file)
@@ -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,
index 557489f211ec27ef40403259e8e69492d4dfbc0d..bef0fd177b3b5cfbad7e0d724e623f74078a0d07 100644 (file)
@@ -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;
 };
 
index 2fb8ec2bb5514e5398034d7daecd4f98fb7a18a7..e484fa8e01153431bdc540a944bff0cda0c8c0ed 100644 (file)
@@ -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];
index 4c84fd41edefb087edd27f76a1955bf280b4c163..a6ec9cfa2dfc514407c1fc016a7a5238ee67be34 100644 (file)
@@ -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];