... | ... |
@@ -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; |