]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
afs: Pass page into dirty region helpers to provide THP size
authorDavid Howells <dhowells@redhat.com>
Wed, 28 Oct 2020 14:23:46 +0000 (14:23 +0000)
committerDavid Howells <dhowells@redhat.com>
Fri, 23 Apr 2021 09:17:26 +0000 (10:17 +0100)
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: David Howells <dhowells@redhat.com>
Tested-By: Marc 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/
Link: https://lore.kernel.org/r/161118144921.1232039.11377711180492625929.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/161161040747.2537118.11435394902674511430.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/161340404553.1303470.11414163641767769882.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/161539548385.286939.8864598314493255313.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/161653804285.2770958.3497360004849598038.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/161789087043.6155.16922142208140170528.stgit@warthog.procyon.org.uk/
fs/afs/file.c
fs/afs/internal.h
fs/afs/write.c
include/trace/events/afs.h

index 314f6a9517c79208e0cd007fd50f21a5da34cddd..f1bae0b0a9c0c3574263dadd1d5dbe3e59e115e0 100644 (file)
@@ -514,8 +514,8 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset,
                return;
 
        /* We may need to shorten the dirty region */
-       f = afs_page_dirty_from(priv);
-       t = afs_page_dirty_to(priv);
+       f = afs_page_dirty_from(page, priv);
+       t = afs_page_dirty_to(page, priv);
 
        if (t <= offset || f >= end)
                return; /* Doesn't overlap */
@@ -533,17 +533,17 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset,
        if (f == t)
                goto undirty;
 
-       priv = afs_page_dirty(f, t);
+       priv = afs_page_dirty(page, f, t);
        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;
 
 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);
 full_invalidate:
-       priv = (unsigned long)detach_page_private(page);
-       trace_afs_page_dirty(vnode, tracepoint_string("inval"), page->index, priv);
+       detach_page_private(page);
+       trace_afs_page_dirty(vnode, tracepoint_string("inval"), page);
 }
 
 /*
@@ -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)
 {
        struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
-       unsigned long priv;
 
        _enter("{{%llx:%llu}[%lu],%lx},%x",
               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)
        /* deny if page is being written to the cache and the caller hasn't
         * elected to wait */
        if (PagePrivate(page)) {
-               priv = (unsigned long)detach_page_private(page);
-               trace_afs_page_dirty(vnode, tracepoint_string("rel"),
-                                    page->index, priv);
+               detach_page_private(page);
+               trace_afs_page_dirty(vnode, tracepoint_string("rel"), page);
        }
 
        /* indicate that the page can be released */
index 1627b1872812570da753f85c5fad8059245ad984..fd437d4722b56e3eac6882801868aaa6c1ecddb5 100644 (file)
@@ -875,31 +875,31 @@ struct afs_vnode_cache_aux {
 #define __AFS_PAGE_PRIV_MMAPPED        0x8000UL
 #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;
 }
 
-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;
 
        /* 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;
 
        /* 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;
        to = (to - 1) >> res;
        return (to << __AFS_PAGE_PRIV_SHIFT) | from;
index 901bd2ee2dd0e32c33b9f05709674027c1a1721f..babc84dd97197d11e8100b617a9af5deb4080a36 100644 (file)
@@ -112,15 +112,14 @@ try_again:
        t = f = 0;
        if (PagePrivate(page)) {
                priv = page_private(page);
-               f = afs_page_dirty_from(priv);
-               t = afs_page_dirty_to(priv);
+               f = afs_page_dirty_from(page, priv);
+               t = afs_page_dirty_to(page, priv);
                ASSERTCMP(f, <=, t);
        }
 
        if (f != t) {
                if (PageWriteback(page)) {
-                       trace_afs_page_dirty(vnode, tracepoint_string("alrdy"),
-                                            page->index, priv);
+                       trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), page);
                        goto flush_conflicting_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,
 
        if (PagePrivate(page)) {
                priv = page_private(page);
-               f = afs_page_dirty_from(priv);
-               t = afs_page_dirty_to(priv);
+               f = afs_page_dirty_from(page, priv);
+               t = afs_page_dirty_to(page, priv);
                if (from < f)
                        f = from;
                if (to > t)
                        t = to;
-               priv = afs_page_dirty(f, t);
+               priv = afs_page_dirty(page, f, t);
                set_page_private(page, priv);
-               trace_afs_page_dirty(vnode, tracepoint_string("dirty+"),
-                                    page->index, priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("dirty+"), page);
        } else {
-               priv = afs_page_dirty(from, to);
+               priv = afs_page_dirty(page, from, to);
                attach_page_private(page, (void *)priv);
-               trace_afs_page_dirty(vnode, tracepoint_string("dirty"),
-                                    page->index, priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("dirty"), page);
        }
 
        set_page_dirty(page);
@@ -321,7 +318,6 @@ static void afs_pages_written_back(struct afs_vnode *vnode,
                                   pgoff_t first, pgoff_t last)
 {
        struct pagevec pv;
-       unsigned long priv;
        unsigned count, loop;
 
        _enter("{%llx:%llu},{%lx-%lx}",
@@ -340,9 +336,9 @@ static void afs_pages_written_back(struct afs_vnode *vnode,
                ASSERTCMP(pv.nr, ==, count);
 
                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"),
-                                            pv.pages[loop]->index, priv);
+                                            pv.pages[loop]);
                        end_page_writeback(pv.pages[loop]);
                }
                first += count;
@@ -516,15 +512,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
         */
        start = primary_page->index;
        priv = page_private(primary_page);
