path: root/fs
diff options
authorOuyang Maochun <ouyang.maochun@zte.com.cn>2013-02-18 09:54:52 -0600
committerSteve French <sfrench@us.ibm.com>2013-02-28 09:01:47 -0600
commitc51bb0ea40ca038da26b1fa7d450f4078124af03 (patch)
treebf3f85dbf6263612dbdea9676670d75777a9d895 /fs
parent0b7bc84000d71f3647ca33ab1bf5bd928535c846 (diff)
cifs: bugfix for unreclaimed writeback pages in cifs_writev_requeue()
Pages get the PG_writeback flag set before cifs sends its request to SMB server in cifs_writepages(), if the SMB service goes down, cifs may try to recommit the writing requests in cifs_writev_requeue(). However, it does not clean its PG_writeback flag and relaimed the pages even if it fails again in cifs_writev_requeue(), which may lead to the hanging of the processes accessing the cifs directory. This patch just cleans the PG_writeback flags and reclaims the pages under that circumstances. Steps to reproduce the bug(trying serveral times may trigger the issue): 1.Write from cifs client continuously.(e.g dd if=/dev/zero of=<cifs file>) 2.Stop SMB service from server.(e.g service smb stop) 3.Wait for two minutes´╝î and then start SMB service from server.(e.g service smb start) 4.The processes which are accessing cifs directory may hang up. Signed-off-by: Ouyang Maochun <ouyang.maochun@zte.com.cn> Signed-off-by: Jiang Yong <jian.yong5@zte.com.cn> Tested-by: Zhang Xianwei <zhang.xianwei8@zte.com.cn> Reviewed-by: Wang Liang <wang.liang82@zte.com.cn> Reviewed-by: Cai Qu <cai.qu@zte.com.cn> Reviewed-by: Jiang Biao <jiang.biao2@zte.com.cn> Reviewed-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
1 files changed, 4 insertions, 1 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 00e12f2d626b..7353bc5d73d7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1909,8 +1909,11 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
} while (rc == -EAGAIN);
for (i = 0; i < wdata->nr_pages; i++) {
- if (rc != 0)
+ if (rc != 0) {
+ end_page_writeback(wdata->pages[i]);
+ page_cache_release(wdata->pages[i]);
+ }