diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index e5ed56729607..f14b17432117 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -196,6 +196,9 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
196 | entry->file_offset = file_offset; | 196 | entry->file_offset = file_offset; |
197 | entry->start = start; | 197 | entry->start = start; |
198 | entry->len = len; | 198 | entry->len = len; |
199 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) && | ||
200 | !(type == BTRFS_ORDERED_NOCOW)) | ||
201 | entry->csum_bytes_left = disk_len; | ||
199 | entry->disk_len = disk_len; | 202 | entry->disk_len = disk_len; |
200 | entry->bytes_left = len; | 203 | entry->bytes_left = len; |
201 | entry->inode = igrab(inode); | 204 | entry->inode = igrab(inode); |
@@ -213,6 +216,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
213 | INIT_LIST_HEAD(&entry->root_extent_list); | 216 | INIT_LIST_HEAD(&entry->root_extent_list); |
214 | INIT_LIST_HEAD(&entry->work_list); | 217 | INIT_LIST_HEAD(&entry->work_list); |
215 | init_completion(&entry->completion); | 218 | init_completion(&entry->completion); |
219 | INIT_LIST_HEAD(&entry->log_list); | ||
216 | 220 | ||
217 | trace_btrfs_ordered_extent_add(inode, entry); | 221 | trace_btrfs_ordered_extent_add(inode, entry); |
218 | 222 | ||
@@ -270,6 +274,10 @@ void btrfs_add_ordered_sum(struct inode *inode, | |||
270 | tree = &BTRFS_I(inode)->ordered_tree; | 274 | tree = &BTRFS_I(inode)->ordered_tree; |
271 | spin_lock_irq(&tree->lock); | 275 | spin_lock_irq(&tree->lock); |
272 | list_add_tail(&sum->list, &entry->list); | 276 | list_add_tail(&sum->list, &entry->list); |
277 | WARN_ON(entry->csum_bytes_left < sum->len); | ||
278 | entry->csum_bytes_left -= sum->len; | ||
279 | if (entry->csum_bytes_left == 0) | ||
280 | wake_up(&entry->wait); | ||
273 | spin_unlock_irq(&tree->lock); | 281 | spin_unlock_irq(&tree->lock); |
274 | } | 282 | } |
275 | 283 | ||
@@ -405,6 +413,66 @@ out: | |||
405 | return ret == 0; | 413 | return ret == 0; |
406 | } | 414 | } |
407 | 415 | ||
416 | /* Needs to either be called under a log transaction or the log_mutex */ | ||
417 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode) | ||
418 | { | ||
419 | struct btrfs_ordered_inode_tree *tree; | ||
420 | struct btrfs_ordered_extent *ordered; | ||
421 | struct rb_node *n; | ||
422 | int index = log->log_transid % 2; | ||
423 | |||
424 | tree = &BTRFS_I(inode)->ordered_tree; | ||
425 | spin_lock_irq(&tree->lock); | ||
426 | for (n = rb_first(&tree->tree); n; n = rb_next(n)) { | ||
427 | ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); | ||
428 | spin_lock(&log->log_extents_lock[index]); | ||
429 | if (list_empty(&ordered->log_list)) { | ||
430 | list_add_tail(&ordered->log_list, &log->logged_list[index]); | ||
431 | atomic_inc(&ordered->refs); | ||
432 | } | ||
433 | spin_unlock(&log->log_extents_lock[index]); | ||
434 | } | ||
435 | spin_unlock_irq(&tree->lock); | ||
436 | } | ||
437 | |||
438 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) | ||
439 | { | ||
440 | struct btrfs_ordered_extent *ordered; | ||
441 | int index = transid % 2; | ||
442 | |||
443 | spin_lock_irq(&log->log_extents_lock[index]); | ||
444 | while (!list_empty(&log->logged_list[index])) { | ||
445 | ordered = list_first_entry(&log->logged_list[index], | ||
446 | struct btrfs_ordered_extent, | ||
447 | log_list); | ||
448 | list_del_init(&ordered->log_list); | ||
449 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
450 | wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE, | ||
451 | &ordered->flags)); | ||
452 | btrfs_put_ordered_extent(ordered); | ||
453 | spin_lock_irq(&log->log_extents_lock[index]); | ||
454 | } | ||
455 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
456 | } | ||
457 | |||
458 | void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid) | ||
459 | { | ||
460 | struct btrfs_ordered_extent *ordered; | ||
461 | int index = transid % 2; | ||
462 | |||
463 | spin_lock_irq(&log->log_extents_lock[index]); | ||
464 | while (!list_empty(&log->logged_list[index])) { | ||
465 | ordered = list_first_entry(&log->logged_list[index], | ||
466 | struct btrfs_ordered_extent, | ||
467 | log_list); | ||
468 | list_del_init(&ordered->log_list); | ||
469 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
470 | btrfs_put_ordered_extent(ordered); | ||
471 | spin_lock_irq(&log->log_extents_lock[index]); | ||
472 | } | ||
473 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
474 | } | ||
475 | |||
408 | /* | 476 | /* |
409 | * used to drop a reference on an ordered extent. This will free | 477 | * used to drop a reference on an ordered extent. This will free |
410 | * the extent if the last reference is dropped | 478 | * the extent if the last reference is dropped |