diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 32214fe0f7e3..892b34785ccc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1555,6 +1555,7 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work) | |||
1555 | struct inode *inode; | 1555 | struct inode *inode; |
1556 | u64 page_start; | 1556 | u64 page_start; |
1557 | u64 page_end; | 1557 | u64 page_end; |
1558 | int ret; | ||
1558 | 1559 | ||
1559 | fixup = container_of(work, struct btrfs_writepage_fixup, work); | 1560 | fixup = container_of(work, struct btrfs_writepage_fixup, work); |
1560 | page = fixup->page; | 1561 | page = fixup->page; |
@@ -1582,12 +1583,21 @@ again: | |||
1582 | page_end, &cached_state, GFP_NOFS); | 1583 | page_end, &cached_state, GFP_NOFS); |
1583 | unlock_page(page); | 1584 | unlock_page(page); |
1584 | btrfs_start_ordered_extent(inode, ordered, 1); | 1585 | btrfs_start_ordered_extent(inode, ordered, 1); |
1586 | btrfs_put_ordered_extent(ordered); | ||
1585 | goto again; | 1587 | goto again; |
1586 | } | 1588 | } |
1587 | 1589 | ||
1588 | BUG(); | 1590 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); |
1591 | if (ret) { | ||
1592 | mapping_set_error(page->mapping, ret); | ||
1593 | end_extent_writepage(page, ret, page_start, page_end); | ||
1594 | ClearPageChecked(page); | ||
1595 | goto out; | ||
1596 | } | ||
1597 | |||
1589 | btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state); | 1598 | btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state); |
1590 | ClearPageChecked(page); | 1599 | ClearPageChecked(page); |
1600 | set_page_dirty(page); | ||
1591 | out: | 1601 | out: |
1592 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end, | 1602 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end, |
1593 | &cached_state, GFP_NOFS); | 1603 | &cached_state, GFP_NOFS); |
@@ -1630,7 +1640,7 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end) | |||
1630 | fixup->work.func = btrfs_writepage_fixup_worker; | 1640 | fixup->work.func = btrfs_writepage_fixup_worker; |
1631 | fixup->page = page; | 1641 | fixup->page = page; |
1632 | btrfs_queue_worker(&root->fs_info->fixup_workers, &fixup->work); | 1642 | btrfs_queue_worker(&root->fs_info->fixup_workers, &fixup->work); |
1633 | return -EAGAIN; | 1643 | return -EBUSY; |
1634 | } | 1644 | } |
1635 | 1645 | ||
1636 | static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | 1646 | static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, |
@@ -4575,7 +4585,8 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
4575 | ret = btrfs_insert_dir_item(trans, root, name, name_len, | 4585 | ret = btrfs_insert_dir_item(trans, root, name, name_len, |
4576 | parent_inode, &key, | 4586 | parent_inode, &key, |
4577 | btrfs_inode_type(inode), index); | 4587 | btrfs_inode_type(inode), index); |
4578 | BUG_ON(ret); | 4588 | if (ret) |
4589 | goto fail_dir_item; | ||
4579 | 4590 | ||
4580 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 4591 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
4581 | name_len * 2); | 4592 | name_len * 2); |
@@ -4583,6 +4594,23 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
4583 | ret = btrfs_update_inode(trans, root, parent_inode); | 4594 | ret = btrfs_update_inode(trans, root, parent_inode); |
4584 | } | 4595 | } |
4585 | return ret; | 4596 | return ret; |
4597 | |||
4598 | fail_dir_item: | ||
4599 | if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) { | ||
4600 | u64 local_index; | ||
4601 | int err; | ||
4602 | err = btrfs_del_root_ref(trans, root->fs_info->tree_root, | ||
4603 | key.objectid, root->root_key.objectid, | ||
4604 | parent_ino, &local_index, name, name_len); | ||
4605 | |||
4606 | } else if (add_backref) { | ||
4607 | u64 local_index; | ||
4608 | int err; | ||
4609 | |||
4610 | err = btrfs_del_inode_ref(trans, root, name, name_len, | ||
4611 | ino, parent_ino, &local_index); | ||
4612 | } | ||
4613 | return ret; | ||
4586 | } | 4614 | } |
4587 | 4615 | ||
4588 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | 4616 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, |
@@ -6696,8 +6724,10 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | |||
6696 | int err; | 6724 | int err; |
6697 | u64 index = 0; | 6725 | u64 index = 0; |
6698 | 6726 | ||
6699 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, | 6727 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, |
6700 | new_dirid, S_IFDIR | 0700, &index); | 6728 | new_dirid, new_dirid, |
6729 | S_IFDIR | (~current_umask() & S_IRWXUGO), | ||
6730 | &index); | ||
6701 | if (IS_ERR(inode)) | 6731 | if (IS_ERR(inode)) |
6702 | return PTR_ERR(inode); | 6732 | return PTR_ERR(inode); |
6703 | inode->i_op = &btrfs_dir_inode_operations; | 6733 | inode->i_op = &btrfs_dir_inode_operations; |