diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-09-05 23:05:43 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-10-22 20:24:37 -0400 |
commit | ebdfed4dc59d177cf26013a0c9b8ee9652e9a140 (patch) | |
tree | 6ef90f068ae41c55234181c93d8e30a303126c43 /fs/nilfs2/mdt.c | |
parent | a8070dd365dd995f6139a2fc3aeee10159bdcc45 (diff) |
nilfs2: add routines to roll back state of DAT file
This adds optional function to metadata files which makes a copy of
bmap, page caches, and b-tree node cache, and rolls back to the copy
as needed.
This enhancement is intended to displace gcdat inode that provides a
similar function in a different way.
In this patch, nilfs_shadow_map structure is added to store a copy of
the foregoing states. nilfs_mdt_setup_shadow_map relates this
structure to a metadata file. And, nilfs_mdt_save_to_shadow_map() and
nilfs_mdt_restore_from_shadow_map() provides save and restore
functions respectively. Finally, nilfs_mdt_clear_shadow_map() clears
states of nilfs_shadow_map.
The copy of b-tree node cache and page cache is made by duplicating
only dirty pages into corresponding caches in nilfs_shadow_map. Their
restoration is done by clearing dirty pages from original caches and
by copying dirty pages back from nilfs_shadow_map.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/mdt.c')
-rw-r--r-- | fs/nilfs2/mdt.c | 104 |
1 files changed, 100 insertions, 4 deletions
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 73e5da3b097..0066468609d 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
@@ -398,16 +398,22 @@ int nilfs_mdt_fetch_dirty(struct inode *inode) | |||
398 | static int | 398 | static int |
399 | nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | 399 | nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) |
400 | { | 400 | { |
401 | struct inode *inode = container_of(page->mapping, | 401 | struct inode *inode; |
402 | struct inode, i_data); | 402 | struct super_block *sb; |
403 | struct super_block *sb = inode->i_sb; | 403 | struct the_nilfs *nilfs; |
404 | struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs; | ||
405 | struct nilfs_sb_info *writer = NULL; | 404 | struct nilfs_sb_info *writer = NULL; |
406 | int err = 0; | 405 | int err = 0; |
407 | 406 | ||
408 | redirty_page_for_writepage(wbc, page); | 407 | redirty_page_for_writepage(wbc, page); |
409 | unlock_page(page); | 408 | unlock_page(page); |
410 | 409 | ||
410 | inode = page->mapping->host; | ||
411 | if (!inode) | ||
412 | return 0; | ||
413 | |||
414 | sb = inode->i_sb; | ||
415 | nilfs = NILFS_MDT(inode)->mi_nilfs; | ||
416 | |||
411 | if (page->mapping->assoc_mapping) | 417 | if (page->mapping->assoc_mapping) |
412 | return 0; /* Do not request flush for shadow page cache */ | 418 | return 0; /* Do not request flush for shadow page cache */ |
413 | if (!sb) { | 419 | if (!sb) { |
@@ -567,6 +573,96 @@ void nilfs_mdt_set_shadow(struct inode *orig, struct inode *shadow) | |||
567 | &NILFS_I(orig)->i_btnode_cache; | 573 | &NILFS_I(orig)->i_btnode_cache; |
568 | } | 574 | } |
569 | 575 | ||
576 | static const struct address_space_operations shadow_map_aops = { | ||
577 | .sync_page = block_sync_page, | ||
578 | }; | ||
579 | |||
580 | /** | ||
581 | * nilfs_mdt_setup_shadow_map - setup shadow map and bind it to metadata file | ||
582 | * @inode: inode of the metadata file | ||
583 | * @shadow: shadow mapping | ||
584 | */ | ||
585 | int nilfs_mdt_setup_shadow_map(struct inode *inode, | ||
586 | struct nilfs_shadow_map *shadow) | ||
587 | { | ||
588 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
589 | struct backing_dev_info *bdi = NILFS_I_NILFS(inode)->ns_bdi; | ||
590 | |||
591 | INIT_LIST_HEAD(&shadow->frozen_buffers); | ||
592 | nilfs_mapping_init_once(&shadow->frozen_data); | ||
593 | nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops); | ||
594 | nilfs_mapping_init_once(&shadow->frozen_btnodes); | ||
595 | nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops); | ||
596 | mi->mi_shadow = shadow; | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * nilfs_mdt_save_to_shadow_map - copy bmap and dirty pages to shadow map | ||
602 | * @inode: inode of the metadata file | ||
603 | */ | ||
604 | int nilfs_mdt_save_to_shadow_map(struct inode *inode) | ||
605 | { | ||
606 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
607 | struct nilfs_inode_info *ii = NILFS_I(inode); | ||
608 | struct nilfs_shadow_map *shadow = mi->mi_shadow; | ||
609 | int ret; | ||
610 | |||
611 | ret = nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping); | ||
612 | if (ret) | ||
613 | goto out; | ||
614 | |||
615 | ret = nilfs_copy_dirty_pages(&shadow->frozen_btnodes, | ||
616 | &ii->i_btnode_cache); | ||
617 | if (ret) | ||
618 | goto out; | ||
619 | |||
620 | nilfs_bmap_save(ii->i_bmap, &shadow->bmap_store); | ||
621 | out: | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | /** | ||
626 | * nilfs_mdt_restore_from_shadow_map - restore dirty pages and bmap state | ||
627 | * @inode: inode of the metadata file | ||
628 | */ | ||
629 | void nilfs_mdt_restore_from_shadow_map(struct inode *inode) | ||
630 | { | ||
631 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
632 | struct nilfs_inode_info *ii = NILFS_I(inode); | ||
633 | struct nilfs_shadow_map *shadow = mi->mi_shadow; | ||
634 | |||
635 | down_write(&mi->mi_sem); | ||
636 | |||
637 | if (mi->mi_palloc_cache) | ||
638 | nilfs_palloc_clear_cache(inode); | ||
639 | |||
640 | nilfs_clear_dirty_pages(inode->i_mapping); | ||
641 | nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data); | ||
642 | |||
643 | nilfs_clear_dirty_pages(&ii->i_btnode_cache); | ||
644 | nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes); | ||
645 | |||
646 | nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); | ||
647 | |||
648 | up_write(&mi->mi_sem); | ||
649 | } | ||
650 | |||
651 | /** | ||
652 | * nilfs_mdt_clear_shadow_map - truncate pages in shadow map caches | ||
653 | * @inode: inode of the metadata file | ||
654 | */ | ||
655 | void nilfs_mdt_clear_shadow_map(struct inode *inode) | ||
656 | { | ||
657 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
658 | struct nilfs_shadow_map *shadow = mi->mi_shadow; | ||
659 | |||
660 | down_write(&mi->mi_sem); | ||
661 | truncate_inode_pages(&shadow->frozen_data, 0); | ||
662 | truncate_inode_pages(&shadow->frozen_btnodes, 0); | ||
663 | up_write(&mi->mi_sem); | ||
664 | } | ||
665 | |||
570 | static void nilfs_mdt_clear(struct inode *inode) | 666 | static void nilfs_mdt_clear(struct inode *inode) |
571 | { | 667 | { |
572 | struct nilfs_inode_info *ii = NILFS_I(inode); | 668 | struct nilfs_inode_info *ii = NILFS_I(inode); |