aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-08-04 15:41:22 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-08-04 15:41:22 -0400
commit59a1cc6bdabf5ed148b48808ad1a418d87f5e6bf (patch)
tree6463071a09201040267702e895d63359e62c393d /fs/gfs2/ops_address.c
parent899bb264507cfed83922bf14cd66a073494601ba (diff)
[GFS2] Fix lock ordering bug in page fault path
Mmapped files were able to trigger a lock ordering bug. Private maps do not need to take the glock so early on. Shared maps do unfortunately, however we can get around that by adding a flag into the flags for the struct gfs2_file. This only works because we are taking an exclusive lock at this point, so we know that nobody else can be racing with us. Fixes Red Hat bugzilla: #201196 Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index fca69f12e4de..bdd4d6b48721 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -237,14 +237,22 @@ static int gfs2_readpage(struct file *file, struct page *page)
237 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); 237 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
238 struct gfs2_holder gh; 238 struct gfs2_holder gh;
239 int error; 239 int error;
240 int do_unlock = 0;
240 241
241 if (likely(file != &gfs2_internal_file_sentinal)) { 242 if (likely(file != &gfs2_internal_file_sentinal)) {
243 if (file) {
244 struct gfs2_file *gf = file->private_data;
245 if (test_bit(GFF_EXLOCK, &gf->f_flags))
246 goto skip_lock;
247 }
242 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|GL_AOP, &gh); 248 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|GL_AOP, &gh);
249 do_unlock = 1;
243 error = gfs2_glock_nq_m_atime(1, &gh); 250 error = gfs2_glock_nq_m_atime(1, &gh);
244 if (unlikely(error)) 251 if (unlikely(error))
245 goto out_unlock; 252 goto out_unlock;
246 } 253 }
247 254
255skip_lock:
248 if (gfs2_is_stuffed(ip)) { 256 if (gfs2_is_stuffed(ip)) {
249 error = stuffed_readpage(ip, page); 257 error = stuffed_readpage(ip, page);
250 unlock_page(page); 258 unlock_page(page);
@@ -262,7 +270,7 @@ out:
262 return error; 270 return error;
263out_unlock: 271out_unlock:
264 unlock_page(page); 272 unlock_page(page);
265 if (file != &gfs2_internal_file_sentinal) 273 if (do_unlock)
266 gfs2_holder_uninit(&gh); 274 gfs2_holder_uninit(&gh);
267 goto out; 275 goto out;
268} 276}
@@ -291,17 +299,24 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
291 struct gfs2_holder gh; 299 struct gfs2_holder gh;
292 unsigned page_idx; 300 unsigned page_idx;
293 int ret; 301 int ret;
302 int do_unlock = 0;
294 303
295 if (likely(file != &gfs2_internal_file_sentinal)) { 304 if (likely(file != &gfs2_internal_file_sentinal)) {
305 if (file) {
306 struct gfs2_file *gf = file->private_data;
307 if (test_bit(GFF_EXLOCK, &gf->f_flags))
308 goto skip_lock;
309 }
296 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 310 gfs2_holder_init(ip->i_gl, LM_ST_SHARED,
297 LM_FLAG_TRY_1CB|GL_ATIME|GL_AOP, &gh); 311 LM_FLAG_TRY_1CB|GL_ATIME|GL_AOP, &gh);
312 do_unlock = 1;
298 ret = gfs2_glock_nq_m_atime(1, &gh); 313 ret = gfs2_glock_nq_m_atime(1, &gh);
299 if (ret == GLR_TRYFAILED) 314 if (ret == GLR_TRYFAILED)
300 goto out_noerror; 315 goto out_noerror;
301 if (unlikely(ret)) 316 if (unlikely(ret))
302 goto out_unlock; 317 goto out_unlock;
303 } 318 }
304 319skip_lock:
305 if (gfs2_is_stuffed(ip)) { 320 if (gfs2_is_stuffed(ip)) {
306 struct pagevec lru_pvec; 321 struct pagevec lru_pvec;
307 pagevec_init(&lru_pvec, 0); 322 pagevec_init(&lru_pvec, 0);
@@ -326,7 +341,7 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
326 ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block); 341 ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block);
327 } 342 }
328 343
329 if (likely(file != &gfs2_internal_file_sentinal)) { 344 if (do_unlock) {
330 gfs2_glock_dq_m(1, &gh); 345 gfs2_glock_dq_m(1, &gh);
331 gfs2_holder_uninit(&gh); 346 gfs2_holder_uninit(&gh);
332 } 347 }
@@ -344,7 +359,7 @@ out_unlock:
344 unlock_page(page); 359 unlock_page(page);
345 page_cache_release(page); 360 page_cache_release(page);
346 } 361 }
347 if (likely(file != &gfs2_internal_file_sentinal)) 362 if (do_unlock)
348 gfs2_holder_uninit(&gh); 363 gfs2_holder_uninit(&gh);
349 goto out; 364 goto out;
350} 365}