Lines Matching refs:offtab
1 /* $NetBSD: offtab.c,v 1.15 2017/07/29 21:04:07 riastradh Exp $ */
33 __RCSID("$NetBSD: offtab.c,v 1.15 2017/07/29 21:04:07 riastradh Exp $");
50 #include "offtab.h"
56 errx(1, "bug in offtab, please report");
63 errx(1, "bug in offtab, please report");
67 offtab_compute_window_size(struct offtab *offtab, uint32_t start)
70 assert(start < offtab->ot_n_offsets);
71 return MIN(offtab->ot_window_size, (offtab->ot_n_offsets - start));
75 offtab_current_window_size(struct offtab *offtab)
78 return offtab_compute_window_size(offtab, offtab->ot_window_start);
82 offtab_current_window_end(struct offtab *offtab)
85 assert(offtab->ot_window_start < offtab->ot_n_offsets);
86 assert(offtab_current_window_size(offtab) <=
87 (offtab->ot_n_offsets - offtab->ot_window_start));
88 return (offtab->ot_window_start + offtab_current_window_size(offtab));
92 offtab_compute_window_position(struct offtab *offtab, uint32_t window_start,
95 const uint32_t window_size = offtab_compute_window_size(offtab,
101 assert(window_start <= offtab->ot_n_offsets);
106 assert(offtab->ot_fdpos <= OFFTAB_MAX_FDPOS);
109 assert(ADD_OK(off_t, offtab->ot_fdpos, window_offset));
110 *pos = (offtab->ot_fdpos + window_offset);
117 offtab_read_window(struct offtab *offtab, uint32_t blkno, int read_flags)
119 const uint32_t window_start = rounddown(blkno, offtab->ot_window_size);
123 assert(offtab->ot_mode == OFFTAB_MODE_READ);
125 (lseek(offtab->ot_fd, 0, SEEK_CUR) == offtab->ot_fdpos) ||
126 ((lseek(offtab->ot_fd, 0, SEEK_CUR) == -1) && (errno == ESPIPE)));
128 offtab_compute_window_position(offtab, window_start,
131 ? pread_block(offtab->ot_fd, offtab->ot_window, window_bytes,
133 : read_block(offtab->ot_fd, offtab->ot_window, window_bytes));
135 (*offtab->ot_report)("read offset table at %"PRIuMAX,
141 (*offtab->ot_reportx)("partial read of offset table"
147 offtab->ot_window_start = window_start;
153 offtab_maybe_read_window(struct offtab *offtab, uint32_t blkno, int read_flags)
157 if ((offtab->ot_window_start <= blkno) &&
158 (blkno < offtab_current_window_end(offtab)))
161 if (!offtab_read_window(offtab, blkno, read_flags))
168 offtab_write_window(struct offtab *offtab)
173 assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
175 offtab_compute_window_position(offtab, offtab->ot_window_start,
177 const ssize_t n_written = pwrite(offtab->ot_fd, offtab->ot_window,
189 offtab_maybe_write_window(struct offtab *offtab, uint32_t start, uint32_t end)
193 if (end <= offtab->ot_window_start)
195 if (offtab_current_window_end(offtab) < start)
198 offtab_write_window(offtab);
203 * Initialize an offtab to support the specified number of offsets read
207 offtab_init(struct offtab *offtab, uint32_t n_offsets, uint32_t window_size,
211 assert(offtab != NULL);
217 offtab->ot_n_offsets = n_offsets;
219 offtab->ot_window_size = n_offsets;
221 offtab->ot_window_size = window_size;
222 assert(offtab->ot_window_size <= offtab->ot_n_offsets);
223 offtab->ot_window_start = (uint32_t)-1;
225 offtab->ot_window = malloc(offtab->ot_window_size * sizeof(uint64_t));
226 if (offtab->ot_window == NULL)
228 offtab->ot_blkno = (uint32_t)-1;
229 offtab->ot_fd = fd;
230 offtab->ot_fdpos = fdpos;
231 offtab->ot_report = &offtab_bug;
232 offtab->ot_reportx = &offtab_bugx;
233 offtab->ot_mode = OFFTAB_MODE_NONE;
237 * Destroy an offtab.
240 offtab_destroy(struct offtab *offtab)
243 free(offtab->ot_window);
247 * For an offtab that has been used to read data from disk, convert it
248 * to an offtab that can be used to write subsequent data to disk.
252 offtab_transmogrify_read_to_write(struct offtab *offtab, uint32_t blkno)
255 assert(offtab->ot_mode == OFFTAB_MODE_READ);
258 if (!offtab_maybe_read_window(offtab, blkno, OFFTAB_READ_SEEK))
261 offtab->ot_mode = OFFTAB_MODE_WRITE;
262 offtab->ot_blkno = blkno;
269 * Reset an offtab for reading an offset table from the beginning.
270 * Initializes in-memory state and may read data from offtab->ot_fd,
271 * which must currently be at byte position offtab->ot_fdpos. Failure
281 offtab_reset_read(struct offtab *offtab,
286 assert((lseek(offtab->ot_fd, 0, SEEK_CUR) == offtab->ot_fdpos) ||
287 ((lseek(offtab->ot_fd, 0, SEEK_CUR) == -1) && (errno == ESPIPE)));
289 offtab->ot_report = report;
290 offtab->ot_reportx = reportx;
291 offtab->ot_mode = OFFTAB_MODE_READ;
292 offtab->ot_blkno = (uint32_t)-1;
294 if (!offtab_read_window(offtab, 0, OFFTAB_READ_NOSEEK))
297 if (offtab->ot_window_size < offtab->ot_n_offsets) {
299 const off_t offtab_bytes = ((off_t)offtab->ot_n_offsets *
301 assert(offtab->ot_fdpos <= OFFTAB_MAX_FDPOS);
304 assert(ADD_OK(off_t, offtab->ot_fdpos, offtab_bytes));
305 const off_t first_offset = (offtab->ot_fdpos + offtab_bytes);
306 if (lseek(offtab->ot_fd, first_offset, SEEK_SET) == -1) {
307 (*offtab->ot_report)("lseek to first offset 0x%"PRIx64,
322 offtab_prepare_get(struct offtab *offtab, uint32_t blkno)
325 assert(offtab->ot_mode == OFFTAB_MODE_READ);
326 assert(blkno < offtab->ot_n_offsets);
328 if (!offtab_maybe_read_window(offtab, blkno, OFFTAB_READ_SEEK))
331 assert(offtab->ot_window_start <= blkno);
332 assert(blkno < offtab_current_window_end(offtab));
334 offtab->ot_blkno = blkno;
343 offtab_get(struct offtab *offtab, uint32_t blkno)
346 assert(offtab->ot_mode == OFFTAB_MODE_READ);
347 assert(blkno == offtab->ot_blkno);
348 assert(offtab->ot_window_start <= blkno);
349 assert(blkno < offtab_current_window_end(offtab));
351 return be64toh(offtab->ot_window[blkno - offtab->ot_window_start]);
356 * Reset offtab for writing a fresh offset table. Initializes
357 * in-memory state and writes an empty offset table to offtab->ot_fd,
358 * which must currently be at byte position offtab->ot_fdpos. May
362 offtab_reset_write(struct offtab *offtab)
366 assert(lseek(offtab->ot_fd, 0, SEEK_CUR) == offtab->ot_fdpos);
368 offtab->ot_mode = OFFTAB_MODE_WRITE;
369 offtab->ot_blkno = (uint32_t)-1;
377 assert(offtab->ot_n_offsets > 0);
380 for (i = 0; i < offtab->ot_window_size; i++)
381 offtab->ot_window[i] = ~(uint64_t)0;
385 howmany(offtab->ot_n_offsets, offtab->ot_window_size);
388 offtab->ot_window_start = (i * offtab->ot_window_size);
389 offtab_write_window(offtab);
394 const off_t offtab_bytes = ((off_t)offtab->ot_n_offsets *
398 assert(offtab->ot_fdpos <= OFFTAB_MAX_FDPOS);
401 assert(ADD_OK(off_t, offtab->ot_fdpos, offtab_bytes));
402 const off_t first_offset = (offtab->ot_fdpos + offtab_bytes);
410 offtab->ot_window_start = 0;
411 offtab->ot_window[0] = htobe64((uint64_t)first_offset);
412 offtab_write_window(offtab);
414 if (lseek(offtab->ot_fd, first_offset, SEEK_SET) == -1)
426 * that is not signal-safe. The only state read is offtab->ot_window,
427 * offtab->ot_window_start, and quantities that are static for the
431 offtab_checkpoint(struct offtab *offtab, uint32_t n_offsets, int flags)
434 assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
435 assert(n_offsets <= offtab->ot_n_offsets);
441 if (offtab->ot_window != NULL)
442 offtab_maybe_write_window(offtab, 0, n_offsets);
450 assert(ADD_OK(off_t, offtab->ot_fdpos, sync_bytes));
451 if (fsync_range(offtab->ot_fd, (FFILESYNC | FDISKSYNC),
452 offtab->ot_fdpos, (offtab->ot_fdpos + sync_bytes))
463 offtab_prepare_put(struct offtab *offtab, uint32_t blkno)
467 assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
468 assert(blkno < offtab->ot_n_offsets);
475 assert((offtab->ot_blkno == (uint32_t)-1) ||
476 ((offtab->ot_blkno + 1) == blkno));
479 if ((offtab->ot_window_start <= blkno) &&
480 (blkno < offtab_current_window_end(offtab)))
484 offtab_write_window(offtab);
486 assert(offtab->ot_window_size <= blkno);
487 assert(offtab->ot_window_start == (blkno - offtab->ot_window_size));
488 assert((offtab->ot_window_start + offtab->ot_window_size) ==
489 rounddown(blkno, offtab->ot_window_size));
500 window = offtab->ot_window;
501 offtab->ot_window = NULL;
505 for (i = 0; i < offtab_current_window_size(offtab); i++)
510 offtab->ot_window = window;
511 offtab->ot_window_start = rounddown(blkno, offtab->ot_window_size);
515 win: assert(offtab->ot_window_start <= blkno);
516 assert(blkno < offtab_current_window_end(offtab));
518 offtab->ot_blkno = blkno;
525 offtab_put(struct offtab *offtab, uint32_t blkno, uint64_t offset)
528 assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
529 assert(blkno == offtab->ot_blkno);
530 assert(offtab->ot_window_start <= blkno);
531 assert(blkno < offtab_current_window_end(offtab));
533 offtab->ot_window[blkno - offtab->ot_window_start] = htobe64(offset);