From da2a6dc16727aed6bf4416102dfeb5ba9ffb5e52 Mon Sep 17 00:00:00 2001 From: Sam Liddicott Date: Fri, 7 Nov 2008 15:39:58 +0000 Subject: [PATCH] Fix broken oplock handling Oplock faking should fake the request not the response. Track oplock status and oplock break status in the proxy file struct --- source4/ntvfs/proxy/vfs_proxy.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/source4/ntvfs/proxy/vfs_proxy.c b/source4/ntvfs/proxy/vfs_proxy.c index 66a1e9e58ee..6ee36bf934d 100644 --- a/source4/ntvfs/proxy/vfs_proxy.c +++ b/source4/ntvfs/proxy/vfs_proxy.c @@ -54,6 +54,7 @@ struct proxy_file { struct ntvfs_handle *h; struct cache_file_entry *cache; int readahead_pending; + int oplock; }; /* this is stored in ntvfs_private */ @@ -230,8 +231,13 @@ static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin return true; } - /* If we don't have an oplock, then we can't rely on the cache */ - cache_handle_stale(f); + if (level==OPLOCK_BREAK_TO_LEVEL_II) { + f->oplock=LEVEL_II_OPLOCK_RETURN; + } else { + /* If we don't have an oplock, then we can't rely on the cache */ + cache_handle_stale(f); + f->oplock=NO_OPLOCK_RETURN; + } DEBUG(5,("vfs_proxy: sending oplock break level %d for fnum %d\n", level, fnum)); status = ntvfs_send_oplock_break(private->ntvfs, h, level); @@ -777,9 +783,10 @@ static void async_open(struct smbcli_request *c_req) file->ntvfs = f->h; DLIST_ADD(proxy->files, f); + f->oplock=io->generic.out.oplock_level; + if (proxy->cache_enabled) { - bool oplock=(io->generic.out.oplock_level != OPLOCK_NONE) || proxy->fake_oplock; - f->cache=cache_open(proxy->cache, f, io, oplock, proxy->cache_readahead); + f->cache=cache_open(proxy->cache, f, io, f->oplock, proxy->cache_readahead); if (proxy->fake_valid) { cache_handle_validated(f, cache_handle_len(f)); } @@ -810,12 +817,19 @@ static NTSTATUS proxy_open(struct ntvfs_module_context *ntvfs, } status = ntvfs_handle_new(ntvfs, req, &h); +#warning should we free this handle if the open fails? NT_STATUS_NOT_OK_RETURN(status); f = talloc_zero(h, struct proxy_file); NT_STATUS_HAVE_NO_MEMORY(f); f->h = h; + /* if oplocks aren't requested, optionally override and request them */ + if (! (io->generic.in.flags & (OPENX_FLAGS_REQUEST_OPLOCK | OPENX_FLAGS_REQUEST_BATCH_OPLOCK)) + && private->fake_oplock) { + io->generic.in.flags |= OPENX_FLAGS_REQUEST_OPLOCK | OPENX_FLAGS_REQUEST_BATCH_OPLOCK; + } + if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { union smb_handle *file; @@ -830,10 +844,10 @@ static NTSTATUS proxy_open(struct ntvfs_module_context *ntvfs, file->ntvfs = f->h; DLIST_ADD(private->files, f); - if (private->cache_enabled) { - bool oplock=(io->generic.out.oplock_level != OPLOCK_NONE) || private->fake_oplock; + f->oplock=io->generic.out.oplock_level; - f->cache=cache_open(private->cache, f, io, oplock, private->cache_readahead); + if (private->cache_enabled) { + f->cache=cache_open(private->cache, f, io, f->oplock, private->cache_readahead); if (private->fake_valid) { cache_handle_validated(f, cache_handle_len(f)); } -- 2.11.4.GIT