/** * Mark current page as dirty. * If there are no deferred writes, the page is immediately flushed to disk. * If ``force'' is TRUE, we also ignore deferred writes and flush the page. * @return TRUE on success. */ bool dirtypag(DBM *db, bool force) { struct lru_cache *cache = db->cache; long n; sdbm_lru_check(cache); n = (db->pagbuf - cache->arena) / DBM_PBLKSIZ; g_assert(n >= 0 && n < cache->pages); g_assert(db->pagbno == cache->numpag[n]); if (cache->write_deferred && !force) { if (cache->dirty[n]) cache->whits++; /* Was already dirty -> write cache hit */ else cache->wmisses++; cache->dirty[n] = TRUE; return TRUE; } /* * Flush current page to the kernel. If they are forcing the flush, * make sure we ask the kernel to synchronize the data as well. */ if (flushpag(db, db->pagbuf, db->pagbno)) { cache->dirty[n] = FALSE; if G_UNLIKELY(force) fd_fdatasync(db->pagf); return TRUE; }
/** * Close a stream, flushing data to disk. * * This is needed on "ext4" filesystems or any other filesystem which delays * the allocation of data blocks, in case there is a crash between the close * and the moment the data is written physically to the disk. * * @return the fclose() status. */ int file_sync_fclose(FILE *f) { int fd, ret; g_assert(f != NULL); ret = fflush(f); /* Send all buffered data to kernel first */ fd = fileno(f); if (-1 == fd_fdatasync(fd)) s_warning("cannot flush data blocks to disk for fd=%d: %m", fd); return fclose(f) | ret; /* Report error if fflush() failed */ }