提交 e902ec99 编写于 作者: J Jiro SEKIBA 提交者: Ryusuke Konishi

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: NJiro SEKIBA <jir@unicus.jp>
Signed-off-by: NRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
上级 724e6d3f
...@@ -74,6 +74,9 @@ norecovery Disable recovery of the filesystem on mount. ...@@ -74,6 +74,9 @@ norecovery Disable recovery of the filesystem on mount.
This disables every write access on the device for This disables every write access on the device for
read-only mounts or snapshots. This option will fail read-only mounts or snapshots. This option will fail
for r/w mounts on an unclean volume. 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 NILFS2 usage
============ ============
......
...@@ -2560,6 +2560,16 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, ...@@ -2560,6 +2560,16 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(sci->sc_interval); schedule_timeout(sci->sc_interval);
} }
if (nilfs_test_opt(sbi, DISCARD)) {
int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs,
sci->sc_nfreesegs);
if (ret) {
printk(KERN_WARNING
"NILFS warning: error %d on discard request, "
"turning discards off for the device\n", ret);
nilfs_clear_opt(sbi, DISCARD);
}
}
out_unlock: out_unlock:
sci->sc_freesegs = NULL; sci->sc_freesegs = NULL;
......
...@@ -481,6 +481,8 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) ...@@ -481,6 +481,8 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
seq_printf(seq, ",order=strict"); seq_printf(seq, ",order=strict");
if (nilfs_test_opt(sbi, NORECOVERY)) if (nilfs_test_opt(sbi, NORECOVERY))
seq_printf(seq, ",norecovery"); seq_printf(seq, ",norecovery");
if (nilfs_test_opt(sbi, DISCARD))
seq_printf(seq, ",discard");
return 0; return 0;
} }
...@@ -550,7 +552,7 @@ static const struct export_operations nilfs_export_ops = { ...@@ -550,7 +552,7 @@ static const struct export_operations nilfs_export_ops = {
enum { enum {
Opt_err_cont, Opt_err_panic, Opt_err_ro, Opt_err_cont, Opt_err_panic, Opt_err_ro,
Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery,
Opt_err, Opt_discard, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -561,6 +563,7 @@ static match_table_t tokens = { ...@@ -561,6 +563,7 @@ static match_table_t tokens = {
{Opt_snapshot, "cp=%u"}, {Opt_snapshot, "cp=%u"},
{Opt_order, "order=%s"}, {Opt_order, "order=%s"},
{Opt_norecovery, "norecovery"}, {Opt_norecovery, "norecovery"},
{Opt_discard, "discard"},
{Opt_err, NULL} {Opt_err, NULL}
}; };
...@@ -614,6 +617,9 @@ static int parse_options(char *options, struct super_block *sb) ...@@ -614,6 +617,9 @@ static int parse_options(char *options, struct super_block *sb)
case Opt_norecovery: case Opt_norecovery:
nilfs_set_opt(sbi, NORECOVERY); nilfs_set_opt(sbi, NORECOVERY);
break; break;
case Opt_discard:
nilfs_set_opt(sbi, DISCARD);
break;
default: default:
printk(KERN_ERR printk(KERN_ERR
"NILFS: Unrecognized mount option \"%s\"\n", p); "NILFS: Unrecognized mount option \"%s\"\n", p);
......
...@@ -646,6 +646,44 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) ...@@ -646,6 +646,44 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
goto out; goto out;
} }
int 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)
return ret;
nblocks = 0;
}
}
if (nblocks)
ret = blkdev_issue_discard(nilfs->ns_bdev,
start * sects_per_block,
nblocks * sects_per_block,
GFP_NOFS, DISCARD_FL_BARRIER);
return ret;
}
int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks)
{ {
struct inode *dat = nilfs_dat_inode(nilfs); struct inode *dat = nilfs_dat_inode(nilfs);
......
...@@ -221,6 +221,7 @@ struct the_nilfs *find_or_create_nilfs(struct block_device *); ...@@ -221,6 +221,7 @@ struct the_nilfs *find_or_create_nilfs(struct block_device *);
void put_nilfs(struct the_nilfs *); void put_nilfs(struct the_nilfs *);
int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
......
...@@ -153,6 +153,7 @@ struct nilfs_super_root { ...@@ -153,6 +153,7 @@ struct nilfs_super_root {
semantics also for data */ semantics also for data */
#define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during #define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during
mount-time recovery */ mount-time recovery */
#define NILFS_MOUNT_DISCARD 0x8000 /* Issue DISCARD requests */
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册