Commit 881764461165d69814194b6fe97d4352bbd0ae82
1 parent
ad44be5c78
Exists in
master
and in
6 other branches
logfs: propagate umode_t
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 2 changed files with 2 additions and 2 deletions Inline Diff
fs/logfs/inode.c
1 | /* | 1 | /* |
2 | * fs/logfs/inode.c - inode handling code | 2 | * fs/logfs/inode.c - inode handling code |
3 | * | 3 | * |
4 | * As should be obvious for Linux kernel code, license is GPLv2 | 4 | * As should be obvious for Linux kernel code, license is GPLv2 |
5 | * | 5 | * |
6 | * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> | 6 | * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> |
7 | */ | 7 | */ |
8 | #include "logfs.h" | 8 | #include "logfs.h" |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/writeback.h> | 10 | #include <linux/writeback.h> |
11 | #include <linux/backing-dev.h> | 11 | #include <linux/backing-dev.h> |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * How soon to reuse old inode numbers? LogFS doesn't store deleted inodes | 14 | * How soon to reuse old inode numbers? LogFS doesn't store deleted inodes |
15 | * on the medium. It therefore also lacks a method to store the previous | 15 | * on the medium. It therefore also lacks a method to store the previous |
16 | * generation number for deleted inodes. Instead a single generation number | 16 | * generation number for deleted inodes. Instead a single generation number |
17 | * is stored which will be used for new inodes. Being just a 32bit counter, | 17 | * is stored which will be used for new inodes. Being just a 32bit counter, |
18 | * this can obvious wrap relatively quickly. So we only reuse inodes if we | 18 | * this can obvious wrap relatively quickly. So we only reuse inodes if we |
19 | * know that a fair number of inodes can be created before we have to increment | 19 | * know that a fair number of inodes can be created before we have to increment |
20 | * the generation again - effectively adding some bits to the counter. | 20 | * the generation again - effectively adding some bits to the counter. |
21 | * But being too aggressive here means we keep a very large and very sparse | 21 | * But being too aggressive here means we keep a very large and very sparse |
22 | * inode file, wasting space on indirect blocks. | 22 | * inode file, wasting space on indirect blocks. |
23 | * So what is a good value? Beats me. 64k seems moderately bad on both | 23 | * So what is a good value? Beats me. 64k seems moderately bad on both |
24 | * fronts, so let's use that for now... | 24 | * fronts, so let's use that for now... |
25 | * | 25 | * |
26 | * NFS sucks, as everyone already knows. | 26 | * NFS sucks, as everyone already knows. |
27 | */ | 27 | */ |
28 | #define INOS_PER_WRAP (0x10000) | 28 | #define INOS_PER_WRAP (0x10000) |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Logfs' requirement to read inodes for garbage collection makes life a bit | 31 | * Logfs' requirement to read inodes for garbage collection makes life a bit |
32 | * harder. GC may have to read inodes that are in I_FREEING state, when they | 32 | * harder. GC may have to read inodes that are in I_FREEING state, when they |
33 | * are being written out - and waiting for GC to make progress, naturally. | 33 | * are being written out - and waiting for GC to make progress, naturally. |
34 | * | 34 | * |
35 | * So we cannot just call iget() or some variant of it, but first have to check | 35 | * So we cannot just call iget() or some variant of it, but first have to check |
36 | * wether the inode in question might be in I_FREEING state. Therefore we | 36 | * wether the inode in question might be in I_FREEING state. Therefore we |
37 | * maintain our own per-sb list of "almost deleted" inodes and check against | 37 | * maintain our own per-sb list of "almost deleted" inodes and check against |
38 | * that list first. Normally this should be at most 1-2 entries long. | 38 | * that list first. Normally this should be at most 1-2 entries long. |
39 | * | 39 | * |
40 | * Also, inodes have logfs-specific reference counting on top of what the vfs | 40 | * Also, inodes have logfs-specific reference counting on top of what the vfs |
41 | * does. When .destroy_inode is called, normally the reference count will drop | 41 | * does. When .destroy_inode is called, normally the reference count will drop |
42 | * to zero and the inode gets deleted. But if GC accessed the inode, its | 42 | * to zero and the inode gets deleted. But if GC accessed the inode, its |
43 | * refcount will remain nonzero and final deletion will have to wait. | 43 | * refcount will remain nonzero and final deletion will have to wait. |
44 | * | 44 | * |
45 | * As a result we have two sets of functions to get/put inodes: | 45 | * As a result we have two sets of functions to get/put inodes: |
46 | * logfs_safe_iget/logfs_safe_iput - safe to call from GC context | 46 | * logfs_safe_iget/logfs_safe_iput - safe to call from GC context |
47 | * logfs_iget/iput - normal version | 47 | * logfs_iget/iput - normal version |
48 | */ | 48 | */ |
49 | static struct kmem_cache *logfs_inode_cache; | 49 | static struct kmem_cache *logfs_inode_cache; |
50 | 50 | ||
51 | static DEFINE_SPINLOCK(logfs_inode_lock); | 51 | static DEFINE_SPINLOCK(logfs_inode_lock); |
52 | 52 | ||
53 | static void logfs_inode_setops(struct inode *inode) | 53 | static void logfs_inode_setops(struct inode *inode) |
54 | { | 54 | { |
55 | switch (inode->i_mode & S_IFMT) { | 55 | switch (inode->i_mode & S_IFMT) { |
56 | case S_IFDIR: | 56 | case S_IFDIR: |
57 | inode->i_op = &logfs_dir_iops; | 57 | inode->i_op = &logfs_dir_iops; |
58 | inode->i_fop = &logfs_dir_fops; | 58 | inode->i_fop = &logfs_dir_fops; |
59 | inode->i_mapping->a_ops = &logfs_reg_aops; | 59 | inode->i_mapping->a_ops = &logfs_reg_aops; |
60 | break; | 60 | break; |
61 | case S_IFREG: | 61 | case S_IFREG: |
62 | inode->i_op = &logfs_reg_iops; | 62 | inode->i_op = &logfs_reg_iops; |
63 | inode->i_fop = &logfs_reg_fops; | 63 | inode->i_fop = &logfs_reg_fops; |
64 | inode->i_mapping->a_ops = &logfs_reg_aops; | 64 | inode->i_mapping->a_ops = &logfs_reg_aops; |
65 | break; | 65 | break; |
66 | case S_IFLNK: | 66 | case S_IFLNK: |
67 | inode->i_op = &logfs_symlink_iops; | 67 | inode->i_op = &logfs_symlink_iops; |
68 | inode->i_mapping->a_ops = &logfs_reg_aops; | 68 | inode->i_mapping->a_ops = &logfs_reg_aops; |
69 | break; | 69 | break; |
70 | case S_IFSOCK: /* fall through */ | 70 | case S_IFSOCK: /* fall through */ |
71 | case S_IFBLK: /* fall through */ | 71 | case S_IFBLK: /* fall through */ |
72 | case S_IFCHR: /* fall through */ | 72 | case S_IFCHR: /* fall through */ |
73 | case S_IFIFO: | 73 | case S_IFIFO: |
74 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 74 | init_special_inode(inode, inode->i_mode, inode->i_rdev); |
75 | break; | 75 | break; |
76 | default: | 76 | default: |
77 | BUG(); | 77 | BUG(); |
78 | } | 78 | } |
79 | } | 79 | } |
80 | 80 | ||
81 | static struct inode *__logfs_iget(struct super_block *sb, ino_t ino) | 81 | static struct inode *__logfs_iget(struct super_block *sb, ino_t ino) |
82 | { | 82 | { |
83 | struct inode *inode = iget_locked(sb, ino); | 83 | struct inode *inode = iget_locked(sb, ino); |
84 | int err; | 84 | int err; |
85 | 85 | ||
86 | if (!inode) | 86 | if (!inode) |
87 | return ERR_PTR(-ENOMEM); | 87 | return ERR_PTR(-ENOMEM); |
88 | if (!(inode->i_state & I_NEW)) | 88 | if (!(inode->i_state & I_NEW)) |
89 | return inode; | 89 | return inode; |
90 | 90 | ||
91 | err = logfs_read_inode(inode); | 91 | err = logfs_read_inode(inode); |
92 | if (err || inode->i_nlink == 0) { | 92 | if (err || inode->i_nlink == 0) { |
93 | /* inode->i_nlink == 0 can be true when called from | 93 | /* inode->i_nlink == 0 can be true when called from |
94 | * block validator */ | 94 | * block validator */ |
95 | /* set i_nlink to 0 to prevent caching */ | 95 | /* set i_nlink to 0 to prevent caching */ |
96 | clear_nlink(inode); | 96 | clear_nlink(inode); |
97 | logfs_inode(inode)->li_flags |= LOGFS_IF_ZOMBIE; | 97 | logfs_inode(inode)->li_flags |= LOGFS_IF_ZOMBIE; |
98 | iget_failed(inode); | 98 | iget_failed(inode); |
99 | if (!err) | 99 | if (!err) |
100 | err = -ENOENT; | 100 | err = -ENOENT; |
101 | return ERR_PTR(err); | 101 | return ERR_PTR(err); |
102 | } | 102 | } |
103 | 103 | ||
104 | logfs_inode_setops(inode); | 104 | logfs_inode_setops(inode); |
105 | unlock_new_inode(inode); | 105 | unlock_new_inode(inode); |
106 | return inode; | 106 | return inode; |
107 | } | 107 | } |
108 | 108 | ||
109 | struct inode *logfs_iget(struct super_block *sb, ino_t ino) | 109 | struct inode *logfs_iget(struct super_block *sb, ino_t ino) |
110 | { | 110 | { |
111 | BUG_ON(ino == LOGFS_INO_MASTER); | 111 | BUG_ON(ino == LOGFS_INO_MASTER); |
112 | BUG_ON(ino == LOGFS_INO_SEGFILE); | 112 | BUG_ON(ino == LOGFS_INO_SEGFILE); |
113 | return __logfs_iget(sb, ino); | 113 | return __logfs_iget(sb, ino); |
114 | } | 114 | } |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * is_cached is set to 1 if we hand out a cached inode, 0 otherwise. | 117 | * is_cached is set to 1 if we hand out a cached inode, 0 otherwise. |
118 | * this allows logfs_iput to do the right thing later | 118 | * this allows logfs_iput to do the right thing later |
119 | */ | 119 | */ |
120 | struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *is_cached) | 120 | struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *is_cached) |
121 | { | 121 | { |
122 | struct logfs_super *super = logfs_super(sb); | 122 | struct logfs_super *super = logfs_super(sb); |
123 | struct logfs_inode *li; | 123 | struct logfs_inode *li; |
124 | 124 | ||
125 | if (ino == LOGFS_INO_MASTER) | 125 | if (ino == LOGFS_INO_MASTER) |
126 | return super->s_master_inode; | 126 | return super->s_master_inode; |
127 | if (ino == LOGFS_INO_SEGFILE) | 127 | if (ino == LOGFS_INO_SEGFILE) |
128 | return super->s_segfile_inode; | 128 | return super->s_segfile_inode; |
129 | 129 | ||
130 | spin_lock(&logfs_inode_lock); | 130 | spin_lock(&logfs_inode_lock); |
131 | list_for_each_entry(li, &super->s_freeing_list, li_freeing_list) | 131 | list_for_each_entry(li, &super->s_freeing_list, li_freeing_list) |
132 | if (li->vfs_inode.i_ino == ino) { | 132 | if (li->vfs_inode.i_ino == ino) { |
133 | li->li_refcount++; | 133 | li->li_refcount++; |
134 | spin_unlock(&logfs_inode_lock); | 134 | spin_unlock(&logfs_inode_lock); |
135 | *is_cached = 1; | 135 | *is_cached = 1; |
136 | return &li->vfs_inode; | 136 | return &li->vfs_inode; |
137 | } | 137 | } |
138 | spin_unlock(&logfs_inode_lock); | 138 | spin_unlock(&logfs_inode_lock); |
139 | 139 | ||
140 | *is_cached = 0; | 140 | *is_cached = 0; |
141 | return __logfs_iget(sb, ino); | 141 | return __logfs_iget(sb, ino); |
142 | } | 142 | } |
143 | 143 | ||
144 | static void logfs_i_callback(struct rcu_head *head) | 144 | static void logfs_i_callback(struct rcu_head *head) |
145 | { | 145 | { |
146 | struct inode *inode = container_of(head, struct inode, i_rcu); | 146 | struct inode *inode = container_of(head, struct inode, i_rcu); |
147 | kmem_cache_free(logfs_inode_cache, logfs_inode(inode)); | 147 | kmem_cache_free(logfs_inode_cache, logfs_inode(inode)); |
148 | } | 148 | } |
149 | 149 | ||
150 | static void __logfs_destroy_inode(struct inode *inode) | 150 | static void __logfs_destroy_inode(struct inode *inode) |
151 | { | 151 | { |
152 | struct logfs_inode *li = logfs_inode(inode); | 152 | struct logfs_inode *li = logfs_inode(inode); |
153 | 153 | ||
154 | BUG_ON(li->li_block); | 154 | BUG_ON(li->li_block); |
155 | list_del(&li->li_freeing_list); | 155 | list_del(&li->li_freeing_list); |
156 | call_rcu(&inode->i_rcu, logfs_i_callback); | 156 | call_rcu(&inode->i_rcu, logfs_i_callback); |
157 | } | 157 | } |
158 | 158 | ||
159 | static void logfs_destroy_inode(struct inode *inode) | 159 | static void logfs_destroy_inode(struct inode *inode) |
160 | { | 160 | { |
161 | struct logfs_inode *li = logfs_inode(inode); | 161 | struct logfs_inode *li = logfs_inode(inode); |
162 | 162 | ||
163 | BUG_ON(list_empty(&li->li_freeing_list)); | 163 | BUG_ON(list_empty(&li->li_freeing_list)); |
164 | spin_lock(&logfs_inode_lock); | 164 | spin_lock(&logfs_inode_lock); |
165 | li->li_refcount--; | 165 | li->li_refcount--; |
166 | if (li->li_refcount == 0) | 166 | if (li->li_refcount == 0) |
167 | __logfs_destroy_inode(inode); | 167 | __logfs_destroy_inode(inode); |
168 | spin_unlock(&logfs_inode_lock); | 168 | spin_unlock(&logfs_inode_lock); |
169 | } | 169 | } |
170 | 170 | ||
171 | void logfs_safe_iput(struct inode *inode, int is_cached) | 171 | void logfs_safe_iput(struct inode *inode, int is_cached) |
172 | { | 172 | { |
173 | if (inode->i_ino == LOGFS_INO_MASTER) | 173 | if (inode->i_ino == LOGFS_INO_MASTER) |
174 | return; | 174 | return; |
175 | if (inode->i_ino == LOGFS_INO_SEGFILE) | 175 | if (inode->i_ino == LOGFS_INO_SEGFILE) |
176 | return; | 176 | return; |
177 | 177 | ||
178 | if (is_cached) { | 178 | if (is_cached) { |
179 | logfs_destroy_inode(inode); | 179 | logfs_destroy_inode(inode); |
180 | return; | 180 | return; |
181 | } | 181 | } |
182 | 182 | ||
183 | iput(inode); | 183 | iput(inode); |
184 | } | 184 | } |
185 | 185 | ||
186 | static void logfs_init_inode(struct super_block *sb, struct inode *inode) | 186 | static void logfs_init_inode(struct super_block *sb, struct inode *inode) |
187 | { | 187 | { |
188 | struct logfs_inode *li = logfs_inode(inode); | 188 | struct logfs_inode *li = logfs_inode(inode); |
189 | int i; | 189 | int i; |
190 | 190 | ||
191 | li->li_flags = 0; | 191 | li->li_flags = 0; |
192 | li->li_height = 0; | 192 | li->li_height = 0; |
193 | li->li_used_bytes = 0; | 193 | li->li_used_bytes = 0; |
194 | li->li_block = NULL; | 194 | li->li_block = NULL; |
195 | inode->i_uid = 0; | 195 | inode->i_uid = 0; |
196 | inode->i_gid = 0; | 196 | inode->i_gid = 0; |
197 | inode->i_size = 0; | 197 | inode->i_size = 0; |
198 | inode->i_blocks = 0; | 198 | inode->i_blocks = 0; |
199 | inode->i_ctime = CURRENT_TIME; | 199 | inode->i_ctime = CURRENT_TIME; |
200 | inode->i_mtime = CURRENT_TIME; | 200 | inode->i_mtime = CURRENT_TIME; |
201 | li->li_refcount = 1; | 201 | li->li_refcount = 1; |
202 | INIT_LIST_HEAD(&li->li_freeing_list); | 202 | INIT_LIST_HEAD(&li->li_freeing_list); |
203 | 203 | ||
204 | for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) | 204 | for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) |
205 | li->li_data[i] = 0; | 205 | li->li_data[i] = 0; |
206 | 206 | ||
207 | return; | 207 | return; |
208 | } | 208 | } |
209 | 209 | ||
210 | static struct inode *logfs_alloc_inode(struct super_block *sb) | 210 | static struct inode *logfs_alloc_inode(struct super_block *sb) |
211 | { | 211 | { |
212 | struct logfs_inode *li; | 212 | struct logfs_inode *li; |
213 | 213 | ||
214 | li = kmem_cache_alloc(logfs_inode_cache, GFP_NOFS); | 214 | li = kmem_cache_alloc(logfs_inode_cache, GFP_NOFS); |
215 | if (!li) | 215 | if (!li) |
216 | return NULL; | 216 | return NULL; |
217 | logfs_init_inode(sb, &li->vfs_inode); | 217 | logfs_init_inode(sb, &li->vfs_inode); |
218 | return &li->vfs_inode; | 218 | return &li->vfs_inode; |
219 | } | 219 | } |
220 | 220 | ||
221 | /* | 221 | /* |
222 | * In logfs inodes are written to an inode file. The inode file, like any | 222 | * In logfs inodes are written to an inode file. The inode file, like any |
223 | * other file, is managed with a inode. The inode file's inode, aka master | 223 | * other file, is managed with a inode. The inode file's inode, aka master |
224 | * inode, requires special handling in several respects. First, it cannot be | 224 | * inode, requires special handling in several respects. First, it cannot be |
225 | * written to the inode file, so it is stored in the journal instead. | 225 | * written to the inode file, so it is stored in the journal instead. |
226 | * | 226 | * |
227 | * Secondly, this inode cannot be written back and destroyed before all other | 227 | * Secondly, this inode cannot be written back and destroyed before all other |
228 | * inodes have been written. The ordering is important. Linux' VFS is happily | 228 | * inodes have been written. The ordering is important. Linux' VFS is happily |
229 | * unaware of the ordering constraint and would ordinarily destroy the master | 229 | * unaware of the ordering constraint and would ordinarily destroy the master |
230 | * inode at umount time while other inodes are still in use and dirty. Not | 230 | * inode at umount time while other inodes are still in use and dirty. Not |
231 | * good. | 231 | * good. |
232 | * | 232 | * |
233 | * So logfs makes sure the master inode is not written until all other inodes | 233 | * So logfs makes sure the master inode is not written until all other inodes |
234 | * have been destroyed. Sadly, this method has another side-effect. The VFS | 234 | * have been destroyed. Sadly, this method has another side-effect. The VFS |
235 | * will notice one remaining inode and print a frightening warning message. | 235 | * will notice one remaining inode and print a frightening warning message. |
236 | * Worse, it is impossible to judge whether such a warning was caused by the | 236 | * Worse, it is impossible to judge whether such a warning was caused by the |
237 | * master inode or any other inodes have leaked as well. | 237 | * master inode or any other inodes have leaked as well. |
238 | * | 238 | * |
239 | * Our attempt of solving this is with logfs_new_meta_inode() below. Its | 239 | * Our attempt of solving this is with logfs_new_meta_inode() below. Its |
240 | * purpose is to create a new inode that will not trigger the warning if such | 240 | * purpose is to create a new inode that will not trigger the warning if such |
241 | * an inode is still in use. An ugly hack, no doubt. Suggections for | 241 | * an inode is still in use. An ugly hack, no doubt. Suggections for |
242 | * improvement are welcome. | 242 | * improvement are welcome. |
243 | * | 243 | * |
244 | * AV: that's what ->put_super() is for... | 244 | * AV: that's what ->put_super() is for... |
245 | */ | 245 | */ |
246 | struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino) | 246 | struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino) |
247 | { | 247 | { |
248 | struct inode *inode; | 248 | struct inode *inode; |
249 | 249 | ||
250 | inode = new_inode(sb); | 250 | inode = new_inode(sb); |
251 | if (!inode) | 251 | if (!inode) |
252 | return ERR_PTR(-ENOMEM); | 252 | return ERR_PTR(-ENOMEM); |
253 | 253 | ||
254 | inode->i_mode = S_IFREG; | 254 | inode->i_mode = S_IFREG; |
255 | inode->i_ino = ino; | 255 | inode->i_ino = ino; |
256 | inode->i_data.a_ops = &logfs_reg_aops; | 256 | inode->i_data.a_ops = &logfs_reg_aops; |
257 | mapping_set_gfp_mask(&inode->i_data, GFP_NOFS); | 257 | mapping_set_gfp_mask(&inode->i_data, GFP_NOFS); |
258 | 258 | ||
259 | return inode; | 259 | return inode; |
260 | } | 260 | } |
261 | 261 | ||
262 | struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino) | 262 | struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino) |
263 | { | 263 | { |
264 | struct inode *inode; | 264 | struct inode *inode; |
265 | int err; | 265 | int err; |
266 | 266 | ||
267 | inode = logfs_new_meta_inode(sb, ino); | 267 | inode = logfs_new_meta_inode(sb, ino); |
268 | if (IS_ERR(inode)) | 268 | if (IS_ERR(inode)) |
269 | return inode; | 269 | return inode; |
270 | 270 | ||
271 | err = logfs_read_inode(inode); | 271 | err = logfs_read_inode(inode); |
272 | if (err) { | 272 | if (err) { |
273 | iput(inode); | 273 | iput(inode); |
274 | return ERR_PTR(err); | 274 | return ERR_PTR(err); |
275 | } | 275 | } |
276 | logfs_inode_setops(inode); | 276 | logfs_inode_setops(inode); |
277 | return inode; | 277 | return inode; |
278 | } | 278 | } |
279 | 279 | ||
280 | static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) | 280 | static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) |
281 | { | 281 | { |
282 | int ret; | 282 | int ret; |
283 | long flags = WF_LOCK; | 283 | long flags = WF_LOCK; |
284 | 284 | ||
285 | /* Can only happen if creat() failed. Safe to skip. */ | 285 | /* Can only happen if creat() failed. Safe to skip. */ |
286 | if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) | 286 | if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) |
287 | return 0; | 287 | return 0; |
288 | 288 | ||
289 | ret = __logfs_write_inode(inode, flags); | 289 | ret = __logfs_write_inode(inode, flags); |
290 | LOGFS_BUG_ON(ret, inode->i_sb); | 290 | LOGFS_BUG_ON(ret, inode->i_sb); |
291 | return ret; | 291 | return ret; |
292 | } | 292 | } |
293 | 293 | ||
294 | /* called with inode->i_lock held */ | 294 | /* called with inode->i_lock held */ |
295 | static int logfs_drop_inode(struct inode *inode) | 295 | static int logfs_drop_inode(struct inode *inode) |
296 | { | 296 | { |
297 | struct logfs_super *super = logfs_super(inode->i_sb); | 297 | struct logfs_super *super = logfs_super(inode->i_sb); |
298 | struct logfs_inode *li = logfs_inode(inode); | 298 | struct logfs_inode *li = logfs_inode(inode); |
299 | 299 | ||
300 | spin_lock(&logfs_inode_lock); | 300 | spin_lock(&logfs_inode_lock); |
301 | list_move(&li->li_freeing_list, &super->s_freeing_list); | 301 | list_move(&li->li_freeing_list, &super->s_freeing_list); |
302 | spin_unlock(&logfs_inode_lock); | 302 | spin_unlock(&logfs_inode_lock); |
303 | return generic_drop_inode(inode); | 303 | return generic_drop_inode(inode); |
304 | } | 304 | } |
305 | 305 | ||
306 | static void logfs_set_ino_generation(struct super_block *sb, | 306 | static void logfs_set_ino_generation(struct super_block *sb, |
307 | struct inode *inode) | 307 | struct inode *inode) |
308 | { | 308 | { |
309 | struct logfs_super *super = logfs_super(sb); | 309 | struct logfs_super *super = logfs_super(sb); |
310 | u64 ino; | 310 | u64 ino; |
311 | 311 | ||
312 | mutex_lock(&super->s_journal_mutex); | 312 | mutex_lock(&super->s_journal_mutex); |
313 | ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1); | 313 | ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1); |
314 | super->s_last_ino = ino; | 314 | super->s_last_ino = ino; |
315 | super->s_inos_till_wrap--; | 315 | super->s_inos_till_wrap--; |
316 | if (super->s_inos_till_wrap < 0) { | 316 | if (super->s_inos_till_wrap < 0) { |
317 | super->s_last_ino = LOGFS_RESERVED_INOS; | 317 | super->s_last_ino = LOGFS_RESERVED_INOS; |
318 | super->s_generation++; | 318 | super->s_generation++; |
319 | super->s_inos_till_wrap = INOS_PER_WRAP; | 319 | super->s_inos_till_wrap = INOS_PER_WRAP; |
320 | } | 320 | } |
321 | inode->i_ino = ino; | 321 | inode->i_ino = ino; |
322 | inode->i_generation = super->s_generation; | 322 | inode->i_generation = super->s_generation; |
323 | mutex_unlock(&super->s_journal_mutex); | 323 | mutex_unlock(&super->s_journal_mutex); |
324 | } | 324 | } |
325 | 325 | ||
326 | struct inode *logfs_new_inode(struct inode *dir, int mode) | 326 | struct inode *logfs_new_inode(struct inode *dir, umode_t mode) |
327 | { | 327 | { |
328 | struct super_block *sb = dir->i_sb; | 328 | struct super_block *sb = dir->i_sb; |
329 | struct inode *inode; | 329 | struct inode *inode; |
330 | 330 | ||
331 | inode = new_inode(sb); | 331 | inode = new_inode(sb); |
332 | if (!inode) | 332 | if (!inode) |
333 | return ERR_PTR(-ENOMEM); | 333 | return ERR_PTR(-ENOMEM); |
334 | 334 | ||
335 | logfs_init_inode(sb, inode); | 335 | logfs_init_inode(sb, inode); |
336 | 336 | ||
337 | /* inherit parent flags */ | 337 | /* inherit parent flags */ |
338 | logfs_inode(inode)->li_flags |= | 338 | logfs_inode(inode)->li_flags |= |
339 | logfs_inode(dir)->li_flags & LOGFS_FL_INHERITED; | 339 | logfs_inode(dir)->li_flags & LOGFS_FL_INHERITED; |
340 | 340 | ||
341 | inode->i_mode = mode; | 341 | inode->i_mode = mode; |
342 | logfs_set_ino_generation(sb, inode); | 342 | logfs_set_ino_generation(sb, inode); |
343 | 343 | ||
344 | inode_init_owner(inode, dir, mode); | 344 | inode_init_owner(inode, dir, mode); |
345 | logfs_inode_setops(inode); | 345 | logfs_inode_setops(inode); |
346 | insert_inode_hash(inode); | 346 | insert_inode_hash(inode); |
347 | 347 | ||
348 | return inode; | 348 | return inode; |
349 | } | 349 | } |
350 | 350 | ||
351 | static void logfs_init_once(void *_li) | 351 | static void logfs_init_once(void *_li) |
352 | { | 352 | { |
353 | struct logfs_inode *li = _li; | 353 | struct logfs_inode *li = _li; |
354 | int i; | 354 | int i; |
355 | 355 | ||
356 | li->li_flags = 0; | 356 | li->li_flags = 0; |
357 | li->li_used_bytes = 0; | 357 | li->li_used_bytes = 0; |
358 | li->li_refcount = 1; | 358 | li->li_refcount = 1; |
359 | for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) | 359 | for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) |
360 | li->li_data[i] = 0; | 360 | li->li_data[i] = 0; |
361 | inode_init_once(&li->vfs_inode); | 361 | inode_init_once(&li->vfs_inode); |
362 | } | 362 | } |
363 | 363 | ||
364 | static int logfs_sync_fs(struct super_block *sb, int wait) | 364 | static int logfs_sync_fs(struct super_block *sb, int wait) |
365 | { | 365 | { |
366 | logfs_write_anchor(sb); | 366 | logfs_write_anchor(sb); |
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | static void logfs_put_super(struct super_block *sb) | 370 | static void logfs_put_super(struct super_block *sb) |
371 | { | 371 | { |
372 | struct logfs_super *super = logfs_super(sb); | 372 | struct logfs_super *super = logfs_super(sb); |
373 | /* kill the meta-inodes */ | 373 | /* kill the meta-inodes */ |
374 | iput(super->s_master_inode); | 374 | iput(super->s_master_inode); |
375 | iput(super->s_segfile_inode); | 375 | iput(super->s_segfile_inode); |
376 | iput(super->s_mapping_inode); | 376 | iput(super->s_mapping_inode); |
377 | } | 377 | } |
378 | 378 | ||
379 | const struct super_operations logfs_super_operations = { | 379 | const struct super_operations logfs_super_operations = { |
380 | .alloc_inode = logfs_alloc_inode, | 380 | .alloc_inode = logfs_alloc_inode, |
381 | .destroy_inode = logfs_destroy_inode, | 381 | .destroy_inode = logfs_destroy_inode, |
382 | .evict_inode = logfs_evict_inode, | 382 | .evict_inode = logfs_evict_inode, |
383 | .drop_inode = logfs_drop_inode, | 383 | .drop_inode = logfs_drop_inode, |
384 | .put_super = logfs_put_super, | 384 | .put_super = logfs_put_super, |
385 | .write_inode = logfs_write_inode, | 385 | .write_inode = logfs_write_inode, |
386 | .statfs = logfs_statfs, | 386 | .statfs = logfs_statfs, |
387 | .sync_fs = logfs_sync_fs, | 387 | .sync_fs = logfs_sync_fs, |
388 | }; | 388 | }; |
389 | 389 | ||
390 | int logfs_init_inode_cache(void) | 390 | int logfs_init_inode_cache(void) |
391 | { | 391 | { |
392 | logfs_inode_cache = kmem_cache_create("logfs_inode_cache", | 392 | logfs_inode_cache = kmem_cache_create("logfs_inode_cache", |
393 | sizeof(struct logfs_inode), 0, SLAB_RECLAIM_ACCOUNT, | 393 | sizeof(struct logfs_inode), 0, SLAB_RECLAIM_ACCOUNT, |
394 | logfs_init_once); | 394 | logfs_init_once); |
395 | if (!logfs_inode_cache) | 395 | if (!logfs_inode_cache) |
396 | return -ENOMEM; | 396 | return -ENOMEM; |
397 | return 0; | 397 | return 0; |
398 | } | 398 | } |
399 | 399 | ||
400 | void logfs_destroy_inode_cache(void) | 400 | void logfs_destroy_inode_cache(void) |
401 | { | 401 | { |
402 | kmem_cache_destroy(logfs_inode_cache); | 402 | kmem_cache_destroy(logfs_inode_cache); |
403 | } | 403 | } |
404 | 404 |
fs/logfs/logfs.h
1 | /* | 1 | /* |
2 | * fs/logfs/logfs.h | 2 | * fs/logfs/logfs.h |
3 | * | 3 | * |
4 | * As should be obvious for Linux kernel code, license is GPLv2 | 4 | * As should be obvious for Linux kernel code, license is GPLv2 |
5 | * | 5 | * |
6 | * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> | 6 | * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> |
7 | * | 7 | * |
8 | * Private header for logfs. | 8 | * Private header for logfs. |
9 | */ | 9 | */ |
10 | #ifndef FS_LOGFS_LOGFS_H | 10 | #ifndef FS_LOGFS_LOGFS_H |
11 | #define FS_LOGFS_LOGFS_H | 11 | #define FS_LOGFS_LOGFS_H |
12 | 12 | ||
13 | #undef __CHECK_ENDIAN__ | 13 | #undef __CHECK_ENDIAN__ |
14 | #define __CHECK_ENDIAN__ | 14 | #define __CHECK_ENDIAN__ |
15 | 15 | ||
16 | #include <linux/btree.h> | 16 | #include <linux/btree.h> |
17 | #include <linux/crc32.h> | 17 | #include <linux/crc32.h> |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/mempool.h> | 20 | #include <linux/mempool.h> |
21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
22 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/mtd.h> |
23 | #include "logfs_abi.h" | 23 | #include "logfs_abi.h" |
24 | 24 | ||
25 | #define LOGFS_DEBUG_SUPER (0x0001) | 25 | #define LOGFS_DEBUG_SUPER (0x0001) |
26 | #define LOGFS_DEBUG_SEGMENT (0x0002) | 26 | #define LOGFS_DEBUG_SEGMENT (0x0002) |
27 | #define LOGFS_DEBUG_JOURNAL (0x0004) | 27 | #define LOGFS_DEBUG_JOURNAL (0x0004) |
28 | #define LOGFS_DEBUG_DIR (0x0008) | 28 | #define LOGFS_DEBUG_DIR (0x0008) |
29 | #define LOGFS_DEBUG_FILE (0x0010) | 29 | #define LOGFS_DEBUG_FILE (0x0010) |
30 | #define LOGFS_DEBUG_INODE (0x0020) | 30 | #define LOGFS_DEBUG_INODE (0x0020) |
31 | #define LOGFS_DEBUG_READWRITE (0x0040) | 31 | #define LOGFS_DEBUG_READWRITE (0x0040) |
32 | #define LOGFS_DEBUG_GC (0x0080) | 32 | #define LOGFS_DEBUG_GC (0x0080) |
33 | #define LOGFS_DEBUG_GC_NOISY (0x0100) | 33 | #define LOGFS_DEBUG_GC_NOISY (0x0100) |
34 | #define LOGFS_DEBUG_ALIASES (0x0200) | 34 | #define LOGFS_DEBUG_ALIASES (0x0200) |
35 | #define LOGFS_DEBUG_BLOCKMOVE (0x0400) | 35 | #define LOGFS_DEBUG_BLOCKMOVE (0x0400) |
36 | #define LOGFS_DEBUG_ALL (0xffffffff) | 36 | #define LOGFS_DEBUG_ALL (0xffffffff) |
37 | 37 | ||
38 | #define LOGFS_DEBUG (0x01) | 38 | #define LOGFS_DEBUG (0x01) |
39 | /* | 39 | /* |
40 | * To enable specific log messages, simply define LOGFS_DEBUG to match any | 40 | * To enable specific log messages, simply define LOGFS_DEBUG to match any |
41 | * or all of the above. | 41 | * or all of the above. |
42 | */ | 42 | */ |
43 | #ifndef LOGFS_DEBUG | 43 | #ifndef LOGFS_DEBUG |
44 | #define LOGFS_DEBUG (0) | 44 | #define LOGFS_DEBUG (0) |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #define log_cond(cond, fmt, arg...) do { \ | 47 | #define log_cond(cond, fmt, arg...) do { \ |
48 | if (cond) \ | 48 | if (cond) \ |
49 | printk(KERN_DEBUG fmt, ##arg); \ | 49 | printk(KERN_DEBUG fmt, ##arg); \ |
50 | } while (0) | 50 | } while (0) |
51 | 51 | ||
52 | #define log_super(fmt, arg...) \ | 52 | #define log_super(fmt, arg...) \ |
53 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SUPER, fmt, ##arg) | 53 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SUPER, fmt, ##arg) |
54 | #define log_segment(fmt, arg...) \ | 54 | #define log_segment(fmt, arg...) \ |
55 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SEGMENT, fmt, ##arg) | 55 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SEGMENT, fmt, ##arg) |
56 | #define log_journal(fmt, arg...) \ | 56 | #define log_journal(fmt, arg...) \ |
57 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_JOURNAL, fmt, ##arg) | 57 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_JOURNAL, fmt, ##arg) |
58 | #define log_dir(fmt, arg...) \ | 58 | #define log_dir(fmt, arg...) \ |
59 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_DIR, fmt, ##arg) | 59 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_DIR, fmt, ##arg) |
60 | #define log_file(fmt, arg...) \ | 60 | #define log_file(fmt, arg...) \ |
61 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_FILE, fmt, ##arg) | 61 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_FILE, fmt, ##arg) |
62 | #define log_inode(fmt, arg...) \ | 62 | #define log_inode(fmt, arg...) \ |
63 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_INODE, fmt, ##arg) | 63 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_INODE, fmt, ##arg) |
64 | #define log_readwrite(fmt, arg...) \ | 64 | #define log_readwrite(fmt, arg...) \ |
65 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_READWRITE, fmt, ##arg) | 65 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_READWRITE, fmt, ##arg) |
66 | #define log_gc(fmt, arg...) \ | 66 | #define log_gc(fmt, arg...) \ |
67 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC, fmt, ##arg) | 67 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC, fmt, ##arg) |
68 | #define log_gc_noisy(fmt, arg...) \ | 68 | #define log_gc_noisy(fmt, arg...) \ |
69 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC_NOISY, fmt, ##arg) | 69 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC_NOISY, fmt, ##arg) |
70 | #define log_aliases(fmt, arg...) \ | 70 | #define log_aliases(fmt, arg...) \ |
71 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_ALIASES, fmt, ##arg) | 71 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_ALIASES, fmt, ##arg) |
72 | #define log_blockmove(fmt, arg...) \ | 72 | #define log_blockmove(fmt, arg...) \ |
73 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_BLOCKMOVE, fmt, ##arg) | 73 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_BLOCKMOVE, fmt, ##arg) |
74 | 74 | ||
75 | #define PG_pre_locked PG_owner_priv_1 | 75 | #define PG_pre_locked PG_owner_priv_1 |
76 | #define PagePreLocked(page) test_bit(PG_pre_locked, &(page)->flags) | 76 | #define PagePreLocked(page) test_bit(PG_pre_locked, &(page)->flags) |
77 | #define SetPagePreLocked(page) set_bit(PG_pre_locked, &(page)->flags) | 77 | #define SetPagePreLocked(page) set_bit(PG_pre_locked, &(page)->flags) |
78 | #define ClearPagePreLocked(page) clear_bit(PG_pre_locked, &(page)->flags) | 78 | #define ClearPagePreLocked(page) clear_bit(PG_pre_locked, &(page)->flags) |
79 | 79 | ||
80 | /* FIXME: This should really be somewhere in the 64bit area. */ | 80 | /* FIXME: This should really be somewhere in the 64bit area. */ |
81 | #define LOGFS_LINK_MAX (1<<30) | 81 | #define LOGFS_LINK_MAX (1<<30) |
82 | 82 | ||
83 | /* Read-only filesystem */ | 83 | /* Read-only filesystem */ |
84 | #define LOGFS_SB_FLAG_RO 0x0001 | 84 | #define LOGFS_SB_FLAG_RO 0x0001 |
85 | #define LOGFS_SB_FLAG_DIRTY 0x0002 | 85 | #define LOGFS_SB_FLAG_DIRTY 0x0002 |
86 | #define LOGFS_SB_FLAG_OBJ_ALIAS 0x0004 | 86 | #define LOGFS_SB_FLAG_OBJ_ALIAS 0x0004 |
87 | #define LOGFS_SB_FLAG_SHUTDOWN 0x0008 | 87 | #define LOGFS_SB_FLAG_SHUTDOWN 0x0008 |
88 | 88 | ||
89 | /* Write Control Flags */ | 89 | /* Write Control Flags */ |
90 | #define WF_LOCK 0x01 /* take write lock */ | 90 | #define WF_LOCK 0x01 /* take write lock */ |
91 | #define WF_WRITE 0x02 /* write block */ | 91 | #define WF_WRITE 0x02 /* write block */ |
92 | #define WF_DELETE 0x04 /* delete old block */ | 92 | #define WF_DELETE 0x04 /* delete old block */ |
93 | 93 | ||
94 | typedef u8 __bitwise level_t; | 94 | typedef u8 __bitwise level_t; |
95 | typedef u8 __bitwise gc_level_t; | 95 | typedef u8 __bitwise gc_level_t; |
96 | 96 | ||
97 | #define LEVEL(level) ((__force level_t)(level)) | 97 | #define LEVEL(level) ((__force level_t)(level)) |
98 | #define GC_LEVEL(gc_level) ((__force gc_level_t)(gc_level)) | 98 | #define GC_LEVEL(gc_level) ((__force gc_level_t)(gc_level)) |
99 | 99 | ||
100 | #define SUBLEVEL(level) ( (void)((level) == LEVEL(1)), \ | 100 | #define SUBLEVEL(level) ( (void)((level) == LEVEL(1)), \ |
101 | (__force level_t)((__force u8)(level) - 1) ) | 101 | (__force level_t)((__force u8)(level) - 1) ) |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * struct logfs_area - area management information | 104 | * struct logfs_area - area management information |
105 | * | 105 | * |
106 | * @a_sb: the superblock this area belongs to | 106 | * @a_sb: the superblock this area belongs to |
107 | * @a_is_open: 1 if the area is currently open, else 0 | 107 | * @a_is_open: 1 if the area is currently open, else 0 |
108 | * @a_segno: segment number of area | 108 | * @a_segno: segment number of area |
109 | * @a_written_bytes: number of bytes already written back | 109 | * @a_written_bytes: number of bytes already written back |
110 | * @a_used_bytes: number of used bytes | 110 | * @a_used_bytes: number of used bytes |
111 | * @a_ops: area operations (either journal or ostore) | 111 | * @a_ops: area operations (either journal or ostore) |
112 | * @a_erase_count: erase count | 112 | * @a_erase_count: erase count |
113 | * @a_level: GC level | 113 | * @a_level: GC level |
114 | */ | 114 | */ |
115 | struct logfs_area { /* a segment open for writing */ | 115 | struct logfs_area { /* a segment open for writing */ |
116 | struct super_block *a_sb; | 116 | struct super_block *a_sb; |
117 | int a_is_open; | 117 | int a_is_open; |
118 | u32 a_segno; | 118 | u32 a_segno; |
119 | u32 a_written_bytes; | 119 | u32 a_written_bytes; |
120 | u32 a_used_bytes; | 120 | u32 a_used_bytes; |
121 | const struct logfs_area_ops *a_ops; | 121 | const struct logfs_area_ops *a_ops; |
122 | u32 a_erase_count; | 122 | u32 a_erase_count; |
123 | gc_level_t a_level; | 123 | gc_level_t a_level; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | /** | 126 | /** |
127 | * struct logfs_area_ops - area operations | 127 | * struct logfs_area_ops - area operations |
128 | * | 128 | * |
129 | * @get_free_segment: fill area->ofs with the offset of a free segment | 129 | * @get_free_segment: fill area->ofs with the offset of a free segment |
130 | * @get_erase_count: fill area->erase_count (needs area->ofs) | 130 | * @get_erase_count: fill area->erase_count (needs area->ofs) |
131 | * @erase_segment: erase and setup segment | 131 | * @erase_segment: erase and setup segment |
132 | */ | 132 | */ |
133 | struct logfs_area_ops { | 133 | struct logfs_area_ops { |
134 | void (*get_free_segment)(struct logfs_area *area); | 134 | void (*get_free_segment)(struct logfs_area *area); |
135 | void (*get_erase_count)(struct logfs_area *area); | 135 | void (*get_erase_count)(struct logfs_area *area); |
136 | int (*erase_segment)(struct logfs_area *area); | 136 | int (*erase_segment)(struct logfs_area *area); |
137 | }; | 137 | }; |
138 | 138 | ||
139 | struct logfs_super; /* forward */ | 139 | struct logfs_super; /* forward */ |
140 | /** | 140 | /** |
141 | * struct logfs_device_ops - device access operations | 141 | * struct logfs_device_ops - device access operations |
142 | * | 142 | * |
143 | * @readpage: read one page (mm page) | 143 | * @readpage: read one page (mm page) |
144 | * @writeseg: write one segment. may be a partial segment | 144 | * @writeseg: write one segment. may be a partial segment |
145 | * @erase: erase one segment | 145 | * @erase: erase one segment |
146 | * @read: read from the device | 146 | * @read: read from the device |
147 | * @erase: erase part of the device | 147 | * @erase: erase part of the device |
148 | * @can_write_buf: decide whether wbuf can be written to ofs | 148 | * @can_write_buf: decide whether wbuf can be written to ofs |
149 | */ | 149 | */ |
150 | struct logfs_device_ops { | 150 | struct logfs_device_ops { |
151 | struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); | 151 | struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); |
152 | struct page *(*find_last_sb)(struct super_block *sb, u64 *ofs); | 152 | struct page *(*find_last_sb)(struct super_block *sb, u64 *ofs); |
153 | int (*write_sb)(struct super_block *sb, struct page *page); | 153 | int (*write_sb)(struct super_block *sb, struct page *page); |
154 | int (*readpage)(void *_sb, struct page *page); | 154 | int (*readpage)(void *_sb, struct page *page); |
155 | void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); | 155 | void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); |
156 | int (*erase)(struct super_block *sb, loff_t ofs, size_t len, | 156 | int (*erase)(struct super_block *sb, loff_t ofs, size_t len, |
157 | int ensure_write); | 157 | int ensure_write); |
158 | int (*can_write_buf)(struct super_block *sb, u64 ofs); | 158 | int (*can_write_buf)(struct super_block *sb, u64 ofs); |
159 | void (*sync)(struct super_block *sb); | 159 | void (*sync)(struct super_block *sb); |
160 | void (*put_device)(struct logfs_super *s); | 160 | void (*put_device)(struct logfs_super *s); |
161 | }; | 161 | }; |
162 | 162 | ||
163 | /** | 163 | /** |
164 | * struct candidate_list - list of similar candidates | 164 | * struct candidate_list - list of similar candidates |
165 | */ | 165 | */ |
166 | struct candidate_list { | 166 | struct candidate_list { |
167 | struct rb_root rb_tree; | 167 | struct rb_root rb_tree; |
168 | int count; | 168 | int count; |
169 | int maxcount; | 169 | int maxcount; |
170 | int sort_by_ec; | 170 | int sort_by_ec; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | /** | 173 | /** |
174 | * struct gc_candidate - "candidate" segment to be garbage collected next | 174 | * struct gc_candidate - "candidate" segment to be garbage collected next |
175 | * | 175 | * |
176 | * @list: list (either free of low) | 176 | * @list: list (either free of low) |
177 | * @segno: segment number | 177 | * @segno: segment number |
178 | * @valid: number of valid bytes | 178 | * @valid: number of valid bytes |
179 | * @erase_count: erase count of segment | 179 | * @erase_count: erase count of segment |
180 | * @dist: distance from tree root | 180 | * @dist: distance from tree root |
181 | * | 181 | * |
182 | * Candidates can be on two lists. The free list contains electees rather | 182 | * Candidates can be on two lists. The free list contains electees rather |
183 | * than candidates - segments that no longer contain any valid data. The | 183 | * than candidates - segments that no longer contain any valid data. The |
184 | * low list contains candidates to be picked for GC. It should be kept | 184 | * low list contains candidates to be picked for GC. It should be kept |
185 | * short. It is not required to always pick a perfect candidate. In the | 185 | * short. It is not required to always pick a perfect candidate. In the |
186 | * worst case GC will have to move more data than absolutely necessary. | 186 | * worst case GC will have to move more data than absolutely necessary. |
187 | */ | 187 | */ |
188 | struct gc_candidate { | 188 | struct gc_candidate { |
189 | struct rb_node rb_node; | 189 | struct rb_node rb_node; |
190 | struct candidate_list *list; | 190 | struct candidate_list *list; |
191 | u32 segno; | 191 | u32 segno; |
192 | u32 valid; | 192 | u32 valid; |
193 | u32 erase_count; | 193 | u32 erase_count; |
194 | u8 dist; | 194 | u8 dist; |
195 | }; | 195 | }; |
196 | 196 | ||
197 | /** | 197 | /** |
198 | * struct logfs_journal_entry - temporary structure used during journal scan | 198 | * struct logfs_journal_entry - temporary structure used during journal scan |
199 | * | 199 | * |
200 | * @used: | 200 | * @used: |
201 | * @version: normalized version | 201 | * @version: normalized version |
202 | * @len: length | 202 | * @len: length |
203 | * @offset: offset | 203 | * @offset: offset |
204 | */ | 204 | */ |
205 | struct logfs_journal_entry { | 205 | struct logfs_journal_entry { |
206 | int used; | 206 | int used; |
207 | s16 version; | 207 | s16 version; |
208 | u16 len; | 208 | u16 len; |
209 | u16 datalen; | 209 | u16 datalen; |
210 | u64 offset; | 210 | u64 offset; |
211 | }; | 211 | }; |
212 | 212 | ||
213 | enum transaction_state { | 213 | enum transaction_state { |
214 | CREATE_1 = 1, | 214 | CREATE_1 = 1, |
215 | CREATE_2, | 215 | CREATE_2, |
216 | UNLINK_1, | 216 | UNLINK_1, |
217 | UNLINK_2, | 217 | UNLINK_2, |
218 | CROSS_RENAME_1, | 218 | CROSS_RENAME_1, |
219 | CROSS_RENAME_2, | 219 | CROSS_RENAME_2, |
220 | TARGET_RENAME_1, | 220 | TARGET_RENAME_1, |
221 | TARGET_RENAME_2, | 221 | TARGET_RENAME_2, |
222 | TARGET_RENAME_3 | 222 | TARGET_RENAME_3 |
223 | }; | 223 | }; |
224 | 224 | ||
225 | /** | 225 | /** |
226 | * struct logfs_transaction - essential fields to support atomic dirops | 226 | * struct logfs_transaction - essential fields to support atomic dirops |
227 | * | 227 | * |
228 | * @ino: target inode | 228 | * @ino: target inode |
229 | * @dir: inode of directory containing dentry | 229 | * @dir: inode of directory containing dentry |
230 | * @pos: pos of dentry in directory | 230 | * @pos: pos of dentry in directory |
231 | */ | 231 | */ |
232 | struct logfs_transaction { | 232 | struct logfs_transaction { |
233 | enum transaction_state state; | 233 | enum transaction_state state; |
234 | u64 ino; | 234 | u64 ino; |
235 | u64 dir; | 235 | u64 dir; |
236 | u64 pos; | 236 | u64 pos; |
237 | }; | 237 | }; |
238 | 238 | ||
239 | /** | 239 | /** |
240 | * struct logfs_shadow - old block in the shadow of a not-yet-committed new one | 240 | * struct logfs_shadow - old block in the shadow of a not-yet-committed new one |
241 | * @old_ofs: offset of old block on medium | 241 | * @old_ofs: offset of old block on medium |
242 | * @new_ofs: offset of new block on medium | 242 | * @new_ofs: offset of new block on medium |
243 | * @ino: inode number | 243 | * @ino: inode number |
244 | * @bix: block index | 244 | * @bix: block index |
245 | * @old_len: size of old block, including header | 245 | * @old_len: size of old block, including header |
246 | * @new_len: size of new block, including header | 246 | * @new_len: size of new block, including header |
247 | * @level: block level | 247 | * @level: block level |
248 | */ | 248 | */ |
249 | struct logfs_shadow { | 249 | struct logfs_shadow { |
250 | u64 old_ofs; | 250 | u64 old_ofs; |
251 | u64 new_ofs; | 251 | u64 new_ofs; |
252 | u64 ino; | 252 | u64 ino; |
253 | u64 bix; | 253 | u64 bix; |
254 | int old_len; | 254 | int old_len; |
255 | int new_len; | 255 | int new_len; |
256 | gc_level_t gc_level; | 256 | gc_level_t gc_level; |
257 | }; | 257 | }; |
258 | 258 | ||
259 | /** | 259 | /** |
260 | * struct shadow_tree | 260 | * struct shadow_tree |
261 | * @new: shadows where old_ofs==0, indexed by new_ofs | 261 | * @new: shadows where old_ofs==0, indexed by new_ofs |
262 | * @old: shadows where old_ofs!=0, indexed by old_ofs | 262 | * @old: shadows where old_ofs!=0, indexed by old_ofs |
263 | * @segment_map: bitfield of segments containing shadows | 263 | * @segment_map: bitfield of segments containing shadows |
264 | * @no_shadowed_segment: number of segments containing shadows | 264 | * @no_shadowed_segment: number of segments containing shadows |
265 | */ | 265 | */ |
266 | struct shadow_tree { | 266 | struct shadow_tree { |
267 | struct btree_head64 new; | 267 | struct btree_head64 new; |
268 | struct btree_head64 old; | 268 | struct btree_head64 old; |
269 | struct btree_head32 segment_map; | 269 | struct btree_head32 segment_map; |
270 | int no_shadowed_segments; | 270 | int no_shadowed_segments; |
271 | }; | 271 | }; |
272 | 272 | ||
273 | struct object_alias_item { | 273 | struct object_alias_item { |
274 | struct list_head list; | 274 | struct list_head list; |
275 | __be64 val; | 275 | __be64 val; |
276 | int child_no; | 276 | int child_no; |
277 | }; | 277 | }; |
278 | 278 | ||
279 | /** | 279 | /** |
280 | * struct logfs_block - contains any block state | 280 | * struct logfs_block - contains any block state |
281 | * @type: indirect block or inode | 281 | * @type: indirect block or inode |
282 | * @full: number of fully populated children | 282 | * @full: number of fully populated children |
283 | * @partial: number of partially populated children | 283 | * @partial: number of partially populated children |
284 | * | 284 | * |
285 | * Most blocks are directly represented by page cache pages. But when a block | 285 | * Most blocks are directly represented by page cache pages. But when a block |
286 | * becomes dirty, is part of a transaction, contains aliases or is otherwise | 286 | * becomes dirty, is part of a transaction, contains aliases or is otherwise |
287 | * special, a struct logfs_block is allocated to track the additional state. | 287 | * special, a struct logfs_block is allocated to track the additional state. |
288 | * Inodes are very similar to indirect blocks, so they can also get one of | 288 | * Inodes are very similar to indirect blocks, so they can also get one of |
289 | * these structures added when appropriate. | 289 | * these structures added when appropriate. |
290 | */ | 290 | */ |
291 | #define BLOCK_INDIRECT 1 /* Indirect block */ | 291 | #define BLOCK_INDIRECT 1 /* Indirect block */ |
292 | #define BLOCK_INODE 2 /* Inode */ | 292 | #define BLOCK_INODE 2 /* Inode */ |
293 | struct logfs_block_ops; | 293 | struct logfs_block_ops; |
294 | struct logfs_block { | 294 | struct logfs_block { |
295 | struct list_head alias_list; | 295 | struct list_head alias_list; |
296 | struct list_head item_list; | 296 | struct list_head item_list; |
297 | struct super_block *sb; | 297 | struct super_block *sb; |
298 | u64 ino; | 298 | u64 ino; |
299 | u64 bix; | 299 | u64 bix; |
300 | level_t level; | 300 | level_t level; |
301 | struct page *page; | 301 | struct page *page; |
302 | struct inode *inode; | 302 | struct inode *inode; |
303 | struct logfs_transaction *ta; | 303 | struct logfs_transaction *ta; |
304 | unsigned long alias_map[LOGFS_BLOCK_FACTOR / BITS_PER_LONG]; | 304 | unsigned long alias_map[LOGFS_BLOCK_FACTOR / BITS_PER_LONG]; |
305 | struct logfs_block_ops *ops; | 305 | struct logfs_block_ops *ops; |
306 | int full; | 306 | int full; |
307 | int partial; | 307 | int partial; |
308 | int reserved_bytes; | 308 | int reserved_bytes; |
309 | }; | 309 | }; |
310 | 310 | ||
311 | typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix, | 311 | typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix, |
312 | level_t level, int child_no, __be64 val); | 312 | level_t level, int child_no, __be64 val); |
313 | struct logfs_block_ops { | 313 | struct logfs_block_ops { |
314 | void (*write_block)(struct logfs_block *block); | 314 | void (*write_block)(struct logfs_block *block); |
315 | void (*free_block)(struct super_block *sb, struct logfs_block*block); | 315 | void (*free_block)(struct super_block *sb, struct logfs_block*block); |
316 | int (*write_alias)(struct super_block *sb, | 316 | int (*write_alias)(struct super_block *sb, |
317 | struct logfs_block *block, | 317 | struct logfs_block *block, |
318 | write_alias_t *write_one_alias); | 318 | write_alias_t *write_one_alias); |
319 | }; | 319 | }; |
320 | 320 | ||
321 | #define MAX_JOURNAL_ENTRIES 256 | 321 | #define MAX_JOURNAL_ENTRIES 256 |
322 | 322 | ||
323 | struct logfs_super { | 323 | struct logfs_super { |
324 | struct mtd_info *s_mtd; /* underlying device */ | 324 | struct mtd_info *s_mtd; /* underlying device */ |
325 | struct block_device *s_bdev; /* underlying device */ | 325 | struct block_device *s_bdev; /* underlying device */ |
326 | const struct logfs_device_ops *s_devops;/* device access */ | 326 | const struct logfs_device_ops *s_devops;/* device access */ |
327 | struct inode *s_master_inode; /* inode file */ | 327 | struct inode *s_master_inode; /* inode file */ |
328 | struct inode *s_segfile_inode; /* segment file */ | 328 | struct inode *s_segfile_inode; /* segment file */ |
329 | struct inode *s_mapping_inode; /* device mapping */ | 329 | struct inode *s_mapping_inode; /* device mapping */ |
330 | atomic_t s_pending_writes; /* outstanting bios */ | 330 | atomic_t s_pending_writes; /* outstanting bios */ |
331 | long s_flags; | 331 | long s_flags; |
332 | mempool_t *s_btree_pool; /* for btree nodes */ | 332 | mempool_t *s_btree_pool; /* for btree nodes */ |
333 | mempool_t *s_alias_pool; /* aliases in segment.c */ | 333 | mempool_t *s_alias_pool; /* aliases in segment.c */ |
334 | u64 s_feature_incompat; | 334 | u64 s_feature_incompat; |
335 | u64 s_feature_ro_compat; | 335 | u64 s_feature_ro_compat; |
336 | u64 s_feature_compat; | 336 | u64 s_feature_compat; |
337 | u64 s_feature_flags; | 337 | u64 s_feature_flags; |
338 | u64 s_sb_ofs[2]; | 338 | u64 s_sb_ofs[2]; |
339 | struct page *s_erase_page; /* for dev_bdev.c */ | 339 | struct page *s_erase_page; /* for dev_bdev.c */ |
340 | /* alias.c fields */ | 340 | /* alias.c fields */ |
341 | struct btree_head32 s_segment_alias; /* remapped segments */ | 341 | struct btree_head32 s_segment_alias; /* remapped segments */ |
342 | int s_no_object_aliases; | 342 | int s_no_object_aliases; |
343 | struct list_head s_object_alias; /* remapped objects */ | 343 | struct list_head s_object_alias; /* remapped objects */ |
344 | struct btree_head128 s_object_alias_tree; /* remapped objects */ | 344 | struct btree_head128 s_object_alias_tree; /* remapped objects */ |
345 | struct mutex s_object_alias_mutex; | 345 | struct mutex s_object_alias_mutex; |
346 | /* dir.c fields */ | 346 | /* dir.c fields */ |
347 | struct mutex s_dirop_mutex; /* for creat/unlink/rename */ | 347 | struct mutex s_dirop_mutex; /* for creat/unlink/rename */ |
348 | u64 s_victim_ino; /* used for atomic dir-ops */ | 348 | u64 s_victim_ino; /* used for atomic dir-ops */ |
349 | u64 s_rename_dir; /* source directory ino */ | 349 | u64 s_rename_dir; /* source directory ino */ |
350 | u64 s_rename_pos; /* position of source dd */ | 350 | u64 s_rename_pos; /* position of source dd */ |
351 | /* gc.c fields */ | 351 | /* gc.c fields */ |
352 | long s_segsize; /* size of a segment */ | 352 | long s_segsize; /* size of a segment */ |
353 | int s_segshift; /* log2 of segment size */ | 353 | int s_segshift; /* log2 of segment size */ |
354 | long s_segmask; /* 1 << s_segshift - 1 */ | 354 | long s_segmask; /* 1 << s_segshift - 1 */ |
355 | long s_no_segs; /* segments on device */ | 355 | long s_no_segs; /* segments on device */ |
356 | long s_no_journal_segs; /* segments used for journal */ | 356 | long s_no_journal_segs; /* segments used for journal */ |
357 | long s_no_blocks; /* blocks per segment */ | 357 | long s_no_blocks; /* blocks per segment */ |
358 | long s_writesize; /* minimum write size */ | 358 | long s_writesize; /* minimum write size */ |
359 | int s_writeshift; /* log2 of write size */ | 359 | int s_writeshift; /* log2 of write size */ |
360 | u64 s_size; /* filesystem size */ | 360 | u64 s_size; /* filesystem size */ |
361 | struct logfs_area *s_area[LOGFS_NO_AREAS]; /* open segment array */ | 361 | struct logfs_area *s_area[LOGFS_NO_AREAS]; /* open segment array */ |
362 | u64 s_gec; /* global erase count */ | 362 | u64 s_gec; /* global erase count */ |
363 | u64 s_wl_gec_ostore; /* time of last wl event */ | 363 | u64 s_wl_gec_ostore; /* time of last wl event */ |
364 | u64 s_wl_gec_journal; /* time of last wl event */ | 364 | u64 s_wl_gec_journal; /* time of last wl event */ |
365 | u64 s_sweeper; /* current sweeper pos */ | 365 | u64 s_sweeper; /* current sweeper pos */ |
366 | u8 s_ifile_levels; /* max level of ifile */ | 366 | u8 s_ifile_levels; /* max level of ifile */ |
367 | u8 s_iblock_levels; /* max level of regular files */ | 367 | u8 s_iblock_levels; /* max level of regular files */ |
368 | u8 s_data_levels; /* # of segments to leaf block*/ | 368 | u8 s_data_levels; /* # of segments to leaf block*/ |
369 | u8 s_total_levels; /* sum of above three */ | 369 | u8 s_total_levels; /* sum of above three */ |
370 | struct btree_head32 s_cand_tree; /* all candidates */ | 370 | struct btree_head32 s_cand_tree; /* all candidates */ |
371 | struct candidate_list s_free_list; /* 100% free segments */ | 371 | struct candidate_list s_free_list; /* 100% free segments */ |
372 | struct candidate_list s_reserve_list; /* Bad segment reserve */ | 372 | struct candidate_list s_reserve_list; /* Bad segment reserve */ |
373 | struct candidate_list s_low_list[LOGFS_NO_AREAS];/* good candidates */ | 373 | struct candidate_list s_low_list[LOGFS_NO_AREAS];/* good candidates */ |
374 | struct candidate_list s_ec_list; /* wear level candidates */ | 374 | struct candidate_list s_ec_list; /* wear level candidates */ |
375 | struct btree_head32 s_reserved_segments;/* sb, journal, bad, etc. */ | 375 | struct btree_head32 s_reserved_segments;/* sb, journal, bad, etc. */ |
376 | /* inode.c fields */ | 376 | /* inode.c fields */ |
377 | u64 s_last_ino; /* highest ino used */ | 377 | u64 s_last_ino; /* highest ino used */ |
378 | long s_inos_till_wrap; | 378 | long s_inos_till_wrap; |
379 | u32 s_generation; /* i_generation for new files */ | 379 | u32 s_generation; /* i_generation for new files */ |
380 | struct list_head s_freeing_list; /* inodes being freed */ | 380 | struct list_head s_freeing_list; /* inodes being freed */ |
381 | /* journal.c fields */ | 381 | /* journal.c fields */ |
382 | struct mutex s_journal_mutex; | 382 | struct mutex s_journal_mutex; |
383 | void *s_je; /* journal entry to compress */ | 383 | void *s_je; /* journal entry to compress */ |
384 | void *s_compressed_je; /* block to write to journal */ | 384 | void *s_compressed_je; /* block to write to journal */ |
385 | u32 s_journal_seg[LOGFS_JOURNAL_SEGS]; /* journal segments */ | 385 | u32 s_journal_seg[LOGFS_JOURNAL_SEGS]; /* journal segments */ |
386 | u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */ | 386 | u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */ |
387 | u64 s_last_version; | 387 | u64 s_last_version; |
388 | struct logfs_area *s_journal_area; /* open journal segment */ | 388 | struct logfs_area *s_journal_area; /* open journal segment */ |
389 | __be64 s_je_array[MAX_JOURNAL_ENTRIES]; | 389 | __be64 s_je_array[MAX_JOURNAL_ENTRIES]; |
390 | int s_no_je; | 390 | int s_no_je; |
391 | 391 | ||
392 | int s_sum_index; /* for the 12 summaries */ | 392 | int s_sum_index; /* for the 12 summaries */ |
393 | struct shadow_tree s_shadow_tree; | 393 | struct shadow_tree s_shadow_tree; |
394 | int s_je_fill; /* index of current je */ | 394 | int s_je_fill; /* index of current je */ |
395 | /* readwrite.c fields */ | 395 | /* readwrite.c fields */ |
396 | struct mutex s_write_mutex; | 396 | struct mutex s_write_mutex; |
397 | int s_lock_count; | 397 | int s_lock_count; |
398 | mempool_t *s_block_pool; /* struct logfs_block pool */ | 398 | mempool_t *s_block_pool; /* struct logfs_block pool */ |
399 | mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ | 399 | mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ |
400 | struct list_head s_writeback_list; /* writeback pages */ | 400 | struct list_head s_writeback_list; /* writeback pages */ |
401 | /* | 401 | /* |
402 | * Space accounting: | 402 | * Space accounting: |
403 | * - s_used_bytes specifies space used to store valid data objects. | 403 | * - s_used_bytes specifies space used to store valid data objects. |
404 | * - s_dirty_used_bytes is space used to store non-committed data | 404 | * - s_dirty_used_bytes is space used to store non-committed data |
405 | * objects. Those objects have already been written themselves, | 405 | * objects. Those objects have already been written themselves, |
406 | * but they don't become valid until all indirect blocks up to the | 406 | * but they don't become valid until all indirect blocks up to the |
407 | * journal have been written as well. | 407 | * journal have been written as well. |
408 | * - s_dirty_free_bytes is space used to store the old copy of a | 408 | * - s_dirty_free_bytes is space used to store the old copy of a |
409 | * replaced object, as long as the replacement is non-committed. | 409 | * replaced object, as long as the replacement is non-committed. |
410 | * In other words, it is the amount of space freed when all dirty | 410 | * In other words, it is the amount of space freed when all dirty |
411 | * blocks are written back. | 411 | * blocks are written back. |
412 | * - s_free_bytes is the amount of free space available for any | 412 | * - s_free_bytes is the amount of free space available for any |
413 | * purpose. | 413 | * purpose. |
414 | * - s_root_reserve is the amount of free space available only to | 414 | * - s_root_reserve is the amount of free space available only to |
415 | * the root user. Non-privileged users can no longer write once | 415 | * the root user. Non-privileged users can no longer write once |
416 | * this watermark has been reached. | 416 | * this watermark has been reached. |
417 | * - s_speed_reserve is space which remains unused to speed up | 417 | * - s_speed_reserve is space which remains unused to speed up |
418 | * garbage collection performance. | 418 | * garbage collection performance. |
419 | * - s_dirty_pages is the space reserved for currently dirty pages. | 419 | * - s_dirty_pages is the space reserved for currently dirty pages. |
420 | * It is a pessimistic estimate, so some/most will get freed on | 420 | * It is a pessimistic estimate, so some/most will get freed on |
421 | * page writeback. | 421 | * page writeback. |
422 | * | 422 | * |
423 | * s_used_bytes + s_free_bytes + s_speed_reserve = total usable size | 423 | * s_used_bytes + s_free_bytes + s_speed_reserve = total usable size |
424 | */ | 424 | */ |
425 | u64 s_free_bytes; | 425 | u64 s_free_bytes; |
426 | u64 s_used_bytes; | 426 | u64 s_used_bytes; |
427 | u64 s_dirty_free_bytes; | 427 | u64 s_dirty_free_bytes; |
428 | u64 s_dirty_used_bytes; | 428 | u64 s_dirty_used_bytes; |
429 | u64 s_root_reserve; | 429 | u64 s_root_reserve; |
430 | u64 s_speed_reserve; | 430 | u64 s_speed_reserve; |
431 | u64 s_dirty_pages; | 431 | u64 s_dirty_pages; |
432 | /* Bad block handling: | 432 | /* Bad block handling: |
433 | * - s_bad_seg_reserve is a number of segments usually kept | 433 | * - s_bad_seg_reserve is a number of segments usually kept |
434 | * free. When encountering bad blocks, the affected segment's data | 434 | * free. When encountering bad blocks, the affected segment's data |
435 | * is _temporarily_ moved to a reserved segment. | 435 | * is _temporarily_ moved to a reserved segment. |
436 | * - s_bad_segments is the number of known bad segments. | 436 | * - s_bad_segments is the number of known bad segments. |
437 | */ | 437 | */ |
438 | u32 s_bad_seg_reserve; | 438 | u32 s_bad_seg_reserve; |
439 | u32 s_bad_segments; | 439 | u32 s_bad_segments; |
440 | }; | 440 | }; |
441 | 441 | ||
442 | /** | 442 | /** |
443 | * struct logfs_inode - in-memory inode | 443 | * struct logfs_inode - in-memory inode |
444 | * | 444 | * |
445 | * @vfs_inode: struct inode | 445 | * @vfs_inode: struct inode |
446 | * @li_data: data pointers | 446 | * @li_data: data pointers |
447 | * @li_used_bytes: number of used bytes | 447 | * @li_used_bytes: number of used bytes |
448 | * @li_freeing_list: used to track inodes currently being freed | 448 | * @li_freeing_list: used to track inodes currently being freed |
449 | * @li_flags: inode flags | 449 | * @li_flags: inode flags |
450 | * @li_refcount: number of internal (GC-induced) references | 450 | * @li_refcount: number of internal (GC-induced) references |
451 | */ | 451 | */ |
452 | struct logfs_inode { | 452 | struct logfs_inode { |
453 | struct inode vfs_inode; | 453 | struct inode vfs_inode; |
454 | u64 li_data[LOGFS_EMBEDDED_FIELDS]; | 454 | u64 li_data[LOGFS_EMBEDDED_FIELDS]; |
455 | u64 li_used_bytes; | 455 | u64 li_used_bytes; |
456 | struct list_head li_freeing_list; | 456 | struct list_head li_freeing_list; |
457 | struct logfs_block *li_block; | 457 | struct logfs_block *li_block; |
458 | u32 li_flags; | 458 | u32 li_flags; |
459 | u8 li_height; | 459 | u8 li_height; |
460 | int li_refcount; | 460 | int li_refcount; |
461 | }; | 461 | }; |
462 | 462 | ||
463 | #define journal_for_each(__i) for (__i = 0; __i < LOGFS_JOURNAL_SEGS; __i++) | 463 | #define journal_for_each(__i) for (__i = 0; __i < LOGFS_JOURNAL_SEGS; __i++) |
464 | #define for_each_area(__i) for (__i = 0; __i < LOGFS_NO_AREAS; __i++) | 464 | #define for_each_area(__i) for (__i = 0; __i < LOGFS_NO_AREAS; __i++) |
465 | #define for_each_area_down(__i) for (__i = LOGFS_NO_AREAS - 1; __i >= 0; __i--) | 465 | #define for_each_area_down(__i) for (__i = LOGFS_NO_AREAS - 1; __i >= 0; __i--) |
466 | 466 | ||
467 | /* compr.c */ | 467 | /* compr.c */ |
468 | int logfs_compress(void *in, void *out, size_t inlen, size_t outlen); | 468 | int logfs_compress(void *in, void *out, size_t inlen, size_t outlen); |
469 | int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen); | 469 | int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen); |
470 | int __init logfs_compr_init(void); | 470 | int __init logfs_compr_init(void); |
471 | void logfs_compr_exit(void); | 471 | void logfs_compr_exit(void); |
472 | 472 | ||
473 | /* dev_bdev.c */ | 473 | /* dev_bdev.c */ |
474 | #ifdef CONFIG_BLOCK | 474 | #ifdef CONFIG_BLOCK |
475 | int logfs_get_sb_bdev(struct logfs_super *s, | 475 | int logfs_get_sb_bdev(struct logfs_super *s, |
476 | struct file_system_type *type, | 476 | struct file_system_type *type, |
477 | const char *devname); | 477 | const char *devname); |
478 | #else | 478 | #else |
479 | static inline int logfs_get_sb_bdev(struct logfs_super *s, | 479 | static inline int logfs_get_sb_bdev(struct logfs_super *s, |
480 | struct file_system_type *type, | 480 | struct file_system_type *type, |
481 | const char *devname) | 481 | const char *devname) |
482 | { | 482 | { |
483 | return -ENODEV; | 483 | return -ENODEV; |
484 | } | 484 | } |
485 | #endif | 485 | #endif |
486 | 486 | ||
487 | /* dev_mtd.c */ | 487 | /* dev_mtd.c */ |
488 | #ifdef CONFIG_MTD | 488 | #ifdef CONFIG_MTD |
489 | int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr); | 489 | int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr); |
490 | #else | 490 | #else |
491 | static inline int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr) | 491 | static inline int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr) |
492 | { | 492 | { |
493 | return -ENODEV; | 493 | return -ENODEV; |
494 | } | 494 | } |
495 | #endif | 495 | #endif |
496 | 496 | ||
497 | /* dir.c */ | 497 | /* dir.c */ |
498 | extern const struct inode_operations logfs_symlink_iops; | 498 | extern const struct inode_operations logfs_symlink_iops; |
499 | extern const struct inode_operations logfs_dir_iops; | 499 | extern const struct inode_operations logfs_dir_iops; |
500 | extern const struct file_operations logfs_dir_fops; | 500 | extern const struct file_operations logfs_dir_fops; |
501 | int logfs_replay_journal(struct super_block *sb); | 501 | int logfs_replay_journal(struct super_block *sb); |
502 | 502 | ||
503 | /* file.c */ | 503 | /* file.c */ |
504 | extern const struct inode_operations logfs_reg_iops; | 504 | extern const struct inode_operations logfs_reg_iops; |
505 | extern const struct file_operations logfs_reg_fops; | 505 | extern const struct file_operations logfs_reg_fops; |
506 | extern const struct address_space_operations logfs_reg_aops; | 506 | extern const struct address_space_operations logfs_reg_aops; |
507 | int logfs_readpage(struct file *file, struct page *page); | 507 | int logfs_readpage(struct file *file, struct page *page); |
508 | long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 508 | long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
509 | int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync); | 509 | int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync); |
510 | 510 | ||
511 | /* gc.c */ | 511 | /* gc.c */ |
512 | u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec); | 512 | u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec); |
513 | void logfs_gc_pass(struct super_block *sb); | 513 | void logfs_gc_pass(struct super_block *sb); |
514 | int logfs_check_areas(struct super_block *sb); | 514 | int logfs_check_areas(struct super_block *sb); |
515 | int logfs_init_gc(struct super_block *sb); | 515 | int logfs_init_gc(struct super_block *sb); |
516 | void logfs_cleanup_gc(struct super_block *sb); | 516 | void logfs_cleanup_gc(struct super_block *sb); |
517 | 517 | ||
518 | /* inode.c */ | 518 | /* inode.c */ |
519 | extern const struct super_operations logfs_super_operations; | 519 | extern const struct super_operations logfs_super_operations; |
520 | struct inode *logfs_iget(struct super_block *sb, ino_t ino); | 520 | struct inode *logfs_iget(struct super_block *sb, ino_t ino); |
521 | struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *cookie); | 521 | struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *cookie); |
522 | void logfs_safe_iput(struct inode *inode, int cookie); | 522 | void logfs_safe_iput(struct inode *inode, int cookie); |
523 | struct inode *logfs_new_inode(struct inode *dir, int mode); | 523 | struct inode *logfs_new_inode(struct inode *dir, umode_t mode); |
524 | struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino); | 524 | struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino); |
525 | struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino); | 525 | struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino); |
526 | int logfs_init_inode_cache(void); | 526 | int logfs_init_inode_cache(void); |
527 | void logfs_destroy_inode_cache(void); | 527 | void logfs_destroy_inode_cache(void); |
528 | void logfs_set_blocks(struct inode *inode, u64 no); | 528 | void logfs_set_blocks(struct inode *inode, u64 no); |
529 | /* these logically belong into inode.c but actually reside in readwrite.c */ | 529 | /* these logically belong into inode.c but actually reside in readwrite.c */ |
530 | int logfs_read_inode(struct inode *inode); | 530 | int logfs_read_inode(struct inode *inode); |
531 | int __logfs_write_inode(struct inode *inode, long flags); | 531 | int __logfs_write_inode(struct inode *inode, long flags); |
532 | void logfs_evict_inode(struct inode *inode); | 532 | void logfs_evict_inode(struct inode *inode); |
533 | 533 | ||
534 | /* journal.c */ | 534 | /* journal.c */ |
535 | void logfs_write_anchor(struct super_block *sb); | 535 | void logfs_write_anchor(struct super_block *sb); |
536 | int logfs_init_journal(struct super_block *sb); | 536 | int logfs_init_journal(struct super_block *sb); |
537 | void logfs_cleanup_journal(struct super_block *sb); | 537 | void logfs_cleanup_journal(struct super_block *sb); |
538 | int write_alias_journal(struct super_block *sb, u64 ino, u64 bix, | 538 | int write_alias_journal(struct super_block *sb, u64 ino, u64 bix, |
539 | level_t level, int child_no, __be64 val); | 539 | level_t level, int child_no, __be64 val); |
540 | void do_logfs_journal_wl_pass(struct super_block *sb); | 540 | void do_logfs_journal_wl_pass(struct super_block *sb); |
541 | 541 | ||
542 | /* readwrite.c */ | 542 | /* readwrite.c */ |
543 | pgoff_t logfs_pack_index(u64 bix, level_t level); | 543 | pgoff_t logfs_pack_index(u64 bix, level_t level); |
544 | void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level); | 544 | void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level); |
545 | int logfs_inode_write(struct inode *inode, const void *buf, size_t count, | 545 | int logfs_inode_write(struct inode *inode, const void *buf, size_t count, |
546 | loff_t bix, long flags, struct shadow_tree *shadow_tree); | 546 | loff_t bix, long flags, struct shadow_tree *shadow_tree); |
547 | int logfs_readpage_nolock(struct page *page); | 547 | int logfs_readpage_nolock(struct page *page); |
548 | int logfs_write_buf(struct inode *inode, struct page *page, long flags); | 548 | int logfs_write_buf(struct inode *inode, struct page *page, long flags); |
549 | int logfs_delete(struct inode *inode, pgoff_t index, | 549 | int logfs_delete(struct inode *inode, pgoff_t index, |
550 | struct shadow_tree *shadow_tree); | 550 | struct shadow_tree *shadow_tree); |
551 | int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, | 551 | int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, |
552 | gc_level_t gc_level, long flags); | 552 | gc_level_t gc_level, long flags); |
553 | int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix, | 553 | int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix, |
554 | gc_level_t gc_level); | 554 | gc_level_t gc_level); |
555 | int logfs_truncate(struct inode *inode, u64 size); | 555 | int logfs_truncate(struct inode *inode, u64 size); |
556 | u64 logfs_seek_hole(struct inode *inode, u64 bix); | 556 | u64 logfs_seek_hole(struct inode *inode, u64 bix); |
557 | u64 logfs_seek_data(struct inode *inode, u64 bix); | 557 | u64 logfs_seek_data(struct inode *inode, u64 bix); |
558 | int logfs_open_segfile(struct super_block *sb); | 558 | int logfs_open_segfile(struct super_block *sb); |
559 | int logfs_init_rw(struct super_block *sb); | 559 | int logfs_init_rw(struct super_block *sb); |
560 | void logfs_cleanup_rw(struct super_block *sb); | 560 | void logfs_cleanup_rw(struct super_block *sb); |
561 | void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta); | 561 | void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta); |
562 | void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta); | 562 | void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta); |
563 | void logfs_write_block(struct logfs_block *block, long flags); | 563 | void logfs_write_block(struct logfs_block *block, long flags); |
564 | int logfs_write_obj_aliases_pagecache(struct super_block *sb); | 564 | int logfs_write_obj_aliases_pagecache(struct super_block *sb); |
565 | void logfs_get_segment_entry(struct super_block *sb, u32 segno, | 565 | void logfs_get_segment_entry(struct super_block *sb, u32 segno, |
566 | struct logfs_segment_entry *se); | 566 | struct logfs_segment_entry *se); |
567 | void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment); | 567 | void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment); |
568 | void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec, | 568 | void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec, |
569 | gc_level_t gc_level); | 569 | gc_level_t gc_level); |
570 | void logfs_set_segment_reserved(struct super_block *sb, u32 segno); | 570 | void logfs_set_segment_reserved(struct super_block *sb, u32 segno); |
571 | void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec); | 571 | void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec); |
572 | struct logfs_block *__alloc_block(struct super_block *sb, | 572 | struct logfs_block *__alloc_block(struct super_block *sb, |
573 | u64 ino, u64 bix, level_t level); | 573 | u64 ino, u64 bix, level_t level); |
574 | void __free_block(struct super_block *sb, struct logfs_block *block); | 574 | void __free_block(struct super_block *sb, struct logfs_block *block); |
575 | void btree_write_block(struct logfs_block *block); | 575 | void btree_write_block(struct logfs_block *block); |
576 | void initialize_block_counters(struct page *page, struct logfs_block *block, | 576 | void initialize_block_counters(struct page *page, struct logfs_block *block, |
577 | __be64 *array, int page_is_empty); | 577 | __be64 *array, int page_is_empty); |
578 | int logfs_exist_block(struct inode *inode, u64 bix); | 578 | int logfs_exist_block(struct inode *inode, u64 bix); |
579 | int get_page_reserve(struct inode *inode, struct page *page); | 579 | int get_page_reserve(struct inode *inode, struct page *page); |
580 | extern struct logfs_block_ops indirect_block_ops; | 580 | extern struct logfs_block_ops indirect_block_ops; |
581 | 581 | ||
582 | /* segment.c */ | 582 | /* segment.c */ |
583 | int logfs_erase_segment(struct super_block *sb, u32 ofs, int ensure_erase); | 583 | int logfs_erase_segment(struct super_block *sb, u32 ofs, int ensure_erase); |
584 | int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf); | 584 | int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf); |
585 | int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix, | 585 | int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix, |
586 | level_t level); | 586 | level_t level); |
587 | int logfs_segment_write(struct inode *inode, struct page *page, | 587 | int logfs_segment_write(struct inode *inode, struct page *page, |
588 | struct logfs_shadow *shadow); | 588 | struct logfs_shadow *shadow); |
589 | int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow); | 589 | int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow); |
590 | int logfs_load_object_aliases(struct super_block *sb, | 590 | int logfs_load_object_aliases(struct super_block *sb, |
591 | struct logfs_obj_alias *oa, int count); | 591 | struct logfs_obj_alias *oa, int count); |
592 | void move_page_to_btree(struct page *page); | 592 | void move_page_to_btree(struct page *page); |
593 | int logfs_init_mapping(struct super_block *sb); | 593 | int logfs_init_mapping(struct super_block *sb); |
594 | void logfs_sync_area(struct logfs_area *area); | 594 | void logfs_sync_area(struct logfs_area *area); |
595 | void logfs_sync_segments(struct super_block *sb); | 595 | void logfs_sync_segments(struct super_block *sb); |
596 | void freeseg(struct super_block *sb, u32 segno); | 596 | void freeseg(struct super_block *sb, u32 segno); |
597 | 597 | ||
598 | /* area handling */ | 598 | /* area handling */ |
599 | int logfs_init_areas(struct super_block *sb); | 599 | int logfs_init_areas(struct super_block *sb); |
600 | void logfs_cleanup_areas(struct super_block *sb); | 600 | void logfs_cleanup_areas(struct super_block *sb); |
601 | int logfs_open_area(struct logfs_area *area, size_t bytes); | 601 | int logfs_open_area(struct logfs_area *area, size_t bytes); |
602 | int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | 602 | int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, |
603 | int use_filler); | 603 | int use_filler); |
604 | 604 | ||
605 | static inline int logfs_buf_write(struct logfs_area *area, u64 ofs, | 605 | static inline int logfs_buf_write(struct logfs_area *area, u64 ofs, |
606 | void *buf, size_t len) | 606 | void *buf, size_t len) |
607 | { | 607 | { |
608 | return __logfs_buf_write(area, ofs, buf, len, 0); | 608 | return __logfs_buf_write(area, ofs, buf, len, 0); |
609 | } | 609 | } |
610 | 610 | ||
611 | static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs, | 611 | static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs, |
612 | void *buf, size_t len) | 612 | void *buf, size_t len) |
613 | { | 613 | { |
614 | return __logfs_buf_write(area, ofs, buf, len, 1); | 614 | return __logfs_buf_write(area, ofs, buf, len, 1); |
615 | } | 615 | } |
616 | 616 | ||
617 | /* super.c */ | 617 | /* super.c */ |
618 | struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index); | 618 | struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index); |
619 | void emergency_read_end(struct page *page); | 619 | void emergency_read_end(struct page *page); |
620 | void logfs_crash_dump(struct super_block *sb); | 620 | void logfs_crash_dump(struct super_block *sb); |
621 | int logfs_statfs(struct dentry *dentry, struct kstatfs *stats); | 621 | int logfs_statfs(struct dentry *dentry, struct kstatfs *stats); |
622 | int logfs_check_ds(struct logfs_disk_super *ds); | 622 | int logfs_check_ds(struct logfs_disk_super *ds); |
623 | int logfs_write_sb(struct super_block *sb); | 623 | int logfs_write_sb(struct super_block *sb); |
624 | 624 | ||
625 | static inline struct logfs_super *logfs_super(struct super_block *sb) | 625 | static inline struct logfs_super *logfs_super(struct super_block *sb) |
626 | { | 626 | { |
627 | return sb->s_fs_info; | 627 | return sb->s_fs_info; |
628 | } | 628 | } |
629 | 629 | ||
630 | static inline struct logfs_inode *logfs_inode(struct inode *inode) | 630 | static inline struct logfs_inode *logfs_inode(struct inode *inode) |
631 | { | 631 | { |
632 | return container_of(inode, struct logfs_inode, vfs_inode); | 632 | return container_of(inode, struct logfs_inode, vfs_inode); |
633 | } | 633 | } |
634 | 634 | ||
635 | static inline void logfs_set_ro(struct super_block *sb) | 635 | static inline void logfs_set_ro(struct super_block *sb) |
636 | { | 636 | { |
637 | logfs_super(sb)->s_flags |= LOGFS_SB_FLAG_RO; | 637 | logfs_super(sb)->s_flags |= LOGFS_SB_FLAG_RO; |
638 | } | 638 | } |
639 | 639 | ||
640 | #define LOGFS_BUG(sb) do { \ | 640 | #define LOGFS_BUG(sb) do { \ |
641 | struct super_block *__sb = sb; \ | 641 | struct super_block *__sb = sb; \ |
642 | logfs_crash_dump(__sb); \ | 642 | logfs_crash_dump(__sb); \ |
643 | logfs_super(__sb)->s_flags |= LOGFS_SB_FLAG_RO; \ | 643 | logfs_super(__sb)->s_flags |= LOGFS_SB_FLAG_RO; \ |
644 | BUG(); \ | 644 | BUG(); \ |
645 | } while (0) | 645 | } while (0) |
646 | 646 | ||
647 | #define LOGFS_BUG_ON(condition, sb) \ | 647 | #define LOGFS_BUG_ON(condition, sb) \ |
648 | do { if (unlikely(condition)) LOGFS_BUG((sb)); } while (0) | 648 | do { if (unlikely(condition)) LOGFS_BUG((sb)); } while (0) |
649 | 649 | ||
650 | static inline __be32 logfs_crc32(void *data, size_t len, size_t skip) | 650 | static inline __be32 logfs_crc32(void *data, size_t len, size_t skip) |
651 | { | 651 | { |
652 | return cpu_to_be32(crc32(~0, data+skip, len-skip)); | 652 | return cpu_to_be32(crc32(~0, data+skip, len-skip)); |
653 | } | 653 | } |
654 | 654 | ||
655 | static inline u8 logfs_type(struct inode *inode) | 655 | static inline u8 logfs_type(struct inode *inode) |
656 | { | 656 | { |
657 | return (inode->i_mode >> 12) & 15; | 657 | return (inode->i_mode >> 12) & 15; |
658 | } | 658 | } |
659 | 659 | ||
660 | static inline pgoff_t logfs_index(struct super_block *sb, u64 pos) | 660 | static inline pgoff_t logfs_index(struct super_block *sb, u64 pos) |
661 | { | 661 | { |
662 | return pos >> sb->s_blocksize_bits; | 662 | return pos >> sb->s_blocksize_bits; |
663 | } | 663 | } |
664 | 664 | ||
665 | static inline u64 dev_ofs(struct super_block *sb, u32 segno, u32 ofs) | 665 | static inline u64 dev_ofs(struct super_block *sb, u32 segno, u32 ofs) |
666 | { | 666 | { |
667 | return ((u64)segno << logfs_super(sb)->s_segshift) + ofs; | 667 | return ((u64)segno << logfs_super(sb)->s_segshift) + ofs; |
668 | } | 668 | } |
669 | 669 | ||
670 | static inline u32 seg_no(struct super_block *sb, u64 ofs) | 670 | static inline u32 seg_no(struct super_block *sb, u64 ofs) |
671 | { | 671 | { |
672 | return ofs >> logfs_super(sb)->s_segshift; | 672 | return ofs >> logfs_super(sb)->s_segshift; |
673 | } | 673 | } |
674 | 674 | ||
675 | static inline u32 seg_ofs(struct super_block *sb, u64 ofs) | 675 | static inline u32 seg_ofs(struct super_block *sb, u64 ofs) |
676 | { | 676 | { |
677 | return ofs & logfs_super(sb)->s_segmask; | 677 | return ofs & logfs_super(sb)->s_segmask; |
678 | } | 678 | } |
679 | 679 | ||
680 | static inline u64 seg_align(struct super_block *sb, u64 ofs) | 680 | static inline u64 seg_align(struct super_block *sb, u64 ofs) |
681 | { | 681 | { |
682 | return ofs & ~logfs_super(sb)->s_segmask; | 682 | return ofs & ~logfs_super(sb)->s_segmask; |
683 | } | 683 | } |
684 | 684 | ||
685 | static inline struct logfs_block *logfs_block(struct page *page) | 685 | static inline struct logfs_block *logfs_block(struct page *page) |
686 | { | 686 | { |
687 | return (void *)page->private; | 687 | return (void *)page->private; |
688 | } | 688 | } |
689 | 689 | ||
690 | static inline level_t shrink_level(gc_level_t __level) | 690 | static inline level_t shrink_level(gc_level_t __level) |
691 | { | 691 | { |
692 | u8 level = (__force u8)__level; | 692 | u8 level = (__force u8)__level; |
693 | 693 | ||
694 | if (level >= LOGFS_MAX_LEVELS) | 694 | if (level >= LOGFS_MAX_LEVELS) |
695 | level -= LOGFS_MAX_LEVELS; | 695 | level -= LOGFS_MAX_LEVELS; |
696 | return (__force level_t)level; | 696 | return (__force level_t)level; |
697 | } | 697 | } |
698 | 698 | ||
699 | static inline gc_level_t expand_level(u64 ino, level_t __level) | 699 | static inline gc_level_t expand_level(u64 ino, level_t __level) |
700 | { | 700 | { |
701 | u8 level = (__force u8)__level; | 701 | u8 level = (__force u8)__level; |
702 | 702 | ||
703 | if (ino == LOGFS_INO_MASTER) { | 703 | if (ino == LOGFS_INO_MASTER) { |
704 | /* ifile has separate areas */ | 704 | /* ifile has separate areas */ |
705 | level += LOGFS_MAX_LEVELS; | 705 | level += LOGFS_MAX_LEVELS; |
706 | } | 706 | } |
707 | return (__force gc_level_t)level; | 707 | return (__force gc_level_t)level; |
708 | } | 708 | } |
709 | 709 | ||
710 | static inline int logfs_block_shift(struct super_block *sb, level_t level) | 710 | static inline int logfs_block_shift(struct super_block *sb, level_t level) |
711 | { | 711 | { |
712 | level = shrink_level((__force gc_level_t)level); | 712 | level = shrink_level((__force gc_level_t)level); |
713 | return (__force int)level * (sb->s_blocksize_bits - 3); | 713 | return (__force int)level * (sb->s_blocksize_bits - 3); |
714 | } | 714 | } |
715 | 715 | ||
716 | static inline u64 logfs_block_mask(struct super_block *sb, level_t level) | 716 | static inline u64 logfs_block_mask(struct super_block *sb, level_t level) |
717 | { | 717 | { |
718 | return ~0ull << logfs_block_shift(sb, level); | 718 | return ~0ull << logfs_block_shift(sb, level); |
719 | } | 719 | } |
720 | 720 | ||
721 | static inline struct logfs_area *get_area(struct super_block *sb, | 721 | static inline struct logfs_area *get_area(struct super_block *sb, |
722 | gc_level_t gc_level) | 722 | gc_level_t gc_level) |
723 | { | 723 | { |
724 | return logfs_super(sb)->s_area[(__force u8)gc_level]; | 724 | return logfs_super(sb)->s_area[(__force u8)gc_level]; |
725 | } | 725 | } |
726 | 726 | ||
727 | static inline void logfs_mempool_destroy(mempool_t *pool) | 727 | static inline void logfs_mempool_destroy(mempool_t *pool) |
728 | { | 728 | { |
729 | if (pool) | 729 | if (pool) |
730 | mempool_destroy(pool); | 730 | mempool_destroy(pool); |
731 | } | 731 | } |
732 | 732 | ||
733 | #endif | 733 | #endif |
734 | 734 |