diff options
Diffstat (limited to 'source4/ntvfs/common')
-rw-r--r-- | source4/ntvfs/common/opendb.c | 5 | ||||
-rw-r--r-- | source4/ntvfs/common/opendb.h | 1 | ||||
-rw-r--r-- | source4/ntvfs/common/opendb_tdb.c | 40 |
3 files changed, 45 insertions, 1 deletions
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c index 4ac10806e1..3f5d7210be 100644 --- a/source4/ntvfs/common/opendb.c +++ b/source4/ntvfs/common/opendb.c @@ -176,3 +176,8 @@ _PUBLIC_ NTSTATUS odb_update_oplock(struct odb_lock *lck, void *file_handle, { return ops->odb_update_oplock(lck, file_handle, oplock_level); } + +_PUBLIC_ NTSTATUS odb_break_oplocks(struct odb_lock *lck) +{ + return ops->odb_break_oplocks(lck); +} diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h index c34a07d6fa..c46390446c 100644 --- a/source4/ntvfs/common/opendb.h +++ b/source4/ntvfs/common/opendb.h @@ -43,6 +43,7 @@ struct opendb_ops { uint32_t access_mask); NTSTATUS (*odb_update_oplock)(struct odb_lock *lck, void *file_handle, uint32_t oplock_level); + NTSTATUS (*odb_break_oplocks)(struct odb_lock *lck); }; struct opendb_oplock_break { diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c index 3d4a760e2e..dd2fb138d6 100644 --- a/source4/ntvfs/common/opendb_tdb.c +++ b/source4/ntvfs/common/opendb_tdb.c @@ -503,6 +503,43 @@ static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle, return odb_push_record(lck, &file); } +/* + send oplocks breaks to none to all level2 holders +*/ +static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck) +{ + struct odb_context *odb = lck->odb; + NTSTATUS status; + struct opendb_file file; + int i; + bool modified = true; + + status = odb_pull_record(lck, &file); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + return NT_STATUS_OK; + } + NT_STATUS_NOT_OK_RETURN(status); + + /* see if anyone has an oplock, which we need to break */ + for (i=0;i<file.num_entries;i++) { + if (file.entries[i].oplock_level == OPLOCK_LEVEL_II) { + /* + * there could be multiple level2 oplocks + * and we just send a break to none to all of them + * without waiting for a release + */ + odb_oplock_break_send(odb, &file.entries[i], + OPLOCK_BREAK_TO_NONE); + file.entries[i].oplock_level = OPLOCK_NONE; + modified = true; + } + } + + if (modified) { + return odb_push_record(lck, &file); + } + return NT_STATUS_OK; +} /* remove a pending opendb entry @@ -682,7 +719,8 @@ static const struct opendb_ops opendb_tdb_ops = { .odb_set_delete_on_close = odb_tdb_set_delete_on_close, .odb_get_delete_on_close = odb_tdb_get_delete_on_close, .odb_can_open = odb_tdb_can_open, - .odb_update_oplock = odb_tdb_update_oplock + .odb_update_oplock = odb_tdb_update_oplock, + .odb_break_oplocks = odb_tdb_break_oplocks }; |