【linux内核】结构体address_space_operations接口分析
结构体address_space_operations接口分析
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
/* Write back some dirty pages from this mapping. */
int (*writepages)(struct address_space *, struct writeback_control *);
/* Set a page dirty. Return true if this dirtied it */
int (*set_page_dirty)(struct page *page);
/*
* Reads in the requested pages. Unlike ->readpage(), this is
* PURELY used for read-ahead!.
*/
int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages);
void (*readahead)(struct readahead_control *);
int (*write_begin)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata);
int (*write_end)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata);
/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
sector_t (*bmap)(struct address_space *, sector_t);
void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, gfp_t);
void (*freepage)(struct page *);
ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
/*
* migrate the contents of a page to the specified target. If
* migrate_mode is MIGRATE_ASYNC, it must not block.
*/
int (*migratepage) (struct address_space *,
struct page *, struct page *, enum migrate_mode);
bool (*isolate_page)(struct page *, isolate_mode_t);
void (*putback_page)(struct page *);
int (*launder_page) (struct page *);
int (*is_partially_uptodate) (struct page *, unsigned long,
unsigned long);
void (*is_dirty_writeback) (struct page *, bool *, bool *);
int (*error_remove_page)(struct address_space *, struct page *);
/* swapfile support */
int (*swap_activate)(struct swap_info_struct *sis, struct file *file,
sector_t *span);
void (*swap_deactivate)(struct file *file);
};
cephfs内核客户蹲会接接口:
const struct address_space_operations ceph_aops = {
.readpage = ceph_readpage,
.readpages = ceph_readpages,
.writepage = ceph_writepage,
.writepages = ceph_writepages_start,
.write_begin = ceph_write_begin,
.write_end = ceph_write_end,
.set_page_dirty = ceph_set_page_dirty,
.invalidatepage = ceph_invalidatepage,
.releasepage = ceph_releasepage,
.direct_IO = ceph_direct_io,
};
- writepage:将Page写回磁盘。
- readpage: 从磁盘读取Page。
- writepages: 写多个Page至磁盘。
- set_page_dirty:设置某个Page为脏页。
- readpages: 读取多个Page, 一般用来预读。
- write_begin: 准备一个写操作。
- write_end: 完成一个写操作。
- invalidatepage:使该Page无效。
- releasepage:释放Page。
- direct_IO:对address_space中的所有Page进行DIO。
write_begin、write_end
以最常见的:
write(fd, buf, len)
为例(非 O_DIRECT):
sys_write
└─ vfs_write
└─ new_sync_write
└─ file->f_op->write_iter
└─ generic_file_write_iter
└─ generic_perform_write
├─ write_begin ← ★ 这里触发
├─ 拷贝用户数据到 page cache
└─ write_end ← ★ 这里触发
👉 真正触发点在 generic_perform_write()
set_page_dirty 触发时机:只要内核认为“这个 page 的内容已经被修改、需要回写”,就会触发 set_page_dirty(),而且 90% 的情况发生在:write_end() 之后。
典型路径:
write(fd)
└─ generic_file_write_iter
└─ generic_perform_write
├─ write_begin
├─ copy_from_iter ← 数据真正被修改
└─ write_end
└─ set_page_dirty(page) ← ★
为什么必须在 write_end?
- write_begin:还没改数据
- copy_from_iter:改了 page 内容
- write_end:确认改成功 → 标脏
📌 这是 page cache 写的“唯一合法点”。

浙公网安备 33010602011771号