diff options
author | Jiro SEKIBA <jir@unicus.jp> | 2010-01-30 04:06:35 -0500 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-02-12 22:26:02 -0500 |
commit | e902ec9906e844f4613fa6190c6fa65f162dc86e (patch) | |
tree | ee0ea829ae04a30fb01c119f050a3967304e55ba /fs/nilfs2 | |
parent | 724e6d3fe8003c3f60bf404bf22e4e331327c596 (diff) |
nilfs2: issue discard request after cleaning segments
This adds a function to send discard requests for given array of
segment numbers, and calls the function when garbage collection
succeeded.
Signed-off-by: Jiro SEKIBA <jir@unicus.jp>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/segment.c | 10 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 8 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 38 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.h | 1 |
4 files changed, 56 insertions, 1 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 105b508b47a8..9280b0f10792 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -2560,6 +2560,16 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, | |||
2560 | set_current_state(TASK_INTERRUPTIBLE); | 2560 | set_current_state(TASK_INTERRUPTIBLE); |
2561 | schedule_timeout(sci->sc_interval); | 2561 | schedule_timeout(sci->sc_interval); |
2562 | } | 2562 | } |
2563 | if (nilfs_test_opt(sbi, DISCARD)) { | ||
2564 | int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs, | ||
2565 | sci->sc_nfreesegs); | ||
2566 | if (ret) { | ||
2567 | printk(KERN_WARNING | ||
2568 | "NILFS warning: error %d on discard request, " | ||
2569 | "turning discards off for the device\n", ret); | ||
2570 | nilfs_clear_opt(sbi, DISCARD); | ||
2571 | } | ||
2572 | } | ||
2563 | 2573 | ||
2564 | out_unlock: | 2574 | out_unlock: |
2565 | sci->sc_freesegs = NULL; | 2575 | sci->sc_freesegs = NULL; |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 8173faee31e6..3f88401a375b 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -481,6 +481,8 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
481 | seq_printf(seq, ",order=strict"); | 481 | seq_printf(seq, ",order=strict"); |
482 | if (nilfs_test_opt(sbi, NORECOVERY)) | 482 | if (nilfs_test_opt(sbi, NORECOVERY)) |
483 | seq_printf(seq, ",norecovery"); | 483 | seq_printf(seq, ",norecovery"); |
484 | if (nilfs_test_opt(sbi, DISCARD)) | ||
485 | seq_printf(seq, ",discard"); | ||
484 | 486 | ||
485 | return 0; | 487 | return 0; |
486 | } | 488 | } |
@@ -550,7 +552,7 @@ static const struct export_operations nilfs_export_ops = { | |||
550 | enum { | 552 | enum { |
551 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 553 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
552 | Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, | 554 | Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
553 | Opt_err, | 555 | Opt_discard, Opt_err, |
554 | }; | 556 | }; |
555 | 557 | ||
556 | static match_table_t tokens = { | 558 | static match_table_t tokens = { |
@@ -561,6 +563,7 @@ static match_table_t tokens = { | |||
561 | {Opt_snapshot, "cp=%u"}, | 563 | {Opt_snapshot, "cp=%u"}, |
562 | {Opt_order, "order=%s"}, | 564 | {Opt_order, "order=%s"}, |
563 | {Opt_norecovery, "norecovery"}, | 565 | {Opt_norecovery, "norecovery"}, |
566 | {Opt_discard, "discard"}, | ||
564 | {Opt_err, NULL} | 567 | {Opt_err, NULL} |
565 | }; | 568 | }; |
566 | 569 | ||
@@ -614,6 +617,9 @@ static int parse_options(char *options, struct super_block *sb) | |||
614 | case Opt_norecovery: | 617 | case Opt_norecovery: |
615 | nilfs_set_opt(sbi, NORECOVERY); | 618 | nilfs_set_opt(sbi, NORECOVERY); |
616 | break; | 619 | break; |
620 | case Opt_discard: | ||
621 | nilfs_set_opt(sbi, DISCARD); | ||
622 | break; | ||
617 | default: | 623 | default: |
618 | printk(KERN_ERR | 624 | printk(KERN_ERR |
619 | "NILFS: Unrecognized mount option \"%s\"\n", p); | 625 | "NILFS: Unrecognized mount option \"%s\"\n", p); |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 6241e1722efc..92733d5651d2 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -646,6 +646,44 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
646 | goto out; | 646 | goto out; |
647 | } | 647 | } |
648 | 648 | ||
649 | int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump, | ||
650 | size_t nsegs) | ||
651 | { | ||
652 | sector_t seg_start, seg_end; | ||
653 | sector_t start = 0, nblocks = 0; | ||
654 | unsigned int sects_per_block; | ||
655 | __u64 *sn; | ||
656 | int ret = 0; | ||
657 | |||
658 | sects_per_block = (1 << nilfs->ns_blocksize_bits) / | ||
659 | bdev_logical_block_size(nilfs->ns_bdev); | ||
660 | for (sn = segnump; sn < segnump + nsegs; sn++) { | ||
661 | nilfs_get_segment_range(nilfs, *sn, &seg_start, &seg_end); | ||
662 | |||
663 | if (!nblocks) { | ||
664 | start = seg_start; | ||
665 | nblocks = seg_end - seg_start + 1; | ||
666 | } else if (start + nblocks == seg_start) { | ||
667 | nblocks += seg_end - seg_start + 1; | ||
668 | } else { | ||
669 | ret = blkdev_issue_discard(nilfs->ns_bdev, | ||
670 | start * sects_per_block, | ||
671 | nblocks * sects_per_block, | ||
672 | GFP_NOFS, | ||
673 | DISCARD_FL_BARRIER); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | nblocks = 0; | ||
677 | } | ||
678 | } | ||
679 | if (nblocks) | ||
680 | ret = blkdev_issue_discard(nilfs->ns_bdev, | ||
681 | start * sects_per_block, | ||
682 | nblocks * sects_per_block, | ||
683 | GFP_NOFS, DISCARD_FL_BARRIER); | ||
684 | return ret; | ||
685 | } | ||
686 | |||
649 | int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) | 687 | int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) |
650 | { | 688 | { |
651 | struct inode *dat = nilfs_dat_inode(nilfs); | 689 | struct inode *dat = nilfs_dat_inode(nilfs); |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 589786e33464..fd057f8ad439 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -221,6 +221,7 @@ struct the_nilfs *find_or_create_nilfs(struct block_device *); | |||
221 | void put_nilfs(struct the_nilfs *); | 221 | void put_nilfs(struct the_nilfs *); |
222 | int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); | 222 | int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); |
223 | int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); | 223 | int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); |
224 | int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); | ||
224 | int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); | 225 | int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); |
225 | struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); | 226 | struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); |
226 | int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); | 227 | int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); |