Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 128521
b: refs/heads/master
c: 179e29e
h: refs/heads/master
i:
  128519: 6ab19c1
v: v3
  • Loading branch information
Chris Mason committed Sep 25, 2008
1 parent 3da78cf commit bf308b2
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 35ebb934bd7fcc7ca991b155b7980c3c4ff9f1a5
refs/heads/master: 179e29e488cc74f1e9bd67bc45f70b832740e9ec
52 changes: 46 additions & 6 deletions trunk/fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1930,7 +1930,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
int btrfs_truncate_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path,
u32 new_size)
u32 new_size, int from_end)
{
int ret = 0;
int slot;
Expand All @@ -1946,13 +1946,17 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,

slot_orig = path->slots[0];
leaf = path->nodes[0];
slot = path->slots[0];

old_size = btrfs_item_size_nr(leaf, slot);
if (old_size == new_size)
return 0;

nritems = btrfs_header_nritems(leaf);
data_end = leaf_data_end(root, leaf);

slot = path->slots[0];
old_data_start = btrfs_item_offset_nr(leaf, slot);
old_size = btrfs_item_size_nr(leaf, slot); BUG_ON(old_size <= new_size);

size_diff = old_size - new_size;

BUG_ON(slot < 0);
Expand Down Expand Up @@ -1984,9 +1988,45 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
}

/* shift the data */
memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
data_end + size_diff, btrfs_leaf_data(leaf) +
data_end, old_data_start + new_size - data_end);
if (from_end) {
memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
data_end + size_diff, btrfs_leaf_data(leaf) +
data_end, old_data_start + new_size - data_end);
} else {
struct btrfs_disk_key disk_key;
u64 offset;

btrfs_item_key(leaf, &disk_key, slot);

if (btrfs_disk_key_type(&disk_key) == BTRFS_EXTENT_DATA_KEY) {
unsigned long ptr;
struct btrfs_file_extent_item *fi;

fi = btrfs_item_ptr(leaf, slot,
struct btrfs_file_extent_item);
fi = (struct btrfs_file_extent_item *)(
(unsigned long)fi - size_diff);

if (btrfs_file_extent_type(leaf, fi) ==
BTRFS_FILE_EXTENT_INLINE) {
ptr = btrfs_item_ptr_offset(leaf, slot);
memmove_extent_buffer(leaf, ptr,
(unsigned long)fi,
offsetof(struct btrfs_file_extent_item,
disk_bytenr));
}
}

memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
data_end + size_diff, btrfs_leaf_data(leaf) +
data_end, old_data_start - data_end);

offset = btrfs_disk_key_offset(&disk_key);
btrfs_set_disk_key_offset(&disk_key, offset + size_diff);
btrfs_set_item_key(leaf, &disk_key, slot);
if (slot == 0)
fixup_low_keys(trans, root, path, &disk_key, 1);
}

item = btrfs_item_nr(leaf, slot);
btrfs_set_item_size(leaf, item, new_size);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
int btrfs_truncate_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path,
u32 new_size);
u32 new_size, int from_end);
int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_key *key, struct btrfs_path *p, int
ins_len, int cow);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/dir-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
item_len - (ptr + sub_item_len - start));
ret = btrfs_truncate_item(trans, root, path,
item_len - sub_item_len);
item_len - sub_item_len, 1);
}
return 0;
}
Expand Down
11 changes: 8 additions & 3 deletions trunk/fs/btrfs/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,12 @@ int add_extent_mapping(struct extent_map_tree *tree,
if (prev && prev->end + 1 == em->start &&
((em->block_start == EXTENT_MAP_HOLE &&
prev->block_start == EXTENT_MAP_HOLE) ||
(em->block_start == prev->block_end + 1))) {
(em->block_start == EXTENT_MAP_INLINE &&
prev->block_start == EXTENT_MAP_INLINE) ||
(em->block_start == EXTENT_MAP_DELALLOC &&
prev->block_start == EXTENT_MAP_DELALLOC) ||
(em->block_start < EXTENT_MAP_DELALLOC - 1 &&
em->block_start == prev->block_end + 1))) {
em->start = prev->start;
em->block_start = prev->block_start;
rb_erase(&prev->rb_node, &tree->map);
Expand Down Expand Up @@ -1618,13 +1623,13 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page,
u64 extent_offset;
u64 last_byte = i_size_read(inode);
u64 block_start;
u64 iosize;
sector_t sector;
struct extent_map *em;
struct block_device *bdev;
int ret;
int nr = 0;
size_t page_offset = 0;
size_t iosize;
size_t blocksize;
loff_t i_size = i_size_read(inode);
unsigned long end_index = i_size >> PAGE_CACHE_SHIFT;
Expand Down Expand Up @@ -1684,7 +1689,7 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page,
clear_extent_dirty(tree, cur, page_end, GFP_NOFS);
break;
}
em = get_extent(inode, page, page_offset, cur, end, 0);
em = get_extent(inode, page, page_offset, cur, end, 1);
if (IS_ERR(em) || !em) {
SetPageError(page);
break;
Expand Down
1 change: 0 additions & 1 deletion trunk/fs/btrfs/extent_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
* page->private values. Every page that is controlled by the extent
* map has page->private set to one.
*/

#define EXTENT_PAGE_PRIVATE 1
#define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3

Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/file-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
new_item_size = blocks * BTRFS_CRC32_SIZE;
if (new_item_size >= btrfs_item_size_nr(leaf, slot))
return 0;
ret = btrfs_truncate_item(trans, root, path, new_item_size);
ret = btrfs_truncate_item(trans, root, path, new_item_size, 1);
BUG_ON(ret);
return ret;
}
Expand Down
36 changes: 30 additions & 6 deletions trunk/fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,20 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
goto fail;
}
if (ret == 1) {
struct btrfs_key found_key;

if (path->slots[0] == 0)
goto insert;

path->slots[0]--;
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);

