aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-09-05 16:13:11 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:07 -0400
commite02119d5a7b4396c5a872582fddc8bd6d305a70a (patch)
tree825efe2a79dbca8d61256183f3526a5b5dc40dc6 /fs/btrfs/file.c
parenta1b32a5932cfac7c38b442582285f3da2a09dfd8 (diff)
Btrfs: Add a write ahead tree log to optimize synchronous operations
File syncs and directory syncs are optimized by copying their items into a special (copy-on-write) log tree. There is one log tree per subvolume and the btrfs super block points to a tree of log tree roots. After a crash, items are copied out of the log tree and back into the subvolume. See tree-log.c for all the details. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e9e86fbaa243..84ecf3ab8511 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -36,6 +36,8 @@
36#include "btrfs_inode.h" 36#include "btrfs_inode.h"
37#include "ioctl.h" 37#include "ioctl.h"
38#include "print-tree.h" 38#include "print-tree.h"
39#include "tree-log.h"
40#include "locking.h"
39#include "compat.h" 41#include "compat.h"
40 42
41 43
@@ -988,10 +990,27 @@ out_nolock:
988 *ppos = pos; 990 *ppos = pos;
989 991
990 if (num_written > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { 992 if (num_written > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
991 err = sync_page_range(inode, inode->i_mapping, 993 struct btrfs_trans_handle *trans;
992 start_pos, num_written); 994
995 err = btrfs_fdatawrite_range(inode->i_mapping, start_pos,
996 start_pos + num_written -1,
997 WB_SYNC_NONE);
998 if (err < 0)
999 num_written = err;
1000
1001 err = btrfs_wait_on_page_writeback_range(inode->i_mapping,
1002 start_pos, start_pos + num_written - 1);
993 if (err < 0) 1003 if (err < 0)
994 num_written = err; 1004 num_written = err;
1005
1006 trans = btrfs_start_transaction(root, 1);
1007 ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
1008 if (ret == 0) {
1009 btrfs_sync_log(trans, root);
1010 btrfs_end_transaction(trans, root);
1011 } else {
1012 btrfs_commit_transaction(trans, root);
1013 }
995 } else if (num_written > 0 && (file->f_flags & O_DIRECT)) { 1014 } else if (num_written > 0 && (file->f_flags & O_DIRECT)) {
996#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) 1015#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
997 do_sync_file_range(file, start_pos, 1016 do_sync_file_range(file, start_pos,
@@ -1019,8 +1038,7 @@ int btrfs_release_file(struct inode * inode, struct file * filp)
1019 return 0; 1038 return 0;
1020} 1039}
1021 1040
1022static int btrfs_sync_file(struct file *file, 1041int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
1023 struct dentry *dentry, int datasync)
1024{ 1042{
1025 struct inode *inode = dentry->d_inode; 1043 struct inode *inode = dentry->d_inode;
1026 struct btrfs_root *root = BTRFS_I(inode)->root; 1044 struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -1043,6 +1061,8 @@ static int btrfs_sync_file(struct file *file,
1043 } 1061 }
1044 mutex_unlock(&root->fs_info->trans_mutex); 1062 mutex_unlock(&root->fs_info->trans_mutex);
1045 1063
1064 filemap_fdatawait(inode->i_mapping);
1065
1046 /* 1066 /*
1047 * ok we haven't committed the transaction yet, lets do a commit 1067 * ok we haven't committed the transaction yet, lets do a commit
1048 */ 1068 */
@@ -1054,7 +1074,16 @@ static int btrfs_sync_file(struct file *file,
1054 ret = -ENOMEM; 1074 ret = -ENOMEM;
1055 goto out; 1075 goto out;
1056 } 1076 }
1057 ret = btrfs_commit_transaction(trans, root); 1077
1078 ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
1079 if (ret < 0)
1080 goto out;
1081 if (ret > 0) {
1082 ret = btrfs_commit_transaction(trans, root);
1083 } else {
1084 btrfs_sync_log(trans, root);
1085 ret = btrfs_end_transaction(trans, root);
1086 }
1058out: 1087out:
1059 return ret > 0 ? EIO : ret; 1088 return ret > 0 ? EIO : ret;
1060} 1089}