diff options
author | Josef Bacik <josef@redhat.com> | 2011-04-06 13:05:22 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-04-08 13:00:27 -0400 |
commit | be1a12a0dfed06cf1e62e35bf91620dc610a451a (patch) | |
tree | f2cd5976aae8a466b926f9fd7c0e10a082b5a11a /fs/btrfs/file.c | |
parent | c9ddec74aa950a220cc4caa5215cfc5d886050b7 (diff) |
Btrfs: deal with the case that we run out of space in the cache
Currently we don't handle running out of space in the cache, so to fix this we
keep track of how far in the cache we are. Then we only dirty the pages if we
successfully modify all of them, otherwise if we have an error or run out of
space we can just drop them and not worry about the vm writing them out.
Thanks,
Tested-by Johannes Hirte <johannes.hirte@fem.tu-ilmenau.de>
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e621ea54a3fd..75899a01dded 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
104 | /* | 104 | /* |
105 | * unlocks pages after btrfs_file_write is done with them | 105 | * unlocks pages after btrfs_file_write is done with them |
106 | */ | 106 | */ |
107 | static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) | 107 | void btrfs_drop_pages(struct page **pages, size_t num_pages) |
108 | { | 108 | { |
109 | size_t i; | 109 | size_t i; |
110 | for (i = 0; i < num_pages; i++) { | 110 | for (i = 0; i < num_pages; i++) { |
@@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) | |||
127 | * this also makes the decision about creating an inline extent vs | 127 | * this also makes the decision about creating an inline extent vs |
128 | * doing real data extents, marking pages dirty and delalloc as required. | 128 | * doing real data extents, marking pages dirty and delalloc as required. |
129 | */ | 129 | */ |
130 | static noinline int dirty_and_release_pages(struct btrfs_root *root, | 130 | int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, |
131 | struct file *file, | 131 | struct page **pages, size_t num_pages, |
132 | struct page **pages, | 132 | loff_t pos, size_t write_bytes, |
133 | size_t num_pages, | 133 | struct extent_state **cached) |
134 | loff_t pos, | ||
135 | size_t write_bytes) | ||
136 | { | 134 | { |
137 | int err = 0; | 135 | int err = 0; |
138 | int i; | 136 | int i; |
139 | struct inode *inode = fdentry(file)->d_inode; | ||
140 | u64 num_bytes; | 137 | u64 num_bytes; |
141 | u64 start_pos; | 138 | u64 start_pos; |
142 | u64 end_of_last_block; | 139 | u64 end_of_last_block; |
@@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struct btrfs_root *root, | |||
149 | 146 | ||
150 | end_of_last_block = start_pos + num_bytes - 1; | 147 | end_of_last_block = start_pos + num_bytes - 1; |
151 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, | 148 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, |
152 | NULL); | 149 | cached); |
153 | if (err) | 150 | if (err) |
154 | return err; | 151 | return err; |
155 | 152 | ||
@@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
992 | } | 989 | } |
993 | 990 | ||
994 | if (copied > 0) { | 991 | if (copied > 0) { |
995 | ret = dirty_and_release_pages(root, file, pages, | 992 | ret = btrfs_dirty_pages(root, inode, pages, |
996 | dirty_pages, pos, | 993 | dirty_pages, pos, copied, |
997 | copied); | 994 | NULL); |
998 | if (ret) { | 995 | if (ret) { |
999 | btrfs_delalloc_release_space(inode, | 996 | btrfs_delalloc_release_space(inode, |
1000 | dirty_pages << PAGE_CACHE_SHIFT); | 997 | dirty_pages << PAGE_CACHE_SHIFT); |