}
}
+static int
+lafs_sync_file(struct file *file, struct dentry *de, int datasync)
+{
+ int err;
+ err = lafs_sync_inode(de->d_inode, 0);
+
+ /* FIXME I ignore datasync, just like file_fsync */
+ err = write_inode_now(de->d_inode, 0) ?: err;
+
+ if (err == 0)
+ lafs_sync_inode(de->d_inode, 1);
+ return err;
+}
+
const struct file_operations lafs_file_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.mmap = generic_file_mmap,
.open = generic_file_open,
/* .release = lafs__release_file,*/
-/* .fsync = lafs_sync_file, */
+ .fsync = lafs_sync_file,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
ino->i_sb->s_dirt = 1;
}
-int lafs_write_inode(struct inode *ino, int wait)
+int lafs_sync_inode(struct inode *ino, int wait)
{
- /* If inode has been changed, we want to write out
- * an update record for this inode.
- * If 'wait' we wait for the last update record to
- * complete.
- * If we cannot (could not) create an update record,
+ /* fsync has been called on this file so we need
+ * to sync any inode updates to the next cluster.
+ *
+ * If we cannot create an update record,
* we wait for a phase change, which writes everything
* out.
- *
- * This is called with wait==0 before doing a sync.
- * ->sync_fs gets called before we are called again with wait==1.
- * ->sync_fs will flush all inodes so the second call should have
- * nothing to do.
- * So if wait==0, we do nothing(later).
*/
struct datablock *b;
struct fs *fs = fs_from_inode(ino);
+ struct update_handle uh;
+ int err;
- if (wait == 0)
+ if (wait) {
+ if (LAFSI(ino)->update_cluster > 1)
+ lafs_cluster_wait(fs, LAFSI(ino)->update_cluster);
+ if (LAFSI(ino)->update_cluster == 1) {
+ lafs_checkpoint_lock(fs);
+ lafs_checkpoint_unlock_wait(fs);
+ }
return 0;
+ }
+ LAFSI(ino)->update_cluster = 0;
+ if (!test_bit(I_Dirty, &LAFSI(ino)->iflags))
+ return 0;
b = lafs_inode_dblock(ino, SYNC, MKREF(write_inode));
- if (IS_ERR(b)) /* FIXME should I mark something clean?? */
+ if (IS_ERR(b))
return PTR_ERR(b);
- /* FIXME this needs lots of thought... I think.
- * In what circumstance do we do an update, and in
- * what circumstance do we just write the block,
- * and how do we move dirty flags around when we do that?
- * And these iblock references should either go or be locked.
- */
- if (test_bit(B_Dirty, &b->b.flags)
- && !test_bit(B_Pinned, &b->b.flags)
- && LAFSI(ino)->iblock != NULL) {
- struct update_handle uh;
- int err;
- LAFSI(ino)->update_cluster = 0;
- BUG_ON(LAFSI(ino)->iblock == NULL);
-
- err = lafs_cluster_update_prepare(&uh, fs, LAFS_INODE_LOG_SIZE);
- if (err)
+ lafs_iolock_written(&b->b);
+ lafs_inode_fillblock(ino);
+ lafs_iounlock_block(&b->b);
+
+ err = lafs_cluster_update_prepare(&uh, fs, LAFS_INODE_LOG_SIZE);
+ if (err)
+ lafs_cluster_update_abort(&uh);
+ else {
+ lafs_checkpoint_lock(fs);
+ if (lafs_cluster_update_pin(&uh) == 0) {
+ if (test_and_clear_bit(B_Dirty, &b->b.flags))
+ lafs_space_return(fs, 1);
+ LAFSI(ino)->update_cluster =
+ lafs_cluster_update_commit
+ (&uh, b, LAFS_INODE_LOG_START,
+ LAFS_INODE_LOG_SIZE);
+ } else
lafs_cluster_update_abort(&uh);
- else {
- lafs_checkpoint_lock(fs);
- if (lafs_cluster_update_pin(&uh) == 0) {
- if (test_and_clear_bit(B_Dirty, &b->b.flags))
- lafs_space_return(fs, 1);
- LAFSI(ino)->update_cluster =
- lafs_cluster_update_commit
- (&uh, b, LAFS_INODE_LOG_START,
- LAFS_INODE_LOG_SIZE);
- } else
- lafs_cluster_update_abort(&uh);
- lafs_checkpoint_unlock(fs);
- }
+ lafs_checkpoint_unlock(fs);
}
if (test_bit(B_Dirty, &b->b.flags)) {
/* FIXME need to write out the data block...
*/
}
- if (wait) {
- if (LAFSI(ino)->update_cluster)
- lafs_cluster_wait(fs, LAFSI(ino)->update_cluster);
- else {
- struct indexblock *ib;
- lafs_checkpoint_lock(fs);
- ib = LAFSI(ino)->iblock;
- if (test_bit(B_Dirty, &ib->b.flags))
- lafs_checkpoint_unlock_wait(fs);
- else
- lafs_checkpoint_unlock(fs);
- }
+ if (LAFSI(ino)->update_cluster == 0) {
+ lafs_checkpoint_lock(fs);
+ if (test_bit(B_Dirty, &b->b.flags))
+ LAFSI(ino)->update_cluster = 1;
+ lafs_checkpoint_start(fs);
+ lafs_checkpoint_unlock(fs);
}
putdref(b, MKREF(write_inode));
return 0; /* FIXME should I return some error message??? */
struct datablock *db = li->dblock;
struct la_inode *lai;
+ clear_bit(I_Dirty, &LAFSI(ino)->iflags);
+
lai = map_dblock(db);
lai->data_blocks = cpu_to_le32(li->cblocks);
lai->index_blocks = cpu_to_le32(li->ciblocks);