1 /* 2 * Copyright (c) 2006-2025 RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2023-05-05 RTT Implement dentry in dfs v2.0 9 */ 10 11 #ifndef DFS_PAGE_CACHE_H__ 12 #define DFS_PAGE_CACHE_H__ 13 14 #include <rtthread.h> 15 16 #ifdef RT_USING_PAGECACHE 17 18 #include <dfs_file.h> 19 #include <avl.h> 20 21 #ifdef __cplusplus 22 extern "C" 23 { 24 #endif 25 26 struct rt_varea; 27 struct rt_aspace; 28 struct dfs_vnode; 29 struct dfs_dentry; 30 struct dfs_aspace; 31 32 /* Memory mapping structure for page cache */ 33 struct dfs_mmap 34 { 35 rt_list_t mmap_node; /* List node for address space's mmap list */ 36 struct rt_aspace *aspace; /* Address space this mapping belongs to */ 37 void *vaddr; /* Virtual address where the page is mapped */ 38 }; 39 40 /* Page structure for file system page cache */ 41 struct dfs_page 42 { 43 rt_list_t space_node; /* Node for address space's page list */ 44 rt_list_t dirty_node; /* Node for dirty page list */ 45 struct util_avl_struct avl_node; /* Node for AVL tree in address space */ 46 rt_list_t mmap_head; /* Head of memory mappings list */ 47 48 rt_atomic_t ref_count; /* Reference count for this page */ 49 50 void *page; /* Pointer to physical page data */ 51 off_t fpos; /* File position this page represents */ 52 size_t size; /* Total size of the page */ 53 size_t len; /* Valid data length in the page */ 54 int is_dirty; /* Dirty flag indicating if page needs writeback */ 55 rt_tick_t tick_ms; /* Last access timestamp */ 56 57 struct dfs_aspace *aspace; /* Address space this page belongs to */ 58 }; 59 60 /* Address space operations interface */ 61 struct dfs_aspace_ops 62 { 63 ssize_t (*read)(struct dfs_file *file, struct dfs_page *page); /* Read operation for page cache */ 64 ssize_t (*write)(struct dfs_page *page); /* Write operation for page cache */ 65 }; 66 67 /* Address space structure for page cache management */ 68 struct dfs_aspace 69 { 70 rt_list_t hash_node, cache_node; /* Nodes for hash table and cache lists */ 71 char *fullpath, *pathname; /* Full path and relative path strings */ 72 struct dfs_mnt *mnt; /* Mount point this space belongs to */ 73 74 rt_list_t list_active, list_inactive; /* Active and inactive page lists */ 75 rt_list_t list_dirty; /* Dirty page list */ 76 size_t pages_count; /* Total pages in this space */ 77 78 struct util_avl_root avl_root; /* AVL tree root for page lookup */ 79 struct dfs_page *avl_page; /* Current AVL tree page */ 80 81 rt_bool_t is_active; /* Active/inactive status flag */ 82 83 struct rt_mutex lock; /* Mutex for thread safety */ 84 rt_atomic_t ref_count; /* Reference counter */ 85 86 struct dfs_vnode *vnode; /* Associated vnode */ 87 const struct dfs_aspace_ops *ops; /* Operations interface */ 88 }; 89 90 #ifndef RT_PAGECACHE_HASH_NR 91 #define RT_PAGECACHE_HASH_NR 1024 92 #endif 93 94 /* Global page cache management structure */ 95 struct dfs_pcache 96 { 97 rt_list_t head[RT_PAGECACHE_HASH_NR]; /* Hash table buckets for address spaces */ 98 rt_list_t list_active, list_inactive; /* Active and inactive space lists */ 99 rt_atomic_t pages_count; /* Total cached pages count */ 100 struct rt_mutex lock; /* Global lock for thread safety */ 101 struct rt_messagequeue *mqueue; /* Message queue for sending GC/WB command.*/ 102 rt_tick_t last_time_wb; /* Last writeback timestamp */ 103 }; 104 105 struct dfs_aspace *dfs_aspace_create(struct dfs_dentry *dentry, struct dfs_vnode *vnode, const struct dfs_aspace_ops *ops); 106 int dfs_aspace_destroy(struct dfs_aspace *aspace); 107 108 int dfs_aspace_read(struct dfs_file *file, void *buf, size_t count, off_t *pos); 109 int dfs_aspace_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos); 110 int dfs_aspace_flush(struct dfs_aspace *aspace); 111 int dfs_aspace_clean(struct dfs_aspace *aspace); 112 113 void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr); 114 int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea); 115 int dfs_aspace_page_unmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr); 116 int dfs_aspace_page_dirty(struct dfs_file *file, struct rt_varea *varea, void *vaddr); 117 118 off_t dfs_aspace_fpos(struct rt_varea *varea, void *vaddr); 119 void *dfs_aspace_vaddr(struct rt_varea *varea, off_t fpos); 120 121 int dfs_aspace_mmap_read(struct dfs_file *file, struct rt_varea *varea, void *data); 122 int dfs_aspace_mmap_write(struct dfs_file *file, struct rt_varea *varea, void *data); 123 124 void dfs_pcache_release(size_t count); 125 void dfs_pcache_unmount(struct dfs_mnt *mnt); 126 void dfs_pcache_clean(struct dfs_mnt *mnt); 127 128 #ifdef __cplusplus 129 } 130 #endif 131 132 #endif 133 134 #endif