Skip to content

Commit 157078f

Browse files
tbetker-rsDavid Woodhouse
authored andcommitted
Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin"
This reverts commit 5ffd341 ("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. Reported-by: Deng Chao <deng.chao1@zte.com.cn> Reported-by: Ming Liu <liu.ming50@gmail.com> Reported-by: wangzaiwei <wangzaiwei@top-vision.cn> Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Cc: stable@vger.kernel.org
1 parent 38714fb commit 157078f

File tree

1 file changed

+18
-21
lines changed

1 file changed

+18
-21
lines changed

fs/jffs2/file.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
137137
struct page *pg;
138138
struct inode *inode = mapping->host;
139139
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
140-
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
141-
struct jffs2_raw_inode ri;
142-
uint32_t alloc_len = 0;
143140
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
144141
uint32_t pageofs = index << PAGE_CACHE_SHIFT;
145142
int ret = 0;
146143

147-
jffs2_dbg(1, "%s()\n", __func__);
148-
149-
if (pageofs > inode->i_size) {
150-
ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
151-
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
152-
if (ret)
153-
return ret;
154-
}
155-
156-
mutex_lock(&f->sem);
157144
pg = grab_cache_page_write_begin(mapping, index, flags);
158-
if (!pg) {
159-
if (alloc_len)
160-
jffs2_complete_reservation(c);
161-
mutex_unlock(&f->sem);
145+
if (!pg)
162146
return -ENOMEM;
163-
}
164147
*pagep = pg;
165148

166-
if (alloc_len) {
149+
jffs2_dbg(1, "%s()\n", __func__);
150+
151+
if (pageofs > inode->i_size) {
167152
/* Make new hole frag from old EOF to new page */
153+
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
154+
struct jffs2_raw_inode ri;
168155
struct jffs2_full_dnode *fn;
156+
uint32_t alloc_len;
169157

170158
jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
171159
(unsigned int)inode->i_size, pageofs);
172160

161+
ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
162+
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
163+
if (ret)
164+
goto out_page;
165+
166+
mutex_lock(&f->sem);
173167
memset(&ri, 0, sizeof(ri));
174168

175169
ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
196190
if (IS_ERR(fn)) {
197191
ret = PTR_ERR(fn);
198192
jffs2_complete_reservation(c);
193+
mutex_unlock(&f->sem);
199194
goto out_page;
200195
}
201196
ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -210,10 +205,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
210205
jffs2_mark_node_obsolete(c, fn->raw);
211206
jffs2_free_full_dnode(fn);
212207
jffs2_complete_reservation(c);
208+
mutex_unlock(&f->sem);
213209
goto out_page;
214210
}
215211
jffs2_complete_reservation(c);
216212
inode->i_size = pageofs;
213+
mutex_unlock(&f->sem);
217214
}
218215

219216
/*
@@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
222219
* case of a short-copy.
223220
*/
224221
if (!PageUptodate(pg)) {
222+
mutex_lock(&f->sem);
225223
ret = jffs2_do_readpage_nolock(inode, pg);
224+
mutex_unlock(&f->sem);
226225
if (ret)
227226
goto out_page;
228227
}
229-
mutex_unlock(&f->sem);
230228
jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
231229
return ret;
232230

233231
out_page:
234232
unlock_page(pg);
235233
page_cache_release(pg);
236-
mutex_unlock(&f->sem);
237234
return ret;
238235
}
239236

0 commit comments

Comments
 (0)