fsdax page is used not only when CoW, but also mapread. To make the it
easily understood, use 'share' to indicate that the dax page is shared
by more than one extent. And add helper functions to use it.
Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
---
fs/dax.c | 38 ++++++++++++++++++++++----------------
include/linux/mm_types.h | 5 ++++-
include/linux/page-flags.h | 2 +-
3 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 1c6867810cbd..85b81963ea31 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
for (pfn = dax_to_pfn(entry); \
pfn < dax_end_pfn(entry); pfn++)
-static inline bool dax_mapping_is_cow(struct address_space *mapping)
+static inline bool dax_mapping_is_shared(struct page *page)
{
- return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
+ return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
}
/*
- * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
+ * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
+ * refcount.
*/
-static inline void dax_mapping_set_cow(struct page *page)
+static inline void dax_mapping_set_shared(struct page *page)
{
- if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
+ if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
/*
* Reset the index if the page was already mapped
* regularly before.
*/
if (page->mapping)
- page->index = 1;
- page->mapping = (void *)PAGE_MAPPING_DAX_COW;
+ page->share = 1;
+ page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
}
- page->index++;
+ page->share++;
+}
+
+static inline unsigned long dax_mapping_decrease_shared(struct page *page)
+{
+ return --page->share;
}
/*
- * When it is called in dax_insert_entry(), the cow flag will indicate that
+ * When it is called in dax_insert_entry(), the shared flag will indicate that
* whether this entry is shared by multiple files. If so, set the page->mapping
- * FS_DAX_MAPPING_COW, and use page->index as refcount.
+ * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
*/
static void dax_associate_entry(void *entry, struct address_space *mapping,
- struct vm_area_struct *vma, unsigned long address, bool cow)
+ struct vm_area_struct *vma, unsigned long address, bool shared)
{
unsigned long size = dax_entry_size(entry), pfn, index;
int i = 0;
@@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
for_each_mapped_pfn(entry, pfn) {
struct page *page = pfn_to_page(pfn);
- if (cow) {
- dax_mapping_set_cow(page);
+ if (shared) {
+ dax_mapping_set_shared(page);
} else {
WARN_ON_ONCE(page->mapping);
page->mapping = mapping;
@@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
struct page *page = pfn_to_page(pfn);
WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
- if (dax_mapping_is_cow(page->mapping)) {
- /* keep the CoW flag if this page is still shared */
- if (page->index-- > 0)
+ if (dax_mapping_is_shared(page)) {
+ /* keep the shared flag if this page is still shared */
+ if (dax_mapping_decrease_shared(page) > 0)
continue;
} else
WARN_ON_ONCE(page->mapping && page->mapping != mapping);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 500e536796ca..f46cac3657ad 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -103,7 +103,10 @@ struct page {
};
/* See page-flags.h for PAGE_MAPPING_FLAGS */
struct address_space *mapping;
- pgoff_t index; /* Our offset within mapping. */
+ union {
+ pgoff_t index; /* Our offset within mapping. */
+ unsigned long share; /* share count for fsdax */
+ };
/**
* @private: Mapping-private opaque data.
* Usually used for buffer_heads if PagePrivate.
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 0b0ae5084e60..c8a3aa02278d 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
* Different with flags above, this flag is used only for fsdax mode. It
* indicates that this page->mapping is now under reflink case.
*/
-#define PAGE_MAPPING_DAX_COW 0x1
+#define PAGE_MAPPING_DAX_SHARED 0x1
static __always_inline bool folio_mapping_flags(struct folio *folio)
{
--
2.38.1
On Thu, Dec 01, 2022 at 03:28:51PM +0000, Shiyang Ruan wrote:
> fsdax page is used not only when CoW, but also mapread. To make the it
> easily understood, use 'share' to indicate that the dax page is shared
> by more than one extent. And add helper functions to use it.
>
> Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
>
> Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
> ---
> fs/dax.c | 38 ++++++++++++++++++++++----------------
> include/linux/mm_types.h | 5 ++++-
> include/linux/page-flags.h | 2 +-
> 3 files changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index 1c6867810cbd..85b81963ea31 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
> for (pfn = dax_to_pfn(entry); \
> pfn < dax_end_pfn(entry); pfn++)
>
> -static inline bool dax_mapping_is_cow(struct address_space *mapping)
> +static inline bool dax_mapping_is_shared(struct page *page)
dax_page_is_shared?
> {
> - return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
> + return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
> }
>
> /*
> - * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
> + * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
> + * refcount.
> */
> -static inline void dax_mapping_set_cow(struct page *page)
> +static inline void dax_mapping_set_shared(struct page *page)
It's odd that a function of a struct page still has 'mapping' in the
name.
dax_page_increase_shared?
or perhaps simply
dax_page_bump_sharing and dax_page_drop_sharing?
Otherwise this mechanical change looks pretty straightforward.
--D
> {
> - if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
> + if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
> /*
> * Reset the index if the page was already mapped
> * regularly before.
> */
> if (page->mapping)
> - page->index = 1;
> - page->mapping = (void *)PAGE_MAPPING_DAX_COW;
> + page->share = 1;
> + page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
> }
> - page->index++;
> + page->share++;
> +}
> +
> +static inline unsigned long dax_mapping_decrease_shared(struct page *page)
> +{
> + return --page->share;
> }
>
> /*
> - * When it is called in dax_insert_entry(), the cow flag will indicate that
> + * When it is called in dax_insert_entry(), the shared flag will indicate that
> * whether this entry is shared by multiple files. If so, set the page->mapping
> - * FS_DAX_MAPPING_COW, and use page->index as refcount.
> + * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
> */
> static void dax_associate_entry(void *entry, struct address_space *mapping,
> - struct vm_area_struct *vma, unsigned long address, bool cow)
> + struct vm_area_struct *vma, unsigned long address, bool shared)
> {
> unsigned long size = dax_entry_size(entry), pfn, index;
> int i = 0;
> @@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
> for_each_mapped_pfn(entry, pfn) {
> struct page *page = pfn_to_page(pfn);
>
> - if (cow) {
> - dax_mapping_set_cow(page);
> + if (shared) {
> + dax_mapping_set_shared(page);
> } else {
> WARN_ON_ONCE(page->mapping);
> page->mapping = mapping;
> @@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
> struct page *page = pfn_to_page(pfn);
>
> WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
> - if (dax_mapping_is_cow(page->mapping)) {
> - /* keep the CoW flag if this page is still shared */
> - if (page->index-- > 0)
> + if (dax_mapping_is_shared(page)) {
> + /* keep the shared flag if this page is still shared */
> + if (dax_mapping_decrease_shared(page) > 0)
> continue;
> } else
> WARN_ON_ONCE(page->mapping && page->mapping != mapping);
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 500e536796ca..f46cac3657ad 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -103,7 +103,10 @@ struct page {
> };
> /* See page-flags.h for PAGE_MAPPING_FLAGS */
> struct address_space *mapping;
> - pgoff_t index; /* Our offset within mapping. */
> + union {
> + pgoff_t index; /* Our offset within mapping. */
> + unsigned long share; /* share count for fsdax */
> + };
> /**
> * @private: Mapping-private opaque data.
> * Usually used for buffer_heads if PagePrivate.
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 0b0ae5084e60..c8a3aa02278d 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
> * Different with flags above, this flag is used only for fsdax mode. It
> * indicates that this page->mapping is now under reflink case.
> */
> -#define PAGE_MAPPING_DAX_COW 0x1
> +#define PAGE_MAPPING_DAX_SHARED 0x1
>
> static __always_inline bool folio_mapping_flags(struct folio *folio)
> {
> --
> 2.38.1
>
fsdax page is used not only when CoW, but also mapread. To make the it
easily understood, use 'share' to indicate that the dax page is shared
by more than one extent. And add helper functions to use it.
Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
---
fs/dax.c | 38 ++++++++++++++++++++++----------------
include/linux/mm_types.h | 5 ++++-
include/linux/page-flags.h | 2 +-
3 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 1c6867810cbd..84fadea08705 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
for (pfn = dax_to_pfn(entry); \
pfn < dax_end_pfn(entry); pfn++)
-static inline bool dax_mapping_is_cow(struct address_space *mapping)
+static inline bool dax_page_is_shared(struct page *page)
{
- return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
+ return page->mapping == PAGE_MAPPING_DAX_SHARED;
}
/*
- * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
+ * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
+ * refcount.
*/
-static inline void dax_mapping_set_cow(struct page *page)
+static inline void dax_page_share_get(struct page *page)
{
- if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
+ if (page->mapping != PAGE_MAPPING_DAX_SHARED) {
/*
* Reset the index if the page was already mapped
* regularly before.
*/
if (page->mapping)
- page->index = 1;
- page->mapping = (void *)PAGE_MAPPING_DAX_COW;
+ page->share = 1;
+ page->mapping = PAGE_MAPPING_DAX_SHARED;
}
- page->index++;
+ page->share++;
+}
+
+static inline unsigned long dax_page_share_put(struct page *page)
+{
+ return --page->share;
}
/*
- * When it is called in dax_insert_entry(), the cow flag will indicate that
+ * When it is called in dax_insert_entry(), the shared flag will indicate that
* whether this entry is shared by multiple files. If so, set the page->mapping
- * FS_DAX_MAPPING_COW, and use page->index as refcount.
+ * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
*/
static void dax_associate_entry(void *entry, struct address_space *mapping,
- struct vm_area_struct *vma, unsigned long address, bool cow)
+ struct vm_area_struct *vma, unsigned long address, bool shared)
{
unsigned long size = dax_entry_size(entry), pfn, index;
int i = 0;
@@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
for_each_mapped_pfn(entry, pfn) {
struct page *page = pfn_to_page(pfn);
- if (cow) {
- dax_mapping_set_cow(page);
+ if (shared) {
+ dax_page_share_get(page);
} else {
WARN_ON_ONCE(page->mapping);
page->mapping = mapping;
@@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
struct page *page = pfn_to_page(pfn);
WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
- if (dax_mapping_is_cow(page->mapping)) {
- /* keep the CoW flag if this page is still shared */
- if (page->index-- > 0)
+ if (dax_page_is_shared(page)) {
+ /* keep the shared flag if this page is still shared */
+ if (dax_page_share_put(page) > 0)
continue;
} else
WARN_ON_ONCE(page->mapping && page->mapping != mapping);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 500e536796ca..f46cac3657ad 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -103,7 +103,10 @@ struct page {
};
/* See page-flags.h for PAGE_MAPPING_FLAGS */
struct address_space *mapping;
- pgoff_t index; /* Our offset within mapping. */
+ union {
+ pgoff_t index; /* Our offset within mapping. */
+ unsigned long share; /* share count for fsdax */
+ };
/**
* @private: Mapping-private opaque data.
* Usually used for buffer_heads if PagePrivate.
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 0b0ae5084e60..d8e94f2f704a 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
* Different with flags above, this flag is used only for fsdax mode. It
* indicates that this page->mapping is now under reflink case.
*/
-#define PAGE_MAPPING_DAX_COW 0x1
+#define PAGE_MAPPING_DAX_SHARED ((void *)0x1)
static __always_inline bool folio_mapping_flags(struct folio *folio)
{
--
2.38.1
On Wed, Dec 07, 2022 at 02:49:19AM +0000, Shiyang Ruan wrote:
> fsdax page is used not only when CoW, but also mapread. To make the it
> easily understood, use 'share' to indicate that the dax page is shared
> by more than one extent. And add helper functions to use it.
>
> Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
>
> Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
> Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Looks fine to me,
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
--D
> ---
> fs/dax.c | 38 ++++++++++++++++++++++----------------
> include/linux/mm_types.h | 5 ++++-
> include/linux/page-flags.h | 2 +-
> 3 files changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index 1c6867810cbd..84fadea08705 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
> for (pfn = dax_to_pfn(entry); \
> pfn < dax_end_pfn(entry); pfn++)
>
> -static inline bool dax_mapping_is_cow(struct address_space *mapping)
> +static inline bool dax_page_is_shared(struct page *page)
> {
> - return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
> + return page->mapping == PAGE_MAPPING_DAX_SHARED;
> }
>
> /*
> - * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
> + * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
> + * refcount.
> */
> -static inline void dax_mapping_set_cow(struct page *page)
> +static inline void dax_page_share_get(struct page *page)
> {
> - if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
> + if (page->mapping != PAGE_MAPPING_DAX_SHARED) {
> /*
> * Reset the index if the page was already mapped
> * regularly before.
> */
> if (page->mapping)
> - page->index = 1;
> - page->mapping = (void *)PAGE_MAPPING_DAX_COW;
> + page->share = 1;
> + page->mapping = PAGE_MAPPING_DAX_SHARED;
> }
> - page->index++;
> + page->share++;
> +}
> +
> +static inline unsigned long dax_page_share_put(struct page *page)
> +{
> + return --page->share;
> }
>
> /*
> - * When it is called in dax_insert_entry(), the cow flag will indicate that
> + * When it is called in dax_insert_entry(), the shared flag will indicate that
> * whether this entry is shared by multiple files. If so, set the page->mapping
> - * FS_DAX_MAPPING_COW, and use page->index as refcount.
> + * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
> */
> static void dax_associate_entry(void *entry, struct address_space *mapping,
> - struct vm_area_struct *vma, unsigned long address, bool cow)
> + struct vm_area_struct *vma, unsigned long address, bool shared)
> {
> unsigned long size = dax_entry_size(entry), pfn, index;
> int i = 0;
> @@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
> for_each_mapped_pfn(entry, pfn) {
> struct page *page = pfn_to_page(pfn);
>
> - if (cow) {
> - dax_mapping_set_cow(page);
> + if (shared) {
> + dax_page_share_get(page);
> } else {
> WARN_ON_ONCE(page->mapping);
> page->mapping = mapping;
> @@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
> struct page *page = pfn_to_page(pfn);
>
> WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
> - if (dax_mapping_is_cow(page->mapping)) {
> - /* keep the CoW flag if this page is still shared */
> - if (page->index-- > 0)
> + if (dax_page_is_shared(page)) {
> + /* keep the shared flag if this page is still shared */
> + if (dax_page_share_put(page) > 0)
> continue;
> } else
> WARN_ON_ONCE(page->mapping && page->mapping != mapping);
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 500e536796ca..f46cac3657ad 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -103,7 +103,10 @@ struct page {
> };
> /* See page-flags.h for PAGE_MAPPING_FLAGS */
> struct address_space *mapping;
> - pgoff_t index; /* Our offset within mapping. */
> + union {
> + pgoff_t index; /* Our offset within mapping. */
> + unsigned long share; /* share count for fsdax */
> + };
> /**
> * @private: Mapping-private opaque data.
> * Usually used for buffer_heads if PagePrivate.
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 0b0ae5084e60..d8e94f2f704a 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
> * Different with flags above, this flag is used only for fsdax mode. It
> * indicates that this page->mapping is now under reflink case.
> */
> -#define PAGE_MAPPING_DAX_COW 0x1
> +#define PAGE_MAPPING_DAX_SHARED ((void *)0x1)
>
> static __always_inline bool folio_mapping_flags(struct folio *folio)
> {
> --
> 2.38.1
>
fsdax page is used not only when CoW, but also mapread. To make the it
easily understood, use 'share' to indicate that the dax page is shared
by more than one extent. And add helper functions to use it.
Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
---
fs/dax.c | 38 ++++++++++++++++++++++----------------
include/linux/mm_types.h | 5 ++++-
include/linux/page-flags.h | 2 +-
3 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 1c6867810cbd..edbacb273ab5 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
for (pfn = dax_to_pfn(entry); \
pfn < dax_end_pfn(entry); pfn++)
-static inline bool dax_mapping_is_cow(struct address_space *mapping)
+static inline bool dax_page_is_shared(struct page *page)
{
- return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
+ return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
}
/*
- * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
+ * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
+ * refcount.
*/
-static inline void dax_mapping_set_cow(struct page *page)
+static inline void dax_page_bump_sharing(struct page *page)
{
- if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
+ if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
/*
* Reset the index if the page was already mapped
* regularly before.
*/
if (page->mapping)
- page->index = 1;
- page->mapping = (void *)PAGE_MAPPING_DAX_COW;
+ page->share = 1;
+ page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
}
- page->index++;
+ page->share++;
+}
+
+static inline unsigned long dax_page_drop_sharing(struct page *page)
+{
+ return --page->share;
}
/*
- * When it is called in dax_insert_entry(), the cow flag will indicate that
+ * When it is called in dax_insert_entry(), the shared flag will indicate that
* whether this entry is shared by multiple files. If so, set the page->mapping
- * FS_DAX_MAPPING_COW, and use page->index as refcount.
+ * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
*/
static void dax_associate_entry(void *entry, struct address_space *mapping,
- struct vm_area_struct *vma, unsigned long address, bool cow)
+ struct vm_area_struct *vma, unsigned long address, bool shared)
{
unsigned long size = dax_entry_size(entry), pfn, index;
int i = 0;
@@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
for_each_mapped_pfn(entry, pfn) {
struct page *page = pfn_to_page(pfn);
- if (cow) {
- dax_mapping_set_cow(page);
+ if (shared) {
+ dax_page_bump_sharing(page);
} else {
WARN_ON_ONCE(page->mapping);
page->mapping = mapping;
@@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
struct page *page = pfn_to_page(pfn);
WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
- if (dax_mapping_is_cow(page->mapping)) {
- /* keep the CoW flag if this page is still shared */
- if (page->index-- > 0)
+ if (dax_page_is_shared(page)) {
+ /* keep the shared flag if this page is still shared */
+ if (dax_page_drop_sharing(page) > 0)
continue;
} else
WARN_ON_ONCE(page->mapping && page->mapping != mapping);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 500e536796ca..f46cac3657ad 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -103,7 +103,10 @@ struct page {
};
/* See page-flags.h for PAGE_MAPPING_FLAGS */
struct address_space *mapping;
- pgoff_t index; /* Our offset within mapping. */
+ union {
+ pgoff_t index; /* Our offset within mapping. */
+ unsigned long share; /* share count for fsdax */
+ };
/**
* @private: Mapping-private opaque data.
* Usually used for buffer_heads if PagePrivate.
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 0b0ae5084e60..c8a3aa02278d 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
* Different with flags above, this flag is used only for fsdax mode. It
* indicates that this page->mapping is now under reflink case.
*/
-#define PAGE_MAPPING_DAX_COW 0x1
+#define PAGE_MAPPING_DAX_SHARED 0x1
static __always_inline bool folio_mapping_flags(struct folio *folio)
{
--
2.38.1
Shiyang Ruan wrote:
> fsdax page is used not only when CoW, but also mapread. To make the it
> easily understood, use 'share' to indicate that the dax page is shared
> by more than one extent. And add helper functions to use it.
>
> Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
>
> Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
> ---
> fs/dax.c | 38 ++++++++++++++++++++++----------------
> include/linux/mm_types.h | 5 ++++-
> include/linux/page-flags.h | 2 +-
> 3 files changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index 1c6867810cbd..edbacb273ab5 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
> for (pfn = dax_to_pfn(entry); \
> pfn < dax_end_pfn(entry); pfn++)
>
> -static inline bool dax_mapping_is_cow(struct address_space *mapping)
> +static inline bool dax_page_is_shared(struct page *page)
> {
> - return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
> + return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
> }
>
> /*
> - * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
> + * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
> + * refcount.
> */
> -static inline void dax_mapping_set_cow(struct page *page)
> +static inline void dax_page_bump_sharing(struct page *page)
Similar to page_ref naming I would call this page_share_get() and the
corresponding function page_share_put().
> {
> - if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
> + if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
> /*
> * Reset the index if the page was already mapped
> * regularly before.
> */
> if (page->mapping)
> - page->index = 1;
> - page->mapping = (void *)PAGE_MAPPING_DAX_COW;
> + page->share = 1;
> + page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
Small nit, You could save a cast here by defining
PAGE_MAPPING_DAX_SHARED as "((void *) 1)".
> }
> - page->index++;
> + page->share++;
> +}
> +
> +static inline unsigned long dax_page_drop_sharing(struct page *page)
> +{
> + return --page->share;
> }
>
> /*
> - * When it is called in dax_insert_entry(), the cow flag will indicate that
> + * When it is called in dax_insert_entry(), the shared flag will indicate that
> * whether this entry is shared by multiple files. If so, set the page->mapping
> - * FS_DAX_MAPPING_COW, and use page->index as refcount.
> + * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
> */
> static void dax_associate_entry(void *entry, struct address_space *mapping,
> - struct vm_area_struct *vma, unsigned long address, bool cow)
> + struct vm_area_struct *vma, unsigned long address, bool shared)
> {
> unsigned long size = dax_entry_size(entry), pfn, index;
> int i = 0;
> @@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
> for_each_mapped_pfn(entry, pfn) {
> struct page *page = pfn_to_page(pfn);
>
> - if (cow) {
> - dax_mapping_set_cow(page);
> + if (shared) {
> + dax_page_bump_sharing(page);
> } else {
> WARN_ON_ONCE(page->mapping);
> page->mapping = mapping;
> @@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
> struct page *page = pfn_to_page(pfn);
>
> WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
> - if (dax_mapping_is_cow(page->mapping)) {
> - /* keep the CoW flag if this page is still shared */
> - if (page->index-- > 0)
> + if (dax_page_is_shared(page)) {
> + /* keep the shared flag if this page is still shared */
> + if (dax_page_drop_sharing(page) > 0)
> continue;
I think part of what makes this hard to read is trying to preserve the
same code paths for shared pages and typical pages.
page_share_put() should, in addition to decrementing the share, clear
out page->mapping value.
> } else
> WARN_ON_ONCE(page->mapping && page->mapping != mapping);
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 500e536796ca..f46cac3657ad 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -103,7 +103,10 @@ struct page {
> };
> /* See page-flags.h for PAGE_MAPPING_FLAGS */
> struct address_space *mapping;
> - pgoff_t index; /* Our offset within mapping. */
> + union {
> + pgoff_t index; /* Our offset within mapping. */
> + unsigned long share; /* share count for fsdax */
> + };
> /**
> * @private: Mapping-private opaque data.
> * Usually used for buffer_heads if PagePrivate.
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 0b0ae5084e60..c8a3aa02278d 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
> * Different with flags above, this flag is used only for fsdax mode. It
> * indicates that this page->mapping is now under reflink case.
> */
> -#define PAGE_MAPPING_DAX_COW 0x1
> +#define PAGE_MAPPING_DAX_SHARED 0x1
>
> static __always_inline bool folio_mapping_flags(struct folio *folio)
> {
> --
> 2.38.1
>
在 2022/12/3 10:07, Dan Williams 写道:
> Shiyang Ruan wrote:
>> fsdax page is used not only when CoW, but also mapread. To make the it
>> easily understood, use 'share' to indicate that the dax page is shared
>> by more than one extent. And add helper functions to use it.
>>
>> Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
>>
>> Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
>> ---
>> fs/dax.c | 38 ++++++++++++++++++++++----------------
>> include/linux/mm_types.h | 5 ++++-
>> include/linux/page-flags.h | 2 +-
>> 3 files changed, 27 insertions(+), 18 deletions(-)
>>
>> diff --git a/fs/dax.c b/fs/dax.c
>> index 1c6867810cbd..edbacb273ab5 100644
>> --- a/fs/dax.c
>> +++ b/fs/dax.c
>> @@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
>> for (pfn = dax_to_pfn(entry); \
>> pfn < dax_end_pfn(entry); pfn++)
>>
>> -static inline bool dax_mapping_is_cow(struct address_space *mapping)
>> +static inline bool dax_page_is_shared(struct page *page)
>> {
>> - return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
>> + return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
>> }
>>
>> /*
>> - * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
>> + * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
>> + * refcount.
>> */
>> -static inline void dax_mapping_set_cow(struct page *page)
>> +static inline void dax_page_bump_sharing(struct page *page)
>
> Similar to page_ref naming I would call this page_share_get() and the
> corresponding function page_share_put().
>
>> {
>> - if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
>> + if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
>> /*
>> * Reset the index if the page was already mapped
>> * regularly before.
>> */
>> if (page->mapping)
>> - page->index = 1;
>> - page->mapping = (void *)PAGE_MAPPING_DAX_COW;
>> + page->share = 1;
>> + page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
>
> Small nit, You could save a cast here by defining
> PAGE_MAPPING_DAX_SHARED as "((void *) 1)".
Ok.
>
>> }
>> - page->index++;
>> + page->share++;
>> +}
>> +
>> +static inline unsigned long dax_page_drop_sharing(struct page *page)
>> +{
>> + return --page->share;
>> }
>>
>> /*
>> - * When it is called in dax_insert_entry(), the cow flag will indicate that
>> + * When it is called in dax_insert_entry(), the shared flag will indicate that
>> * whether this entry is shared by multiple files. If so, set the page->mapping
>> - * FS_DAX_MAPPING_COW, and use page->index as refcount.
>> + * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
>> */
>> static void dax_associate_entry(void *entry, struct address_space *mapping,
>> - struct vm_area_struct *vma, unsigned long address, bool cow)
>> + struct vm_area_struct *vma, unsigned long address, bool shared)
>> {
>> unsigned long size = dax_entry_size(entry), pfn, index;
>> int i = 0;
>> @@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
>> for_each_mapped_pfn(entry, pfn) {
>> struct page *page = pfn_to_page(pfn);
>>
>> - if (cow) {
>> - dax_mapping_set_cow(page);
>> + if (shared) {
>> + dax_page_bump_sharing(page);
>> } else {
>> WARN_ON_ONCE(page->mapping);
>> page->mapping = mapping;
>> @@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
>> struct page *page = pfn_to_page(pfn);
>>
>> WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
>> - if (dax_mapping_is_cow(page->mapping)) {
>> - /* keep the CoW flag if this page is still shared */
>> - if (page->index-- > 0)
>> + if (dax_page_is_shared(page)) {
>> + /* keep the shared flag if this page is still shared */
>> + if (dax_page_drop_sharing(page) > 0)
>> continue;
>
> I think part of what makes this hard to read is trying to preserve the
> same code paths for shared pages and typical pages.
>
> page_share_put() should, in addition to decrementing the share, clear
> out page->mapping value.
In order to be consistent, how about naming the 3 helper functions like
this:
bool dax_page_is_shared(struct page *page);
void dax_page_share_get(struct page *page);
unsigned long dax_page_share_put(struct page *page);
--
Thanks,
Ruan.
>
>> } else
>> WARN_ON_ONCE(page->mapping && page->mapping != mapping);
>> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
>> index 500e536796ca..f46cac3657ad 100644
>> --- a/include/linux/mm_types.h
>> +++ b/include/linux/mm_types.h
>> @@ -103,7 +103,10 @@ struct page {
>> };
>> /* See page-flags.h for PAGE_MAPPING_FLAGS */
>> struct address_space *mapping;
>> - pgoff_t index; /* Our offset within mapping. */
>> + union {
>> + pgoff_t index; /* Our offset within mapping. */
>> + unsigned long share; /* share count for fsdax */
>> + };
>> /**
>> * @private: Mapping-private opaque data.
>> * Usually used for buffer_heads if PagePrivate.
>> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
>> index 0b0ae5084e60..c8a3aa02278d 100644
>> --- a/include/linux/page-flags.h
>> +++ b/include/linux/page-flags.h
>> @@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
>> * Different with flags above, this flag is used only for fsdax mode. It
>> * indicates that this page->mapping is now under reflink case.
>> */
>> -#define PAGE_MAPPING_DAX_COW 0x1
>> +#define PAGE_MAPPING_DAX_SHARED 0x1
>>
>> static __always_inline bool folio_mapping_flags(struct folio *folio)
>> {
>> --
>> 2.38.1
>>
>
>
On Mon, Dec 05, 2022 at 01:56:24PM +0800, Shiyang Ruan wrote:
>
>
> 在 2022/12/3 10:07, Dan Williams 写道:
> > Shiyang Ruan wrote:
> > > fsdax page is used not only when CoW, but also mapread. To make the it
> > > easily understood, use 'share' to indicate that the dax page is shared
> > > by more than one extent. And add helper functions to use it.
> > >
> > > Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
> > >
> > > Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
> > > ---
> > > fs/dax.c | 38 ++++++++++++++++++++++----------------
> > > include/linux/mm_types.h | 5 ++++-
> > > include/linux/page-flags.h | 2 +-
> > > 3 files changed, 27 insertions(+), 18 deletions(-)
> > >
> > > diff --git a/fs/dax.c b/fs/dax.c
> > > index 1c6867810cbd..edbacb273ab5 100644
> > > --- a/fs/dax.c
> > > +++ b/fs/dax.c
> > > @@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
> > > for (pfn = dax_to_pfn(entry); \
> > > pfn < dax_end_pfn(entry); pfn++)
> > > -static inline bool dax_mapping_is_cow(struct address_space *mapping)
> > > +static inline bool dax_page_is_shared(struct page *page)
> > > {
> > > - return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
> > > + return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
> > > }
> > > /*
> > > - * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the refcount.
> > > + * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
> > > + * refcount.
> > > */
> > > -static inline void dax_mapping_set_cow(struct page *page)
> > > +static inline void dax_page_bump_sharing(struct page *page)
> >
> > Similar to page_ref naming I would call this page_share_get() and the
> > corresponding function page_share_put().
> >
> > > {
> > > - if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
> > > + if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
> > > /*
> > > * Reset the index if the page was already mapped
> > > * regularly before.
> > > */
> > > if (page->mapping)
> > > - page->index = 1;
> > > - page->mapping = (void *)PAGE_MAPPING_DAX_COW;
> > > + page->share = 1;
> > > + page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
> >
> > Small nit, You could save a cast here by defining
> > PAGE_MAPPING_DAX_SHARED as "((void *) 1)".
>
> Ok.
It's sort of a pity you can't pass around a pointer to a privately
defined const struct in dax.c. But yeah, you might as well include the
cast in the macro definition.
> >
> > > }
> > > - page->index++;
> > > + page->share++;
> > > +}
> > > +
> > > +static inline unsigned long dax_page_drop_sharing(struct page *page)
> > > +{
> > > + return --page->share;
> > > }
> > > /*
> > > - * When it is called in dax_insert_entry(), the cow flag will indicate that
> > > + * When it is called in dax_insert_entry(), the shared flag will indicate that
> > > * whether this entry is shared by multiple files. If so, set the page->mapping
> > > - * FS_DAX_MAPPING_COW, and use page->index as refcount.
> > > + * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
> > > */
> > > static void dax_associate_entry(void *entry, struct address_space *mapping,
> > > - struct vm_area_struct *vma, unsigned long address, bool cow)
> > > + struct vm_area_struct *vma, unsigned long address, bool shared)
> > > {
> > > unsigned long size = dax_entry_size(entry), pfn, index;
> > > int i = 0;
> > > @@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
> > > for_each_mapped_pfn(entry, pfn) {
> > > struct page *page = pfn_to_page(pfn);
> > > - if (cow) {
> > > - dax_mapping_set_cow(page);
> > > + if (shared) {
> > > + dax_page_bump_sharing(page);
> > > } else {
> > > WARN_ON_ONCE(page->mapping);
> > > page->mapping = mapping;
> > > @@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
> > > struct page *page = pfn_to_page(pfn);
> > > WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
> > > - if (dax_mapping_is_cow(page->mapping)) {
> > > - /* keep the CoW flag if this page is still shared */
> > > - if (page->index-- > 0)
> > > + if (dax_page_is_shared(page)) {
> > > + /* keep the shared flag if this page is still shared */
> > > + if (dax_page_drop_sharing(page) > 0)
> > > continue;
> >
> > I think part of what makes this hard to read is trying to preserve the
> > same code paths for shared pages and typical pages.
> >
> > page_share_put() should, in addition to decrementing the share, clear
> > out page->mapping value.
>
> In order to be consistent, how about naming the 3 helper functions like
> this:
>
> bool dax_page_is_shared(struct page *page);
> void dax_page_share_get(struct page *page);
> unsigned long dax_page_share_put(struct page *page);
_sharing_get/_sharing_put ?
Either way sounds fine to me.
--D
>
> --
> Thanks,
> Ruan.
>
> >
> > > } else
> > > WARN_ON_ONCE(page->mapping && page->mapping != mapping);
> > > diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> > > index 500e536796ca..f46cac3657ad 100644
> > > --- a/include/linux/mm_types.h
> > > +++ b/include/linux/mm_types.h
> > > @@ -103,7 +103,10 @@ struct page {
> > > };
> > > /* See page-flags.h for PAGE_MAPPING_FLAGS */
> > > struct address_space *mapping;
> > > - pgoff_t index; /* Our offset within mapping. */
> > > + union {
> > > + pgoff_t index; /* Our offset within mapping. */
> > > + unsigned long share; /* share count for fsdax */
> > > + };
> > > /**
> > > * @private: Mapping-private opaque data.
> > > * Usually used for buffer_heads if PagePrivate.
> > > diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> > > index 0b0ae5084e60..c8a3aa02278d 100644
> > > --- a/include/linux/page-flags.h
> > > +++ b/include/linux/page-flags.h
> > > @@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
> > > * Different with flags above, this flag is used only for fsdax mode. It
> > > * indicates that this page->mapping is now under reflink case.
> > > */
> > > -#define PAGE_MAPPING_DAX_COW 0x1
> > > +#define PAGE_MAPPING_DAX_SHARED 0x1
> > > static __always_inline bool folio_mapping_flags(struct folio *folio)
> > > {
> > > --
> > > 2.38.1
> > >
> >
> >
On Fri, 2022-12-02 at 09:23 +0000, Shiyang Ruan wrote:
> fsdax page is used not only when CoW, but also mapread. To make the
> it
> easily understood, use 'share' to indicate that the dax page is
> shared
> by more than one extent. And add helper functions to use it.
>
> Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
>
The new changes look reasonable to me
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
> Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
> ---
> fs/dax.c | 38 ++++++++++++++++++++++--------------
> --
> include/linux/mm_types.h | 5 ++++-
> include/linux/page-flags.h | 2 +-
> 3 files changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index 1c6867810cbd..edbacb273ab5 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -334,35 +334,41 @@ static unsigned long dax_end_pfn(void *entry)
> for (pfn = dax_to_pfn(entry); \
> pfn < dax_end_pfn(entry); pfn++)
>
> -static inline bool dax_mapping_is_cow(struct address_space *mapping)
> +static inline bool dax_page_is_shared(struct page *page)
> {
> - return (unsigned long)mapping == PAGE_MAPPING_DAX_COW;
> + return (unsigned long)page->mapping ==
> PAGE_MAPPING_DAX_SHARED;
> }
>
> /*
> - * Set the page->mapping with FS_DAX_MAPPING_COW flag, increase the
> refcount.
> + * Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase
> the
> + * refcount.
> */
> -static inline void dax_mapping_set_cow(struct page *page)
> +static inline void dax_page_bump_sharing(struct page *page)
> {
> - if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_COW) {
> + if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
> /*
> * Reset the index if the page was already mapped
> * regularly before.
> */
> if (page->mapping)
> - page->index = 1;
> - page->mapping = (void *)PAGE_MAPPING_DAX_COW;
> + page->share = 1;
> + page->mapping = (void *)PAGE_MAPPING_DAX_SHARED;
> }
> - page->index++;
> + page->share++;
> +}
> +
> +static inline unsigned long dax_page_drop_sharing(struct page *page)
> +{
> + return --page->share;
> }
>
> /*
> - * When it is called in dax_insert_entry(), the cow flag will
> indicate that
> + * When it is called in dax_insert_entry(), the shared flag will
> indicate that
> * whether this entry is shared by multiple files. If so, set the
> page->mapping
> - * FS_DAX_MAPPING_COW, and use page->index as refcount.
> + * PAGE_MAPPING_DAX_SHARED, and use page->share as refcount.
> */
> static void dax_associate_entry(void *entry, struct address_space
> *mapping,
> - struct vm_area_struct *vma, unsigned long address,
> bool cow)
> + struct vm_area_struct *vma, unsigned long address,
> bool shared)
> {
> unsigned long size = dax_entry_size(entry), pfn, index;
> int i = 0;
> @@ -374,8 +380,8 @@ static void dax_associate_entry(void *entry,
> struct address_space *mapping,
> for_each_mapped_pfn(entry, pfn) {
> struct page *page = pfn_to_page(pfn);
>
> - if (cow) {
> - dax_mapping_set_cow(page);
> + if (shared) {
> + dax_page_bump_sharing(page);
> } else {
> WARN_ON_ONCE(page->mapping);
> page->mapping = mapping;
> @@ -396,9 +402,9 @@ static void dax_disassociate_entry(void *entry,
> struct address_space *mapping,
> struct page *page = pfn_to_page(pfn);
>
> WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
> - if (dax_mapping_is_cow(page->mapping)) {
> - /* keep the CoW flag if this page is still
> shared */
> - if (page->index-- > 0)
> + if (dax_page_is_shared(page)) {
> + /* keep the shared flag if this page is still
> shared */
> + if (dax_page_drop_sharing(page) > 0)
> continue;
> } else
> WARN_ON_ONCE(page->mapping && page->mapping
> != mapping);
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 500e536796ca..f46cac3657ad 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -103,7 +103,10 @@ struct page {
> };
> /* See page-flags.h for PAGE_MAPPING_FLAGS */
> struct address_space *mapping;
> - pgoff_t index; /* Our offset within
> mapping. */
> + union {
> + pgoff_t index; /* Our offset
> within mapping. */
> + unsigned long share; /* share
> count for fsdax */
> + };
> /**
> * @private: Mapping-private opaque data.
> * Usually used for buffer_heads if
> PagePrivate.
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 0b0ae5084e60..c8a3aa02278d 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -641,7 +641,7 @@ PAGEFLAG_FALSE(VmemmapSelfHosted,
> vmemmap_self_hosted)
> * Different with flags above, this flag is used only for fsdax
> mode. It
> * indicates that this page->mapping is now under reflink case.
> */
> -#define PAGE_MAPPING_DAX_COW 0x1
> +#define PAGE_MAPPING_DAX_SHARED 0x1
>
> static __always_inline bool folio_mapping_flags(struct folio *folio)
> {
On Fri, 2 Dec 2022 09:23:11 +0000 Shiyang Ruan <ruansy.fnst@fujitsu.com> wrote:
> fsdax page is used not only when CoW, but also mapread. To make the it
> easily understood, use 'share' to indicate that the dax page is shared
> by more than one extent. And add helper functions to use it.
>
> Also, the flag needs to be renamed to PAGE_MAPPING_DAX_SHARED.
>
For those who are wondering what changed, I queued the below incremental
patch.
From: Shiyang Ruan <ruansy.fnst@fujitsu.com>
Subject: fsdax: introduce page->share for fsdax in reflink mode
Date: Fri, 2 Dec 2022 09:23:11 +0000
rename several functions
Link: https://lkml.kernel.org/r/1669972991-246-1-git-send-email-ruansy.fnst@fujitsu.com
Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Darrick J. Wong <djwong@kernel.org>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
fs/dax.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/fs/dax.c~fsdax-introduce-page-share-for-fsdax-in-reflink-mode-fix
+++ a/fs/dax.c
@@ -334,7 +334,7 @@ static unsigned long dax_end_pfn(void *e
for (pfn = dax_to_pfn(entry); \
pfn < dax_end_pfn(entry); pfn++)
-static inline bool dax_mapping_is_shared(struct page *page)
+static inline bool dax_page_is_shared(struct page *page)
{
return (unsigned long)page->mapping == PAGE_MAPPING_DAX_SHARED;
}
@@ -343,7 +343,7 @@ static inline bool dax_mapping_is_shared
* Set the page->mapping with PAGE_MAPPING_DAX_SHARED flag, increase the
* refcount.
*/
-static inline void dax_mapping_set_shared(struct page *page)
+static inline void dax_page_bump_sharing(struct page *page)
{
if ((uintptr_t)page->mapping != PAGE_MAPPING_DAX_SHARED) {
/*
@@ -357,7 +357,7 @@ static inline void dax_mapping_set_share
page->share++;
}
-static inline unsigned long dax_mapping_decrease_shared(struct page *page)
+static inline unsigned long dax_page_drop_sharing(struct page *page)
{
return --page->share;
}
@@ -381,7 +381,7 @@ static void dax_associate_entry(void *en
struct page *page = pfn_to_page(pfn);
if (shared) {
- dax_mapping_set_shared(page);
+ dax_page_bump_sharing(page);
} else {
WARN_ON_ONCE(page->mapping);
page->mapping = mapping;
@@ -402,9 +402,9 @@ static void dax_disassociate_entry(void
struct page *page = pfn_to_page(pfn);
WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
- if (dax_mapping_is_shared(page)) {
+ if (dax_page_is_shared(page)) {
/* keep the shared flag if this page is still shared */
- if (dax_mapping_decrease_shared(page) > 0)
+ if (dax_page_drop_sharing(page) > 0)
continue;
} else
WARN_ON_ONCE(page->mapping && page->mapping != mapping);
_
© 2016 - 2026 Red Hat, Inc.