Linux PageDirty定义

Linux PageDirty系列函数定义

Kernel版本:Linux 6.1.0

1. PG_Flags检测类型

1.1 分为以下三类

#define PAGEFLAG(uname, lname, policy)                  \
    TESTPAGEFLAG(uname, lname, policy)              \
    SETPAGEFLAG(uname, lname, policy)               \
    CLEARPAGEFLAG(uname, lname, policy)

#define __PAGEFLAG(uname, lname, policy)                \
    TESTPAGEFLAG(uname, lname, policy)              \
    __SETPAGEFLAG(uname, lname, policy)             \
    __CLEARPAGEFLAG(uname, lname, policy)

#define TESTSCFLAG(uname, lname, policy)                \
    TESTSETFLAG(uname, lname, policy)               \
    TESTCLEARFLAG(uname, lname, policy)

1.2 对应的函数定义与实现

以上定义的实际实现为函数定义的拼装
包括:

Page##uname
SetPage##uname
ClearPage##uname
__SetPage##uname
__ClearPage##uname
TestSetPage##uname
TestClearPage##uname

他们的定义为:

/*
 * Macros to create function definitions for page flags
 */
#define TESTPAGEFLAG(uname, lname, policy)              \
static __always_inline bool folio_test_##lname(struct folio *folio) \
{ return test_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); }    \
static __always_inline int Page##uname(struct page *page)       \
{ return test_bit(PG_##lname, &policy(page, 0)->flags); }

#define SETPAGEFLAG(uname, lname, policy)               \
static __always_inline                          \
void folio_set_##lname(struct folio *folio)             \
{ set_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); }        \
static __always_inline void SetPage##uname(struct page *page)       \
{ set_bit(PG_##lname, &policy(page, 1)->flags); }

#define CLEARPAGEFLAG(uname, lname, policy)             \
static __always_inline                          \
void folio_clear_##lname(struct folio *folio)               \
{ clear_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); }      \
static __always_inline void ClearPage##uname(struct page *page)     \
{ clear_bit(PG_##lname, &policy(page, 1)->flags); }

#define __SETPAGEFLAG(uname, lname, policy)             \
static __always_inline                          \
void __folio_set_##lname(struct folio *folio)               \
{ __set_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); }      \
static __always_inline void __SetPage##uname(struct page *page)     \
{ __set_bit(PG_##lname, &policy(page, 1)->flags); }

#define __CLEARPAGEFLAG(uname, lname, policy)               \
static __always_inline                          \
void __folio_clear_##lname(struct folio *folio)             \
{ __clear_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); }    \
static __always_inline void __ClearPage##uname(struct page *page)   \
{ __clear_bit(PG_##lname, &policy(page, 1)->flags); }

#define TESTSETFLAG(uname, lname, policy)               \
static __always_inline                          \
bool folio_test_set_##lname(struct folio *folio)            \
{ return test_and_set_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); } \
static __always_inline int TestSetPage##uname(struct page *page)    \
{ return test_and_set_bit(PG_##lname, &policy(page, 1)->flags); }

#define TESTCLEARFLAG(uname, lname, policy)             \
static __always_inline                          \
bool folio_test_clear_##lname(struct folio *folio)          \
{ return test_and_clear_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); } \
static __always_inline int TestClearPage##uname(struct page *page)  \
{ return test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); }

2. 定义位置

include/linux/page-flags.h

3. 定义函数

以Dirty标志的检测为例

PAGEFLAG(Dirty, dirty, PF_HEAD) TESTSCFLAG(Dirty, dirty, PF_HEAD)
    __CLEARPAGEFLAG(Dirty, dirty, PF_HEAD)

该定义根据如下代码在编译阶段被解析

#define PAGEFLAG(uname, lname, policy)                  \
    TESTPAGEFLAG(uname, lname, policy)              \
    SETPAGEFLAG(uname, lname, policy)               \
    CLEARPAGEFLAG(uname, lname, policy)

解析结果为

    TESTPAGEFLAG(Dirty, dirty, PF_HEAD)
    SETPAGEFLAG(Dirty, dirty, PF_HEAD)
    CLEARPAGEFLAG(Dirty, dirty, PF_HEAD)

进一步被解析为

static __always_inline bool folio_test_dirty(struct folio *folio)
{ return test_bit(PG_dirty, folio_flags(folio, FOLIO_PF_HEAD)); }

static __always_inline int PageDirty(struct page *page)
{ return test_bit(PG_dirty, &PF_HEAD(page, 0)->flags); }

static __always_inline
void folio_set_dirty(struct folio *folio)
{ set_bit(PG_dirty, folio_flags(folio, FOLIO_PF_HEAD)); }

static __always_inline void SetPageDirty(struct page *page)
{ set_bit(PG_dirty, &PF_HEAD(page, 1)->flags); }

static __always_inline
void folio_clear_dirty(struct folio *folio)
{ clear_bit(PG_##dirty, folio_flags(folio, FOLIO_PF_HEAD)); }

static __always_inline void ClearPageDirty(struct page *page)
{ clear_bit(PG_##dirty, &PF_HEAD(page, 1)->flags); }

解析后的函数为别为

folio_test_dirty
PageDirty
folio_set_dirty
SetPageDirty
folio_clear_dirty
ClearPageDirty

3.1 进一步分析函数实现

以PageDirty为例

static __always_inline int PageDirty(struct page *page)
{ return test_bit(PG_dirty, &PF_HEAD(page, 0)->flags); }

根据宏定义

#define PF_POISONED_CHECK(page) ({                  \
        VM_BUG_ON_PGFLAGS(PagePoisoned(page), page);        \
        page; })
#define PF_HEAD(page, enforce)  PF_POISONED_CHECK(compound_head(page))

进一步解析为

static __always_inline int PageDirty(struct page *page)
{ return test_bit(PG_dirty, &({
        VM_BUG_ON_PGFLAGS(PagePoisoned(compound_head(page)), compound_head(page));
        compound_head(page); })->flags); }

其中可以简化为如下定义

static __always_inline int PageDirty(struct page *page)
{ return test_bit(PG_dirty, &page->flags); }

page->flags的定义为

include/linux/mm_types.h
struct page {
	unsigned long flags;		/* Atomic flags, some possibly

其类型为 enum pageflags
函数的第一个参数PG_dirty正是其中的一个bit位

4. 结论

所以PageDirty函数的作用是检测page->flags中是否将PG_dirty置位。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值