[RFT PATCH] mmc: block: implement REQ_OP_WRITE_ZEROES

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

 



card->erased_byte read from SCR(for SD cards) or EXT_CSD[181](for eMMC)
indicates whether the TRIM or ERASE make the erased data content zeros,
but DISCARD doesn't. Use the fact to implement REQ_OP_WRITE_ZEROES.

Cc: Faiz Abbas <faiz_abbas@xxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Signed-off-by: Shawn Lin <shawn.lin@xxxxxxxxxxxxxx>
---
Hi Faiz,
Would you like to test this patch to see if it could
solve your performance drop on the first write after
filesystem creation?

 drivers/mmc/core/block.c | 10 +++++++++-
 drivers/mmc/core/queue.c |  3 +++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index a0b9102..7d59887 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1132,7 +1132,14 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 	from = blk_rq_pos(req);
 	nr = blk_rq_sectors(req);
 
-	if (mmc_can_discard(card))
+	/*
+	 * DISCARD says the contents of a write block where the discard
+	 * function has been applied shold be 'don't care'. But TRIM and
+	 * ERASE should have explicit '1' or '0' indicated by
+	 * card->erased_byte. So REQ_OP_WRITE_ZEROES should use TRIM/ERASE
+	 * instead.
+	 */
+	if (mmc_can_discard(card) && req_op(req) != REQ_OP_WRITE_ZEROES)
 		arg = MMC_DISCARD_ARG;
 	else if (mmc_can_trim(card))
 		arg = MMC_TRIM_ARG;
@@ -2228,6 +2235,7 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req)
 			mmc_blk_issue_drv_op(mq, req);
 			break;
 		case REQ_OP_DISCARD:
+		case REQ_OP_WRITE_ZEROES:
 			mmc_blk_issue_discard_rq(mq, req);
 			break;
 		case REQ_OP_SECURE_ERASE:
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 56e9a80..2657a46 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -51,6 +51,7 @@ static enum mmc_issue_type mmc_cqe_issue_type(struct mmc_host *host,
 	case REQ_OP_DRV_OUT:
 	case REQ_OP_DISCARD:
 	case REQ_OP_SECURE_ERASE:
+	case REQ_OP_WRITE_ZEROES:
 		return MMC_ISSUE_SYNC;
 	case REQ_OP_FLUSH:
 		return mmc_cqe_can_dcmd(host) ? MMC_ISSUE_DCMD : MMC_ISSUE_SYNC;
@@ -193,6 +194,8 @@ static void mmc_queue_setup_discard(struct request_queue *q,
 		q->limits.discard_granularity = 0;
 	if (mmc_can_secure_erase_trim(card))
 		blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
+	if (!card->erased_byte)
+		q->limits.max_write_zeroes_sectors = max_discard;
 }
 
 /**
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux