All of lore.kernel.org
 help / color / mirror / Atom feed
From: hujianyang <hujianyang@huawei.com>
To: Artem Bityutskiy <dedekind1@gmail.com>,
	Laurence Withers <lwithers@guralp.com>
Cc: linux-mtd <linux-mtd@lists.infradead.org>
Subject: [PATCH RFC] UBIFS: Fix assert failed in ubifs_set_page_dirty
Date: Sat, 26 Apr 2014 17:25:42 +0800	[thread overview]
Message-ID: <535B7B96.9030008@huawei.com> (raw)

Hi,

I meet some assert failed as Laurence Withers reported in February.

show like this:

[69440.577932] UBIFS assert failed in ubifs_set_page_dirty at 1421 (pid 2067)
[69440.658567] UBIFS assert failed in ubifs_writepage at 1009 (pid 2069)
[69440.735605] UBIFS assert failed in do_writepage at 936 (pid 2069)
[69440.735881] UBIFS assert failed in ubifs_release_budget at 567 (pid 2069)
[69440.736360] UBIFS assert failed in ubifs_release_budget at 567 (pid 2069)
[69441.581541] UBIFS assert failed in ubifs_budget_space at 464 (pid 2070)
[69441.659118] UBIFS assert failed in ubifs_release_budget at 567 (pid 2072)
[69441.740405] UBIFS assert failed in ubifs_set_page_dirty at 1421 (pid 2070)
[69441.822369] UBIFS assert failed in ubifs_writepage at 1009 (pid 2072)
[69441.899574] UBIFS assert failed in do_writepage at 936 (pid 2072)
[69441.899853] UBIFS assert failed in ubifs_release_budget at 567 (pid 2072)
[69450.677679] UBIFS assert failed in ubifs_release_budget at 567 (pid 6)
[69455.757670] UBIFS assert failed in ubifs_release_budget at 567 (pid 6)
[69458.147075] UBIFS assert failed in ubifs_put_super at 1776 (pid 2077)

After communicating with Laurence, I found this assert failed can
be easily reproduced by running mmap(PROT_WRITE, MAP_SHARED) and
fsync with same file at same time.

I think there is a race in __do_fault and ubifs_writepage.

We do ->page_mkwrite in __do_fault, perform space budget and set
PagePrivate, then execute __set_page_dirty_nobuffers to make the
page dirty. But at the end of ubifs_vm_page_mkwrite, we release
page lock.

At the same time, fsync process may hold the lock and do ->writepage
as page is set to dirty in ->page_mkwrite. We will clear page_dirty,
clear page_private and release budget here. In the end, unlock page.

Mmap then get the lock and perform ->set_page_dirty. We will meet
the first assert failed here because dirty bit is clear by fsync.

"UBIFS assert failed in ubifs_set_page_dirty at 1421"

static int ubifs_set_page_dirty(struct page *page)
{
        int ret;

        ret = __set_page_dirty_nobuffers(page); /* Here reset dirty bit */
        /*
         * An attempt to dirty a page without budgeting for it - should not
         * happen.
         */
        ubifs_assert(ret == 0);
        return ret;
}

With this assert failed, ->set_page_dirty will reset the dirty bit
without space budget and SetPagePrivate. When we want to writeback
this page, we will meet PagePrivate assert failed.

"UBIFS assert failed in ubifs_writepage at 1009 (pid 2069)
 UBIFS assert failed in do_writepage at 936 (pid 2069)"

Then, release budget without budgeting and meet budget assert failed.

"UBIFS assert failed in ubifs_release_budget at 567
 UBIFS assert failed in ubifs_budget_space at 464"

c->bi.dd_growth is less than zero now.

I want to fix this problem but I don't have enough knowledge about
this filesystem. In my fix, I remove __set_page_dirty_nobuffers
in ->page_mkwrite and just set dirty bit in ->set_page_dirty.

I don't know if my fix works and causes no other problems. I can only
test it with linux-3.10 and it seems not bad.

-------------------------------------------------------------------

>From 2e7de10767d687c28b90bf013cd20e96b5f0f1a3 Mon Sep 17 00:00:00 2001
From: hujianyang <hujianyang@huawei.com>
Date: Sat, 26 Apr 2014 17:17:19 +0800
Subject: [PATCH] UBIFS: Fix assert failed in ubifs_set_page_dirty

---
 fs/ubifs/file.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 4f34dba..0f3e3ac 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1412,15 +1412,7 @@ static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov,

 static int ubifs_set_page_dirty(struct page *page)
 {
-	int ret;
-
-	ret = __set_page_dirty_nobuffers(page);
-	/*
-	 * An attempt to dirty a page without budgeting for it - should not
-	 * happen.
-	 */
-	ubifs_assert(ret == 0);
-	return ret;
+	return __set_page_dirty_nobuffers(page);
 }

 static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
@@ -1508,7 +1500,6 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma,
 			ubifs_convert_page_budget(c);
 		SetPagePrivate(page);
 		atomic_long_inc(&c->dirty_pg_cnt);
-		__set_page_dirty_nobuffers(page);
 	}

 	if (update_time) {
-- 
1.8.5.5

             reply	other threads:[~2014-04-26  9:26 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-26  9:25 hujianyang [this message]
2014-04-30  6:06 ` [PATCH v2] UBIFS: Fix assert failed in ubifs_set_page_dirty hujianyang
2014-04-30 12:18   ` Laurence Withers
2014-04-30 13:48     ` Dolev Raviv
2014-05-04  6:38       ` hujianyang
2014-05-04 11:54         ` Dolev Raviv
2014-05-05  7:07     ` Artem Bityutskiy
2014-05-05 11:50       ` Laurence Withers
2014-05-05  7:02   ` Artem Bityutskiy
2014-05-05  7:16     ` Artem Bityutskiy
2014-05-05  7:30       ` hujianyang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=535B7B96.9030008@huawei.com \
    --to=hujianyang@huawei.com \
    --cc=dedekind1@gmail.com \
    --cc=linux-mtd@lists.infradead.org \
    --cc=lwithers@guralp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.