summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-09-11 15:53:12 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:07 -0400
commit49eb7e46d47ea72a9bd2a5f8cedb04f5159cc277 (patch)
treec3d05588c3cf73453673206214fadedc07bd79d7
parent98509cfc5a6857bddcfe4b19a9539726655ec9bd (diff)
downloadop-kernel-dev-49eb7e46d47ea72a9bd2a5f8cedb04f5159cc277.zip
op-kernel-dev-49eb7e46d47ea72a9bd2a5f8cedb04f5159cc277.tar.gz
Btrfs: Dir fsync optimizations
Drop i_mutex during the commit Don't bother doing the fsync at all unless the dir is marked as dirtied and needing fsync in this transaction. For directories, this means that someone has unlinked a file from the dir without fsyncing the file. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/btrfs_inode.h3
-rw-r--r--fs/btrfs/file.c19
-rw-r--r--fs/btrfs/inode.c5
-rw-r--r--fs/btrfs/tree-log.c8
4 files changed, 29 insertions, 6 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index fcc8cf2..0577fda 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -56,6 +56,9 @@ struct btrfs_inode {
* transid that last logged this inode
*/
u64 logged_trans;
+
+ /* trans that last made a change that should be fully fsync'd */
+ u64 log_dirty_trans;
u64 delalloc_bytes;
u64 disk_i_size;
u32 flags;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 84ecf3a..58b329d 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1061,7 +1061,9 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
}
mutex_unlock(&root->fs_info->trans_mutex);
+ root->fs_info->tree_log_batch++;
filemap_fdatawait(inode->i_mapping);
+ root->fs_info->tree_log_batch++;
/*
* ok we haven't committed the transaction yet, lets do a commit
@@ -1076,14 +1078,29 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
}
ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
- if (ret < 0)
+ if (ret < 0) {
goto out;
+ }
+
+ /* we've logged all the items and now have a consistent
+ * version of the file in the log. It is possible that
+ * someone will come in and modify the file, but that's
+ * fine because the log is consistent on disk, and we
+ * have references to all of the file's extents
+ *
+ * It is possible that someone will come in and log the
+ * file again, but that will end up using the synchronization
+ * inside btrfs_sync_log to keep things safe.
+ */
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+
if (ret > 0) {
ret = btrfs_commit_transaction(trans, root);
} else {
btrfs_sync_log(trans, root);
ret = btrfs_end_transaction(trans, root);
}
+ mutex_lock(&file->f_dentry->d_inode->i_mutex);
out:
return ret > 0 ? EIO : ret;
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 24b7e97..12c1c05 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1187,7 +1187,9 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
inode, dir->i_ino);
- BUG_ON(ret);
+ BUG_ON(ret != 0 && ret != -ENOENT);
+ if (ret != -ENOENT)
+ BTRFS_I(dir)->log_dirty_trans = trans->transid;
ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len,
dir, index);
@@ -1790,6 +1792,7 @@ static noinline void init_btrfs_i(struct inode *inode)
bi->disk_i_size = 0;
bi->flags = 0;
bi->index_cnt = (u64)-1;
+ bi->log_dirty_trans = 0;
extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
extent_io_tree_init(&BTRFS_I(inode)->io_tree,
inode->i_mapping, GFP_NOFS);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 3f4b139..5d49a70 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1973,10 +1973,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
atomic_set(&log->fs_info->tree_log_commit, 1);
while(1) {
+ batch = log->fs_info->tree_log_batch;
mutex_unlock(&log->fs_info->tree_log_mutex);
schedule_timeout_uninterruptible(1);
mutex_lock(&log->fs_info->tree_log_mutex);
- batch = log->fs_info->tree_log_batch;
while(atomic_read(&log->fs_info->tree_log_writers)) {
DEFINE_WAIT(wait);
@@ -2189,8 +2189,6 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
mutex_unlock(&BTRFS_I(inode)->log_mutex);
end_log_trans(root);
- if (ret == 0 || ret == -ENOENT)
- return 0;
return ret;
}
@@ -2620,9 +2618,11 @@ static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
else
break;
}
- if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
+ if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode) &&
+ BTRFS_I(inode)->log_dirty_trans >= trans->transid) {
btrfs_release_path(root, path);
btrfs_release_path(log, dst_path);
+ BTRFS_I(inode)->log_dirty_trans = 0;
ret = log_directory_changes(trans, root, inode, path, dst_path);
BUG_ON(ret);
}
OpenPOWER on IntegriCloud