diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-07-25 18:47:17 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-07-29 10:45:54 -0400 |
commit | 6451e041c8d39daf39c71eefe839641c2093713e (patch) | |
tree | 971f0c3ab382126d3d584c5fbe235a6d03cc8965 /fs/f2fs | |
parent | 953e6cc6bcb615dfa373320ffa62b574c6be608a (diff) |
f2fs: add infra for ino management
This patch changes the naming of orphan-related data structures to use as
inode numbers managed globally.
Later, we can use this facility for managing any inode number lists.
Reviewed-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/checkpoint.c | 76 | ||||
-rw-r--r-- | fs/f2fs/debug.c | 2 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 19 | ||||
-rw-r--r-- | fs/f2fs/super.c | 2 |
4 files changed, 55 insertions, 44 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 1c6eb6bcfd99..f93d154e2770 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "segment.h" | 22 | #include "segment.h" |
23 | #include <trace/events/f2fs.h> | 23 | #include <trace/events/f2fs.h> |
24 | 24 | ||
25 | static struct kmem_cache *orphan_entry_slab; | 25 | static struct kmem_cache *ino_entry_slab; |
26 | static struct kmem_cache *inode_entry_slab; | 26 | static struct kmem_cache *inode_entry_slab; |
27 | 27 | ||
28 | /* | 28 | /* |
@@ -282,19 +282,18 @@ const struct address_space_operations f2fs_meta_aops = { | |||
282 | .set_page_dirty = f2fs_set_meta_page_dirty, | 282 | .set_page_dirty = f2fs_set_meta_page_dirty, |
283 | }; | 283 | }; |
284 | 284 | ||
285 | static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino) | 285 | static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) |
286 | { | 286 | { |
287 | struct list_head *head; | 287 | struct ino_entry *new, *e; |
288 | struct orphan_inode_entry *new, *e; | ||
289 | 288 | ||
290 | new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC); | 289 | new = f2fs_kmem_cache_alloc(ino_entry_slab, GFP_ATOMIC); |
291 | new->ino = ino; | 290 | new->ino = ino; |
292 | 291 | ||
293 | spin_lock(&sbi->orphan_inode_lock); | 292 | spin_lock(&sbi->ino_lock[type]); |
294 | list_for_each_entry(e, &sbi->orphan_inode_list, list) { | 293 | list_for_each_entry(e, &sbi->ino_list[type], list) { |
295 | if (e->ino == ino) { | 294 | if (e->ino == ino) { |
296 | spin_unlock(&sbi->orphan_inode_lock); | 295 | spin_unlock(&sbi->ino_lock[type]); |
297 | kmem_cache_free(orphan_entry_slab, new); | 296 | kmem_cache_free(ino_entry_slab, new); |
298 | return; | 297 | return; |
299 | } | 298 | } |
300 | if (e->ino > ino) | 299 | if (e->ino > ino) |
@@ -303,58 +302,58 @@ static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino) | |||
303 | 302 | ||
304 | /* add new entry into list which is sorted by inode number */ | 303 | /* add new entry into list which is sorted by inode number */ |
305 | list_add_tail(&new->list, &e->list); | 304 | list_add_tail(&new->list, &e->list); |
306 | spin_unlock(&sbi->orphan_inode_lock); | 305 | spin_unlock(&sbi->ino_lock[type]); |
307 | } | 306 | } |
308 | 307 | ||
309 | static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino) | 308 | static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) |
310 | { | 309 | { |
311 | struct orphan_inode_entry *e; | 310 | struct ino_entry *e; |
312 | 311 | ||
313 | spin_lock(&sbi->orphan_inode_lock); | 312 | spin_lock(&sbi->ino_lock[type]); |
314 | list_for_each_entry(e, &sbi->orphan_inode_list, list) { | 313 | list_for_each_entry(e, &sbi->ino_list[type], list) { |
315 | if (e->ino == ino) { | 314 | if (e->ino == ino) { |
316 | list_del(&e->list); | 315 | list_del(&e->list); |
317 | sbi->n_orphans--; | 316 | sbi->n_orphans--; |
318 | spin_unlock(&sbi->orphan_inode_lock); | 317 | spin_unlock(&sbi->ino_lock[type]); |
319 | kmem_cache_free(orphan_entry_slab, e); | 318 | kmem_cache_free(ino_entry_slab, e); |
320 | return; | 319 | return; |
321 | } | 320 | } |
322 | } | 321 | } |
323 | spin_unlock(&sbi->orphan_inode_lock); | 322 | spin_unlock(&sbi->ino_lock[type]); |
324 | } | 323 | } |
325 | 324 | ||
326 | int acquire_orphan_inode(struct f2fs_sb_info *sbi) | 325 | int acquire_orphan_inode(struct f2fs_sb_info *sbi) |
327 | { | 326 | { |
328 | int err = 0; | 327 | int err = 0; |
329 | 328 | ||
330 | spin_lock(&sbi->orphan_inode_lock); | 329 | spin_lock(&sbi->ino_lock[ORPHAN_INO]); |
331 | if (unlikely(sbi->n_orphans >= sbi->max_orphans)) | 330 | if (unlikely(sbi->n_orphans >= sbi->max_orphans)) |
332 | err = -ENOSPC; | 331 | err = -ENOSPC; |
333 | else | 332 | else |
334 | sbi->n_orphans++; | 333 | sbi->n_orphans++; |
335 | spin_unlock(&sbi->orphan_inode_lock); | 334 | spin_unlock(&sbi->ino_lock[ORPHAN_INO]); |
336 | 335 | ||
337 | return err; | 336 | return err; |
338 | } | 337 | } |
339 | 338 | ||
340 | void release_orphan_inode(struct f2fs_sb_info *sbi) | 339 | void release_orphan_inode(struct f2fs_sb_info *sbi) |
341 | { | 340 | { |
342 | spin_lock(&sbi->orphan_inode_lock); | 341 | spin_lock(&sbi->ino_lock[ORPHAN_INO]); |
343 | f2fs_bug_on(sbi->n_orphans == 0); | 342 | f2fs_bug_on(sbi->n_orphans == 0); |
344 | sbi->n_orphans--; | 343 | sbi->n_orphans--; |
345 | spin_unlock(&sbi->orphan_inode_lock); | 344 | spin_unlock(&sbi->ino_lock[ORPHAN_INO]); |
346 | } | 345 | } |
347 | 346 | ||
348 | void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 347 | void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
349 | { | 348 | { |
350 | /* add new orphan entry into list which is sorted by inode number */ | 349 | /* add new orphan entry into list which is sorted by inode number */ |
351 | __add_ino_entry(sbi, ino); | 350 | __add_ino_entry(sbi, ino, ORPHAN_INO); |
352 | } | 351 | } |
353 | 352 | ||
354 | void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 353 | void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
355 | { | 354 | { |
356 | /* remove orphan entry from orphan list */ | 355 | /* remove orphan entry from orphan list */ |
357 | __remove_ino_entry(sbi, ino); | 356 | __remove_ino_entry(sbi, ino, ORPHAN_INO); |
358 | } | 357 | } |
359 | 358 | ||
360 | static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 359 | static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
@@ -408,14 +407,14 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) | |||
408 | unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans + | 407 | unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans + |
409 | (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK); | 408 | (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK); |
410 | struct page *page = NULL; | 409 | struct page *page = NULL; |
411 | struct orphan_inode_entry *orphan = NULL; | 410 | struct ino_entry *orphan = NULL; |
412 | 411 | ||
413 | for (index = 0; index < orphan_blocks; index++) | 412 | for (index = 0; index < orphan_blocks; index++) |
414 | grab_meta_page(sbi, start_blk + index); | 413 | grab_meta_page(sbi, start_blk + index); |
415 | 414 | ||
416 | index = 1; | 415 | index = 1; |
417 | spin_lock(&sbi->orphan_inode_lock); | 416 | spin_lock(&sbi->ino_lock[ORPHAN_INO]); |
418 | head = &sbi->orphan_inode_list; | 417 | head = &sbi->ino_list[ORPHAN_INO]; |
419 | 418 | ||
420 | /* loop for each orphan inode entry and write them in Jornal block */ | 419 | /* loop for each orphan inode entry and write them in Jornal block */ |
421 | list_for_each_entry(orphan, head, list) { | 420 | list_for_each_entry(orphan, head, list) { |
@@ -455,7 +454,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) | |||
455 | f2fs_put_page(page, 1); | 454 | f2fs_put_page(page, 1); |
456 | } | 455 | } |
457 | 456 | ||
458 | spin_unlock(&sbi->orphan_inode_lock); | 457 | spin_unlock(&sbi->ino_lock[ORPHAN_INO]); |
459 | } | 458 | } |
460 | 459 | ||
461 | static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | 460 | static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, |
@@ -939,31 +938,36 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
939 | trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint"); | 938 | trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint"); |
940 | } | 939 | } |
941 | 940 | ||
942 | void init_orphan_info(struct f2fs_sb_info *sbi) | 941 | void init_ino_entry_info(struct f2fs_sb_info *sbi) |
943 | { | 942 | { |
944 | spin_lock_init(&sbi->orphan_inode_lock); | 943 | int i; |
945 | INIT_LIST_HEAD(&sbi->orphan_inode_list); | 944 | |
946 | sbi->n_orphans = 0; | 945 | for (i = 0; i < MAX_INO_ENTRY; i++) { |
946 | spin_lock_init(&sbi->ino_lock[i]); | ||
947 | INIT_LIST_HEAD(&sbi->ino_list[i]); | ||
948 | } | ||
949 | |||
947 | /* | 950 | /* |
948 | * considering 512 blocks in a segment 8 blocks are needed for cp | 951 | * considering 512 blocks in a segment 8 blocks are needed for cp |
949 | * and log segment summaries. Remaining blocks are used to keep | 952 | * and log segment summaries. Remaining blocks are used to keep |
950 | * orphan entries with the limitation one reserved segment | 953 | * orphan entries with the limitation one reserved segment |
951 | * for cp pack we can have max 1020*504 orphan entries | 954 | * for cp pack we can have max 1020*504 orphan entries |
952 | */ | 955 | */ |
956 | sbi->n_orphans = 0; | ||
953 | sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE) | 957 | sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE) |
954 | * F2FS_ORPHANS_PER_BLOCK; | 958 | * F2FS_ORPHANS_PER_BLOCK; |
955 | } | 959 | } |
956 | 960 | ||
957 | int __init create_checkpoint_caches(void) | 961 | int __init create_checkpoint_caches(void) |
958 | { | 962 | { |
959 | orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", | 963 | ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry", |
960 | sizeof(struct orphan_inode_entry)); | 964 | sizeof(struct ino_entry)); |
961 | if (!orphan_entry_slab) | 965 | if (!ino_entry_slab) |
962 | return -ENOMEM; | 966 | return -ENOMEM; |
963 | inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry", | 967 | inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry", |
964 | sizeof(struct dir_inode_entry)); | 968 | sizeof(struct dir_inode_entry)); |
965 | if (!inode_entry_slab) { | 969 | if (!inode_entry_slab) { |
966 | kmem_cache_destroy(orphan_entry_slab); | 970 | kmem_cache_destroy(ino_entry_slab); |
967 | return -ENOMEM; | 971 | return -ENOMEM; |
968 | } | 972 | } |
969 | return 0; | 973 | return 0; |
@@ -971,6 +975,6 @@ int __init create_checkpoint_caches(void) | |||
971 | 975 | ||
972 | void destroy_checkpoint_caches(void) | 976 | void destroy_checkpoint_caches(void) |
973 | { | 977 | { |
974 | kmem_cache_destroy(orphan_entry_slab); | 978 | kmem_cache_destroy(ino_entry_slab); |
975 | kmem_cache_destroy(inode_entry_slab); | 979 | kmem_cache_destroy(inode_entry_slab); |
976 | } | 980 | } |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 3f99266ccc17..a441ba33be11 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
@@ -167,7 +167,7 @@ get_cache: | |||
167 | si->cache_mem += npages << PAGE_CACHE_SHIFT; | 167 | si->cache_mem += npages << PAGE_CACHE_SHIFT; |
168 | npages = META_MAPPING(sbi)->nrpages; | 168 | npages = META_MAPPING(sbi)->nrpages; |
169 | si->cache_mem += npages << PAGE_CACHE_SHIFT; | 169 | si->cache_mem += npages << PAGE_CACHE_SHIFT; |
170 | si->cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry); | 170 | si->cache_mem += sbi->n_orphans * sizeof(struct ino_entry); |
171 | si->cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry); | 171 | si->cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry); |
172 | } | 172 | } |
173 | 173 | ||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e999eec200b7..b6fa6ec54f98 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -100,8 +100,13 @@ enum { | |||
100 | META_SSA | 100 | META_SSA |
101 | }; | 101 | }; |
102 | 102 | ||
103 | /* for the list of orphan inodes */ | 103 | /* for the list of ino */ |
104 | struct orphan_inode_entry { | 104 | enum { |
105 | ORPHAN_INO, /* for orphan ino list */ | ||
106 | MAX_INO_ENTRY, /* max. list */ | ||
107 | }; | ||
108 | |||
109 | struct ino_entry { | ||
105 | struct list_head list; /* list head */ | 110 | struct list_head list; /* list head */ |
106 | nid_t ino; /* inode number */ | 111 | nid_t ino; /* inode number */ |
107 | }; | 112 | }; |
@@ -450,9 +455,11 @@ struct f2fs_sb_info { | |||
450 | bool por_doing; /* recovery is doing or not */ | 455 | bool por_doing; /* recovery is doing or not */ |
451 | wait_queue_head_t cp_wait; | 456 | wait_queue_head_t cp_wait; |
452 | 457 | ||
453 | /* for orphan inode management */ | 458 | /* for inode management */ |
454 | struct list_head orphan_inode_list; /* orphan inode list */ | 459 | spinlock_t ino_lock[MAX_INO_ENTRY]; /* for ino entry lock */ |
455 | spinlock_t orphan_inode_lock; /* for orphan inode list */ | 460 | struct list_head ino_list[MAX_INO_ENTRY]; /* inode list head */ |
461 | |||
462 | /* for orphan inode, use 0'th array */ | ||
456 | unsigned int n_orphans; /* # of orphan inodes */ | 463 | unsigned int n_orphans; /* # of orphan inodes */ |
457 | unsigned int max_orphans; /* max orphan inodes */ | 464 | unsigned int max_orphans; /* max orphan inodes */ |
458 | 465 | ||
@@ -1255,7 +1262,7 @@ void add_dirty_dir_inode(struct inode *); | |||
1255 | void remove_dirty_dir_inode(struct inode *); | 1262 | void remove_dirty_dir_inode(struct inode *); |
1256 | void sync_dirty_dir_inodes(struct f2fs_sb_info *); | 1263 | void sync_dirty_dir_inodes(struct f2fs_sb_info *); |
1257 | void write_checkpoint(struct f2fs_sb_info *, bool); | 1264 | void write_checkpoint(struct f2fs_sb_info *, bool); |
1258 | void init_orphan_info(struct f2fs_sb_info *); | 1265 | void init_ino_entry_info(struct f2fs_sb_info *); |
1259 | int __init create_checkpoint_caches(void); | 1266 | int __init create_checkpoint_caches(void); |
1260 | void destroy_checkpoint_caches(void); | 1267 | void destroy_checkpoint_caches(void); |
1261 | 1268 | ||
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 93593ceec175..f253e222dcea 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -1003,7 +1003,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
1003 | INIT_LIST_HEAD(&sbi->dir_inode_list); | 1003 | INIT_LIST_HEAD(&sbi->dir_inode_list); |
1004 | spin_lock_init(&sbi->dir_inode_lock); | 1004 | spin_lock_init(&sbi->dir_inode_lock); |
1005 | 1005 | ||
1006 | init_orphan_info(sbi); | 1006 | init_ino_entry_info(sbi); |
1007 | 1007 | ||
1008 | /* setup f2fs internal modules */ | 1008 | /* setup f2fs internal modules */ |
1009 | err = build_segment_manager(sbi); | 1009 | err = build_segment_manager(sbi); |