Hi Sekiba-san, On Sat, 30 Jan 2010 13:28:52 +0900, Jiro SEKIBA <jir@xxxxxxxxx> wrote: > Hi, > > This is the revised patch. The original patch is found in > nilfs/experimental tree. I add mount option to enable the feature > and modify block devcie layer for recent block device layer. > > > 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: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx> > Signed-off-by: Jiro SEKIBA <jir@xxxxxxxxx> Thank you for sending this revised patch. I'll inline an additional comment. > --- > Documentation/filesystems/nilfs2.txt | 3 ++ > fs/nilfs2/segment.c | 3 ++ > fs/nilfs2/super.c | 8 +++++- > fs/nilfs2/the_nilfs.c | 45 ++++++++++++++++++++++++++++++++++ > fs/nilfs2/the_nilfs.h | 1 + > 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 839efd8..cf6d0d8 100644 > --- a/Documentation/filesystems/nilfs2.txt > +++ b/Documentation/filesystems/nilfs2.txt > @@ -74,6 +74,9 @@ norecovery Disable recovery of the filesystem on mount. > This disables every write access on the device for > read-only mounts or snapshots. This option will fail > for r/w mounts on an unclean volume. > +discard Issue discard/TRIM commands to the underlying block > + device when blocks are freed. This is useful for SSD > + devices and sparse/thinly-provisioned LUNs. > > NILFS2 usage > ============ > diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c > index 17584c5..db6869f 100644 > --- a/fs/nilfs2/segment.c > +++ b/fs/nilfs2/segment.c > @@ -2560,6 +2560,9 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, > set_current_state(TASK_INTERRUPTIBLE); > schedule_timeout(sci->sc_interval); > } > + if (nilfs_test_opt(sbi, DISCARD)) > + nilfs_discard_segments(nilfs, sci->sc_freesegs, > + sci->sc_nfreesegs); > > out_unlock: > sci->sc_freesegs = NULL; > diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c > index 8173fae..3f88401 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) > seq_printf(seq, ",order=strict"); > if (nilfs_test_opt(sbi, NORECOVERY)) > seq_printf(seq, ",norecovery"); > + if (nilfs_test_opt(sbi, DISCARD)) > + seq_printf(seq, ",discard"); > > return 0; > } > @@ -550,7 +552,7 @@ static const struct export_operations nilfs_export_ops = { > enum { > Opt_err_cont, Opt_err_panic, Opt_err_ro, > Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, > - Opt_err, > + Opt_discard, Opt_err, > }; > > static match_table_t tokens = { > @@ -561,6 +563,7 @@ static match_table_t tokens = { > {Opt_snapshot, "cp=%u"}, > {Opt_order, "order=%s"}, > {Opt_norecovery, "norecovery"}, > + {Opt_discard, "discard"}, > {Opt_err, NULL} > }; > > @@ -614,6 +617,9 @@ static int parse_options(char *options, struct super_block *sb) > case Opt_norecovery: > nilfs_set_opt(sbi, NORECOVERY); > break; > + case Opt_discard: > + nilfs_set_opt(sbi, DISCARD); > + break; > default: > printk(KERN_ERR > "NILFS: Unrecognized mount option \"%s\"\n", p); > diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c > index 6241e17..9ad5b83 100644 > --- a/fs/nilfs2/the_nilfs.c > +++ b/fs/nilfs2/the_nilfs.c > @@ -646,6 +646,51 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) > goto out; > } > > +void nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump, > + size_t nsegs) > +{ > + sector_t seg_start, seg_end; > + sector_t start = 0, nblocks = 0; > + unsigned int sects_per_block; > + __u64 *sn; > + int ret = 0; > + > + sects_per_block = (1 << nilfs->ns_blocksize_bits) / > + bdev_logical_block_size(nilfs->ns_bdev); > + for (sn = segnump; sn < segnump + nsegs; sn++) { > + nilfs_get_segment_range(nilfs, *sn, &seg_start, &seg_end); > + > + if (!nblocks) { > + start = seg_start; > + nblocks = seg_end - seg_start + 1; > + } else if (start + nblocks == seg_start) { > + nblocks += seg_end - seg_start + 1; > + } else { > + ret = blkdev_issue_discard(nilfs->ns_bdev, > + start * sects_per_block, > + nblocks * sects_per_block, > + GFP_NOFS, > + DISCARD_FL_BARRIER); > + if (ret < 0) > + goto failed; > + nblocks = 0; > + } > + } > + if (nblocks) { > + ret = blkdev_issue_discard(nilfs->ns_bdev, > + start * sects_per_block, > + nblocks * sects_per_block, > + GFP_NOFS, DISCARD_FL_BARRIER); > + if (ret < 0) > + goto failed; > + } > + return; > + failed: > + printk(KERN_WARNING "NILFS warning: error %d on discard request, " > + "turning discards off for the device\n", ret); > + nilfs_clear_opt(nilfs->ns_current, DISCARD); I prefer to move these error handling code to the caller to remove the nilfs->ns_current reference. You can change nilfs_discard_segments to make it return error codes, and then the above printk and nilfs_clear_opt() can be moved to the caller which has a valid sbi reference. > +} > + > int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) > { > struct inode *dat = nilfs_dat_inode(nilfs); > diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h > index 589786e..8e3de6e 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 *); > void put_nilfs(struct the_nilfs *); > int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); > int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); > +void nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); > int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); > struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); > 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 3fe02cf..640702e 100644 > --- a/include/linux/nilfs2_fs.h > +++ b/include/linux/nilfs2_fs.h > @@ -153,6 +153,7 @@ struct nilfs_super_root { > semantics also for data */ > #define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during > mount-time recovery */ > +#define NILFS_MOUNT_DISCARD 0x8000 /* Issue DISCARD requests */ > > > /** > -- > 1.5.6.5 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html Regards, Ryusuke Konishi -- To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html