summaryrefslogtreecommitdiff
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-10 10:23:21 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commit16432985920f3c45af82da214e2498f3e2f9066b (patch)
treece05f57eefb1a6f5952c53205ec8a07e93d03b3c /fs/btrfs/file.c
parent85d824c4a407ba8dbd897f4e05bbe21bf24cc071 (diff)
downloadlwn-16432985920f3c45af82da214e2498f3e2f9066b.tar.gz
lwn-16432985920f3c45af82da214e2498f3e2f9066b.zip
Btrfs: Add O_DIRECT read and write (writes == buffered + cache flush)
This adds basic O_DIRECT read and write support. In the write case, we just do a normal buffered write followed by a cache flush. O_DIRECT + O_SYNC are required to trigger metadata syncs. In the read case, there is a basic btrfs_get_block call for use by the generic O_DIRECT code. This does honor multi-volume mapping rules but it skips all checksumming. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 5fa450452f9b..5b9386452218 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -796,8 +796,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
PAGE_CACHE_SIZE / (sizeof(struct page *)));
pinned[0] = NULL;
pinned[1] = NULL;
- if (file->f_flags & O_DIRECT)
- return -EINVAL;
pos = *ppos;
start_pos = pos;
@@ -909,6 +907,15 @@ out_nolock:
start_pos, num_written);
if (err < 0)
num_written = err;
+ } else if (num_written > 0 && (file->f_flags & O_DIRECT)) {
+ do_sync_mapping_range(inode->i_mapping, start_pos,
+ start_pos + num_written - 1,
+ SYNC_FILE_RANGE_WRITE |
+ SYNC_FILE_RANGE_WAIT_AFTER);
+
+ invalidate_mapping_pages(inode->i_mapping,
+ start_pos >> PAGE_CACHE_SHIFT,
+ (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT);
}
current->backing_dev_info = NULL;
return num_written ? num_written : err;