cifs: bugfix for unreclaimed writeback pages in cifs_writev_requeue()
Ouyang Maochun [Mon, 18 Feb 2013 15:54:52 +0000 (09:54 -0600)]
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>

fs/cifs/cifssmb.c

index 00e12f2..7353bc5 100644 (file)
@@ -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) {
                        SetPageError(wdata->pages[i]);
+                       end_page_writeback(wdata->pages[i]);
+                       page_cache_release(wdata->pages[i]);
+               }
                unlock_page(wdata->pages[i]);
        }