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,
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;
};
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];
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.
****************************************************************************/
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"));
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;
}
{
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];