mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
ocfs2: convert w_pages to w_folios
Pass around an array of folios instead of an array of pages. Removes a few calls to compound_head(). Link: https://lkml.kernel.org/r/20241205171653.3179945-10-willy@infradead.org Signed-off-by: Mark Tinguely <mark.tinguely@oracle.com> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> Cc: Changwei Ge <gechangwei@live.cn> Cc: Joel Becker <jlbec@evilplan.org> Cc: Jun Piao <piaojun@huawei.com> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Mark Fasheh <mark@fasheh.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
57ea4b8920
commit
7e119cff9d
2 changed files with 65 additions and 54 deletions
112
fs/ocfs2/aops.c
112
fs/ocfs2/aops.c
|
@ -729,19 +729,19 @@ struct ocfs2_write_ctxt {
|
||||||
unsigned int w_large_pages;
|
unsigned int w_large_pages;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pages involved in this write.
|
* Folios involved in this write.
|
||||||
*
|
*
|
||||||
* w_target_folio is the folio being written to by the user.
|
* w_target_folio is the folio being written to by the user.
|
||||||
*
|
*
|
||||||
* w_pages is an array of pages which always contains
|
* w_folios is an array of folios which always contains
|
||||||
* w_target_folio, and in the case of an allocating write with
|
* w_target_folio, and in the case of an allocating write with
|
||||||
* page_size < cluster size, it will contain zero'd and mapped
|
* page_size < cluster size, it will contain zero'd and mapped
|
||||||
* pages adjacent to w_target_folio which need to be written
|
* pages adjacent to w_target_folio which need to be written
|
||||||
* out in so that future reads from that region will get
|
* out in so that future reads from that region will get
|
||||||
* zero's.
|
* zero's.
|
||||||
*/
|
*/
|
||||||
unsigned int w_num_pages;
|
unsigned int w_num_folios;
|
||||||
struct page *w_pages[OCFS2_MAX_CTXT_PAGES];
|
struct folio *w_folios[OCFS2_MAX_CTXT_PAGES];
|
||||||
struct folio *w_target_folio;
|
struct folio *w_target_folio;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -771,6 +771,19 @@ struct ocfs2_write_ctxt {
|
||||||
unsigned int w_unwritten_count;
|
unsigned int w_unwritten_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ocfs2_unlock_and_free_folios(struct folio **folios, int num_folios)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < num_folios; i++) {
|
||||||
|
if (!folios[i])
|
||||||
|
continue;
|
||||||
|
folio_unlock(folios[i]);
|
||||||
|
folio_mark_accessed(folios[i]);
|
||||||
|
folio_put(folios[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
|
void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -784,7 +797,7 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc)
|
static void ocfs2_unlock_folios(struct ocfs2_write_ctxt *wc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -795,16 +808,16 @@ static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc)
|
||||||
*/
|
*/
|
||||||
if (wc->w_target_locked) {
|
if (wc->w_target_locked) {
|
||||||
BUG_ON(!wc->w_target_folio);
|
BUG_ON(!wc->w_target_folio);
|
||||||
for (i = 0; i < wc->w_num_pages; i++) {
|
for (i = 0; i < wc->w_num_folios; i++) {
|
||||||
if (&wc->w_target_folio->page == wc->w_pages[i]) {
|
if (wc->w_target_folio == wc->w_folios[i]) {
|
||||||
wc->w_pages[i] = NULL;
|
wc->w_folios[i] = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
folio_mark_accessed(wc->w_target_folio);
|
folio_mark_accessed(wc->w_target_folio);
|
||||||
folio_put(wc->w_target_folio);
|
folio_put(wc->w_target_folio);
|
||||||
}
|
}
|
||||||
ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages);
|
ocfs2_unlock_and_free_folios(wc->w_folios, wc->w_num_folios);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocfs2_free_unwritten_list(struct inode *inode,
|
static void ocfs2_free_unwritten_list(struct inode *inode,
|
||||||
|
@ -826,7 +839,7 @@ static void ocfs2_free_write_ctxt(struct inode *inode,
|
||||||
struct ocfs2_write_ctxt *wc)
|
struct ocfs2_write_ctxt *wc)
|
||||||
{
|
{
|
||||||
ocfs2_free_unwritten_list(inode, &wc->w_unwritten_list);
|
ocfs2_free_unwritten_list(inode, &wc->w_unwritten_list);
|
||||||
ocfs2_unlock_pages(wc);
|
ocfs2_unlock_folios(wc);
|
||||||
brelse(wc->w_di_bh);
|
brelse(wc->w_di_bh);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
}
|
}
|
||||||
|
@ -922,8 +935,8 @@ static void ocfs2_write_failure(struct inode *inode,
|
||||||
if (wc->w_target_folio)
|
if (wc->w_target_folio)
|
||||||
ocfs2_zero_new_buffers(wc->w_target_folio, from, to);
|
ocfs2_zero_new_buffers(wc->w_target_folio, from, to);
|
||||||
|
|
||||||
for(i = 0; i < wc->w_num_pages; i++) {
|
for (i = 0; i < wc->w_num_folios; i++) {
|
||||||
tmppage = wc->w_pages[i];
|
tmppage = &wc->w_folios[i]->page;
|
||||||
|
|
||||||
if (tmppage && page_has_buffers(tmppage)) {
|
if (tmppage && page_has_buffers(tmppage)) {
|
||||||
if (ocfs2_should_order_data(inode))
|
if (ocfs2_should_order_data(inode))
|
||||||
|
@ -935,12 +948,11 @@ static void ocfs2_write_failure(struct inode *inode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
|
static int ocfs2_prepare_folio_for_write(struct inode *inode, u64 *p_blkno,
|
||||||
struct ocfs2_write_ctxt *wc,
|
struct ocfs2_write_ctxt *wc, struct folio *folio, u32 cpos,
|
||||||
struct page *page, u32 cpos,
|
loff_t user_pos, unsigned user_len, int new)
|
||||||
loff_t user_pos, unsigned user_len,
|
|
||||||
int new)
|
|
||||||
{
|
{
|
||||||
|
struct page *page = &folio->page;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int map_from = 0, map_to = 0;
|
unsigned int map_from = 0, map_to = 0;
|
||||||
unsigned int cluster_start, cluster_end;
|
unsigned int cluster_start, cluster_end;
|
||||||
|
@ -1019,11 +1031,9 @@ out:
|
||||||
/*
|
/*
|
||||||
* This function will only grab one clusters worth of pages.
|
* This function will only grab one clusters worth of pages.
|
||||||
*/
|
*/
|
||||||
static int ocfs2_grab_pages_for_write(struct address_space *mapping,
|
static int ocfs2_grab_folios_for_write(struct address_space *mapping,
|
||||||
struct ocfs2_write_ctxt *wc,
|
struct ocfs2_write_ctxt *wc, u32 cpos, loff_t user_pos,
|
||||||
u32 cpos, loff_t user_pos,
|
unsigned user_len, int new, struct folio *mmap_folio)
|
||||||
unsigned user_len, int new,
|
|
||||||
struct folio *mmap_folio)
|
|
||||||
{
|
{
|
||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
unsigned long start, target_index, end_index, index;
|
unsigned long start, target_index, end_index, index;
|
||||||
|
@ -1040,7 +1050,7 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
|
||||||
* last page of the write.
|
* last page of the write.
|
||||||
*/
|
*/
|
||||||
if (new) {
|
if (new) {
|
||||||
wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);
|
wc->w_num_folios = ocfs2_pages_per_cluster(inode->i_sb);
|
||||||
start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
|
start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
|
||||||
/*
|
/*
|
||||||
* We need the index *past* the last page we could possibly
|
* We need the index *past* the last page we could possibly
|
||||||
|
@ -1050,15 +1060,15 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
|
||||||
last_byte = max(user_pos + user_len, i_size_read(inode));
|
last_byte = max(user_pos + user_len, i_size_read(inode));
|
||||||
BUG_ON(last_byte < 1);
|
BUG_ON(last_byte < 1);
|
||||||
end_index = ((last_byte - 1) >> PAGE_SHIFT) + 1;
|
end_index = ((last_byte - 1) >> PAGE_SHIFT) + 1;
|
||||||
if ((start + wc->w_num_pages) > end_index)
|
if ((start + wc->w_num_folios) > end_index)
|
||||||
wc->w_num_pages = end_index - start;
|
wc->w_num_folios = end_index - start;
|
||||||
} else {
|
} else {
|
||||||
wc->w_num_pages = 1;
|
wc->w_num_folios = 1;
|
||||||
start = target_index;
|
start = target_index;
|
||||||
}
|
}
|
||||||
end_index = (user_pos + user_len - 1) >> PAGE_SHIFT;
|
end_index = (user_pos + user_len - 1) >> PAGE_SHIFT;
|
||||||
|
|
||||||
for(i = 0; i < wc->w_num_pages; i++) {
|
for(i = 0; i < wc->w_num_folios; i++) {
|
||||||
index = start + i;
|
index = start + i;
|
||||||
|
|
||||||
if (index >= target_index && index <= end_index &&
|
if (index >= target_index && index <= end_index &&
|
||||||
|
@ -1079,26 +1089,27 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
|
||||||
}
|
}
|
||||||
|
|
||||||
folio_get(mmap_folio);
|
folio_get(mmap_folio);
|
||||||
wc->w_pages[i] = &mmap_folio->page;
|
wc->w_folios[i] = mmap_folio;
|
||||||
wc->w_target_locked = true;
|
wc->w_target_locked = true;
|
||||||
} else if (index >= target_index && index <= end_index &&
|
} else if (index >= target_index && index <= end_index &&
|
||||||
wc->w_type == OCFS2_WRITE_DIRECT) {
|
wc->w_type == OCFS2_WRITE_DIRECT) {
|
||||||
/* Direct write has no mapping page. */
|
/* Direct write has no mapping page. */
|
||||||
wc->w_pages[i] = NULL;
|
wc->w_folios[i] = NULL;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
wc->w_pages[i] = find_or_create_page(mapping, index,
|
wc->w_folios[i] = __filemap_get_folio(mapping, index,
|
||||||
|
FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
if (!wc->w_pages[i]) {
|
if (IS_ERR(wc->w_folios[i])) {
|
||||||
ret = -ENOMEM;
|
ret = PTR_ERR(wc->w_folios[i]);
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wait_for_stable_page(wc->w_pages[i]);
|
folio_wait_stable(wc->w_folios[i]);
|
||||||
|
|
||||||
if (index == target_index)
|
if (index == target_index)
|
||||||
wc->w_target_folio = page_folio(wc->w_pages[i]);
|
wc->w_target_folio = wc->w_folios[i];
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1182,18 +1193,17 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||||
if (!should_zero)
|
if (!should_zero)
|
||||||
p_blkno += (user_pos >> inode->i_sb->s_blocksize_bits) & (u64)(bpc - 1);
|
p_blkno += (user_pos >> inode->i_sb->s_blocksize_bits) & (u64)(bpc - 1);
|
||||||
|
|
||||||
for(i = 0; i < wc->w_num_pages; i++) {
|
for (i = 0; i < wc->w_num_folios; i++) {
|
||||||
int tmpret;
|
int tmpret;
|
||||||
|
|
||||||
/* This is the direct io target page. */
|
/* This is the direct io target page. */
|
||||||
if (wc->w_pages[i] == NULL) {
|
if (wc->w_folios[i] == NULL) {
|
||||||
p_blkno += (1 << (PAGE_SHIFT - inode->i_sb->s_blocksize_bits));
|
p_blkno += (1 << (PAGE_SHIFT - inode->i_sb->s_blocksize_bits));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,
|
tmpret = ocfs2_prepare_folio_for_write(inode, &p_blkno, wc,
|
||||||
wc->w_pages[i], cpos,
|
wc->w_folios[i], cpos, user_pos, user_len,
|
||||||
user_pos, user_len,
|
|
||||||
should_zero);
|
should_zero);
|
||||||
if (tmpret) {
|
if (tmpret) {
|
||||||
mlog_errno(tmpret);
|
mlog_errno(tmpret);
|
||||||
|
@ -1493,12 +1503,12 @@ static int ocfs2_write_begin_inline(struct address_space *mapping,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we don't set w_num_pages then this folio won't get unlocked
|
* If we don't set w_num_folios then this folio won't get unlocked
|
||||||
* and freed on cleanup of the write context.
|
* and freed on cleanup of the write context.
|
||||||
*/
|
*/
|
||||||
wc->w_target_folio = folio;
|
wc->w_target_folio = folio;
|
||||||
wc->w_pages[0] = &folio->page;
|
wc->w_folios[0] = folio;
|
||||||
wc->w_num_pages = 1;
|
wc->w_num_folios = 1;
|
||||||
|
|
||||||
ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), wc->w_di_bh,
|
ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), wc->w_di_bh,
|
||||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||||
|
@ -1791,18 +1801,18 @@ try_again:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill our page array first. That way we've grabbed enough so
|
* Fill our folio array first. That way we've grabbed enough so
|
||||||
* that we can zero and flush if we error after adding the
|
* that we can zero and flush if we error after adding the
|
||||||
* extent.
|
* extent.
|
||||||
*/
|
*/
|
||||||
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len,
|
ret = ocfs2_grab_folios_for_write(mapping, wc, wc->w_cpos, pos, len,
|
||||||
cluster_of_pages, mmap_folio);
|
cluster_of_pages, mmap_folio);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/*
|
/*
|
||||||
* ocfs2_grab_pages_for_write() returns -EAGAIN if it could not lock
|
* ocfs2_grab_folios_for_write() returns -EAGAIN if it
|
||||||
* the target page. In this case, we exit with no error and no target
|
* could not lock the target folio. In this case, we exit
|
||||||
* page. This will trigger the caller, page_mkwrite(), to re-try
|
* with no error and no target folio. This will trigger
|
||||||
* the operation.
|
* the caller, page_mkwrite(), to re-try the operation.
|
||||||
*/
|
*/
|
||||||
if (type == OCFS2_WRITE_MMAP && ret == -EAGAIN) {
|
if (type == OCFS2_WRITE_MMAP && ret == -EAGAIN) {
|
||||||
BUG_ON(wc->w_target_folio);
|
BUG_ON(wc->w_target_folio);
|
||||||
|
@ -1997,8 +2007,8 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
|
||||||
if (wc->w_target_folio)
|
if (wc->w_target_folio)
|
||||||
flush_dcache_folio(wc->w_target_folio);
|
flush_dcache_folio(wc->w_target_folio);
|
||||||
|
|
||||||
for(i = 0; i < wc->w_num_pages; i++) {
|
for (i = 0; i < wc->w_num_folios; i++) {
|
||||||
tmppage = wc->w_pages[i];
|
tmppage = &wc->w_folios[i]->page;
|
||||||
|
|
||||||
/* This is the direct io target page. */
|
/* This is the direct io target page. */
|
||||||
if (tmppage == NULL)
|
if (tmppage == NULL)
|
||||||
|
@ -2059,7 +2069,7 @@ out:
|
||||||
* this lock and will ask for the page lock when flushing the data.
|
* this lock and will ask for the page lock when flushing the data.
|
||||||
* put it here to preserve the unlock order.
|
* put it here to preserve the unlock order.
|
||||||
*/
|
*/
|
||||||
ocfs2_unlock_pages(wc);
|
ocfs2_unlock_folios(wc);
|
||||||
|
|
||||||
if (handle)
|
if (handle)
|
||||||
ocfs2_commit_trans(osb, handle);
|
ocfs2_commit_trans(osb, handle);
|
||||||
|
|
|
@ -17,6 +17,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
|
||||||
struct inode *inode, unsigned int from,
|
struct inode *inode, unsigned int from,
|
||||||
unsigned int to, int new);
|
unsigned int to, int new);
|
||||||
|
|
||||||
|
void ocfs2_unlock_and_free_folios(struct folio **folios, int num_folios);
|
||||||
void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages);
|
void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages);
|
||||||
|
|
||||||
int walk_page_buffers( handle_t *handle,
|
int walk_page_buffers( handle_t *handle,
|
||||||
|
|
Loading…
Add table
Reference in a new issue