* [PATCHv2] nilfs2: issue discard request after cleaning segments
@ 2010-01-30 4:28 Jiro SEKIBA
[not found] ` <87fx5onrln.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Jiro SEKIBA @ 2010-01-30 4:28 UTC (permalink / raw)
To: linux-nilfs-u79uwXL29TY76Z2rM5mHXA; +Cc: Ryusuke Konishi
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-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
---
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);
+}
+
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-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread[parent not found: <87fx5onrln.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCHv2] nilfs2: issue discard request after cleaning segments [not found] ` <87fx5onrln.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org> @ 2010-01-30 7:11 ` Ryusuke Konishi [not found] ` <20100130.161157.55833148.ryusuke-sG5X7nlA6pw@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: Ryusuke Konishi @ 2010-01-30 7:11 UTC (permalink / raw) To: jir-hfpbi5WX9J54Eiagz67IpQ; +Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA Hi Sekiba-san, On Sat, 30 Jan 2010 13:28:52 +0900, Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> 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-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org> > Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> 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-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > 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-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <20100130.161157.55833148.ryusuke-sG5X7nlA6pw@public.gmane.org>]
* [PATCHv3] nilfs2: issue discard request after cleaning segments [not found] ` <20100130.161157.55833148.ryusuke-sG5X7nlA6pw@public.gmane.org> @ 2010-01-30 9:06 ` Jiro SEKIBA [not found] ` <877hr07yhw.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: Jiro SEKIBA @ 2010-01-30 9:06 UTC (permalink / raw) To: linux-nilfs-u79uwXL29TY76Z2rM5mHXA; +Cc: Ryusuke Konishi Hi, Konishi-san, thank you for the comment. I revised the patch so as to remove the nilfs->ns_current reference. I introduce new variable "ret" instead of reuseing "err" in nilfs_clean_segments so that error of discard request won't stop GC process. 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-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org> Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> --- Documentation/filesystems/nilfs2.txt | 3 ++ fs/nilfs2/segment.c | 10 +++++++++ fs/nilfs2/super.c | 8 ++++++- fs/nilfs2/the_nilfs.c | 38 ++++++++++++++++++++++++++++++++++ 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..9eae057 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, 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; 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..92733d5 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) 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); diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 589786e..fd057f8 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 *); +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); 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-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 4+ messages in thread
[parent not found: <877hr07yhw.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCHv3] nilfs2: issue discard request after cleaning segments [not found] ` <877hr07yhw.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org> @ 2010-01-30 10:10 ` Ryusuke Konishi 0 siblings, 0 replies; 4+ messages in thread From: Ryusuke Konishi @ 2010-01-30 10:10 UTC (permalink / raw) To: jir-hfpbi5WX9J54Eiagz67IpQ; +Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA On Sat, 30 Jan 2010 18:06:35 +0900, Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> wrote: > Hi, > > Konishi-san, thank you for the comment. > > I revised the patch so as to remove the nilfs->ns_current reference. > > I introduce new variable "ret" instead of reuseing "err" in nilfs_clean_segments > so that error of discard request won't stop GC process. > > > 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-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org> > Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> Applied, thank you. Ryusuke Konishi > --- > Documentation/filesystems/nilfs2.txt | 3 ++ > fs/nilfs2/segment.c | 10 +++++++++ > fs/nilfs2/super.c | 8 ++++++- > fs/nilfs2/the_nilfs.c | 38 ++++++++++++++++++++++++++++++++++ > 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..9eae057 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, > 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; > 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..92733d5 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) > 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); > diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h > index 589786e..fd057f8 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 *); > +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); > 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-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-01-30 10:10 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-30 4:28 [PATCHv2] nilfs2: issue discard request after cleaning segments Jiro SEKIBA
[not found] ` <87fx5onrln.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
2010-01-30 7:11 ` Ryusuke Konishi
[not found] ` <20100130.161157.55833148.ryusuke-sG5X7nlA6pw@public.gmane.org>
2010-01-30 9:06 ` [PATCHv3] " Jiro SEKIBA
[not found] ` <877hr07yhw.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
2010-01-30 10:10 ` Ryusuke Konishi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox