aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/file.c
diff options
context:
space:
mode:
authorThomas Betker <thomas.betker@rohde-schwarz.com>2015-11-10 16:18:15 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2016-02-25 06:11:25 -0500
commit157078f64b8a9cd7011b6b900b2f2498df850748 (patch)
tree7bfe4c748232f41764dcaa80c1810abacd70bef4 /fs/jffs2/file.c
parent38714fbd299f992080a11b977f609136ec8530c2 (diff)
Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin"
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. 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
Diffstat (limited to 'fs/jffs2/file.c')
-rw-r--r--fs/jffs2/file.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index c5ac5944bc1b..cad86bac3453 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
137 struct page *pg; 137 struct page *pg;
138 struct inode *inode = mapping->host; 138 struct inode *inode = mapping->host;
139 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 139 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;
143 pgoff_t index = pos >> PAGE_CACHE_SHIFT; 140 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
144 uint32_t pageofs = index << PAGE_CACHE_SHIFT; 141 uint32_t pageofs = index << PAGE_CACHE_SHIFT;
145 int ret = 0; 142 int ret = 0;
146 143
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);
157 pg = grab_cache_page_write_begin(mapping, index, flags); 144 pg = grab_cache_page_write_begin(mapping, index, flags);
158 if (!pg) { 145 if (!pg)
159 if (alloc_len)
160 jffs2_complete_reservation(c);
161 mutex_unlock(&f->sem);
162 return -ENOMEM; 146 return -ENOMEM;
163 }
164 *pagep = pg; 147 *pagep = pg;
165 148
166 if (alloc_len) { 149 jffs2_dbg(1, "%s()\n", __func__);
150
151 if (pageofs > inode->i_size) {
167 /* Make new hole frag from old EOF to new page */ 152 /* 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;
168 struct jffs2_full_dnode *fn; 155 struct jffs2_full_dnode *fn;
156 uint32_t alloc_len;
169 157
170 jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", 158 jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
171 (unsigned int)inode->i_size, pageofs); 159 (unsigned int)inode->i_size, pageofs);
172 160
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);
173 memset(&ri, 0, sizeof(ri)); 167 memset(&ri, 0, sizeof(ri));
174 168
175 ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 169 ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
196 if (IS_ERR(fn)) { 190 if (IS_ERR(fn)) {
197 ret = PTR_ERR(fn); 191 ret = PTR_ERR(fn);
198 jffs2_complete_reservation(c); 192 jffs2_complete_reservation(c);
193 mutex_unlock(&f->sem);
199 goto out_page; 194 goto out_page;
200 } 195 }
201 ret = jffs2_add_full_dnode_to_inode(c, f, fn); 196 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,
210 jffs2_mark_node_obsolete(c, fn->raw); 205 jffs2_mark_node_obsolete(c, fn->raw);
211 jffs2_free_full_dnode(fn); 206 jffs2_free_full_dnode(fn);
212 jffs2_complete_reservation(c); 207 jffs2_complete_reservation(c);
208 mutex_unlock(&f->sem);
213 goto out_page; 209 goto out_page;
214 } 210 }
215 jffs2_complete_reservation(c); 211 jffs2_complete_reservation(c);
216 inode->i_size = pageofs; 212 inode->i_size = pageofs;
213 mutex_unlock(&f->sem);
217 } 214 }
218 215
219 /* 216 /*
@@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
222 * case of a short-copy. 219 * case of a short-copy.
223 */ 220 */
224 if (!PageUptodate(pg)) { 221 if (!PageUptodate(pg)) {
222 mutex_lock(&f->sem);
225 ret = jffs2_do_readpage_nolock(inode, pg); 223 ret = jffs2_do_readpage_nolock(inode, pg);
224 mutex_unlock(&f->sem);
226 if (ret) 225 if (ret)
227 goto out_page; 226 goto out_page;
228 } 227 }
229 mutex_unlock(&f->sem);
230 jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); 228 jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
231 return ret; 229 return ret;
232 230
233out_page: 231out_page:
234 unlock_page(pg); 232 unlock_page(pg);
235 page_cache_release(pg); 233 page_cache_release(pg);
236 mutex_unlock(&f->sem);
237 return ret; 234 return ret;
238} 235}
239 236