diff --git a/source4/cluster/ctdb/opendb_ctdb.c b/source4/cluster/ctdb/opendb_ctdb.c index e84f2364d40..fe48f987601 100644 --- a/source4/cluster/ctdb/opendb_ctdb.c +++ b/source4/cluster/ctdb/opendb_ctdb.c @@ -284,6 +284,7 @@ static NTSTATUS odb_ctdb_open_file(struct odb_lock *lck, uint32_t stream_id, uint32_t share_access, uint32_t access_mask, bool delete_on_close, uint32_t open_disposition, bool break_to_none, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { diff --git a/source4/librpc/idl/opendb.idl b/source4/librpc/idl/opendb.idl index eaa626e89de..e3bc2d0f177 100644 --- a/source4/librpc/idl/opendb.idl +++ b/source4/librpc/idl/opendb.idl @@ -23,6 +23,7 @@ interface opendb /* we need a per-entry delete on close, as well as a per-file one, to cope with strange semantics on open */ boolean8 delete_on_close; + boolean8 allow_level_II_oplock; uint32 oplock_level; } opendb_entry; diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c index 6c1a9c070ae..a7e5458aaf8 100644 --- a/source4/ntvfs/common/opendb.c +++ b/source4/ntvfs/common/opendb.c @@ -98,11 +98,13 @@ _PUBLIC_ NTSTATUS odb_open_file(struct odb_lock *lck, uint32_t stream_id, uint32_t share_access, uint32_t access_mask, bool delete_on_close, uint32_t open_disposition, bool break_to_none, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { return ops->odb_open_file(lck, file_handle, path, stream_id, share_access, access_mask, delete_on_close, open_disposition, - break_to_none, oplock_level, oplock_granted); + break_to_none, allow_level_II_oplock, + oplock_level, oplock_granted); } diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h index 69a7f718ba6..1c7f815dea4 100644 --- a/source4/ntvfs/common/opendb.h +++ b/source4/ntvfs/common/opendb.h @@ -30,6 +30,7 @@ struct opendb_ops { uint32_t stream_id, uint32_t share_access, uint32_t access_mask, bool delete_on_close, uint32_t open_disposition, bool break_to_none, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted); NTSTATUS (*odb_open_file_pending)(struct odb_lock *lck, void *private); NTSTATUS (*odb_close_file)(struct odb_lock *lck, void *file_handle, diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c index 47b35f594c6..0736af3d1ef 100644 --- a/source4/ntvfs/common/opendb_tdb.c +++ b/source4/ntvfs/common/opendb_tdb.c @@ -344,7 +344,8 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb, break request and suspending this call until the break is acknowledged or the file is closed */ - if (break_to_none) { + if (break_to_none || + !file->entries[i].allow_level_II_oplock) { oplock_return = OPLOCK_BREAK_TO_NONE; } odb_oplock_break_send(odb, &file->entries[i], @@ -391,7 +392,8 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb, * send an oplock break to the holder of the * oplock and tell caller to retry later */ - if (break_to_none) { + if (break_to_none || + !file->entries[i].allow_level_II_oplock) { oplock_return = OPLOCK_BREAK_TO_NONE; } odb_oplock_break_send(odb, &file->entries[i], @@ -418,6 +420,7 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, uint32_t stream_id, uint32_t share_access, uint32_t access_mask, bool delete_on_close, uint32_t open_disposition, bool break_to_none, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { struct odb_context *odb = lck->odb; @@ -447,13 +450,14 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, NT_STATUS_NOT_OK_RETURN(status); /* see if it conflicts */ - e.server = odb->ntvfs_ctx->server_id; - e.file_handle = file_handle; - e.stream_id = stream_id; - e.share_access = share_access; - e.access_mask = access_mask; - e.delete_on_close = delete_on_close; - e.oplock_level = OPLOCK_NONE; + e.server = odb->ntvfs_ctx->server_id; + e.file_handle = file_handle; + e.stream_id = stream_id; + e.share_access = share_access; + e.access_mask = access_mask; + e.delete_on_close = delete_on_close; + e.allow_level_II_oplock = allow_level_II_oplock; + e.oplock_level = OPLOCK_NONE; /* possibly grant an exclusive, batch or level2 oplock @@ -466,17 +470,23 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, if (file.num_entries == 0) { e.oplock_level = OPLOCK_EXCLUSIVE; *oplock_granted = EXCLUSIVE_OPLOCK_RETURN; - } else { + } else if (allow_level_II_oplock) { e.oplock_level = OPLOCK_LEVEL_II; *oplock_granted = LEVEL_II_OPLOCK_RETURN; + } else { + e.oplock_level = OPLOCK_NONE; + *oplock_granted = NO_OPLOCK_RETURN; } } else if (oplock_level == OPLOCK_BATCH) { if (file.num_entries == 0) { e.oplock_level = OPLOCK_BATCH; *oplock_granted = BATCH_OPLOCK_RETURN; - } else { + } else if (allow_level_II_oplock) { e.oplock_level = OPLOCK_LEVEL_II; *oplock_granted = LEVEL_II_OPLOCK_RETURN; + } else { + e.oplock_level = OPLOCK_NONE; + *oplock_granted = NO_OPLOCK_RETURN; } } else if (oplock_level == OPLOCK_LEVEL_II) { e.oplock_level = OPLOCK_LEVEL_II;