Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165892
b: refs/heads/master
c: 8b62b72
h: refs/heads/master
v: v3
  • Loading branch information
Chris Mason committed Sep 11, 2009
1 parent c11457d commit 454de96
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 56 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: 9655d2982b53fdb38a9e0f2f11315b99b92d66e2
refs/heads/master: 8b62b72b26bcd72082c4a69d179dd906bcc22200
29 changes: 10 additions & 19 deletions trunk/fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -885,13 +885,6 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
NULL, mask);
}

int set_extent_ordered(struct extent_io_tree *tree, u64 start, u64 end,
gfp_t mask)
{
return set_extent_bit(tree, start, end, EXTENT_ORDERED, 0, NULL, NULL,
mask);
}

int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
int bits, gfp_t mask)
{
Expand Down Expand Up @@ -921,13 +914,6 @@ int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
NULL, mask);
}

int clear_extent_ordered(struct extent_io_tree *tree, u64 start, u64 end,
gfp_t mask)
{
return clear_extent_bit(tree, start, end, EXTENT_ORDERED, 1, 0,
NULL, mask);
}

int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end,
gfp_t mask)
{
Expand Down Expand Up @@ -1373,7 +1359,8 @@ int extent_clear_unlock_delalloc(struct inode *inode,
int clear_unlock,
int clear_delalloc, int clear_dirty,
int set_writeback,
int end_writeback)
int end_writeback,
int set_private2)
{
int ret;
struct page *pages[16];
Expand All @@ -1392,14 +1379,19 @@ int extent_clear_unlock_delalloc(struct inode *inode,
clear_bits |= EXTENT_DELALLOC;

clear_extent_bit(tree, start, end, clear_bits, 1, 0, NULL, GFP_NOFS);
if (!(unlock_pages || clear_dirty || set_writeback || end_writeback))
if (!(unlock_pages || clear_dirty || set_writeback || end_writeback ||
set_private2))
return 0;

while (nr_pages > 0) {
ret = find_get_pages_contig(inode->i_mapping, index,
min_t(unsigned long,
nr_pages, ARRAY_SIZE(pages)), pages);
for (i = 0; i < ret; i++) {

if (set_private2)
SetPagePrivate2(pages[i]);

if (pages[i] == locked_page) {
page_cache_release(pages[i]);
continue;
Expand Down Expand Up @@ -2792,7 +2784,7 @@ int try_release_extent_state(struct extent_map_tree *map,
int ret = 1;

if (test_range_bit(tree, start, end,
EXTENT_IOBITS | EXTENT_ORDERED, 0, NULL))
EXTENT_IOBITS, 0, NULL))
ret = 0;
else {
if ((mask & GFP_NOFS) == GFP_NOFS)
Expand Down Expand Up @@ -2835,8 +2827,7 @@ int try_release_extent_mapping(struct extent_map_tree *map,
}
if (!test_range_bit(tree, em->start,
extent_map_end(em) - 1,
EXTENT_LOCKED | EXTENT_WRITEBACK |
EXTENT_ORDERED,
EXTENT_LOCKED | EXTENT_WRITEBACK,
0, NULL)) {
remove_extent_mapping(map, em);
/* once for the rb tree */
Expand Down
9 changes: 4 additions & 5 deletions trunk/fs/btrfs/extent_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
#define EXTENT_DEFRAG (1 << 6)
#define EXTENT_DEFRAG_DONE (1 << 7)
#define EXTENT_BUFFER_FILLED (1 << 8)
#define EXTENT_ORDERED (1 << 9)
#define EXTENT_ORDERED_METADATA (1 << 10)
#define EXTENT_BOUNDARY (1 << 11)
#define EXTENT_NODATASUM (1 << 12)
#define EXTENT_BOUNDARY (1 << 9)
#define EXTENT_NODATASUM (1 << 10)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)

/* flags for bio submission */
Expand Down Expand Up @@ -285,5 +283,6 @@ int extent_clear_unlock_delalloc(struct inode *inode,
int clear_unlock,
int clear_delalloc, int clear_dirty,
int set_writeback,
int end_writeback);
int end_writeback,
int set_private2);
#endif
47 changes: 30 additions & 17 deletions trunk/fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ static noinline int compress_file_range(struct inode *inode,
extent_clear_unlock_delalloc(inode,
&BTRFS_I(inode)->io_tree,
start, end, NULL, 1, 0,
0, 1, 1, 1);
0, 1, 1, 1, 0);
ret = 0;
goto free_pages_out;
}
Expand Down Expand Up @@ -641,7 +641,7 @@ static noinline int submit_compressed_extents(struct inode *inode,
async_extent->start,
async_extent->start +
async_extent->ram_size - 1,
NULL, 1, 1, 0, 1, 1, 0);
NULL, 1, 1, 0, 1, 1, 0, 0);

ret = btrfs_submit_compressed_write(inode,
async_extent->start,
Expand Down Expand Up @@ -714,7 +714,7 @@ static noinline int cow_file_range(struct inode *inode,
extent_clear_unlock_delalloc(inode,
&BTRFS_I(inode)->io_tree,
start, end, NULL, 1, 1,
1, 1, 1, 1);
1, 1, 1, 1, 0);
*nr_written = *nr_written +
(end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
*page_started = 1;
Expand Down Expand Up @@ -777,11 +777,14 @@ static noinline int cow_file_range(struct inode *inode,
/* we're not doing compressed IO, don't unlock the first
* page (which the caller expects to stay locked), don't
* clear any dirty bits and don't set any writeback bits
*
* Do set the Private2 bit so we know this page was properly
* setup for writepage
*/
extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
start, start + ram_size - 1,
locked_page, unlock, 1,
1, 0, 0, 0);
1, 0, 0, 0, 1);
disk_num_bytes -= cur_alloc_size;
num_bytes -= cur_alloc_size;
alloc_hint = ins.objectid + ins.offset;
Expand Down Expand Up @@ -1102,7 +1105,7 @@ static noinline int run_delalloc_nocow(struct inode *inode,

extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
cur_offset, cur_offset + num_bytes - 1,
locked_page, 1, 1, 1, 0, 0, 0);
locked_page, 1, 1, 1, 0, 0, 0, 1);
cur_offset = extent_end;
if (cur_offset > end)
break;
Expand Down Expand Up @@ -1375,10 +1378,8 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end, GFP_NOFS);

/* already ordered? We're done */
if (test_range_bit(&BTRFS_I(inode)->io_tree, page_start, page_end,
EXTENT_ORDERED, 0, NULL)) {
if (PagePrivate2(page))
goto out;
}

ordered = btrfs_lookup_ordered_extent(inode, page_start);
if (ordered) {
Expand Down Expand Up @@ -1414,11 +1415,9 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end)
struct inode *inode = page->mapping->host;
struct btrfs_writepage_fixup *fixup;
struct btrfs_root *root = BTRFS_I(inode)->root;
int ret;

ret = test_range_bit(&BTRFS_I(inode)->io_tree, start, end,
EXTENT_ORDERED, 0, NULL);
if (ret)
/* this page is properly in the ordered list */
if (TestClearPagePrivate2(page))
return 0;

if (PageChecked(page))
Expand Down Expand Up @@ -1624,6 +1623,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
struct extent_state *state, int uptodate)
{
ClearPagePrivate2(page);
return btrfs_finish_ordered_io(page->mapping->host, start, end);
}

Expand Down Expand Up @@ -4403,13 +4403,21 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
u64 page_start = page_offset(page);
u64 page_end = page_start + PAGE_CACHE_SIZE - 1;


/*
* we have the page locked, so new writeback can't start,
* and the dirty bit won't be cleared while we are here.
*
* Wait for IO on this page so that we can safely clear
* the PagePrivate2 bit and do ordered accounting
*/
wait_on_page_writeback(page);

tree = &BTRFS_I(page->mapping->host)->io_tree;
if (offset) {
btrfs_releasepage(page, GFP_NOFS);
return;
}

lock_extent(tree, page_start, page_end, GFP_NOFS);
ordered = btrfs_lookup_ordered_extent(page->mapping->host,
page_offset(page));
Expand All @@ -4421,14 +4429,19 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
clear_extent_bit(tree, page_start, page_end,
EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_LOCKED, 1, 0, NULL, GFP_NOFS);
btrfs_finish_ordered_io(page->mapping->host,
page_start, page_end);
/*
* whoever cleared the private bit is responsible
* for the finish_ordered_io
*/
if (TestClearPagePrivate2(page)) {
btrfs_finish_ordered_io(page->mapping->host,
page_start, page_end);
}
btrfs_put_ordered_extent(ordered);
lock_extent(tree, page_start, page_end, GFP_NOFS);
}
clear_extent_bit(tree, page_start, page_end,
EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_ORDERED,
EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC,
1, 1, NULL, GFP_NOFS);
__btrfs_releasepage(page, GFP_NOFS);

