#define page_tree i_pages
#define ll_xa_lock_irqsave(lockp, flags) xa_lock_irqsave(lockp, flags)
#define ll_xa_unlock_irqrestore(lockp, flags) xa_unlock_irqrestore(lockp, flags)
+#define ll_xa_lock(lockp) xa_lock(lockp)
+#define ll_xa_unlock(lockp) xa_unlock(lockp)
#else
#define i_pages tree_lock
#define ll_xa_lock_irqsave(lockp, flags) spin_lock_irqsave(lockp, flags)
#define ll_xa_unlock_irqrestore(lockp, flags) spin_unlock_irqrestore(lockp, flags)
+#define ll_xa_lock(lockp) spin_lock(lockp)
+#define ll_xa_unlock(lockp) spin_unlock(lockp)
#endif
#ifndef HAVE_LOCK_PAGE_MEMCG
#ifndef HAVE_ACCOUNT_PAGE_DIRTIED_EXPORT
unsigned int (*vvp_account_page_dirtied)(struct page *page,
struct address_space *mapping);
+
+unsigned int ll_account_page_dirtied(struct page *page,
+ struct address_space *mapping)
+{
+ /* must use __set_page_dirty, which means unlocking and
+ * relocking, which hurts performance.
+ */
+ ll_xa_unlock(&mapping->i_pages);
+ __set_page_dirty(page, mapping, 0);
+ ll_xa_lock(&mapping->i_pages);
+ return 0;
+}
#endif
/**
*/
vvp_account_page_dirtied = (void *)
cfs_kallsyms_lookup_name("account_page_dirtied");
+ if (!vvp_account_page_dirtied)
+ vvp_account_page_dirtied = ll_account_page_dirtied;
#endif
return 0;
}
/*
+ * From kernel v4.19-rc5-248-g9b89a0355144 use XArrary
+ * Prior kernels use radix_tree for tags
+ */
+static inline void ll_page_tag_dirty(struct page *page,
+ struct address_space *mapping)
+{
+#ifndef HAVE_RADIX_TREE_TAG_SET
+ __xa_set_mark(&mapping->i_pages, page_index(page), PAGECACHE_TAG_DIRTY);
+#else
+ radix_tree_tag_set(&mapping->page_tree, page_index(page),
+ PAGECACHE_TAG_DIRTY);
+#endif
+}
+
+/*
* Kernels 4.2 - 4.5 pass memcg argument to account_page_dirtied()
* Kernel v5.2-5678-gac1c3e4 no longer exports account_page_dirtied
*/
#elif defined(HAVE_ACCOUNT_PAGE_DIRTIED_EXPORT)
account_page_dirtied(page, mapping);
#else
- if (vvp_account_page_dirtied)
- vvp_account_page_dirtied(page, mapping);
-#endif
-}
-
-/*
- * From kernel v4.19-rc5-248-g9b89a0355144 use XArrary
- * Prior kernels use radix_tree for tags
- */
-static inline void ll_page_tag_dirty(struct page *page,
- struct address_space *mapping)
-{
-#ifndef HAVE_RADIX_TREE_TAG_SET
- __xa_set_mark(&mapping->i_pages, page_index(page), PAGECACHE_TAG_DIRTY);
-#else
- radix_tree_tag_set(&mapping->page_tree, page_index(page),
- PAGECACHE_TAG_DIRTY);
+ vvp_account_page_dirtied(page, mapping);
#endif
+ ll_page_tag_dirty(page, mapping);
}
/* Taken from kernel set_page_dirty, __set_page_dirty_nobuffers
page, page->mapping, mapping);
WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
ll_account_page_dirtied(page, mapping);
- ll_page_tag_dirty(page, mapping);
dirtied++;
unlock_page_memcg(page);
}