if (found_key.objectid != inode->i_ino)
goto insert;

if (found_key.type != BTRFS_EXTENT_DATA_KEY)
goto insert;
ei = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);

Expand Down Expand Up @@ -152,6 +164,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
ret = btrfs_search_slot(trans, root, &key, path,
offset + size - found_end, 1);
BUG_ON(ret != 0);

ret = btrfs_extend_item(trans, root, path,
offset + size - found_end);
if (ret) {
Expand Down Expand Up @@ -292,7 +305,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
*/
inline_size = end_pos;
if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
inline_size > 8192 ||
inline_size > 32768 ||
inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
u64 last_end;

Expand All @@ -312,7 +325,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
aligned_end = (pos + write_bytes + root->sectorsize - 1) &
~((u64)root->sectorsize - 1);
err = btrfs_drop_extents(trans, root, inode, start_pos,
aligned_end, end_pos, &hint_byte);
aligned_end, aligned_end, &hint_byte);
if (err)
goto failed;
err = insert_inline_extent(trans, root, inode, start_pos,
Expand Down Expand Up @@ -456,13 +469,15 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
goto next_slot;
}

/* FIXME, there's only one inline extent allowed right now */
if (found_inline) {
u64 mask = root->sectorsize - 1;
search_start = (extent_end + mask) & ~mask;
} else
search_start = extent_end;

