* [PATCH] Separate bch_moving_gc() from bch_btree_gc()
@ 2023-06-27 9:21 Mingzhe Zou
2023-06-27 14:41 ` kernel test robot
2023-06-27 17:34 ` kernel test robot
0 siblings, 2 replies; 3+ messages in thread
From: Mingzhe Zou @ 2023-06-27 9:21 UTC (permalink / raw)
To: colyli, linux-bcache; +Cc: bcache, zoumingzhe
From: Mingzhe Zou <zoumingzhe@qq.com>
Moving gc uses cache->heap to defragment disk. Unlike btree gc,
moving gc only takes up part of the disk bandwidth.
The number of heap is constant. However, the buckets released by
each moving gc is limited. So bch_moving_gc() needs to be called
multiple times.
If bch_gc_thread() always calls bch_btree_gc(), it will block
the IO request.This patch allows bch_gc_thread() to only call
bch_moving_gc() when there are many fragments.
Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
---
drivers/md/bcache/bcache.h | 4 ++-
drivers/md/bcache/btree.c | 62 ++++++++++++++++++++++++++++++++++--
drivers/md/bcache/movinggc.c | 2 ++
3 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 5a79bb3c272f..155deff0ce05 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -461,7 +461,8 @@ struct cache {
* until a gc finishes - otherwise we could pointlessly burn a ton of
* cpu
*/
- unsigned int invalidate_needs_gc;
+ unsigned int invalidate_needs_gc:1;
+ unsigned int only_moving_gc:1;
bool discard; /* Get rid of? */
@@ -629,6 +630,7 @@ struct cache_set {
struct gc_stat gc_stats;
size_t nbuckets;
size_t avail_nbuckets;
+ size_t fragment_nbuckets;
struct task_struct *gc_thread;
/* Where in the btree gc currently is */
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 68b9d7ca864e..de28d5c991a1 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -88,6 +88,7 @@
* Test module load/unload
*/
+#define COPY_GC_PERCENT 5
#define MAX_NEED_GC 64
#define MAX_SAVE_PRIO 72
#define MAX_GC_TIMES 100
@@ -1705,6 +1706,7 @@ static void btree_gc_start(struct cache_set *c)
mutex_lock(&c->bucket_lock);
+ set_gc_sectors(c);
c->gc_mark_valid = 0;
c->gc_done = ZERO_KEY;
@@ -1825,8 +1827,47 @@ static void bch_btree_gc(struct cache_set *c)
memcpy(&c->gc_stats, &stats, sizeof(struct gc_stat));
trace_bcache_gc_end(c);
+}
+
+static bool moving_gc_should_run(struct cache_set *c)
+{
+ struct cache *ca = c->cache;
+ size_t moving_gc_threshold = ca->sb.bucket_size >> 2, frag_percent;
+ unsigned long used_buckets = 0, frag_buckets = 0, move_buckets = 0;
+ unsigned long dirty_sectors = 0, frag_sectors, used_sectors;
+
+ if (c->gc_stats.in_use > bch_cutoff_writeback_sync)
+ return true;
- bch_moving_gc(c);
+ mutex_lock(&c->bucket_lock);
+ for_each_bucket(b, ca) {
+ if (GC_MARK(b) != GC_MARK_DIRTY)
+ continue;
+
+ used_buckets++;
+
+ used_sectors = GC_SECTORS_USED(b);
+ dirty_sectors += used_sectors;
+
+ if (used_sectors < ca->sb.bucket_size)
+ frag_buckets++;
+
+ if (used_sectors <= moving_gc_threshold)
+ move_buckets++;
+ }
+ mutex_unlock(&c->bucket_lock);
+
+ c->fragment_nbuckets = frag_buckets;
+ frag_sectors = used_buckets * ca->sb.bucket_size - dirty_sectors;
+ frag_percent = div_u64(frag_sectors * 100, ca->sb.bucket_size * c->nbuckets)
+
+ if (move_buckets > ca->heap.size)
+ return true;
+
+ if (frag_percent >= COPY_GC_PERCENT)
+ return true;
+
+ return false;
}
static bool gc_should_run(struct cache_set *c)
@@ -1839,6 +1880,19 @@ static bool gc_should_run(struct cache_set *c)
if (atomic_read(&c->sectors_to_gc) < 0)
return true;
+ /*
+ * Moving gc uses cache->heap to defragment disk. Unlike btree gc,
+ * moving gc only takes up part of the disk bandwidth.
+ * The number of heap is constant. However, the buckets released by
+ * each moving gc is limited. So bch_moving_gc() needs to be called
+ * multiple times. If bch_gc_thread() always calls bch_btree_gc(),
+ * it will block the IO request.
+ */
+ if (c->copy_gc_enabled && moving_gc_should_run(c)) {
+ ca->only_moving_gc = 1;
+ return true;
+ }
+
return false;
}
@@ -1856,8 +1910,10 @@ static int bch_gc_thread(void *arg)
test_bit(CACHE_SET_IO_DISABLE, &c->flags))
break;
- set_gc_sectors(c);
- bch_btree_gc(c);
+ if (!c->cache->only_moving_gc)
+ bch_btree_gc(c);
+
+ bch_moving_gc(c);
}
wait_for_kthread_stop();
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 9f32901fdad1..04da088cefe8 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -200,6 +200,8 @@ void bch_moving_gc(struct cache_set *c)
struct bucket *b;
unsigned long sectors_to_move, reserve_sectors;
+ c->cache->only_moving_gc = 0;
+
if (!c->copy_gc_enabled)
return;
--
2.17.1.windows.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] Separate bch_moving_gc() from bch_btree_gc()
2023-06-27 9:21 [PATCH] Separate bch_moving_gc() from bch_btree_gc() Mingzhe Zou
@ 2023-06-27 14:41 ` kernel test robot
2023-06-27 17:34 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2023-06-27 14:41 UTC (permalink / raw)
To: Mingzhe Zou, colyli, linux-bcache; +Cc: llvm, oe-kbuild-all, bcache, zoumingzhe
Hi Mingzhe,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.4 next-20230627]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Mingzhe-Zou/Separate-bch_moving_gc-from-bch_btree_gc/20230627-172221
base: linus/master
patch link: https://lore.kernel.org/r/20230627092122.197-1-mingzhe.zou%40easystack.cn
patch subject: [PATCH] Separate bch_moving_gc() from bch_btree_gc()
config: powerpc-randconfig-r012-20230627 (https://download.01.org/0day-ci/archive/20230627/202306272212.276Fkm0f-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce: (https://download.01.org/0day-ci/archive/20230627/202306272212.276Fkm0f-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306272212.276Fkm0f-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/md/bcache/btree.c:1839:27: error: use of undeclared identifier 'bch_cutoff_writeback_sync'
1839 | if (c->gc_stats.in_use > bch_cutoff_writeback_sync)
| ^
>> drivers/md/bcache/btree.c:1843:18: error: use of undeclared identifier 'b'
1843 | for_each_bucket(b, ca) {
| ^
>> drivers/md/bcache/btree.c:1843:18: error: use of undeclared identifier 'b'
>> drivers/md/bcache/btree.c:1843:18: error: use of undeclared identifier 'b'
drivers/md/bcache/btree.c:1844:15: error: use of undeclared identifier 'b'
1844 | if (GC_MARK(b) != GC_MARK_DIRTY)
| ^
drivers/md/bcache/btree.c:1849:34: error: use of undeclared identifier 'b'
1849 | used_sectors = GC_SECTORS_USED(b);
| ^
>> drivers/md/bcache/btree.c:1862:78: error: expected ';' after expression
1862 | frag_percent = div_u64(frag_sectors * 100, ca->sb.bucket_size * c->nbuckets)
| ^
| ;
7 errors generated.
vim +/bch_cutoff_writeback_sync +1839 drivers/md/bcache/btree.c
1831
1832 static bool moving_gc_should_run(struct cache_set *c)
1833 {
1834 struct cache *ca = c->cache;
1835 size_t moving_gc_threshold = ca->sb.bucket_size >> 2, frag_percent;
1836 unsigned long used_buckets = 0, frag_buckets = 0, move_buckets = 0;
1837 unsigned long dirty_sectors = 0, frag_sectors, used_sectors;
1838
> 1839 if (c->gc_stats.in_use > bch_cutoff_writeback_sync)
1840 return true;
1841
1842 mutex_lock(&c->bucket_lock);
> 1843 for_each_bucket(b, ca) {
1844 if (GC_MARK(b) != GC_MARK_DIRTY)
1845 continue;
1846
1847 used_buckets++;
1848
1849 used_sectors = GC_SECTORS_USED(b);
1850 dirty_sectors += used_sectors;
1851
1852 if (used_sectors < ca->sb.bucket_size)
1853 frag_buckets++;
1854
1855 if (used_sectors <= moving_gc_threshold)
1856 move_buckets++;
1857 }
1858 mutex_unlock(&c->bucket_lock);
1859
1860 c->fragment_nbuckets = frag_buckets;
1861 frag_sectors = used_buckets * ca->sb.bucket_size - dirty_sectors;
> 1862 frag_percent = div_u64(frag_sectors * 100, ca->sb.bucket_size * c->nbuckets)
1863
1864 if (move_buckets > ca->heap.size)
1865 return true;
1866
1867 if (frag_percent >= COPY_GC_PERCENT)
1868 return true;
1869
1870 return false;
1871 }
1872
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Separate bch_moving_gc() from bch_btree_gc()
2023-06-27 9:21 [PATCH] Separate bch_moving_gc() from bch_btree_gc() Mingzhe Zou
2023-06-27 14:41 ` kernel test robot
@ 2023-06-27 17:34 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2023-06-27 17:34 UTC (permalink / raw)
To: Mingzhe Zou, colyli, linux-bcache; +Cc: oe-kbuild-all, bcache, zoumingzhe
Hi Mingzhe,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.4 next-20230627]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Mingzhe-Zou/Separate-bch_moving_gc-from-bch_btree_gc/20230627-172221
base: linus/master
patch link: https://lore.kernel.org/r/20230627092122.197-1-mingzhe.zou%40easystack.cn
patch subject: [PATCH] Separate bch_moving_gc() from bch_btree_gc()
config: arc-randconfig-r043-20230627 (https://download.01.org/0day-ci/archive/20230628/202306280137.Dirtk7fY-lkp@intel.com/config)
compiler: arc-elf-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230628/202306280137.Dirtk7fY-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306280137.Dirtk7fY-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/md/bcache/btree.c: In function 'moving_gc_should_run':
>> drivers/md/bcache/btree.c:1839:34: error: 'bch_cutoff_writeback_sync' undeclared (first use in this function)
1839 | if (c->gc_stats.in_use > bch_cutoff_writeback_sync)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/md/bcache/btree.c:1839:34: note: each undeclared identifier is reported only once for each function it appears in
In file included from drivers/md/bcache/btree.c:24:
>> drivers/md/bcache/btree.c:1843:25: error: 'b' undeclared (first use in this function)
1843 | for_each_bucket(b, ca) {
| ^
drivers/md/bcache/bcache.h:890:14: note: in definition of macro 'for_each_bucket'
890 | for (b = (ca)->buckets + (ca)->sb.first_bucket; \
| ^
>> drivers/md/bcache/btree.c:1862:85: error: expected ';' before 'if'
1862 | frag_percent = div_u64(frag_sectors * 100, ca->sb.bucket_size * c->nbuckets)
| ^
| ;
1863 |
1864 | if (move_buckets > ca->heap.size)
| ~~
vim +/bch_cutoff_writeback_sync +1839 drivers/md/bcache/btree.c
1831
1832 static bool moving_gc_should_run(struct cache_set *c)
1833 {
1834 struct cache *ca = c->cache;
1835 size_t moving_gc_threshold = ca->sb.bucket_size >> 2, frag_percent;
1836 unsigned long used_buckets = 0, frag_buckets = 0, move_buckets = 0;
1837 unsigned long dirty_sectors = 0, frag_sectors, used_sectors;
1838
> 1839 if (c->gc_stats.in_use > bch_cutoff_writeback_sync)
1840 return true;
1841
1842 mutex_lock(&c->bucket_lock);
> 1843 for_each_bucket(b, ca) {
1844 if (GC_MARK(b) != GC_MARK_DIRTY)
1845 continue;
1846
1847 used_buckets++;
1848
1849 used_sectors = GC_SECTORS_USED(b);
1850 dirty_sectors += used_sectors;
1851
1852 if (used_sectors < ca->sb.bucket_size)
1853 frag_buckets++;
1854
1855 if (used_sectors <= moving_gc_threshold)
1856 move_buckets++;
1857 }
1858 mutex_unlock(&c->bucket_lock);
1859
1860 c->fragment_nbuckets = frag_buckets;
1861 frag_sectors = used_buckets * ca->sb.bucket_size - dirty_sectors;
> 1862 frag_percent = div_u64(frag_sectors * 100, ca->sb.bucket_size * c->nbuckets)
1863
1864 if (move_buckets > ca->heap.size)
1865 return true;
1866
1867 if (frag_percent >= COPY_GC_PERCENT)
1868 return true;
1869
1870 return false;
1871 }
1872
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-06-27 17:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-27 9:21 [PATCH] Separate bch_moving_gc() from bch_btree_gc() Mingzhe Zou
2023-06-27 14:41 ` kernel test robot
2023-06-27 17:34 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).