#
#
# patch "src/fs/coss/store_coss.h"
#  from [f844eb6984673084b6f79b7dcb39b7203c7eb7b4]
#    to [9c9ce133b4e0e10484aa1078935ec75d1ea0f20f]
# 
# patch "src/fs/coss/store_dir_coss.c"
#  from [1d02b09394328b30b7d094eea06fcf575faa51c9]
#    to [85f5baf9794c73ee798ac61825b412a27d274c31]
#
============================================================
--- src/fs/coss/store_coss.h	f844eb6984673084b6f79b7dcb39b7203c7eb7b4
+++ src/fs/coss/store_coss.h	9c9ce133b4e0e10484aa1078935ec75d1ea0f20f
@@ -26,7 +26,7 @@ typedef struct _cossstripe CossStripe;
  * Define this if you would like to use the aufs IO method for
  * disk IO instead of the POSIX AIO method.
  */
-//#define	USE_AUFSOPS 1
+#define	USE_AUFSOPS 1
 
 #if USE_AUFSOPS
 /* XXX a hack; the async ops should be broken out! */
============================================================
--- src/fs/coss/store_dir_coss.c	1d02b09394328b30b7d094eea06fcf575faa51c9
+++ src/fs/coss/store_dir_coss.c	85f5baf9794c73ee798ac61825b412a27d274c31
@@ -197,6 +197,7 @@ storeCossRemove(SwapDir * sd, StoreEntry
     int stripe;
     //debug(1, 1) ("storeCossRemove: %x: %d/%d\n", e, (int) e->swap_dirn, (e) e->swap_filen);
     CossIndexNode *coss_node = e->repl.data;
+    assert(sd->index == e->swap_dirn);
     assert(e->swap_filen >= 0);
     e->repl.data = NULL;
     stripe = storeCossFilenoToStripe(cs, e->swap_filen);
@@ -212,6 +213,7 @@ storeCossAdd(SwapDir * sd, StoreEntry * 
     CossStripe *cstripe = &cs->stripes[curstripe];
     CossIndexNode *coss_node = memPoolAlloc(coss_index_pool);
     assert(!e->repl.data);
+    assert(sd->index == e->swap_dirn);
     /* Make sure the object exists in the current stripe, it should do! */
     assert(curstripe == storeCossFilenoToStripe(cs, e->swap_filen));
     e->repl.data = coss_node;
@@ -897,12 +899,27 @@ static void storeCoss_ConsiderStoreEntry
 static void storeDirCoss_ParseStripeBuffer(RebuildState *rb);
 static void storeCoss_ConsiderStoreEntry(RebuildState *rb, const cache_key *key, StoreEntry *e);
 
+#if USE_AUFSOPS
 static void
+storeDirCoss_ReadStripeComplete(int fd, void *my_data, const char *buf, int aio_return, int aio_errno)
+#else
+static void
 storeDirCoss_ReadStripeComplete(int fd, const char *buf, int r_len, int r_errflag, void *my_data)
+#endif
 {
 	RebuildState *rb = my_data;
 	SwapDir *SD = rb->sd;
 	CossInfo *cs = SD->fsdata;
+#if USE_AUFSOPS
+	int r_errflag;
+	int r_len;
+        r_len = aio_return;
+        if (aio_errno)
+                r_errflag = aio_errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
+        else
+                r_errflag = DISK_OK;
+	xmemcpy(cs->rebuild.buf, buf, r_len);
+#endif
 
 	debug(47, 2) ("COSS: %s: stripe %d, read %d bytes, status %d\n", SD->path, cs->rebuild.curstripe, r_len, r_errflag);
 	cs->rebuild.reading = 0;
@@ -942,7 +959,12 @@ storeDirCoss_ReadStripe(RebuildState *rb
 		    cs->rebuild.curstripe * 100 / cs->numstripes, cs->rebuild.curstripe, cs->numstripes);
 		rb->report_current += rb->report_interval;
 	}
+#if USE_AUFSOPS
+	/* XXX this should be a prime candidate to use a modified aioRead which doesn't malloc a damned buffer */
+	aioRead(cs->fd, cs->rebuild.curstripe * COSS_MEMBUF_SZ, COSS_MEMBUF_SZ, storeDirCoss_ReadStripeComplete, rb);
+#else
 	a_file_read(&cs->aq, cs->fd, cs->rebuild.buf, COSS_MEMBUF_SZ, cs->rebuild.curstripe * COSS_MEMBUF_SZ, storeDirCoss_ReadStripeComplete, rb);
+#endif
 }
 
 static void
@@ -1000,7 +1022,7 @@ storeDirCoss_ParseStripeBuffer(RebuildSt
 			debug(47, 3) ("COSS: %s: stripe %d: offset %d gives NULL swapmeta data; end of stripe\n", SD->path, cs->rebuild.curstripe, j);
 			return;
 		}
-		filen = j / blocksize + (cs->rebuild.curstripe * COSS_MEMBUF_SZ / blocksize);
+		filen = (off_t) j / (off_t) blocksize + (off_t) ((off_t) cs->rebuild.curstripe * (off_t) COSS_MEMBUF_SZ / (off_t) blocksize);
 		debug(47, 3) ("COSS: %s: stripe %d: filen %d: header size %d\n", SD->path, cs->rebuild.curstripe, filen, bl);
 
 		/* COSS objects will have an object size written into the metadata */
@@ -1118,6 +1140,7 @@ storeCoss_AddStoreEntry(RebuildState *rb
 	CossInfo *cs = SD->fsdata;
 	rb->counts.objcount++;
 	/* The Passed-in store entry is temporary; don't bloody use it directly! */
+	assert(e->swap_dirn == SD->index);
 	ne = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL);
 	ne->store_status = STORE_OK;
 	storeSetMemStatus(ne, NOT_IN_MEMORY);
@@ -1147,10 +1170,10 @@ storeCoss_DeleteStoreEntry(RebuildState 
 static void
 storeCoss_DeleteStoreEntry(RebuildState *rb, const cache_key *key, StoreEntry *e)
 {
-	SwapDir *SD = rb->sd;
 	assert(rb->counts.objcount >= 0);
 	rb->counts.objcount--;
-	storeCossRemove(SD, e);
+	assert(e->swap_dirn >= 0);
+	storeCossRemove(INDEXSD(e->swap_dirn), e);
 	e->swap_filen = -1;
 	storeExpireNow(e);
 	storeReleaseRequest(e);
@@ -1174,7 +1197,6 @@ storeCoss_ConsiderStoreEntry(RebuildStat
 static void
 storeCoss_ConsiderStoreEntry(RebuildState *rb, const cache_key *key, StoreEntry *e)
 {
-	SwapDir *SD = rb->sd;
 	StoreEntry *oe;
 
 	/* Check for clashes */
@@ -1185,8 +1207,11 @@ storeCoss_ConsiderStoreEntry(RebuildStat
 		storeCoss_AddStoreEntry(rb, key, e);
 		return;
 	}
-	assert(oe->swap_dirn == SD->index);
 
+	/* This isn't valid - its possible we have a fresher object in another store */
+	/* unlike the UFS-based stores we don't "delete" the disk object when we
+	 * have deleted the object; its one of the annoying things about COSS. */
+	//assert(oe->swap_dirn == SD->index);
 	/* Dang, its a clash. See if its fresher */
 
 	/* Fresher? Its a new object: deallocate the old one, reallocate the new one */
