* cloud. When the write completes, we will allow old journal segments (those
* that were fully written _before_ the snapshot process started) to be garbage
* collected. Newer journal segments can't be collected yet since they may
- * still contain data which has not been written persistently to the cloud. */
+ * still contain data which has not been written persistently to the cloud.
+ *
+ * Note that some of this code relies on the fact that only this thread of
+ * control (running flushd_cloud) is manipulating the inode map, and so
+ * concurrent updates to the inode map are prevented even without the
+ * filesystem lock held. Take great care if allowing multi-threaded access to
+ * the inode map... */
static void flushd_cloud(BlueSkyFS *fs)
{
g_mutex_lock(fs->lock);
/* TODO: Locking? Since we're reading a single variable this is probably
* atomic but a lock could be safer. */
+ BlueSkyCloudLog *marker = bluesky_log_get_commit_point(fs);
int journal_seq_start = fs->log->seq_num;
while (1) {
g_mutex_unlock(fs->lock);
g_mutex_lock(inode->lock);
- flushd_dirty_inode(inode);
+ g_assert(inode->change_cloud == inode->change_commit);
g_mutex_lock(fs->lock);
bluesky_list_unlink(&fs->dirty_list, inode->dirty_list);
inode->dirty_list = NULL;
g_mutex_unlock(fs->lock);
BlueSkyCloudLog *log = inode->committed_item;
- bluesky_cloudlog_ref(log);
+ inode->committed_item = NULL;
g_mutex_unlock(inode->lock);
if (log != NULL)
g_mutex_lock(fs->lock);
}
-
g_mutex_unlock(fs->lock);
+
+ /* Write out any updated inode map entries, so that all inodes just written
+ * can be located, and then a final commit record. */
+ BlueSkyCloudLog *commit_record = bluesky_inode_map_serialize(fs);
+ if (commit_record != NULL) {
+ bluesky_cloudlog_serialize(commit_record, fs);
+ } else {
+ g_print("No need for a checkpoint record...\n");
+ }
+
bluesky_cloudlog_flush(fs);
/* Wait until all segments have been written to the cloud, so that it
fs->log_state->pending_segments);
}
+ bluesky_log_write_commit_point(fs, marker);
+ bluesky_cloudlog_unref(commit_record);
+
g_print("All segments have been flushed, journal < %d is clean\n",
journal_seq_start);
fs->log->journal_watermark = journal_seq_start;
+
+ bluesky_inode_map_minimize(fs);
}
/* Drop cached data for a given inode, if it is clean. inode must be locked. */