Implement SMB Oplocks Phase 4+6
Phase 4: CREATE Handler dynamic oplock granting - Use OplockManager.can_grant() to determine oplock level - Register OplockEntry if oplock granted - Support ShareAccess compatibility checking - Grant Level II if exclusive/batch oplock exists Phase 6: CLOSE Handler oplock cleanup - Unregister from OplockManager when file closed - Only unregister if oplock_level > 0 All 229 tests pass.
This commit is contained in:
8
vendor/smb-server/src/handlers/close.rs
vendored
8
vendor/smb-server/src/handlers/close.rs
vendored
@@ -15,7 +15,7 @@ use crate::server::ServerState;
|
|||||||
const FLAG_POSTQUERY_ATTRIB: u16 = 0x0001;
|
const FLAG_POSTQUERY_ATTRIB: u16 = 0x0001;
|
||||||
|
|
||||||
pub async fn handle(
|
pub async fn handle(
|
||||||
_server: &Arc<ServerState>,
|
server: &Arc<ServerState>,
|
||||||
conn: &Arc<Connection>,
|
conn: &Arc<Connection>,
|
||||||
hdr: &Smb2Header,
|
hdr: &Smb2Header,
|
||||||
body: &[u8],
|
body: &[u8],
|
||||||
@@ -43,9 +43,15 @@ pub async fn handle(
|
|||||||
let handle = open.handle.take();
|
let handle = open.handle.take();
|
||||||
let path = open.last_path.clone();
|
let path = open.last_path.clone();
|
||||||
let delete_on_close = open.delete_on_close;
|
let delete_on_close = open.delete_on_close;
|
||||||
|
let oplock_level = open.oplock_level;
|
||||||
let want_attrs = req.flags & FLAG_POSTQUERY_ATTRIB != 0;
|
let want_attrs = req.flags & FLAG_POSTQUERY_ATTRIB != 0;
|
||||||
drop(open);
|
drop(open);
|
||||||
|
|
||||||
|
// Phase 6: Unregister from OplockManager if oplock was granted
|
||||||
|
if oplock_level > 0 {
|
||||||
|
server.oplock_manager.unregister(&path, &req.file_id).await;
|
||||||
|
}
|
||||||
|
|
||||||
// Stat before closing if needed.
|
// Stat before closing if needed.
|
||||||
let info_before_close = if want_attrs {
|
let info_before_close = if want_attrs {
|
||||||
if let Some(h) = handle.as_ref() {
|
if let Some(h) = handle.as_ref() {
|
||||||
|
|||||||
33
vendor/smb-server/src/handlers/create.rs
vendored
33
vendor/smb-server/src/handlers/create.rs
vendored
@@ -46,7 +46,7 @@ const FILE_OPENED: u32 = 0x0000_0001;
|
|||||||
const FILE_CREATED: u32 = 0x0000_0002;
|
const FILE_CREATED: u32 = 0x0000_0002;
|
||||||
|
|
||||||
pub async fn handle(
|
pub async fn handle(
|
||||||
_server: &Arc<ServerState>,
|
server: &Arc<ServerState>,
|
||||||
conn: &Arc<Connection>,
|
conn: &Arc<Connection>,
|
||||||
hdr: &Smb2Header,
|
hdr: &Smb2Header,
|
||||||
body: &[u8],
|
body: &[u8],
|
||||||
@@ -154,14 +154,39 @@ pub async fn handle(
|
|||||||
let tree = tree_arc.write().await;
|
let tree = tree_arc.write().await;
|
||||||
let file_id = tree.alloc_file_id();
|
let file_id = tree.alloc_file_id();
|
||||||
|
|
||||||
// Phase 4: Oplock support - determine oplock level
|
// Phase 4: Oplock support - use OplockManager to determine granted level
|
||||||
let granted_oplock = 0; // Phase 1 placeholder (will be dynamic in Phase 4)
|
let requested_oplock = req.requested_oplock_level;
|
||||||
|
let granted_oplock = if requested_oplock == 0 {
|
||||||
|
0 // No oplock requested
|
||||||
|
} else {
|
||||||
|
// Check with OplockManager
|
||||||
|
server.oplock_manager.can_grant(
|
||||||
|
&path,
|
||||||
|
requested_oplock,
|
||||||
|
req.share_access,
|
||||||
|
if want_write { granted } else { Access::Read },
|
||||||
|
).await.unwrap_or(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register with OplockManager if oplock granted
|
||||||
|
if granted_oplock > 0 {
|
||||||
|
use crate::oplock::OplockEntry;
|
||||||
|
server.oplock_manager.register(&path, OplockEntry {
|
||||||
|
file_id,
|
||||||
|
tree_id: tree.id,
|
||||||
|
session_id: hdr.session_id,
|
||||||
|
oplock_level: granted_oplock,
|
||||||
|
share_access: req.share_access,
|
||||||
|
granted_access: if want_write { granted } else { Access::Read },
|
||||||
|
connection_id: 0, // Will be tracked in Phase 3
|
||||||
|
}).await;
|
||||||
|
}
|
||||||
|
|
||||||
let open = Open::new(
|
let open = Open::new(
|
||||||
file_id,
|
file_id,
|
||||||
handle,
|
handle,
|
||||||
if want_write { granted } else { Access::Read },
|
if want_write { granted } else { Access::Read },
|
||||||
path,
|
path.clone(),
|
||||||
info.is_directory,
|
info.is_directory,
|
||||||
delete_on_close,
|
delete_on_close,
|
||||||
granted_oplock, // oplock_level
|
granted_oplock, // oplock_level
|
||||||
|
|||||||
Reference in New Issue
Block a user