提交 67d78a6f 编写于 作者: D David Howells

afs: Pass page into dirty region helpers to provide THP size

Pass a pointer to the page being accessed into the dirty region helpers so
that the size of the page can be determined in case it's a transparent huge
page.

This also required the page to be passed into the afs_page_dirty trace
point - so there's no need to specifically pass in the index or private
data as these can be retrieved directly from the page struct.
Signed-off-by: NDavid Howells <dhowells@redhat.com>
Tested-By: NMarc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-cachefs@redhat.com
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/160588527183.3465195.16107942526481976308.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/161118144921.1232039.11377711180492625929.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/161161040747.2537118.11435394902674511430.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/161340404553.1303470.11414163641767769882.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/161539548385.286939.8864598314493255313.stgit@warthog.procyon.org.uk/ # v4
Link: https://lore.kernel.org/r/161653804285.2770958.3497360004849598038.stgit@warthog.procyon.org.uk/ # v5
Link: https://lore.kernel.org/r/161789087043.6155.16922142208140170528.stgit@warthog.procyon.org.uk/ # v6
上级 03ffae90
...@@ -514,8 +514,8 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset, ...@@ -514,8 +514,8 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset,
return; return;
/* We may need to shorten the dirty region */ /* We may need to shorten the dirty region */
f = afs_page_dirty_from(priv); f = afs_page_dirty_from(page, priv);
t = afs_page_dirty_to(priv); t = afs_page_dirty_to(page, priv);
if (t <= offset || f >= end) if (t <= offset || f >= end)
return; /* Doesn't overlap */ return; /* Doesn't overlap */
...@@ -533,17 +533,17 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset, ...@@ -533,17 +533,17 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset,
if (f == t) if (f == t)
goto undirty; goto undirty;
priv = afs_page_dirty(f, t); priv = afs_page_dirty(page, f, t);
set_page_private(page, priv); set_page_private(page, priv);
trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page->index, priv); trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page);
return; return;
undirty: undirty:
trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page->index, priv); trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page);
clear_page_dirty_for_io(page); clear_page_dirty_for_io(page);
full_invalidate: full_invalidate:
priv = (unsigned long)detach_page_private(page); detach_page_private(page);
trace_afs_page_dirty(vnode, tracepoint_string("inval"), page->index, priv); trace_afs_page_dirty(vnode, tracepoint_string("inval"), page);
} }
/* /*
...@@ -571,7 +571,6 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, ...@@ -571,7 +571,6 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
static int afs_releasepage(struct page *page, gfp_t gfp_flags) static int afs_releasepage(struct page *page, gfp_t gfp_flags)
{ {
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
unsigned long priv;
_enter("{{%llx:%llu}[%lu],%lx},%x", _enter("{{%llx:%llu}[%lu],%lx},%x",
vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
...@@ -580,9 +579,8 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) ...@@ -580,9 +579,8 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
/* deny if page is being written to the cache and the caller hasn't /* deny if page is being written to the cache and the caller hasn't
* elected to wait */ * elected to wait */
if (PagePrivate(page)) { if (PagePrivate(page)) {
priv = (unsigned long)detach_page_private(page); detach_page_private(page);
trace_afs_page_dirty(vnode, tracepoint_string("rel"), trace_afs_page_dirty(vnode, tracepoint_string("rel"), page);
page->index, priv);
} }
/* indicate that the page can be released */ /* indicate that the page can be released */
......
...@@ -875,31 +875,31 @@ struct afs_vnode_cache_aux { ...@@ -875,31 +875,31 @@ struct afs_vnode_cache_aux {
#define __AFS_PAGE_PRIV_MMAPPED 0x8000UL #define __AFS_PAGE_PRIV_MMAPPED 0x8000UL
#endif #endif
static inline unsigned int afs_page_dirty_resolution(void) static inline unsigned int afs_page_dirty_resolution(struct page *page)
{ {
int shift = PAGE_SHIFT - (__AFS_PAGE_PRIV_SHIFT - 1); int shift = thp_order(page) + PAGE_SHIFT - (__AFS_PAGE_PRIV_SHIFT - 1);
return (shift > 0) ? shift : 0; return (shift > 0) ? shift : 0;
} }
static inline size_t afs_page_dirty_from(unsigned long priv) static inline size_t afs_page_dirty_from(struct page *page, unsigned long priv)
{ {
unsigned long x = priv & __AFS_PAGE_PRIV_MASK; unsigned long x = priv & __AFS_PAGE_PRIV_MASK;
/* The lower bound is inclusive */ /* The lower bound is inclusive */
return x << afs_page_dirty_resolution(); return x << afs_page_dirty_resolution(page);
} }
static inline size_t afs_page_dirty_to(unsigned long priv) static inline size_t afs_page_dirty_to(struct page *page, unsigned long priv)
{ {
unsigned long x = (priv >> __AFS_PAGE_PRIV_SHIFT) & __AFS_PAGE_PRIV_MASK; unsigned long x = (priv >> __AFS_PAGE_PRIV_SHIFT) & __AFS_PAGE_PRIV_MASK;
/* The upper bound is immediately beyond the region */ /* The upper bound is immediately beyond the region */
return (x + 1) << afs_page_dirty_resolution(); return (x + 1) << afs_page_dirty_resolution(page);
} }
static inline unsigned long afs_page_dirty(size_t from, size_t to) static inline unsigned long afs_page_dirty(struct page *page, size_t from, size_t to)
{ {
unsigned int res = afs_page_dirty_resolution(); unsigned int res = afs_page_dirty_resolution(page);
from >>= res; from >>= res;
to = (to - 1) >> res; to = (to - 1) >> res;
return (to << __AFS_PAGE_PRIV_SHIFT) | from; return (to << __AFS_PAGE_PRIV_SHIFT) | from;
......
...@@ -112,15 +112,14 @@ int afs_write_begin(struct file *file, struct address_space *mapping, ...@@ -112,15 +112,14 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
t = f = 0; t = f = 0;
if (PagePrivate(page)) { if (PagePrivate(page)) {
priv = page_private(page); priv = page_private(page);
f = afs_page_dirty_from(priv); f = afs_page_dirty_from(page, priv);
t = afs_page_dirty_to(priv); t = afs_page_dirty_to(page, priv);
ASSERTCMP(f, <=, t); ASSERTCMP(f, <=, t);
} }
if (f != t) { if (f != t) {
if (PageWriteback(page)) { if (PageWriteback(page)) {
trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), page);
page->index, priv);
goto flush_conflicting_write; goto flush_conflicting_write;
} }
/* If the file is being filled locally, allow inter-write /* If the file is being filled locally, allow inter-write
...@@ -204,21 +203,19 @@ int afs_write_end(struct file *file, struct address_space *mapping, ...@@ -204,21 +203,19 @@ int afs_write_end(struct file *file, struct address_space *mapping,
if (PagePrivate(page)) { if (PagePrivate(page)) {
priv = page_private(page); priv = page_private(page);
f = afs_page_dirty_from(priv); f = afs_page_dirty_from(page, priv);
t = afs_page_dirty_to(priv); t = afs_page_dirty_to(page, priv);
if (from < f) if (from < f)
f = from; f = from;
if (to > t) if (to > t)
t = to; t = to;
priv = afs_page_dirty(f, t); priv = afs_page_dirty(page, f, t);
set_page_private(page, priv); set_page_private(page, priv);
trace_afs_page_dirty(vnode, tracepoint_string("dirty+"), trace_afs_page_dirty(vnode, tracepoint_string("dirty+"), page);
page->index, priv);
} else { } else {
priv = afs_page_dirty(from, to); priv = afs_page_dirty(page, from, to);
attach_page_private(page, (void *)priv); attach_page_private(page, (void *)priv);
trace_afs_page_dirty(vnode, tracepoint_string("dirty"), trace_afs_page_dirty(vnode, tracepoint_string("dirty"), page);
page->index, priv);
} }
set_page_dirty(page); set_page_dirty(page);
...@@ -321,7 +318,6 @@ static void afs_pages_written_back(struct afs_vnode *vnode, ...@@ -321,7 +318,6 @@ static void afs_pages_written_back(struct afs_vnode *vnode,
pgoff_t first, pgoff_t last) pgoff_t first, pgoff_t last)
{ {
struct pagevec pv; struct pagevec pv;
unsigned long priv;
unsigned count, loop; unsigned count, loop;
_enter("{%llx:%llu},{%lx-%lx}", _enter("{%llx:%llu},{%lx-%lx}",
...@@ -340,9 +336,9 @@ static void afs_pages_written_back(struct afs_vnode *vnode, ...@@ -340,9 +336,9 @@ static void afs_pages_written_back(struct afs_vnode *vnode,
ASSERTCMP(pv.nr, ==, count); ASSERTCMP(pv.nr, ==, count);
for (loop = 0; loop < count; loop++) { for (loop = 0; loop < count; loop++) {
priv = (unsigned long)detach_page_private(pv.pages[loop]); detach_page_private(pv.pages[loop]);
trace_afs_page_dirty(vnode, tracepoint_string("clear"), trace_afs_page_dirty(vnode, tracepoint_string("clear"),
pv.pages[loop]->index, priv); pv.pages[loop]);
end_page_writeback(pv.pages[loop]); end_page_writeback(pv.pages[loop]);
} }
first += count; first += count;
...@@ -516,15 +512,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, ...@@ -516,15 +512,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
*/ */
start = primary_page->index; start = primary_page->index;
priv = page_private(primary_page); priv = page_private(primary_page);
offset = afs_page_dirty_from(priv); offset = afs_page_dirty_from(primary_page, priv);
to = afs_page_dirty_to(priv); to = afs_page_dirty_to(primary_page, priv);
trace_afs_page_dirty(vnode, tracepoint_string("store"), trace_afs_page_dirty(vnode, tracepoint_string("store"), primary_page);
primary_page->index, priv);
WARN_ON(offset == to); WARN_ON(offset == to);
if (offset == to) if (offset == to)
trace_afs_page_dirty(vnode, tracepoint_string("WARN"), trace_afs_page_dirty(vnode, tracepoint_string("WARN"), primary_page);
primary_page->index, priv);
if (start >= final_page || if (start >= final_page ||
(to < PAGE_SIZE && !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags))) (to < PAGE_SIZE && !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)))
...@@ -562,8 +556,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, ...@@ -562,8 +556,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
} }
priv = page_private(page); priv = page_private(page);
f = afs_page_dirty_from(priv); f = afs_page_dirty_from(page, priv);
t = afs_page_dirty_to(priv); t = afs_page_dirty_to(page, priv);
if (f != 0 && if (f != 0 &&
!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) { !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) {
unlock_page(page); unlock_page(page);
...@@ -571,8 +565,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, ...@@ -571,8 +565,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
} }
to = t; to = t;
trace_afs_page_dirty(vnode, tracepoint_string("store+"), trace_afs_page_dirty(vnode, tracepoint_string("store+"), page);
page->index, priv);
if (!clear_page_dirty_for_io(page)) if (!clear_page_dirty_for_io(page))
BUG(); BUG();
...@@ -860,14 +853,13 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) ...@@ -860,14 +853,13 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
*/ */
wait_on_page_writeback(vmf->page); wait_on_page_writeback(vmf->page);
priv = afs_page_dirty(0, PAGE_SIZE); priv = afs_page_dirty(vmf->page, 0, PAGE_SIZE);
priv = afs_page_dirty_mmapped(priv); priv = afs_page_dirty_mmapped(priv);
trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"),
vmf->page->index, priv);
if (PagePrivate(vmf->page)) if (PagePrivate(vmf->page))
set_page_private(vmf->page, priv); set_page_private(vmf->page, priv);
else else
attach_page_private(vmf->page, (void *)priv); attach_page_private(vmf->page, (void *)priv);
trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), vmf->page);
file_update_time(file); file_update_time(file);
sb_end_pagefault(inode->i_sb); sb_end_pagefault(inode->i_sb);
...@@ -920,17 +912,15 @@ int afs_launder_page(struct page *page) ...@@ -920,17 +912,15 @@ int afs_launder_page(struct page *page)
f = 0; f = 0;
t = PAGE_SIZE; t = PAGE_SIZE;
if (PagePrivate(page)) { if (PagePrivate(page)) {
f = afs_page_dirty_from(priv); f = afs_page_dirty_from(page, priv);
t = afs_page_dirty_to(priv); t = afs_page_dirty_to(page, priv);
} }
trace_afs_page_dirty(vnode, tracepoint_string("launder"), trace_afs_page_dirty(vnode, tracepoint_string("launder"), page);
page->index, priv);
ret = afs_store_data(mapping, page->index, page->index, t, f, true); ret = afs_store_data(mapping, page->index, page->index, t, f, true);
} }
priv = (unsigned long)detach_page_private(page); detach_page_private(page);
trace_afs_page_dirty(vnode, tracepoint_string("laundered"), trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page);
page->index, priv);
return ret; return ret;
} }
...@@ -969,30 +969,33 @@ TRACE_EVENT(afs_dir_check_failed, ...@@ -969,30 +969,33 @@ TRACE_EVENT(afs_dir_check_failed,
); );
TRACE_EVENT(afs_page_dirty, TRACE_EVENT(afs_page_dirty,
TP_PROTO(struct afs_vnode *vnode, const char *where, TP_PROTO(struct afs_vnode *vnode, const char *where, struct page *page),
pgoff_t page, unsigned long priv),
TP_ARGS(vnode, where, page, priv), TP_ARGS(vnode, where, page),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(struct afs_vnode *, vnode ) __field(struct afs_vnode *, vnode )
__field(const char *, where ) __field(const char *, where )
__field(pgoff_t, page ) __field(pgoff_t, page )
__field(unsigned long, priv ) __field(unsigned long, from )
__field(unsigned long, to )
), ),
TP_fast_assign( TP_fast_assign(
__entry->vnode = vnode; __entry->vnode = vnode;
__entry->where = where; __entry->where = where;
__entry->page = page; __entry->page = page->index;
__entry->priv = priv; __entry->from = afs_page_dirty_from(page, page->private);
__entry->to = afs_page_dirty_to(page, page->private);
__entry->to |= (afs_is_page_dirty_mmapped(page->private) ?
(1UL << (BITS_PER_LONG - 1)) : 0);
), ),
TP_printk("vn=%p %lx %s %zx-%zx%s", TP_printk("vn=%p %lx %s %lx-%lx%s",
__entry->vnode, __entry->page, __entry->where, __entry->vnode, __entry->page, __entry->where,
afs_page_dirty_from(__entry->priv), __entry->from,
afs_page_dirty_to(__entry->priv), __entry->to & ~(1UL << (BITS_PER_LONG - 1)),
afs_is_page_dirty_mmapped(__entry->priv) ? " M" : "") __entry->to & (1UL << (BITS_PER_LONG - 1)) ? " M" : "")
); );
TRACE_EVENT(afs_call_state, TRACE_EVENT(afs_call_state,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册