diff options
Diffstat (limited to 'fs')
76 files changed, 1171 insertions, 725 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index f0d268b97d19..a439548de785 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -70,9 +70,13 @@ struct autofs_info { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */ | 72 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */ |
73 | #define AUTOFS_INF_NO_RCU (1<<1) /* the dentry is being considered | 73 | #define AUTOFS_INF_WANT_EXPIRE (1<<1) /* the dentry is being considered |
74 | * for expiry, so RCU_walk is | 74 | * for expiry, so RCU_walk is |
75 | * not permitted | 75 | * not permitted. If it progresses to |
76 | * actual expiry attempt, the flag is | ||
77 | * not cleared when EXPIRING is set - | ||
78 | * in that case it gets cleared only | ||
79 | * when it comes to clearing EXPIRING. | ||
76 | */ | 80 | */ |
77 | #define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */ | 81 | #define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */ |
78 | 82 | ||
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 9510d8d2e9cd..b493909e7492 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -316,19 +316,17 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, | |||
316 | if (ino->flags & AUTOFS_INF_PENDING) | 316 | if (ino->flags & AUTOFS_INF_PENDING) |
317 | goto out; | 317 | goto out; |
318 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | 318 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { |
319 | ino->flags |= AUTOFS_INF_NO_RCU; | 319 | ino->flags |= AUTOFS_INF_WANT_EXPIRE; |
320 | spin_unlock(&sbi->fs_lock); | 320 | spin_unlock(&sbi->fs_lock); |
321 | synchronize_rcu(); | 321 | synchronize_rcu(); |
322 | spin_lock(&sbi->fs_lock); | 322 | spin_lock(&sbi->fs_lock); |
323 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | 323 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { |
324 | ino->flags |= AUTOFS_INF_EXPIRING; | 324 | ino->flags |= AUTOFS_INF_EXPIRING; |
325 | smp_mb(); | ||
326 | ino->flags &= ~AUTOFS_INF_NO_RCU; | ||
327 | init_completion(&ino->expire_complete); | 325 | init_completion(&ino->expire_complete); |
328 | spin_unlock(&sbi->fs_lock); | 326 | spin_unlock(&sbi->fs_lock); |
329 | return root; | 327 | return root; |
330 | } | 328 | } |
331 | ino->flags &= ~AUTOFS_INF_NO_RCU; | 329 | ino->flags &= ~AUTOFS_INF_WANT_EXPIRE; |
332 | } | 330 | } |
333 | out: | 331 | out: |
334 | spin_unlock(&sbi->fs_lock); | 332 | spin_unlock(&sbi->fs_lock); |
@@ -446,7 +444,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
446 | while ((dentry = get_next_positive_subdir(dentry, root))) { | 444 | while ((dentry = get_next_positive_subdir(dentry, root))) { |
447 | spin_lock(&sbi->fs_lock); | 445 | spin_lock(&sbi->fs_lock); |
448 | ino = autofs4_dentry_ino(dentry); | 446 | ino = autofs4_dentry_ino(dentry); |
449 | if (ino->flags & AUTOFS_INF_NO_RCU) | 447 | if (ino->flags & AUTOFS_INF_WANT_EXPIRE) |
450 | expired = NULL; | 448 | expired = NULL; |
451 | else | 449 | else |
452 | expired = should_expire(dentry, mnt, timeout, how); | 450 | expired = should_expire(dentry, mnt, timeout, how); |
@@ -455,7 +453,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
455 | continue; | 453 | continue; |
456 | } | 454 | } |
457 | ino = autofs4_dentry_ino(expired); | 455 | ino = autofs4_dentry_ino(expired); |
458 | ino->flags |= AUTOFS_INF_NO_RCU; | 456 | ino->flags |= AUTOFS_INF_WANT_EXPIRE; |
459 | spin_unlock(&sbi->fs_lock); | 457 | spin_unlock(&sbi->fs_lock); |
460 | synchronize_rcu(); | 458 | synchronize_rcu(); |
461 | spin_lock(&sbi->fs_lock); | 459 | spin_lock(&sbi->fs_lock); |
@@ -465,7 +463,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
465 | goto found; | 463 | goto found; |
466 | } | 464 | } |
467 | 465 | ||
468 | ino->flags &= ~AUTOFS_INF_NO_RCU; | 466 | ino->flags &= ~AUTOFS_INF_WANT_EXPIRE; |
469 | if (expired != dentry) | 467 | if (expired != dentry) |
470 | dput(expired); | 468 | dput(expired); |
471 | spin_unlock(&sbi->fs_lock); | 469 | spin_unlock(&sbi->fs_lock); |
@@ -475,17 +473,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
475 | found: | 473 | found: |
476 | pr_debug("returning %p %pd\n", expired, expired); | 474 | pr_debug("returning %p %pd\n", expired, expired); |
477 | ino->flags |= AUTOFS_INF_EXPIRING; | 475 | ino->flags |= AUTOFS_INF_EXPIRING; |
478 | smp_mb(); | ||
479 | ino->flags &= ~AUTOFS_INF_NO_RCU; | ||
480 | init_completion(&ino->expire_complete); | 476 | init_completion(&ino->expire_complete); |
481 | spin_unlock(&sbi->fs_lock); | 477 | spin_unlock(&sbi->fs_lock); |
482 | spin_lock(&sbi->lookup_lock); | ||
483 | spin_lock(&expired->d_parent->d_lock); | ||
484 | spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED); | ||
485 | list_move(&expired->d_parent->d_subdirs, &expired->d_child); | ||
486 | spin_unlock(&expired->d_lock); | ||
487 | spin_unlock(&expired->d_parent->d_lock); | ||
488 | spin_unlock(&sbi->lookup_lock); | ||
489 | return expired; | 478 | return expired; |
490 | } | 479 | } |
491 | 480 | ||
@@ -496,7 +485,7 @@ int autofs4_expire_wait(struct dentry *dentry, int rcu_walk) | |||
496 | int status; | 485 | int status; |
497 | 486 | ||
498 | /* Block on any pending expire */ | 487 | /* Block on any pending expire */ |
499 | if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))) | 488 | if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE)) |
500 | return 0; | 489 | return 0; |
501 | if (rcu_walk) | 490 | if (rcu_walk) |
502 | return -ECHILD; | 491 | return -ECHILD; |
@@ -554,7 +543,7 @@ int autofs4_expire_run(struct super_block *sb, | |||
554 | ino = autofs4_dentry_ino(dentry); | 543 | ino = autofs4_dentry_ino(dentry); |
555 | /* avoid rapid-fire expire attempts if expiry fails */ | 544 | /* avoid rapid-fire expire attempts if expiry fails */ |
556 | ino->last_used = now; | 545 | ino->last_used = now; |
557 | ino->flags &= ~AUTOFS_INF_EXPIRING; | 546 | ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE); |
558 | complete_all(&ino->expire_complete); | 547 | complete_all(&ino->expire_complete); |
559 | spin_unlock(&sbi->fs_lock); | 548 | spin_unlock(&sbi->fs_lock); |
560 | 549 | ||
@@ -583,7 +572,7 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
583 | spin_lock(&sbi->fs_lock); | 572 | spin_lock(&sbi->fs_lock); |
584 | /* avoid rapid-fire expire attempts if expiry fails */ | 573 | /* avoid rapid-fire expire attempts if expiry fails */ |
585 | ino->last_used = now; | 574 | ino->last_used = now; |
586 | ino->flags &= ~AUTOFS_INF_EXPIRING; | 575 | ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE); |
587 | complete_all(&ino->expire_complete); | 576 | complete_all(&ino->expire_complete); |
588 | spin_unlock(&sbi->fs_lock); | 577 | spin_unlock(&sbi->fs_lock); |
589 | dput(dentry); | 578 | dput(dentry); |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 78bd80298528..3767f6641af1 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -458,7 +458,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) | |||
458 | */ | 458 | */ |
459 | struct inode *inode; | 459 | struct inode *inode; |
460 | 460 | ||
461 | if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)) | 461 | if (ino->flags & AUTOFS_INF_WANT_EXPIRE) |
462 | return 0; | 462 | return 0; |
463 | if (d_mountpoint(dentry)) | 463 | if (d_mountpoint(dentry)) |
464 | return 0; | 464 | return 0; |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 0146d911f468..631f1554c87b 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -66,11 +66,12 @@ static int autofs4_write(struct autofs_sb_info *sbi, | |||
66 | set_fs(KERNEL_DS); | 66 | set_fs(KERNEL_DS); |
67 | 67 | ||
68 | mutex_lock(&sbi->pipe_mutex); | 68 | mutex_lock(&sbi->pipe_mutex); |
69 | wr = __vfs_write(file, data, bytes, &file->f_pos); | 69 | while (bytes) { |
70 | while (bytes && wr) { | 70 | wr = __vfs_write(file, data, bytes, &file->f_pos); |
71 | if (wr <= 0) | ||
72 | break; | ||
71 | data += wr; | 73 | data += wr; |
72 | bytes -= wr; | 74 | bytes -= wr; |
73 | wr = __vfs_write(file, data, bytes, &file->f_pos); | ||
74 | } | 75 | } |
75 | mutex_unlock(&sbi->pipe_mutex); | 76 | mutex_unlock(&sbi->pipe_mutex); |
76 | 77 | ||
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index b677a6ea6001..7706c8dc5fa6 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c | |||
@@ -2645,7 +2645,7 @@ static void btrfsic_dump_tree_sub(const struct btrfsic_state *state, | |||
2645 | * This algorithm is recursive because the amount of used stack space | 2645 | * This algorithm is recursive because the amount of used stack space |
2646 | * is very small and the max recursion depth is limited. | 2646 | * is very small and the max recursion depth is limited. |
2647 | */ | 2647 | */ |
2648 | indent_add = sprintf(buf, "%c-%llu(%s/%llu/%d)", | 2648 | indent_add = sprintf(buf, "%c-%llu(%s/%llu/%u)", |
2649 | btrfsic_get_block_type(state, block), | 2649 | btrfsic_get_block_type(state, block), |
2650 | block->logical_bytenr, block->dev_state->name, | 2650 | block->logical_bytenr, block->dev_state->name, |
2651 | block->dev_bytenr, block->mirror_num); | 2651 | block->dev_bytenr, block->mirror_num); |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 427c36b430a6..a85cf7d23309 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1373,7 +1373,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path, | |||
1373 | 1373 | ||
1374 | if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { | 1374 | if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { |
1375 | BUG_ON(tm->slot != 0); | 1375 | BUG_ON(tm->slot != 0); |
1376 | eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start); | 1376 | eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start, |
1377 | eb->len); | ||
1377 | if (!eb_rewin) { | 1378 | if (!eb_rewin) { |
1378 | btrfs_tree_read_unlock_blocking(eb); | 1379 | btrfs_tree_read_unlock_blocking(eb); |
1379 | free_extent_buffer(eb); | 1380 | free_extent_buffer(eb); |
@@ -1454,7 +1455,8 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
1454 | } else if (old_root) { | 1455 | } else if (old_root) { |
1455 | btrfs_tree_read_unlock(eb_root); | 1456 | btrfs_tree_read_unlock(eb_root); |
1456 | free_extent_buffer(eb_root); | 1457 | free_extent_buffer(eb_root); |
1457 | eb = alloc_dummy_extent_buffer(root->fs_info, logical); | 1458 | eb = alloc_dummy_extent_buffer(root->fs_info, logical, |
1459 | root->nodesize); | ||
1458 | } else { | 1460 | } else { |
1459 | btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK); | 1461 | btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK); |
1460 | eb = btrfs_clone_extent_buffer(eb_root); | 1462 | eb = btrfs_clone_extent_buffer(eb_root); |
@@ -1552,6 +1554,7 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
1552 | trans->transid, root->fs_info->generation); | 1554 | trans->transid, root->fs_info->generation); |
1553 | 1555 | ||
1554 | if (!should_cow_block(trans, root, buf)) { | 1556 | if (!should_cow_block(trans, root, buf)) { |
1557 | trans->dirty = true; | ||
1555 | *cow_ret = buf; | 1558 | *cow_ret = buf; |
1556 | return 0; | 1559 | return 0; |
1557 | } | 1560 | } |
@@ -1783,10 +1786,12 @@ static noinline int generic_bin_search(struct extent_buffer *eb, | |||
1783 | if (!err) { | 1786 | if (!err) { |
1784 | tmp = (struct btrfs_disk_key *)(kaddr + offset - | 1787 | tmp = (struct btrfs_disk_key *)(kaddr + offset - |
1785 | map_start); | 1788 | map_start); |
1786 | } else { | 1789 | } else if (err == 1) { |
1787 | read_extent_buffer(eb, &unaligned, | 1790 | read_extent_buffer(eb, &unaligned, |
1788 | offset, sizeof(unaligned)); | 1791 | offset, sizeof(unaligned)); |
1789 | tmp = &unaligned; | 1792 | tmp = &unaligned; |
1793 | } else { | ||
1794 | return err; | ||
1790 | } | 1795 | } |
1791 | 1796 | ||
1792 | } else { | 1797 | } else { |
@@ -2510,6 +2515,8 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
2510 | if (!btrfs_buffer_uptodate(tmp, 0, 0)) | 2515 | if (!btrfs_buffer_uptodate(tmp, 0, 0)) |
2511 | ret = -EIO; | 2516 | ret = -EIO; |
2512 | free_extent_buffer(tmp); | 2517 | free_extent_buffer(tmp); |
2518 | } else { | ||
2519 | ret = PTR_ERR(tmp); | ||
2513 | } | 2520 | } |
2514 | return ret; | 2521 | return ret; |
2515 | } | 2522 | } |
@@ -2773,8 +2780,10 @@ again: | |||
2773 | * then we don't want to set the path blocking, | 2780 | * then we don't want to set the path blocking, |
2774 | * so we test it here | 2781 | * so we test it here |
2775 | */ | 2782 | */ |
2776 | if (!should_cow_block(trans, root, b)) | 2783 | if (!should_cow_block(trans, root, b)) { |
2784 | trans->dirty = true; | ||
2777 | goto cow_done; | 2785 | goto cow_done; |
2786 | } | ||
2778 | 2787 | ||
2779 | /* | 2788 | /* |
2780 | * must have write locks on this node and the | 2789 | * must have write locks on this node and the |
@@ -2823,6 +2832,8 @@ cow_done: | |||
2823 | } | 2832 | } |
2824 | 2833 | ||
2825 | ret = key_search(b, key, level, &prev_cmp, &slot); | 2834 | ret = key_search(b, key, level, &prev_cmp, &slot); |
2835 | if (ret < 0) | ||
2836 | goto done; | ||
2826 | 2837 | ||
2827 | if (level != 0) { | 2838 | if (level != 0) { |
2828 | int dec = 0; | 2839 | int dec = 0; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 101c3cfd3f7c..4274a7bfdaed 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2518,7 +2518,7 @@ void btrfs_put_block_group(struct btrfs_block_group_cache *cache); | |||
2518 | int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | 2518 | int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, |
2519 | struct btrfs_root *root, unsigned long count); | 2519 | struct btrfs_root *root, unsigned long count); |
2520 | int btrfs_async_run_delayed_refs(struct btrfs_root *root, | 2520 | int btrfs_async_run_delayed_refs(struct btrfs_root *root, |
2521 | unsigned long count, int wait); | 2521 | unsigned long count, u64 transid, int wait); |
2522 | int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len); | 2522 | int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len); |
2523 | int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | 2523 | int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, |
2524 | struct btrfs_root *root, u64 bytenr, | 2524 | struct btrfs_root *root, u64 bytenr, |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 61561c2a3f96..d3aaabbfada0 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -1606,15 +1606,23 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode) | |||
1606 | return 0; | 1606 | return 0; |
1607 | } | 1607 | } |
1608 | 1608 | ||
1609 | void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, | 1609 | bool btrfs_readdir_get_delayed_items(struct inode *inode, |
1610 | struct list_head *del_list) | 1610 | struct list_head *ins_list, |
1611 | struct list_head *del_list) | ||
1611 | { | 1612 | { |
1612 | struct btrfs_delayed_node *delayed_node; | 1613 | struct btrfs_delayed_node *delayed_node; |
1613 | struct btrfs_delayed_item *item; | 1614 | struct btrfs_delayed_item *item; |
1614 | 1615 | ||
1615 | delayed_node = btrfs_get_delayed_node(inode); | 1616 | delayed_node = btrfs_get_delayed_node(inode); |
1616 | if (!delayed_node) | 1617 | if (!delayed_node) |
1617 | return; | 1618 | return false; |
1619 | |||
1620 | /* | ||
1621 | * We can only do one readdir with delayed items at a time because of | ||
1622 | * item->readdir_list. | ||
1623 | */ | ||
1624 | inode_unlock_shared(inode); | ||
1625 | inode_lock(inode); | ||
1618 | 1626 | ||
1619 | mutex_lock(&delayed_node->mutex); | 1627 | mutex_lock(&delayed_node->mutex); |
1620 | item = __btrfs_first_delayed_insertion_item(delayed_node); | 1628 | item = __btrfs_first_delayed_insertion_item(delayed_node); |
@@ -1641,10 +1649,13 @@ void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, | |||
1641 | * requeue or dequeue this delayed node. | 1649 | * requeue or dequeue this delayed node. |
1642 | */ | 1650 | */ |
1643 | atomic_dec(&delayed_node->refs); | 1651 | atomic_dec(&delayed_node->refs); |
1652 | |||
1653 | return true; | ||
1644 | } | 1654 | } |
1645 | 1655 | ||
1646 | void btrfs_put_delayed_items(struct list_head *ins_list, | 1656 | void btrfs_readdir_put_delayed_items(struct inode *inode, |
1647 | struct list_head *del_list) | 1657 | struct list_head *ins_list, |
1658 | struct list_head *del_list) | ||
1648 | { | 1659 | { |
1649 | struct btrfs_delayed_item *curr, *next; | 1660 | struct btrfs_delayed_item *curr, *next; |
1650 | 1661 | ||
@@ -1659,6 +1670,12 @@ void btrfs_put_delayed_items(struct list_head *ins_list, | |||
1659 | if (atomic_dec_and_test(&curr->refs)) | 1670 | if (atomic_dec_and_test(&curr->refs)) |
1660 | kfree(curr); | 1671 | kfree(curr); |
1661 | } | 1672 | } |
1673 | |||
1674 | /* | ||
1675 | * The VFS is going to do up_read(), so we need to downgrade back to a | ||
1676 | * read lock. | ||
1677 | */ | ||
1678 | downgrade_write(&inode->i_rwsem); | ||
1662 | } | 1679 | } |
1663 | 1680 | ||
1664 | int btrfs_should_delete_dir_index(struct list_head *del_list, | 1681 | int btrfs_should_delete_dir_index(struct list_head *del_list, |
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 0167853c84ae..2495b3d4075f 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h | |||
@@ -137,10 +137,12 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); | |||
137 | void btrfs_destroy_delayed_inodes(struct btrfs_root *root); | 137 | void btrfs_destroy_delayed_inodes(struct btrfs_root *root); |
138 | 138 | ||
139 | /* Used for readdir() */ | 139 | /* Used for readdir() */ |
140 | void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, | 140 | bool btrfs_readdir_get_delayed_items(struct inode *inode, |
141 | struct list_head *del_list); | 141 | struct list_head *ins_list, |
142 | void btrfs_put_delayed_items(struct list_head *ins_list, | 142 | struct list_head *del_list); |
143 | struct list_head *del_list); | 143 | void btrfs_readdir_put_delayed_items(struct inode *inode, |
144 | struct list_head *ins_list, | ||
145 | struct list_head *del_list); | ||
144 | int btrfs_should_delete_dir_index(struct list_head *del_list, | 146 | int btrfs_should_delete_dir_index(struct list_head *del_list, |
145 | u64 index); | 147 | u64 index); |
146 | int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, | 148 | int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6628fca9f4ed..60ce1190307b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1098,7 +1098,7 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr) | |||
1098 | struct inode *btree_inode = root->fs_info->btree_inode; | 1098 | struct inode *btree_inode = root->fs_info->btree_inode; |
1099 | 1099 | ||
1100 | buf = btrfs_find_create_tree_block(root, bytenr); | 1100 | buf = btrfs_find_create_tree_block(root, bytenr); |
1101 | if (!buf) | 1101 | if (IS_ERR(buf)) |
1102 | return; | 1102 | return; |
1103 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, | 1103 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, |
1104 | buf, 0, WAIT_NONE, btree_get_extent, 0); | 1104 | buf, 0, WAIT_NONE, btree_get_extent, 0); |
@@ -1114,7 +1114,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, | |||
1114 | int ret; | 1114 | int ret; |
1115 | 1115 | ||
1116 | buf = btrfs_find_create_tree_block(root, bytenr); | 1116 | buf = btrfs_find_create_tree_block(root, bytenr); |
1117 | if (!buf) | 1117 | if (IS_ERR(buf)) |
1118 | return 0; | 1118 | return 0; |
1119 | 1119 | ||
1120 | set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags); | 1120 | set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags); |
@@ -1147,7 +1147,8 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, | |||
1147 | u64 bytenr) | 1147 | u64 bytenr) |
1148 | { | 1148 | { |
1149 | if (btrfs_test_is_dummy_root(root)) | 1149 | if (btrfs_test_is_dummy_root(root)) |
1150 | return alloc_test_extent_buffer(root->fs_info, bytenr); | 1150 | return alloc_test_extent_buffer(root->fs_info, bytenr, |
1151 | root->nodesize); | ||
1151 | return alloc_extent_buffer(root->fs_info, bytenr); | 1152 | return alloc_extent_buffer(root->fs_info, bytenr); |
1152 | } | 1153 | } |
1153 | 1154 | ||
@@ -1171,8 +1172,8 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | |||
1171 | int ret; | 1172 | int ret; |
1172 | 1173 | ||
1173 | buf = btrfs_find_create_tree_block(root, bytenr); | 1174 | buf = btrfs_find_create_tree_block(root, bytenr); |
1174 | if (!buf) | 1175 | if (IS_ERR(buf)) |
1175 | return ERR_PTR(-ENOMEM); | 1176 | return buf; |
1176 | 1177 | ||
1177 | ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); | 1178 | ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); |
1178 | if (ret) { | 1179 | if (ret) { |
@@ -1314,14 +1315,16 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info, | |||
1314 | 1315 | ||
1315 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | 1316 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS |
1316 | /* Should only be used by the testing infrastructure */ | 1317 | /* Should only be used by the testing infrastructure */ |
1317 | struct btrfs_root *btrfs_alloc_dummy_root(void) | 1318 | struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize) |
1318 | { | 1319 | { |
1319 | struct btrfs_root *root; | 1320 | struct btrfs_root *root; |
1320 | 1321 | ||
1321 | root = btrfs_alloc_root(NULL, GFP_KERNEL); | 1322 | root = btrfs_alloc_root(NULL, GFP_KERNEL); |
1322 | if (!root) | 1323 | if (!root) |
1323 | return ERR_PTR(-ENOMEM); | 1324 | return ERR_PTR(-ENOMEM); |
1324 | __setup_root(4096, 4096, 4096, root, NULL, 1); | 1325 | /* We don't use the stripesize in selftest, set it as sectorsize */ |
1326 | __setup_root(nodesize, sectorsize, sectorsize, root, NULL, | ||
1327 | BTRFS_ROOT_TREE_OBJECTID); | ||
1325 | set_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state); | 1328 | set_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state); |
1326 | root->alloc_bytenr = 0; | 1329 | root->alloc_bytenr = 0; |
1327 | 1330 | ||
@@ -1803,6 +1806,13 @@ static int cleaner_kthread(void *arg) | |||
1803 | if (btrfs_need_cleaner_sleep(root)) | 1806 | if (btrfs_need_cleaner_sleep(root)) |
1804 | goto sleep; | 1807 | goto sleep; |
1805 | 1808 | ||
1809 | /* | ||
1810 | * Do not do anything if we might cause open_ctree() to block | ||
1811 | * before we have finished mounting the filesystem. | ||
1812 | */ | ||
1813 | if (!root->fs_info->open) | ||
1814 | goto sleep; | ||
1815 | |||
1806 | if (!mutex_trylock(&root->fs_info->cleaner_mutex)) | 1816 | if (!mutex_trylock(&root->fs_info->cleaner_mutex)) |
1807 | goto sleep; | 1817 | goto sleep; |
1808 | 1818 | ||
@@ -2517,7 +2527,6 @@ int open_ctree(struct super_block *sb, | |||
2517 | int num_backups_tried = 0; | 2527 | int num_backups_tried = 0; |
2518 | int backup_index = 0; | 2528 | int backup_index = 0; |
2519 | int max_active; | 2529 | int max_active; |
2520 | bool cleaner_mutex_locked = false; | ||
2521 | 2530 | ||
2522 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL); | 2531 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL); |
2523 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL); | 2532 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL); |
@@ -2797,7 +2806,7 @@ int open_ctree(struct super_block *sb, | |||
2797 | 2806 | ||
2798 | nodesize = btrfs_super_nodesize(disk_super); | 2807 | nodesize = btrfs_super_nodesize(disk_super); |
2799 | sectorsize = btrfs_super_sectorsize(disk_super); | 2808 | sectorsize = btrfs_super_sectorsize(disk_super); |
2800 | stripesize = btrfs_super_stripesize(disk_super); | 2809 | stripesize = sectorsize; |
2801 | fs_info->dirty_metadata_batch = nodesize * (1 + ilog2(nr_cpu_ids)); | 2810 | fs_info->dirty_metadata_batch = nodesize * (1 + ilog2(nr_cpu_ids)); |
2802 | fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids)); | 2811 | fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids)); |
2803 | 2812 | ||
@@ -2996,13 +3005,6 @@ retry_root_backup: | |||
2996 | goto fail_sysfs; | 3005 | goto fail_sysfs; |
2997 | } | 3006 | } |
2998 | 3007 | ||
2999 | /* | ||
3000 | * Hold the cleaner_mutex thread here so that we don't block | ||
3001 | * for a long time on btrfs_recover_relocation. cleaner_kthread | ||
3002 | * will wait for us to finish mounting the filesystem. | ||
3003 | */ | ||
3004 | mutex_lock(&fs_info->cleaner_mutex); | ||
3005 | cleaner_mutex_locked = true; | ||
3006 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, | 3008 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, |
3007 | "btrfs-cleaner"); | 3009 | "btrfs-cleaner"); |
3008 | if (IS_ERR(fs_info->cleaner_kthread)) | 3010 | if (IS_ERR(fs_info->cleaner_kthread)) |
@@ -3062,8 +3064,10 @@ retry_root_backup: | |||
3062 | ret = btrfs_cleanup_fs_roots(fs_info); | 3064 | ret = btrfs_cleanup_fs_roots(fs_info); |
3063 | if (ret) | 3065 | if (ret) |
3064 | goto fail_qgroup; | 3066 | goto fail_qgroup; |
3065 | /* We locked cleaner_mutex before creating cleaner_kthread. */ | 3067 | |
3068 | mutex_lock(&fs_info->cleaner_mutex); | ||
3066 | ret = btrfs_recover_relocation(tree_root); | 3069 | ret = btrfs_recover_relocation(tree_root); |
3070 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3067 | if (ret < 0) { | 3071 | if (ret < 0) { |
3068 | btrfs_warn(fs_info, "failed to recover relocation: %d", | 3072 | btrfs_warn(fs_info, "failed to recover relocation: %d", |
3069 | ret); | 3073 | ret); |
@@ -3071,8 +3075,6 @@ retry_root_backup: | |||
3071 | goto fail_qgroup; | 3075 | goto fail_qgroup; |
3072 | } | 3076 | } |
3073 | } | 3077 | } |
3074 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3075 | cleaner_mutex_locked = false; | ||
3076 | 3078 | ||
3077 | location.objectid = BTRFS_FS_TREE_OBJECTID; | 3079 | location.objectid = BTRFS_FS_TREE_OBJECTID; |
3078 | location.type = BTRFS_ROOT_ITEM_KEY; | 3080 | location.type = BTRFS_ROOT_ITEM_KEY; |
@@ -3186,10 +3188,6 @@ fail_cleaner: | |||
3186 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); | 3188 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); |
3187 | 3189 | ||
3188 | fail_sysfs: | 3190 | fail_sysfs: |
3189 | if (cleaner_mutex_locked) { | ||
3190 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3191 | cleaner_mutex_locked = false; | ||
3192 | } | ||
3193 | btrfs_sysfs_remove_mounted(fs_info); | 3191 | btrfs_sysfs_remove_mounted(fs_info); |
3194 | 3192 | ||
3195 | fail_fsdev_sysfs: | 3193 | fail_fsdev_sysfs: |
@@ -4130,6 +4128,16 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | |||
4130 | * Hint to catch really bogus numbers, bitflips or so, more exact checks are | 4128 | * Hint to catch really bogus numbers, bitflips or so, more exact checks are |
4131 | * done later | 4129 | * done later |
4132 | */ | 4130 | */ |
4131 | if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) { | ||
4132 | btrfs_err(fs_info, "bytes_used is too small %llu", | ||
4133 | btrfs_super_bytes_used(sb)); | ||
4134 | ret = -EINVAL; | ||
4135 | } | ||
4136 | if (!is_power_of_2(btrfs_super_stripesize(sb))) { | ||
4137 | btrfs_err(fs_info, "invalid stripesize %u", | ||
4138 | btrfs_super_stripesize(sb)); | ||
4139 | ret = -EINVAL; | ||
4140 | } | ||
4133 | if (btrfs_super_num_devices(sb) > (1UL << 31)) | 4141 | if (btrfs_super_num_devices(sb) > (1UL << 31)) |
4134 | printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n", | 4142 | printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n", |
4135 | btrfs_super_num_devices(sb)); | 4143 | btrfs_super_num_devices(sb)); |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 8e79d0070bcf..acba821499a9 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -90,7 +90,7 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, | |||
90 | void btrfs_free_fs_root(struct btrfs_root *root); | 90 | void btrfs_free_fs_root(struct btrfs_root *root); |
91 | 91 | ||
92 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | 92 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS |
93 | struct btrfs_root *btrfs_alloc_dummy_root(void); | 93 | struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize); |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | /* | 96 | /* |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 689d25ac6a68..82b912a293ab 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2835,6 +2835,7 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, | |||
2835 | 2835 | ||
2836 | struct async_delayed_refs { | 2836 | struct async_delayed_refs { |
2837 | struct btrfs_root *root; | 2837 | struct btrfs_root *root; |
2838 | u64 transid; | ||
2838 | int count; | 2839 | int count; |
2839 | int error; | 2840 | int error; |
2840 | int sync; | 2841 | int sync; |
@@ -2850,6 +2851,10 @@ static void delayed_ref_async_start(struct btrfs_work *work) | |||
2850 | 2851 | ||
2851 | async = container_of(work, struct async_delayed_refs, work); | 2852 | async = container_of(work, struct async_delayed_refs, work); |
2852 | 2853 | ||
2854 | /* if the commit is already started, we don't need to wait here */ | ||
2855 | if (btrfs_transaction_blocked(async->root->fs_info)) | ||
2856 | goto done; | ||
2857 | |||
2853 | trans = btrfs_join_transaction(async->root); | 2858 | trans = btrfs_join_transaction(async->root); |
2854 | if (IS_ERR(trans)) { | 2859 | if (IS_ERR(trans)) { |
2855 | async->error = PTR_ERR(trans); | 2860 | async->error = PTR_ERR(trans); |
@@ -2861,10 +2866,15 @@ static void delayed_ref_async_start(struct btrfs_work *work) | |||
2861 | * wait on delayed refs | 2866 | * wait on delayed refs |
2862 | */ | 2867 | */ |
2863 | trans->sync = true; | 2868 | trans->sync = true; |
2869 | |||
2870 | /* Don't bother flushing if we got into a different transaction */ | ||
2871 | if (trans->transid > async->transid) | ||
2872 | goto end; | ||
2873 | |||
2864 | ret = btrfs_run_delayed_refs(trans, async->root, async->count); | 2874 | ret = btrfs_run_delayed_refs(trans, async->root, async->count); |
2865 | if (ret) | 2875 | if (ret) |
2866 | async->error = ret; | 2876 | async->error = ret; |
2867 | 2877 | end: | |
2868 | ret = btrfs_end_transaction(trans, async->root); | 2878 | ret = btrfs_end_transaction(trans, async->root); |
2869 | if (ret && !async->error) | 2879 | if (ret && !async->error) |
2870 | async->error = ret; | 2880 | async->error = ret; |
@@ -2876,7 +2886,7 @@ done: | |||
2876 | } | 2886 | } |
2877 | 2887 | ||
2878 | int btrfs_async_run_delayed_refs(struct btrfs_root *root, | 2888 | int btrfs_async_run_delayed_refs(struct btrfs_root *root, |
2879 | unsigned long count, int wait) | 2889 | unsigned long count, u64 transid, int wait) |
2880 | { | 2890 | { |
2881 | struct async_delayed_refs *async; | 2891 | struct async_delayed_refs *async; |
2882 | int ret; | 2892 | int ret; |
@@ -2888,6 +2898,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root, | |||
2888 | async->root = root->fs_info->tree_root; | 2898 | async->root = root->fs_info->tree_root; |
2889 | async->count = count; | 2899 | async->count = count; |
2890 | async->error = 0; | 2900 | async->error = 0; |
2901 | async->transid = transid; | ||
2891 | if (wait) | 2902 | if (wait) |
2892 | async->sync = 1; | 2903 | async->sync = 1; |
2893 | else | 2904 | else |
@@ -8016,8 +8027,9 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
8016 | struct extent_buffer *buf; | 8027 | struct extent_buffer *buf; |
8017 | 8028 | ||
8018 | buf = btrfs_find_create_tree_block(root, bytenr); | 8029 | buf = btrfs_find_create_tree_block(root, bytenr); |
8019 | if (!buf) | 8030 | if (IS_ERR(buf)) |
8020 | return ERR_PTR(-ENOMEM); | 8031 | return buf; |
8032 | |||
8021 | btrfs_set_header_generation(buf, trans->transid); | 8033 | btrfs_set_header_generation(buf, trans->transid); |
8022 | btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level); | 8034 | btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level); |
8023 | btrfs_tree_lock(buf); | 8035 | btrfs_tree_lock(buf); |
@@ -8044,7 +8056,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
8044 | set_extent_dirty(&trans->transaction->dirty_pages, buf->start, | 8056 | set_extent_dirty(&trans->transaction->dirty_pages, buf->start, |
8045 | buf->start + buf->len - 1, GFP_NOFS); | 8057 | buf->start + buf->len - 1, GFP_NOFS); |
8046 | } | 8058 | } |
8047 | trans->blocks_used++; | 8059 | trans->dirty = true; |
8048 | /* this returns a buffer locked for blocking */ | 8060 | /* this returns a buffer locked for blocking */ |
8049 | return buf; | 8061 | return buf; |
8050 | } | 8062 | } |
@@ -8659,8 +8671,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
8659 | next = btrfs_find_tree_block(root->fs_info, bytenr); | 8671 | next = btrfs_find_tree_block(root->fs_info, bytenr); |
8660 | if (!next) { | 8672 | if (!next) { |
8661 | next = btrfs_find_create_tree_block(root, bytenr); | 8673 | next = btrfs_find_create_tree_block(root, bytenr); |
8662 | if (!next) | 8674 | if (IS_ERR(next)) |
8663 | return -ENOMEM; | 8675 | return PTR_ERR(next); |
8676 | |||
8664 | btrfs_set_buffer_lockdep_class(root->root_key.objectid, next, | 8677 | btrfs_set_buffer_lockdep_class(root->root_key.objectid, next, |
8665 | level - 1); | 8678 | level - 1); |
8666 | reada = 1; | 8679 | reada = 1; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 6e953de83f08..75533adef998 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -4728,16 +4728,16 @@ err: | |||
4728 | } | 4728 | } |
4729 | 4729 | ||
4730 | struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, | 4730 | struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, |
4731 | u64 start) | 4731 | u64 start, u32 nodesize) |
4732 | { | 4732 | { |
4733 | unsigned long len; | 4733 | unsigned long len; |
4734 | 4734 | ||
4735 | if (!fs_info) { | 4735 | if (!fs_info) { |
4736 | /* | 4736 | /* |
4737 | * Called only from tests that don't always have a fs_info | 4737 | * Called only from tests that don't always have a fs_info |
4738 | * available, but we know that nodesize is 4096 | 4738 | * available |
4739 | */ | 4739 | */ |
4740 | len = 4096; | 4740 | len = nodesize; |
4741 | } else { | 4741 | } else { |
4742 | len = fs_info->tree_root->nodesize; | 4742 | len = fs_info->tree_root->nodesize; |
4743 | } | 4743 | } |
@@ -4833,7 +4833,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, | |||
4833 | 4833 | ||
4834 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | 4834 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS |
4835 | struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, | 4835 | struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, |
4836 | u64 start) | 4836 | u64 start, u32 nodesize) |
4837 | { | 4837 | { |
4838 | struct extent_buffer *eb, *exists = NULL; | 4838 | struct extent_buffer *eb, *exists = NULL; |
4839 | int ret; | 4839 | int ret; |
@@ -4841,7 +4841,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, | |||
4841 | eb = find_extent_buffer(fs_info, start); | 4841 | eb = find_extent_buffer(fs_info, start); |
4842 | if (eb) | 4842 | if (eb) |
4843 | return eb; | 4843 | return eb; |
4844 | eb = alloc_dummy_extent_buffer(fs_info, start); | 4844 | eb = alloc_dummy_extent_buffer(fs_info, start, nodesize); |
4845 | if (!eb) | 4845 | if (!eb) |
4846 | return NULL; | 4846 | return NULL; |
4847 | eb->fs_info = fs_info; | 4847 | eb->fs_info = fs_info; |
@@ -4892,18 +4892,25 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, | |||
4892 | int uptodate = 1; | 4892 | int uptodate = 1; |
4893 | int ret; | 4893 | int ret; |
4894 | 4894 | ||
4895 | if (!IS_ALIGNED(start, fs_info->tree_root->sectorsize)) { | ||
4896 | btrfs_err(fs_info, "bad tree block start %llu", start); | ||
4897 | return ERR_PTR(-EINVAL); | ||
4898 | } | ||
4899 | |||
4895 | eb = find_extent_buffer(fs_info, start); | 4900 | eb = find_extent_buffer(fs_info, start); |
4896 | if (eb) | 4901 | if (eb) |
4897 | return eb; | 4902 | return eb; |
4898 | 4903 | ||
4899 | eb = __alloc_extent_buffer(fs_info, start, len); | 4904 | eb = __alloc_extent_buffer(fs_info, start, len); |
4900 | if (!eb) | 4905 | if (!eb) |
4901 | return NULL; | 4906 | return ERR_PTR(-ENOMEM); |
4902 | 4907 | ||
4903 | for (i = 0; i < num_pages; i++, index++) { | 4908 | for (i = 0; i < num_pages; i++, index++) { |
4904 | p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL); | 4909 | p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL); |
4905 | if (!p) | 4910 | if (!p) { |
4911 | exists = ERR_PTR(-ENOMEM); | ||
4906 | goto free_eb; | 4912 | goto free_eb; |
4913 | } | ||
4907 | 4914 | ||
4908 | spin_lock(&mapping->private_lock); | 4915 | spin_lock(&mapping->private_lock); |
4909 | if (PagePrivate(p)) { | 4916 | if (PagePrivate(p)) { |
@@ -4948,8 +4955,10 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, | |||
4948 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 4955 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
4949 | again: | 4956 | again: |
4950 | ret = radix_tree_preload(GFP_NOFS); | 4957 | ret = radix_tree_preload(GFP_NOFS); |
4951 | if (ret) | 4958 | if (ret) { |
4959 | exists = ERR_PTR(ret); | ||
4952 | goto free_eb; | 4960 | goto free_eb; |
4961 | } | ||
4953 | 4962 | ||
4954 | spin_lock(&fs_info->buffer_lock); | 4963 | spin_lock(&fs_info->buffer_lock); |
4955 | ret = radix_tree_insert(&fs_info->buffer_radix, | 4964 | ret = radix_tree_insert(&fs_info->buffer_radix, |
@@ -5333,6 +5342,11 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv, | |||
5333 | return ret; | 5342 | return ret; |
5334 | } | 5343 | } |
5335 | 5344 | ||
5345 | /* | ||
5346 | * return 0 if the item is found within a page. | ||
5347 | * return 1 if the item spans two pages. | ||
5348 | * return -EINVAL otherwise. | ||
5349 | */ | ||
5336 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, | 5350 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, |
5337 | unsigned long min_len, char **map, | 5351 | unsigned long min_len, char **map, |
5338 | unsigned long *map_start, | 5352 | unsigned long *map_start, |
@@ -5347,7 +5361,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, | |||
5347 | PAGE_SHIFT; | 5361 | PAGE_SHIFT; |
5348 | 5362 | ||
5349 | if (i != end_i) | 5363 | if (i != end_i) |
5350 | return -EINVAL; | 5364 | return 1; |
5351 | 5365 | ||
5352 | if (i == 0) { | 5366 | if (i == 0) { |
5353 | offset = start_offset; | 5367 | offset = start_offset; |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 1baf19c9b79d..c0c1c4fef6ce 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -348,7 +348,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, | |||
348 | struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, | 348 | struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, |
349 | u64 start, unsigned long len); | 349 | u64 start, unsigned long len); |
350 | struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, | 350 | struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, |
351 | u64 start); | 351 | u64 start, u32 nodesize); |
352 | struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src); | 352 | struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src); |
353 | struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, | 353 | struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, |
354 | u64 start); | 354 | u64 start); |
@@ -468,5 +468,5 @@ noinline u64 find_lock_delalloc_range(struct inode *inode, | |||
468 | u64 *end, u64 max_bytes); | 468 | u64 *end, u64 max_bytes); |
469 | #endif | 469 | #endif |
470 | struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, | 470 | struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, |
471 | u64 start); | 471 | u64 start, u32 nodesize); |
472 | #endif | 472 | #endif |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e0c9bd3fb02d..2234e88cf674 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1534,30 +1534,30 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
1534 | reserve_bytes = round_up(write_bytes + sector_offset, | 1534 | reserve_bytes = round_up(write_bytes + sector_offset, |
1535 | root->sectorsize); | 1535 | root->sectorsize); |
1536 | 1536 | ||
1537 | if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW | | ||
1538 | BTRFS_INODE_PREALLOC)) && | ||
1539 | check_can_nocow(inode, pos, &write_bytes) > 0) { | ||
1540 | /* | ||
1541 | * For nodata cow case, no need to reserve | ||
1542 | * data space. | ||
1543 | */ | ||
1544 | only_release_metadata = true; | ||
1545 | /* | ||
1546 | * our prealloc extent may be smaller than | ||
1547 | * write_bytes, so scale down. | ||
1548 | */ | ||
1549 | num_pages = DIV_ROUND_UP(write_bytes + offset, | ||
1550 | PAGE_SIZE); | ||
1551 | reserve_bytes = round_up(write_bytes + sector_offset, | ||
1552 | root->sectorsize); | ||
1553 | goto reserve_metadata; | ||
1554 | } | ||
1555 | |||
1556 | ret = btrfs_check_data_free_space(inode, pos, write_bytes); | 1537 | ret = btrfs_check_data_free_space(inode, pos, write_bytes); |
1557 | if (ret < 0) | 1538 | if (ret < 0) { |
1558 | break; | 1539 | if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW | |
1540 | BTRFS_INODE_PREALLOC)) && | ||
1541 | check_can_nocow(inode, pos, &write_bytes) > 0) { | ||
1542 | /* | ||
1543 | * For nodata cow case, no need to reserve | ||
1544 | * data space. | ||
1545 | */ | ||
1546 | only_release_metadata = true; | ||
1547 | /* | ||
1548 | * our prealloc extent may be smaller than | ||
1549 | * write_bytes, so scale down. | ||
1550 | */ | ||
1551 | num_pages = DIV_ROUND_UP(write_bytes + offset, | ||
1552 | PAGE_SIZE); | ||
1553 | reserve_bytes = round_up(write_bytes + | ||
1554 | sector_offset, | ||
1555 | root->sectorsize); | ||
1556 | } else { | ||
1557 | break; | ||
1558 | } | ||
1559 | } | ||
1559 | 1560 | ||
1560 | reserve_metadata: | ||
1561 | ret = btrfs_delalloc_reserve_metadata(inode, reserve_bytes); | 1561 | ret = btrfs_delalloc_reserve_metadata(inode, reserve_bytes); |
1562 | if (ret) { | 1562 | if (ret) { |
1563 | if (!only_release_metadata) | 1563 | if (!only_release_metadata) |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index c6dc1183f542..69d270f6602c 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "inode-map.h" | 29 | #include "inode-map.h" |
30 | #include "volumes.h" | 30 | #include "volumes.h" |
31 | 31 | ||
32 | #define BITS_PER_BITMAP (PAGE_SIZE * 8) | 32 | #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) |
33 | #define MAX_CACHE_BYTES_PER_GIG SZ_32K | 33 | #define MAX_CACHE_BYTES_PER_GIG SZ_32K |
34 | 34 | ||
35 | struct btrfs_trim_range { | 35 | struct btrfs_trim_range { |
@@ -1415,11 +1415,11 @@ static inline u64 offset_to_bitmap(struct btrfs_free_space_ctl *ctl, | |||
1415 | u64 offset) | 1415 | u64 offset) |
1416 | { | 1416 | { |
1417 | u64 bitmap_start; | 1417 | u64 bitmap_start; |
1418 | u32 bytes_per_bitmap; | 1418 | u64 bytes_per_bitmap; |
1419 | 1419 | ||
1420 | bytes_per_bitmap = BITS_PER_BITMAP * ctl->unit; | 1420 | bytes_per_bitmap = BITS_PER_BITMAP * ctl->unit; |
1421 | bitmap_start = offset - ctl->start; | 1421 | bitmap_start = offset - ctl->start; |
1422 | bitmap_start = div_u64(bitmap_start, bytes_per_bitmap); | 1422 | bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap); |
1423 | bitmap_start *= bytes_per_bitmap; | 1423 | bitmap_start *= bytes_per_bitmap; |
1424 | bitmap_start += ctl->start; | 1424 | bitmap_start += ctl->start; |
1425 | 1425 | ||
@@ -1638,10 +1638,10 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl) | |||
1638 | u64 bitmap_bytes; | 1638 | u64 bitmap_bytes; |
1639 | u64 extent_bytes; | 1639 | u64 extent_bytes; |
1640 | u64 size = block_group->key.offset; | 1640 | u64 size = block_group->key.offset; |
1641 | u32 bytes_per_bg = BITS_PER_BITMAP * ctl->unit; | 1641 | u64 bytes_per_bg = BITS_PER_BITMAP * ctl->unit; |
1642 | u32 max_bitmaps = div_u64(size + bytes_per_bg - 1, bytes_per_bg); | 1642 | u64 max_bitmaps = div64_u64(size + bytes_per_bg - 1, bytes_per_bg); |
1643 | 1643 | ||
1644 | max_bitmaps = max_t(u32, max_bitmaps, 1); | 1644 | max_bitmaps = max_t(u64, max_bitmaps, 1); |
1645 | 1645 | ||
1646 | ASSERT(ctl->total_bitmaps <= max_bitmaps); | 1646 | ASSERT(ctl->total_bitmaps <= max_bitmaps); |
1647 | 1647 | ||
@@ -1660,7 +1660,7 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl) | |||
1660 | * sure we don't go over our overall goal of MAX_CACHE_BYTES_PER_GIG as | 1660 | * sure we don't go over our overall goal of MAX_CACHE_BYTES_PER_GIG as |
1661 | * we add more bitmaps. | 1661 | * we add more bitmaps. |
1662 | */ | 1662 | */ |
1663 | bitmap_bytes = (ctl->total_bitmaps + 1) * PAGE_SIZE; | 1663 | bitmap_bytes = (ctl->total_bitmaps + 1) * ctl->unit; |
1664 | 1664 | ||
1665 | if (bitmap_bytes >= max_bytes) { | 1665 | if (bitmap_bytes >= max_bytes) { |
1666 | ctl->extents_thresh = 0; | 1666 | ctl->extents_thresh = 0; |
@@ -3662,7 +3662,7 @@ have_info: | |||
3662 | if (tmp->offset + tmp->bytes < offset) | 3662 | if (tmp->offset + tmp->bytes < offset) |
3663 | break; | 3663 | break; |
3664 | if (offset + bytes < tmp->offset) { | 3664 | if (offset + bytes < tmp->offset) { |
3665 | n = rb_prev(&info->offset_index); | 3665 | n = rb_prev(&tmp->offset_index); |
3666 | continue; | 3666 | continue; |
3667 | } | 3667 | } |
3668 | info = tmp; | 3668 | info = tmp; |
@@ -3676,7 +3676,7 @@ have_info: | |||
3676 | if (offset + bytes < tmp->offset) | 3676 | if (offset + bytes < tmp->offset) |
3677 | break; | 3677 | break; |
3678 | if (tmp->offset + tmp->bytes < offset) { | 3678 | if (tmp->offset + tmp->bytes < offset) { |
3679 | n = rb_next(&info->offset_index); | 3679 | n = rb_next(&tmp->offset_index); |
3680 | continue; | 3680 | continue; |
3681 | } | 3681 | } |
3682 | info = tmp; | 3682 | info = tmp; |
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c index aae520b2aee5..a97fdc156a03 100644 --- a/fs/btrfs/hash.c +++ b/fs/btrfs/hash.c | |||
@@ -24,6 +24,11 @@ int __init btrfs_hash_init(void) | |||
24 | return PTR_ERR_OR_ZERO(tfm); | 24 | return PTR_ERR_OR_ZERO(tfm); |
25 | } | 25 | } |
26 | 26 | ||
27 | const char* btrfs_crc32c_impl(void) | ||
28 | { | ||
29 | return crypto_tfm_alg_driver_name(crypto_shash_tfm(tfm)); | ||
30 | } | ||
31 | |||
27 | void btrfs_hash_exit(void) | 32 | void btrfs_hash_exit(void) |
28 | { | 33 | { |
29 | crypto_free_shash(tfm); | 34 | crypto_free_shash(tfm); |
diff --git a/fs/btrfs/hash.h b/fs/btrfs/hash.h index 118a2316e5d3..c3a2ec554361 100644 --- a/fs/btrfs/hash.h +++ b/fs/btrfs/hash.h | |||
@@ -22,6 +22,7 @@ | |||
22 | int __init btrfs_hash_init(void); | 22 | int __init btrfs_hash_init(void); |
23 | 23 | ||
24 | void btrfs_hash_exit(void); | 24 | void btrfs_hash_exit(void); |
25 | const char* btrfs_crc32c_impl(void); | ||
25 | 26 | ||
26 | u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length); | 27 | u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length); |
27 | 28 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8b1212e8f7a8..4421954720b8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3271,7 +3271,16 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
3271 | /* grab metadata reservation from transaction handle */ | 3271 | /* grab metadata reservation from transaction handle */ |
3272 | if (reserve) { | 3272 | if (reserve) { |
3273 | ret = btrfs_orphan_reserve_metadata(trans, inode); | 3273 | ret = btrfs_orphan_reserve_metadata(trans, inode); |
3274 | BUG_ON(ret); /* -ENOSPC in reservation; Logic error? JDM */ | 3274 | ASSERT(!ret); |
3275 | if (ret) { | ||
3276 | atomic_dec(&root->orphan_inodes); | ||
3277 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | ||
3278 | &BTRFS_I(inode)->runtime_flags); | ||
3279 | if (insert) | ||
3280 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | ||
3281 | &BTRFS_I(inode)->runtime_flags); | ||
3282 | return ret; | ||
3283 | } | ||
3275 | } | 3284 | } |
3276 | 3285 | ||
3277 | /* insert an orphan item to track this unlinked/truncated file */ | 3286 | /* insert an orphan item to track this unlinked/truncated file */ |
@@ -4549,6 +4558,7 @@ delete: | |||
4549 | BUG_ON(ret); | 4558 | BUG_ON(ret); |
4550 | if (btrfs_should_throttle_delayed_refs(trans, root)) | 4559 | if (btrfs_should_throttle_delayed_refs(trans, root)) |
4551 | btrfs_async_run_delayed_refs(root, | 4560 | btrfs_async_run_delayed_refs(root, |
4561 | trans->transid, | ||
4552 | trans->delayed_ref_updates * 2, 0); | 4562 | trans->delayed_ref_updates * 2, 0); |
4553 | if (be_nice) { | 4563 | if (be_nice) { |
4554 | if (truncate_space_check(trans, root, | 4564 | if (truncate_space_check(trans, root, |
@@ -5748,6 +5758,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) | |||
5748 | int name_len; | 5758 | int name_len; |
5749 | int is_curr = 0; /* ctx->pos points to the current index? */ | 5759 | int is_curr = 0; /* ctx->pos points to the current index? */ |
5750 | bool emitted; | 5760 | bool emitted; |
5761 | bool put = false; | ||
5751 | 5762 | ||
5752 | /* FIXME, use a real flag for deciding about the key type */ | 5763 | /* FIXME, use a real flag for deciding about the key type */ |
5753 | if (root->fs_info->tree_root == root) | 5764 | if (root->fs_info->tree_root == root) |
@@ -5765,7 +5776,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) | |||
5765 | if (key_type == BTRFS_DIR_INDEX_KEY) { | 5776 | if (key_type == BTRFS_DIR_INDEX_KEY) { |
5766 | INIT_LIST_HEAD(&ins_list); | 5777 | INIT_LIST_HEAD(&ins_list); |
5767 | INIT_LIST_HEAD(&del_list); | 5778 | INIT_LIST_HEAD(&del_list); |
5768 | btrfs_get_delayed_items(inode, &ins_list, &del_list); | 5779 | put = btrfs_readdir_get_delayed_items(inode, &ins_list, |
5780 | &del_list); | ||
5769 | } | 5781 | } |
5770 | 5782 | ||
5771 | key.type = key_type; | 5783 | key.type = key_type; |
@@ -5912,8 +5924,8 @@ next: | |||
5912 | nopos: | 5924 | nopos: |
5913 | ret = 0; | 5925 | ret = 0; |
5914 | err: | 5926 | err: |
5915 | if (key_type == BTRFS_DIR_INDEX_KEY) | 5927 | if (put) |
5916 | btrfs_put_delayed_items(&ins_list, &del_list); | 5928 | btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list); |
5917 | btrfs_free_path(path); | 5929 | btrfs_free_path(path); |
5918 | return ret; | 5930 | return ret; |
5919 | } | 5931 | } |
@@ -10525,7 +10537,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = { | |||
10525 | static const struct file_operations btrfs_dir_file_operations = { | 10537 | static const struct file_operations btrfs_dir_file_operations = { |
10526 | .llseek = generic_file_llseek, | 10538 | .llseek = generic_file_llseek, |
10527 | .read = generic_read_dir, | 10539 | .read = generic_read_dir, |
10528 | .iterate = btrfs_real_readdir, | 10540 | .iterate_shared = btrfs_real_readdir, |
10529 | .unlocked_ioctl = btrfs_ioctl, | 10541 | .unlocked_ioctl = btrfs_ioctl, |
10530 | #ifdef CONFIG_COMPAT | 10542 | #ifdef CONFIG_COMPAT |
10531 | .compat_ioctl = btrfs_compat_ioctl, | 10543 | .compat_ioctl = btrfs_compat_ioctl, |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index e96634a725c3..aca8264f4a49 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -968,6 +968,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
968 | struct rb_node *prev = NULL; | 968 | struct rb_node *prev = NULL; |
969 | struct btrfs_ordered_extent *test; | 969 | struct btrfs_ordered_extent *test; |
970 | int ret = 1; | 970 | int ret = 1; |
971 | u64 orig_offset = offset; | ||
971 | 972 | ||
972 | spin_lock_irq(&tree->lock); | 973 | spin_lock_irq(&tree->lock); |
973 | if (ordered) { | 974 | if (ordered) { |
@@ -983,7 +984,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
983 | 984 | ||
984 | /* truncate file */ | 985 | /* truncate file */ |
985 | if (disk_i_size > i_size) { | 986 | if (disk_i_size > i_size) { |
986 | BTRFS_I(inode)->disk_i_size = i_size; | 987 | BTRFS_I(inode)->disk_i_size = orig_offset; |
987 | ret = 0; | 988 | ret = 0; |
988 | goto out; | 989 | goto out; |
989 | } | 990 | } |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4e59a91a11e0..60e7179ed4b7 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -235,7 +235,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, | |||
235 | trans->aborted = errno; | 235 | trans->aborted = errno; |
236 | /* Nothing used. The other threads that have joined this | 236 | /* Nothing used. The other threads that have joined this |
237 | * transaction may be able to continue. */ | 237 | * transaction may be able to continue. */ |
238 | if (!trans->blocks_used && list_empty(&trans->new_bgs)) { | 238 | if (!trans->dirty && list_empty(&trans->new_bgs)) { |
239 | const char *errstr; | 239 | const char *errstr; |
240 | 240 | ||
241 | errstr = btrfs_decode_error(errno); | 241 | errstr = btrfs_decode_error(errno); |
@@ -1807,6 +1807,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1807 | } | 1807 | } |
1808 | } | 1808 | } |
1809 | sb->s_flags &= ~MS_RDONLY; | 1809 | sb->s_flags &= ~MS_RDONLY; |
1810 | |||
1811 | fs_info->open = 1; | ||
1810 | } | 1812 | } |
1811 | out: | 1813 | out: |
1812 | wake_up_process(fs_info->transaction_kthread); | 1814 | wake_up_process(fs_info->transaction_kthread); |
@@ -2303,7 +2305,7 @@ static void btrfs_interface_exit(void) | |||
2303 | 2305 | ||
2304 | static void btrfs_print_mod_info(void) | 2306 | static void btrfs_print_mod_info(void) |
2305 | { | 2307 | { |
2306 | printk(KERN_INFO "Btrfs loaded" | 2308 | printk(KERN_INFO "Btrfs loaded, crc32c=%s" |
2307 | #ifdef CONFIG_BTRFS_DEBUG | 2309 | #ifdef CONFIG_BTRFS_DEBUG |
2308 | ", debug=on" | 2310 | ", debug=on" |
2309 | #endif | 2311 | #endif |
@@ -2313,33 +2315,48 @@ static void btrfs_print_mod_info(void) | |||
2313 | #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY | 2315 | #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY |
2314 | ", integrity-checker=on" | 2316 | ", integrity-checker=on" |
2315 | #endif | 2317 | #endif |
2316 | "\n"); | 2318 | "\n", |
2319 | btrfs_crc32c_impl()); | ||
2317 | } | 2320 | } |
2318 | 2321 | ||
2319 | static int btrfs_run_sanity_tests(void) | 2322 | static int btrfs_run_sanity_tests(void) |
2320 | { | 2323 | { |
2321 | int ret; | 2324 | int ret, i; |
2322 | 2325 | u32 sectorsize, nodesize; | |
2326 | u32 test_sectorsize[] = { | ||
2327 | PAGE_SIZE, | ||
2328 | }; | ||
2323 | ret = btrfs_init_test_fs(); | 2329 | ret = btrfs_init_test_fs(); |
2324 | if (ret) | 2330 | if (ret) |
2325 | return ret; | 2331 | return ret; |
2326 | 2332 | for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) { | |
2327 | ret = btrfs_test_free_space_cache(); | 2333 | sectorsize = test_sectorsize[i]; |
2328 | if (ret) | 2334 | for (nodesize = sectorsize; |
2329 | goto out; | 2335 | nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE; |
2330 | ret = btrfs_test_extent_buffer_operations(); | 2336 | nodesize <<= 1) { |
2331 | if (ret) | 2337 | pr_info("BTRFS: selftest: sectorsize: %u nodesize: %u\n", |
2332 | goto out; | 2338 | sectorsize, nodesize); |
2333 | ret = btrfs_test_extent_io(); | 2339 | ret = btrfs_test_free_space_cache(sectorsize, nodesize); |
2334 | if (ret) | 2340 | if (ret) |
2335 | goto out; | 2341 | goto out; |
2336 | ret = btrfs_test_inodes(); | 2342 | ret = btrfs_test_extent_buffer_operations(sectorsize, |
2337 | if (ret) | 2343 | nodesize); |
2338 | goto out; | 2344 | if (ret) |
2339 | ret = btrfs_test_qgroups(); | 2345 | goto out; |
2340 | if (ret) | 2346 | ret = btrfs_test_extent_io(sectorsize, nodesize); |
2341 | goto out; | 2347 | if (ret) |
2342 | ret = btrfs_test_free_space_tree(); | 2348 | goto out; |
2349 | ret = btrfs_test_inodes(sectorsize, nodesize); | ||
2350 | if (ret) | ||
2351 | goto out; | ||
2352 | ret = btrfs_test_qgroups(sectorsize, nodesize); | ||
2353 | if (ret) | ||
2354 | goto out; | ||
2355 | ret = btrfs_test_free_space_tree(sectorsize, nodesize); | ||
2356 | if (ret) | ||
2357 | goto out; | ||
2358 | } | ||
2359 | } | ||
2343 | out: | 2360 | out: |
2344 | btrfs_destroy_test_fs(); | 2361 | btrfs_destroy_test_fs(); |
2345 | return ret; | 2362 | return ret; |
diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c index f54bf450bad3..02223f3f78f4 100644 --- a/fs/btrfs/tests/btrfs-tests.c +++ b/fs/btrfs/tests/btrfs-tests.c | |||
@@ -68,7 +68,7 @@ int btrfs_init_test_fs(void) | |||
68 | if (IS_ERR(test_mnt)) { | 68 | if (IS_ERR(test_mnt)) { |
69 | printk(KERN_ERR "btrfs: cannot mount test file system\n"); | 69 | printk(KERN_ERR "btrfs: cannot mount test file system\n"); |
70 | unregister_filesystem(&test_type); | 70 | unregister_filesystem(&test_type); |
71 | return ret; | 71 | return PTR_ERR(test_mnt); |
72 | } | 72 | } |
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
@@ -175,7 +175,7 @@ void btrfs_free_dummy_root(struct btrfs_root *root) | |||
175 | } | 175 | } |
176 | 176 | ||
177 | struct btrfs_block_group_cache * | 177 | struct btrfs_block_group_cache * |
178 | btrfs_alloc_dummy_block_group(unsigned long length) | 178 | btrfs_alloc_dummy_block_group(unsigned long length, u32 sectorsize) |
179 | { | 179 | { |
180 | struct btrfs_block_group_cache *cache; | 180 | struct btrfs_block_group_cache *cache; |
181 | 181 | ||
@@ -192,8 +192,8 @@ btrfs_alloc_dummy_block_group(unsigned long length) | |||
192 | cache->key.objectid = 0; | 192 | cache->key.objectid = 0; |
193 | cache->key.offset = length; | 193 | cache->key.offset = length; |
194 | cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; | 194 | cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; |
195 | cache->sectorsize = 4096; | 195 | cache->sectorsize = sectorsize; |
196 | cache->full_stripe_len = 4096; | 196 | cache->full_stripe_len = sectorsize; |
197 | 197 | ||
198 | INIT_LIST_HEAD(&cache->list); | 198 | INIT_LIST_HEAD(&cache->list); |
199 | INIT_LIST_HEAD(&cache->cluster_list); | 199 | INIT_LIST_HEAD(&cache->cluster_list); |
diff --git a/fs/btrfs/tests/btrfs-tests.h b/fs/btrfs/tests/btrfs-tests.h index 054b8c73c951..66fb6b701eb7 100644 --- a/fs/btrfs/tests/btrfs-tests.h +++ b/fs/btrfs/tests/btrfs-tests.h | |||
@@ -26,27 +26,28 @@ | |||
26 | struct btrfs_root; | 26 | struct btrfs_root; |
27 | struct btrfs_trans_handle; | 27 | struct btrfs_trans_handle; |
28 | 28 | ||
29 | int btrfs_test_free_space_cache(void); | 29 | int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize); |
30 | int btrfs_test_extent_buffer_operations(void); | 30 | int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize); |
31 | int btrfs_test_extent_io(void); | 31 | int btrfs_test_extent_io(u32 sectorsize, u32 nodesize); |
32 | int btrfs_test_inodes(void); | 32 | int btrfs_test_inodes(u32 sectorsize, u32 nodesize); |
33 | int btrfs_test_qgroups(void); | 33 | int btrfs_test_qgroups(u32 sectorsize, u32 nodesize); |
34 | int btrfs_test_free_space_tree(void); | 34 | int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize); |
35 | int btrfs_init_test_fs(void); | 35 | int btrfs_init_test_fs(void); |
36 | void btrfs_destroy_test_fs(void); | 36 | void btrfs_destroy_test_fs(void); |
37 | struct inode *btrfs_new_test_inode(void); | 37 | struct inode *btrfs_new_test_inode(void); |
38 | struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void); | 38 | struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void); |
39 | void btrfs_free_dummy_root(struct btrfs_root *root); | 39 | void btrfs_free_dummy_root(struct btrfs_root *root); |
40 | struct btrfs_block_group_cache * | 40 | struct btrfs_block_group_cache * |
41 | btrfs_alloc_dummy_block_group(unsigned long length); | 41 | btrfs_alloc_dummy_block_group(unsigned long length, u32 sectorsize); |
42 | void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache); | 42 | void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache); |
43 | void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans); | 43 | void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans); |
44 | #else | 44 | #else |
45 | static inline int btrfs_test_free_space_cache(void) | 45 | static inline int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize) |
46 | { | 46 | { |
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | static inline int btrfs_test_extent_buffer_operations(void) | 49 | static inline int btrfs_test_extent_buffer_operations(u32 sectorsize, |
50 | u32 nodesize) | ||
50 | { | 51 | { |
51 | return 0; | 52 | return 0; |
52 | } | 53 | } |
@@ -57,19 +58,19 @@ static inline int btrfs_init_test_fs(void) | |||
57 | static inline void btrfs_destroy_test_fs(void) | 58 | static inline void btrfs_destroy_test_fs(void) |
58 | { | 59 | { |
59 | } | 60 | } |
60 | static inline int btrfs_test_extent_io(void) | 61 | static inline int btrfs_test_extent_io(u32 sectorsize, u32 nodesize) |
61 | { | 62 | { |
62 | return 0; | 63 | return 0; |
63 | } | 64 | } |
64 | static inline int btrfs_test_inodes(void) | 65 | static inline int btrfs_test_inodes(u32 sectorsize, u32 nodesize) |
65 | { | 66 | { |
66 | return 0; | 67 | return 0; |
67 | } | 68 | } |
68 | static inline int btrfs_test_qgroups(void) | 69 | static inline int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) |
69 | { | 70 | { |
70 | return 0; | 71 | return 0; |
71 | } | 72 | } |
72 | static inline int btrfs_test_free_space_tree(void) | 73 | static inline int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize) |
73 | { | 74 | { |
74 | return 0; | 75 | return 0; |
75 | } | 76 | } |
diff --git a/fs/btrfs/tests/extent-buffer-tests.c b/fs/btrfs/tests/extent-buffer-tests.c index f51963a8f929..4f8cbd1ec5ee 100644 --- a/fs/btrfs/tests/extent-buffer-tests.c +++ b/fs/btrfs/tests/extent-buffer-tests.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "../extent_io.h" | 22 | #include "../extent_io.h" |
23 | #include "../disk-io.h" | 23 | #include "../disk-io.h" |
24 | 24 | ||
25 | static int test_btrfs_split_item(void) | 25 | static int test_btrfs_split_item(u32 sectorsize, u32 nodesize) |
26 | { | 26 | { |
27 | struct btrfs_path *path; | 27 | struct btrfs_path *path; |
28 | struct btrfs_root *root; | 28 | struct btrfs_root *root; |
@@ -40,7 +40,7 @@ static int test_btrfs_split_item(void) | |||
40 | 40 | ||
41 | test_msg("Running btrfs_split_item tests\n"); | 41 | test_msg("Running btrfs_split_item tests\n"); |
42 | 42 | ||
43 | root = btrfs_alloc_dummy_root(); | 43 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
44 | if (IS_ERR(root)) { | 44 | if (IS_ERR(root)) { |
45 | test_msg("Could not allocate root\n"); | 45 | test_msg("Could not allocate root\n"); |
46 | return PTR_ERR(root); | 46 | return PTR_ERR(root); |
@@ -53,7 +53,8 @@ static int test_btrfs_split_item(void) | |||
53 | return -ENOMEM; | 53 | return -ENOMEM; |
54 | } | 54 | } |
55 | 55 | ||
56 | path->nodes[0] = eb = alloc_dummy_extent_buffer(NULL, 4096); | 56 | path->nodes[0] = eb = alloc_dummy_extent_buffer(NULL, nodesize, |
57 | nodesize); | ||
57 | if (!eb) { | 58 | if (!eb) { |
58 | test_msg("Could not allocate dummy buffer\n"); | 59 | test_msg("Could not allocate dummy buffer\n"); |
59 | ret = -ENOMEM; | 60 | ret = -ENOMEM; |
@@ -222,8 +223,8 @@ out: | |||
222 | return ret; | 223 | return ret; |
223 | } | 224 | } |
224 | 225 | ||
225 | int btrfs_test_extent_buffer_operations(void) | 226 | int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize) |
226 | { | 227 | { |
227 | test_msg("Running extent buffer operation tests"); | 228 | test_msg("Running extent buffer operation tests\n"); |
228 | return test_btrfs_split_item(); | 229 | return test_btrfs_split_item(sectorsize, nodesize); |
229 | } | 230 | } |
diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c index 55724607f79b..d19ab0317283 100644 --- a/fs/btrfs/tests/extent-io-tests.c +++ b/fs/btrfs/tests/extent-io-tests.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/sizes.h> | 22 | #include <linux/sizes.h> |
23 | #include "btrfs-tests.h" | 23 | #include "btrfs-tests.h" |
24 | #include "../ctree.h" | ||
24 | #include "../extent_io.h" | 25 | #include "../extent_io.h" |
25 | 26 | ||
26 | #define PROCESS_UNLOCK (1 << 0) | 27 | #define PROCESS_UNLOCK (1 << 0) |
@@ -65,7 +66,7 @@ static noinline int process_page_range(struct inode *inode, u64 start, u64 end, | |||
65 | return count; | 66 | return count; |
66 | } | 67 | } |
67 | 68 | ||
68 | static int test_find_delalloc(void) | 69 | static int test_find_delalloc(u32 sectorsize) |
69 | { | 70 | { |
70 | struct inode *inode; | 71 | struct inode *inode; |
71 | struct extent_io_tree tmp; | 72 | struct extent_io_tree tmp; |
@@ -113,7 +114,7 @@ static int test_find_delalloc(void) | |||
113 | * |--- delalloc ---| | 114 | * |--- delalloc ---| |
114 | * |--- search ---| | 115 | * |--- search ---| |
115 | */ | 116 | */ |
116 | set_extent_delalloc(&tmp, 0, 4095, NULL); | 117 | set_extent_delalloc(&tmp, 0, sectorsize - 1, NULL); |
117 | start = 0; | 118 | start = 0; |
118 | end = 0; | 119 | end = 0; |
119 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 120 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, |
@@ -122,9 +123,9 @@ static int test_find_delalloc(void) | |||
122 | test_msg("Should have found at least one delalloc\n"); | 123 | test_msg("Should have found at least one delalloc\n"); |
123 | goto out_bits; | 124 | goto out_bits; |
124 | } | 125 | } |
125 | if (start != 0 || end != 4095) { | 126 | if (start != 0 || end != (sectorsize - 1)) { |
126 | test_msg("Expected start 0 end 4095, got start %Lu end %Lu\n", | 127 | test_msg("Expected start 0 end %u, got start %llu end %llu\n", |
127 | start, end); | 128 | sectorsize - 1, start, end); |
128 | goto out_bits; | 129 | goto out_bits; |
129 | } | 130 | } |
130 | unlock_extent(&tmp, start, end); | 131 | unlock_extent(&tmp, start, end); |
@@ -144,7 +145,7 @@ static int test_find_delalloc(void) | |||
144 | test_msg("Couldn't find the locked page\n"); | 145 | test_msg("Couldn't find the locked page\n"); |
145 | goto out_bits; | 146 | goto out_bits; |
146 | } | 147 | } |
147 | set_extent_delalloc(&tmp, 4096, max_bytes - 1, NULL); | 148 | set_extent_delalloc(&tmp, sectorsize, max_bytes - 1, NULL); |
148 | start = test_start; | 149 | start = test_start; |
149 | end = 0; | 150 | end = 0; |
150 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 151 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, |
@@ -172,7 +173,7 @@ static int test_find_delalloc(void) | |||
172 | * |--- delalloc ---| | 173 | * |--- delalloc ---| |
173 | * |--- search ---| | 174 | * |--- search ---| |
174 | */ | 175 | */ |
175 | test_start = max_bytes + 4096; | 176 | test_start = max_bytes + sectorsize; |
176 | locked_page = find_lock_page(inode->i_mapping, test_start >> | 177 | locked_page = find_lock_page(inode->i_mapping, test_start >> |
177 | PAGE_SHIFT); | 178 | PAGE_SHIFT); |
178 | if (!locked_page) { | 179 | if (!locked_page) { |
@@ -272,6 +273,16 @@ out: | |||
272 | return ret; | 273 | return ret; |
273 | } | 274 | } |
274 | 275 | ||
276 | /** | ||
277 | * test_bit_in_byte - Determine whether a bit is set in a byte | ||
278 | * @nr: bit number to test | ||
279 | * @addr: Address to start counting from | ||
280 | */ | ||
281 | static inline int test_bit_in_byte(int nr, const u8 *addr) | ||
282 | { | ||
283 | return 1UL & (addr[nr / BITS_PER_BYTE] >> (nr & (BITS_PER_BYTE - 1))); | ||
284 | } | ||
285 | |||
275 | static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb, | 286 | static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb, |
276 | unsigned long len) | 287 | unsigned long len) |
277 | { | 288 | { |
@@ -298,25 +309,29 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb, | |||
298 | return -EINVAL; | 309 | return -EINVAL; |
299 | } | 310 | } |
300 | 311 | ||
301 | bitmap_set(bitmap, (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE, | 312 | /* Straddling pages test */ |
302 | sizeof(long) * BITS_PER_BYTE); | 313 | if (len > PAGE_SIZE) { |
303 | extent_buffer_bitmap_set(eb, PAGE_SIZE - sizeof(long) / 2, 0, | 314 | bitmap_set(bitmap, |
304 | sizeof(long) * BITS_PER_BYTE); | 315 | (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE, |
305 | if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { | 316 | sizeof(long) * BITS_PER_BYTE); |
306 | test_msg("Setting straddling pages failed\n"); | 317 | extent_buffer_bitmap_set(eb, PAGE_SIZE - sizeof(long) / 2, 0, |
307 | return -EINVAL; | 318 | sizeof(long) * BITS_PER_BYTE); |
308 | } | 319 | if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { |
320 | test_msg("Setting straddling pages failed\n"); | ||
321 | return -EINVAL; | ||
322 | } | ||
309 | 323 | ||
310 | bitmap_set(bitmap, 0, len * BITS_PER_BYTE); | 324 | bitmap_set(bitmap, 0, len * BITS_PER_BYTE); |
311 | bitmap_clear(bitmap, | 325 | bitmap_clear(bitmap, |
312 | (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE, | 326 | (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE, |
313 | sizeof(long) * BITS_PER_BYTE); | 327 | sizeof(long) * BITS_PER_BYTE); |
314 | extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE); | 328 | extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE); |
315 | extent_buffer_bitmap_clear(eb, PAGE_SIZE - sizeof(long) / 2, 0, | 329 | extent_buffer_bitmap_clear(eb, PAGE_SIZE - sizeof(long) / 2, 0, |
316 | sizeof(long) * BITS_PER_BYTE); | 330 | sizeof(long) * BITS_PER_BYTE); |
317 | if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { | 331 | if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { |
318 | test_msg("Clearing straddling pages failed\n"); | 332 | test_msg("Clearing straddling pages failed\n"); |
319 | return -EINVAL; | 333 | return -EINVAL; |
334 | } | ||
320 | } | 335 | } |
321 | 336 | ||
322 | /* | 337 | /* |
@@ -333,7 +348,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb, | |||
333 | for (i = 0; i < len * BITS_PER_BYTE; i++) { | 348 | for (i = 0; i < len * BITS_PER_BYTE; i++) { |
334 | int bit, bit1; | 349 | int bit, bit1; |
335 | 350 | ||
336 | bit = !!test_bit(i, bitmap); | 351 | bit = !!test_bit_in_byte(i, (u8 *)bitmap); |
337 | bit1 = !!extent_buffer_test_bit(eb, 0, i); | 352 | bit1 = !!extent_buffer_test_bit(eb, 0, i); |
338 | if (bit1 != bit) { | 353 | if (bit1 != bit) { |
339 | test_msg("Testing bit pattern failed\n"); | 354 | test_msg("Testing bit pattern failed\n"); |
@@ -351,15 +366,22 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb, | |||
351 | return 0; | 366 | return 0; |
352 | } | 367 | } |
353 | 368 | ||
354 | static int test_eb_bitmaps(void) | 369 | static int test_eb_bitmaps(u32 sectorsize, u32 nodesize) |
355 | { | 370 | { |
356 | unsigned long len = PAGE_SIZE * 4; | 371 | unsigned long len; |
357 | unsigned long *bitmap; | 372 | unsigned long *bitmap; |
358 | struct extent_buffer *eb; | 373 | struct extent_buffer *eb; |
359 | int ret; | 374 | int ret; |
360 | 375 | ||
361 | test_msg("Running extent buffer bitmap tests\n"); | 376 | test_msg("Running extent buffer bitmap tests\n"); |
362 | 377 | ||
378 | /* | ||
379 | * In ppc64, sectorsize can be 64K, thus 4 * 64K will be larger than | ||
380 | * BTRFS_MAX_METADATA_BLOCKSIZE. | ||
381 | */ | ||
382 | len = (sectorsize < BTRFS_MAX_METADATA_BLOCKSIZE) | ||
383 | ? sectorsize * 4 : sectorsize; | ||
384 | |||
363 | bitmap = kmalloc(len, GFP_KERNEL); | 385 | bitmap = kmalloc(len, GFP_KERNEL); |
364 | if (!bitmap) { | 386 | if (!bitmap) { |
365 | test_msg("Couldn't allocate test bitmap\n"); | 387 | test_msg("Couldn't allocate test bitmap\n"); |
@@ -379,7 +401,7 @@ static int test_eb_bitmaps(void) | |||
379 | 401 | ||
380 | /* Do it over again with an extent buffer which isn't page-aligned. */ | 402 | /* Do it over again with an extent buffer which isn't page-aligned. */ |
381 | free_extent_buffer(eb); | 403 | free_extent_buffer(eb); |
382 | eb = __alloc_dummy_extent_buffer(NULL, PAGE_SIZE / 2, len); | 404 | eb = __alloc_dummy_extent_buffer(NULL, nodesize / 2, len); |
383 | if (!eb) { | 405 | if (!eb) { |
384 | test_msg("Couldn't allocate test extent buffer\n"); | 406 | test_msg("Couldn't allocate test extent buffer\n"); |
385 | kfree(bitmap); | 407 | kfree(bitmap); |
@@ -393,17 +415,17 @@ out: | |||
393 | return ret; | 415 | return ret; |
394 | } | 416 | } |
395 | 417 | ||
396 | int btrfs_test_extent_io(void) | 418 | int btrfs_test_extent_io(u32 sectorsize, u32 nodesize) |
397 | { | 419 | { |
398 | int ret; | 420 | int ret; |
399 | 421 | ||
400 | test_msg("Running extent I/O tests\n"); | 422 | test_msg("Running extent I/O tests\n"); |
401 | 423 | ||
402 | ret = test_find_delalloc(); | 424 | ret = test_find_delalloc(sectorsize); |
403 | if (ret) | 425 | if (ret) |
404 | goto out; | 426 | goto out; |
405 | 427 | ||
406 | ret = test_eb_bitmaps(); | 428 | ret = test_eb_bitmaps(sectorsize, nodesize); |
407 | out: | 429 | out: |
408 | test_msg("Extent I/O tests finished\n"); | 430 | test_msg("Extent I/O tests finished\n"); |
409 | return ret; | 431 | return ret; |
diff --git a/fs/btrfs/tests/free-space-tests.c b/fs/btrfs/tests/free-space-tests.c index 0eeb8f3d6b67..3956bb2ff84c 100644 --- a/fs/btrfs/tests/free-space-tests.c +++ b/fs/btrfs/tests/free-space-tests.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "../disk-io.h" | 22 | #include "../disk-io.h" |
23 | #include "../free-space-cache.h" | 23 | #include "../free-space-cache.h" |
24 | 24 | ||
25 | #define BITS_PER_BITMAP (PAGE_SIZE * 8) | 25 | #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * This test just does basic sanity checking, making sure we can add an extent | 28 | * This test just does basic sanity checking, making sure we can add an extent |
@@ -99,7 +99,8 @@ static int test_extents(struct btrfs_block_group_cache *cache) | |||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | static int test_bitmaps(struct btrfs_block_group_cache *cache) | 102 | static int test_bitmaps(struct btrfs_block_group_cache *cache, |
103 | u32 sectorsize) | ||
103 | { | 104 | { |
104 | u64 next_bitmap_offset; | 105 | u64 next_bitmap_offset; |
105 | int ret; | 106 | int ret; |
@@ -139,7 +140,7 @@ static int test_bitmaps(struct btrfs_block_group_cache *cache) | |||
139 | * The first bitmap we have starts at offset 0 so the next one is just | 140 | * The first bitmap we have starts at offset 0 so the next one is just |
140 | * at the end of the first bitmap. | 141 | * at the end of the first bitmap. |
141 | */ | 142 | */ |
142 | next_bitmap_offset = (u64)(BITS_PER_BITMAP * 4096); | 143 | next_bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize); |
143 | 144 | ||
144 | /* Test a bit straddling two bitmaps */ | 145 | /* Test a bit straddling two bitmaps */ |
145 | ret = test_add_free_space_entry(cache, next_bitmap_offset - SZ_2M, | 146 | ret = test_add_free_space_entry(cache, next_bitmap_offset - SZ_2M, |
@@ -167,9 +168,10 @@ static int test_bitmaps(struct btrfs_block_group_cache *cache) | |||
167 | } | 168 | } |
168 | 169 | ||
169 | /* This is the high grade jackassery */ | 170 | /* This is the high grade jackassery */ |
170 | static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache) | 171 | static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache, |
172 | u32 sectorsize) | ||
171 | { | 173 | { |
172 | u64 bitmap_offset = (u64)(BITS_PER_BITMAP * 4096); | 174 | u64 bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize); |
173 | int ret; | 175 | int ret; |
174 | 176 | ||
175 | test_msg("Running bitmap and extent tests\n"); | 177 | test_msg("Running bitmap and extent tests\n"); |
@@ -401,7 +403,8 @@ static int check_cache_empty(struct btrfs_block_group_cache *cache) | |||
401 | * requests. | 403 | * requests. |
402 | */ | 404 | */ |
403 | static int | 405 | static int |
404 | test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | 406 | test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache, |
407 | u32 sectorsize) | ||
405 | { | 408 | { |
406 | int ret; | 409 | int ret; |
407 | u64 offset; | 410 | u64 offset; |
@@ -539,7 +542,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
539 | * The goal is to test that the bitmap entry space stealing doesn't | 542 | * The goal is to test that the bitmap entry space stealing doesn't |
540 | * steal this space region. | 543 | * steal this space region. |
541 | */ | 544 | */ |
542 | ret = btrfs_add_free_space(cache, SZ_128M + SZ_16M, 4096); | 545 | ret = btrfs_add_free_space(cache, SZ_128M + SZ_16M, sectorsize); |
543 | if (ret) { | 546 | if (ret) { |
544 | test_msg("Error adding free space: %d\n", ret); | 547 | test_msg("Error adding free space: %d\n", ret); |
545 | return ret; | 548 | return ret; |
@@ -597,8 +600,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
597 | return -ENOENT; | 600 | return -ENOENT; |
598 | } | 601 | } |
599 | 602 | ||
600 | if (cache->free_space_ctl->free_space != (SZ_1M + 4096)) { | 603 | if (cache->free_space_ctl->free_space != (SZ_1M + sectorsize)) { |
601 | test_msg("Cache free space is not 1Mb + 4Kb\n"); | 604 | test_msg("Cache free space is not 1Mb + %u\n", sectorsize); |
602 | return -EINVAL; | 605 | return -EINVAL; |
603 | } | 606 | } |
604 | 607 | ||
@@ -611,22 +614,25 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
611 | return -EINVAL; | 614 | return -EINVAL; |
612 | } | 615 | } |
613 | 616 | ||
614 | /* All that remains is a 4Kb free space region in a bitmap. Confirm. */ | 617 | /* |
618 | * All that remains is a sectorsize free space region in a bitmap. | ||
619 | * Confirm. | ||
620 | */ | ||
615 | ret = check_num_extents_and_bitmaps(cache, 1, 1); | 621 | ret = check_num_extents_and_bitmaps(cache, 1, 1); |
616 | if (ret) | 622 | if (ret) |
617 | return ret; | 623 | return ret; |
618 | 624 | ||
619 | if (cache->free_space_ctl->free_space != 4096) { | 625 | if (cache->free_space_ctl->free_space != sectorsize) { |
620 | test_msg("Cache free space is not 4Kb\n"); | 626 | test_msg("Cache free space is not %u\n", sectorsize); |
621 | return -EINVAL; | 627 | return -EINVAL; |
622 | } | 628 | } |
623 | 629 | ||
624 | offset = btrfs_find_space_for_alloc(cache, | 630 | offset = btrfs_find_space_for_alloc(cache, |
625 | 0, 4096, 0, | 631 | 0, sectorsize, 0, |
626 | &max_extent_size); | 632 | &max_extent_size); |
627 | if (offset != (SZ_128M + SZ_16M)) { | 633 | if (offset != (SZ_128M + SZ_16M)) { |
628 | test_msg("Failed to allocate 4Kb from space cache, returned offset is: %llu\n", | 634 | test_msg("Failed to allocate %u, returned offset : %llu\n", |
629 | offset); | 635 | sectorsize, offset); |
630 | return -EINVAL; | 636 | return -EINVAL; |
631 | } | 637 | } |
632 | 638 | ||
@@ -733,7 +739,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
733 | * The goal is to test that the bitmap entry space stealing doesn't | 739 | * The goal is to test that the bitmap entry space stealing doesn't |
734 | * steal this space region. | 740 | * steal this space region. |
735 | */ | 741 | */ |
736 | ret = btrfs_add_free_space(cache, SZ_32M, 8192); | 742 | ret = btrfs_add_free_space(cache, SZ_32M, 2 * sectorsize); |
737 | if (ret) { | 743 | if (ret) { |
738 | test_msg("Error adding free space: %d\n", ret); | 744 | test_msg("Error adding free space: %d\n", ret); |
739 | return ret; | 745 | return ret; |
@@ -757,7 +763,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
757 | 763 | ||
758 | /* | 764 | /* |
759 | * Confirm that our extent entry didn't stole all free space from the | 765 | * Confirm that our extent entry didn't stole all free space from the |
760 | * bitmap, because of the small 8Kb free space region. | 766 | * bitmap, because of the small 2 * sectorsize free space region. |
761 | */ | 767 | */ |
762 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | 768 | ret = check_num_extents_and_bitmaps(cache, 2, 1); |
763 | if (ret) | 769 | if (ret) |
@@ -783,8 +789,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
783 | return -ENOENT; | 789 | return -ENOENT; |
784 | } | 790 | } |
785 | 791 | ||
786 | if (cache->free_space_ctl->free_space != (SZ_1M + 8192)) { | 792 | if (cache->free_space_ctl->free_space != (SZ_1M + 2 * sectorsize)) { |
787 | test_msg("Cache free space is not 1Mb + 8Kb\n"); | 793 | test_msg("Cache free space is not 1Mb + %u\n", 2 * sectorsize); |
788 | return -EINVAL; | 794 | return -EINVAL; |
789 | } | 795 | } |
790 | 796 | ||
@@ -796,21 +802,25 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
796 | return -EINVAL; | 802 | return -EINVAL; |
797 | } | 803 | } |
798 | 804 | ||
799 | /* All that remains is a 8Kb free space region in a bitmap. Confirm. */ | 805 | /* |
806 | * All that remains is 2 * sectorsize free space region | ||
807 | * in a bitmap. Confirm. | ||
808 | */ | ||
800 | ret = check_num_extents_and_bitmaps(cache, 1, 1); | 809 | ret = check_num_extents_and_bitmaps(cache, 1, 1); |
801 | if (ret) | 810 | if (ret) |
802 | return ret; | 811 | return ret; |
803 | 812 | ||
804 | if (cache->free_space_ctl->free_space != 8192) { | 813 | if (cache->free_space_ctl->free_space != 2 * sectorsize) { |
805 | test_msg("Cache free space is not 8Kb\n"); | 814 | test_msg("Cache free space is not %u\n", 2 * sectorsize); |
806 | return -EINVAL; | 815 | return -EINVAL; |
807 | } | 816 | } |
808 | 817 | ||
809 | offset = btrfs_find_space_for_alloc(cache, | 818 | offset = btrfs_find_space_for_alloc(cache, |
810 | 0, 8192, 0, | 819 | 0, 2 * sectorsize, 0, |
811 | &max_extent_size); | 820 | &max_extent_size); |
812 | if (offset != SZ_32M) { | 821 | if (offset != SZ_32M) { |
813 | test_msg("Failed to allocate 8Kb from space cache, returned offset is: %llu\n", | 822 | test_msg("Failed to allocate %u, offset: %llu\n", |
823 | 2 * sectorsize, | ||
814 | offset); | 824 | offset); |
815 | return -EINVAL; | 825 | return -EINVAL; |
816 | } | 826 | } |
@@ -825,7 +835,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache) | |||
825 | return 0; | 835 | return 0; |
826 | } | 836 | } |
827 | 837 | ||
828 | int btrfs_test_free_space_cache(void) | 838 | int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize) |
829 | { | 839 | { |
830 | struct btrfs_block_group_cache *cache; | 840 | struct btrfs_block_group_cache *cache; |
831 | struct btrfs_root *root = NULL; | 841 | struct btrfs_root *root = NULL; |
@@ -833,13 +843,19 @@ int btrfs_test_free_space_cache(void) | |||
833 | 843 | ||
834 | test_msg("Running btrfs free space cache tests\n"); | 844 | test_msg("Running btrfs free space cache tests\n"); |
835 | 845 | ||
836 | cache = btrfs_alloc_dummy_block_group(1024 * 1024 * 1024); | 846 | /* |
847 | * For ppc64 (with 64k page size), bytes per bitmap might be | ||
848 | * larger than 1G. To make bitmap test available in ppc64, | ||
849 | * alloc dummy block group whose size cross bitmaps. | ||
850 | */ | ||
851 | cache = btrfs_alloc_dummy_block_group(BITS_PER_BITMAP * sectorsize | ||
852 | + PAGE_SIZE, sectorsize); | ||
837 | if (!cache) { | 853 | if (!cache) { |
838 | test_msg("Couldn't run the tests\n"); | 854 | test_msg("Couldn't run the tests\n"); |
839 | return 0; | 855 | return 0; |
840 | } | 856 | } |
841 | 857 | ||
842 | root = btrfs_alloc_dummy_root(); | 858 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
843 | if (IS_ERR(root)) { | 859 | if (IS_ERR(root)) { |
844 | ret = PTR_ERR(root); | 860 | ret = PTR_ERR(root); |
845 | goto out; | 861 | goto out; |
@@ -855,14 +871,14 @@ int btrfs_test_free_space_cache(void) | |||
855 | ret = test_extents(cache); | 871 | ret = test_extents(cache); |
856 | if (ret) | 872 | if (ret) |
857 | goto out; | 873 | goto out; |
858 | ret = test_bitmaps(cache); | 874 | ret = test_bitmaps(cache, sectorsize); |
859 | if (ret) | 875 | if (ret) |
860 | goto out; | 876 | goto out; |
861 | ret = test_bitmaps_and_extents(cache); | 877 | ret = test_bitmaps_and_extents(cache, sectorsize); |
862 | if (ret) | 878 | if (ret) |
863 | goto out; | 879 | goto out; |
864 | 880 | ||
865 | ret = test_steal_space_from_bitmap_to_extent(cache); | 881 | ret = test_steal_space_from_bitmap_to_extent(cache, sectorsize); |
866 | out: | 882 | out: |
867 | btrfs_free_dummy_block_group(cache); | 883 | btrfs_free_dummy_block_group(cache); |
868 | btrfs_free_dummy_root(root); | 884 | btrfs_free_dummy_root(root); |
diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c index 7cea4462acd5..aac507085ab0 100644 --- a/fs/btrfs/tests/free-space-tree-tests.c +++ b/fs/btrfs/tests/free-space-tree-tests.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/types.h> | ||
19 | #include "btrfs-tests.h" | 20 | #include "btrfs-tests.h" |
20 | #include "../ctree.h" | 21 | #include "../ctree.h" |
21 | #include "../disk-io.h" | 22 | #include "../disk-io.h" |
@@ -30,7 +31,7 @@ struct free_space_extent { | |||
30 | * The test cases align their operations to this in order to hit some of the | 31 | * The test cases align their operations to this in order to hit some of the |
31 | * edge cases in the bitmap code. | 32 | * edge cases in the bitmap code. |
32 | */ | 33 | */ |
33 | #define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * 4096) | 34 | #define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE) |
34 | 35 | ||
35 | static int __check_free_space_extents(struct btrfs_trans_handle *trans, | 36 | static int __check_free_space_extents(struct btrfs_trans_handle *trans, |
36 | struct btrfs_fs_info *fs_info, | 37 | struct btrfs_fs_info *fs_info, |
@@ -439,7 +440,8 @@ typedef int (*test_func_t)(struct btrfs_trans_handle *, | |||
439 | struct btrfs_block_group_cache *, | 440 | struct btrfs_block_group_cache *, |
440 | struct btrfs_path *); | 441 | struct btrfs_path *); |
441 | 442 | ||
442 | static int run_test(test_func_t test_func, int bitmaps) | 443 | static int run_test(test_func_t test_func, int bitmaps, |
444 | u32 sectorsize, u32 nodesize) | ||
443 | { | 445 | { |
444 | struct btrfs_root *root = NULL; | 446 | struct btrfs_root *root = NULL; |
445 | struct btrfs_block_group_cache *cache = NULL; | 447 | struct btrfs_block_group_cache *cache = NULL; |
@@ -447,7 +449,7 @@ static int run_test(test_func_t test_func, int bitmaps) | |||
447 | struct btrfs_path *path = NULL; | 449 | struct btrfs_path *path = NULL; |
448 | int ret; | 450 | int ret; |
449 | 451 | ||
450 | root = btrfs_alloc_dummy_root(); | 452 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
451 | if (IS_ERR(root)) { | 453 | if (IS_ERR(root)) { |
452 | test_msg("Couldn't allocate dummy root\n"); | 454 | test_msg("Couldn't allocate dummy root\n"); |
453 | ret = PTR_ERR(root); | 455 | ret = PTR_ERR(root); |
@@ -466,7 +468,8 @@ static int run_test(test_func_t test_func, int bitmaps) | |||
466 | root->fs_info->free_space_root = root; | 468 | root->fs_info->free_space_root = root; |
467 | root->fs_info->tree_root = root; | 469 | root->fs_info->tree_root = root; |
468 | 470 | ||
469 | root->node = alloc_test_extent_buffer(root->fs_info, 4096); | 471 | root->node = alloc_test_extent_buffer(root->fs_info, |
472 | nodesize, nodesize); | ||
470 | if (!root->node) { | 473 | if (!root->node) { |
471 | test_msg("Couldn't allocate dummy buffer\n"); | 474 | test_msg("Couldn't allocate dummy buffer\n"); |
472 | ret = -ENOMEM; | 475 | ret = -ENOMEM; |
@@ -474,9 +477,9 @@ static int run_test(test_func_t test_func, int bitmaps) | |||
474 | } | 477 | } |
475 | btrfs_set_header_level(root->node, 0); | 478 | btrfs_set_header_level(root->node, 0); |
476 | btrfs_set_header_nritems(root->node, 0); | 479 | btrfs_set_header_nritems(root->node, 0); |
477 | root->alloc_bytenr += 8192; | 480 | root->alloc_bytenr += 2 * nodesize; |
478 | 481 | ||
479 | cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE); | 482 | cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE, sectorsize); |
480 | if (!cache) { | 483 | if (!cache) { |
481 | test_msg("Couldn't allocate dummy block group cache\n"); | 484 | test_msg("Couldn't allocate dummy block group cache\n"); |
482 | ret = -ENOMEM; | 485 | ret = -ENOMEM; |
@@ -534,17 +537,18 @@ out: | |||
534 | return ret; | 537 | return ret; |
535 | } | 538 | } |
536 | 539 | ||
537 | static int run_test_both_formats(test_func_t test_func) | 540 | static int run_test_both_formats(test_func_t test_func, |
541 | u32 sectorsize, u32 nodesize) | ||
538 | { | 542 | { |
539 | int ret; | 543 | int ret; |
540 | 544 | ||
541 | ret = run_test(test_func, 0); | 545 | ret = run_test(test_func, 0, sectorsize, nodesize); |
542 | if (ret) | 546 | if (ret) |
543 | return ret; | 547 | return ret; |
544 | return run_test(test_func, 1); | 548 | return run_test(test_func, 1, sectorsize, nodesize); |
545 | } | 549 | } |
546 | 550 | ||
547 | int btrfs_test_free_space_tree(void) | 551 | int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize) |
548 | { | 552 | { |
549 | test_func_t tests[] = { | 553 | test_func_t tests[] = { |
550 | test_empty_block_group, | 554 | test_empty_block_group, |
@@ -561,9 +565,11 @@ int btrfs_test_free_space_tree(void) | |||
561 | 565 | ||
562 | test_msg("Running free space tree tests\n"); | 566 | test_msg("Running free space tree tests\n"); |
563 | for (i = 0; i < ARRAY_SIZE(tests); i++) { | 567 | for (i = 0; i < ARRAY_SIZE(tests); i++) { |
564 | int ret = run_test_both_formats(tests[i]); | 568 | int ret = run_test_both_formats(tests[i], sectorsize, |
569 | nodesize); | ||
565 | if (ret) { | 570 | if (ret) { |
566 | test_msg("%pf failed\n", tests[i]); | 571 | test_msg("%pf : sectorsize %u failed\n", |
572 | tests[i], sectorsize); | ||
567 | return ret; | 573 | return ret; |
568 | } | 574 | } |
569 | } | 575 | } |
diff --git a/fs/btrfs/tests/inode-tests.c b/fs/btrfs/tests/inode-tests.c index 8a25fe8b7c45..29648c0a39f1 100644 --- a/fs/btrfs/tests/inode-tests.c +++ b/fs/btrfs/tests/inode-tests.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/types.h> | ||
19 | #include "btrfs-tests.h" | 20 | #include "btrfs-tests.h" |
20 | #include "../ctree.h" | 21 | #include "../ctree.h" |
21 | #include "../btrfs_inode.h" | 22 | #include "../btrfs_inode.h" |
@@ -86,19 +87,19 @@ static void insert_inode_item_key(struct btrfs_root *root) | |||
86 | * diagram of how the extents will look though this may not be possible we still | 87 | * diagram of how the extents will look though this may not be possible we still |
87 | * want to make sure everything acts normally (the last number is not inclusive) | 88 | * want to make sure everything acts normally (the last number is not inclusive) |
88 | * | 89 | * |
89 | * [0 - 5][5 - 6][6 - 10][10 - 4096][ 4096 - 8192 ][8192 - 12288] | 90 | * [0 - 5][5 - 6][ 6 - 4096 ][ 4096 - 4100][4100 - 8195][8195 - 12291] |
90 | * [hole ][inline][ hole ][ regular ][regular1 split][ hole ] | 91 | * [hole ][inline][hole but no extent][ hole ][ regular ][regular1 split] |
91 | * | 92 | * |
92 | * [ 12288 - 20480][20480 - 24576][ 24576 - 28672 ][28672 - 36864][36864 - 45056] | 93 | * [12291 - 16387][16387 - 24579][24579 - 28675][ 28675 - 32771][32771 - 36867 ] |
93 | * [regular1 split][ prealloc1 ][prealloc1 written][ prealloc1 ][ compressed ] | 94 | * [ hole ][regular1 split][ prealloc ][ prealloc1 ][prealloc1 written] |
94 | * | 95 | * |
95 | * [45056 - 49152][49152-53248][53248-61440][61440-65536][ 65536+81920 ] | 96 | * [36867 - 45059][45059 - 53251][53251 - 57347][57347 - 61443][61443- 69635] |
96 | * [ compressed1 ][ regular ][compressed1][ regular ][ hole but no extent] | 97 | * [ prealloc1 ][ compressed ][ compressed1 ][ regular ][ compressed1] |
97 | * | 98 | * |
98 | * [81920-86016] | 99 | * [69635-73731][ 73731 - 86019 ][86019-90115] |
99 | * [ regular ] | 100 | * [ regular ][ hole but no extent][ regular ] |
100 | */ | 101 | */ |
101 | static void setup_file_extents(struct btrfs_root *root) | 102 | static void setup_file_extents(struct btrfs_root *root, u32 sectorsize) |
102 | { | 103 | { |
103 | int slot = 0; | 104 | int slot = 0; |
104 | u64 disk_bytenr = SZ_1M; | 105 | u64 disk_bytenr = SZ_1M; |
@@ -119,7 +120,7 @@ static void setup_file_extents(struct btrfs_root *root) | |||
119 | insert_extent(root, offset, 1, 1, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0, | 120 | insert_extent(root, offset, 1, 1, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0, |
120 | slot); | 121 | slot); |
121 | slot++; | 122 | slot++; |
122 | offset = 4096; | 123 | offset = sectorsize; |
123 | 124 | ||
124 | /* Now another hole */ | 125 | /* Now another hole */ |
125 | insert_extent(root, offset, 4, 4, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0, | 126 | insert_extent(root, offset, 4, 4, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0, |
@@ -128,99 +129,106 @@ static void setup_file_extents(struct btrfs_root *root) | |||
128 | offset += 4; | 129 | offset += 4; |
129 | 130 | ||
130 | /* Now for a regular extent */ | 131 | /* Now for a regular extent */ |
131 | insert_extent(root, offset, 4095, 4095, 0, disk_bytenr, 4096, | 132 | insert_extent(root, offset, sectorsize - 1, sectorsize - 1, 0, |
132 | BTRFS_FILE_EXTENT_REG, 0, slot); | 133 | disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); |
133 | slot++; | 134 | slot++; |
134 | disk_bytenr += 4096; | 135 | disk_bytenr += sectorsize; |
135 | offset += 4095; | 136 | offset += sectorsize - 1; |
136 | 137 | ||
137 | /* | 138 | /* |
138 | * Now for 3 extents that were split from a hole punch so we test | 139 | * Now for 3 extents that were split from a hole punch so we test |
139 | * offsets properly. | 140 | * offsets properly. |
140 | */ | 141 | */ |
141 | insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 16384, | 142 | insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr, |
142 | BTRFS_FILE_EXTENT_REG, 0, slot); | 143 | 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); |
143 | slot++; | 144 | slot++; |
144 | offset += 4096; | 145 | offset += sectorsize; |
145 | insert_extent(root, offset, 4096, 4096, 0, 0, 0, BTRFS_FILE_EXTENT_REG, | 146 | insert_extent(root, offset, sectorsize, sectorsize, 0, 0, 0, |
146 | 0, slot); | 147 | BTRFS_FILE_EXTENT_REG, 0, slot); |
147 | slot++; | 148 | slot++; |
148 | offset += 4096; | 149 | offset += sectorsize; |
149 | insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 16384, | 150 | insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize, |
151 | 2 * sectorsize, disk_bytenr, 4 * sectorsize, | ||
150 | BTRFS_FILE_EXTENT_REG, 0, slot); | 152 | BTRFS_FILE_EXTENT_REG, 0, slot); |
151 | slot++; | 153 | slot++; |
152 | offset += 8192; | 154 | offset += 2 * sectorsize; |
153 | disk_bytenr += 16384; | 155 | disk_bytenr += 4 * sectorsize; |
154 | 156 | ||
155 | /* Now for a unwritten prealloc extent */ | 157 | /* Now for a unwritten prealloc extent */ |
156 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096, | 158 | insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr, |
157 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); | 159 | sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot); |
158 | slot++; | 160 | slot++; |
159 | offset += 4096; | 161 | offset += sectorsize; |
160 | 162 | ||
161 | /* | 163 | /* |
162 | * We want to jack up disk_bytenr a little more so the em stuff doesn't | 164 | * We want to jack up disk_bytenr a little more so the em stuff doesn't |
163 | * merge our records. | 165 | * merge our records. |
164 | */ | 166 | */ |
165 | disk_bytenr += 8192; | 167 | disk_bytenr += 2 * sectorsize; |
166 | 168 | ||
167 | /* | 169 | /* |
168 | * Now for a partially written prealloc extent, basically the same as | 170 | * Now for a partially written prealloc extent, basically the same as |
169 | * the hole punch example above. Ram_bytes never changes when you mark | 171 | * the hole punch example above. Ram_bytes never changes when you mark |
170 | * extents written btw. | 172 | * extents written btw. |
171 | */ | 173 | */ |
172 | insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 16384, | 174 | insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr, |
173 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); | 175 | 4 * sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot); |
174 | slot++; | 176 | slot++; |
175 | offset += 4096; | 177 | offset += sectorsize; |
176 | insert_extent(root, offset, 4096, 16384, 4096, disk_bytenr, 16384, | 178 | insert_extent(root, offset, sectorsize, 4 * sectorsize, sectorsize, |
177 | BTRFS_FILE_EXTENT_REG, 0, slot); | 179 | disk_bytenr, 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, |
180 | slot); | ||
178 | slot++; | 181 | slot++; |
179 | offset += 4096; | 182 | offset += sectorsize; |
180 | insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 16384, | 183 | insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize, |
184 | 2 * sectorsize, disk_bytenr, 4 * sectorsize, | ||
181 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); | 185 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); |
182 | slot++; | 186 | slot++; |
183 | offset += 8192; | 187 | offset += 2 * sectorsize; |
184 | disk_bytenr += 16384; | 188 | disk_bytenr += 4 * sectorsize; |
185 | 189 | ||
186 | /* Now a normal compressed extent */ | 190 | /* Now a normal compressed extent */ |
187 | insert_extent(root, offset, 8192, 8192, 0, disk_bytenr, 4096, | 191 | insert_extent(root, offset, 2 * sectorsize, 2 * sectorsize, 0, |
188 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); | 192 | disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, |
193 | BTRFS_COMPRESS_ZLIB, slot); | ||
189 | slot++; | 194 | slot++; |
190 | offset += 8192; | 195 | offset += 2 * sectorsize; |
191 | /* No merges */ | 196 | /* No merges */ |
192 | disk_bytenr += 8192; | 197 | disk_bytenr += 2 * sectorsize; |
193 | 198 | ||
194 | /* Now a split compressed extent */ | 199 | /* Now a split compressed extent */ |
195 | insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 4096, | 200 | insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr, |
196 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); | 201 | sectorsize, BTRFS_FILE_EXTENT_REG, |
202 | BTRFS_COMPRESS_ZLIB, slot); | ||
197 | slot++; | 203 | slot++; |
198 | offset += 4096; | 204 | offset += sectorsize; |
199 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr + 4096, 4096, | 205 | insert_extent(root, offset, sectorsize, sectorsize, 0, |
206 | disk_bytenr + sectorsize, sectorsize, | ||
200 | BTRFS_FILE_EXTENT_REG, 0, slot); | 207 | BTRFS_FILE_EXTENT_REG, 0, slot); |
201 | slot++; | 208 | slot++; |
202 | offset += 4096; | 209 | offset += sectorsize; |
203 | insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 4096, | 210 | insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize, |
211 | 2 * sectorsize, disk_bytenr, sectorsize, | ||
204 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); | 212 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); |
205 | slot++; | 213 | slot++; |
206 | offset += 8192; | 214 | offset += 2 * sectorsize; |
207 | disk_bytenr += 8192; | 215 | disk_bytenr += 2 * sectorsize; |
208 | 216 | ||
209 | /* Now extents that have a hole but no hole extent */ | 217 | /* Now extents that have a hole but no hole extent */ |
210 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096, | 218 | insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr, |
211 | BTRFS_FILE_EXTENT_REG, 0, slot); | 219 | sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); |
212 | slot++; | 220 | slot++; |
213 | offset += 16384; | 221 | offset += 4 * sectorsize; |
214 | disk_bytenr += 4096; | 222 | disk_bytenr += sectorsize; |
215 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096, | 223 | insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr, |
216 | BTRFS_FILE_EXTENT_REG, 0, slot); | 224 | sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); |
217 | } | 225 | } |
218 | 226 | ||
219 | static unsigned long prealloc_only = 0; | 227 | static unsigned long prealloc_only = 0; |
220 | static unsigned long compressed_only = 0; | 228 | static unsigned long compressed_only = 0; |
221 | static unsigned long vacancy_only = 0; | 229 | static unsigned long vacancy_only = 0; |
222 | 230 | ||
223 | static noinline int test_btrfs_get_extent(void) | 231 | static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize) |
224 | { | 232 | { |
225 | struct inode *inode = NULL; | 233 | struct inode *inode = NULL; |
226 | struct btrfs_root *root = NULL; | 234 | struct btrfs_root *root = NULL; |
@@ -240,7 +248,7 @@ static noinline int test_btrfs_get_extent(void) | |||
240 | BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID; | 248 | BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID; |
241 | BTRFS_I(inode)->location.offset = 0; | 249 | BTRFS_I(inode)->location.offset = 0; |
242 | 250 | ||
243 | root = btrfs_alloc_dummy_root(); | 251 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
244 | if (IS_ERR(root)) { | 252 | if (IS_ERR(root)) { |
245 | test_msg("Couldn't allocate root\n"); | 253 | test_msg("Couldn't allocate root\n"); |
246 | goto out; | 254 | goto out; |
@@ -256,7 +264,7 @@ static noinline int test_btrfs_get_extent(void) | |||
256 | goto out; | 264 | goto out; |
257 | } | 265 | } |
258 | 266 | ||
259 | root->node = alloc_dummy_extent_buffer(NULL, 4096); | 267 | root->node = alloc_dummy_extent_buffer(NULL, nodesize, nodesize); |
260 | if (!root->node) { | 268 | if (!root->node) { |
261 | test_msg("Couldn't allocate dummy buffer\n"); | 269 | test_msg("Couldn't allocate dummy buffer\n"); |
262 | goto out; | 270 | goto out; |
@@ -273,7 +281,7 @@ static noinline int test_btrfs_get_extent(void) | |||
273 | 281 | ||
274 | /* First with no extents */ | 282 | /* First with no extents */ |
275 | BTRFS_I(inode)->root = root; | 283 | BTRFS_I(inode)->root = root; |
276 | em = btrfs_get_extent(inode, NULL, 0, 0, 4096, 0); | 284 | em = btrfs_get_extent(inode, NULL, 0, 0, sectorsize, 0); |
277 | if (IS_ERR(em)) { | 285 | if (IS_ERR(em)) { |
278 | em = NULL; | 286 | em = NULL; |
279 | test_msg("Got an error when we shouldn't have\n"); | 287 | test_msg("Got an error when we shouldn't have\n"); |
@@ -295,7 +303,7 @@ static noinline int test_btrfs_get_extent(void) | |||
295 | * setup_file_extents, so if you change anything there you need to | 303 | * setup_file_extents, so if you change anything there you need to |
296 | * update the comment and update the expected values below. | 304 | * update the comment and update the expected values below. |
297 | */ | 305 | */ |
298 | setup_file_extents(root); | 306 | setup_file_extents(root, sectorsize); |
299 | 307 | ||
300 | em = btrfs_get_extent(inode, NULL, 0, 0, (u64)-1, 0); | 308 | em = btrfs_get_extent(inode, NULL, 0, 0, (u64)-1, 0); |
301 | if (IS_ERR(em)) { | 309 | if (IS_ERR(em)) { |
@@ -318,7 +326,7 @@ static noinline int test_btrfs_get_extent(void) | |||
318 | offset = em->start + em->len; | 326 | offset = em->start + em->len; |
319 | free_extent_map(em); | 327 | free_extent_map(em); |
320 | 328 | ||
321 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 329 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
322 | if (IS_ERR(em)) { | 330 | if (IS_ERR(em)) { |
323 | test_msg("Got an error when we shouldn't have\n"); | 331 | test_msg("Got an error when we shouldn't have\n"); |
324 | goto out; | 332 | goto out; |
@@ -327,7 +335,8 @@ static noinline int test_btrfs_get_extent(void) | |||
327 | test_msg("Expected an inline, got %llu\n", em->block_start); | 335 | test_msg("Expected an inline, got %llu\n", em->block_start); |
328 | goto out; | 336 | goto out; |
329 | } | 337 | } |
330 | if (em->start != offset || em->len != 4091) { | 338 | |
339 | if (em->start != offset || em->len != (sectorsize - 5)) { | ||
331 | test_msg("Unexpected extent wanted start %llu len 1, got start " | 340 | test_msg("Unexpected extent wanted start %llu len 1, got start " |
332 | "%llu len %llu\n", offset, em->start, em->len); | 341 | "%llu len %llu\n", offset, em->start, em->len); |
333 | goto out; | 342 | goto out; |
@@ -344,7 +353,7 @@ static noinline int test_btrfs_get_extent(void) | |||
344 | offset = em->start + em->len; | 353 | offset = em->start + em->len; |
345 | free_extent_map(em); | 354 | free_extent_map(em); |
346 | 355 | ||
347 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 356 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
348 | if (IS_ERR(em)) { | 357 | if (IS_ERR(em)) { |
349 | test_msg("Got an error when we shouldn't have\n"); | 358 | test_msg("Got an error when we shouldn't have\n"); |
350 | goto out; | 359 | goto out; |
@@ -366,7 +375,7 @@ static noinline int test_btrfs_get_extent(void) | |||
366 | free_extent_map(em); | 375 | free_extent_map(em); |
367 | 376 | ||
368 | /* Regular extent */ | 377 | /* Regular extent */ |
369 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 378 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
370 | if (IS_ERR(em)) { | 379 | if (IS_ERR(em)) { |
371 | test_msg("Got an error when we shouldn't have\n"); | 380 | test_msg("Got an error when we shouldn't have\n"); |
372 | goto out; | 381 | goto out; |
@@ -375,7 +384,7 @@ static noinline int test_btrfs_get_extent(void) | |||
375 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 384 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
376 | goto out; | 385 | goto out; |
377 | } | 386 | } |
378 | if (em->start != offset || em->len != 4095) { | 387 | if (em->start != offset || em->len != sectorsize - 1) { |
379 | test_msg("Unexpected extent wanted start %llu len 4095, got " | 388 | test_msg("Unexpected extent wanted start %llu len 4095, got " |
380 | "start %llu len %llu\n", offset, em->start, em->len); | 389 | "start %llu len %llu\n", offset, em->start, em->len); |
381 | goto out; | 390 | goto out; |
@@ -393,7 +402,7 @@ static noinline int test_btrfs_get_extent(void) | |||
393 | free_extent_map(em); | 402 | free_extent_map(em); |
394 | 403 | ||
395 | /* The next 3 are split extents */ | 404 | /* The next 3 are split extents */ |
396 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 405 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
397 | if (IS_ERR(em)) { | 406 | if (IS_ERR(em)) { |
398 | test_msg("Got an error when we shouldn't have\n"); | 407 | test_msg("Got an error when we shouldn't have\n"); |
399 | goto out; | 408 | goto out; |
@@ -402,9 +411,10 @@ static noinline int test_btrfs_get_extent(void) | |||
402 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 411 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
403 | goto out; | 412 | goto out; |
404 | } | 413 | } |
405 | if (em->start != offset || em->len != 4096) { | 414 | if (em->start != offset || em->len != sectorsize) { |
406 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 415 | test_msg("Unexpected extent start %llu len %u, " |
407 | "start %llu len %llu\n", offset, em->start, em->len); | 416 | "got start %llu len %llu\n", |
417 | offset, sectorsize, em->start, em->len); | ||
408 | goto out; | 418 | goto out; |
409 | } | 419 | } |
410 | if (em->flags != 0) { | 420 | if (em->flags != 0) { |
@@ -421,7 +431,7 @@ static noinline int test_btrfs_get_extent(void) | |||
421 | offset = em->start + em->len; | 431 | offset = em->start + em->len; |
422 | free_extent_map(em); | 432 | free_extent_map(em); |
423 | 433 | ||
424 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 434 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
425 | if (IS_ERR(em)) { | 435 | if (IS_ERR(em)) { |
426 | test_msg("Got an error when we shouldn't have\n"); | 436 | test_msg("Got an error when we shouldn't have\n"); |
427 | goto out; | 437 | goto out; |
@@ -430,9 +440,10 @@ static noinline int test_btrfs_get_extent(void) | |||
430 | test_msg("Expected a hole, got %llu\n", em->block_start); | 440 | test_msg("Expected a hole, got %llu\n", em->block_start); |
431 | goto out; | 441 | goto out; |
432 | } | 442 | } |
433 | if (em->start != offset || em->len != 4096) { | 443 | if (em->start != offset || em->len != sectorsize) { |
434 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 444 | test_msg("Unexpected extent wanted start %llu len %u, " |
435 | "start %llu len %llu\n", offset, em->start, em->len); | 445 | "got start %llu len %llu\n", |
446 | offset, sectorsize, em->start, em->len); | ||
436 | goto out; | 447 | goto out; |
437 | } | 448 | } |
438 | if (em->flags != 0) { | 449 | if (em->flags != 0) { |
@@ -442,7 +453,7 @@ static noinline int test_btrfs_get_extent(void) | |||
442 | offset = em->start + em->len; | 453 | offset = em->start + em->len; |
443 | free_extent_map(em); | 454 | free_extent_map(em); |
444 | 455 | ||
445 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 456 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
446 | if (IS_ERR(em)) { | 457 | if (IS_ERR(em)) { |
447 | test_msg("Got an error when we shouldn't have\n"); | 458 | test_msg("Got an error when we shouldn't have\n"); |
448 | goto out; | 459 | goto out; |
@@ -451,9 +462,10 @@ static noinline int test_btrfs_get_extent(void) | |||
451 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 462 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
452 | goto out; | 463 | goto out; |
453 | } | 464 | } |
454 | if (em->start != offset || em->len != 8192) { | 465 | if (em->start != offset || em->len != 2 * sectorsize) { |
455 | test_msg("Unexpected extent wanted start %llu len 8192, got " | 466 | test_msg("Unexpected extent wanted start %llu len %u, " |
456 | "start %llu len %llu\n", offset, em->start, em->len); | 467 | "got start %llu len %llu\n", |
468 | offset, 2 * sectorsize, em->start, em->len); | ||
457 | goto out; | 469 | goto out; |
458 | } | 470 | } |
459 | if (em->flags != 0) { | 471 | if (em->flags != 0) { |
@@ -475,7 +487,7 @@ static noinline int test_btrfs_get_extent(void) | |||
475 | free_extent_map(em); | 487 | free_extent_map(em); |
476 | 488 | ||
477 | /* Prealloc extent */ | 489 | /* Prealloc extent */ |
478 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 490 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
479 | if (IS_ERR(em)) { | 491 | if (IS_ERR(em)) { |
480 | test_msg("Got an error when we shouldn't have\n"); | 492 | test_msg("Got an error when we shouldn't have\n"); |
481 | goto out; | 493 | goto out; |
@@ -484,9 +496,10 @@ static noinline int test_btrfs_get_extent(void) | |||
484 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 496 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
485 | goto out; | 497 | goto out; |
486 | } | 498 | } |
487 | if (em->start != offset || em->len != 4096) { | 499 | if (em->start != offset || em->len != sectorsize) { |
488 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 500 | test_msg("Unexpected extent wanted start %llu len %u, " |
489 | "start %llu len %llu\n", offset, em->start, em->len); | 501 | "got start %llu len %llu\n", |
502 | offset, sectorsize, em->start, em->len); | ||
490 | goto out; | 503 | goto out; |
491 | } | 504 | } |
492 | if (em->flags != prealloc_only) { | 505 | if (em->flags != prealloc_only) { |
@@ -503,7 +516,7 @@ static noinline int test_btrfs_get_extent(void) | |||
503 | free_extent_map(em); | 516 | free_extent_map(em); |
504 | 517 | ||
505 | /* The next 3 are a half written prealloc extent */ | 518 | /* The next 3 are a half written prealloc extent */ |
506 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 519 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
507 | if (IS_ERR(em)) { | 520 | if (IS_ERR(em)) { |
508 | test_msg("Got an error when we shouldn't have\n"); | 521 | test_msg("Got an error when we shouldn't have\n"); |
509 | goto out; | 522 | goto out; |
@@ -512,9 +525,10 @@ static noinline int test_btrfs_get_extent(void) | |||
512 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 525 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
513 | goto out; | 526 | goto out; |
514 | } | 527 | } |
515 | if (em->start != offset || em->len != 4096) { | 528 | if (em->start != offset || em->len != sectorsize) { |
516 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 529 | test_msg("Unexpected extent wanted start %llu len %u, " |
517 | "start %llu len %llu\n", offset, em->start, em->len); | 530 | "got start %llu len %llu\n", |
531 | offset, sectorsize, em->start, em->len); | ||
518 | goto out; | 532 | goto out; |
519 | } | 533 | } |
520 | if (em->flags != prealloc_only) { | 534 | if (em->flags != prealloc_only) { |
@@ -532,7 +546,7 @@ static noinline int test_btrfs_get_extent(void) | |||
532 | offset = em->start + em->len; | 546 | offset = em->start + em->len; |
533 | free_extent_map(em); | 547 | free_extent_map(em); |
534 | 548 | ||
535 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 549 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
536 | if (IS_ERR(em)) { | 550 | if (IS_ERR(em)) { |
537 | test_msg("Got an error when we shouldn't have\n"); | 551 | test_msg("Got an error when we shouldn't have\n"); |
538 | goto out; | 552 | goto out; |
@@ -541,9 +555,10 @@ static noinline int test_btrfs_get_extent(void) | |||
541 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 555 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
542 | goto out; | 556 | goto out; |
543 | } | 557 | } |
544 | if (em->start != offset || em->len != 4096) { | 558 | if (em->start != offset || em->len != sectorsize) { |
545 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 559 | test_msg("Unexpected extent wanted start %llu len %u, " |
546 | "start %llu len %llu\n", offset, em->start, em->len); | 560 | "got start %llu len %llu\n", |
561 | offset, sectorsize, em->start, em->len); | ||
547 | goto out; | 562 | goto out; |
548 | } | 563 | } |
549 | if (em->flags != 0) { | 564 | if (em->flags != 0) { |
@@ -564,7 +579,7 @@ static noinline int test_btrfs_get_extent(void) | |||
564 | offset = em->start + em->len; | 579 | offset = em->start + em->len; |
565 | free_extent_map(em); | 580 | free_extent_map(em); |
566 | 581 | ||
567 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 582 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
568 | if (IS_ERR(em)) { | 583 | if (IS_ERR(em)) { |
569 | test_msg("Got an error when we shouldn't have\n"); | 584 | test_msg("Got an error when we shouldn't have\n"); |
570 | goto out; | 585 | goto out; |
@@ -573,9 +588,10 @@ static noinline int test_btrfs_get_extent(void) | |||
573 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 588 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
574 | goto out; | 589 | goto out; |
575 | } | 590 | } |
576 | if (em->start != offset || em->len != 8192) { | 591 | if (em->start != offset || em->len != 2 * sectorsize) { |
577 | test_msg("Unexpected extent wanted start %llu len 8192, got " | 592 | test_msg("Unexpected extent wanted start %llu len %u, " |
578 | "start %llu len %llu\n", offset, em->start, em->len); | 593 | "got start %llu len %llu\n", |
594 | offset, 2 * sectorsize, em->start, em->len); | ||
579 | goto out; | 595 | goto out; |
580 | } | 596 | } |
581 | if (em->flags != prealloc_only) { | 597 | if (em->flags != prealloc_only) { |
@@ -598,7 +614,7 @@ static noinline int test_btrfs_get_extent(void) | |||
598 | free_extent_map(em); | 614 | free_extent_map(em); |
599 | 615 | ||
600 | /* Now for the compressed extent */ | 616 | /* Now for the compressed extent */ |
601 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 617 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
602 | if (IS_ERR(em)) { | 618 | if (IS_ERR(em)) { |
603 | test_msg("Got an error when we shouldn't have\n"); | 619 | test_msg("Got an error when we shouldn't have\n"); |
604 | goto out; | 620 | goto out; |
@@ -607,9 +623,10 @@ static noinline int test_btrfs_get_extent(void) | |||
607 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 623 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
608 | goto out; | 624 | goto out; |
609 | } | 625 | } |
610 | if (em->start != offset || em->len != 8192) { | 626 | if (em->start != offset || em->len != 2 * sectorsize) { |
611 | test_msg("Unexpected extent wanted start %llu len 8192, got " | 627 | test_msg("Unexpected extent wanted start %llu len %u," |
612 | "start %llu len %llu\n", offset, em->start, em->len); | 628 | "got start %llu len %llu\n", |
629 | offset, 2 * sectorsize, em->start, em->len); | ||
613 | goto out; | 630 | goto out; |
614 | } | 631 | } |
615 | if (em->flags != compressed_only) { | 632 | if (em->flags != compressed_only) { |
@@ -631,7 +648,7 @@ static noinline int test_btrfs_get_extent(void) | |||
631 | free_extent_map(em); | 648 | free_extent_map(em); |
632 | 649 | ||
633 | /* Split compressed extent */ | 650 | /* Split compressed extent */ |
634 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 651 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
635 | if (IS_ERR(em)) { | 652 | if (IS_ERR(em)) { |
636 | test_msg("Got an error when we shouldn't have\n"); | 653 | test_msg("Got an error when we shouldn't have\n"); |
637 | goto out; | 654 | goto out; |
@@ -640,9 +657,10 @@ static noinline int test_btrfs_get_extent(void) | |||
640 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 657 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
641 | goto out; | 658 | goto out; |
642 | } | 659 | } |
643 | if (em->start != offset || em->len != 4096) { | 660 | if (em->start != offset || em->len != sectorsize) { |
644 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 661 | test_msg("Unexpected extent wanted start %llu len %u," |
645 | "start %llu len %llu\n", offset, em->start, em->len); | 662 | "got start %llu len %llu\n", |
663 | offset, sectorsize, em->start, em->len); | ||
646 | goto out; | 664 | goto out; |
647 | } | 665 | } |
648 | if (em->flags != compressed_only) { | 666 | if (em->flags != compressed_only) { |
@@ -665,7 +683,7 @@ static noinline int test_btrfs_get_extent(void) | |||
665 | offset = em->start + em->len; | 683 | offset = em->start + em->len; |
666 | free_extent_map(em); | 684 | free_extent_map(em); |
667 | 685 | ||
668 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 686 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
669 | if (IS_ERR(em)) { | 687 | if (IS_ERR(em)) { |
670 | test_msg("Got an error when we shouldn't have\n"); | 688 | test_msg("Got an error when we shouldn't have\n"); |
671 | goto out; | 689 | goto out; |
@@ -674,9 +692,10 @@ static noinline int test_btrfs_get_extent(void) | |||
674 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 692 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
675 | goto out; | 693 | goto out; |
676 | } | 694 | } |
677 | if (em->start != offset || em->len != 4096) { | 695 | if (em->start != offset || em->len != sectorsize) { |
678 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 696 | test_msg("Unexpected extent wanted start %llu len %u, " |
679 | "start %llu len %llu\n", offset, em->start, em->len); | 697 | "got start %llu len %llu\n", |
698 | offset, sectorsize, em->start, em->len); | ||
680 | goto out; | 699 | goto out; |
681 | } | 700 | } |
682 | if (em->flags != 0) { | 701 | if (em->flags != 0) { |
@@ -691,7 +710,7 @@ static noinline int test_btrfs_get_extent(void) | |||
691 | offset = em->start + em->len; | 710 | offset = em->start + em->len; |
692 | free_extent_map(em); | 711 | free_extent_map(em); |
693 | 712 | ||
694 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 713 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
695 | if (IS_ERR(em)) { | 714 | if (IS_ERR(em)) { |
696 | test_msg("Got an error when we shouldn't have\n"); | 715 | test_msg("Got an error when we shouldn't have\n"); |
697 | goto out; | 716 | goto out; |
@@ -701,9 +720,10 @@ static noinline int test_btrfs_get_extent(void) | |||
701 | disk_bytenr, em->block_start); | 720 | disk_bytenr, em->block_start); |
702 | goto out; | 721 | goto out; |
703 | } | 722 | } |
704 | if (em->start != offset || em->len != 8192) { | 723 | if (em->start != offset || em->len != 2 * sectorsize) { |
705 | test_msg("Unexpected extent wanted start %llu len 8192, got " | 724 | test_msg("Unexpected extent wanted start %llu len %u, " |
706 | "start %llu len %llu\n", offset, em->start, em->len); | 725 | "got start %llu len %llu\n", |
726 | offset, 2 * sectorsize, em->start, em->len); | ||
707 | goto out; | 727 | goto out; |
708 | } | 728 | } |
709 | if (em->flags != compressed_only) { | 729 | if (em->flags != compressed_only) { |
@@ -725,7 +745,7 @@ static noinline int test_btrfs_get_extent(void) | |||
725 | free_extent_map(em); | 745 | free_extent_map(em); |
726 | 746 | ||
727 | /* A hole between regular extents but no hole extent */ | 747 | /* A hole between regular extents but no hole extent */ |
728 | em = btrfs_get_extent(inode, NULL, 0, offset + 6, 4096, 0); | 748 | em = btrfs_get_extent(inode, NULL, 0, offset + 6, sectorsize, 0); |
729 | if (IS_ERR(em)) { | 749 | if (IS_ERR(em)) { |
730 | test_msg("Got an error when we shouldn't have\n"); | 750 | test_msg("Got an error when we shouldn't have\n"); |
731 | goto out; | 751 | goto out; |
@@ -734,9 +754,10 @@ static noinline int test_btrfs_get_extent(void) | |||
734 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 754 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
735 | goto out; | 755 | goto out; |
736 | } | 756 | } |
737 | if (em->start != offset || em->len != 4096) { | 757 | if (em->start != offset || em->len != sectorsize) { |
738 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 758 | test_msg("Unexpected extent wanted start %llu len %u, " |
739 | "start %llu len %llu\n", offset, em->start, em->len); | 759 | "got start %llu len %llu\n", |
760 | offset, sectorsize, em->start, em->len); | ||
740 | goto out; | 761 | goto out; |
741 | } | 762 | } |
742 | if (em->flags != 0) { | 763 | if (em->flags != 0) { |
@@ -765,9 +786,10 @@ static noinline int test_btrfs_get_extent(void) | |||
765 | * length of the actual hole, if this changes we'll have to change this | 786 | * length of the actual hole, if this changes we'll have to change this |
766 | * test. | 787 | * test. |
767 | */ | 788 | */ |
768 | if (em->start != offset || em->len != 12288) { | 789 | if (em->start != offset || em->len != 3 * sectorsize) { |
769 | test_msg("Unexpected extent wanted start %llu len 12288, got " | 790 | test_msg("Unexpected extent wanted start %llu len %u, " |
770 | "start %llu len %llu\n", offset, em->start, em->len); | 791 | "got start %llu len %llu\n", |
792 | offset, 3 * sectorsize, em->start, em->len); | ||
771 | goto out; | 793 | goto out; |
772 | } | 794 | } |
773 | if (em->flags != vacancy_only) { | 795 | if (em->flags != vacancy_only) { |
@@ -783,7 +805,7 @@ static noinline int test_btrfs_get_extent(void) | |||
783 | offset = em->start + em->len; | 805 | offset = em->start + em->len; |
784 | free_extent_map(em); | 806 | free_extent_map(em); |
785 | 807 | ||
786 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | 808 | em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0); |
787 | if (IS_ERR(em)) { | 809 | if (IS_ERR(em)) { |
788 | test_msg("Got an error when we shouldn't have\n"); | 810 | test_msg("Got an error when we shouldn't have\n"); |
789 | goto out; | 811 | goto out; |
@@ -792,9 +814,10 @@ static noinline int test_btrfs_get_extent(void) | |||
792 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 814 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
793 | goto out; | 815 | goto out; |
794 | } | 816 | } |
795 | if (em->start != offset || em->len != 4096) { | 817 | if (em->start != offset || em->len != sectorsize) { |
796 | test_msg("Unexpected extent wanted start %llu len 4096, got " | 818 | test_msg("Unexpected extent wanted start %llu len %u," |
797 | "start %llu len %llu\n", offset, em->start, em->len); | 819 | "got start %llu len %llu\n", |
820 | offset, sectorsize, em->start, em->len); | ||
798 | goto out; | 821 | goto out; |
799 | } | 822 | } |
800 | if (em->flags != 0) { | 823 | if (em->flags != 0) { |
@@ -815,7 +838,7 @@ out: | |||
815 | return ret; | 838 | return ret; |
816 | } | 839 | } |
817 | 840 | ||
818 | static int test_hole_first(void) | 841 | static int test_hole_first(u32 sectorsize, u32 nodesize) |
819 | { | 842 | { |
820 | struct inode *inode = NULL; | 843 | struct inode *inode = NULL; |
821 | struct btrfs_root *root = NULL; | 844 | struct btrfs_root *root = NULL; |
@@ -832,7 +855,7 @@ static int test_hole_first(void) | |||
832 | BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID; | 855 | BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID; |
833 | BTRFS_I(inode)->location.offset = 0; | 856 | BTRFS_I(inode)->location.offset = 0; |
834 | 857 | ||
835 | root = btrfs_alloc_dummy_root(); | 858 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
836 | if (IS_ERR(root)) { | 859 | if (IS_ERR(root)) { |
837 | test_msg("Couldn't allocate root\n"); | 860 | test_msg("Couldn't allocate root\n"); |
838 | goto out; | 861 | goto out; |
@@ -844,7 +867,7 @@ static int test_hole_first(void) | |||
844 | goto out; | 867 | goto out; |
845 | } | 868 | } |
846 | 869 | ||
847 | root->node = alloc_dummy_extent_buffer(NULL, 4096); | 870 | root->node = alloc_dummy_extent_buffer(NULL, nodesize, nodesize); |
848 | if (!root->node) { | 871 | if (!root->node) { |
849 | test_msg("Couldn't allocate dummy buffer\n"); | 872 | test_msg("Couldn't allocate dummy buffer\n"); |
850 | goto out; | 873 | goto out; |
@@ -861,9 +884,9 @@ static int test_hole_first(void) | |||
861 | * btrfs_get_extent. | 884 | * btrfs_get_extent. |
862 | */ | 885 | */ |
863 | insert_inode_item_key(root); | 886 | insert_inode_item_key(root); |
864 | insert_extent(root, 4096, 4096, 4096, 0, 4096, 4096, | 887 | insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize, |
865 | BTRFS_FILE_EXTENT_REG, 0, 1); | 888 | sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1); |
866 | em = btrfs_get_extent(inode, NULL, 0, 0, 8192, 0); | 889 | em = btrfs_get_extent(inode, NULL, 0, 0, 2 * sectorsize, 0); |
867 | if (IS_ERR(em)) { | 890 | if (IS_ERR(em)) { |
868 | test_msg("Got an error when we shouldn't have\n"); | 891 | test_msg("Got an error when we shouldn't have\n"); |
869 | goto out; | 892 | goto out; |
@@ -872,9 +895,10 @@ static int test_hole_first(void) | |||
872 | test_msg("Expected a hole, got %llu\n", em->block_start); | 895 | test_msg("Expected a hole, got %llu\n", em->block_start); |
873 | goto out; | 896 | goto out; |
874 | } | 897 | } |
875 | if (em->start != 0 || em->len != 4096) { | 898 | if (em->start != 0 || em->len != sectorsize) { |
876 | test_msg("Unexpected extent wanted start 0 len 4096, got start " | 899 | test_msg("Unexpected extent wanted start 0 len %u, " |
877 | "%llu len %llu\n", em->start, em->len); | 900 | "got start %llu len %llu\n", |
901 | sectorsize, em->start, em->len); | ||
878 | goto out; | 902 | goto out; |
879 | } | 903 | } |
880 | if (em->flags != vacancy_only) { | 904 | if (em->flags != vacancy_only) { |
@@ -884,18 +908,19 @@ static int test_hole_first(void) | |||
884 | } | 908 | } |
885 | free_extent_map(em); | 909 | free_extent_map(em); |
886 | 910 | ||
887 | em = btrfs_get_extent(inode, NULL, 0, 4096, 8192, 0); | 911 | em = btrfs_get_extent(inode, NULL, 0, sectorsize, 2 * sectorsize, 0); |
888 | if (IS_ERR(em)) { | 912 | if (IS_ERR(em)) { |
889 | test_msg("Got an error when we shouldn't have\n"); | 913 | test_msg("Got an error when we shouldn't have\n"); |
890 | goto out; | 914 | goto out; |
891 | } | 915 | } |
892 | if (em->block_start != 4096) { | 916 | if (em->block_start != sectorsize) { |
893 | test_msg("Expected a real extent, got %llu\n", em->block_start); | 917 | test_msg("Expected a real extent, got %llu\n", em->block_start); |
894 | goto out; | 918 | goto out; |
895 | } | 919 | } |
896 | if (em->start != 4096 || em->len != 4096) { | 920 | if (em->start != sectorsize || em->len != sectorsize) { |
897 | test_msg("Unexpected extent wanted start 4096 len 4096, got " | 921 | test_msg("Unexpected extent wanted start %u len %u, " |
898 | "start %llu len %llu\n", em->start, em->len); | 922 | "got start %llu len %llu\n", |
923 | sectorsize, sectorsize, em->start, em->len); | ||
899 | goto out; | 924 | goto out; |
900 | } | 925 | } |
901 | if (em->flags != 0) { | 926 | if (em->flags != 0) { |
@@ -912,7 +937,7 @@ out: | |||
912 | return ret; | 937 | return ret; |
913 | } | 938 | } |
914 | 939 | ||
915 | static int test_extent_accounting(void) | 940 | static int test_extent_accounting(u32 sectorsize, u32 nodesize) |
916 | { | 941 | { |
917 | struct inode *inode = NULL; | 942 | struct inode *inode = NULL; |
918 | struct btrfs_root *root = NULL; | 943 | struct btrfs_root *root = NULL; |
@@ -924,7 +949,7 @@ static int test_extent_accounting(void) | |||
924 | return ret; | 949 | return ret; |
925 | } | 950 | } |
926 | 951 | ||
927 | root = btrfs_alloc_dummy_root(); | 952 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
928 | if (IS_ERR(root)) { | 953 | if (IS_ERR(root)) { |
929 | test_msg("Couldn't allocate root\n"); | 954 | test_msg("Couldn't allocate root\n"); |
930 | goto out; | 955 | goto out; |
@@ -954,10 +979,11 @@ static int test_extent_accounting(void) | |||
954 | goto out; | 979 | goto out; |
955 | } | 980 | } |
956 | 981 | ||
957 | /* [BTRFS_MAX_EXTENT_SIZE][4k] */ | 982 | /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ |
958 | BTRFS_I(inode)->outstanding_extents++; | 983 | BTRFS_I(inode)->outstanding_extents++; |
959 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE, | 984 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE, |
960 | BTRFS_MAX_EXTENT_SIZE + 4095, NULL); | 985 | BTRFS_MAX_EXTENT_SIZE + sectorsize - 1, |
986 | NULL); | ||
961 | if (ret) { | 987 | if (ret) { |
962 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | 988 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); |
963 | goto out; | 989 | goto out; |
@@ -969,10 +995,10 @@ static int test_extent_accounting(void) | |||
969 | goto out; | 995 | goto out; |
970 | } | 996 | } |
971 | 997 | ||
972 | /* [BTRFS_MAX_EXTENT_SIZE/2][4K HOLE][the rest] */ | 998 | /* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */ |
973 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, | 999 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, |
974 | BTRFS_MAX_EXTENT_SIZE >> 1, | 1000 | BTRFS_MAX_EXTENT_SIZE >> 1, |
975 | (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095, | 1001 | (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1, |
976 | EXTENT_DELALLOC | EXTENT_DIRTY | | 1002 | EXTENT_DELALLOC | EXTENT_DIRTY | |
977 | EXTENT_UPTODATE | EXTENT_DO_ACCOUNTING, 0, 0, | 1003 | EXTENT_UPTODATE | EXTENT_DO_ACCOUNTING, 0, 0, |
978 | NULL, GFP_KERNEL); | 1004 | NULL, GFP_KERNEL); |
@@ -987,10 +1013,11 @@ static int test_extent_accounting(void) | |||
987 | goto out; | 1013 | goto out; |
988 | } | 1014 | } |
989 | 1015 | ||
990 | /* [BTRFS_MAX_EXTENT_SIZE][4K] */ | 1016 | /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ |
991 | BTRFS_I(inode)->outstanding_extents++; | 1017 | BTRFS_I(inode)->outstanding_extents++; |
992 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1, | 1018 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1, |
993 | (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095, | 1019 | (BTRFS_MAX_EXTENT_SIZE >> 1) |
1020 | + sectorsize - 1, | ||
994 | NULL); | 1021 | NULL); |
995 | if (ret) { | 1022 | if (ret) { |
996 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | 1023 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); |
@@ -1004,16 +1031,17 @@ static int test_extent_accounting(void) | |||
1004 | } | 1031 | } |
1005 | 1032 | ||
1006 | /* | 1033 | /* |
1007 | * [BTRFS_MAX_EXTENT_SIZE+4K][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4K] | 1034 | * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize] |
1008 | * | 1035 | * |
1009 | * I'm artificially adding 2 to outstanding_extents because in the | 1036 | * I'm artificially adding 2 to outstanding_extents because in the |
1010 | * buffered IO case we'd add things up as we go, but I don't feel like | 1037 | * buffered IO case we'd add things up as we go, but I don't feel like |
1011 | * doing that here, this isn't the interesting case we want to test. | 1038 | * doing that here, this isn't the interesting case we want to test. |
1012 | */ | 1039 | */ |
1013 | BTRFS_I(inode)->outstanding_extents += 2; | 1040 | BTRFS_I(inode)->outstanding_extents += 2; |
1014 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE + 8192, | 1041 | ret = btrfs_set_extent_delalloc(inode, |
1015 | (BTRFS_MAX_EXTENT_SIZE << 1) + 12287, | 1042 | BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize, |
1016 | NULL); | 1043 | (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1, |
1044 | NULL); | ||
1017 | if (ret) { | 1045 | if (ret) { |
1018 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | 1046 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); |
1019 | goto out; | 1047 | goto out; |
@@ -1025,10 +1053,13 @@ static int test_extent_accounting(void) | |||
1025 | goto out; | 1053 | goto out; |
1026 | } | 1054 | } |
1027 | 1055 | ||
1028 | /* [BTRFS_MAX_EXTENT_SIZE+4k][4k][BTRFS_MAX_EXTENT_SIZE+4k] */ | 1056 | /* |
1057 | * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize] | ||
1058 | */ | ||
1029 | BTRFS_I(inode)->outstanding_extents++; | 1059 | BTRFS_I(inode)->outstanding_extents++; |
1030 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096, | 1060 | ret = btrfs_set_extent_delalloc(inode, |
1031 | BTRFS_MAX_EXTENT_SIZE+8191, NULL); | 1061 | BTRFS_MAX_EXTENT_SIZE + sectorsize, |
1062 | BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL); | ||
1032 | if (ret) { | 1063 | if (ret) { |
1033 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | 1064 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); |
1034 | goto out; | 1065 | goto out; |
@@ -1042,8 +1073,8 @@ static int test_extent_accounting(void) | |||
1042 | 1073 | ||
1043 | /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */ | 1074 | /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */ |
1044 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, | 1075 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, |
1045 | BTRFS_MAX_EXTENT_SIZE+4096, | 1076 | BTRFS_MAX_EXTENT_SIZE + sectorsize, |
1046 | BTRFS_MAX_EXTENT_SIZE+8191, | 1077 | BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, |
1047 | EXTENT_DIRTY | EXTENT_DELALLOC | | 1078 | EXTENT_DIRTY | EXTENT_DELALLOC | |
1048 | EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0, | 1079 | EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0, |
1049 | NULL, GFP_KERNEL); | 1080 | NULL, GFP_KERNEL); |
@@ -1063,8 +1094,9 @@ static int test_extent_accounting(void) | |||
1063 | * might fail and I'd rather satisfy my paranoia at this point. | 1094 | * might fail and I'd rather satisfy my paranoia at this point. |
1064 | */ | 1095 | */ |
1065 | BTRFS_I(inode)->outstanding_extents++; | 1096 | BTRFS_I(inode)->outstanding_extents++; |
1066 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096, | 1097 | ret = btrfs_set_extent_delalloc(inode, |
1067 | BTRFS_MAX_EXTENT_SIZE+8191, NULL); | 1098 | BTRFS_MAX_EXTENT_SIZE + sectorsize, |
1099 | BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL); | ||
1068 | if (ret) { | 1100 | if (ret) { |
1069 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | 1101 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); |
1070 | goto out; | 1102 | goto out; |
@@ -1103,7 +1135,7 @@ out: | |||
1103 | return ret; | 1135 | return ret; |
1104 | } | 1136 | } |
1105 | 1137 | ||
1106 | int btrfs_test_inodes(void) | 1138 | int btrfs_test_inodes(u32 sectorsize, u32 nodesize) |
1107 | { | 1139 | { |
1108 | int ret; | 1140 | int ret; |
1109 | 1141 | ||
@@ -1112,13 +1144,13 @@ int btrfs_test_inodes(void) | |||
1112 | set_bit(EXTENT_FLAG_PREALLOC, &prealloc_only); | 1144 | set_bit(EXTENT_FLAG_PREALLOC, &prealloc_only); |
1113 | 1145 | ||
1114 | test_msg("Running btrfs_get_extent tests\n"); | 1146 | test_msg("Running btrfs_get_extent tests\n"); |
1115 | ret = test_btrfs_get_extent(); | 1147 | ret = test_btrfs_get_extent(sectorsize, nodesize); |
1116 | if (ret) | 1148 | if (ret) |
1117 | return ret; | 1149 | return ret; |
1118 | test_msg("Running hole first btrfs_get_extent test\n"); | 1150 | test_msg("Running hole first btrfs_get_extent test\n"); |
1119 | ret = test_hole_first(); | 1151 | ret = test_hole_first(sectorsize, nodesize); |
1120 | if (ret) | 1152 | if (ret) |
1121 | return ret; | 1153 | return ret; |
1122 | test_msg("Running outstanding_extents tests\n"); | 1154 | test_msg("Running outstanding_extents tests\n"); |
1123 | return test_extent_accounting(); | 1155 | return test_extent_accounting(sectorsize, nodesize); |
1124 | } | 1156 | } |
diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c index 8aa4ded31326..57a12c0d680b 100644 --- a/fs/btrfs/tests/qgroup-tests.c +++ b/fs/btrfs/tests/qgroup-tests.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/types.h> | ||
19 | #include "btrfs-tests.h" | 20 | #include "btrfs-tests.h" |
20 | #include "../ctree.h" | 21 | #include "../ctree.h" |
21 | #include "../transaction.h" | 22 | #include "../transaction.h" |
@@ -216,7 +217,8 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr, | |||
216 | return ret; | 217 | return ret; |
217 | } | 218 | } |
218 | 219 | ||
219 | static int test_no_shared_qgroup(struct btrfs_root *root) | 220 | static int test_no_shared_qgroup(struct btrfs_root *root, |
221 | u32 sectorsize, u32 nodesize) | ||
220 | { | 222 | { |
221 | struct btrfs_trans_handle trans; | 223 | struct btrfs_trans_handle trans; |
222 | struct btrfs_fs_info *fs_info = root->fs_info; | 224 | struct btrfs_fs_info *fs_info = root->fs_info; |
@@ -227,7 +229,7 @@ static int test_no_shared_qgroup(struct btrfs_root *root) | |||
227 | btrfs_init_dummy_trans(&trans); | 229 | btrfs_init_dummy_trans(&trans); |
228 | 230 | ||
229 | test_msg("Qgroup basic add\n"); | 231 | test_msg("Qgroup basic add\n"); |
230 | ret = btrfs_create_qgroup(NULL, fs_info, 5); | 232 | ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FS_TREE_OBJECTID); |
231 | if (ret) { | 233 | if (ret) { |
232 | test_msg("Couldn't create a qgroup %d\n", ret); | 234 | test_msg("Couldn't create a qgroup %d\n", ret); |
233 | return ret; | 235 | return ret; |
@@ -238,18 +240,19 @@ static int test_no_shared_qgroup(struct btrfs_root *root) | |||
238 | * we can only call btrfs_qgroup_account_extent() directly to test | 240 | * we can only call btrfs_qgroup_account_extent() directly to test |
239 | * quota. | 241 | * quota. |
240 | */ | 242 | */ |
241 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); | 243 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); |
242 | if (ret) { | 244 | if (ret) { |
243 | ulist_free(old_roots); | 245 | ulist_free(old_roots); |
244 | test_msg("Couldn't find old roots: %d\n", ret); | 246 | test_msg("Couldn't find old roots: %d\n", ret); |
245 | return ret; | 247 | return ret; |
246 | } | 248 | } |
247 | 249 | ||
248 | ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5); | 250 | ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, |
251 | BTRFS_FS_TREE_OBJECTID); | ||
249 | if (ret) | 252 | if (ret) |
250 | return ret; | 253 | return ret; |
251 | 254 | ||
252 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); | 255 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); |
253 | if (ret) { | 256 | if (ret) { |
254 | ulist_free(old_roots); | 257 | ulist_free(old_roots); |
255 | ulist_free(new_roots); | 258 | ulist_free(new_roots); |
@@ -257,32 +260,33 @@ static int test_no_shared_qgroup(struct btrfs_root *root) | |||
257 | return ret; | 260 | return ret; |
258 | } | 261 | } |
259 | 262 | ||
260 | ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, | 263 | ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, |
261 | old_roots, new_roots); | 264 | nodesize, old_roots, new_roots); |
262 | if (ret) { | 265 | if (ret) { |
263 | test_msg("Couldn't account space for a qgroup %d\n", ret); | 266 | test_msg("Couldn't account space for a qgroup %d\n", ret); |
264 | return ret; | 267 | return ret; |
265 | } | 268 | } |
266 | 269 | ||
267 | if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) { | 270 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, |
271 | nodesize, nodesize)) { | ||
268 | test_msg("Qgroup counts didn't match expected values\n"); | 272 | test_msg("Qgroup counts didn't match expected values\n"); |
269 | return -EINVAL; | 273 | return -EINVAL; |
270 | } | 274 | } |
271 | old_roots = NULL; | 275 | old_roots = NULL; |
272 | new_roots = NULL; | 276 | new_roots = NULL; |
273 | 277 | ||
274 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); | 278 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); |
275 | if (ret) { | 279 | if (ret) { |
276 | ulist_free(old_roots); | 280 | ulist_free(old_roots); |
277 | test_msg("Couldn't find old roots: %d\n", ret); | 281 | test_msg("Couldn't find old roots: %d\n", ret); |
278 | return ret; | 282 | return ret; |
279 | } | 283 | } |
280 | 284 | ||
281 | ret = remove_extent_item(root, 4096, 4096); | 285 | ret = remove_extent_item(root, nodesize, nodesize); |
282 | if (ret) | 286 | if (ret) |
283 | return -EINVAL; | 287 | return -EINVAL; |
284 | 288 | ||
285 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); | 289 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); |
286 | if (ret) { | 290 | if (ret) { |
287 | ulist_free(old_roots); | 291 | ulist_free(old_roots); |
288 | ulist_free(new_roots); | 292 | ulist_free(new_roots); |
@@ -290,14 +294,14 @@ static int test_no_shared_qgroup(struct btrfs_root *root) | |||
290 | return ret; | 294 | return ret; |
291 | } | 295 | } |
292 | 296 | ||
293 | ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, | 297 | ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, |
294 | old_roots, new_roots); | 298 | nodesize, old_roots, new_roots); |
295 | if (ret) { | 299 | if (ret) { |
296 | test_msg("Couldn't account space for a qgroup %d\n", ret); | 300 | test_msg("Couldn't account space for a qgroup %d\n", ret); |
297 | return -EINVAL; | 301 | return -EINVAL; |
298 | } | 302 | } |
299 | 303 | ||
300 | if (btrfs_verify_qgroup_counts(fs_info, 5, 0, 0)) { | 304 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) { |
301 | test_msg("Qgroup counts didn't match expected values\n"); | 305 | test_msg("Qgroup counts didn't match expected values\n"); |
302 | return -EINVAL; | 306 | return -EINVAL; |
303 | } | 307 | } |
@@ -310,7 +314,8 @@ static int test_no_shared_qgroup(struct btrfs_root *root) | |||
310 | * right, also remove one of the roots and make sure the exclusive count is | 314 | * right, also remove one of the roots and make sure the exclusive count is |
311 | * adjusted properly. | 315 | * adjusted properly. |
312 | */ | 316 | */ |
313 | static int test_multiple_refs(struct btrfs_root *root) | 317 | static int test_multiple_refs(struct btrfs_root *root, |
318 | u32 sectorsize, u32 nodesize) | ||
314 | { | 319 | { |
315 | struct btrfs_trans_handle trans; | 320 | struct btrfs_trans_handle trans; |
316 | struct btrfs_fs_info *fs_info = root->fs_info; | 321 | struct btrfs_fs_info *fs_info = root->fs_info; |
@@ -322,25 +327,29 @@ static int test_multiple_refs(struct btrfs_root *root) | |||
322 | 327 | ||
323 | test_msg("Qgroup multiple refs test\n"); | 328 | test_msg("Qgroup multiple refs test\n"); |
324 | 329 | ||
325 | /* We have 5 created already from the previous test */ | 330 | /* |
326 | ret = btrfs_create_qgroup(NULL, fs_info, 256); | 331 | * We have BTRFS_FS_TREE_OBJECTID created already from the |
332 | * previous test. | ||
333 | */ | ||
334 | ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FIRST_FREE_OBJECTID); | ||
327 | if (ret) { | 335 | if (ret) { |
328 | test_msg("Couldn't create a qgroup %d\n", ret); | 336 | test_msg("Couldn't create a qgroup %d\n", ret); |
329 | return ret; | 337 | return ret; |
330 | } | 338 | } |
331 | 339 | ||
332 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); | 340 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); |
333 | if (ret) { | 341 | if (ret) { |
334 | ulist_free(old_roots); | 342 | ulist_free(old_roots); |
335 | test_msg("Couldn't find old roots: %d\n", ret); | 343 | test_msg("Couldn't find old roots: %d\n", ret); |
336 | return ret; | 344 | return ret; |
337 | } | 345 | } |
338 | 346 | ||
339 | ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5); | 347 | ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, |
348 | BTRFS_FS_TREE_OBJECTID); | ||
340 | if (ret) | 349 | if (ret) |
341 | return ret; | 350 | return ret; |
342 | 351 | ||
343 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); | 352 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); |
344 | if (ret) { | 353 | if (ret) { |
345 | ulist_free(old_roots); | 354 | ulist_free(old_roots); |
346 | ulist_free(new_roots); | 355 | ulist_free(new_roots); |
@@ -348,30 +357,32 @@ static int test_multiple_refs(struct btrfs_root *root) | |||
348 | return ret; | 357 | return ret; |
349 | } | 358 | } |
350 | 359 | ||
351 | ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, | 360 | ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, |
352 | old_roots, new_roots); | 361 | nodesize, old_roots, new_roots); |
353 | if (ret) { | 362 | if (ret) { |
354 | test_msg("Couldn't account space for a qgroup %d\n", ret); | 363 | test_msg("Couldn't account space for a qgroup %d\n", ret); |
355 | return ret; | 364 | return ret; |
356 | } | 365 | } |
357 | 366 | ||
358 | if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) { | 367 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, |
368 | nodesize, nodesize)) { | ||
359 | test_msg("Qgroup counts didn't match expected values\n"); | 369 | test_msg("Qgroup counts didn't match expected values\n"); |
360 | return -EINVAL; | 370 | return -EINVAL; |
361 | } | 371 | } |
362 | 372 | ||
363 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); | 373 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); |
364 | if (ret) { | 374 | if (ret) { |
365 | ulist_free(old_roots); | 375 | ulist_free(old_roots); |
366 | test_msg("Couldn't find old roots: %d\n", ret); | 376 | test_msg("Couldn't find old roots: %d\n", ret); |
367 | return ret; | 377 | return ret; |
368 | } | 378 | } |
369 | 379 | ||
370 | ret = add_tree_ref(root, 4096, 4096, 0, 256); | 380 | ret = add_tree_ref(root, nodesize, nodesize, 0, |
381 | BTRFS_FIRST_FREE_OBJECTID); | ||
371 | if (ret) | 382 | if (ret) |
372 | return ret; | 383 | return ret; |
373 | 384 | ||
374 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); | 385 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); |
375 | if (ret) { | 386 | if (ret) { |
376 | ulist_free(old_roots); | 387 | ulist_free(old_roots); |
377 | ulist_free(new_roots); | 388 | ulist_free(new_roots); |
@@ -379,35 +390,38 @@ static int test_multiple_refs(struct btrfs_root *root) | |||
379 | return ret; | 390 | return ret; |
380 | } | 391 | } |
381 | 392 | ||
382 | ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, | 393 | ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, |
383 | old_roots, new_roots); | 394 | nodesize, old_roots, new_roots); |
384 | if (ret) { | 395 | if (ret) { |
385 | test_msg("Couldn't account space for a qgroup %d\n", ret); | 396 | test_msg("Couldn't account space for a qgroup %d\n", ret); |
386 | return ret; | 397 | return ret; |
387 | } | 398 | } |
388 | 399 | ||
389 | if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 0)) { | 400 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, |
401 | nodesize, 0)) { | ||
390 | test_msg("Qgroup counts didn't match expected values\n"); | 402 | test_msg("Qgroup counts didn't match expected values\n"); |
391 | return -EINVAL; | 403 | return -EINVAL; |
392 | } | 404 | } |
393 | 405 | ||
394 | if (btrfs_verify_qgroup_counts(fs_info, 256, 4096, 0)) { | 406 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, |
407 | nodesize, 0)) { | ||
395 | test_msg("Qgroup counts didn't match expected values\n"); | 408 | test_msg("Qgroup counts didn't match expected values\n"); |
396 | return -EINVAL; | 409 | return -EINVAL; |
397 | } | 410 | } |
398 | 411 | ||
399 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); | 412 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); |
400 | if (ret) { | 413 | if (ret) { |
401 | ulist_free(old_roots); | 414 | ulist_free(old_roots); |
402 | test_msg("Couldn't find old roots: %d\n", ret); | 415 | test_msg("Couldn't find old roots: %d\n", ret); |
403 | return ret; | 416 | return ret; |
404 | } | 417 | } |
405 | 418 | ||
406 | ret = remove_extent_ref(root, 4096, 4096, 0, 256); | 419 | ret = remove_extent_ref(root, nodesize, nodesize, 0, |
420 | BTRFS_FIRST_FREE_OBJECTID); | ||
407 | if (ret) | 421 | if (ret) |
408 | return ret; | 422 | return ret; |
409 | 423 | ||
410 | ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); | 424 | ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); |
411 | if (ret) { | 425 | if (ret) { |
412 | ulist_free(old_roots); | 426 | ulist_free(old_roots); |
413 | ulist_free(new_roots); | 427 | ulist_free(new_roots); |
@@ -415,19 +429,21 @@ static int test_multiple_refs(struct btrfs_root *root) | |||
415 | return ret; | 429 | return ret; |
416 | } | 430 | } |
417 | 431 | ||
418 | ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, | 432 | ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, |
419 | old_roots, new_roots); | 433 | nodesize, old_roots, new_roots); |
420 | if (ret) { | 434 | if (ret) { |
421 | test_msg("Couldn't account space for a qgroup %d\n", ret); | 435 | test_msg("Couldn't account space for a qgroup %d\n", ret); |
422 | return ret; | 436 | return ret; |
423 | } | 437 | } |
424 | 438 | ||
425 | if (btrfs_verify_qgroup_counts(fs_info, 256, 0, 0)) { | 439 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, |
440 | 0, 0)) { | ||
426 | test_msg("Qgroup counts didn't match expected values\n"); | 441 | test_msg("Qgroup counts didn't match expected values\n"); |
427 | return -EINVAL; | 442 | return -EINVAL; |
428 | } | 443 | } |
429 | 444 | ||
430 | if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) { | 445 | if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, |
446 | nodesize, nodesize)) { | ||
431 | test_msg("Qgroup counts didn't match expected values\n"); | 447 | test_msg("Qgroup counts didn't match expected values\n"); |
432 | return -EINVAL; | 448 | return -EINVAL; |
433 | } | 449 | } |
@@ -435,13 +451,13 @@ static int test_multiple_refs(struct btrfs_root *root) | |||
435 | return 0; | 451 | return 0; |
436 | } | 452 | } |
437 | 453 | ||
438 | int btrfs_test_qgroups(void) | 454 | int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) |
439 | { | 455 | { |
440 | struct btrfs_root *root; | 456 | struct btrfs_root *root; |
441 | struct btrfs_root *tmp_root; | 457 | struct btrfs_root *tmp_root; |
442 | int ret = 0; | 458 | int ret = 0; |
443 | 459 | ||
444 | root = btrfs_alloc_dummy_root(); | 460 | root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
445 | if (IS_ERR(root)) { | 461 | if (IS_ERR(root)) { |
446 | test_msg("Couldn't allocate root\n"); | 462 | test_msg("Couldn't allocate root\n"); |
447 | return PTR_ERR(root); | 463 | return PTR_ERR(root); |
@@ -468,7 +484,8 @@ int btrfs_test_qgroups(void) | |||
468 | * Can't use bytenr 0, some things freak out | 484 | * Can't use bytenr 0, some things freak out |
469 | * *cough*backref walking code*cough* | 485 | * *cough*backref walking code*cough* |
470 | */ | 486 | */ |
471 | root->node = alloc_test_extent_buffer(root->fs_info, 4096); | 487 | root->node = alloc_test_extent_buffer(root->fs_info, nodesize, |
488 | nodesize); | ||
472 | if (!root->node) { | 489 | if (!root->node) { |
473 | test_msg("Couldn't allocate dummy buffer\n"); | 490 | test_msg("Couldn't allocate dummy buffer\n"); |
474 | ret = -ENOMEM; | 491 | ret = -ENOMEM; |
@@ -476,16 +493,16 @@ int btrfs_test_qgroups(void) | |||
476 | } | 493 | } |
477 | btrfs_set_header_level(root->node, 0); | 494 | btrfs_set_header_level(root->node, 0); |
478 | btrfs_set_header_nritems(root->node, 0); | 495 | btrfs_set_header_nritems(root->node, 0); |
479 | root->alloc_bytenr += 8192; | 496 | root->alloc_bytenr += 2 * nodesize; |
480 | 497 | ||
481 | tmp_root = btrfs_alloc_dummy_root(); | 498 | tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
482 | if (IS_ERR(tmp_root)) { | 499 | if (IS_ERR(tmp_root)) { |
483 | test_msg("Couldn't allocate a fs root\n"); | 500 | test_msg("Couldn't allocate a fs root\n"); |
484 | ret = PTR_ERR(tmp_root); | 501 | ret = PTR_ERR(tmp_root); |
485 | goto out; | 502 | goto out; |
486 | } | 503 | } |
487 | 504 | ||
488 | tmp_root->root_key.objectid = 5; | 505 | tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID; |
489 | root->fs_info->fs_root = tmp_root; | 506 | root->fs_info->fs_root = tmp_root; |
490 | ret = btrfs_insert_fs_root(root->fs_info, tmp_root); | 507 | ret = btrfs_insert_fs_root(root->fs_info, tmp_root); |
491 | if (ret) { | 508 | if (ret) { |
@@ -493,14 +510,14 @@ int btrfs_test_qgroups(void) | |||
493 | goto out; | 510 | goto out; |
494 | } | 511 | } |
495 | 512 | ||
496 | tmp_root = btrfs_alloc_dummy_root(); | 513 | tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize); |
497 | if (IS_ERR(tmp_root)) { | 514 | if (IS_ERR(tmp_root)) { |
498 | test_msg("Couldn't allocate a fs root\n"); | 515 | test_msg("Couldn't allocate a fs root\n"); |
499 | ret = PTR_ERR(tmp_root); | 516 | ret = PTR_ERR(tmp_root); |
500 | goto out; | 517 | goto out; |
501 | } | 518 | } |
502 | 519 | ||
503 | tmp_root->root_key.objectid = 256; | 520 | tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID; |
504 | ret = btrfs_insert_fs_root(root->fs_info, tmp_root); | 521 | ret = btrfs_insert_fs_root(root->fs_info, tmp_root); |
505 | if (ret) { | 522 | if (ret) { |
506 | test_msg("Couldn't insert fs root %d\n", ret); | 523 | test_msg("Couldn't insert fs root %d\n", ret); |
@@ -508,10 +525,10 @@ int btrfs_test_qgroups(void) | |||
508 | } | 525 | } |
509 | 526 | ||
510 | test_msg("Running qgroup tests\n"); | 527 | test_msg("Running qgroup tests\n"); |
511 | ret = test_no_shared_qgroup(root); | 528 | ret = test_no_shared_qgroup(root, sectorsize, nodesize); |
512 | if (ret) | 529 | if (ret) |
513 | goto out; | 530 | goto out; |
514 | ret = test_multiple_refs(root); | 531 | ret = test_multiple_refs(root, sectorsize, nodesize); |
515 | out: | 532 | out: |
516 | btrfs_free_dummy_root(root); | 533 | btrfs_free_dummy_root(root); |
517 | return ret; | 534 | return ret; |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f6e24cb423ae..948aa186b353 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -818,6 +818,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
818 | { | 818 | { |
819 | struct btrfs_transaction *cur_trans = trans->transaction; | 819 | struct btrfs_transaction *cur_trans = trans->transaction; |
820 | struct btrfs_fs_info *info = root->fs_info; | 820 | struct btrfs_fs_info *info = root->fs_info; |
821 | u64 transid = trans->transid; | ||
821 | unsigned long cur = trans->delayed_ref_updates; | 822 | unsigned long cur = trans->delayed_ref_updates; |
822 | int lock = (trans->type != TRANS_JOIN_NOLOCK); | 823 | int lock = (trans->type != TRANS_JOIN_NOLOCK); |
823 | int err = 0; | 824 | int err = 0; |
@@ -905,7 +906,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
905 | 906 | ||
906 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 907 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
907 | if (must_run_delayed_refs) { | 908 | if (must_run_delayed_refs) { |
908 | btrfs_async_run_delayed_refs(root, cur, | 909 | btrfs_async_run_delayed_refs(root, cur, transid, |
909 | must_run_delayed_refs == 1); | 910 | must_run_delayed_refs == 1); |
910 | } | 911 | } |
911 | return err; | 912 | return err; |
@@ -1311,11 +1312,6 @@ int btrfs_defrag_root(struct btrfs_root *root) | |||
1311 | return ret; | 1312 | return ret; |
1312 | } | 1313 | } |
1313 | 1314 | ||
1314 | /* Bisesctability fixup, remove in 4.8 */ | ||
1315 | #ifndef btrfs_std_error | ||
1316 | #define btrfs_std_error btrfs_handle_fs_error | ||
1317 | #endif | ||
1318 | |||
1319 | /* | 1315 | /* |
1320 | * Do all special snapshot related qgroup dirty hack. | 1316 | * Do all special snapshot related qgroup dirty hack. |
1321 | * | 1317 | * |
@@ -1385,7 +1381,7 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans, | |||
1385 | switch_commit_roots(trans->transaction, fs_info); | 1381 | switch_commit_roots(trans->transaction, fs_info); |
1386 | ret = btrfs_write_and_wait_transaction(trans, src); | 1382 | ret = btrfs_write_and_wait_transaction(trans, src); |
1387 | if (ret) | 1383 | if (ret) |
1388 | btrfs_std_error(fs_info, ret, | 1384 | btrfs_handle_fs_error(fs_info, ret, |
1389 | "Error while writing out transaction for qgroup"); | 1385 | "Error while writing out transaction for qgroup"); |
1390 | 1386 | ||
1391 | out: | 1387 | out: |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 9fe0ec2bf0fe..c5abee4f01ad 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -110,7 +110,6 @@ struct btrfs_trans_handle { | |||
110 | u64 chunk_bytes_reserved; | 110 | u64 chunk_bytes_reserved; |
111 | unsigned long use_count; | 111 | unsigned long use_count; |
112 | unsigned long blocks_reserved; | 112 | unsigned long blocks_reserved; |
113 | unsigned long blocks_used; | ||
114 | unsigned long delayed_ref_updates; | 113 | unsigned long delayed_ref_updates; |
115 | struct btrfs_transaction *transaction; | 114 | struct btrfs_transaction *transaction; |
116 | struct btrfs_block_rsv *block_rsv; | 115 | struct btrfs_block_rsv *block_rsv; |
@@ -121,6 +120,7 @@ struct btrfs_trans_handle { | |||
121 | bool can_flush_pending_bgs; | 120 | bool can_flush_pending_bgs; |
122 | bool reloc_reserved; | 121 | bool reloc_reserved; |
123 | bool sync; | 122 | bool sync; |
123 | bool dirty; | ||
124 | unsigned int type; | 124 | unsigned int type; |
125 | /* | 125 | /* |
126 | * this root is only needed to validate that the root passed to | 126 | * this root is only needed to validate that the root passed to |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index b7665af471d8..c05f69a8ec42 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2422,8 +2422,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
2422 | root_owner = btrfs_header_owner(parent); | 2422 | root_owner = btrfs_header_owner(parent); |
2423 | 2423 | ||
2424 | next = btrfs_find_create_tree_block(root, bytenr); | 2424 | next = btrfs_find_create_tree_block(root, bytenr); |
2425 | if (!next) | 2425 | if (IS_ERR(next)) |
2426 | return -ENOMEM; | 2426 | return PTR_ERR(next); |
2427 | 2427 | ||
2428 | if (*level == 1) { | 2428 | if (*level == 1) { |
2429 | ret = wc->process_func(root, next, wc, ptr_gen); | 2429 | ret = wc->process_func(root, next, wc, ptr_gen); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index da9e0036a864..589f128173b1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -4241,6 +4241,7 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info) | |||
4241 | if (IS_ERR(uuid_root)) { | 4241 | if (IS_ERR(uuid_root)) { |
4242 | ret = PTR_ERR(uuid_root); | 4242 | ret = PTR_ERR(uuid_root); |
4243 | btrfs_abort_transaction(trans, tree_root, ret); | 4243 | btrfs_abort_transaction(trans, tree_root, ret); |
4244 | btrfs_end_transaction(trans, tree_root); | ||
4244 | return ret; | 4245 | return ret; |
4245 | } | 4246 | } |
4246 | 4247 | ||
@@ -4693,12 +4694,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
4693 | 4694 | ||
4694 | if (type & BTRFS_BLOCK_GROUP_RAID5) { | 4695 | if (type & BTRFS_BLOCK_GROUP_RAID5) { |
4695 | raid_stripe_len = find_raid56_stripe_len(ndevs - 1, | 4696 | raid_stripe_len = find_raid56_stripe_len(ndevs - 1, |
4696 | btrfs_super_stripesize(info->super_copy)); | 4697 | extent_root->stripesize); |
4697 | data_stripes = num_stripes - 1; | 4698 | data_stripes = num_stripes - 1; |
4698 | } | 4699 | } |
4699 | if (type & BTRFS_BLOCK_GROUP_RAID6) { | 4700 | if (type & BTRFS_BLOCK_GROUP_RAID6) { |
4700 | raid_stripe_len = find_raid56_stripe_len(ndevs - 2, | 4701 | raid_stripe_len = find_raid56_stripe_len(ndevs - 2, |
4701 | btrfs_super_stripesize(info->super_copy)); | 4702 | extent_root->stripesize); |
4702 | data_stripes = num_stripes - 2; | 4703 | data_stripes = num_stripes - 2; |
4703 | } | 4704 | } |
4704 | 4705 | ||
@@ -6258,27 +6259,23 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, | |||
6258 | return dev; | 6259 | return dev; |
6259 | } | 6260 | } |
6260 | 6261 | ||
6261 | static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | 6262 | /* Return -EIO if any error, otherwise return 0. */ |
6262 | struct extent_buffer *leaf, | 6263 | static int btrfs_check_chunk_valid(struct btrfs_root *root, |
6263 | struct btrfs_chunk *chunk) | 6264 | struct extent_buffer *leaf, |
6265 | struct btrfs_chunk *chunk, u64 logical) | ||
6264 | { | 6266 | { |
6265 | struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree; | ||
6266 | struct map_lookup *map; | ||
6267 | struct extent_map *em; | ||
6268 | u64 logical; | ||
6269 | u64 length; | 6267 | u64 length; |
6270 | u64 stripe_len; | 6268 | u64 stripe_len; |
6271 | u64 devid; | 6269 | u16 num_stripes; |
6272 | u8 uuid[BTRFS_UUID_SIZE]; | 6270 | u16 sub_stripes; |
6273 | int num_stripes; | 6271 | u64 type; |
6274 | int ret; | ||
6275 | int i; | ||
6276 | 6272 | ||
6277 | logical = key->offset; | ||
6278 | length = btrfs_chunk_length(leaf, chunk); | 6273 | length = btrfs_chunk_length(leaf, chunk); |
6279 | stripe_len = btrfs_chunk_stripe_len(leaf, chunk); | 6274 | stripe_len = btrfs_chunk_stripe_len(leaf, chunk); |
6280 | num_stripes = btrfs_chunk_num_stripes(leaf, chunk); | 6275 | num_stripes = btrfs_chunk_num_stripes(leaf, chunk); |
6281 | /* Validation check */ | 6276 | sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); |
6277 | type = btrfs_chunk_type(leaf, chunk); | ||
6278 | |||
6282 | if (!num_stripes) { | 6279 | if (!num_stripes) { |
6283 | btrfs_err(root->fs_info, "invalid chunk num_stripes: %u", | 6280 | btrfs_err(root->fs_info, "invalid chunk num_stripes: %u", |
6284 | num_stripes); | 6281 | num_stripes); |
@@ -6289,6 +6286,11 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
6289 | "invalid chunk logical %llu", logical); | 6286 | "invalid chunk logical %llu", logical); |
6290 | return -EIO; | 6287 | return -EIO; |
6291 | } | 6288 | } |
6289 | if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) { | ||
6290 | btrfs_err(root->fs_info, "invalid chunk sectorsize %u", | ||
6291 | btrfs_chunk_sector_size(leaf, chunk)); | ||
6292 | return -EIO; | ||
6293 | } | ||
6292 | if (!length || !IS_ALIGNED(length, root->sectorsize)) { | 6294 | if (!length || !IS_ALIGNED(length, root->sectorsize)) { |
6293 | btrfs_err(root->fs_info, | 6295 | btrfs_err(root->fs_info, |
6294 | "invalid chunk length %llu", length); | 6296 | "invalid chunk length %llu", length); |
@@ -6300,13 +6302,54 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
6300 | return -EIO; | 6302 | return -EIO; |
6301 | } | 6303 | } |
6302 | if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & | 6304 | if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & |
6303 | btrfs_chunk_type(leaf, chunk)) { | 6305 | type) { |
6304 | btrfs_err(root->fs_info, "unrecognized chunk type: %llu", | 6306 | btrfs_err(root->fs_info, "unrecognized chunk type: %llu", |
6305 | ~(BTRFS_BLOCK_GROUP_TYPE_MASK | | 6307 | ~(BTRFS_BLOCK_GROUP_TYPE_MASK | |
6306 | BTRFS_BLOCK_GROUP_PROFILE_MASK) & | 6308 | BTRFS_BLOCK_GROUP_PROFILE_MASK) & |
6307 | btrfs_chunk_type(leaf, chunk)); | 6309 | btrfs_chunk_type(leaf, chunk)); |
6308 | return -EIO; | 6310 | return -EIO; |
6309 | } | 6311 | } |
6312 | if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) || | ||
6313 | (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) || | ||
6314 | (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) || | ||
6315 | (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) || | ||
6316 | (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) || | ||
6317 | ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && | ||
6318 | num_stripes != 1)) { | ||
6319 | btrfs_err(root->fs_info, | ||
6320 | "invalid num_stripes:sub_stripes %u:%u for profile %llu", | ||
6321 | num_stripes, sub_stripes, | ||
6322 | type & BTRFS_BLOCK_GROUP_PROFILE_MASK); | ||
6323 | return -EIO; | ||
6324 | } | ||
6325 | |||
6326 | return 0; | ||
6327 | } | ||
6328 | |||
6329 | static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | ||
6330 | struct extent_buffer *leaf, | ||
6331 | struct btrfs_chunk *chunk) | ||
6332 | { | ||
6333 | struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree; | ||
6334 | struct map_lookup *map; | ||
6335 | struct extent_map *em; | ||
6336 | u64 logical; | ||
6337 | u64 length; | ||
6338 | u64 stripe_len; | ||
6339 | u64 devid; | ||
6340 | u8 uuid[BTRFS_UUID_SIZE]; | ||
6341 | int num_stripes; | ||
6342 | int ret; | ||
6343 | int i; | ||
6344 | |||
6345 | logical = key->offset; | ||
6346 | length = btrfs_chunk_length(leaf, chunk); | ||
6347 | stripe_len = btrfs_chunk_stripe_len(leaf, chunk); | ||
6348 | num_stripes = btrfs_chunk_num_stripes(leaf, chunk); | ||
6349 | |||
6350 | ret = btrfs_check_chunk_valid(root, leaf, chunk, logical); | ||
6351 | if (ret) | ||
6352 | return ret; | ||
6310 | 6353 | ||
6311 | read_lock(&map_tree->map_tree.lock); | 6354 | read_lock(&map_tree->map_tree.lock); |
6312 | em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); | 6355 | em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); |
@@ -6554,6 +6597,7 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
6554 | u32 array_size; | 6597 | u32 array_size; |
6555 | u32 len = 0; | 6598 | u32 len = 0; |
6556 | u32 cur_offset; | 6599 | u32 cur_offset; |
6600 | u64 type; | ||
6557 | struct btrfs_key key; | 6601 | struct btrfs_key key; |
6558 | 6602 | ||
6559 | ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize); | 6603 | ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize); |
@@ -6563,8 +6607,8 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
6563 | * overallocate but we can keep it as-is, only the first page is used. | 6607 | * overallocate but we can keep it as-is, only the first page is used. |
6564 | */ | 6608 | */ |
6565 | sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET); | 6609 | sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET); |
6566 | if (!sb) | 6610 | if (IS_ERR(sb)) |
6567 | return -ENOMEM; | 6611 | return PTR_ERR(sb); |
6568 | set_extent_buffer_uptodate(sb); | 6612 | set_extent_buffer_uptodate(sb); |
6569 | btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0); | 6613 | btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0); |
6570 | /* | 6614 | /* |
@@ -6620,6 +6664,15 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
6620 | break; | 6664 | break; |
6621 | } | 6665 | } |
6622 | 6666 | ||
6667 | type = btrfs_chunk_type(sb, chunk); | ||
6668 | if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) { | ||
6669 | btrfs_err(root->fs_info, | ||
6670 | "invalid chunk type %llu in sys_array at offset %u", | ||
6671 | type, cur_offset); | ||
6672 | ret = -EIO; | ||
6673 | break; | ||
6674 | } | ||
6675 | |||
6623 | len = btrfs_chunk_item_size(num_stripes); | 6676 | len = btrfs_chunk_item_size(num_stripes); |
6624 | if (cur_offset + len > array_size) | 6677 | if (cur_offset + len > array_size) |
6625 | goto out_short_read; | 6678 | goto out_short_read; |
@@ -6638,12 +6691,14 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
6638 | sb_array_offset += len; | 6691 | sb_array_offset += len; |
6639 | cur_offset += len; | 6692 | cur_offset += len; |
6640 | } | 6693 | } |
6694 | clear_extent_buffer_uptodate(sb); | ||
6641 | free_extent_buffer_stale(sb); | 6695 | free_extent_buffer_stale(sb); |
6642 | return ret; | 6696 | return ret; |
6643 | 6697 | ||
6644 | out_short_read: | 6698 | out_short_read: |
6645 | printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n", | 6699 | printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n", |
6646 | len, cur_offset); | 6700 | len, cur_offset); |
6701 | clear_extent_buffer_uptodate(sb); | ||
6647 | free_extent_buffer_stale(sb); | 6702 | free_extent_buffer_stale(sb); |
6648 | return -EIO; | 6703 | return -EIO; |
6649 | } | 6704 | } |
@@ -6656,6 +6711,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root) | |||
6656 | struct btrfs_key found_key; | 6711 | struct btrfs_key found_key; |
6657 | int ret; | 6712 | int ret; |
6658 | int slot; | 6713 | int slot; |
6714 | u64 total_dev = 0; | ||
6659 | 6715 | ||
6660 | root = root->fs_info->chunk_root; | 6716 | root = root->fs_info->chunk_root; |
6661 | 6717 | ||
@@ -6697,6 +6753,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root) | |||
6697 | ret = read_one_dev(root, leaf, dev_item); | 6753 | ret = read_one_dev(root, leaf, dev_item); |
6698 | if (ret) | 6754 | if (ret) |
6699 | goto error; | 6755 | goto error; |
6756 | total_dev++; | ||
6700 | } else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) { | 6757 | } else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) { |
6701 | struct btrfs_chunk *chunk; | 6758 | struct btrfs_chunk *chunk; |
6702 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); | 6759 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); |
@@ -6706,6 +6763,28 @@ int btrfs_read_chunk_tree(struct btrfs_root *root) | |||
6706 | } | 6763 | } |
6707 | path->slots[0]++; | 6764 | path->slots[0]++; |
6708 | } | 6765 | } |
6766 | |||
6767 | /* | ||
6768 | * After loading chunk tree, we've got all device information, | ||
6769 | * do another round of validation checks. | ||
6770 | */ | ||
6771 | if (total_dev != root->fs_info->fs_devices->total_devices) { | ||
6772 | btrfs_err(root->fs_info, | ||
6773 | "super_num_devices %llu mismatch with num_devices %llu found here", | ||
6774 | btrfs_super_num_devices(root->fs_info->super_copy), | ||
6775 | total_dev); | ||
6776 | ret = -EINVAL; | ||
6777 | goto error; | ||
6778 | } | ||
6779 | if (btrfs_super_total_bytes(root->fs_info->super_copy) < | ||
6780 | root->fs_info->fs_devices->total_rw_bytes) { | ||
6781 | btrfs_err(root->fs_info, | ||
6782 | "super_total_bytes %llu mismatch with fs_devices total_rw_bytes %llu", | ||
6783 | btrfs_super_total_bytes(root->fs_info->super_copy), | ||
6784 | root->fs_info->fs_devices->total_rw_bytes); | ||
6785 | ret = -EINVAL; | ||
6786 | goto error; | ||
6787 | } | ||
6709 | ret = 0; | 6788 | ret = 0; |
6710 | error: | 6789 | error: |
6711 | unlock_chunks(root); | 6790 | unlock_chunks(root); |
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 5a53ac6b1e02..02b071bf3732 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
@@ -101,6 +101,12 @@ convert_sfm_char(const __u16 src_char, char *target) | |||
101 | case SFM_SLASH: | 101 | case SFM_SLASH: |
102 | *target = '\\'; | 102 | *target = '\\'; |
103 | break; | 103 | break; |
104 | case SFM_SPACE: | ||
105 | *target = ' '; | ||
106 | break; | ||
107 | case SFM_PERIOD: | ||
108 | *target = '.'; | ||
109 | break; | ||
104 | default: | 110 | default: |
105 | return false; | 111 | return false; |
106 | } | 112 | } |
@@ -404,7 +410,7 @@ static __le16 convert_to_sfu_char(char src_char) | |||
404 | return dest_char; | 410 | return dest_char; |
405 | } | 411 | } |
406 | 412 | ||
407 | static __le16 convert_to_sfm_char(char src_char) | 413 | static __le16 convert_to_sfm_char(char src_char, bool end_of_string) |
408 | { | 414 | { |
409 | __le16 dest_char; | 415 | __le16 dest_char; |
410 | 416 | ||
@@ -427,6 +433,18 @@ static __le16 convert_to_sfm_char(char src_char) | |||
427 | case '|': | 433 | case '|': |
428 | dest_char = cpu_to_le16(SFM_PIPE); | 434 | dest_char = cpu_to_le16(SFM_PIPE); |
429 | break; | 435 | break; |
436 | case '.': | ||
437 | if (end_of_string) | ||
438 | dest_char = cpu_to_le16(SFM_PERIOD); | ||
439 | else | ||
440 | dest_char = 0; | ||
441 | break; | ||
442 | case ' ': | ||
443 | if (end_of_string) | ||
444 | dest_char = cpu_to_le16(SFM_SPACE); | ||
445 | else | ||
446 | dest_char = 0; | ||
447 | break; | ||
430 | default: | 448 | default: |
431 | dest_char = 0; | 449 | dest_char = 0; |
432 | } | 450 | } |
@@ -469,9 +487,16 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, | |||
469 | /* see if we must remap this char */ | 487 | /* see if we must remap this char */ |
470 | if (map_chars == SFU_MAP_UNI_RSVD) | 488 | if (map_chars == SFU_MAP_UNI_RSVD) |
471 | dst_char = convert_to_sfu_char(src_char); | 489 | dst_char = convert_to_sfu_char(src_char); |
472 | else if (map_chars == SFM_MAP_UNI_RSVD) | 490 | else if (map_chars == SFM_MAP_UNI_RSVD) { |
473 | dst_char = convert_to_sfm_char(src_char); | 491 | bool end_of_string; |
474 | else | 492 | |
493 | if (i == srclen - 1) | ||
494 | end_of_string = true; | ||
495 | else | ||
496 | end_of_string = false; | ||
497 | |||
498 | dst_char = convert_to_sfm_char(src_char, end_of_string); | ||
499 | } else | ||
475 | dst_char = 0; | 500 | dst_char = 0; |
476 | /* | 501 | /* |
477 | * FIXME: We can not handle remapping backslash (UNI_SLASH) | 502 | * FIXME: We can not handle remapping backslash (UNI_SLASH) |
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index bdc52cb9a676..479bc0a941f3 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h | |||
@@ -64,6 +64,8 @@ | |||
64 | #define SFM_LESSTHAN ((__u16) 0xF023) | 64 | #define SFM_LESSTHAN ((__u16) 0xF023) |
65 | #define SFM_PIPE ((__u16) 0xF027) | 65 | #define SFM_PIPE ((__u16) 0xF027) |
66 | #define SFM_SLASH ((__u16) 0xF026) | 66 | #define SFM_SLASH ((__u16) 0xF026) |
67 | #define SFM_PERIOD ((__u16) 0xF028) | ||
68 | #define SFM_SPACE ((__u16) 0xF029) | ||
67 | 69 | ||
68 | /* | 70 | /* |
69 | * Mapping mechanism to use when one of the seven reserved characters is | 71 | * Mapping mechanism to use when one of the seven reserved characters is |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5d8b7edf8a8f..5d841f39c4b7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -87,6 +87,7 @@ extern mempool_t *cifs_req_poolp; | |||
87 | extern mempool_t *cifs_mid_poolp; | 87 | extern mempool_t *cifs_mid_poolp; |
88 | 88 | ||
89 | struct workqueue_struct *cifsiod_wq; | 89 | struct workqueue_struct *cifsiod_wq; |
90 | __u32 cifs_lock_secret; | ||
90 | 91 | ||
91 | /* | 92 | /* |
92 | * Bumps refcount for cifs super block. | 93 | * Bumps refcount for cifs super block. |
@@ -1266,6 +1267,8 @@ init_cifs(void) | |||
1266 | spin_lock_init(&cifs_file_list_lock); | 1267 | spin_lock_init(&cifs_file_list_lock); |
1267 | spin_lock_init(&GlobalMid_Lock); | 1268 | spin_lock_init(&GlobalMid_Lock); |
1268 | 1269 | ||
1270 | get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret)); | ||
1271 | |||
1269 | if (cifs_max_pending < 2) { | 1272 | if (cifs_max_pending < 2) { |
1270 | cifs_max_pending = 2; | 1273 | cifs_max_pending = 2; |
1271 | cifs_dbg(FYI, "cifs_max_pending set to min of 2\n"); | 1274 | cifs_dbg(FYI, "cifs_max_pending set to min of 2\n"); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index bba106cdc43c..8f1d8c1e72be 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -1619,6 +1619,7 @@ void cifs_oplock_break(struct work_struct *work); | |||
1619 | 1619 | ||
1620 | extern const struct slow_work_ops cifs_oplock_break_ops; | 1620 | extern const struct slow_work_ops cifs_oplock_break_ops; |
1621 | extern struct workqueue_struct *cifsiod_wq; | 1621 | extern struct workqueue_struct *cifsiod_wq; |
1622 | extern __u32 cifs_lock_secret; | ||
1622 | 1623 | ||
1623 | extern mempool_t *cifs_mid_poolp; | 1624 | extern mempool_t *cifs_mid_poolp; |
1624 | 1625 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 66736f57b5ab..7d2b15c06090 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -428,7 +428,9 @@ cifs_echo_request(struct work_struct *work) | |||
428 | * server->ops->need_neg() == true. Also, no need to ping if | 428 | * server->ops->need_neg() == true. Also, no need to ping if |
429 | * we got a response recently. | 429 | * we got a response recently. |
430 | */ | 430 | */ |
431 | if (!server->ops->need_neg || server->ops->need_neg(server) || | 431 | |
432 | if (server->tcpStatus == CifsNeedReconnect || | ||
433 | server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew || | ||
432 | (server->ops->can_echo && !server->ops->can_echo(server)) || | 434 | (server->ops->can_echo && !server->ops->can_echo(server)) || |
433 | time_before(jiffies, server->lstrp + echo_interval - HZ)) | 435 | time_before(jiffies, server->lstrp + echo_interval - HZ)) |
434 | goto requeue_echo; | 436 | goto requeue_echo; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9793ae0bcaa2..d4890b6dc22d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1112,6 +1112,12 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
1112 | return rc; | 1112 | return rc; |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | static __u32 | ||
1116 | hash_lockowner(fl_owner_t owner) | ||
1117 | { | ||
1118 | return cifs_lock_secret ^ hash32_ptr((const void *)owner); | ||
1119 | } | ||
1120 | |||
1115 | struct lock_to_push { | 1121 | struct lock_to_push { |
1116 | struct list_head llist; | 1122 | struct list_head llist; |
1117 | __u64 offset; | 1123 | __u64 offset; |
@@ -1178,7 +1184,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1178 | else | 1184 | else |
1179 | type = CIFS_WRLCK; | 1185 | type = CIFS_WRLCK; |
1180 | lck = list_entry(el, struct lock_to_push, llist); | 1186 | lck = list_entry(el, struct lock_to_push, llist); |
1181 | lck->pid = flock->fl_pid; | 1187 | lck->pid = hash_lockowner(flock->fl_owner); |
1182 | lck->netfid = cfile->fid.netfid; | 1188 | lck->netfid = cfile->fid.netfid; |
1183 | lck->length = length; | 1189 | lck->length = length; |
1184 | lck->type = type; | 1190 | lck->type = type; |
@@ -1305,7 +1311,8 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1305 | posix_lock_type = CIFS_RDLCK; | 1311 | posix_lock_type = CIFS_RDLCK; |
1306 | else | 1312 | else |
1307 | posix_lock_type = CIFS_WRLCK; | 1313 | posix_lock_type = CIFS_WRLCK; |
1308 | rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, | 1314 | rc = CIFSSMBPosixLock(xid, tcon, netfid, |
1315 | hash_lockowner(flock->fl_owner), | ||
1309 | flock->fl_start, length, flock, | 1316 | flock->fl_start, length, flock, |
1310 | posix_lock_type, wait_flag); | 1317 | posix_lock_type, wait_flag); |
1311 | return rc; | 1318 | return rc; |
@@ -1505,7 +1512,8 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1505 | posix_lock_type = CIFS_UNLCK; | 1512 | posix_lock_type = CIFS_UNLCK; |
1506 | 1513 | ||
1507 | rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid, | 1514 | rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid, |
1508 | current->tgid, flock->fl_start, length, | 1515 | hash_lockowner(flock->fl_owner), |
1516 | flock->fl_start, length, | ||
1509 | NULL, posix_lock_type, wait_flag); | 1517 | NULL, posix_lock_type, wait_flag); |
1510 | goto out; | 1518 | goto out; |
1511 | } | 1519 | } |
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 848249fa120f..3079b38f0afb 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h | |||
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE { | |||
133 | 133 | ||
134 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); | 134 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); |
135 | void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); | 135 | void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); |
136 | int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen, | 136 | int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen, |
137 | struct cifs_ses *ses, | 137 | struct cifs_ses *ses, |
138 | const struct nls_table *nls_cp); | 138 | const struct nls_table *nls_cp); |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index af0ec2d5ad0e..538d9b55699a 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -364,19 +364,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
364 | sec_blob->DomainName.MaximumLength = 0; | 364 | sec_blob->DomainName.MaximumLength = 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | /* We do not malloc the blob, it is passed in pbuffer, because its | 367 | static int size_of_ntlmssp_blob(struct cifs_ses *ses) |
368 | maximum possible size is fixed and small, making this approach cleaner. | 368 | { |
369 | This function returns the length of the data in the blob */ | 369 | int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len |
370 | int build_ntlmssp_auth_blob(unsigned char *pbuffer, | 370 | - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2; |
371 | |||
372 | if (ses->domainName) | ||
373 | sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); | ||
374 | else | ||
375 | sz += 2; | ||
376 | |||
377 | if (ses->user_name) | ||
378 | sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); | ||
379 | else | ||
380 | sz += 2; | ||
381 | |||
382 | return sz; | ||
383 | } | ||
384 | |||
385 | int build_ntlmssp_auth_blob(unsigned char **pbuffer, | ||
371 | u16 *buflen, | 386 | u16 *buflen, |
372 | struct cifs_ses *ses, | 387 | struct cifs_ses *ses, |
373 | const struct nls_table *nls_cp) | 388 | const struct nls_table *nls_cp) |
374 | { | 389 | { |
375 | int rc; | 390 | int rc; |
376 | AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; | 391 | AUTHENTICATE_MESSAGE *sec_blob; |
377 | __u32 flags; | 392 | __u32 flags; |
378 | unsigned char *tmp; | 393 | unsigned char *tmp; |
379 | 394 | ||
395 | rc = setup_ntlmv2_rsp(ses, nls_cp); | ||
396 | if (rc) { | ||
397 | cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); | ||
398 | *buflen = 0; | ||
399 | goto setup_ntlmv2_ret; | ||
400 | } | ||
401 | *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL); | ||
402 | sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer; | ||
403 | |||
380 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); | 404 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); |
381 | sec_blob->MessageType = NtLmAuthenticate; | 405 | sec_blob->MessageType = NtLmAuthenticate; |
382 | 406 | ||
@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
391 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | 415 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
392 | } | 416 | } |
393 | 417 | ||
394 | tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); | 418 | tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE); |
395 | sec_blob->NegotiateFlags = cpu_to_le32(flags); | 419 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
396 | 420 | ||
397 | sec_blob->LmChallengeResponse.BufferOffset = | 421 | sec_blob->LmChallengeResponse.BufferOffset = |
@@ -399,13 +423,9 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
399 | sec_blob->LmChallengeResponse.Length = 0; | 423 | sec_blob->LmChallengeResponse.Length = 0; |
400 | sec_blob->LmChallengeResponse.MaximumLength = 0; | 424 | sec_blob->LmChallengeResponse.MaximumLength = 0; |
401 | 425 | ||
402 | sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); | 426 | sec_blob->NtChallengeResponse.BufferOffset = |
427 | cpu_to_le32(tmp - *pbuffer); | ||
403 | if (ses->user_name != NULL) { | 428 | if (ses->user_name != NULL) { |
404 | rc = setup_ntlmv2_rsp(ses, nls_cp); | ||
405 | if (rc) { | ||
406 | cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); | ||
407 | goto setup_ntlmv2_ret; | ||
408 | } | ||
409 | memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE, | 429 | memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE, |
410 | ses->auth_key.len - CIFS_SESS_KEY_SIZE); | 430 | ses->auth_key.len - CIFS_SESS_KEY_SIZE); |
411 | tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE; | 431 | tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE; |
@@ -423,23 +443,23 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
423 | } | 443 | } |
424 | 444 | ||
425 | if (ses->domainName == NULL) { | 445 | if (ses->domainName == NULL) { |
426 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 446 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
427 | sec_blob->DomainName.Length = 0; | 447 | sec_blob->DomainName.Length = 0; |
428 | sec_blob->DomainName.MaximumLength = 0; | 448 | sec_blob->DomainName.MaximumLength = 0; |
429 | tmp += 2; | 449 | tmp += 2; |
430 | } else { | 450 | } else { |
431 | int len; | 451 | int len; |
432 | len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, | 452 | len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, |
433 | CIFS_MAX_USERNAME_LEN, nls_cp); | 453 | CIFS_MAX_DOMAINNAME_LEN, nls_cp); |
434 | len *= 2; /* unicode is 2 bytes each */ | 454 | len *= 2; /* unicode is 2 bytes each */ |
435 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 455 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
436 | sec_blob->DomainName.Length = cpu_to_le16(len); | 456 | sec_blob->DomainName.Length = cpu_to_le16(len); |
437 | sec_blob->DomainName.MaximumLength = cpu_to_le16(len); | 457 | sec_blob->DomainName.MaximumLength = cpu_to_le16(len); |
438 | tmp += len; | 458 | tmp += len; |
439 | } | 459 | } |
440 | 460 | ||
441 | if (ses->user_name == NULL) { | 461 | if (ses->user_name == NULL) { |
442 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 462 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
443 | sec_blob->UserName.Length = 0; | 463 | sec_blob->UserName.Length = 0; |
444 | sec_blob->UserName.MaximumLength = 0; | 464 | sec_blob->UserName.MaximumLength = 0; |
445 | tmp += 2; | 465 | tmp += 2; |
@@ -448,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
448 | len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, | 468 | len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, |
449 | CIFS_MAX_USERNAME_LEN, nls_cp); | 469 | CIFS_MAX_USERNAME_LEN, nls_cp); |
450 | len *= 2; /* unicode is 2 bytes each */ | 470 | len *= 2; /* unicode is 2 bytes each */ |
451 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 471 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
452 | sec_blob->UserName.Length = cpu_to_le16(len); | 472 | sec_blob->UserName.Length = cpu_to_le16(len); |
453 | sec_blob->UserName.MaximumLength = cpu_to_le16(len); | 473 | sec_blob->UserName.MaximumLength = cpu_to_le16(len); |
454 | tmp += len; | 474 | tmp += len; |
455 | } | 475 | } |
456 | 476 | ||
457 | sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 477 | sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
458 | sec_blob->WorkstationName.Length = 0; | 478 | sec_blob->WorkstationName.Length = 0; |
459 | sec_blob->WorkstationName.MaximumLength = 0; | 479 | sec_blob->WorkstationName.MaximumLength = 0; |
460 | tmp += 2; | 480 | tmp += 2; |
@@ -463,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
463 | (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) | 483 | (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) |
464 | && !calc_seckey(ses)) { | 484 | && !calc_seckey(ses)) { |
465 | memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); | 485 | memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); |
466 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | 486 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
467 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); | 487 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); |
468 | sec_blob->SessionKey.MaximumLength = | 488 | sec_blob->SessionKey.MaximumLength = |
469 | cpu_to_le16(CIFS_CPHTXT_SIZE); | 489 | cpu_to_le16(CIFS_CPHTXT_SIZE); |
470 | tmp += CIFS_CPHTXT_SIZE; | 490 | tmp += CIFS_CPHTXT_SIZE; |
471 | } else { | 491 | } else { |
472 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | 492 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
473 | sec_blob->SessionKey.Length = 0; | 493 | sec_blob->SessionKey.Length = 0; |
474 | sec_blob->SessionKey.MaximumLength = 0; | 494 | sec_blob->SessionKey.MaximumLength = 0; |
475 | } | 495 | } |
476 | 496 | ||
497 | *buflen = tmp - *pbuffer; | ||
477 | setup_ntlmv2_ret: | 498 | setup_ntlmv2_ret: |
478 | *buflen = tmp - pbuffer; | ||
479 | return rc; | 499 | return rc; |
480 | } | 500 | } |
481 | 501 | ||
@@ -690,6 +710,8 @@ sess_auth_lanman(struct sess_data *sess_data) | |||
690 | rc = calc_lanman_hash(ses->password, ses->server->cryptkey, | 710 | rc = calc_lanman_hash(ses->password, ses->server->cryptkey, |
691 | ses->server->sec_mode & SECMODE_PW_ENCRYPT ? | 711 | ses->server->sec_mode & SECMODE_PW_ENCRYPT ? |
692 | true : false, lnm_session_key); | 712 | true : false, lnm_session_key); |
713 | if (rc) | ||
714 | goto out; | ||
693 | 715 | ||
694 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); | 716 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); |
695 | bcc_ptr += CIFS_AUTH_RESP_SIZE; | 717 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
@@ -1266,7 +1288,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data) | |||
1266 | struct cifs_ses *ses = sess_data->ses; | 1288 | struct cifs_ses *ses = sess_data->ses; |
1267 | __u16 bytes_remaining; | 1289 | __u16 bytes_remaining; |
1268 | char *bcc_ptr; | 1290 | char *bcc_ptr; |
1269 | char *ntlmsspblob = NULL; | 1291 | unsigned char *ntlmsspblob = NULL; |
1270 | u16 blob_len; | 1292 | u16 blob_len; |
1271 | 1293 | ||
1272 | cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n"); | 1294 | cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n"); |
@@ -1279,19 +1301,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data) | |||
1279 | /* Build security blob before we assemble the request */ | 1301 | /* Build security blob before we assemble the request */ |
1280 | pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; | 1302 | pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; |
1281 | smb_buf = (struct smb_hdr *)pSMB; | 1303 | smb_buf = (struct smb_hdr *)pSMB; |
1282 | /* | 1304 | rc = build_ntlmssp_auth_blob(&ntlmsspblob, |
1283 | * 5 is an empirical value, large enough to hold | ||
1284 | * authenticate message plus max 10 of av paris, | ||
1285 | * domain, user, workstation names, flags, etc. | ||
1286 | */ | ||
1287 | ntlmsspblob = kzalloc(5*sizeof(struct _AUTHENTICATE_MESSAGE), | ||
1288 | GFP_KERNEL); | ||
1289 | if (!ntlmsspblob) { | ||
1290 | rc = -ENOMEM; | ||
1291 | goto out; | ||
1292 | } | ||
1293 | |||
1294 | rc = build_ntlmssp_auth_blob(ntlmsspblob, | ||
1295 | &blob_len, ses, sess_data->nls_cp); | 1305 | &blob_len, ses, sess_data->nls_cp); |
1296 | if (rc) | 1306 | if (rc) |
1297 | goto out_free_ntlmsspblob; | 1307 | goto out_free_ntlmsspblob; |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 8f38e33d365b..29e06db5f187 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -588,7 +588,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
588 | u16 blob_length = 0; | 588 | u16 blob_length = 0; |
589 | struct key *spnego_key = NULL; | 589 | struct key *spnego_key = NULL; |
590 | char *security_blob = NULL; | 590 | char *security_blob = NULL; |
591 | char *ntlmssp_blob = NULL; | 591 | unsigned char *ntlmssp_blob = NULL; |
592 | bool use_spnego = false; /* else use raw ntlmssp */ | 592 | bool use_spnego = false; /* else use raw ntlmssp */ |
593 | 593 | ||
594 | cifs_dbg(FYI, "Session Setup\n"); | 594 | cifs_dbg(FYI, "Session Setup\n"); |
@@ -713,13 +713,7 @@ ssetup_ntlmssp_authenticate: | |||
713 | iov[1].iov_len = blob_length; | 713 | iov[1].iov_len = blob_length; |
714 | } else if (phase == NtLmAuthenticate) { | 714 | } else if (phase == NtLmAuthenticate) { |
715 | req->hdr.SessionId = ses->Suid; | 715 | req->hdr.SessionId = ses->Suid; |
716 | ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500, | 716 | rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, |
717 | GFP_KERNEL); | ||
718 | if (ntlmssp_blob == NULL) { | ||
719 | rc = -ENOMEM; | ||
720 | goto ssetup_exit; | ||
721 | } | ||
722 | rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses, | ||
723 | nls_cp); | 717 | nls_cp); |
724 | if (rc) { | 718 | if (rc) { |
725 | cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", | 719 | cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", |
@@ -1818,6 +1812,33 @@ SMB2_echo(struct TCP_Server_Info *server) | |||
1818 | 1812 | ||
1819 | cifs_dbg(FYI, "In echo request\n"); | 1813 | cifs_dbg(FYI, "In echo request\n"); |
1820 | 1814 | ||
1815 | if (server->tcpStatus == CifsNeedNegotiate) { | ||
1816 | struct list_head *tmp, *tmp2; | ||
1817 | struct cifs_ses *ses; | ||
1818 | struct cifs_tcon *tcon; | ||
1819 | |||
1820 | cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); | ||
1821 | spin_lock(&cifs_tcp_ses_lock); | ||
1822 | list_for_each(tmp, &server->smb_ses_list) { | ||
1823 | ses = list_entry(tmp, struct cifs_ses, smb_ses_list); | ||
1824 | list_for_each(tmp2, &ses->tcon_list) { | ||
1825 | tcon = list_entry(tmp2, struct cifs_tcon, | ||
1826 | tcon_list); | ||
1827 | /* add check for persistent handle reconnect */ | ||
1828 | if (tcon && tcon->need_reconnect) { | ||
1829 | spin_unlock(&cifs_tcp_ses_lock); | ||
1830 | rc = smb2_reconnect(SMB2_ECHO, tcon); | ||
1831 | spin_lock(&cifs_tcp_ses_lock); | ||
1832 | } | ||
1833 | } | ||
1834 | } | ||
1835 | spin_unlock(&cifs_tcp_ses_lock); | ||
1836 | } | ||
1837 | |||
1838 | /* if no session, renegotiate failed above */ | ||
1839 | if (server->tcpStatus == CifsNeedNegotiate) | ||
1840 | return -EIO; | ||
1841 | |||
1821 | rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req); | 1842 | rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req); |
1822 | if (rc) | 1843 | if (rc) |
1823 | return rc; | 1844 | return rc; |
diff --git a/fs/dcache.c b/fs/dcache.c index 817c243c1ff1..d6847d7b123d 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -507,6 +507,44 @@ void d_drop(struct dentry *dentry) | |||
507 | } | 507 | } |
508 | EXPORT_SYMBOL(d_drop); | 508 | EXPORT_SYMBOL(d_drop); |
509 | 509 | ||
510 | static inline void dentry_unlist(struct dentry *dentry, struct dentry *parent) | ||
511 | { | ||
512 | struct dentry *next; | ||
513 | /* | ||
514 | * Inform d_walk() and shrink_dentry_list() that we are no longer | ||
515 | * attached to the dentry tree | ||
516 | */ | ||
517 | dentry->d_flags |= DCACHE_DENTRY_KILLED; | ||
518 | if (unlikely(list_empty(&dentry->d_child))) | ||
519 | return; | ||
520 | __list_del_entry(&dentry->d_child); | ||
521 | /* | ||
522 | * Cursors can move around the list of children. While we'd been | ||
523 | * a normal list member, it didn't matter - ->d_child.next would've | ||
524 | * been updated. However, from now on it won't be and for the | ||
525 | * things like d_walk() it might end up with a nasty surprise. | ||
526 | * Normally d_walk() doesn't care about cursors moving around - | ||
527 | * ->d_lock on parent prevents that and since a cursor has no children | ||
528 | * of its own, we get through it without ever unlocking the parent. | ||
529 | * There is one exception, though - if we ascend from a child that | ||
530 | * gets killed as soon as we unlock it, the next sibling is found | ||
531 | * using the value left in its ->d_child.next. And if _that_ | ||
532 | * pointed to a cursor, and cursor got moved (e.g. by lseek()) | ||
533 | * before d_walk() regains parent->d_lock, we'll end up skipping | ||
534 | * everything the cursor had been moved past. | ||
535 | * | ||
536 | * Solution: make sure that the pointer left behind in ->d_child.next | ||
537 | * points to something that won't be moving around. I.e. skip the | ||
538 | * cursors. | ||
539 | */ | ||
540 | while (dentry->d_child.next != &parent->d_subdirs) { | ||
541 | next = list_entry(dentry->d_child.next, struct dentry, d_child); | ||
542 | if (likely(!(next->d_flags & DCACHE_DENTRY_CURSOR))) | ||
543 | break; | ||
544 | dentry->d_child.next = next->d_child.next; | ||
545 | } | ||
546 | } | ||
547 | |||
510 | static void __dentry_kill(struct dentry *dentry) | 548 | static void __dentry_kill(struct dentry *dentry) |
511 | { | 549 | { |
512 | struct dentry *parent = NULL; | 550 | struct dentry *parent = NULL; |
@@ -532,12 +570,7 @@ static void __dentry_kill(struct dentry *dentry) | |||
532 | } | 570 | } |
533 | /* if it was on the hash then remove it */ | 571 | /* if it was on the hash then remove it */ |
534 | __d_drop(dentry); | 572 | __d_drop(dentry); |
535 | __list_del_entry(&dentry->d_child); | 573 | dentry_unlist(dentry, parent); |
536 | /* | ||
537 | * Inform d_walk() that we are no longer attached to the | ||
538 | * dentry tree | ||
539 | */ | ||
540 | dentry->d_flags |= DCACHE_DENTRY_KILLED; | ||
541 | if (parent) | 574 | if (parent) |
542 | spin_unlock(&parent->d_lock); | 575 | spin_unlock(&parent->d_lock); |
543 | dentry_iput(dentry); | 576 | dentry_iput(dentry); |
@@ -1203,6 +1236,9 @@ resume: | |||
1203 | struct dentry *dentry = list_entry(tmp, struct dentry, d_child); | 1236 | struct dentry *dentry = list_entry(tmp, struct dentry, d_child); |
1204 | next = tmp->next; | 1237 | next = tmp->next; |
1205 | 1238 | ||
1239 | if (unlikely(dentry->d_flags & DCACHE_DENTRY_CURSOR)) | ||
1240 | continue; | ||
1241 | |||
1206 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | 1242 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); |
1207 | 1243 | ||
1208 | ret = enter(data, dentry); | 1244 | ret = enter(data, dentry); |
@@ -1651,6 +1687,16 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1651 | } | 1687 | } |
1652 | EXPORT_SYMBOL(d_alloc); | 1688 | EXPORT_SYMBOL(d_alloc); |
1653 | 1689 | ||
1690 | struct dentry *d_alloc_cursor(struct dentry * parent) | ||
1691 | { | ||
1692 | struct dentry *dentry = __d_alloc(parent->d_sb, NULL); | ||
1693 | if (dentry) { | ||
1694 | dentry->d_flags |= DCACHE_RCUACCESS | DCACHE_DENTRY_CURSOR; | ||
1695 | dentry->d_parent = dget(parent); | ||
1696 | } | ||
1697 | return dentry; | ||
1698 | } | ||
1699 | |||
1654 | /** | 1700 | /** |
1655 | * d_alloc_pseudo - allocate a dentry (for lookup-less filesystems) | 1701 | * d_alloc_pseudo - allocate a dentry (for lookup-less filesystems) |
1656 | * @sb: the superblock | 1702 | * @sb: the superblock |
@@ -2457,7 +2503,6 @@ retry: | |||
2457 | rcu_read_unlock(); | 2503 | rcu_read_unlock(); |
2458 | goto retry; | 2504 | goto retry; |
2459 | } | 2505 | } |
2460 | rcu_read_unlock(); | ||
2461 | /* | 2506 | /* |
2462 | * No changes for the parent since the beginning of d_lookup(). | 2507 | * No changes for the parent since the beginning of d_lookup(). |
2463 | * Since all removals from the chain happen with hlist_bl_lock(), | 2508 | * Since all removals from the chain happen with hlist_bl_lock(), |
@@ -2470,8 +2515,6 @@ retry: | |||
2470 | continue; | 2515 | continue; |
2471 | if (dentry->d_parent != parent) | 2516 | if (dentry->d_parent != parent) |
2472 | continue; | 2517 | continue; |
2473 | if (d_unhashed(dentry)) | ||
2474 | continue; | ||
2475 | if (parent->d_flags & DCACHE_OP_COMPARE) { | 2518 | if (parent->d_flags & DCACHE_OP_COMPARE) { |
2476 | int tlen = dentry->d_name.len; | 2519 | int tlen = dentry->d_name.len; |
2477 | const char *tname = dentry->d_name.name; | 2520 | const char *tname = dentry->d_name.name; |
@@ -2483,9 +2526,18 @@ retry: | |||
2483 | if (dentry_cmp(dentry, str, len)) | 2526 | if (dentry_cmp(dentry, str, len)) |
2484 | continue; | 2527 | continue; |
2485 | } | 2528 | } |
2486 | dget(dentry); | ||
2487 | hlist_bl_unlock(b); | 2529 | hlist_bl_unlock(b); |
2488 | /* somebody is doing lookup for it right now; wait for it */ | 2530 | /* now we can try to grab a reference */ |
2531 | if (!lockref_get_not_dead(&dentry->d_lockref)) { | ||
2532 | rcu_read_unlock(); | ||
2533 | goto retry; | ||
2534 | } | ||
2535 | |||
2536 | rcu_read_unlock(); | ||
2537 | /* | ||
2538 | * somebody is likely to be still doing lookup for it; | ||
2539 | * wait for them to finish | ||
2540 | */ | ||
2489 | spin_lock(&dentry->d_lock); | 2541 | spin_lock(&dentry->d_lock); |
2490 | d_wait_lookup(dentry); | 2542 | d_wait_lookup(dentry); |
2491 | /* | 2543 | /* |
@@ -2516,6 +2568,7 @@ retry: | |||
2516 | dput(new); | 2568 | dput(new); |
2517 | return dentry; | 2569 | return dentry; |
2518 | } | 2570 | } |
2571 | rcu_read_unlock(); | ||
2519 | /* we can't take ->d_lock here; it's OK, though. */ | 2572 | /* we can't take ->d_lock here; it's OK, though. */ |
2520 | new->d_flags |= DCACHE_PAR_LOOKUP; | 2573 | new->d_flags |= DCACHE_PAR_LOOKUP; |
2521 | new->d_wait = wq; | 2574 | new->d_wait = wq; |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 9c1c9a01b7e5..592059f88e04 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -127,7 +127,6 @@ static int open_proxy_open(struct inode *inode, struct file *filp) | |||
127 | r = real_fops->open(inode, filp); | 127 | r = real_fops->open(inode, filp); |
128 | 128 | ||
129 | out: | 129 | out: |
130 | fops_put(real_fops); | ||
131 | debugfs_use_file_finish(srcu_idx); | 130 | debugfs_use_file_finish(srcu_idx); |
132 | return r; | 131 | return r; |
133 | } | 132 | } |
@@ -262,8 +261,10 @@ static int full_proxy_open(struct inode *inode, struct file *filp) | |||
262 | 261 | ||
263 | if (real_fops->open) { | 262 | if (real_fops->open) { |
264 | r = real_fops->open(inode, filp); | 263 | r = real_fops->open(inode, filp); |
265 | 264 | if (r) { | |
266 | if (filp->f_op != proxy_fops) { | 265 | replace_fops(filp, d_inode(dentry)->i_fop); |
266 | goto free_proxy; | ||
267 | } else if (filp->f_op != proxy_fops) { | ||
267 | /* No protection against file removal anymore. */ | 268 | /* No protection against file removal anymore. */ |
268 | WARN(1, "debugfs file owner replaced proxy fops: %pd", | 269 | WARN(1, "debugfs file owner replaced proxy fops: %pd", |
269 | dentry); | 270 | dentry); |
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 866bb18efefe..e818f5ac7a26 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/wait.h> | 26 | #include <linux/wait.h> |
27 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
28 | #include <linux/file.h> | ||
28 | #include "ecryptfs_kernel.h" | 29 | #include "ecryptfs_kernel.h" |
29 | 30 | ||
30 | struct ecryptfs_open_req { | 31 | struct ecryptfs_open_req { |
@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
147 | flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR; | 148 | flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR; |
148 | (*lower_file) = dentry_open(&req.path, flags, cred); | 149 | (*lower_file) = dentry_open(&req.path, flags, cred); |
149 | if (!IS_ERR(*lower_file)) | 150 | if (!IS_ERR(*lower_file)) |
150 | goto out; | 151 | goto have_file; |
151 | if ((flags & O_ACCMODE) == O_RDONLY) { | 152 | if ((flags & O_ACCMODE) == O_RDONLY) { |
152 | rc = PTR_ERR((*lower_file)); | 153 | rc = PTR_ERR((*lower_file)); |
153 | goto out; | 154 | goto out; |
@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
165 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 166 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
166 | wake_up(&ecryptfs_kthread_ctl.wait); | 167 | wake_up(&ecryptfs_kthread_ctl.wait); |
167 | wait_for_completion(&req.done); | 168 | wait_for_completion(&req.done); |
168 | if (IS_ERR(*lower_file)) | 169 | if (IS_ERR(*lower_file)) { |
169 | rc = PTR_ERR(*lower_file); | 170 | rc = PTR_ERR(*lower_file); |
171 | goto out; | ||
172 | } | ||
173 | have_file: | ||
174 | if ((*lower_file)->f_op->mmap == NULL) { | ||
175 | fput(*lower_file); | ||
176 | *lower_file = NULL; | ||
177 | rc = -EMEDIUMTYPE; | ||
178 | } | ||
170 | out: | 179 | out: |
171 | return rc; | 180 | return rc; |
172 | } | 181 | } |
diff --git a/fs/internal.h b/fs/internal.h index b71deeecea17..f57ced528cde 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -130,6 +130,7 @@ extern int invalidate_inodes(struct super_block *, bool); | |||
130 | extern struct dentry *__d_alloc(struct super_block *, const struct qstr *); | 130 | extern struct dentry *__d_alloc(struct super_block *, const struct qstr *); |
131 | extern int d_set_mounted(struct dentry *dentry); | 131 | extern int d_set_mounted(struct dentry *dentry); |
132 | extern long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc); | 132 | extern long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc); |
133 | extern struct dentry *d_alloc_cursor(struct dentry *); | ||
133 | 134 | ||
134 | /* | 135 | /* |
135 | * read_write.c | 136 | * read_write.c |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index b31852f76f46..e3ca4b4cac84 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -2329,18 +2329,10 @@ void *jbd2_alloc(size_t size, gfp_t flags) | |||
2329 | 2329 | ||
2330 | BUG_ON(size & (size-1)); /* Must be a power of 2 */ | 2330 | BUG_ON(size & (size-1)); /* Must be a power of 2 */ |
2331 | 2331 | ||
2332 | flags |= __GFP_REPEAT; | 2332 | if (size < PAGE_SIZE) |
2333 | if (size == PAGE_SIZE) | ||
2334 | ptr = (void *)__get_free_pages(flags, 0); | ||
2335 | else if (size > PAGE_SIZE) { | ||
2336 | int order = get_order(size); | ||
2337 | |||
2338 | if (order < 3) | ||
2339 | ptr = (void *)__get_free_pages(flags, order); | ||
2340 | else | ||
2341 | ptr = vmalloc(size); | ||
2342 | } else | ||
2343 | ptr = kmem_cache_alloc(get_slab(size), flags); | 2333 | ptr = kmem_cache_alloc(get_slab(size), flags); |
2334 | else | ||
2335 | ptr = (void *)__get_free_pages(flags, get_order(size)); | ||
2344 | 2336 | ||
2345 | /* Check alignment; SLUB has gotten this wrong in the past, | 2337 | /* Check alignment; SLUB has gotten this wrong in the past, |
2346 | * and this can lead to user data corruption! */ | 2338 | * and this can lead to user data corruption! */ |
@@ -2351,20 +2343,10 @@ void *jbd2_alloc(size_t size, gfp_t flags) | |||
2351 | 2343 | ||
2352 | void jbd2_free(void *ptr, size_t size) | 2344 | void jbd2_free(void *ptr, size_t size) |
2353 | { | 2345 | { |
2354 | if (size == PAGE_SIZE) { | 2346 | if (size < PAGE_SIZE) |
2355 | free_pages((unsigned long)ptr, 0); | 2347 | kmem_cache_free(get_slab(size), ptr); |
2356 | return; | 2348 | else |
2357 | } | 2349 | free_pages((unsigned long)ptr, get_order(size)); |
2358 | if (size > PAGE_SIZE) { | ||
2359 | int order = get_order(size); | ||
2360 | |||
2361 | if (order < 3) | ||
2362 | free_pages((unsigned long)ptr, order); | ||
2363 | else | ||
2364 | vfree(ptr); | ||
2365 | return; | ||
2366 | } | ||
2367 | kmem_cache_free(get_slab(size), ptr); | ||
2368 | }; | 2350 | }; |
2369 | 2351 | ||
2370 | /* | 2352 | /* |
diff --git a/fs/libfs.c b/fs/libfs.c index 3db2721144c2..cedeacbae303 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -71,9 +71,7 @@ EXPORT_SYMBOL(simple_lookup); | |||
71 | 71 | ||
72 | int dcache_dir_open(struct inode *inode, struct file *file) | 72 | int dcache_dir_open(struct inode *inode, struct file *file) |
73 | { | 73 | { |
74 | static struct qstr cursor_name = QSTR_INIT(".", 1); | 74 | file->private_data = d_alloc_cursor(file->f_path.dentry); |
75 | |||
76 | file->private_data = d_alloc(file->f_path.dentry, &cursor_name); | ||
77 | 75 | ||
78 | return file->private_data ? 0 : -ENOMEM; | 76 | return file->private_data ? 0 : -ENOMEM; |
79 | } | 77 | } |
diff --git a/fs/namespace.c b/fs/namespace.c index a7ec92c051f5..783004af5707 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -3247,6 +3247,10 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags) | |||
3247 | if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC) | 3247 | if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC) |
3248 | mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC); | 3248 | mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC); |
3249 | 3249 | ||
3250 | /* Don't miss readonly hidden in the superblock flags */ | ||
3251 | if (mnt->mnt.mnt_sb->s_flags & MS_RDONLY) | ||
3252 | mnt_flags |= MNT_LOCK_READONLY; | ||
3253 | |||
3250 | /* Verify the mount flags are equal to or more permissive | 3254 | /* Verify the mount flags are equal to or more permissive |
3251 | * than the proposed new mount. | 3255 | * than the proposed new mount. |
3252 | */ | 3256 | */ |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index aaf7bd0cbae2..d8015a03db4c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, | |||
424 | static | 424 | static |
425 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 425 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
426 | { | 426 | { |
427 | struct inode *inode; | ||
427 | struct nfs_inode *nfsi; | 428 | struct nfs_inode *nfsi; |
428 | 429 | ||
429 | if (d_really_is_negative(dentry)) | 430 | if (d_really_is_negative(dentry)) |
430 | return 0; | 431 | return 0; |
431 | 432 | ||
432 | nfsi = NFS_I(d_inode(dentry)); | 433 | inode = d_inode(dentry); |
434 | if (is_bad_inode(inode) || NFS_STALE(inode)) | ||
435 | return 0; | ||
436 | |||
437 | nfsi = NFS_I(inode); | ||
433 | if (entry->fattr->fileid == nfsi->fileid) | 438 | if (entry->fattr->fileid == nfsi->fileid) |
434 | return 1; | 439 | return 1; |
435 | if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) | 440 | if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) |
@@ -1363,7 +1368,6 @@ EXPORT_SYMBOL_GPL(nfs_dentry_operations); | |||
1363 | struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) | 1368 | struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
1364 | { | 1369 | { |
1365 | struct dentry *res; | 1370 | struct dentry *res; |
1366 | struct dentry *parent; | ||
1367 | struct inode *inode = NULL; | 1371 | struct inode *inode = NULL; |
1368 | struct nfs_fh *fhandle = NULL; | 1372 | struct nfs_fh *fhandle = NULL; |
1369 | struct nfs_fattr *fattr = NULL; | 1373 | struct nfs_fattr *fattr = NULL; |
@@ -1393,7 +1397,6 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1393 | if (IS_ERR(label)) | 1397 | if (IS_ERR(label)) |
1394 | goto out; | 1398 | goto out; |
1395 | 1399 | ||
1396 | parent = dentry->d_parent; | ||
1397 | /* Protect against concurrent sillydeletes */ | 1400 | /* Protect against concurrent sillydeletes */ |
1398 | trace_nfs_lookup_enter(dir, dentry, flags); | 1401 | trace_nfs_lookup_enter(dir, dentry, flags); |
1399 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1402 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
@@ -1536,9 +1539,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1536 | err = PTR_ERR(inode); | 1539 | err = PTR_ERR(inode); |
1537 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | 1540 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); |
1538 | put_nfs_open_context(ctx); | 1541 | put_nfs_open_context(ctx); |
1542 | d_drop(dentry); | ||
1539 | switch (err) { | 1543 | switch (err) { |
1540 | case -ENOENT: | 1544 | case -ENOENT: |
1541 | d_drop(dentry); | ||
1542 | d_add(dentry, NULL); | 1545 | d_add(dentry, NULL); |
1543 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1546 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1544 | break; | 1547 | break; |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 979b3c4dee6a..c7326c2af2c3 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -353,10 +353,12 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) | |||
353 | 353 | ||
354 | result = wait_for_completion_killable(&dreq->completion); | 354 | result = wait_for_completion_killable(&dreq->completion); |
355 | 355 | ||
356 | if (!result) { | ||
357 | result = dreq->count; | ||
358 | WARN_ON_ONCE(dreq->count < 0); | ||
359 | } | ||
356 | if (!result) | 360 | if (!result) |
357 | result = dreq->error; | 361 | result = dreq->error; |
358 | if (!result) | ||
359 | result = dreq->count; | ||
360 | 362 | ||
361 | out: | 363 | out: |
362 | return (ssize_t) result; | 364 | return (ssize_t) result; |
@@ -386,8 +388,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) | |||
386 | 388 | ||
387 | if (dreq->iocb) { | 389 | if (dreq->iocb) { |
388 | long res = (long) dreq->error; | 390 | long res = (long) dreq->error; |
389 | if (!res) | 391 | if (dreq->count != 0) { |
390 | res = (long) dreq->count; | 392 | res = (long) dreq->count; |
393 | WARN_ON_ONCE(dreq->count < 0); | ||
394 | } | ||
391 | dreq->iocb->ki_complete(dreq->iocb, res, 0); | 395 | dreq->iocb->ki_complete(dreq->iocb, res, 0); |
392 | } | 396 | } |
393 | 397 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 52e7d6869e3b..dda689d7a8a7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -282,6 +282,7 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
282 | struct nfs_fattr *fattr = desc->fattr; | 282 | struct nfs_fattr *fattr = desc->fattr; |
283 | 283 | ||
284 | set_nfs_fileid(inode, fattr->fileid); | 284 | set_nfs_fileid(inode, fattr->fileid); |
285 | inode->i_mode = fattr->mode; | ||
285 | nfs_copy_fh(NFS_FH(inode), desc->fh); | 286 | nfs_copy_fh(NFS_FH(inode), desc->fh); |
286 | return 0; | 287 | return 0; |
287 | } | 288 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index de97567795a5..ff416d0e24bc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2882,12 +2882,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2882 | call_close |= is_wronly; | 2882 | call_close |= is_wronly; |
2883 | else if (is_wronly) | 2883 | else if (is_wronly) |
2884 | calldata->arg.fmode |= FMODE_WRITE; | 2884 | calldata->arg.fmode |= FMODE_WRITE; |
2885 | if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE)) | ||
2886 | call_close |= is_rdwr; | ||
2885 | } else if (is_rdwr) | 2887 | } else if (is_rdwr) |
2886 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; | 2888 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; |
2887 | 2889 | ||
2888 | if (calldata->arg.fmode == 0) | ||
2889 | call_close |= is_rdwr; | ||
2890 | |||
2891 | if (!nfs4_valid_open_stateid(state)) | 2890 | if (!nfs4_valid_open_stateid(state)) |
2892 | call_close = 0; | 2891 | call_close = 0; |
2893 | spin_unlock(&state->owner->so_lock); | 2892 | spin_unlock(&state->owner->so_lock); |
@@ -7924,8 +7923,8 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, | |||
7924 | break; | 7923 | break; |
7925 | } | 7924 | } |
7926 | lo = NFS_I(inode)->layout; | 7925 | lo = NFS_I(inode)->layout; |
7927 | if (lo && nfs4_stateid_match(&lgp->args.stateid, | 7926 | if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) && |
7928 | &lo->plh_stateid)) { | 7927 | nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) { |
7929 | LIST_HEAD(head); | 7928 | LIST_HEAD(head); |
7930 | 7929 | ||
7931 | /* | 7930 | /* |
@@ -7936,10 +7935,10 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, | |||
7936 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0); | 7935 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0); |
7937 | spin_unlock(&inode->i_lock); | 7936 | spin_unlock(&inode->i_lock); |
7938 | pnfs_free_lseg_list(&head); | 7937 | pnfs_free_lseg_list(&head); |
7938 | status = -EAGAIN; | ||
7939 | goto out; | ||
7939 | } else | 7940 | } else |
7940 | spin_unlock(&inode->i_lock); | 7941 | spin_unlock(&inode->i_lock); |
7941 | status = -EAGAIN; | ||
7942 | goto out; | ||
7943 | } | 7942 | } |
7944 | 7943 | ||
7945 | status = nfs4_handle_exception(server, status, exception); | 7944 | status = nfs4_handle_exception(server, status, exception); |
@@ -8036,7 +8035,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags) | |||
8036 | .flags = RPC_TASK_ASYNC, | 8035 | .flags = RPC_TASK_ASYNC, |
8037 | }; | 8036 | }; |
8038 | struct pnfs_layout_segment *lseg = NULL; | 8037 | struct pnfs_layout_segment *lseg = NULL; |
8039 | struct nfs4_exception exception = { .timeout = *timeout }; | 8038 | struct nfs4_exception exception = { |
8039 | .inode = inode, | ||
8040 | .timeout = *timeout, | ||
8041 | }; | ||
8040 | int status = 0; | 8042 | int status = 0; |
8041 | 8043 | ||
8042 | dprintk("--> %s\n", __func__); | 8044 | dprintk("--> %s\n", __func__); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 9679f4749364..834b875900d6 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1488,9 +1488,9 @@ restart: | |||
1488 | } | 1488 | } |
1489 | spin_unlock(&state->state_lock); | 1489 | spin_unlock(&state->state_lock); |
1490 | } | 1490 | } |
1491 | nfs4_put_open_state(state); | ||
1492 | clear_bit(NFS_STATE_RECLAIM_NOGRACE, | 1491 | clear_bit(NFS_STATE_RECLAIM_NOGRACE, |
1493 | &state->flags); | 1492 | &state->flags); |
1493 | nfs4_put_open_state(state); | ||
1494 | spin_lock(&sp->so_lock); | 1494 | spin_lock(&sp->so_lock); |
1495 | goto restart; | 1495 | goto restart; |
1496 | } | 1496 | } |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0c7e0d45a4de..0fbe734cc38c 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -361,8 +361,10 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, | |||
361 | list_del_init(&lseg->pls_list); | 361 | list_del_init(&lseg->pls_list); |
362 | /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ | 362 | /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ |
363 | atomic_dec(&lo->plh_refcount); | 363 | atomic_dec(&lo->plh_refcount); |
364 | if (list_empty(&lo->plh_segs)) | 364 | if (list_empty(&lo->plh_segs)) { |
365 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
365 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); | 366 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); |
367 | } | ||
366 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); | 368 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); |
367 | } | 369 | } |
368 | 370 | ||
@@ -1290,6 +1292,7 @@ alloc_init_layout_hdr(struct inode *ino, | |||
1290 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); | 1292 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); |
1291 | lo->plh_inode = ino; | 1293 | lo->plh_inode = ino; |
1292 | lo->plh_lc_cred = get_rpccred(ctx->cred); | 1294 | lo->plh_lc_cred = get_rpccred(ctx->cred); |
1295 | lo->plh_flags |= 1 << NFS_LAYOUT_INVALID_STID; | ||
1293 | return lo; | 1296 | return lo; |
1294 | } | 1297 | } |
1295 | 1298 | ||
@@ -1297,6 +1300,8 @@ static struct pnfs_layout_hdr * | |||
1297 | pnfs_find_alloc_layout(struct inode *ino, | 1300 | pnfs_find_alloc_layout(struct inode *ino, |
1298 | struct nfs_open_context *ctx, | 1301 | struct nfs_open_context *ctx, |
1299 | gfp_t gfp_flags) | 1302 | gfp_t gfp_flags) |
1303 | __releases(&ino->i_lock) | ||
1304 | __acquires(&ino->i_lock) | ||
1300 | { | 1305 | { |
1301 | struct nfs_inode *nfsi = NFS_I(ino); | 1306 | struct nfs_inode *nfsi = NFS_I(ino); |
1302 | struct pnfs_layout_hdr *new = NULL; | 1307 | struct pnfs_layout_hdr *new = NULL; |
@@ -1565,8 +1570,7 @@ lookup_again: | |||
1565 | * stateid, or it has been invalidated, then we must use the open | 1570 | * stateid, or it has been invalidated, then we must use the open |
1566 | * stateid. | 1571 | * stateid. |
1567 | */ | 1572 | */ |
1568 | if (lo->plh_stateid.seqid == 0 || | 1573 | if (test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { |
1569 | test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { | ||
1570 | 1574 | ||
1571 | /* | 1575 | /* |
1572 | * The first layoutget for the file. Need to serialize per | 1576 | * The first layoutget for the file. Need to serialize per |
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index 0dfc476da3e1..b38e3c0dc790 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -247,7 +247,11 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, | |||
247 | } | 247 | } |
248 | 248 | ||
249 | /* Helper function for pnfs_generic_commit_pagelist to catch an empty | 249 | /* Helper function for pnfs_generic_commit_pagelist to catch an empty |
250 | * page list. This can happen when two commits race. */ | 250 | * page list. This can happen when two commits race. |
251 | * | ||
252 | * This must be called instead of nfs_init_commit - call one or the other, but | ||
253 | * not both! | ||
254 | */ | ||
251 | static bool | 255 | static bool |
252 | pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | 256 | pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, |
253 | struct nfs_commit_data *data, | 257 | struct nfs_commit_data *data, |
@@ -256,7 +260,11 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | |||
256 | if (list_empty(pages)) { | 260 | if (list_empty(pages)) { |
257 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) | 261 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) |
258 | wake_up_atomic_t(&cinfo->mds->rpcs_out); | 262 | wake_up_atomic_t(&cinfo->mds->rpcs_out); |
259 | nfs_commitdata_release(data); | 263 | /* don't call nfs_commitdata_release - it tries to put |
264 | * the open_context which is not acquired until nfs_init_commit | ||
265 | * which has not been called on @data */ | ||
266 | WARN_ON_ONCE(data->context); | ||
267 | nfs_commit_free(data); | ||
260 | return true; | 268 | return true; |
261 | } | 269 | } |
262 | 270 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6776d7a7839e..572e5b3b06f1 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -367,13 +367,13 @@ readpage_async_filler(void *data, struct page *page) | |||
367 | nfs_list_remove_request(new); | 367 | nfs_list_remove_request(new); |
368 | nfs_readpage_release(new); | 368 | nfs_readpage_release(new); |
369 | error = desc->pgio->pg_error; | 369 | error = desc->pgio->pg_error; |
370 | goto out_unlock; | 370 | goto out; |
371 | } | 371 | } |
372 | return 0; | 372 | return 0; |
373 | out_error: | 373 | out_error: |
374 | error = PTR_ERR(new); | 374 | error = PTR_ERR(new); |
375 | out_unlock: | ||
376 | unlock_page(page); | 375 | unlock_page(page); |
376 | out: | ||
377 | return error; | 377 | return error; |
378 | } | 378 | } |
379 | 379 | ||
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c index e55b5242614d..31f3df193bdb 100644 --- a/fs/nfsd/blocklayout.c +++ b/fs/nfsd/blocklayout.c | |||
@@ -290,7 +290,7 @@ out_free_buf: | |||
290 | return error; | 290 | return error; |
291 | } | 291 | } |
292 | 292 | ||
293 | #define NFSD_MDS_PR_KEY 0x0100000000000000 | 293 | #define NFSD_MDS_PR_KEY 0x0100000000000000ULL |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * We use the client ID as a unique key for the reservations. | 296 | * We use the client ID as a unique key for the reservations. |
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 1580ea6fd64d..d08cd88155c7 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
@@ -104,22 +104,21 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp, | |||
104 | goto out; | 104 | goto out; |
105 | 105 | ||
106 | inode = d_inode(fh->fh_dentry); | 106 | inode = d_inode(fh->fh_dentry); |
107 | if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { | ||
108 | error = -EOPNOTSUPP; | ||
109 | goto out_errno; | ||
110 | } | ||
111 | 107 | ||
112 | error = fh_want_write(fh); | 108 | error = fh_want_write(fh); |
113 | if (error) | 109 | if (error) |
114 | goto out_errno; | 110 | goto out_errno; |
115 | 111 | ||
116 | error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); | 112 | fh_lock(fh); |
113 | |||
114 | error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); | ||
117 | if (error) | 115 | if (error) |
118 | goto out_drop_write; | 116 | goto out_drop_lock; |
119 | error = inode->i_op->set_acl(inode, argp->acl_default, | 117 | error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); |
120 | ACL_TYPE_DEFAULT); | ||
121 | if (error) | 118 | if (error) |
122 | goto out_drop_write; | 119 | goto out_drop_lock; |
120 | |||
121 | fh_unlock(fh); | ||
123 | 122 | ||
124 | fh_drop_write(fh); | 123 | fh_drop_write(fh); |
125 | 124 | ||
@@ -131,7 +130,8 @@ out: | |||
131 | posix_acl_release(argp->acl_access); | 130 | posix_acl_release(argp->acl_access); |
132 | posix_acl_release(argp->acl_default); | 131 | posix_acl_release(argp->acl_default); |
133 | return nfserr; | 132 | return nfserr; |
134 | out_drop_write: | 133 | out_drop_lock: |
134 | fh_unlock(fh); | ||
135 | fh_drop_write(fh); | 135 | fh_drop_write(fh); |
136 | out_errno: | 136 | out_errno: |
137 | nfserr = nfserrno(error); | 137 | nfserr = nfserrno(error); |
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index 01df4cd7c753..0c890347cde3 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c | |||
@@ -95,22 +95,20 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp, | |||
95 | goto out; | 95 | goto out; |
96 | 96 | ||
97 | inode = d_inode(fh->fh_dentry); | 97 | inode = d_inode(fh->fh_dentry); |
98 | if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { | ||
99 | error = -EOPNOTSUPP; | ||
100 | goto out_errno; | ||
101 | } | ||
102 | 98 | ||
103 | error = fh_want_write(fh); | 99 | error = fh_want_write(fh); |
104 | if (error) | 100 | if (error) |
105 | goto out_errno; | 101 | goto out_errno; |
106 | 102 | ||
107 | error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); | 103 | fh_lock(fh); |
104 | |||
105 | error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); | ||
108 | if (error) | 106 | if (error) |
109 | goto out_drop_write; | 107 | goto out_drop_lock; |
110 | error = inode->i_op->set_acl(inode, argp->acl_default, | 108 | error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); |
111 | ACL_TYPE_DEFAULT); | ||
112 | 109 | ||
113 | out_drop_write: | 110 | out_drop_lock: |
111 | fh_unlock(fh); | ||
114 | fh_drop_write(fh); | 112 | fh_drop_write(fh); |
115 | out_errno: | 113 | out_errno: |
116 | nfserr = nfserrno(error); | 114 | nfserr = nfserrno(error); |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 6adabd6049b7..71292a0d6f09 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -770,9 +770,6 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
770 | dentry = fhp->fh_dentry; | 770 | dentry = fhp->fh_dentry; |
771 | inode = d_inode(dentry); | 771 | inode = d_inode(dentry); |
772 | 772 | ||
773 | if (!inode->i_op->set_acl || !IS_POSIXACL(inode)) | ||
774 | return nfserr_attrnotsupp; | ||
775 | |||
776 | if (S_ISDIR(inode->i_mode)) | 773 | if (S_ISDIR(inode->i_mode)) |
777 | flags = NFS4_ACL_DIR; | 774 | flags = NFS4_ACL_DIR; |
778 | 775 | ||
@@ -782,16 +779,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
782 | if (host_error < 0) | 779 | if (host_error < 0) |
783 | goto out_nfserr; | 780 | goto out_nfserr; |
784 | 781 | ||
785 | host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS); | 782 | fh_lock(fhp); |
783 | |||
784 | host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl); | ||
786 | if (host_error < 0) | 785 | if (host_error < 0) |
787 | goto out_release; | 786 | goto out_drop_lock; |
788 | 787 | ||
789 | if (S_ISDIR(inode->i_mode)) { | 788 | if (S_ISDIR(inode->i_mode)) { |
790 | host_error = inode->i_op->set_acl(inode, dpacl, | 789 | host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl); |
791 | ACL_TYPE_DEFAULT); | ||
792 | } | 790 | } |
793 | 791 | ||
794 | out_release: | 792 | out_drop_lock: |
793 | fh_unlock(fhp); | ||
794 | |||
795 | posix_acl_release(pacl); | 795 | posix_acl_release(pacl); |
796 | posix_acl_release(dpacl); | 796 | posix_acl_release(dpacl); |
797 | out_nfserr: | 797 | out_nfserr: |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 7389cb1d7409..04c68d900324 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -710,22 +710,6 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc | |||
710 | } | 710 | } |
711 | } | 711 | } |
712 | 712 | ||
713 | static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args) | ||
714 | { | ||
715 | struct rpc_xprt *xprt; | ||
716 | |||
717 | if (args->protocol != XPRT_TRANSPORT_BC_TCP) | ||
718 | return rpc_create(args); | ||
719 | |||
720 | xprt = args->bc_xprt->xpt_bc_xprt; | ||
721 | if (xprt) { | ||
722 | xprt_get(xprt); | ||
723 | return rpc_create_xprt(args, xprt); | ||
724 | } | ||
725 | |||
726 | return rpc_create(args); | ||
727 | } | ||
728 | |||
729 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) | 713 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) |
730 | { | 714 | { |
731 | int maxtime = max_cb_time(clp->net); | 715 | int maxtime = max_cb_time(clp->net); |
@@ -768,7 +752,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c | |||
768 | args.authflavor = ses->se_cb_sec.flavor; | 752 | args.authflavor = ses->se_cb_sec.flavor; |
769 | } | 753 | } |
770 | /* Create RPC client */ | 754 | /* Create RPC client */ |
771 | client = create_backchannel_client(&args); | 755 | client = rpc_create(&args); |
772 | if (IS_ERR(client)) { | 756 | if (IS_ERR(client)) { |
773 | dprintk("NFSD: couldn't create callback client: %ld\n", | 757 | dprintk("NFSD: couldn't create callback client: %ld\n", |
774 | PTR_ERR(client)); | 758 | PTR_ERR(client)); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index f5f82e145018..70d0b9b33031 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -3480,12 +3480,17 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, | |||
3480 | } | 3480 | } |
3481 | 3481 | ||
3482 | static struct nfs4_ol_stateid * | 3482 | static struct nfs4_ol_stateid * |
3483 | init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | 3483 | init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open) |
3484 | struct nfsd4_open *open) | ||
3485 | { | 3484 | { |
3486 | 3485 | ||
3487 | struct nfs4_openowner *oo = open->op_openowner; | 3486 | struct nfs4_openowner *oo = open->op_openowner; |
3488 | struct nfs4_ol_stateid *retstp = NULL; | 3487 | struct nfs4_ol_stateid *retstp = NULL; |
3488 | struct nfs4_ol_stateid *stp; | ||
3489 | |||
3490 | stp = open->op_stp; | ||
3491 | /* We are moving these outside of the spinlocks to avoid the warnings */ | ||
3492 | mutex_init(&stp->st_mutex); | ||
3493 | mutex_lock(&stp->st_mutex); | ||
3489 | 3494 | ||
3490 | spin_lock(&oo->oo_owner.so_client->cl_lock); | 3495 | spin_lock(&oo->oo_owner.so_client->cl_lock); |
3491 | spin_lock(&fp->fi_lock); | 3496 | spin_lock(&fp->fi_lock); |
@@ -3493,6 +3498,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | |||
3493 | retstp = nfsd4_find_existing_open(fp, open); | 3498 | retstp = nfsd4_find_existing_open(fp, open); |
3494 | if (retstp) | 3499 | if (retstp) |
3495 | goto out_unlock; | 3500 | goto out_unlock; |
3501 | |||
3502 | open->op_stp = NULL; | ||
3496 | atomic_inc(&stp->st_stid.sc_count); | 3503 | atomic_inc(&stp->st_stid.sc_count); |
3497 | stp->st_stid.sc_type = NFS4_OPEN_STID; | 3504 | stp->st_stid.sc_type = NFS4_OPEN_STID; |
3498 | INIT_LIST_HEAD(&stp->st_locks); | 3505 | INIT_LIST_HEAD(&stp->st_locks); |
@@ -3502,14 +3509,19 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | |||
3502 | stp->st_access_bmap = 0; | 3509 | stp->st_access_bmap = 0; |
3503 | stp->st_deny_bmap = 0; | 3510 | stp->st_deny_bmap = 0; |
3504 | stp->st_openstp = NULL; | 3511 | stp->st_openstp = NULL; |
3505 | init_rwsem(&stp->st_rwsem); | ||
3506 | list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); | 3512 | list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); |
3507 | list_add(&stp->st_perfile, &fp->fi_stateids); | 3513 | list_add(&stp->st_perfile, &fp->fi_stateids); |
3508 | 3514 | ||
3509 | out_unlock: | 3515 | out_unlock: |
3510 | spin_unlock(&fp->fi_lock); | 3516 | spin_unlock(&fp->fi_lock); |
3511 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | 3517 | spin_unlock(&oo->oo_owner.so_client->cl_lock); |
3512 | return retstp; | 3518 | if (retstp) { |
3519 | mutex_lock(&retstp->st_mutex); | ||
3520 | /* To keep mutex tracking happy */ | ||
3521 | mutex_unlock(&stp->st_mutex); | ||
3522 | stp = retstp; | ||
3523 | } | ||
3524 | return stp; | ||
3513 | } | 3525 | } |
3514 | 3526 | ||
3515 | /* | 3527 | /* |
@@ -4305,7 +4317,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
4305 | struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; | 4317 | struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; |
4306 | struct nfs4_file *fp = NULL; | 4318 | struct nfs4_file *fp = NULL; |
4307 | struct nfs4_ol_stateid *stp = NULL; | 4319 | struct nfs4_ol_stateid *stp = NULL; |
4308 | struct nfs4_ol_stateid *swapstp = NULL; | ||
4309 | struct nfs4_delegation *dp = NULL; | 4320 | struct nfs4_delegation *dp = NULL; |
4310 | __be32 status; | 4321 | __be32 status; |
4311 | 4322 | ||
@@ -4335,32 +4346,28 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
4335 | */ | 4346 | */ |
4336 | if (stp) { | 4347 | if (stp) { |
4337 | /* Stateid was found, this is an OPEN upgrade */ | 4348 | /* Stateid was found, this is an OPEN upgrade */ |
4338 | down_read(&stp->st_rwsem); | 4349 | mutex_lock(&stp->st_mutex); |
4339 | status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); | 4350 | status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); |
4340 | if (status) { | 4351 | if (status) { |
4341 | up_read(&stp->st_rwsem); | 4352 | mutex_unlock(&stp->st_mutex); |
4342 | goto out; | 4353 | goto out; |
4343 | } | 4354 | } |
4344 | } else { | 4355 | } else { |
4345 | stp = open->op_stp; | 4356 | /* stp is returned locked. */ |
4346 | open->op_stp = NULL; | 4357 | stp = init_open_stateid(fp, open); |
4347 | swapstp = init_open_stateid(stp, fp, open); | 4358 | /* See if we lost the race to some other thread */ |
4348 | if (swapstp) { | 4359 | if (stp->st_access_bmap != 0) { |
4349 | nfs4_put_stid(&stp->st_stid); | ||
4350 | stp = swapstp; | ||
4351 | down_read(&stp->st_rwsem); | ||
4352 | status = nfs4_upgrade_open(rqstp, fp, current_fh, | 4360 | status = nfs4_upgrade_open(rqstp, fp, current_fh, |
4353 | stp, open); | 4361 | stp, open); |
4354 | if (status) { | 4362 | if (status) { |
4355 | up_read(&stp->st_rwsem); | 4363 | mutex_unlock(&stp->st_mutex); |
4356 | goto out; | 4364 | goto out; |
4357 | } | 4365 | } |
4358 | goto upgrade_out; | 4366 | goto upgrade_out; |
4359 | } | 4367 | } |
4360 | down_read(&stp->st_rwsem); | ||
4361 | status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); | 4368 | status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); |
4362 | if (status) { | 4369 | if (status) { |
4363 | up_read(&stp->st_rwsem); | 4370 | mutex_unlock(&stp->st_mutex); |
4364 | release_open_stateid(stp); | 4371 | release_open_stateid(stp); |
4365 | goto out; | 4372 | goto out; |
4366 | } | 4373 | } |
@@ -4372,7 +4379,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
4372 | } | 4379 | } |
4373 | upgrade_out: | 4380 | upgrade_out: |
4374 | nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid); | 4381 | nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid); |
4375 | up_read(&stp->st_rwsem); | 4382 | mutex_unlock(&stp->st_mutex); |
4376 | 4383 | ||
4377 | if (nfsd4_has_session(&resp->cstate)) { | 4384 | if (nfsd4_has_session(&resp->cstate)) { |
4378 | if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { | 4385 | if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { |
@@ -4977,12 +4984,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_ | |||
4977 | * revoked delegations are kept only for free_stateid. | 4984 | * revoked delegations are kept only for free_stateid. |
4978 | */ | 4985 | */ |
4979 | return nfserr_bad_stateid; | 4986 | return nfserr_bad_stateid; |
4980 | down_write(&stp->st_rwsem); | 4987 | mutex_lock(&stp->st_mutex); |
4981 | status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); | 4988 | status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); |
4982 | if (status == nfs_ok) | 4989 | if (status == nfs_ok) |
4983 | status = nfs4_check_fh(current_fh, &stp->st_stid); | 4990 | status = nfs4_check_fh(current_fh, &stp->st_stid); |
4984 | if (status != nfs_ok) | 4991 | if (status != nfs_ok) |
4985 | up_write(&stp->st_rwsem); | 4992 | mutex_unlock(&stp->st_mutex); |
4986 | return status; | 4993 | return status; |
4987 | } | 4994 | } |
4988 | 4995 | ||
@@ -5030,7 +5037,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs | |||
5030 | return status; | 5037 | return status; |
5031 | oo = openowner(stp->st_stateowner); | 5038 | oo = openowner(stp->st_stateowner); |
5032 | if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { | 5039 | if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { |
5033 | up_write(&stp->st_rwsem); | 5040 | mutex_unlock(&stp->st_mutex); |
5034 | nfs4_put_stid(&stp->st_stid); | 5041 | nfs4_put_stid(&stp->st_stid); |
5035 | return nfserr_bad_stateid; | 5042 | return nfserr_bad_stateid; |
5036 | } | 5043 | } |
@@ -5062,12 +5069,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5062 | oo = openowner(stp->st_stateowner); | 5069 | oo = openowner(stp->st_stateowner); |
5063 | status = nfserr_bad_stateid; | 5070 | status = nfserr_bad_stateid; |
5064 | if (oo->oo_flags & NFS4_OO_CONFIRMED) { | 5071 | if (oo->oo_flags & NFS4_OO_CONFIRMED) { |
5065 | up_write(&stp->st_rwsem); | 5072 | mutex_unlock(&stp->st_mutex); |
5066 | goto put_stateid; | 5073 | goto put_stateid; |
5067 | } | 5074 | } |
5068 | oo->oo_flags |= NFS4_OO_CONFIRMED; | 5075 | oo->oo_flags |= NFS4_OO_CONFIRMED; |
5069 | nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid); | 5076 | nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid); |
5070 | up_write(&stp->st_rwsem); | 5077 | mutex_unlock(&stp->st_mutex); |
5071 | dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", | 5078 | dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", |
5072 | __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); | 5079 | __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); |
5073 | 5080 | ||
@@ -5143,7 +5150,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, | |||
5143 | nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid); | 5150 | nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid); |
5144 | status = nfs_ok; | 5151 | status = nfs_ok; |
5145 | put_stateid: | 5152 | put_stateid: |
5146 | up_write(&stp->st_rwsem); | 5153 | mutex_unlock(&stp->st_mutex); |
5147 | nfs4_put_stid(&stp->st_stid); | 5154 | nfs4_put_stid(&stp->st_stid); |
5148 | out: | 5155 | out: |
5149 | nfsd4_bump_seqid(cstate, status); | 5156 | nfsd4_bump_seqid(cstate, status); |
@@ -5196,7 +5203,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5196 | if (status) | 5203 | if (status) |
5197 | goto out; | 5204 | goto out; |
5198 | nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); | 5205 | nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); |
5199 | up_write(&stp->st_rwsem); | 5206 | mutex_unlock(&stp->st_mutex); |
5200 | 5207 | ||
5201 | nfsd4_close_open_stateid(stp); | 5208 | nfsd4_close_open_stateid(stp); |
5202 | 5209 | ||
@@ -5422,7 +5429,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, | |||
5422 | stp->st_access_bmap = 0; | 5429 | stp->st_access_bmap = 0; |
5423 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 5430 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
5424 | stp->st_openstp = open_stp; | 5431 | stp->st_openstp = open_stp; |
5425 | init_rwsem(&stp->st_rwsem); | 5432 | mutex_init(&stp->st_mutex); |
5426 | list_add(&stp->st_locks, &open_stp->st_locks); | 5433 | list_add(&stp->st_locks, &open_stp->st_locks); |
5427 | list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); | 5434 | list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); |
5428 | spin_lock(&fp->fi_lock); | 5435 | spin_lock(&fp->fi_lock); |
@@ -5591,7 +5598,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5591 | &open_stp, nn); | 5598 | &open_stp, nn); |
5592 | if (status) | 5599 | if (status) |
5593 | goto out; | 5600 | goto out; |
5594 | up_write(&open_stp->st_rwsem); | 5601 | mutex_unlock(&open_stp->st_mutex); |
5595 | open_sop = openowner(open_stp->st_stateowner); | 5602 | open_sop = openowner(open_stp->st_stateowner); |
5596 | status = nfserr_bad_stateid; | 5603 | status = nfserr_bad_stateid; |
5597 | if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, | 5604 | if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, |
@@ -5600,7 +5607,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5600 | status = lookup_or_create_lock_state(cstate, open_stp, lock, | 5607 | status = lookup_or_create_lock_state(cstate, open_stp, lock, |
5601 | &lock_stp, &new); | 5608 | &lock_stp, &new); |
5602 | if (status == nfs_ok) | 5609 | if (status == nfs_ok) |
5603 | down_write(&lock_stp->st_rwsem); | 5610 | mutex_lock(&lock_stp->st_mutex); |
5604 | } else { | 5611 | } else { |
5605 | status = nfs4_preprocess_seqid_op(cstate, | 5612 | status = nfs4_preprocess_seqid_op(cstate, |
5606 | lock->lk_old_lock_seqid, | 5613 | lock->lk_old_lock_seqid, |
@@ -5704,7 +5711,7 @@ out: | |||
5704 | seqid_mutating_err(ntohl(status))) | 5711 | seqid_mutating_err(ntohl(status))) |
5705 | lock_sop->lo_owner.so_seqid++; | 5712 | lock_sop->lo_owner.so_seqid++; |
5706 | 5713 | ||
5707 | up_write(&lock_stp->st_rwsem); | 5714 | mutex_unlock(&lock_stp->st_mutex); |
5708 | 5715 | ||
5709 | /* | 5716 | /* |
5710 | * If this is a new, never-before-used stateid, and we are | 5717 | * If this is a new, never-before-used stateid, and we are |
@@ -5874,7 +5881,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5874 | fput: | 5881 | fput: |
5875 | fput(filp); | 5882 | fput(filp); |
5876 | put_stateid: | 5883 | put_stateid: |
5877 | up_write(&stp->st_rwsem); | 5884 | mutex_unlock(&stp->st_mutex); |
5878 | nfs4_put_stid(&stp->st_stid); | 5885 | nfs4_put_stid(&stp->st_stid); |
5879 | out: | 5886 | out: |
5880 | nfsd4_bump_seqid(cstate, status); | 5887 | nfsd4_bump_seqid(cstate, status); |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 986e51e5ceac..64053eadeb81 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -535,7 +535,7 @@ struct nfs4_ol_stateid { | |||
535 | unsigned char st_access_bmap; | 535 | unsigned char st_access_bmap; |
536 | unsigned char st_deny_bmap; | 536 | unsigned char st_deny_bmap; |
537 | struct nfs4_ol_stateid *st_openstp; | 537 | struct nfs4_ol_stateid *st_openstp; |
538 | struct rw_semaphore st_rwsem; | 538 | struct mutex st_mutex; |
539 | }; | 539 | }; |
540 | 540 | ||
541 | static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) | 541 | static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 809bd2de7ad0..e9fd241b9a0a 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -439,7 +439,7 @@ static int nilfs_valid_sb(struct nilfs_super_block *sbp) | |||
439 | if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC) | 439 | if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC) |
440 | return 0; | 440 | return 0; |
441 | bytes = le16_to_cpu(sbp->s_bytes); | 441 | bytes = le16_to_cpu(sbp->s_bytes); |
442 | if (bytes > BLOCK_SIZE) | 442 | if (bytes < sumoff + 4 || bytes > BLOCK_SIZE) |
443 | return 0; | 443 | return 0; |
444 | crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp, | 444 | crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp, |
445 | sumoff); | 445 | sumoff); |
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile index e27e6527912b..4342c7ee7d20 100644 --- a/fs/ocfs2/Makefile +++ b/fs/ocfs2/Makefile | |||
@@ -1,7 +1,5 @@ | |||
1 | ccflags-y := -Ifs/ocfs2 | 1 | ccflags-y := -Ifs/ocfs2 |
2 | 2 | ||
3 | ccflags-y += -DCATCH_BH_JBD_RACES | ||
4 | |||
5 | obj-$(CONFIG_OCFS2_FS) += \ | 3 | obj-$(CONFIG_OCFS2_FS) += \ |
6 | ocfs2.o \ | 4 | ocfs2.o \ |
7 | ocfs2_stackglue.o | 5 | ocfs2_stackglue.o |
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index fe50ded1b4ce..498641eed2db 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -139,11 +139,16 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, | |||
139 | 139 | ||
140 | lock_buffer(bh); | 140 | lock_buffer(bh); |
141 | if (buffer_jbd(bh)) { | 141 | if (buffer_jbd(bh)) { |
142 | #ifdef CATCH_BH_JBD_RACES | ||
142 | mlog(ML_ERROR, | 143 | mlog(ML_ERROR, |
143 | "block %llu had the JBD bit set " | 144 | "block %llu had the JBD bit set " |
144 | "while I was in lock_buffer!", | 145 | "while I was in lock_buffer!", |
145 | (unsigned long long)bh->b_blocknr); | 146 | (unsigned long long)bh->b_blocknr); |
146 | BUG(); | 147 | BUG(); |
148 | #else | ||
149 | unlock_buffer(bh); | ||
150 | continue; | ||
151 | #endif | ||
147 | } | 152 | } |
148 | 153 | ||
149 | clear_buffer_uptodate(bh); | 154 | clear_buffer_uptodate(bh); |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 22f0253a3567..c2a6b0894022 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
@@ -405,12 +405,21 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev, | |||
405 | err = ovl_create_upper(dentry, inode, &stat, link, hardlink); | 405 | err = ovl_create_upper(dentry, inode, &stat, link, hardlink); |
406 | } else { | 406 | } else { |
407 | const struct cred *old_cred; | 407 | const struct cred *old_cred; |
408 | struct cred *override_cred; | ||
408 | 409 | ||
409 | old_cred = ovl_override_creds(dentry->d_sb); | 410 | old_cred = ovl_override_creds(dentry->d_sb); |
410 | 411 | ||
411 | err = ovl_create_over_whiteout(dentry, inode, &stat, link, | 412 | err = -ENOMEM; |
412 | hardlink); | 413 | override_cred = prepare_creds(); |
414 | if (override_cred) { | ||
415 | override_cred->fsuid = old_cred->fsuid; | ||
416 | override_cred->fsgid = old_cred->fsgid; | ||
417 | put_cred(override_creds(override_cred)); | ||
418 | put_cred(override_cred); | ||
413 | 419 | ||
420 | err = ovl_create_over_whiteout(dentry, inode, &stat, | ||
421 | link, hardlink); | ||
422 | } | ||
414 | revert_creds(old_cred); | 423 | revert_creds(old_cred); |
415 | } | 424 | } |
416 | 425 | ||
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 0ed7c4012437..1dbeab6cf96e 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -238,41 +238,27 @@ out: | |||
238 | return err; | 238 | return err; |
239 | } | 239 | } |
240 | 240 | ||
241 | static bool ovl_need_xattr_filter(struct dentry *dentry, | ||
242 | enum ovl_path_type type) | ||
243 | { | ||
244 | if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER) | ||
245 | return S_ISDIR(dentry->d_inode->i_mode); | ||
246 | else | ||
247 | return false; | ||
248 | } | ||
249 | |||
250 | ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, | 241 | ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, |
251 | const char *name, void *value, size_t size) | 242 | const char *name, void *value, size_t size) |
252 | { | 243 | { |
253 | struct path realpath; | 244 | struct dentry *realdentry = ovl_dentry_real(dentry); |
254 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
255 | 245 | ||
256 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 246 | if (ovl_is_private_xattr(name)) |
257 | return -ENODATA; | 247 | return -ENODATA; |
258 | 248 | ||
259 | return vfs_getxattr(realpath.dentry, name, value, size); | 249 | return vfs_getxattr(realdentry, name, value, size); |
260 | } | 250 | } |
261 | 251 | ||
262 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) | 252 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) |
263 | { | 253 | { |
264 | struct path realpath; | 254 | struct dentry *realdentry = ovl_dentry_real(dentry); |
265 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
266 | ssize_t res; | 255 | ssize_t res; |
267 | int off; | 256 | int off; |
268 | 257 | ||
269 | res = vfs_listxattr(realpath.dentry, list, size); | 258 | res = vfs_listxattr(realdentry, list, size); |
270 | if (res <= 0 || size == 0) | 259 | if (res <= 0 || size == 0) |
271 | return res; | 260 | return res; |
272 | 261 | ||
273 | if (!ovl_need_xattr_filter(dentry, type)) | ||
274 | return res; | ||
275 | |||
276 | /* filter out private xattrs */ | 262 | /* filter out private xattrs */ |
277 | for (off = 0; off < res;) { | 263 | for (off = 0; off < res;) { |
278 | char *s = list + off; | 264 | char *s = list + off; |
@@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) | |||
302 | goto out; | 288 | goto out; |
303 | 289 | ||
304 | err = -ENODATA; | 290 | err = -ENODATA; |
305 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 291 | if (ovl_is_private_xattr(name)) |
306 | goto out_drop_write; | 292 | goto out_drop_write; |
307 | 293 | ||
308 | if (!OVL_TYPE_UPPER(type)) { | 294 | if (!OVL_TYPE_UPPER(type)) { |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 8a4a266beff3..edc452c2a563 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -820,39 +820,43 @@ posix_acl_xattr_get(const struct xattr_handler *handler, | |||
820 | return error; | 820 | return error; |
821 | } | 821 | } |
822 | 822 | ||
823 | static int | 823 | int |
824 | posix_acl_xattr_set(const struct xattr_handler *handler, | 824 | set_posix_acl(struct inode *inode, int type, struct posix_acl *acl) |
825 | struct dentry *unused, struct inode *inode, | ||
826 | const char *name, const void *value, | ||
827 | size_t size, int flags) | ||
828 | { | 825 | { |
829 | struct posix_acl *acl = NULL; | ||
830 | int ret; | ||
831 | |||
832 | if (!IS_POSIXACL(inode)) | 826 | if (!IS_POSIXACL(inode)) |
833 | return -EOPNOTSUPP; | 827 | return -EOPNOTSUPP; |
834 | if (!inode->i_op->set_acl) | 828 | if (!inode->i_op->set_acl) |
835 | return -EOPNOTSUPP; | 829 | return -EOPNOTSUPP; |
836 | 830 | ||
837 | if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) | 831 | if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) |
838 | return value ? -EACCES : 0; | 832 | return acl ? -EACCES : 0; |
839 | if (!inode_owner_or_capable(inode)) | 833 | if (!inode_owner_or_capable(inode)) |
840 | return -EPERM; | 834 | return -EPERM; |
841 | 835 | ||
836 | if (acl) { | ||
837 | int ret = posix_acl_valid(acl); | ||
838 | if (ret) | ||
839 | return ret; | ||
840 | } | ||
841 | return inode->i_op->set_acl(inode, acl, type); | ||
842 | } | ||
843 | EXPORT_SYMBOL(set_posix_acl); | ||
844 | |||
845 | static int | ||
846 | posix_acl_xattr_set(const struct xattr_handler *handler, | ||
847 | struct dentry *unused, struct inode *inode, | ||
848 | const char *name, const void *value, | ||
849 | size_t size, int flags) | ||
850 | { | ||
851 | struct posix_acl *acl = NULL; | ||
852 | int ret; | ||
853 | |||
842 | if (value) { | 854 | if (value) { |
843 | acl = posix_acl_from_xattr(&init_user_ns, value, size); | 855 | acl = posix_acl_from_xattr(&init_user_ns, value, size); |
844 | if (IS_ERR(acl)) | 856 | if (IS_ERR(acl)) |
845 | return PTR_ERR(acl); | 857 | return PTR_ERR(acl); |
846 | |||
847 | if (acl) { | ||
848 | ret = posix_acl_valid(acl); | ||
849 | if (ret) | ||
850 | goto out; | ||
851 | } | ||
852 | } | 858 | } |
853 | 859 | ret = set_posix_acl(inode, handler->flags, acl); | |
854 | ret = inode->i_op->set_acl(inode, acl, handler->flags); | ||
855 | out: | ||
856 | posix_acl_release(acl); | 860 | posix_acl_release(acl); |
857 | return ret; | 861 | return ret; |
858 | } | 862 | } |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 55bc7d6c8aac..06702783bf40 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -121,6 +121,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, | |||
121 | if (IS_ERR(sb)) | 121 | if (IS_ERR(sb)) |
122 | return ERR_CAST(sb); | 122 | return ERR_CAST(sb); |
123 | 123 | ||
124 | /* | ||
125 | * procfs isn't actually a stacking filesystem; however, there is | ||
126 | * too much magic going on inside it to permit stacking things on | ||
127 | * top of it | ||
128 | */ | ||
129 | sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH; | ||
130 | |||
124 | if (!proc_parse_options(options, ns)) { | 131 | if (!proc_parse_options(options, ns)) { |
125 | deactivate_locked_super(sb); | 132 | deactivate_locked_super(sb); |
126 | return ERR_PTR(-EINVAL); | 133 | return ERR_PTR(-EINVAL); |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index b8f2d1e8c645..c72c16c5a60f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1393,7 +1393,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1393 | unsigned long safe_mask = 0; | 1393 | unsigned long safe_mask = 0; |
1394 | unsigned int commit_max_age = (unsigned int)-1; | 1394 | unsigned int commit_max_age = (unsigned int)-1; |
1395 | struct reiserfs_journal *journal = SB_JOURNAL(s); | 1395 | struct reiserfs_journal *journal = SB_JOURNAL(s); |
1396 | char *new_opts = kstrdup(arg, GFP_KERNEL); | 1396 | char *new_opts; |
1397 | int err; | 1397 | int err; |
1398 | char *qf_names[REISERFS_MAXQUOTAS]; | 1398 | char *qf_names[REISERFS_MAXQUOTAS]; |
1399 | unsigned int qfmt = 0; | 1399 | unsigned int qfmt = 0; |
@@ -1401,6 +1401,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1401 | int i; | 1401 | int i; |
1402 | #endif | 1402 | #endif |
1403 | 1403 | ||
1404 | new_opts = kstrdup(arg, GFP_KERNEL); | ||
1405 | if (arg && !new_opts) | ||
1406 | return -ENOMEM; | ||
1407 | |||
1404 | sync_filesystem(s); | 1408 | sync_filesystem(s); |
1405 | reiserfs_write_lock(s); | 1409 | reiserfs_write_lock(s); |
1406 | 1410 | ||
@@ -1546,7 +1550,8 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1546 | } | 1550 | } |
1547 | 1551 | ||
1548 | out_ok_unlocked: | 1552 | out_ok_unlocked: |
1549 | replace_mount_options(s, new_opts); | 1553 | if (new_opts) |
1554 | replace_mount_options(s, new_opts); | ||
1550 | return 0; | 1555 | return 0; |
1551 | 1556 | ||
1552 | out_err_unlock: | 1557 | out_err_unlock: |
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 08316972ff93..7bbf420d1289 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "ubifs.h" | 52 | #include "ubifs.h" |
53 | #include <linux/mount.h> | 53 | #include <linux/mount.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/migrate.h> | ||
55 | 56 | ||
56 | static int read_block(struct inode *inode, void *addr, unsigned int block, | 57 | static int read_block(struct inode *inode, void *addr, unsigned int block, |
57 | struct ubifs_data_node *dn) | 58 | struct ubifs_data_node *dn) |
@@ -1452,6 +1453,26 @@ static int ubifs_set_page_dirty(struct page *page) | |||
1452 | return ret; | 1453 | return ret; |
1453 | } | 1454 | } |
1454 | 1455 | ||
1456 | #ifdef CONFIG_MIGRATION | ||
1457 | static int ubifs_migrate_page(struct address_space *mapping, | ||
1458 | struct page *newpage, struct page *page, enum migrate_mode mode) | ||
1459 | { | ||
1460 | int rc; | ||
1461 | |||
1462 | rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0); | ||
1463 | if (rc != MIGRATEPAGE_SUCCESS) | ||
1464 | return rc; | ||
1465 | |||
1466 | if (PagePrivate(page)) { | ||
1467 | ClearPagePrivate(page); | ||
1468 | SetPagePrivate(newpage); | ||
1469 | } | ||
1470 | |||
1471 | migrate_page_copy(newpage, page); | ||
1472 | return MIGRATEPAGE_SUCCESS; | ||
1473 | } | ||
1474 | #endif | ||
1475 | |||
1455 | static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags) | 1476 | static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags) |
1456 | { | 1477 | { |
1457 | /* | 1478 | /* |
@@ -1591,6 +1612,9 @@ const struct address_space_operations ubifs_file_address_operations = { | |||
1591 | .write_end = ubifs_write_end, | 1612 | .write_end = ubifs_write_end, |
1592 | .invalidatepage = ubifs_invalidatepage, | 1613 | .invalidatepage = ubifs_invalidatepage, |
1593 | .set_page_dirty = ubifs_set_page_dirty, | 1614 | .set_page_dirty = ubifs_set_page_dirty, |
1615 | #ifdef CONFIG_MIGRATION | ||
1616 | .migratepage = ubifs_migrate_page, | ||
1617 | #endif | ||
1594 | .releasepage = ubifs_releasepage, | 1618 | .releasepage = ubifs_releasepage, |
1595 | }; | 1619 | }; |
1596 | 1620 | ||
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 5f861ed287c3..888c364b2fe9 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c | |||
@@ -295,7 +295,8 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, | |||
295 | map = &UDF_SB(sb)->s_partmaps[partition]; | 295 | map = &UDF_SB(sb)->s_partmaps[partition]; |
296 | /* map to sparable/physical partition desc */ | 296 | /* map to sparable/physical partition desc */ |
297 | phyblock = udf_get_pblock(sb, eloc.logicalBlockNum, | 297 | phyblock = udf_get_pblock(sb, eloc.logicalBlockNum, |
298 | map->s_partition_num, ext_offset + offset); | 298 | map->s_type_specific.s_metadata.s_phys_partition_ref, |
299 | ext_offset + offset); | ||
299 | } | 300 | } |
300 | 301 | ||
301 | brelse(epos.bh); | 302 | brelse(epos.bh); |
@@ -317,14 +318,18 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block, | |||
317 | mdata = &map->s_type_specific.s_metadata; | 318 | mdata = &map->s_type_specific.s_metadata; |
318 | inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe; | 319 | inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe; |
319 | 320 | ||
320 | /* We shouldn't mount such media... */ | 321 | if (!inode) |
321 | BUG_ON(!inode); | 322 | return 0xFFFFFFFF; |
323 | |||
322 | retblk = udf_try_read_meta(inode, block, partition, offset); | 324 | retblk = udf_try_read_meta(inode, block, partition, offset); |
323 | if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) { | 325 | if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) { |
324 | udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n"); | 326 | udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n"); |
325 | if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { | 327 | if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { |
326 | mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, | 328 | mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, |
327 | mdata->s_mirror_file_loc, map->s_partition_num); | 329 | mdata->s_mirror_file_loc, |
330 | mdata->s_phys_partition_ref); | ||
331 | if (IS_ERR(mdata->s_mirror_fe)) | ||
332 | mdata->s_mirror_fe = NULL; | ||
328 | mdata->s_flags |= MF_MIRROR_FE_LOADED; | 333 | mdata->s_flags |= MF_MIRROR_FE_LOADED; |
329 | } | 334 | } |
330 | 335 | ||
diff --git a/fs/udf/super.c b/fs/udf/super.c index 5e2c8c814e1b..4942549e7dc8 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -951,13 +951,13 @@ out2: | |||
951 | } | 951 | } |
952 | 952 | ||
953 | struct inode *udf_find_metadata_inode_efe(struct super_block *sb, | 953 | struct inode *udf_find_metadata_inode_efe(struct super_block *sb, |
954 | u32 meta_file_loc, u32 partition_num) | 954 | u32 meta_file_loc, u32 partition_ref) |
955 | { | 955 | { |
956 | struct kernel_lb_addr addr; | 956 | struct kernel_lb_addr addr; |
957 | struct inode *metadata_fe; | 957 | struct inode *metadata_fe; |
958 | 958 | ||
959 | addr.logicalBlockNum = meta_file_loc; | 959 | addr.logicalBlockNum = meta_file_loc; |
960 | addr.partitionReferenceNum = partition_num; | 960 | addr.partitionReferenceNum = partition_ref; |
961 | 961 | ||
962 | metadata_fe = udf_iget_special(sb, &addr); | 962 | metadata_fe = udf_iget_special(sb, &addr); |
963 | 963 | ||
@@ -974,7 +974,8 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb, | |||
974 | return metadata_fe; | 974 | return metadata_fe; |
975 | } | 975 | } |
976 | 976 | ||
977 | static int udf_load_metadata_files(struct super_block *sb, int partition) | 977 | static int udf_load_metadata_files(struct super_block *sb, int partition, |
978 | int type1_index) | ||
978 | { | 979 | { |
979 | struct udf_sb_info *sbi = UDF_SB(sb); | 980 | struct udf_sb_info *sbi = UDF_SB(sb); |
980 | struct udf_part_map *map; | 981 | struct udf_part_map *map; |
@@ -984,20 +985,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) | |||
984 | 985 | ||
985 | map = &sbi->s_partmaps[partition]; | 986 | map = &sbi->s_partmaps[partition]; |
986 | mdata = &map->s_type_specific.s_metadata; | 987 | mdata = &map->s_type_specific.s_metadata; |
988 | mdata->s_phys_partition_ref = type1_index; | ||
987 | 989 | ||
988 | /* metadata address */ | 990 | /* metadata address */ |
989 | udf_debug("Metadata file location: block = %d part = %d\n", | 991 | udf_debug("Metadata file location: block = %d part = %d\n", |
990 | mdata->s_meta_file_loc, map->s_partition_num); | 992 | mdata->s_meta_file_loc, mdata->s_phys_partition_ref); |
991 | 993 | ||
992 | fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc, | 994 | fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc, |
993 | map->s_partition_num); | 995 | mdata->s_phys_partition_ref); |
994 | if (IS_ERR(fe)) { | 996 | if (IS_ERR(fe)) { |
995 | /* mirror file entry */ | 997 | /* mirror file entry */ |
996 | udf_debug("Mirror metadata file location: block = %d part = %d\n", | 998 | udf_debug("Mirror metadata file location: block = %d part = %d\n", |
997 | mdata->s_mirror_file_loc, map->s_partition_num); | 999 | mdata->s_mirror_file_loc, mdata->s_phys_partition_ref); |
998 | 1000 | ||
999 | fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc, | 1001 | fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc, |
1000 | map->s_partition_num); | 1002 | mdata->s_phys_partition_ref); |
1001 | 1003 | ||
1002 | if (IS_ERR(fe)) { | 1004 | if (IS_ERR(fe)) { |
1003 | udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n"); | 1005 | udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n"); |
@@ -1015,7 +1017,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) | |||
1015 | */ | 1017 | */ |
1016 | if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) { | 1018 | if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) { |
1017 | addr.logicalBlockNum = mdata->s_bitmap_file_loc; | 1019 | addr.logicalBlockNum = mdata->s_bitmap_file_loc; |
1018 | addr.partitionReferenceNum = map->s_partition_num; | 1020 | addr.partitionReferenceNum = mdata->s_phys_partition_ref; |
1019 | 1021 | ||
1020 | udf_debug("Bitmap file location: block = %d part = %d\n", | 1022 | udf_debug("Bitmap file location: block = %d part = %d\n", |
1021 | addr.logicalBlockNum, addr.partitionReferenceNum); | 1023 | addr.logicalBlockNum, addr.partitionReferenceNum); |
@@ -1283,7 +1285,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) | |||
1283 | p = (struct partitionDesc *)bh->b_data; | 1285 | p = (struct partitionDesc *)bh->b_data; |
1284 | partitionNumber = le16_to_cpu(p->partitionNumber); | 1286 | partitionNumber = le16_to_cpu(p->partitionNumber); |
1285 | 1287 | ||
1286 | /* First scan for TYPE1, SPARABLE and METADATA partitions */ | 1288 | /* First scan for TYPE1 and SPARABLE partitions */ |
1287 | for (i = 0; i < sbi->s_partitions; i++) { | 1289 | for (i = 0; i < sbi->s_partitions; i++) { |
1288 | map = &sbi->s_partmaps[i]; | 1290 | map = &sbi->s_partmaps[i]; |
1289 | udf_debug("Searching map: (%d == %d)\n", | 1291 | udf_debug("Searching map: (%d == %d)\n", |
@@ -1333,7 +1335,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) | |||
1333 | goto out_bh; | 1335 | goto out_bh; |
1334 | 1336 | ||
1335 | if (map->s_partition_type == UDF_METADATA_MAP25) { | 1337 | if (map->s_partition_type == UDF_METADATA_MAP25) { |
1336 | ret = udf_load_metadata_files(sb, i); | 1338 | ret = udf_load_metadata_files(sb, i, type1_idx); |
1337 | if (ret < 0) { | 1339 | if (ret < 0) { |
1338 | udf_err(sb, "error loading MetaData partition map %d\n", | 1340 | udf_err(sb, "error loading MetaData partition map %d\n", |
1339 | i); | 1341 | i); |
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 27b5335730c9..c13875d669c0 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h | |||
@@ -61,6 +61,11 @@ struct udf_meta_data { | |||
61 | __u32 s_bitmap_file_loc; | 61 | __u32 s_bitmap_file_loc; |
62 | __u32 s_alloc_unit_size; | 62 | __u32 s_alloc_unit_size; |
63 | __u16 s_align_unit_size; | 63 | __u16 s_align_unit_size; |
64 | /* | ||
65 | * Partition Reference Number of the associated physical / sparable | ||
66 | * partition | ||
67 | */ | ||
68 | __u16 s_phys_partition_ref; | ||
64 | int s_flags; | 69 | int s_flags; |
65 | struct inode *s_metadata_fe; | 70 | struct inode *s_metadata_fe; |
66 | struct inode *s_mirror_fe; | 71 | struct inode *s_mirror_fe; |