|
28 | 28 | * gcinodes), and this file provides lookup function of the dummy |
29 | 29 | * inodes and their buffer read function. |
30 | 30 | * |
31 | | - * Since NILFS2 keeps up multiple checkpoints/snapshots across GC, it |
32 | | - * has to treat blocks that belong to a same file but have different |
33 | | - * checkpoint numbers. To avoid interference among generations, dummy |
34 | | - * inodes are managed separately from actual inodes, and their lookup |
35 | | - * function (nilfs_gc_iget) is designed to be specified with a |
36 | | - * checkpoint number argument as well as an inode number. |
37 | | - * |
38 | 31 | * Buffers and pages held by the dummy inodes will be released each |
39 | 32 | * time after they are copied to a new log. Dirty blocks made on the |
40 | 33 | * current generation and the blocks to be moved by GC never overlap |
@@ -180,124 +173,41 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh) |
180 | 173 | return 0; |
181 | 174 | } |
182 | 175 |
|
183 | | -/* |
184 | | - * nilfs_init_gccache() - allocate and initialize gc_inode hash table |
185 | | - * @nilfs - the_nilfs |
186 | | - * |
187 | | - * Return Value: On success, 0. |
188 | | - * On error, a negative error code is returned. |
189 | | - */ |
190 | | -int nilfs_init_gccache(struct the_nilfs *nilfs) |
191 | | -{ |
192 | | - int loop; |
193 | | - |
194 | | - BUG_ON(nilfs->ns_gc_inodes_h); |
195 | | - |
196 | | - INIT_LIST_HEAD(&nilfs->ns_gc_inodes); |
197 | | - |
198 | | - nilfs->ns_gc_inodes_h = |
199 | | - kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE, |
200 | | - GFP_NOFS); |
201 | | - if (nilfs->ns_gc_inodes_h == NULL) |
202 | | - return -ENOMEM; |
203 | | - |
204 | | - for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++) |
205 | | - INIT_HLIST_HEAD(&nilfs->ns_gc_inodes_h[loop]); |
206 | | - return 0; |
207 | | -} |
208 | | - |
209 | | -/* |
210 | | - * nilfs_destroy_gccache() - free gc_inode hash table |
211 | | - * @nilfs - the nilfs |
212 | | - */ |
213 | | -void nilfs_destroy_gccache(struct the_nilfs *nilfs) |
| 176 | +int nilfs_init_gcinode(struct inode *inode) |
214 | 177 | { |
215 | | - if (nilfs->ns_gc_inodes_h) { |
216 | | - nilfs_remove_all_gcinode(nilfs); |
217 | | - kfree(nilfs->ns_gc_inodes_h); |
218 | | - nilfs->ns_gc_inodes_h = NULL; |
219 | | - } |
220 | | -} |
221 | | - |
222 | | -static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino, |
223 | | - __u64 cno) |
224 | | -{ |
225 | | - struct inode *inode; |
226 | | - struct nilfs_inode_info *ii; |
227 | | - |
228 | | - inode = nilfs_mdt_new_common(nilfs, NULL, ino); |
229 | | - if (!inode) |
230 | | - return NULL; |
231 | | - |
232 | | - if (nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0) < 0) { |
233 | | - nilfs_destroy_inode(inode); |
234 | | - return NULL; |
235 | | - } |
236 | | - inode->i_op = NULL; |
237 | | - inode->i_fop = NULL; |
238 | | - inode->i_mapping->a_ops = &def_gcinode_aops; |
239 | | - |
240 | | - ii = NILFS_I(inode); |
241 | | - ii->i_cno = cno; |
242 | | - ii->i_flags = 0; |
243 | | - ii->i_state = 1 << NILFS_I_GCINODE; |
244 | | - ii->i_bh = NULL; |
245 | | - nilfs_bmap_init_gc(ii->i_bmap); |
| 178 | + struct nilfs_inode_info *ii = NILFS_I(inode); |
| 179 | + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
| 180 | + int ret; |
246 | 181 |
|
247 | | - return inode; |
248 | | -} |
| 182 | + ret = nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0); |
| 183 | + if (!ret) { |
| 184 | + inode->i_mapping->a_ops = &def_gcinode_aops; |
249 | 185 |
|
250 | | -static unsigned long ihash(ino_t ino, __u64 cno) |
251 | | -{ |
252 | | - return hash_long((unsigned long)((ino << 2) + cno), |
253 | | - NILFS_GCINODE_HASH_BITS); |
254 | | -} |
| 186 | + ii->i_flags = 0; |
| 187 | + nilfs_bmap_init_gc(ii->i_bmap); |
255 | 188 |
|
256 | | -/* |
257 | | - * nilfs_gc_iget() - find or create gc inode with specified (ino,cno) |
258 | | - */ |
259 | | -struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno) |
260 | | -{ |
261 | | - struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno); |
262 | | - struct hlist_node *node; |
263 | | - struct inode *inode; |
264 | | - |
265 | | - hlist_for_each_entry(inode, node, head, i_hash) { |
266 | | - if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno) |
267 | | - return inode; |
268 | | - } |
269 | | - |
270 | | - inode = alloc_gcinode(nilfs, ino, cno); |
271 | | - if (likely(inode)) { |
272 | | - hlist_add_head(&inode->i_hash, head); |
| 189 | + /* |
| 190 | + * Add the inode to GC inode list. Garbage Collection |
| 191 | + * is serialized and no two processes manipulate the |
| 192 | + * list simultaneously. |
| 193 | + */ |
| 194 | + igrab(inode); |
273 | 195 | list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); |
274 | 196 | } |
275 | | - return inode; |
276 | | -} |
277 | | - |
278 | | -/* |
279 | | - * nilfs_clear_gcinode() - clear and free a gc inode |
280 | | - */ |
281 | | -void nilfs_clear_gcinode(struct inode *inode) |
282 | | -{ |
283 | | - nilfs_mdt_destroy(inode); |
| 197 | + return ret; |
284 | 198 | } |
285 | 199 |
|
286 | | -/* |
287 | | - * nilfs_remove_all_gcinode() - remove all inodes from the_nilfs |
| 200 | +/** |
| 201 | + * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes |
288 | 202 | */ |
289 | | -void nilfs_remove_all_gcinode(struct the_nilfs *nilfs) |
| 203 | +void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs) |
290 | 204 | { |
291 | | - struct hlist_head *head = nilfs->ns_gc_inodes_h; |
292 | | - struct hlist_node *node, *n; |
293 | | - struct inode *inode; |
294 | | - int loop; |
| 205 | + struct list_head *head = &nilfs->ns_gc_inodes; |
| 206 | + struct nilfs_inode_info *ii; |
295 | 207 |
|
296 | | - for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++, head++) { |
297 | | - hlist_for_each_entry_safe(inode, node, n, head, i_hash) { |
298 | | - hlist_del_init(&inode->i_hash); |
299 | | - list_del_init(&NILFS_I(inode)->i_dirty); |
300 | | - nilfs_clear_gcinode(inode); /* might sleep */ |
301 | | - } |
| 208 | + while (!list_empty(head)) { |
| 209 | + ii = list_first_entry(head, struct nilfs_inode_info, i_dirty); |
| 210 | + list_del_init(&ii->i_dirty); |
| 211 | + iput(&ii->vfs_inode); |
302 | 212 | } |
303 | 213 | } |
0 commit comments