-       offset = afs_page_dirty_from(priv);
-       to = afs_page_dirty_to(priv);
-       trace_afs_page_dirty(vnode, tracepoint_string("store"),
-                            primary_page->index, priv);
+       offset = afs_page_dirty_from(primary_page, priv);
+       to = afs_page_dirty_to(primary_page, priv);
+       trace_afs_page_dirty(vnode, tracepoint_string("store"), primary_page);
 
        WARN_ON(offset == to);
        if (offset == to)
-               trace_afs_page_dirty(vnode, tracepoint_string("WARN"),
-                                    primary_page->index, priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("WARN"), primary_page);
 
        if (start >= final_page ||
            (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,
                        }
 
                        priv = page_private(page);
-                       f = afs_page_dirty_from(priv);
-                       t = afs_page_dirty_to(priv);
+                       f = afs_page_dirty_from(page, priv);
+                       t = afs_page_dirty_to(page, priv);
                        if (f != 0 &&
                            !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) {
                                unlock_page(page);
@@ -571,8 +565,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
                        }
                        to = t;
 
-                       trace_afs_page_dirty(vnode, tracepoint_string("store+"),
-                                            page->index, priv);
+                       trace_afs_page_dirty(vnode, tracepoint_string("store+"), page);
 
                        if (!clear_page_dirty_for_io(page))
                                BUG();
@@ -860,14 +853,13 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
         */
        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);
-       trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"),
-                            vmf->page->index, priv);
        if (PagePrivate(vmf->page))
                set_page_private(vmf->page, priv);
        else
                attach_page_private(vmf->page, (void *)priv);
+       trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), vmf->page);
        file_update_time(file);
 
        sb_end_pagefault(inode->i_sb);
@@ -920,17 +912,15 @@ int afs_launder_page(struct page *page)
                f = 0;
                t = PAGE_SIZE;
                if (PagePrivate(page)) {
-                       f = afs_page_dirty_from(priv);
-                       t = afs_page_dirty_to(priv);
+                       f = afs_page_dirty_from(page, priv);
+                       t = afs_page_dirty_to(page, priv);
                }
 
-               trace_afs_page_dirty(vnode, tracepoint_string("launder"),
-                                    page->index, priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("launder"), page);
                ret = afs_store_data(mapping, page->index, page->index, t, f, true);
        }
 
-       priv = (unsigned long)detach_page_private(page);
-       trace_afs_page_dirty(vnode, tracepoint_string("laundered"),
-                            page->index, priv);
+       detach_page_private(page);
+       trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page);
        return ret;
 }
index 4a5cc8c64be3470b3ecf18b6d7aec66233089f07..9203cf6a8c5344f3cbbc16e7b3ddbbbb001d1941 100644 (file)
@@ -969,30 +969,33 @@ TRACE_EVENT(afs_dir_check_failed,
            );
 
 TRACE_EVENT(afs_page_dirty,
-           TP_PROTO(struct afs_vnode *vnode, const char *where,
-                    pgoff_t page, unsigned long priv),
+           TP_PROTO(struct afs_vnode *vnode, const char *where, struct page *page),
 
-           TP_ARGS(vnode, where, page, priv),
+           TP_ARGS(vnode, where, page),
 
            TP_STRUCT__entry(
                    __field(struct afs_vnode *,         vnode           )
                    __field(const char *,               where           )
                    __field(pgoff_t,                    page            )
-                   __field(unsigned long,              priv            )
+                   __field(unsigned long,              from            )
+                   __field(unsigned long,              to              )
                             ),
 
            TP_fast_assign(
                    __entry->vnode = vnode;
                    __entry->where = where;
-                   __entry->page = page;
-                   __entry->priv = priv;
+                   __entry->page = page->index;
+                   __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,
-                     afs_page_dirty_from(__entry->priv),
-                     afs_page_dirty_to(__entry->priv),
-                     afs_is_page_dirty_mmapped(__entry->priv) ? " M" : "")
+                     __entry->from,
+                     __entry->to & ~(1UL << (BITS_PER_LONG - 1)),
+                     __entry->to & (1UL << (BITS_PER_LONG - 1)) ? " M" : "")
            );
 
 TRACE_EVENT(afs_call_state,