From patchwork Thu Aug 14 09:50:33 2014
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Li Wang
X-Patchwork-Id: 379888
X-Patchwork-Delegate: dwmw2@infradead.org
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Received: from bombadil.infradead.org (bombadil.infradead.org
[IPv6:2001:1868:205::9])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256
bits)) (No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 21CF71400B5
for ;
Thu, 14 Aug 2014 19:52:52 +1000 (EST)
Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux))
id 1XHrgm-000689-Et; Thu, 14 Aug 2014 09:51:20 +0000
Received: from mail.windriver.com ([147.11.1.11])
by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat
Linux)) id 1XHrgf-0005ym-Kj; Thu, 14 Aug 2014 09:51:14 +0000
Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com
[147.11.189.40])
by mail.windriver.com (8.14.9/8.14.5) with ESMTP id s7E9oomT021133
(version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL);
Thu, 14 Aug 2014 02:50:50 -0700 (PDT)
Received: from lwang1-OptiPlex-9010.corp.ad.wrs.com (128.224.162.134) by
ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server id
14.3.174.1; Thu, 14 Aug 2014 02:50:50 -0700
From: Li Wang
To: , ,
Subject: [PATCH] mtd: put flash block erasing into wait queue,
if has any thread in queue
Date: Thu, 14 Aug 2014 17:50:33 +0800
Message-ID: <1408009833-26494-2-git-send-email-li.wang@windriver.com>
X-Mailer: git-send-email 1.7.9.5
In-Reply-To: <1408009833-26494-1-git-send-email-li.wang@windriver.com>
References: <1408009833-26494-1-git-send-email-li.wang@windriver.com>
MIME-Version: 1.0
X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
X-CRM114-CacheID: sfid-20140814_025113_699823_A08D6E08
X-CRM114-Status: GOOD ( 11.96 )
X-Spam-Score: -3.0 (---)
X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary:
Content analysis details: (-3.0 points)
pts rule name description
---- ----------------------
--------------------------------------------------
-2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/,
medium trust [147.11.1.11 listed in list.dnswl.org]
-0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay
domain
Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org
X-BeenThere: linux-mtd@lists.infradead.org
X-Mailman-Version: 2.1.18-1
Precedence: list
List-Id: Linux MTD discussion mailing list
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Sender: "linux-mtd"
Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org
When erases many flash blocks, it maybe stop flash writing operation:
=====
erase thread:
for(;;) {
do_erase_oneblock() {
mutex_lock(&chip->mutex);
chip->state = FL_ERASING;
mutex_unlock(&chip->mutex);
msleep(); <--- erase wait
mutex_lock(&chip->mutex);
chip->state = FL_READY;
mutex_unlock(&chip->mutex); <--- finish one block erasing
}
}
write thread:
retry:
mutex_lock(&cfi->chips[chipnum].mutex);
if (cfi->chips[chipnum].state != FL_READY) {
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&cfi->chips[chipnum].wq, &wait);
mutex_unlock(&cfi->chips[chipnum].mutex);
schedule(); <--- write wait
remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
goto retry;
=====
Only when finishes one block erasing, writing operation just has chance to run.
But, if writing operation is put into wait queue(write wait), the mutex_unlock
(finish one block erasing) can not wake up writing operation. So, if many blocks
need erase, writing operation has no chance to run.
it will cause the following backtrace:
=====
INFO: task sh:727 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
sh D 0fe76ad0 0 727 711 0x00000000
Call Trace:
[df0cdc40] [00000002] 0x2 (unreliable)
[df0cdd00] [c0008974] __switch_to+0x64/0xd8
[df0cdd10] [c043f2e4] schedule+0x218/0x408
[df0cdd60] [c04401f4] __mutex_lock_slowpath+0xd0/0x174
[df0cdda0] [c044087c] mutex_lock+0x5c/0x60
[df0cddc0] [c00ff18c] do_truncate+0x60/0xa8
[df0cde10] [c010d1d0] do_last+0x5a0/0x6d0
[df0cde40] [c010f778] do_filp_open+0x1d4/0x5e8
[df0cdf20] [c00fe0d0] do_sys_open+0x64/0x19c
[df0cdf40] [c0010d04] ret_from_syscall+0x0/0x4
--- Exception: c01 at 0xfe76ad0
LR = 0xffd3ae8
...
sh D 0fe77068 0 607 590 0x00000000
Call Trace:
[dbca98e0] [c009ad4c] rcu_process_callbacks+0x38/0x4c (unreliable)
[dbca99a0] [c0008974] __switch_to+0x64/0xd8
[dbca99b0] [c043f2e4] schedule+0x218/0x408
[dbca9a00] [c034bfa4] cfi_amdstd_write_words+0x364/0x480
[dbca9a80] [c034c9b4] cfi_amdstd_write_buffers+0x8f4/0xca8
[dbca9b10] [c03437ac] part_write+0xb0/0xe4
[dbca9b20] [c02051f8] jffs2_flash_direct_writev+0xdc/0x140
[dbca9b70] [c02079ac] jffs2_flash_writev+0x38c/0x4fc
[dbca9bc0] [c01fc6ac] jffs2_write_dnode+0x140/0x5bc
[dbca9c40] [c01fd0dc] jffs2_write_inode_range+0x288/0x514
[dbca9cd0] [c01f5ed4] jffs2_write_end+0x190/0x37c
[dbca9d10] [c00bf2f0] generic_file_buffered_write+0x100/0x26c
[dbca9da0] [c00c1828] __generic_file_aio_write+0x2c0/0x4fc
[dbca9e10] [c00c1ad4] generic_file_aio_write+0x70/0xf0
[dbca9e40] [c0100398] do_sync_write+0xac/0x120
[dbca9ee0] [c0101088] vfs_write+0xb4/0x184
[dbca9f00] [c01012cc] sys_write+0x50/0x10c
[dbca9f40] [c0010d04] ret_from_syscall+0x0/0x4
--- Exception: c01 at 0xfe77068
LR = 0xffd3c8c
...
flash_erase R running 0 869 32566 0x00000000
Call Trace:
[dbc6dae0] [c0017ac0] kunmap_atomic+0x14/0x3c (unreliable)
[dbc6dba0] [c0008974] __switch_to+0x64/0xd8
[dbc6dbb0] [c043f2e4] schedule+0x218/0x408
[dbc6dc00] [c043fbe4] schedule_timeout+0x170/0x2cc
[dbc6dc50] [c00531f0] msleep+0x1c/0x34
[dbc6dc60] [c034d538] do_erase_oneblock+0x7d0/0x944
[dbc6dcd0] [c0349dfc] cfi_varsize_frob+0x1a8/0x2cc
[dbc6dd20] [c034e4d4] cfi_amdstd_erase_varsize+0x30/0x60
[dbc6dd30] [c0343abc] part_erase+0x80/0x104
[dbc6dd40] [c0345c80] mtd_ioctl+0x3e0/0xc3c
[dbc6de80] [c0111050] vfs_ioctl+0xcc/0xe4
[dbc6dea0] [c011122c] do_vfs_ioctl+0x80/0x770
[dbc6df10] [c01119b0] sys_ioctl+0x94/0x108
[dbc6df40] [c0010d04] ret_from_syscall+0x0/0x4
--- Exception: c01 at 0xff586a0
LR = 0xff58608
=====
So, if there is any thread in wait queue, puts erasing operation into queue.
It makes writing operation have chance to run.
Signed-off-by: Li Wang
---
drivers/mtd/chips/cfi_cmdset_0002.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 5a4bfe3..53f5774 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -2400,6 +2400,19 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->state = FL_READY;
DISABLE_VPP(map);
put_chip(map, chip, adr);
+ if (waitqueue_active(&chip->wq)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+ mutex_unlock(&chip->mutex);
+ /*
+ * If the other thread in queue misses to wake up erasing in
+ * 3ms, erasing will wake up itself. The way makes erasing not
+ * to hang up by the error of the other thread in queue.
+ */
+ schedule_timeout(msecs_to_jiffies(3));
+ remove_wait_queue(&chip->wq, &wait);
+ return ret;
+ }
mutex_unlock(&chip->mutex);
return ret;
}