From 8fa2d55b03879ba1bb21012d611c812fdb519d0e Mon Sep 17 00:00:00 2001 From: Sam Liddicott Date: Wed, 12 Nov 2008 08:35:32 +0000 Subject: [PATCH] Use validate as read-ahead --- source4/ntvfs/proxy/vfs_proxy.c | 79 +++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/source4/ntvfs/proxy/vfs_proxy.c b/source4/ntvfs/proxy/vfs_proxy.c index 6bf7d1d1aa1..51faf08b31f 100644 --- a/source4/ntvfs/proxy/vfs_proxy.c +++ b/source4/ntvfs/proxy/vfs_proxy.c @@ -28,7 +28,7 @@ #define TALLOC_ABORT(why) smb_panic(why) #warning handle SMB_FLAGS2_COMPRESSED flag from client: http://msdn2.microsoft.com/en-us/library/cc246254.aspx #define __LOCATION__ (talloc_asprintf(debug_ctx(),"%s:%d %s",__FILE__,__LINE__,__FUNCTION__)) -#define PROXY_NTIOCTL_MAXDATA 0x20000 +#define PROXY_NTIOCTL_MAXDATA 0x2000000 #include "includes.h" #include "libcli/raw/libcliraw.h" @@ -1745,6 +1745,7 @@ static void async_open(struct smbcli_request *c_req) find_search_cache_item(SMB_OPEN_IN_FILE(io), &s, &item) && item->cache) { DEBUG(5,("%s: Using cached file cache\n",__LOCATION__)); f->cache=talloc_reference(f, item->cache); + cache_beopen(f->cache); if (item->metadata) { *(f->metadata)=*(item->metadata); f->metadata->info_data.fname.s=talloc_strdup(f, item->metadata->info_data.fname.s); @@ -2424,7 +2425,7 @@ static NTSTATUS proxy_validate(struct ntvfs_module_context *ntvfs, if (!f) return NT_STATUS_INVALID_HANDLE; - DEBUG(5,("%s: fnum=%d\n",__FUNCTION__,f->fnum)); + DEBUG(5,("%s: fnum=%d **** %lld bytes \n\n\n\n",__LOCATION__,f->fnum,(long long int)r->in.maxcnt)); parts = talloc_zero(req, struct proxy_validate_parts_parts); DEBUG(5,("%s: parts=%p\n",__FUNCTION__,parts)); @@ -2464,6 +2465,9 @@ NTSTATUS proxy_validate_complete(struct proxy_validate_parts_parts *parts) { NTSTATUS status; struct proxy_Read* r=parts->r; + + DEBUG(5,("%s: %d/%d bytes \n\n\n\n",__LOCATION__,r->out.nread,r->in.maxcnt)); + MD5Final(parts->digest, &parts->context); status = parts->fragments->status; @@ -2484,13 +2488,13 @@ NTSTATUS proxy_validate_complete(struct proxy_validate_parts_parts *parts) DEBUG(5,("======= VALIDATED FINE \n\n\n")); } else if (r->in.flags & PROXY_USE_ZLIB) { ssize_t size = r->out.response.generic.count; - DEBUG(5,("======= VALIDATED WRONG \n\n\n")); + DEBUG(5,("======= VALIDATED WRONG; compress size %d \n\n\n",size)); if (compress_block(r->out.response.generic.data, &size) ) { r->out.flags|=PROXY_USE_ZLIB; r->out.response.compress.count=size; r->out.response.compress.data=r->out.response.generic.data; DEBUG(3,("%s: Compressed from %d to %d = %d%%\n", - __FUNCTION__,r->out.nread,size,size*100/r->out.nread)); + __LOCATION__,r->out.nread,size,size*100/r->out.nread)); } } @@ -2520,25 +2524,29 @@ NTSTATUS async_proxy_validate_parts(struct async_info *async, void* io1, void* i union smb_read *io_frag = fragment->io_frag; struct async_read_fragments* fragments=fragment->fragments; - DEBUG(5,("%s: parts=%p c_req=%p io_frag=%p\n",__FUNCTION__,parts, c_req, io_frag)); /* if request is not already received by a chained handler, read it */ if (c_req) status=smb_raw_read_recv(c_req, io_frag); DEBUG(5,("%s: status %s\n",__FUNCTION__,get_friendly_nt_error_msg (status))); + DEBUG(5,("\n\n%s: parts=%p c_req=%p io_frag=%p read %lld\n",__LOCATION__,parts, c_req, io_frag,(long long int)io_frag->generic.out.nread)); fragment->status=status; if (NT_STATUS_IS_OK(status)) { /* TODO: If we are not sequentially "next" the queue until we can do it */ /* log this data in r->out.generic.data */ - ssize_t extent = io_frag->generic.in.offset + io_frag->generic.out.nread; /* Find memcpy window, copy data from the io_frag to the io */ + + /* extent is the last byte we (don't) read for this frag */ + ssize_t extent = io_frag->generic.in.offset + io_frag->generic.out.nread; + /* start_offset is the file offset we first care about */ off_t start_offset=MAX(io_frag->generic.in.offset, r->in.offset); - /* Don't want to go past mincnt */ + /* Don't want to go past mincnt cos we don't have the buffer */ off_t io_extent=r->in.offset + r->in.mincnt; off_t end_offset=MIN(io_extent, extent); /* ASSERT(start_offset <= end_offset) */ /* ASSERT(start_offset <= io_extent) */ + /* Don't copy beyond buffer */ if (! (start_offset >= io_extent)) { uint8_t* dst=r->out.response.generic.data + (start_offset - r->in.offset); uint8_t* src=io_frag->generic.out.data+(start_offset - io_frag->generic.in.offset); @@ -2547,6 +2555,7 @@ NTSTATUS async_proxy_validate_parts(struct async_info *async, void* io1, void* i if (src != dst) memcpy(dst, src, end_offset - start_offset); r->out.nread=end_offset - r->in.offset; + DEBUG(5,("%s: nread %lld ++++++++++++++++++\n", __LOCATION__,(long long int)r->out.nread)); } MD5Update(&parts->context, io_frag->generic.out.data, @@ -2608,6 +2617,11 @@ static NTSTATUS proxy_validate_parts(struct ntvfs_module_context *ntvfs, #warning maybe true is more permissive? io_frag->generic.in.read_for_execute = false; + DEBUG(5,("%s: issue part read offset=%lld, size=%lld,%lld\n",__LOCATION__, + (long long int)io_frag->generic.in.offset, + (long long int)io_frag->generic.in.mincnt, + (long long int)io_frag->generic.in.maxcnt)); + //c_req = smb_raw_read_send(ntvfs, io_frag, parts->f, parts->r); c_req = smb_raw_read_send(private->tree, io_frag); NT_STATUS_HAVE_NO_MEMORY(c_req); @@ -2624,7 +2638,7 @@ static NTSTATUS proxy_validate_parts(struct ntvfs_module_context *ntvfs, ASYNC_RECV_TAIL_F_ORPHAN(io_frag, async_read_handler, parts->f, c_req->async.private, NT_STATUS_UNSUCCESSFUL); } - DEBUG(5,("%s: issued read parts=%p c_req=%p io_frag=%p\n",__FUNCTION__,parts, c_req, io_frag)); + DEBUG(5,("%s: issued read parts=%p c_req=%p io_frag=%p\n",__LOCATION__,parts, c_req, io_frag)); return NT_STATUS_OK; } @@ -2699,6 +2713,7 @@ static NTSTATUS proxy_read(struct ntvfs_module_context *ntvfs, return status; } } + DEBUG(5,("Cache read status: %s\n",get_friendly_nt_error_msg (status))); } fragments=talloc_zero(req, struct async_read_fragments); @@ -2840,13 +2855,22 @@ static NTSTATUS proxy_read(struct ntvfs_module_context *ntvfs, memcpy(r->in.digest.digest, digest, sizeof(digest)); r->in.flags |= PROXY_VALIDATE | PROXY_USE_CACHE; io_frag->generic.in.maxcnt = length; + r->in.mincnt=io_frag->generic.in.mincnt; /* the proxy send function will calculate the checksum based on *data */ } else { + /* try bulk read */ + if (f->oplock) { + DEBUG(5,("%s: *** faking bulkd read\n\n",__LOCATION__)); + r=talloc_zero(io_frag, struct proxy_Read); + r->in.flags |= PROXY_VALIDATE | PROXY_USE_CACHE | PROXY_USE_ZLIB; + io_frag->generic.in.maxcnt = MIN(f->metadata->info_data.size, private->cache_validatesize); + r->in.mincnt=io_frag->generic.in.maxcnt; + } /* not enough in cache to make it worthwhile anymore */ DEBUG(5,("VALIDATE DOWNGRADE 1, no more on this file: frag length %zu, offset %llu, cache=%x len=%lld\n", length, (unsigned long long) offset, (f->cache)?(f->cache->status):0, (unsigned long long)length)); - cache_handle_novalidate(f); + //cache_handle_novalidate(f); DEBUG(5,("VALIDATE DOWNGRADE 1, no more on this file: frag length %zu, offset %llu, cache=%x\n", length, (unsigned long long) offset, (f->cache)?(f->cache->status):0)); } @@ -3258,7 +3282,8 @@ static NTSTATUS proxy_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_OK; } DEBUG(5,("%s: Real close of %d\n",__FUNCTION__, f->fnum)); - cache_close(f->cache); + /* only close the cache if we aren't keeping references */ + //cache_close(f->cache); /* possibly samba can't do RAW_CLOSE_SEND yet */ if (! (c_req = smb_raw_close_send(private->tree, io))) { @@ -5135,6 +5160,7 @@ NTSTATUS async_proxy_smb_raw_read_rpc(struct async_info *async, { union smb_read* io =talloc_get_type_abort(io1, union smb_read); struct proxy_Read* r=talloc_get_type_abort(io2, struct proxy_Read); + struct proxy_file *f = async->f; DEBUG(5,("\n>>\n%s() rpc status: %s\n",__FUNCTION__, get_friendly_nt_error_msg(status))); @@ -5175,9 +5201,32 @@ NTSTATUS async_proxy_smb_raw_read_rpc(struct async_info *async, /* we may need to uncompress */ if (r->out.flags & PROXY_USE_ZLIB) { ssize_t size=r->out.response.compress.count; - if (! uncompress_block_to(io->generic.out.data, - r->out.response.compress.data, &size, - io->generic.in.maxcnt) || + DEBUG(5,("%s: uncompress, %lld wanted %lld or %lld\n",__LOCATION__, + (long long int)size, + (long long int)io->generic.in.maxcnt, + (long long int)io->generic.in.mincnt)); + if (size > io->generic.in.mincnt) { + /* we did a bulk read for the cache */ + uint8_t *data=talloc_size(io, io->generic.in.maxcnt); + DEBUG(5,("%s: bulk uncompress to %p\n",__LOCATION__,data)); + if (! uncompress_block_to(data, + r->out.response.compress.data, &size, + io->generic.in.maxcnt) || + size != r->out.nread) { + status=NT_STATUS_INVALID_USER_BUFFER; + } else { + DEBUG(5,("%s: uncompressed\n",__LOCATION__)); + /* copy as much as they can take */ + io->generic.out.nread=MIN(io->generic.in.mincnt, size); + memcpy(io->generic.out.data, data, io->generic.out.nread); + /* copy the rest to the cache */ + cache_handle_save(f, data, + size, + io->generic.in.offset); + } + } else if (! uncompress_block_to(io->generic.out.data, + r->out.response.compress.data, &size, + io->generic.in.maxcnt) || size != r->out.nread) { io->generic.out.nread=size; status=NT_STATUS_INVALID_USER_BUFFER; @@ -5205,14 +5254,14 @@ struct smbcli_request *proxy_smb_raw_read_send(struct ntvfs_module_context *ntvf struct smbcli_request *c_req; if (! r) { r=talloc_zero(io, struct proxy_Read); + if (! r) return NULL; + r->in.mincnt = io->generic.in.mincnt; } - if (! r) return NULL; r->in.fnum = io->generic.in.file.fnum; r->in.read_for_execute=io->generic.in.read_for_execute; r->in.offset = io->generic.in.offset; - r->in.mincnt = io->generic.in.mincnt; r->in.maxcnt = io->generic.in.maxcnt; r->in.remaining = io->generic.in.remaining; r->in.flags |= PROXY_USE_ZLIB; -- 2.11.4.GIT