1 /* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */
2 /*
3 * Copyright (C) 2018 HUAWEI, Inc.
4 * http://www.huawei.com/
5 * Created by Miao Xie <[email protected]>
6 * with heavy changes by Gao Xiang <[email protected]>
7 */
8 #ifndef __EROFS_CACHE_H
9 #define __EROFS_CACHE_H
10
11 #ifdef __cplusplus
12 extern "C"
13 {
14 #endif
15
16 #include "internal.h"
17
18 struct erofs_buffer_head;
19 struct erofs_buffer_block;
20
21 #define DATA 0
22 #define META 1
23 /* including inline xattrs, extent */
24 #define INODE 2
25 /* directory data */
26 #define DIRA 3
27 /* shared xattrs */
28 #define XATTR 4
29 /* device table */
30 #define DEVT 5
31
32 struct erofs_bhops {
33 int (*flush)(struct erofs_buffer_head *bh);
34 };
35
36 struct erofs_buffer_head {
37 struct list_head list;
38 struct erofs_buffer_block *block;
39
40 erofs_off_t off;
41 const struct erofs_bhops *op;
42
43 void *fsprivate;
44 };
45
46 struct erofs_buffer_block {
47 struct list_head list;
48 struct list_head mapped_list;
49
50 erofs_blk_t blkaddr;
51 int type;
52
53 struct erofs_buffer_head buffers;
54 };
55
56 struct erofs_bufmgr {
57 struct erofs_sb_info *sbi;
58
59 /* buckets for all mapped buffer blocks to boost up allocation */
60 struct list_head mapped_buckets[META + 1][EROFS_MAX_BLOCK_SIZE];
61
62 struct erofs_buffer_block blkh;
63 erofs_blk_t tail_blkaddr, metablkcnt;
64
65 /* last mapped buffer block to accelerate erofs_mapbh() */
66 struct erofs_buffer_block *last_mapped_block;
67 };
68
get_alignsize(struct erofs_sb_info * sbi,int type,int * type_ret)69 static inline const int get_alignsize(struct erofs_sb_info *sbi, int type,
70 int *type_ret)
71 {
72 if (type == DATA)
73 return erofs_blksiz(sbi);
74
75 if (type == INODE) {
76 *type_ret = META;
77 return sizeof(struct erofs_inode_compact);
78 } else if (type == DIRA) {
79 *type_ret = META;
80 return erofs_blksiz(sbi);
81 } else if (type == XATTR) {
82 *type_ret = META;
83 return sizeof(struct erofs_xattr_entry);
84 } else if (type == DEVT) {
85 *type_ret = META;
86 return EROFS_DEVT_SLOT_SIZE;
87 }
88
89 if (type == META)
90 return 1;
91 return -EINVAL;
92 }
93
94 extern const struct erofs_bhops erofs_drop_directly_bhops;
95 extern const struct erofs_bhops erofs_skip_write_bhops;
96
erofs_btell(struct erofs_buffer_head * bh,bool end)97 static inline erofs_off_t erofs_btell(struct erofs_buffer_head *bh, bool end)
98 {
99 const struct erofs_buffer_block *bb = bh->block;
100 struct erofs_bufmgr *bmgr =
101 (struct erofs_bufmgr *)bb->buffers.fsprivate;
102
103 if (bb->blkaddr == NULL_ADDR)
104 return NULL_ADDR_UL;
105
106 return erofs_pos(bmgr->sbi, bb->blkaddr) +
107 (end ? list_next_entry(bh, list)->off : bh->off);
108 }
109
erofs_bh_flush_generic_end(struct erofs_buffer_head * bh)110 static inline int erofs_bh_flush_generic_end(struct erofs_buffer_head *bh)
111 {
112 list_del(&bh->list);
113 free(bh);
114 return 0;
115 }
116
117 struct erofs_bufmgr *erofs_buffer_init(struct erofs_sb_info *sbi,
118 erofs_blk_t startblk);
119 int erofs_bh_balloon(struct erofs_buffer_head *bh, erofs_off_t incr);
120
121 struct erofs_buffer_head *erofs_balloc(struct erofs_bufmgr *bmgr,
122 int type, erofs_off_t size,
123 unsigned int required_ext,
124 unsigned int inline_ext);
125 struct erofs_buffer_head *erofs_battach(struct erofs_buffer_head *bh,
126 int type, unsigned int size);
127
128 erofs_blk_t erofs_mapbh(struct erofs_bufmgr *bmgr,
129 struct erofs_buffer_block *bb);
130 int erofs_bflush(struct erofs_bufmgr *bmgr,
131 struct erofs_buffer_block *bb);
132
133 void erofs_bdrop(struct erofs_buffer_head *bh, bool tryrevoke);
134 erofs_blk_t erofs_total_metablocks(struct erofs_bufmgr *bmgr);
135 void erofs_buffer_exit(struct erofs_bufmgr *bmgr);
136
137 #ifdef __cplusplus
138 }
139 #endif
140
141 #endif
142