diff options
| -rw-r--r-- | Documentation/filesystems/nilfs2.txt | 3 | ||||
| -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 | ||||
| -rw-r--r-- | include/linux/nilfs2_fs.h | 1 | 
6 files changed, 60 insertions, 1 deletions
| diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt index 839efd8a8a8c..cf6d0d85ca82 100644 --- a/Documentation/filesystems/nilfs2.txt +++ b/Documentation/filesystems/nilfs2.txt | |||
| @@ -74,6 +74,9 @@ norecovery Disable recovery of the filesystem on mount. | |||
| 74 | This disables every write access on the device for | 74 | This disables every write access on the device for | 
| 75 | read-only mounts or snapshots. This option will fail | 75 | read-only mounts or snapshots. This option will fail | 
| 76 | for r/w mounts on an unclean volume. | 76 | for r/w mounts on an unclean volume. | 
| 77 | discard Issue discard/TRIM commands to the underlying block | ||
| 78 | device when blocks are freed. This is useful for SSD | ||
| 79 | devices and sparse/thinly-provisioned LUNs. | ||
| 77 | 80 | ||
| 78 | NILFS2 usage | 81 | NILFS2 usage | 
| 79 | ============ | 82 | ============ | 
| 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); | 
| diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 3fe02cf8b65a..640702e97457 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h | |||
| @@ -153,6 +153,7 @@ struct nilfs_super_root { | |||
| 153 | semantics also for data */ | 153 | semantics also for data */ | 
| 154 | #define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during | 154 | #define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during | 
| 155 | mount-time recovery */ | 155 | mount-time recovery */ | 
| 156 | #define NILFS_MOUNT_DISCARD 0x8000 /* Issue DISCARD requests */ | ||
| 156 | 157 | ||
| 157 | 158 | ||
| 158 | /** | 159 | /** | 