Expand Down
29 changes: 15 additions & 14 deletions trunk/fs/btrfs/ordered-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree,
*
* len is the length of the extent
*
* This also sets the EXTENT_ORDERED bit on the range in the inode.
*
* The tree is given a single reference on the ordered extent that was
* inserted.
*/
Expand All @@ -181,6 +179,7 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
entry->start = start;
entry->len = len;
entry->disk_len = disk_len;
entry->bytes_left = len;
entry->inode = inode;
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE)
set_bit(type, &entry->flags);
Expand All @@ -195,9 +194,6 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
&entry->rb_node);
BUG_ON(node);

set_extent_ordered(&BTRFS_I(inode)->io_tree, file_offset,
entry_end(entry) - 1, GFP_NOFS);

spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
list_add_tail(&entry->root_extent_list,
&BTRFS_I(inode)->root->fs_info->ordered_extents);
Expand Down Expand Up @@ -241,13 +237,10 @@ int btrfs_dec_test_ordered_pending(struct inode *inode,
struct btrfs_ordered_inode_tree *tree;
struct rb_node *node;
struct btrfs_ordered_extent *entry;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
int ret;

tree = &BTRFS_I(inode)->ordered_tree;
mutex_lock(&tree->mutex);
clear_extent_ordered(io_tree, file_offset, file_offset + io_size - 1,
GFP_NOFS);
node = tree_search(tree, file_offset);
if (!node) {
ret = 1;
Expand All @@ -260,11 +253,16 @@ int btrfs_dec_test_ordered_pending(struct inode *inode,
goto out;
}

ret = test_range_bit(io_tree, entry->file_offset,
entry->file_offset + entry->len - 1,
EXTENT_ORDERED, 0, NULL);
if (ret == 0)
if (io_size > entry->bytes_left) {
printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n",
(unsigned long long)entry->bytes_left,
(unsigned long long)io_size);
}
entry->bytes_left -= io_size;
if (entry->bytes_left == 0)
ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
else
ret = 1;
out:
mutex_unlock(&tree->mutex);
return ret == 0;
Expand Down Expand Up @@ -476,6 +474,7 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
u64 orig_end;
u64 wait_end;
struct btrfs_ordered_extent *ordered;
int found;

if (start + len < start) {
orig_end = INT_LIMIT(loff_t);
Expand All @@ -502,6 +501,7 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
orig_end >> PAGE_CACHE_SHIFT);

end = orig_end;
found = 0;
while (1) {
ordered = btrfs_lookup_first_ordered_extent(inode, end);
if (!ordered)
Expand All @@ -514,15 +514,16 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
btrfs_put_ordered_extent(ordered);
break;
}
found++;
btrfs_start_ordered_extent(inode, ordered, 1);
end = ordered->file_offset;
btrfs_put_ordered_extent(ordered);
if (end == 0 || end == start)
break;
end--;
}
if (test_range_bit(&BTRFS_I(inode)->io_tree, start, orig_end,
EXTENT_ORDERED | EXTENT_DELALLOC, 0, NULL)) {
if (found || test_range_bit(&BTRFS_I(inode)->io_tree, start, orig_end,
EXTENT_DELALLOC, 0, NULL)) {
schedule_timeout(1);
goto again;
}
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/btrfs/ordered-data.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ struct btrfs_ordered_extent {
/* extent length on disk */
u64 disk_len;

/* number of bytes that still need writing */
u64 bytes_left;

/* flags (described above) */
unsigned long flags;

Expand Down

0 comments on commit 454de96

Please sign in to comment.