Index: src/cf.data.pre =================================================================== RCS file: /server/cvs-server/squid/squid/src/cf.data.pre,v retrieving revision 1.363 diff -u -r1.363 cf.data.pre --- src/cf.data.pre 3 Aug 2006 02:31:11 -0000 1.363 +++ src/cf.data.pre 11 Aug 2006 04:55:21 -0000 @@ -1162,6 +1162,14 @@ number of memory-only buffers that COSS will use. The default value is 10, which will use a maximum of 10MB of memory for buffers. + maxfullbufs=n defines the maximum number of stripes a COSS partition + will have in memory waiting to be freed (either because the disk is + under load and the stripe is unwritten, or because clients are still + transferring data from objects using the memory). In order to try + and maintain a good hit rate under load, COSS will reserve the last + 2 full stripes for object hits. (ie a COSS cache_dir will reject + new objects when the number of full stripes is 2 less than maxfullbufs) + Common options: read-only, this cache_dir is read only. Index: src/fs/coss/store_coss.h =================================================================== RCS file: /server/cvs-server/squid/squid/src/fs/coss/store_coss.h,v retrieving revision 1.11 diff -u -r1.11 store_coss.h --- src/fs/coss/store_coss.h 3 Aug 2006 02:31:12 -0000 1.11 +++ src/fs/coss/store_coss.h 11 Aug 2006 04:55:22 -0000 @@ -145,6 +145,9 @@ float minumum_overwrite_pct; int minimum_stripe_distance; int numstripes; + int maxfullstripes; + int hitonlyfullstripes; + int numfullstripes; int sizerange_max; int sizerange_min; struct _cossstripe *stripes; Index: src/fs/coss/store_dir_coss.c =================================================================== RCS file: /server/cvs-server/squid/squid/src/fs/coss/store_dir_coss.c,v retrieving revision 1.52 diff -u -r1.52 store_dir_coss.c --- src/fs/coss/store_dir_coss.c 5 Aug 2006 15:36:24 -0000 1.52 +++ src/fs/coss/store_dir_coss.c 11 Aug 2006 04:55:23 -0000 @@ -44,6 +44,7 @@ #endif #define STORE_META_BUFSZ 4096 +#define HITONLY_BUFS 2 int n_coss_dirs = 0; int max_coss_dir_size = 0; @@ -97,10 +98,12 @@ static void storeCossDirParseOverwritePct(SwapDir *, const char *, const char *, int); static void storeCossDirParseMaxWaste(SwapDir *, const char *, const char *, int); static void storeCossDirParseMemOnlyBufs(SwapDir *, const char *, const char *, int); +static void storeCossDirParseMaxFullBufs(SwapDir *, const char *, const char *, int); static void storeCossDirDumpBlkSize(StoreEntry *, const char *, SwapDir *); static void storeCossDirDumpOverwritePct(StoreEntry *, const char *, SwapDir *); static void storeCossDirDumpMaxWaste(StoreEntry *, const char *, SwapDir *); static void storeCossDirDumpMemOnlyBufs(StoreEntry *, const char *, SwapDir *); +static void storeCossDirDumpMaxFullBufs(StoreEntry *, const char *, SwapDir *); static OBJH storeCossStats; static void storeDirCoss_StartDiskRebuild(RebuildState * rb); @@ -114,6 +117,7 @@ {"overwrite-percent", storeCossDirParseOverwritePct, storeCossDirDumpOverwritePct}, {"max-stripe-waste", storeCossDirParseMaxWaste, storeCossDirDumpMaxWaste}, {"membufs", storeCossDirParseMemOnlyBufs, storeCossDirDumpMemOnlyBufs}, + {"maxfullbufs", storeCossDirParseMaxFullBufs, storeCossDirDumpMaxFullBufs}, {NULL, NULL} }; @@ -624,11 +628,17 @@ loadav += disk_size_weight * current_write_weight; /* Remove the folowing check if we want to allow COSS partitions to get - * "too busy" + * too busy to accept new objects */ if (loadav > MAX_LOAD_VALUE) loadav = MAX_LOAD_VALUE; + /* Finally, we want to reject all new obects if the number of full stripes + * is too large + */ + if (cs->numfullstripes > cs->hitonlyfullstripes) + loadav += MAX_LOAD_VALUE; + debug(47, 9) ("storeAufsDirCheckObj: load=%d\n", loadav); return loadav; #else @@ -802,6 +812,15 @@ } cs->minimum_stripe_distance = cs->numstripes * cs->minumum_overwrite_pct; + /* Make sure cs->maxfull has a default value */ + if(cs->maxfullstripes == 0) + cs->maxfullstripes = cs->numstripes; + + /* We will reject new objects (ie go into hit-only mode) + * if there are <= 2 stripes available + */ + cs->hitonlyfullstripes = cs->maxfullstripes - HITONLY_BUFS; + debug(47, 0) ("COSS: number of memory-only stripes %d of %d bytes each\n", cs->nummemstripes, COSS_MEMBUF_SZ); cs->memstripes = xcalloc(cs->nummemstripes, sizeof(struct _cossstripe)); for (i = 0; i < cs->nummemstripes; i++) { @@ -810,7 +829,7 @@ cs->memstripes[i].numdiskobjs = -1; } - /* Update the max size (used for load calculations */ + /* Update the max size (used for load calculations) */ if (sd->max_size > max_coss_dir_size) max_coss_dir_size = sd->max_size; } @@ -846,6 +865,18 @@ } static void +storeCossDirParseMaxFullBufs(SwapDir * sd, const char *name, const char *value, int reconfiguring) +{ + CossInfo *cs = sd->fsdata; + int maxfull = atoi(value); + if (maxfull <= HITONLY_BUFS) + fatalf("COSS ERROR: There must be more than %d maxfullbufs\n", HITONLY_BUFS); + if (maxfull > 500) + fatal("COSS ERROR: Squid will likely use too much memory if it ever used 500MB worth of full buffers\n"); + cs->maxfullstripes = maxfull; +} + +static void storeCossDirParseMemOnlyBufs(SwapDir * sd, const char *name, const char *value, int reconfiguring) { CossInfo *cs = sd->fsdata; @@ -918,6 +949,13 @@ } static void +storeCossDirDumpMaxFullBufs(StoreEntry * e, const char *option, SwapDir * sd) +{ + CossInfo *cs = sd->fsdata; + storeAppendPrintf(e, " maxfullbufs=%d MB", cs->maxfullstripes); +} + +static void storeCossDirDumpMemOnlyBufs(StoreEntry * e, const char *option, SwapDir * sd) { CossInfo *cs = sd->fsdata; Index: src/fs/coss/store_io_coss.c =================================================================== RCS file: /server/cvs-server/squid/squid/src/fs/coss/store_io_coss.c,v retrieving revision 1.27 diff -u -r1.27 store_io_coss.c --- src/fs/coss/store_io_coss.c 5 Aug 2006 15:06:29 -0000 1.27 +++ src/fs/coss/store_io_coss.c 11 Aug 2006 04:55:25 -0000 @@ -162,14 +162,29 @@ /* Since we're not supporting NOTIFY anymore, lets fail */ assert(which != COSS_ALLOC_NOTIFY); - /* Check if we have overflowed the disk .. */ - if ((cs->current_offset + allocsize) > ((off_t) SD->max_size << 10)) { + /* Check to see if we need to allocate a membuf to start */ + if (cs->current_membuf == NULL) { + if(cs->curstripe < cs->numstripes) + newmb = storeCossCreateMemBuf(SD, cs->curstripe + 1, checkf, &coll); + else + newmb = storeCossCreateMemBuf(SD, 0, checkf, &coll); + + cs->current_membuf = newmb; + if (newmb == NULL) { + cs->sizerange_max = SD->max_objsize; + return -1; + } + cs->current_offset = cs->current_membuf->diskstart; + + /* Check if we have overflowed the disk .. */ + } else if ((cs->current_offset + allocsize) > ((off_t) SD->max_size << 10)) { /* * tried to allocate past the end of the disk, so wrap * back to the beginning */ coss_stats.disk_overflows++; cs->current_membuf->flags.full = 1; + cs->numfullstripes++; cs->current_membuf->diskend = cs->current_offset; storeCossMaybeWriteMemBuf(SD, cs->current_membuf); /* cs->current_membuf may be invalid at this point */ @@ -178,6 +193,10 @@ newmb = storeCossCreateMemBuf(SD, 0, checkf, &coll); cs->current_membuf = newmb; + if (newmb == NULL) { + cs->sizerange_max = SD->max_objsize; + return -1; + } /* Check if we have overflowed the MemBuf */ } else if ((cs->current_offset + allocsize) >= cs->current_membuf->diskend) { @@ -186,6 +205,7 @@ */ coss_stats.stripe_overflows++; cs->current_membuf->flags.full = 1; + cs->numfullstripes++; cs->current_offset = cs->current_membuf->diskend; storeCossMaybeWriteMemBuf(SD, cs->current_membuf); /* cs->current_membuf may be invalid at this point */ @@ -194,6 +214,10 @@ assert(cs->curstripe < (cs->numstripes - 1)); newmb = storeCossCreateMemBuf(SD, cs->curstripe + 1, checkf, &coll); cs->current_membuf = newmb; + if (newmb == NULL) { + cs->sizerange_max = SD->max_objsize; + return -1; + } } /* If we didn't get a collision, then update the current offset and return it */ if (coll == 0) { @@ -372,6 +396,10 @@ } else { debug(79, 3) ("storeCossOpen: %s memory miss - not reallocating (Current stripe : %d Object in stripe : %d)\n", SD->path, cs->curstripe, storeCossFilenoToStripe(cs, sio->swap_filen)); nf = storeCossMemOnlyAllocate(SD, e); + if (nf == -1) { + debug(79, 3) ("storeCossOpen: %s memory miss - reallocating because all membufs are in use\n", SD->path); + nf = storeCossAllocate(SD, e, COSS_ALLOC_REALLOC); + } } if (nf == -1) { /* We have to clean up neatly .. */ @@ -732,6 +760,10 @@ assert(cs->memstripes[mb->stripe].membuf == mb); cs->memstripes[mb->stripe].membuf = NULL; } + else + { + cs->numfullstripes--; + } debug(79, 3) ("storeCossMaybeFreeBuf: %p: lockcount = 0, written = 1: marking dead\n", mb); mb->flags.dead = 1; dlinkDelete(&mb->node, &cs->membufs); @@ -807,6 +839,7 @@ CossInfo *cs = (CossInfo *) SD->fsdata; off_t start; int stripe; + static time_t last_warn = 0; /* TODO: Maybe make this a simple search for a free membuf */ for (stripe = 0; stripe < cs->nummemstripes; stripe++) { @@ -814,7 +847,10 @@ break; } if (stripe >= cs->nummemstripes) { - debug(79, 1) ("storeCossCreateMemOnlyBuf: no free membufs. You may beed to increase the value of membufs on the %s cache_dir\n", SD->path); + if (last_warn + 15 < squid_curtime) { + debug(79, 1) ("storeCossCreateMemOnlyBuf: no free membufs. You may need to increase the value of membufs on the %s cache_dir\n", SD->path); + last_warn = squid_curtime; + } return NULL; } cs->curmemstripe = stripe; @@ -854,8 +890,17 @@ CossInfo *cs = (CossInfo *) SD->fsdata; off_t start = (off_t) stripe * COSS_MEMBUF_SZ; off_t o; + static time_t last_warn = 0; assert(start >= 0); + if (cs->numfullstripes >= cs->maxfullstripes) { + if (last_warn + 15 < squid_curtime) { + debug(79, 1) ("storeCossCreateMemBuf: Maximum number of full buffers reached on %s. You may need to increase the maxfullbuffers option for this cache_dir\n", SD->path); + last_warn = squid_curtime; + } + return NULL; + } + /* No, we shouldn't ever try to create a membuf if we haven't freed the one on * this stripe. Grr */ assert(cs->stripes[stripe].membuf == NULL);