mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
724e6d3fe8
commit
e902ec9906
|
@ -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
|
||||
============
|
||||
|
|
|
@ -2560,6 +2560,16 @@ 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)) {
|
||||
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:
|
||||
sci->sc_freesegs = NULL;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -646,6 +646,44 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
|
|||
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)
|
||||
{
|
||||
struct inode *dat = nilfs_dat_inode(nilfs);
|
||||
|
|
|
@ -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 *);
|
||||
int 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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue