diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-08-27 16:49:44 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-08-27 16:49:44 -0400 |
commit | b888db2bd7b67f190b32934e6a86181f262ac3ec (patch) | |
tree | 7eb4472c65b6a634db6be689eedca09f09a40cd5 /fs/btrfs/file.c | |
parent | a52d9a8033c454cd9b4697cfafb467509fc1693f (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.c | 50 |
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); |
254 | out_unlock: | 243 | out_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 | } |