Skip to content

Commit da2c700

Browse files
Liu Bokdave
authored andcommitted
btrfs: teach __process_pages_contig about PAGE_LOCK operation
Signed-off-by: Liu Bo <[email protected]> Reviewed-by: David Sterba <[email protected]> [ changes to the helper separated from the following patch ] Signed-off-by: David Sterba <[email protected]>
1 parent 873695b commit da2c700

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

fs/btrfs/extent_io.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,6 +1554,11 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
15541554
return found;
15551555
}
15561556

1557+
static int __process_pages_contig(struct address_space *mapping,
1558+
struct page *locked_page,
1559+
pgoff_t start_index, pgoff_t end_index,
1560+
unsigned long page_ops, pgoff_t *index_ret);
1561+
15571562
static noinline void __unlock_for_delalloc(struct inode *inode,
15581563
struct page *locked_page,
15591564
u64 start, u64 end)
@@ -1731,31 +1736,47 @@ STATIC u64 find_lock_delalloc_range(struct inode *inode,
17311736
return found;
17321737
}
17331738

1734-
static void __process_pages_contig(struct address_space *mapping,
1735-
struct page *locked_page,
1736-
pgoff_t start_index, pgoff_t end_index,
1737-
unsigned long page_ops)
1739+
static int __process_pages_contig(struct address_space *mapping,
1740+
struct page *locked_page,
1741+
pgoff_t start_index, pgoff_t end_index,
1742+
unsigned long page_ops, pgoff_t *index_ret)
17381743
{
17391744
unsigned long nr_pages = end_index - start_index + 1;
1745+
unsigned long pages_locked = 0;
17401746
pgoff_t index = start_index;
17411747
struct page *pages[16];
17421748
unsigned ret;
1749+
int err = 0;
17431750
int i;
17441751

1752+
if (page_ops & PAGE_LOCK) {
1753+
ASSERT(page_ops == PAGE_LOCK);
1754+
ASSERT(index_ret && *index_ret == start_index);
1755+
}
1756+
17451757
if ((page_ops & PAGE_SET_ERROR) && nr_pages > 0)
17461758
mapping_set_error(mapping, -EIO);
17471759

17481760
while (nr_pages > 0) {
17491761
ret = find_get_pages_contig(mapping, index,
17501762
min_t(unsigned long,
17511763
nr_pages, ARRAY_SIZE(pages)), pages);
1752-
for (i = 0; i < ret; i++) {
1764+
if (ret == 0) {
1765+
/*
1766+
* Only if we're going to lock these pages,
1767+
* can we find nothing at @index.
1768+
*/
1769+
ASSERT(page_ops & PAGE_LOCK);
1770+
return ret;
1771+
}
17531772

1773+
for (i = 0; i < ret; i++) {
17541774
if (page_ops & PAGE_SET_PRIVATE2)
17551775
SetPagePrivate2(pages[i]);
17561776

17571777
if (pages[i] == locked_page) {
17581778
put_page(pages[i]);
1779+
pages_locked++;
17591780
continue;
17601781
}
17611782
if (page_ops & PAGE_CLEAR_DIRTY)
@@ -1768,12 +1789,27 @@ static void __process_pages_contig(struct address_space *mapping,
17681789
end_page_writeback(pages[i]);
17691790
if (page_ops & PAGE_UNLOCK)
17701791
unlock_page(pages[i]);
1792+
if (page_ops & PAGE_LOCK) {
1793+
lock_page(pages[i]);
1794+
if (!PageDirty(pages[i]) ||
1795+
pages[i]->mapping != mapping) {
1796+
unlock_page(pages[i]);
1797+
put_page(pages[i]);
1798+
err = -EAGAIN;
1799+
goto out;
1800+
}
1801+
}
17711802
put_page(pages[i]);
1803+
pages_locked++;
17721804
}
17731805
nr_pages -= ret;
17741806
index += ret;
17751807
cond_resched();
17761808
}
1809+
out:
1810+
if (err && index_ret)
1811+
*index_ret = start_index + pages_locked - 1;
1812+
return err;
17771813
}
17781814

17791815
void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
@@ -1786,7 +1822,7 @@ void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
17861822

17871823
__process_pages_contig(inode->i_mapping, locked_page,
17881824
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
1789-
page_ops);
1825+
page_ops, NULL);
17901826
}
17911827

17921828
/*

fs/btrfs/extent_io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@
4545
#define EXTENT_BUFFER_IN_TREE 10
4646
#define EXTENT_BUFFER_WRITE_ERR 11 /* write IO error */
4747

48-
/* these are flags for extent_clear_unlock_delalloc */
48+
/* these are flags for __process_pages_contig */
4949
#define PAGE_UNLOCK (1 << 0)
5050
#define PAGE_CLEAR_DIRTY (1 << 1)
5151
#define PAGE_SET_WRITEBACK (1 << 2)
5252
#define PAGE_END_WRITEBACK (1 << 3)
5353
#define PAGE_SET_PRIVATE2 (1 << 4)
5454
#define PAGE_SET_ERROR (1 << 5)
55+
#define PAGE_LOCK (1 << 6)
5556

5657
/*
5758
* page->private values. Every page that is controlled by the extent

0 commit comments

Comments
 (0)