aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-27 16:49:44 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-27 16:49:44 -0400
commitb888db2bd7b67f190b32934e6a86181f262ac3ec (patch)
tree7eb4472c65b6a634db6be689eedca09f09a40cd5 /fs/btrfs/file.c
parenta52d9a8033c454cd9b4697cfafb467509fc1693f (diff)
Btrfs: Add delayed allocation to the extent based page tree code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c50
1 files changed, 21 insertions, 29 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 71a481894ab6..d3d39e4a2797 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -143,7 +143,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
143 struct inode *inode = file->f_path.dentry->d_inode; 143 struct inode *inode = file->f_path.dentry->d_inode;
144 struct extent_map *em; 144 struct extent_map *em;
145 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 145 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
146 struct btrfs_key ins;
147 u64 hint_block; 146 u64 hint_block;
148 u64 num_blocks; 147 u64 num_blocks;
149 u64 start_pos; 148 u64 start_pos;
@@ -162,6 +161,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
162 inode->i_blkbits; 161 inode->i_blkbits;
163 162
164 end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1; 163 end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1;
164 lock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS);
165 mutex_lock(&root->fs_info->fs_mutex); 165 mutex_lock(&root->fs_info->fs_mutex);
166 trans = btrfs_start_transaction(root, 1); 166 trans = btrfs_start_transaction(root, 1);
167 if (!trans) { 167 if (!trans) {
@@ -179,16 +179,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
179 179
180 /* FIXME...EIEIO, ENOSPC and more */ 180 /* FIXME...EIEIO, ENOSPC and more */
181 181
182 /* step one, delete the existing extents in this range */
183 /* FIXME blocksize != pagesize */
184 if (start_pos < inode->i_size) {
185 err = btrfs_drop_extents(trans, root, inode,
186 start_pos, (pos + write_bytes + root->blocksize -1) &
187 ~((u64)root->blocksize - 1), &hint_block);
188 if (err)
189 goto failed;
190 }
191
192 /* insert any holes we need to create */ 182 /* insert any holes we need to create */
193 if (inode->i_size < start_pos) { 183 if (inode->i_size < start_pos) {
194 u64 last_pos_in_file; 184 u64 last_pos_in_file;
@@ -213,29 +203,28 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
213 */ 203 */
214 if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size || 204 if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size ||
215 pos + write_bytes - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { 205 pos + write_bytes - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) {
216 err = btrfs_alloc_extent(trans, root, inode->i_ino, 206 u64 last_end;
217 num_blocks, 0, hint_block, (u64)-1,
218 &ins, 1);
219 BUG_ON(err);
220 err = btrfs_insert_file_extent(trans, root, inode->i_ino,
221 start_pos, ins.objectid, ins.offset,
222 ins.offset);
223 BUG_ON(err);
224 em->start = start_pos;
225 em->end = end_of_last_block;
226 em->block_start = ins.objectid << inode->i_blkbits;
227 em->block_end = em->block_start +
228 (ins.offset << inode->i_blkbits) - 1;
229 set_extent_dirty(em_tree, start_pos, end_of_last_block,
230 GFP_NOFS);
231 err = add_extent_mapping(em_tree, em);
232 for (i = 0; i < num_pages; i++) { 207 for (i = 0; i < num_pages; i++) {
233 struct page *p = pages[i]; 208 struct page *p = pages[i];
234 SetPageUptodate(p); 209 SetPageUptodate(p);
235 __set_page_dirty_nobuffers(p); 210 set_page_dirty(p);
236 } 211 }
212 last_end = pages[num_pages -1]->index << PAGE_CACHE_SHIFT;
213 last_end += PAGE_CACHE_SIZE - 1;
214 set_extent_delalloc(em_tree, start_pos, end_of_last_block,
215 GFP_NOFS);
237 } else { 216 } else {
238 struct page *p = pages[0]; 217 struct page *p = pages[0];
218 /* step one, delete the existing extents in this range */
219 /* FIXME blocksize != pagesize */
220 if (start_pos < inode->i_size) {
221 err = btrfs_drop_extents(trans, root, inode, start_pos,
222 (pos + write_bytes + root->blocksize -1) &
223 ~((u64)root->blocksize - 1), &hint_block);
224 if (err)
225 goto failed;
226 }
227
239 err = insert_inline_extent(trans, root, inode, start_pos, 228 err = insert_inline_extent(trans, root, inode, start_pos,
240 end_pos - start_pos, p, 0); 229 end_pos - start_pos, p, 0);
241 BUG_ON(err); 230 BUG_ON(err);
@@ -253,6 +242,7 @@ failed:
253 err = btrfs_end_transaction(trans, root); 242 err = btrfs_end_transaction(trans, root);
254out_unlock: 243out_unlock:
255 mutex_unlock(&root->fs_info->fs_mutex); 244 mutex_unlock(&root->fs_info->fs_mutex);
245 unlock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS);
256 free_extent_map(em); 246 free_extent_map(em);
257 return err; 247 return err;
258} 248}
@@ -531,7 +521,7 @@ static int prepare_pages(struct btrfs_root *root,
531 u64 num_blocks; 521 u64 num_blocks;
532 u64 start_pos; 522 u64 start_pos;
533 523
534 start_pos = pos & ~((u64)PAGE_CACHE_SIZE - 1); 524 start_pos = pos & ~((u64)root->blocksize - 1);
535 num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> 525 num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >>
536 inode->i_blkbits; 526 inode->i_blkbits;
537 527
@@ -548,8 +538,10 @@ static int prepare_pages(struct btrfs_root *root,
548 if (!PagePrivate(pages[i])) { 538 if (!PagePrivate(pages[i])) {
549 SetPagePrivate(pages[i]); 539 SetPagePrivate(pages[i]);
550 set_page_private(pages[i], 1); 540 set_page_private(pages[i], 1);
541 WARN_ON(!pages[i]->mapping->a_ops->invalidatepage);
551 page_cache_get(pages[i]); 542 page_cache_get(pages[i]);
552 } 543 }
544 WARN_ON(!PageLocked(pages[i]));
553 } 545 }
554 return 0; 546 return 0;
555} 547}