Experimental read cache patches, part 4 of 4
David Collier-Brown -- Customer Engineering
David.Collier-Brown at Sun.COM
Thu May 29 20:44:29 GMT 2003
jra at dp.samba.org wrote:
> b). Send patches as *attachments*, not as inline code. This
> preserves all line boundaries etc.
Oh RATS! I was carefully pasting them in as message text
to keep the list processor from removing them.
Let's try that one again (;-)) Here they are again
as diff files generated with the gnu diff, with
-ugh options. If I literally need to use CVS, I'll
redo them at home.
--dave
--
David Collier-Brown, | Always do right. This will gratify
Sun Microsystems DCMO | some people and astonish the rest.
Toronto, Ontario |
(905) 415-2849 or x52849 | davecb at canada.sun.com
-------------- next part --------------
--- close.old.c Tue May 27 20:05:13 2003
+++ close.c Wed May 28 21:17:21 2003
@@ -96,6 +96,7 @@ static int close_filestruct(files_struct
ret = -1;
delete_write_cache(fsp);
+ delete_read_cache(fsp);
}
conn->num_files_open--;
-------------- next part --------------
--- fileio.old.c Tue May 27 20:05:13 2003
+++ fileio.c Wed May 28 21:37:09 2003
@@ -23,6 +23,11 @@
#include "includes.h"
static BOOL setup_write_cache(files_struct *, SMB_OFF_T);
+static BOOL setup_read_cache(files_struct *);
+static int copy_from_cache(write_cache *, char *, size_t);
+static int read_from_read_cache(files_struct *,char
*,SMB_OFF_T,size_t);
+static void delete_cache(write_cache *cp);
+
/****************************************************************************
Seek a file. Try to avoid the seek if possible.
@@ -71,6 +76,109 @@ static BOOL read_from_write_cache(files_
return True;
}
+/*
+ * Read from the read cache, too.
+ */
+static int read_from_read_cache(files_struct *fsp, char *data,
+ SMB_OFF_T pos, size_t n)
+{
+ write_cache *rcp;
+ int rc,
+ ncopied = 0;
+
+ DEBUG(10,("read_from_read_cache\n"));
+ rcp = fsp->rcp;
+ if (rcp == NULL && fsp->wcp != NULL) {
+ /* There is a write cache, and it takes precedence. */
+ return 0;
+ }
+ else if (rcp == NULL) {
+ /* There is no write cache, so make a read cache. */
+ if (setup_read_cache(fsp) == False) {
+ return 0;
+ }
+ else {
+ /* Reload our copy of rcp. */
+ rcp = fsp->rcp;
+ }
+ }
+
+
+ if (rcp->data_size == -1) {
+ /* We are already at eof. */
+ return EOF;
+ }
+ else if (n <= rcp->data_size) {
+ /* It can be read straight from the buffer. */
+ (void) copy_from_cache(rcp, &data[ncopied], n);
+ return n;
+ }
+ else {
+ /* It requires a buffer-refilling loop. */
+ ncopied = 0;
+ rc = copy_from_cache(rcp, &data[ncopied],
rcp->data_size);
+ ncopied += rc;
+ n -= rc;
+
+ while ((rc = reload_read_cache(fsp)) != 0 && rc != -1) {
+ if (n <= rc) {
+ rc = copy_from_cache(rcp,
&data[ncopied], n);
+ ncopied += rc;
+ return ncopied;
+ }
+ else {
+ rc = copy_from_cache(rcp,
&data[ncopied], rcp->data_size);
+ ncopied += rc;
+ n -= rc;
+ }
+ }
+ }
+
+ /* DO_PROFILE_INC(readcache_read_hits); */
+ return ncopied;
+}
+
+
+/*
+ * copy_from_cache -- do the bookkeeping in one place.
+ */
+ static int
+copy_from_cache(write_cache *rcp, char *data, size_t size) {
+ size_t i = MIN(size, rcp->data_size);
+
+ (void) memcpy(data, rcp->at, i);
+ rcp->at += i;
+ rcp->offset += i;
+ rcp->data_size -= i;
+ return i;
+}
+
+
+/*
+ * reload_read_cache -- return a non-zero length or EOF.
+ */
+ int
+reload_read_cache(files_struct *fsp) {
+ write_cache *rcp = fsp->rcp; /* The read cache. */
+ int nread;
+
+ rcp->at = rcp->data;
+ nread = read(fsp->fd, rcp->data, rcp->alloc_size);
+ if (nread == -1 || nread == 0) {
+ rcp->data_size = -1; /* We hit EOF. */
+ return -1;
+ }
+ else {
+ rcp->data_size = nread;
+ rcp->data[nread] = '\0';
+ return nread;
+ }
+}
+
+
+
+
+
/****************************************************************************
Read from a file.
****************************************************************************/
@@ -83,6 +191,16 @@ ssize_t read_file(files_struct *fsp,char
if (fsp->print_file)
return -1;
+
+ /*
+ * Serve from read cache if we can. If not, we'll
+ * continue to the write cache and one last direct read.
+ */
+ if ((ret = read_from_read_cache(fsp, data, pos, n)) > 0) {
+ return ret;
+ }
+
+
/*
* Serve from write cache if we can.
*/
@@ -96,7 +214,24 @@ ssize_t read_file(files_struct *fsp,char
DEBUG(3,("read_file: Failed to seek to
%.0f\n",(double)pos));
return(ret);
}
-
+
+
+ ret = really_read_file(fsp, data, pos, n);
+
+ DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned
%lu\n",
+ fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret
));
+
+ return(ret);
+}
+
+/*
+ * really_read_file -- read with optional retry hack.
+ */
+ int
+really_read_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t
n) {
+ int ret, readret;
+
+
if (n > 0) {
#ifdef DMF_FIX
int numretries = 3;
@@ -628,30 +763,41 @@ n = %u, wcp->offset=%.0f, wcp->data_size
}
/****************************************************************************
- Delete the write cache structure.
+ Delete the read/write cache structures.
****************************************************************************/
void delete_write_cache(files_struct *fsp)
{
- write_cache *wcp;
-
- if(!fsp)
- return;
-
- if(!(wcp = fsp->wcp))
- return;
+ if (fsp) {
+ delete_cache(fsp->wcp);
+ DEBUG(10,("delete_write_cache: File %s deleted write
cache\n",fsp->fsp_name ));
- DO_PROFILE_DEC(writecache_allocated_write_caches);
- allocated_write_caches--;
-
- SMB_ASSERT(wcp->data_size == 0);
+ }
+}
- SAFE_FREE(wcp->data);
- SAFE_FREE(fsp->wcp);
+void delete_read_cache(files_struct *fsp)
+{
+ if (fsp) {
+ delete_cache(fsp->rcp);
+ DEBUG(10,("delete_read_cache: File %s deleted read
cache\n", fsp->fsp_name ));
+ }
+}
- DEBUG(10,("delete_write_cache: File %s deleted write cache\n",
fsp->fsp_name ));
+static void delete_cache(write_cache *cp) {
+
+ if (cp == NULL)
+ return;
+
+ DO_PROFILE_DEC(writecache_allocated_write_caches);
+ allocated_write_caches--;
+
+ SMB_ASSERT(cp->data_size == 0);
+
+ SAFE_FREE(cp->data);
+ SAFE_FREE(cp);
}
+
/****************************************************************************
Setup the write cache structure.
****************************************************************************/
@@ -694,6 +840,51 @@ static BOOL setup_write_cache(files_stru
return True;
}
+
+/* Setup read cache -- use same cache pool as write caches. */
+static BOOL setup_read_cache(files_struct *fsp)
+{
+ ssize_t alloc_size = lp_read_cache_size(SNUM(fsp->conn));
+ write_cache *rcp;
+
+ DEBUG(10,("setup_read_cache\n"));
+ if (alloc_size == 0) {
+ return False;
+ }
+ if (allocated_write_caches >= MAX_WRITE_CACHES)
+ return False;
+
+ if (fsp->rcp)
+ return False;
+
+ if((rcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) {
+ DEBUG(0,("setup_read_cache: malloc fail.\n"));
+ return False;
+ }
+
+
+ rcp->file_size = 0; /* Junk value.*/
+ rcp->offset = 0; /* -1 would mean EOF. */
+ rcp->alloc_size = alloc_size;
+ rcp->data_size = 0;
+ if((rcp->data = malloc(rcp->alloc_size)) == NULL) {
+ DEBUG(0,("setup_write_cache: malloc fail for buffer size
%u.\n",
+ (unsigned int)rcp->alloc_size ));
+ SAFE_FREE(rcp);
+ return False;
+ }
+ rcp->at = rcp->data;
+
+ fsp->rcp = rcp;
+ /* DO_PROFILE_INC(writecache_allocated_read_caches); */
+ allocated_write_caches++;
+
+ DEBUG(10,("setup_read_cache: File %s allocated read cache size
%u\n",
+ fsp->fsp_name, rcp->alloc_size ));
+
+ return True;
+ }
+
/****************************************************************************
Cope with a size change.
-------------- next part --------------
--- loadparm.old.c Wed May 28 21:23:51 2003
+++ loadparm.c Wed May 28 21:40:18 2003
@@ -347,6 +347,7 @@ typedef struct
int iMaxPrintJobs;
int iMaxReportedPrintJobs;
int iWriteCacheSize;
+ int iReadCacheSize;
int iCreate_mask;
int iCreate_force_mode;
int iSecurity_mask;
@@ -466,6 +467,7 @@ static service sDefault = {
1000, /* iMaxPrintJobs */
0, /* iMaxReportedPrintJobs */
0, /* iWriteCacheSize */
+ 0, /* iReadCacheSize */
0744, /* iCreate_mask */
0000, /* iCreate_force_mode */
0777, /* iSecurity_mask */
@@ -902,6 +904,7 @@ static struct parm_struct parm_table[] =
{"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL,
NULL, FLAG_SHARE},
{"hostname lookups", P_BOOL, P_GLOBAL,
&Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"write cache size", P_INTEGER, P_LOCAL,
&sDefault.iWriteCacheSize, NULL, NULL, FLAG_SHARE},
+ {"read cache size", P_INTEGER, P_LOCAL,
&sDefault.iReadCacheSize, NULL, NULL, FLAG_SHARE},
{"name cache timeout", P_INTEGER, P_GLOBAL,
&Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED |
FLAG_DEVELOPER},
@@ -1851,6 +1854,7 @@ FN_LOCAL_INTEGER(lp_max_reported_jobs, i
FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
+FN_LOCAL_INTEGER(lp_read_cache_size, iReadCacheSize)
FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
-------------- next part --------------
--- smb.old.h Tue May 27 20:04:23 2003
+++ smb.h Wed May 28 21:13:48 2003
@@ -365,6 +365,7 @@ typedef struct write_cache
size_t alloc_size;
size_t data_size;
char *data;
+ char *at; /* Used only in read buffers. */
} write_cache;
typedef struct
@@ -393,6 +394,7 @@ typedef struct files_struct
uint16 vuid;
write_bmpx_struct *wbmpx_ptr;
write_cache *wcp;
+ write_cache *rcp; /* Read cache. */
struct timeval open_time;
int share_mode;
uint32 desired_access;
More information about the samba-technical
mailing list