aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-29 15:15:18 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:00 -0400
commit9c58309d6cf22471dacbcb6de54d00cef9ca20d4 (patch)
tree9f3ae79d2db86de12c4ee5152b3b491b1f1a88a4 /fs/btrfs
parent85e21bac165b4ba1f6f90431ad6fc658ffcbaf3a (diff)
Btrfs: Add inode item and backref in one insert, reducing cpu usage
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c39
-rw-r--r--fs/btrfs/ctree.h17
-rw-r--r--fs/btrfs/inode.c85
3 files changed, 102 insertions, 39 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 84ad53e06b3a..fb2e2bd506c8 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2332,27 +2332,34 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
2332 * Given a key and some data, insert an item into the tree. 2332 * Given a key and some data, insert an item into the tree.
2333 * This does all the path init required, making room in the tree if needed. 2333 * This does all the path init required, making room in the tree if needed.
2334 */ 2334 */
2335int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, 2335int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
2336 struct btrfs_root *root, 2336 struct btrfs_root *root,
2337 struct btrfs_path *path, 2337 struct btrfs_path *path,
2338 struct btrfs_key *cpu_key, u32 data_size) 2338 struct btrfs_key *cpu_key, u32 *data_size,
2339 int nr)
2339{ 2340{
2340 struct extent_buffer *leaf; 2341 struct extent_buffer *leaf;
2341 struct btrfs_item *item; 2342 struct btrfs_item *item;
2342 int ret = 0; 2343 int ret = 0;
2343 int slot; 2344 int slot;
2344 int slot_orig; 2345 int slot_orig;
2346 int i;
2345 u32 nritems; 2347 u32 nritems;
2348 u32 total_size = 0;
2349 u32 total_data = 0;
2346 unsigned int data_end; 2350 unsigned int data_end;
2347 struct btrfs_disk_key disk_key; 2351 struct btrfs_disk_key disk_key;
2348 2352
2349 btrfs_cpu_key_to_disk(&disk_key, cpu_key); 2353 for (i = 0; i < nr; i++) {
2354 total_data += data_size[i];
2355 }
2350 2356
2351 /* create a root if there isn't one */ 2357 /* create a root if there isn't one */
2352 if (!root->node) 2358 if (!root->node)
2353 BUG(); 2359 BUG();
2354 2360
2355 ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); 2361 total_size = total_data + (nr - 1) * sizeof(struct btrfs_item);
2362 ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1);
2356 if (ret == 0) { 2363 if (ret == 0) {
2357 return -EEXIST; 2364 return -EEXIST;
2358 } 2365 }
@@ -2366,10 +2373,10 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
2366 data_end = leaf_data_end(root, leaf); 2373 data_end = leaf_data_end(root, leaf);
2367 2374
2368 if (btrfs_leaf_free_space(root, leaf) < 2375 if (btrfs_leaf_free_space(root, leaf) <
2369 sizeof(struct btrfs_item) + data_size) { 2376 sizeof(struct btrfs_item) + total_size) {
2370 btrfs_print_leaf(root, leaf); 2377 btrfs_print_leaf(root, leaf);
2371 printk("not enough freespace need %u have %d\n", 2378 printk("not enough freespace need %u have %d\n",
2372 data_size, btrfs_leaf_free_space(root, leaf)); 2379 total_size, btrfs_leaf_free_space(root, leaf));
2373 BUG(); 2380 BUG();
2374 } 2381 }
2375 2382
@@ -2404,7 +2411,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
2404 } 2411 }
2405 2412
2406 ioff = btrfs_item_offset(leaf, item); 2413 ioff = btrfs_item_offset(leaf, item);
2407 btrfs_set_item_offset(leaf, item, ioff - data_size); 2414 btrfs_set_item_offset(leaf, item, ioff - total_data);
2408 } 2415 }
2409 if (leaf->map_token) { 2416 if (leaf->map_token) {
2410 unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); 2417 unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
@@ -2412,23 +2419,27 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
2412 } 2419 }
2413 2420
2414 /* shift the items */ 2421 /* shift the items */
2415 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1), 2422 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
2416 btrfs_item_nr_offset(slot), 2423 btrfs_item_nr_offset(slot),
2417 (nritems - slot) * sizeof(struct btrfs_item)); 2424 (nritems - slot) * sizeof(struct btrfs_item));
2418 2425
2419 /* shift the data */ 2426 /* shift the data */
2420 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + 2427 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
2421 data_end - data_size, btrfs_leaf_data(leaf) + 2428 data_end - total_data, btrfs_leaf_data(leaf) +
2422 data_end, old_data - data_end); 2429 data_end, old_data - data_end);
2423 data_end = old_data; 2430 data_end = old_data;
2424 } 2431 }
2425 2432
2426 /* setup the item for the new data */ 2433 /* setup the item for the new data */
2427 btrfs_set_item_key(leaf, &disk_key, slot); 2434 for (i = 0; i < nr; i++) {
2428 item = btrfs_item_nr(leaf, slot); 2435 btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
2429 btrfs_set_item_offset(leaf, item, data_end - data_size); 2436 btrfs_set_item_key(leaf, &disk_key, slot + i);
2430 btrfs_set_item_size(leaf, item, data_size); 2437 item = btrfs_item_nr(leaf, slot + i);
2431 btrfs_set_header_nritems(leaf, nritems + 1); 2438 btrfs_set_item_offset(leaf, item, data_end - data_size[i]);
2439 data_end -= data_size[i];
2440 btrfs_set_item_size(leaf, item, data_size[i]);
2441 }
2442 btrfs_set_header_nritems(leaf, nritems + nr);
2432 btrfs_mark_buffer_dirty(leaf); 2443 btrfs_mark_buffer_dirty(leaf);
2433 2444
2434 ret = 0; 2445 ret = 0;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 098cf0883150..127c86f795d0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1050,9 +1050,20 @@ static inline int btrfs_del_item(struct btrfs_trans_handle *trans,
1050 1050
1051int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root 1051int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
1052 *root, struct btrfs_key *key, void *data, u32 data_size); 1052 *root, struct btrfs_key *key, void *data, u32 data_size);
1053int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root 1053int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
1054 *root, struct btrfs_path *path, struct btrfs_key 1054 struct btrfs_root *root,
1055 *cpu_key, u32 data_size); 1055 struct btrfs_path *path,
1056 struct btrfs_key *cpu_key, u32 *data_size, int nr);
1057
1058static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
1059 struct btrfs_root *root,
1060 struct btrfs_path *path,
1061 struct btrfs_key *key,
1062 u32 data_size)
1063{
1064 return btrfs_insert_empty_items(trans, root, path, key, &data_size, 1);
1065}
1066
1056int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); 1067int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
1057int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); 1068int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
1058int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); 1069int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 0a2fe51c4127..413b1012de53 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1500,6 +1500,8 @@ void btrfs_dirty_inode(struct inode *inode)
1500 1500
1501static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, 1501static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1502 struct btrfs_root *root, 1502 struct btrfs_root *root,
1503 const char *name, int name_len,
1504 u64 ref_objectid,
1503 u64 objectid, 1505 u64 objectid,
1504 struct btrfs_block_group_cache *group, 1506 struct btrfs_block_group_cache *group,
1505 int mode) 1507 int mode)
@@ -1508,6 +1510,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1508 struct btrfs_inode_item *inode_item; 1510 struct btrfs_inode_item *inode_item;
1509 struct btrfs_key *location; 1511 struct btrfs_key *location;
1510 struct btrfs_path *path; 1512 struct btrfs_path *path;
1513 struct btrfs_inode_ref *ref;
1514 struct btrfs_key key[2];
1515 u32 sizes[2];
1516 unsigned long ptr;
1511 int ret; 1517 int ret;
1512 int owner; 1518 int owner;
1513 1519
@@ -1530,10 +1536,25 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1530 group = btrfs_find_block_group(root, group, 0, 0, owner); 1536 group = btrfs_find_block_group(root, group, 0, 0, owner);
1531 BTRFS_I(inode)->block_group = group; 1537 BTRFS_I(inode)->block_group = group;
1532 BTRFS_I(inode)->flags = 0; 1538 BTRFS_I(inode)->flags = 0;
1533 ret = btrfs_insert_empty_inode(trans, root, path, objectid); 1539
1534 if (ret) 1540 key[0].objectid = objectid;
1541 btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
1542 key[0].offset = 0;
1543
1544 key[1].objectid = objectid;
1545 btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY);
1546 key[1].offset = ref_objectid;
1547
1548 sizes[0] = sizeof(struct btrfs_inode_item);
1549 sizes[1] = name_len + sizeof(*ref);
1550
1551 ret = btrfs_insert_empty_items(trans, root, path, key, sizes, 2);
1552 if (ret != 0)
1535 goto fail; 1553 goto fail;
1536 1554
1555 if (objectid > root->highest_inode)
1556 root->highest_inode = objectid;
1557
1537 inode->i_uid = current->fsuid; 1558 inode->i_uid = current->fsuid;
1538 inode->i_gid = current->fsgid; 1559 inode->i_gid = current->fsgid;
1539 inode->i_mode = mode; 1560 inode->i_mode = mode;
@@ -1543,6 +1564,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1543 inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], 1564 inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
1544 struct btrfs_inode_item); 1565 struct btrfs_inode_item);
1545 fill_inode_item(path->nodes[0], inode_item, inode); 1566 fill_inode_item(path->nodes[0], inode_item, inode);
1567
1568 ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1,
1569 struct btrfs_inode_ref);
1570 btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
1571 ptr = (unsigned long)(ref + 1);
1572 write_extent_buffer(path->nodes[0], name, ptr, name_len);
1573
1546 btrfs_mark_buffer_dirty(path->nodes[0]); 1574 btrfs_mark_buffer_dirty(path->nodes[0]);
1547 btrfs_free_path(path); 1575 btrfs_free_path(path);
1548 1576
@@ -1564,7 +1592,8 @@ static inline u8 btrfs_inode_type(struct inode *inode)
1564} 1592}
1565 1593
1566static int btrfs_add_link(struct btrfs_trans_handle *trans, 1594static int btrfs_add_link(struct btrfs_trans_handle *trans,
1567 struct dentry *dentry, struct inode *inode) 1595 struct dentry *dentry, struct inode *inode,
1596 int add_backref)
1568{ 1597{
1569 int ret; 1598 int ret;
1570 struct btrfs_key key; 1599 struct btrfs_key key;
@@ -1580,11 +1609,13 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
1580 dentry->d_parent->d_inode->i_ino, 1609 dentry->d_parent->d_inode->i_ino,
1581 &key, btrfs_inode_type(inode)); 1610 &key, btrfs_inode_type(inode));
1582 if (ret == 0) { 1611 if (ret == 0) {
1583 ret = btrfs_insert_inode_ref(trans, root, 1612 if (add_backref) {
1584 dentry->d_name.name, 1613 ret = btrfs_insert_inode_ref(trans, root,
1585 dentry->d_name.len, 1614 dentry->d_name.name,
1586 inode->i_ino, 1615 dentry->d_name.len,
1587 dentry->d_parent->d_inode->i_ino); 1616 inode->i_ino,
1617 dentry->d_parent->d_inode->i_ino);
1618 }
1588 parent_inode = dentry->d_parent->d_inode; 1619 parent_inode = dentry->d_parent->d_inode;
1589 parent_inode->i_size += dentry->d_name.len * 2; 1620 parent_inode->i_size += dentry->d_name.len * 2;
1590 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; 1621 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
@@ -1595,9 +1626,10 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
1595} 1626}
1596 1627
1597static int btrfs_add_nondir(struct btrfs_trans_handle *trans, 1628static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
1598 struct dentry *dentry, struct inode *inode) 1629 struct dentry *dentry, struct inode *inode,
1630 int backref)
1599{ 1631{
1600 int err = btrfs_add_link(trans, dentry, inode); 1632 int err = btrfs_add_link(trans, dentry, inode, backref);
1601 if (!err) { 1633 if (!err) {
1602 d_instantiate(dentry, inode); 1634 d_instantiate(dentry, inode);
1603 return 0; 1635 return 0;
@@ -1635,14 +1667,16 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
1635 goto out_unlock; 1667 goto out_unlock;
1636 } 1668 }
1637 1669
1638 inode = btrfs_new_inode(trans, root, objectid, 1670 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
1671 dentry->d_name.len,
1672 dentry->d_parent->d_inode->i_ino, objectid,
1639 BTRFS_I(dir)->block_group, mode); 1673 BTRFS_I(dir)->block_group, mode);
1640 err = PTR_ERR(inode); 1674 err = PTR_ERR(inode);
1641 if (IS_ERR(inode)) 1675 if (IS_ERR(inode))
1642 goto out_unlock; 1676 goto out_unlock;
1643 1677
1644 btrfs_set_trans_block_group(trans, inode); 1678 btrfs_set_trans_block_group(trans, inode);
1645 err = btrfs_add_nondir(trans, dentry, inode); 1679 err = btrfs_add_nondir(trans, dentry, inode, 0);
1646 if (err) 1680 if (err)
1647 drop_inode = 1; 1681 drop_inode = 1;
1648 else { 1682 else {
@@ -1692,14 +1726,16 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
1692 goto out_unlock; 1726 goto out_unlock;
1693 } 1727 }
1694 1728
1695 inode = btrfs_new_inode(trans, root, objectid, 1729 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
1696 BTRFS_I(dir)->block_group, mode); 1730 dentry->d_name.len,
1731 dentry->d_parent->d_inode->i_ino,
1732 objectid, BTRFS_I(dir)->block_group, mode);
1697 err = PTR_ERR(inode); 1733 err = PTR_ERR(inode);
1698 if (IS_ERR(inode)) 1734 if (IS_ERR(inode))
1699 goto out_unlock; 1735 goto out_unlock;
1700 1736
1701 btrfs_set_trans_block_group(trans, inode); 1737 btrfs_set_trans_block_group(trans, inode);
1702 err = btrfs_add_nondir(trans, dentry, inode); 1738 err = btrfs_add_nondir(trans, dentry, inode, 0);
1703 if (err) 1739 if (err)
1704 drop_inode = 1; 1740 drop_inode = 1;
1705 else { 1741 else {
@@ -1755,7 +1791,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
1755 1791
1756 btrfs_set_trans_block_group(trans, dir); 1792 btrfs_set_trans_block_group(trans, dir);
1757 atomic_inc(&inode->i_count); 1793 atomic_inc(&inode->i_count);
1758 err = btrfs_add_nondir(trans, dentry, inode); 1794 err = btrfs_add_nondir(trans, dentry, inode, 1);
1759 1795
1760 if (err) 1796 if (err)
1761 drop_inode = 1; 1797 drop_inode = 1;
@@ -1810,7 +1846,9 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1810 goto out_unlock; 1846 goto out_unlock;
1811 } 1847 }
1812 1848
1813 inode = btrfs_new_inode(trans, root, objectid, 1849 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
1850 dentry->d_name.len,
1851 dentry->d_parent->d_inode->i_ino, objectid,
1814 BTRFS_I(dir)->block_group, S_IFDIR | mode); 1852 BTRFS_I(dir)->block_group, S_IFDIR | mode);
1815 if (IS_ERR(inode)) { 1853 if (IS_ERR(inode)) {
1816 err = PTR_ERR(inode); 1854 err = PTR_ERR(inode);
@@ -1827,7 +1865,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1827 if (err) 1865 if (err)
1828 goto out_fail; 1866 goto out_fail;
1829 1867
1830 err = btrfs_add_link(trans, dentry, inode); 1868 err = btrfs_add_link(trans, dentry, inode, 0);
1831 if (err) 1869 if (err)
1832 goto out_fail; 1870 goto out_fail;
1833 1871
@@ -2320,7 +2358,8 @@ static int noinline create_subvol(struct btrfs_root *root, char *name,
2320 trans = btrfs_start_transaction(new_root, 1); 2358 trans = btrfs_start_transaction(new_root, 1);
2321 BUG_ON(!trans); 2359 BUG_ON(!trans);
2322 2360
2323 inode = btrfs_new_inode(trans, new_root, new_dirid, 2361 inode = btrfs_new_inode(trans, new_root, "..", 2, new_dirid,
2362 new_dirid,
2324 BTRFS_I(dir)->block_group, S_IFDIR | 0700); 2363 BTRFS_I(dir)->block_group, S_IFDIR | 0700);
2325 if (IS_ERR(inode)) 2364 if (IS_ERR(inode))
2326 goto fail; 2365 goto fail;
@@ -2817,7 +2856,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
2817 if (ret) 2856 if (ret)
2818 goto out_fail; 2857 goto out_fail;
2819 } 2858 }
2820 ret = btrfs_add_link(trans, new_dentry, old_inode); 2859 ret = btrfs_add_link(trans, new_dentry, old_inode, 1);
2821 if (ret) 2860 if (ret)
2822 goto out_fail; 2861 goto out_fail;
2823 2862
@@ -2865,14 +2904,16 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
2865 goto out_unlock; 2904 goto out_unlock;
2866 } 2905 }
2867 2906
2868 inode = btrfs_new_inode(trans, root, objectid, 2907 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
2908 dentry->d_name.len,
2909 dentry->d_parent->d_inode->i_ino, objectid,
2869 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO); 2910 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO);
2870 err = PTR_ERR(inode); 2911 err = PTR_ERR(inode);
2871 if (IS_ERR(inode)) 2912 if (IS_ERR(inode))
2872 goto out_unlock; 2913 goto out_unlock;
2873 2914
2874 btrfs_set_trans_block_group(trans, inode); 2915 btrfs_set_trans_block_group(trans, inode);
2875 err = btrfs_add_nondir(trans, dentry, inode); 2916 err = btrfs_add_nondir(trans, dentry, inode, 0);
2876 if (err) 2917 if (err)
2877 drop_inode = 1; 2918 drop_inode = 1;
2878 else { 2919 else {