if (end <= extent_end && start >= key.offset && found_inline) {
*hint_byte = EXTENT_MAP_INLINE;
}
if (end < extent_end && end >= key.offset) {
if (found_extent) {
u64 disk_bytenr =
Expand All @@ -479,8 +494,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
BUG_ON(ret);
}
}
if (!found_inline)
bookend = 1;
bookend = 1;
if (found_inline && start <= key.offset &&
inline_end < extent_end)
keep = 1;
}
/* truncate existing extent */
if (start > key.offset) {
Expand Down Expand Up @@ -510,7 +527,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
new_size = btrfs_file_extent_calc_inline_size(
inline_end - key.offset);
btrfs_truncate_item(trans, root, path,
new_size);
new_size, 1);
}
}
/* delete the entire extent */
Expand Down Expand Up @@ -551,6 +568,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
if (!bookend)
continue;
}
if (bookend && found_inline && start <= key.offset &&
inline_end < extent_end) {
u32 new_size;
new_size = btrfs_file_extent_calc_inline_size(
extent_end - inline_end);
btrfs_truncate_item(trans, root, path, new_size, 0);
}
/* create bookend, splitting the extent in two */
if (bookend && found_extent) {
struct btrfs_key ins;
Expand Down
67 changes: 48 additions & 19 deletions trunk/fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
ret = btrfs_drop_extents(trans, root, inode,
start, start + num_bytes, start, &alloc_hint);

if (alloc_hint == EXTENT_MAP_INLINE)
goto out;

ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0,
alloc_hint, (u64)-1, &ins, 1);
if (ret) {
Expand Down Expand Up @@ -558,6 +561,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
u64 item_end = 0;
int found_extent;
int del_item;
int extent_type = -1;

btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1);
path = btrfs_alloc_path();
Expand Down Expand Up @@ -597,18 +601,23 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
if (found_type == BTRFS_EXTENT_DATA_KEY) {
fi = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);
if (btrfs_file_extent_type(leaf, fi) !=
BTRFS_FILE_EXTENT_INLINE) {
extent_type = btrfs_file_extent_type(leaf, fi);
if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
item_end +=
btrfs_file_extent_num_bytes(leaf, fi);
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
struct btrfs_item *item = btrfs_item_nr(leaf,
path->slots[0]);
item_end += btrfs_file_extent_inline_len(leaf,
item);
}
}
if (found_type == BTRFS_CSUM_ITEM_KEY) {
ret = btrfs_csum_truncate(trans, root, path,
inode->i_size);
BUG_ON(ret);
}
if (item_end < inode->i_size) {
if (item_end <= inode->i_size) {
if (found_type == BTRFS_DIR_ITEM_KEY) {
found_type = BTRFS_INODE_ITEM_KEY;
} else if (found_type == BTRFS_EXTENT_ITEM_KEY) {
Expand All @@ -629,9 +638,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
found_extent = 0;

/* FIXME, shrink the extent if the ref count is only 1 */
if (found_type == BTRFS_EXTENT_DATA_KEY &&
btrfs_file_extent_type(leaf, fi) !=
BTRFS_FILE_EXTENT_INLINE) {
if (found_type != BTRFS_EXTENT_DATA_KEY)
goto delete;

if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
u64 num_dec;
extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
if (!del_item) {
Expand Down Expand Up @@ -659,7 +669,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
inode->i_blocks -= num_dec;
}
}
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE &&
!del_item) {
u32 newsize = inode->i_size - found_key.offset;
newsize = btrfs_file_extent_calc_inline_size(newsize);
ret = btrfs_truncate_item(trans, root, path,
newsize, 1);
BUG_ON(ret);
}
delete:
if (del_item) {
ret = btrfs_del_item(trans, root, path);
if (ret)
Expand Down Expand Up @@ -769,7 +787,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
u64 pos = (inode->i_size + mask) & ~mask;
u64 block_end = attr->ia_size | mask;
u64 hole_size;
u64 alloc_hint;
u64 alloc_hint = 0;

if (attr->ia_size <= pos)
goto out;
Expand All @@ -786,8 +804,11 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
pos, pos + hole_size, pos,
&alloc_hint);

err = btrfs_insert_file_extent(trans, root, inode->i_ino,
pos, 0, 0, hole_size);
if (alloc_hint != EXTENT_MAP_INLINE) {
err = btrfs_insert_file_extent(trans, root,
inode->i_ino,
pos, 0, 0, hole_size);
}
btrfs_end_transaction(trans, root);
mutex_unlock(&root->fs_info->fs_mutex);
unlock_extent(em_tree, pos, block_end, GFP_NOFS);
Expand Down Expand Up @@ -1531,8 +1552,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
em->end = EXTENT_MAP_HOLE;
}
em->bdev = inode->i_sb->s_bdev;
ret = btrfs_lookup_file_extent(NULL, root, path,
objectid, start, 0);
ret = btrfs_lookup_file_extent(trans, root, path,
objectid, start, trans != NULL);
if (ret < 0) {
err = ret;
goto out;
Expand Down Expand Up @@ -1627,15 +1648,23 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
((u64)root->sectorsize -1);
map = kmap(page);
ptr = btrfs_file_extent_inline_start(item) + extent_offset;
read_extent_buffer(leaf, map + page_offset, ptr, copy_size);

if (em->start + copy_size <= em->end) {
size = min_t(u64, em->end + 1 - em->start,
PAGE_CACHE_SIZE - page_offset) - copy_size;
memset(map + page_offset + copy_size, 0, size);
if (create == 0 && !PageUptodate(page)) {
read_extent_buffer(leaf, map + page_offset, ptr,
copy_size);
flush_dcache_page(page);
} else if (create && PageUptodate(page)) {
if (!trans) {
kunmap(page);
free_extent_map(em);
em = NULL;
btrfs_release_path(root, path);
trans = btrfs_start_transaction(root, 1);
goto again;
}
write_extent_buffer(leaf, map + page_offset, ptr,
copy_size);
btrfs_mark_buffer_dirty(leaf);
}

flush_dcache_page(page);
kunmap(page);
set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS);
goto insert;
Expand Down

0 comments on commit bf308b2

Please sign in to comment.