mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-30 19:15:14 +00:00
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
6 changed files with 60 additions and 1 deletions
|
@ -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,
|
||||||
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)
|
||||||
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 = {
|
||||||
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 = {
|
||||||
{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)
|
||||||
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)
|
||||||
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 *);
|
||||||
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 {
|
||||||
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 */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue