Browse code

squash preads

acab authored on 2009/08/28 01:29:03
Showing 1 changed files
... ...
@@ -48,10 +48,10 @@
48 48
 */
49 49
 
50 50
 /* FIXME: tune this stuff */
51
-#define UNPAGE_THRSHLD_LO 4*1024
52
-#define UNPAGE_THRSHLD_HI 8*1024
51
+#define UNPAGE_THRSHLD_LO 4*1024*1024
52
+#define UNPAGE_THRSHLD_HI 8*1024*1024
53 53
 
54
-//#define READAHEAD_PAGES 4
54
+#define READAHEAD_PAGES 4
55 55
 
56 56
 struct F_MAP {
57 57
     int fd;
... ...
@@ -184,71 +184,99 @@ static void fmap_aging(struct F_MAP *m) {
184 184
 }
185 185
 
186 186
 
187
-static int fmap_readpage(struct F_MAP *m, unsigned int page, int lock) {
188
-    size_t readsz, got;
189
-    char *pptr;
190
-    uint32_t s = m->bitmap[page];
191
-
192
-    if(s & FM_MASK_PAGED) {
193
-	/* page already paged */
194
-	if(lock) {
195
-	    /* we want locking */
196
-	    if(s & FM_MASK_LOCKED) {
197
-		/* page already locked */
198
-		s &= FM_MASK_COUNT;
199
-		if(s == FM_MASK_COUNT) { /* lock count already at max: fial! */
200
-		    cli_errmsg("fmap_readpage: lock count exceeded\n");
201
-		    return 1;
187
+static int fmap_readpage(struct F_MAP *m, unsigned int first_page, unsigned int count, unsigned int lock_count) {
188
+    size_t readsz = 0, got;
189
+    char *pptr = NULL;
190
+    uint32_t s;
191
+    unsigned int i, page = first_page, force_read = 0;
192
+
193
+    for(i=0; i<=count; i++, page++) {
194
+	int lock;
195
+	if(lock_count) {
196
+	    lock_count--;
197
+	    lock = 1;
198
+	} else lock = 0;
199
+	if(i == count) {
200
+	    /* we count one page too much to flush pending reads */
201
+	    if(!pptr) return 0; /* if we have any */
202
+	    force_read = 1;
203
+	} else if((s=m->bitmap[page]) & FM_MASK_PAGED) {
204
+	    /* page already paged */
205
+	    if(lock) {
206
+		/* we want locking */
207
+		if(s & FM_MASK_LOCKED) {
208
+		    /* page already locked */
209
+		    s &= FM_MASK_COUNT;
210
+		    if(s == FM_MASK_COUNT) { /* lock count already at max: fial! */
211
+			cli_errmsg("fmap_readpage: lock count exceeded\n");
212
+			return 1;
213
+		    }
214
+		    /* acceptable lock count: inc lock count */
215
+		    m->bitmap[page]++;
216
+		} else /* page not currently locked: set lock count = 1 */
217
+		    m->bitmap[page] = 1 | FM_MASK_LOCKED | FM_MASK_PAGED;
218
+	    } else {
219
+		/* we don't want locking */
220
+		if(!(s & FM_MASK_LOCKED)) {
221
+		    /* page is not locked: we reset aging to max */
222
+		    m->bitmap[page] = FM_MASK_PAGED | FM_MASK_COUNT;
202 223
 		}
203
-		/* acceptable lock count: inc lock count */
204
-		m->bitmap[page]++;
205
-	    } else /* page not currently locked: set lock count = 1 */
206
-		m->bitmap[page] = 1 | FM_MASK_LOCKED | FM_MASK_PAGED;
207
-	} else {
208
-	    /* we don't want locking */
209
-	    if(!(s & FM_MASK_LOCKED)) {
210
-		/* page is not locked: we reset aging to max */
211
-		m->bitmap[page] = FM_MASK_PAGED | FM_MASK_COUNT;
212 224
 	    }
225
+	    if(!pptr) continue;
226
+	    force_read = 1;
213 227
 	}
214
-	return 0;
215
-    }
216 228
 
217
-    /* page is not already paged */
218
-    pptr = (char *)m + page * m->pgsz + m->hdrsz;
219
-    if((page == m->pages - 1) && (m->len % m->pgsz))
220
-	readsz = m->len % m->pgsz;
221
-    else
222
-	readsz = m->pgsz;
223
-    if(s & FM_MASK_SEEN) {
224
-	/* page we've seen before: check mtime */
225
-	struct stat st;
226
-
227
-	if(fstat(m->fd, &st)) {
228
-	    cli_warnmsg("fmap_readpage: fstat failed\n");
229
-	    return 1;
229
+	if(force_read) {
230
+	    /* we have some pending reads to perform */
231
+	    unsigned int j;
232
+	    for(j=first_page; j<page; j++) {
233
+		if(m->bitmap[j] & FM_MASK_SEEN) {
234
+		    /* page we've seen before: check mtime */
235
+		    struct stat st;
236
+		    if(fstat(m->fd, &st)) {
237
+			cli_warnmsg("fmap_readpage: fstat failed\n");
238
+			return 1;
239
+		    }
240
+		    if(m->mtime != st.st_mtime) {
241
+			cli_warnmsg("fmap_readpage: file changed as we read it\n");
242
+			return 1;
243
+		    }
244
+		    break;
245
+		}
246
+	    }
247
+
248
+	    if((got=pread(m->fd, pptr, readsz, m->offset + first_page * m->pgsz)) != readsz) {
249
+		cli_warnmsg("pread fail: page %u pages %u map-offset %lu - asked for %lu bytes, got %lu\n", first_page, m->pages, (long unsigned int)m->offset, (long unsigned int)readsz, (long unsigned int)got);
250
+		return 1;
251
+	    }
252
+	    pptr = NULL;
253
+	    force_read = 0;
254
+	    readsz = 0;
255
+	    continue;
230 256
 	}
231
-	if(m->mtime != st.st_mtime) {
232
-	    cli_warnmsg("fmap_readpage: file changed as we read it\n");
233
-	    return 1;
257
+
258
+	/* page is not already paged */
259
+	if(!pptr) {
260
+	    /* set a new start for pending reads if we don't have one */
261
+	    pptr = (char *)m + page * m->pgsz + m->hdrsz;
262
+	    first_page = page;
234 263
 	}
264
+	if((page == m->pages - 1) && (m->len % m->pgsz))
265
+	    readsz += m->len % m->pgsz;
266
+	else
267
+	    readsz += m->pgsz;
268
+	if(lock) /* lock requested: set paged, lock page and set lock count to 1 */
269
+	    m->bitmap[page] = FM_MASK_PAGED | FM_MASK_LOCKED | 1;
270
+	else /* no locking: set paged and set aging to max */
271
+	    m->bitmap[page] = FM_MASK_PAGED | FM_MASK_COUNT;
272
+	m->paged++;
235 273
     }
236
-    if((got=pread(m->fd, pptr, readsz, m->offset + page * m->pgsz)) != readsz) {
237
-	cli_warnmsg("pread fail: page %u pages %u map-offset %lu - asked for %lu bytes, got %lu\n", page, m->pages, (long unsigned int)m->offset, (long unsigned int)readsz, (long unsigned int)got);
238
-	return 1;
239
-    }
240
-
241
-    if(lock) /* lock requested: set paged, lock page and set lock count to 1 */
242
-	m->bitmap[page] = FM_MASK_PAGED | FM_MASK_LOCKED | 1;
243
-    else /* no locking: set paged and set aging to max */
244
-	m->bitmap[page] = FM_MASK_PAGED | FM_MASK_COUNT;
245
-    m->paged++;
246 274
     return 0;
247 275
 }
248 276
 
249 277
 
250 278
 static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
251
-    unsigned int i, first_page, last_page, rahead_page;
279
+    unsigned int i, first_page, last_page, lock_count;
252 280
     char *ret;
253 281
 
254 282
     if(!len) {
... ...
@@ -265,21 +293,16 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
265 265
 
266 266
     first_page = fmap_which_page(m, at);
267 267
     last_page = fmap_which_page(m, at + len - 1);
268
+    lock_count = (lock!=0) * (last_page-first_page+1);
268 269
 #ifdef READAHED_PAGES
269
-    rahead_page = last_page;
270 270
     last_page += READAHED_PAGES;
271 271
     if(last_page >= m->pages) last_page = m->pages - 1;
272 272
 #endif
273 273
 
274 274
 //    cli_errmsg("FMAPDBG: +++ map %p - len %u lock: %d (page %u to %u)\n", m, len, lock, first_page, last_page);
275 275
 
276
-    for(i=first_page; i<=last_page; i++) {
277
-	if(fmap_readpage(m, i, lock))
278
-	    return NULL;
279
-#ifdef READAHED_PAGES
280
-	if(i==rahead_page) lock = 0;
281
-#endif
282
-    }
276
+    if(fmap_readpage(m, first_page, last_page-first_page+1, lock_count))
277
+	return NULL;
283 278
 
284 279
     ret = (char *)m;
285 280
     ret += at + m->hdrsz;
... ...
@@ -327,7 +350,7 @@ void *fmap_need_str(struct F_MAP *m, void *ptr, size_t len) {
327 327
 
328 328
 //	cli_errmsg("FMAPDBG: +s+ map %p - (page %u)\n", m, i);
329 329
 
330
-	if(fmap_readpage(m, i, 1))
330
+	if(fmap_readpage(m, i, 1, 1))
331 331
 	    return NULL;
332 332
 	if(i == first_page) {
333 333
 	    scanat = at % m->pgsz;