Patch "Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin"" has been added to the 3.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin"
to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch
and it can be found in the queue-3.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
157078f64b8a9cd7011b6b900b2f2498df850748Mon Sep 17 00:00:00 2001
From: Thomas Betker <[email protected]>
Date: Tue, 10 Nov 2015 22:18:15 +0100
Subject: Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin"
From: Thomas Betker <[email protected]>
commit 157078f64b8a9cd7011b6b900b2f2498df850748 upstream.
This reverts commit 5ffd3412ae55
("jffs2: Fix lock acquisition order bug in jffs2_write_begin").
The commit modified jffs2_write_begin() to remove a deadlock with jffs2_garbage_collect_live(), but this introduced new deadlocks found by multiple users. page_lock() actually has to be called before mutex_lock(&c->alloc_sem) or mutex_lock(&f->sem) because jffs2_write_end() and jffs2_readpage() are called with the page locked, and they acquire c->alloc_sem and f->sem, resp.
In other words, the lock order in jffs2_write_begin() was correct, and it is the jffs2_garbage_collect_live() path that has to be changed.
Revert the commit to get rid of the new deadlocks, and to clear the way for a better fix of the original deadlock.
--- fs/jffs2/file.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-)
fs/jffs2/file.c +18 -21
@@ -138,39 +138,33 @@ static int jffs2_write_begin(struct filestruct page *pg;struct inode *inode = mapping->host;struct jffs2_inode_info *f =JFFS2_INODE_INFO (inode); -struct jffs2_sb_info *c =JFFS2_SB_INFO (inode->i_sb); -struct jffs2_raw_inode ri; -uint32_t alloc_len =0 ;pgoff_t index = pos >>PAGE_CACHE_SHIFT ;uint32_t pageofs = index <<PAGE_CACHE_SHIFT ;int ret =0 ; -jffs2_dbg (1 ,"%s()\n" , __func__); - -if (pageofs > inode->i_size) { - ret =jffs2_reserve_space (c,sizeof (ri), &alloc_len, -ALLOC_NORMAL ,JFFS2_SUMMARY_INODE_SIZE ); -if (ret) -return ret; - } - -mutex_lock (&f->sem); pg =grab_cache_page_write_begin (mapping, index, flags); -if (!pg) { -if (alloc_len) -jffs2_complete_reservation (c); -mutex_unlock (&f->sem); +if (!pg)return -ENOMEM ; - } *pagep = pg; -if (alloc_len) { +jffs2_dbg (1 ,"%s()\n" , __func__); + +if (pageofs > inode->i_size) {/* Make new hole frag from old EOF to new page */ +struct jffs2_sb_info *c =JFFS2_SB_INFO (inode->i_sb); +struct jffs2_raw_inode ri;struct jffs2_full_dnode *fn; +uint32_t alloc_len;jffs2_dbg (1 ,"Writing new hole frag 0x%x-0x%x between current EOF and new page\n" , (unsigned int )inode->i_size, pageofs); + ret =jffs2_reserve_space (c,sizeof (ri), &alloc_len, +ALLOC_NORMAL ,JFFS2_SUMMARY_INODE_SIZE ); +if (ret) + goto out_page; + +mutex_lock (&f->sem);memset (&ri,0 ,sizeof (ri)); ri.magic =cpu_to_je16 (JFFS2_MAGIC_BITMASK );
@@ -197,6 +191,7 @@ static int jffs2_write_begin(struct fileif (IS_ERR (fn)) { ret =PTR_ERR (fn);jffs2_complete_reservation (c); +mutex_unlock (&f->sem); goto out_page; } ret =jffs2_add_full_dnode_to_inode (c, f, fn);
@@ -211,10 +206,12 @@ static int jffs2_write_begin(struct filejffs2_mark_node_obsolete (c, fn->raw);jffs2_free_full_dnode (fn);jffs2_complete_reservation (c); +mutex_unlock (&f->sem); goto out_page; }jffs2_complete_reservation (c); inode->i_size = pageofs; +mutex_unlock (&f->sem); }/*
@@ -223,18 +220,18 @@ static int jffs2_write_begin(struct file* case of a short-copy. */ if (!PageUptodate (pg)) { +mutex_lock (&f->sem); ret =jffs2_do_readpage_nolock (inode, pg); +mutex_unlock (&f->sem);if (ret) goto out_page; } -mutex_unlock (&f->sem);jffs2_dbg (1 ,"end write_begin(). pg->flags %lx\n" , pg->flags);return ret; out_page:unlock_page (pg);page_cache_release (pg); -mutex_unlock (&f->sem);return ret; }
Patches currently in stable-queue which might be from [email protected] are
queue-3.10/revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch queue-3.10/jffs2-fix-page-lock-f-sem-deadlock.patch