[PATCH 2/2] bcache: send request to backing when detaching and there is no dirty

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If bcache device is detaching and there is no dirty data in cache,
we should send request to backing rather than get dc->count to do
cached_dev_read or cached_dev_write.

Otherwise, if there are lots of requests here to call cached_dev_get(dc),
we could never put dc->count to be 0 where calling schedule_work(&dc->detach) to finish
detaching, that means this detaching will never finish.

This commit introduce a new bit in bcache dev flags BCACHE_DEV_DETACHING_WB_DONE, this
will be set when we finish writeback in detaching and cleared in cached_dev_detach_finish().
when the request find BCACHE_DEV_DETACHING_WB_DONE is set, that means, this request should
go into backing device directly.

Signed-off-by: Dongsheng Yang <dongsheng.yang@xxxxxxxxxxxx>
---
 drivers/md/bcache/bcache.h    |  1 +
 drivers/md/bcache/request.c   | 11 ++++++++++-
 drivers/md/bcache/super.c     |  1 +
 drivers/md/bcache/writeback.c |  7 +++++++
 4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 870f146..aedf211 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -265,6 +265,7 @@ struct bcache_device {
 #define BCACHE_DEV_UNLINK_DONE		2
 #define BCACHE_DEV_WB_RUNNING		3
 #define BCACHE_DEV_RATE_DW_RUNNING	4
+#define BCACHE_DEV_DETACHING_WB_DONE	5
 	int			nr_stripes;
 	unsigned int		stripe_size;
 	atomic_t		*stripe_sectors_dirty;
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index c7cadaa..94c44f2 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -1194,7 +1194,16 @@ blk_qc_t cached_dev_submit_bio(struct bio *bio)
 	bio_set_dev(bio, dc->bdev);
 	bio->bi_iter.bi_sector += dc->sb.data_offset;
 
-	if (cached_dev_get(dc)) {
+	/*
+	 * If BCACHE_DEV_DETACHING_WB_DONE is set,
+	 * we should send request to backing rather than get dc->count to do
+	 * cached_dev_read or cached_dev_write. Otherwise, if there are lots
+	 * of requests here to call cached_dev_get(dc), we could never put
+	 * dc->count to be 0 where calling schedule_work(&dc->detach) to finish
+	 * detaching, that means this detaching will never finish.
+	 */
+	if (!test_bit(BCACHE_DEV_DETACHING_WB_DONE, &dc->disk.flags) &&
+	    cached_dev_get(dc)) {
 		s = search_alloc(bio, d);
 		trace_bcache_request_start(s->d, bio);
 
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 9298fc7..3c32ddb 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1147,6 +1147,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
 	bcache_device_detach(&dc->disk);
 	list_move(&dc->list, &uncached_devices);
 
+	clear_bit(BCACHE_DEV_DETACHING_WB_DONE, &dc->disk.flags);
 	clear_bit(BCACHE_DEV_DETACHING, &dc->disk.flags);
 	clear_bit(BCACHE_DEV_UNLINK_DONE, &dc->disk.flags);
 
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 2cd0340..6799f99 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -714,6 +714,13 @@ static int bch_writeback_thread(void *arg)
 				bch_write_bdev_super(dc, &cl);
 				closure_sync(&cl);
 
+				/*
+				 * BCACHE_DEV_DETACHING_WB_DONE will tell
+				 * request should be sent directly to backing
+				 * device directly, without getting dc->count.
+				 */
+				set_bit(BCACHE_DEV_DETACHING_WB_DONE,
+					&dc->disk.flags);
 				up_write(&dc->writeback_lock);
 				break;
 			}
-- 
1.8.3.1




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux ARM Kernel]     [Linux Filesystem Development]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux