diff options
-rw-r--r-- | fs/btrfs/delayed-inode.c | 104 | ||||
-rw-r--r-- | fs/btrfs/delayed-inode.h | 1 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 12 |
3 files changed, 91 insertions, 26 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index f1cbd028f7b3..98c68e658a9b 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -82,19 +82,16 @@ static inline struct btrfs_delayed_root *btrfs_get_delayed_root( | |||
82 | return root->fs_info->delayed_root; | 82 | return root->fs_info->delayed_root; |
83 | } | 83 | } |
84 | 84 | ||
85 | static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( | 85 | static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode) |
86 | struct inode *inode) | ||
87 | { | 86 | { |
88 | struct btrfs_delayed_node *node; | ||
89 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); | 87 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); |
90 | struct btrfs_root *root = btrfs_inode->root; | 88 | struct btrfs_root *root = btrfs_inode->root; |
91 | u64 ino = btrfs_ino(inode); | 89 | u64 ino = btrfs_ino(inode); |
92 | int ret; | 90 | struct btrfs_delayed_node *node; |
93 | 91 | ||
94 | again: | ||
95 | node = ACCESS_ONCE(btrfs_inode->delayed_node); | 92 | node = ACCESS_ONCE(btrfs_inode->delayed_node); |
96 | if (node) { | 93 | if (node) { |
97 | atomic_inc(&node->refs); /* can be accessed */ | 94 | atomic_inc(&node->refs); |
98 | return node; | 95 | return node; |
99 | } | 96 | } |
100 | 97 | ||
@@ -102,8 +99,10 @@ again: | |||
102 | node = radix_tree_lookup(&root->delayed_nodes_tree, ino); | 99 | node = radix_tree_lookup(&root->delayed_nodes_tree, ino); |
103 | if (node) { | 100 | if (node) { |
104 | if (btrfs_inode->delayed_node) { | 101 | if (btrfs_inode->delayed_node) { |
102 | atomic_inc(&node->refs); /* can be accessed */ | ||
103 | BUG_ON(btrfs_inode->delayed_node != node); | ||
105 | spin_unlock(&root->inode_lock); | 104 | spin_unlock(&root->inode_lock); |
106 | goto again; | 105 | return node; |
107 | } | 106 | } |
108 | btrfs_inode->delayed_node = node; | 107 | btrfs_inode->delayed_node = node; |
109 | atomic_inc(&node->refs); /* can be accessed */ | 108 | atomic_inc(&node->refs); /* can be accessed */ |
@@ -113,6 +112,23 @@ again: | |||
113 | } | 112 | } |
114 | spin_unlock(&root->inode_lock); | 113 | spin_unlock(&root->inode_lock); |
115 | 114 | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( | ||
119 | struct inode *inode) | ||
120 | { | ||
121 | struct btrfs_delayed_node *node; | ||
122 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); | ||
123 | struct btrfs_root *root = btrfs_inode->root; | ||
124 | u64 ino = btrfs_ino(inode); | ||
125 | int ret; | ||
126 | |||
127 | again: | ||
128 | node = btrfs_get_delayed_node(inode); | ||
129 | if (node) | ||
130 | return node; | ||
131 | |||
116 | node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS); | 132 | node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS); |
117 | if (!node) | 133 | if (!node) |
118 | return ERR_PTR(-ENOMEM); | 134 | return ERR_PTR(-ENOMEM); |
@@ -548,19 +564,6 @@ struct btrfs_delayed_item *__btrfs_next_delayed_item( | |||
548 | return next; | 564 | return next; |
549 | } | 565 | } |
550 | 566 | ||
551 | static inline struct btrfs_delayed_node *btrfs_get_delayed_node( | ||
552 | struct inode *inode) | ||
553 | { | ||
554 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); | ||
555 | struct btrfs_delayed_node *delayed_node; | ||
556 | |||
557 | delayed_node = btrfs_inode->delayed_node; | ||
558 | if (delayed_node) | ||
559 | atomic_inc(&delayed_node->refs); | ||
560 | |||
561 | return delayed_node; | ||
562 | } | ||
563 | |||
564 | static inline struct btrfs_root *btrfs_get_fs_root(struct btrfs_root *root, | 567 | static inline struct btrfs_root *btrfs_get_fs_root(struct btrfs_root *root, |
565 | u64 root_id) | 568 | u64 root_id) |
566 | { | 569 | { |
@@ -1404,8 +1407,7 @@ end: | |||
1404 | 1407 | ||
1405 | int btrfs_inode_delayed_dir_index_count(struct inode *inode) | 1408 | int btrfs_inode_delayed_dir_index_count(struct inode *inode) |
1406 | { | 1409 | { |
1407 | struct btrfs_delayed_node *delayed_node = BTRFS_I(inode)->delayed_node; | 1410 | struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); |
1408 | int ret = 0; | ||
1409 | 1411 | ||
1410 | if (!delayed_node) | 1412 | if (!delayed_node) |
1411 | return -ENOENT; | 1413 | return -ENOENT; |
@@ -1415,11 +1417,14 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode) | |||
1415 | * a new directory index is added into the delayed node and index_cnt | 1417 | * a new directory index is added into the delayed node and index_cnt |
1416 | * is updated now. So we needn't lock the delayed node. | 1418 | * is updated now. So we needn't lock the delayed node. |
1417 | */ | 1419 | */ |
1418 | if (!delayed_node->index_cnt) | 1420 | if (!delayed_node->index_cnt) { |
1421 | btrfs_release_delayed_node(delayed_node); | ||
1419 | return -EINVAL; | 1422 | return -EINVAL; |
1423 | } | ||
1420 | 1424 | ||
1421 | BTRFS_I(inode)->index_cnt = delayed_node->index_cnt; | 1425 | BTRFS_I(inode)->index_cnt = delayed_node->index_cnt; |
1422 | return ret; | 1426 | btrfs_release_delayed_node(delayed_node); |
1427 | return 0; | ||
1423 | } | 1428 | } |
1424 | 1429 | ||
1425 | void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, | 1430 | void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, |
@@ -1613,6 +1618,57 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, | |||
1613 | inode->i_ctime.tv_nsec); | 1618 | inode->i_ctime.tv_nsec); |
1614 | } | 1619 | } |
1615 | 1620 | ||
1621 | int btrfs_fill_inode(struct inode *inode, u32 *rdev) | ||
1622 | { | ||
1623 | struct btrfs_delayed_node *delayed_node; | ||
1624 | struct btrfs_inode_item *inode_item; | ||
1625 | struct btrfs_timespec *tspec; | ||
1626 | |||
1627 | delayed_node = btrfs_get_delayed_node(inode); | ||
1628 | if (!delayed_node) | ||
1629 | return -ENOENT; | ||
1630 | |||
1631 | mutex_lock(&delayed_node->mutex); | ||
1632 | if (!delayed_node->inode_dirty) { | ||
1633 | mutex_unlock(&delayed_node->mutex); | ||
1634 | btrfs_release_delayed_node(delayed_node); | ||
1635 | return -ENOENT; | ||
1636 | } | ||
1637 | |||
1638 | inode_item = &delayed_node->inode_item; | ||
1639 | |||
1640 | inode->i_uid = btrfs_stack_inode_uid(inode_item); | ||
1641 | inode->i_gid = btrfs_stack_inode_gid(inode_item); | ||
1642 | btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); | ||
1643 | inode->i_mode = btrfs_stack_inode_mode(inode_item); | ||
1644 | inode->i_nlink = btrfs_stack_inode_nlink(inode_item); | ||
1645 | inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item)); | ||
1646 | BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item); | ||
1647 | BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item); | ||
1648 | inode->i_rdev = 0; | ||
1649 | *rdev = btrfs_stack_inode_rdev(inode_item); | ||
1650 | BTRFS_I(inode)->flags = btrfs_stack_inode_flags(inode_item); | ||
1651 | |||
1652 | tspec = btrfs_inode_atime(inode_item); | ||
1653 | inode->i_atime.tv_sec = btrfs_stack_timespec_sec(tspec); | ||
1654 | inode->i_atime.tv_nsec = btrfs_stack_timespec_nsec(tspec); | ||
1655 | |||
1656 | tspec = btrfs_inode_mtime(inode_item); | ||
1657 | inode->i_mtime.tv_sec = btrfs_stack_timespec_sec(tspec); | ||
1658 | inode->i_mtime.tv_nsec = btrfs_stack_timespec_nsec(tspec); | ||
1659 | |||
1660 | tspec = btrfs_inode_ctime(inode_item); | ||
1661 | inode->i_ctime.tv_sec = btrfs_stack_timespec_sec(tspec); | ||
1662 | inode->i_ctime.tv_nsec = btrfs_stack_timespec_nsec(tspec); | ||
1663 | |||
1664 | inode->i_generation = BTRFS_I(inode)->generation; | ||
1665 | BTRFS_I(inode)->index_cnt = (u64)-1; | ||
1666 | |||
1667 | mutex_unlock(&delayed_node->mutex); | ||
1668 | btrfs_release_delayed_node(delayed_node); | ||
1669 | return 0; | ||
1670 | } | ||
1671 | |||
1616 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, | 1672 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, |
1617 | struct btrfs_root *root, struct inode *inode) | 1673 | struct btrfs_root *root, struct inode *inode) |
1618 | { | 1674 | { |
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index d1a6a2915c66..8d27af4bd8b9 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h | |||
@@ -119,6 +119,7 @@ void btrfs_kill_delayed_inode_items(struct inode *inode); | |||
119 | 119 | ||
120 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, | 120 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, |
121 | struct btrfs_root *root, struct inode *inode); | 121 | struct btrfs_root *root, struct inode *inode); |
122 | int btrfs_fill_inode(struct inode *inode, u32 *rdev); | ||
122 | 123 | ||
123 | /* Used for drop dead root */ | 124 | /* Used for drop dead root */ |
124 | void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); | 125 | void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 87f1e0cf26f8..447612d3a16a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2509,6 +2509,11 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
2509 | int maybe_acls; | 2509 | int maybe_acls; |
2510 | u32 rdev; | 2510 | u32 rdev; |
2511 | int ret; | 2511 | int ret; |
2512 | bool filled = false; | ||
2513 | |||
2514 | ret = btrfs_fill_inode(inode, &rdev); | ||
2515 | if (!ret) | ||
2516 | filled = true; | ||
2512 | 2517 | ||
2513 | path = btrfs_alloc_path(); | 2518 | path = btrfs_alloc_path(); |
2514 | BUG_ON(!path); | 2519 | BUG_ON(!path); |
@@ -2520,6 +2525,10 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
2520 | goto make_bad; | 2525 | goto make_bad; |
2521 | 2526 | ||
2522 | leaf = path->nodes[0]; | 2527 | leaf = path->nodes[0]; |
2528 | |||
2529 | if (filled) | ||
2530 | goto cache_acl; | ||
2531 | |||
2523 | inode_item = btrfs_item_ptr(leaf, path->slots[0], | 2532 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
2524 | struct btrfs_inode_item); | 2533 | struct btrfs_inode_item); |
2525 | if (!leaf->map_token) | 2534 | if (!leaf->map_token) |
@@ -2556,7 +2565,7 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
2556 | 2565 | ||
2557 | BTRFS_I(inode)->index_cnt = (u64)-1; | 2566 | BTRFS_I(inode)->index_cnt = (u64)-1; |
2558 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | 2567 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); |
2559 | 2568 | cache_acl: | |
2560 | /* | 2569 | /* |
2561 | * try to precache a NULL acl entry for files that don't have | 2570 | * try to precache a NULL acl entry for files that don't have |
2562 | * any xattrs or acls | 2571 | * any xattrs or acls |
@@ -2572,7 +2581,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
2572 | } | 2581 | } |
2573 | 2582 | ||
2574 | btrfs_free_path(path); | 2583 | btrfs_free_path(path); |
2575 | inode_item = NULL; | ||
2576 | 2584 | ||
2577 | switch (inode->i_mode & S_IFMT) { | 2585 | switch (inode->i_mode & S_IFMT) { |
2578 | case S_IFREG: | 2586 | case S_IFREG: |