diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-04 20:06:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-04 20:06:28 -0400 |
commit | 6f66f9005b66a9a09028f8c85d67600b20a979ec (patch) | |
tree | 8d805ed204c8beba4ca01449a651b871234084c2 /fs | |
parent | 8764d86100fe58e69877753faa44fc1d9276c624 (diff) | |
parent | a6a4d98b0124b5d3befe8b3a99f51f1b4fcc6dcf (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
Pull gfs2 fixes from Steven Whitehouse:
"There are four patches this time.
The first fixes a problem where the wrong descriptor type was being
written into the log for journaled data blocks.
The second fixes a race relating to the deallocation of allocator
data.
The third provides a fallback if kmalloc is unable to satisfy a
request to allocate a directory hash table.
The fourth fixes the iopen glock caching so that inodes are deleted in
a more timely manner after rmdir/unlink"
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes:
GFS2: Don't cache iopen glocks
GFS2: Fall back to vmalloc if kmalloc fails for dir hash tables
GFS2: Increase i_writecount during gfs2_setattr_size
GFS2: Set log descriptor type for jdata blocks
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/bmap.c | 17 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 43 | ||||
-rw-r--r-- | fs/gfs2/file.c | 19 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 1 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 4 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 4 | ||||
-rw-r--r-- | fs/gfs2/super.c | 6 |
7 files changed, 71 insertions, 23 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 1dc9a13ce6bb..93b5809c20bb 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -1286,17 +1286,26 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize) | |||
1286 | if (ret) | 1286 | if (ret) |
1287 | return ret; | 1287 | return ret; |
1288 | 1288 | ||
1289 | ret = get_write_access(inode); | ||
1290 | if (ret) | ||
1291 | return ret; | ||
1292 | |||
1289 | inode_dio_wait(inode); | 1293 | inode_dio_wait(inode); |
1290 | 1294 | ||
1291 | ret = gfs2_rs_alloc(GFS2_I(inode)); | 1295 | ret = gfs2_rs_alloc(GFS2_I(inode)); |
1292 | if (ret) | 1296 | if (ret) |
1293 | return ret; | 1297 | goto out; |
1294 | 1298 | ||
1295 | oldsize = inode->i_size; | 1299 | oldsize = inode->i_size; |
1296 | if (newsize >= oldsize) | 1300 | if (newsize >= oldsize) { |
1297 | return do_grow(inode, newsize); | 1301 | ret = do_grow(inode, newsize); |
1302 | goto out; | ||
1303 | } | ||
1298 | 1304 | ||
1299 | return do_shrink(inode, oldsize, newsize); | 1305 | ret = do_shrink(inode, oldsize, newsize); |
1306 | out: | ||
1307 | put_write_access(inode); | ||
1308 | return ret; | ||
1300 | } | 1309 | } |
1301 | 1310 | ||
1302 | int gfs2_truncatei_resume(struct gfs2_inode *ip) | 1311 | int gfs2_truncatei_resume(struct gfs2_inode *ip) |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index c3e82bd23179..b631c9043460 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -354,22 +354,31 @@ static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip) | |||
354 | return ERR_PTR(-EIO); | 354 | return ERR_PTR(-EIO); |
355 | } | 355 | } |
356 | 356 | ||
357 | hc = kmalloc(hsize, GFP_NOFS); | 357 | hc = kmalloc(hsize, GFP_NOFS | __GFP_NOWARN); |
358 | ret = -ENOMEM; | 358 | if (hc == NULL) |
359 | hc = __vmalloc(hsize, GFP_NOFS, PAGE_KERNEL); | ||
360 | |||
359 | if (hc == NULL) | 361 | if (hc == NULL) |
360 | return ERR_PTR(-ENOMEM); | 362 | return ERR_PTR(-ENOMEM); |
361 | 363 | ||
362 | ret = gfs2_dir_read_data(ip, hc, hsize); | 364 | ret = gfs2_dir_read_data(ip, hc, hsize); |
363 | if (ret < 0) { | 365 | if (ret < 0) { |
364 | kfree(hc); | 366 | if (is_vmalloc_addr(hc)) |
367 | vfree(hc); | ||
368 | else | ||
369 | kfree(hc); | ||
365 | return ERR_PTR(ret); | 370 | return ERR_PTR(ret); |
366 | } | 371 | } |
367 | 372 | ||
368 | spin_lock(&inode->i_lock); | 373 | spin_lock(&inode->i_lock); |
369 | if (ip->i_hash_cache) | 374 | if (ip->i_hash_cache) { |
370 | kfree(hc); | 375 | if (is_vmalloc_addr(hc)) |
371 | else | 376 | vfree(hc); |
377 | else | ||
378 | kfree(hc); | ||
379 | } else { | ||
372 | ip->i_hash_cache = hc; | 380 | ip->i_hash_cache = hc; |
381 | } | ||
373 | spin_unlock(&inode->i_lock); | 382 | spin_unlock(&inode->i_lock); |
374 | 383 | ||
375 | return ip->i_hash_cache; | 384 | return ip->i_hash_cache; |
@@ -385,7 +394,10 @@ void gfs2_dir_hash_inval(struct gfs2_inode *ip) | |||
385 | { | 394 | { |
386 | __be64 *hc = ip->i_hash_cache; | 395 | __be64 *hc = ip->i_hash_cache; |
387 | ip->i_hash_cache = NULL; | 396 | ip->i_hash_cache = NULL; |
388 | kfree(hc); | 397 | if (is_vmalloc_addr(hc)) |
398 | vfree(hc); | ||
399 | else | ||
400 | kfree(hc); | ||
389 | } | 401 | } |
390 | 402 | ||
391 | static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) | 403 | static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) |
@@ -1113,7 +1125,10 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
1113 | if (IS_ERR(hc)) | 1125 | if (IS_ERR(hc)) |
1114 | return PTR_ERR(hc); | 1126 | return PTR_ERR(hc); |
1115 | 1127 | ||
1116 | h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS); | 1128 | h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN); |
1129 | if (hc2 == NULL) | ||
1130 | hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL); | ||
1131 | |||
1117 | if (!hc2) | 1132 | if (!hc2) |
1118 | return -ENOMEM; | 1133 | return -ENOMEM; |
1119 | 1134 | ||
@@ -1145,7 +1160,10 @@ fail: | |||
1145 | gfs2_dinode_out(dip, dibh->b_data); | 1160 | gfs2_dinode_out(dip, dibh->b_data); |
1146 | brelse(dibh); | 1161 | brelse(dibh); |
1147 | out_kfree: | 1162 | out_kfree: |
1148 | kfree(hc2); | 1163 | if (is_vmalloc_addr(hc2)) |
1164 | vfree(hc2); | ||
1165 | else | ||
1166 | kfree(hc2); | ||
1149 | return error; | 1167 | return error; |
1150 | } | 1168 | } |
1151 | 1169 | ||
@@ -1846,6 +1864,8 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
1846 | memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); | 1864 | memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); |
1847 | 1865 | ||
1848 | ht = kzalloc(size, GFP_NOFS); | 1866 | ht = kzalloc(size, GFP_NOFS); |
1867 | if (ht == NULL) | ||
1868 | ht = vzalloc(size); | ||
1849 | if (!ht) | 1869 | if (!ht) |
1850 | return -ENOMEM; | 1870 | return -ENOMEM; |
1851 | 1871 | ||
@@ -1933,7 +1953,10 @@ out_rlist: | |||
1933 | gfs2_rlist_free(&rlist); | 1953 | gfs2_rlist_free(&rlist); |
1934 | gfs2_quota_unhold(dip); | 1954 | gfs2_quota_unhold(dip); |
1935 | out: | 1955 | out: |
1936 | kfree(ht); | 1956 | if (is_vmalloc_addr(ht)) |
1957 | vfree(ht); | ||
1958 | else | ||
1959 | kfree(ht); | ||
1937 | return error; | 1960 | return error; |
1938 | } | 1961 | } |
1939 | 1962 | ||
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index acd16764b133..ad0dc38d87ab 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -402,16 +402,20 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
402 | /* Update file times before taking page lock */ | 402 | /* Update file times before taking page lock */ |
403 | file_update_time(vma->vm_file); | 403 | file_update_time(vma->vm_file); |
404 | 404 | ||
405 | ret = get_write_access(inode); | ||
406 | if (ret) | ||
407 | goto out; | ||
408 | |||
405 | ret = gfs2_rs_alloc(ip); | 409 | ret = gfs2_rs_alloc(ip); |
406 | if (ret) | 410 | if (ret) |
407 | return ret; | 411 | goto out_write_access; |
408 | 412 | ||
409 | gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); | 413 | gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); |
410 | 414 | ||
411 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 415 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
412 | ret = gfs2_glock_nq(&gh); | 416 | ret = gfs2_glock_nq(&gh); |
413 | if (ret) | 417 | if (ret) |
414 | goto out; | 418 | goto out_uninit; |
415 | 419 | ||
416 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); | 420 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); |
417 | set_bit(GIF_SW_PAGED, &ip->i_flags); | 421 | set_bit(GIF_SW_PAGED, &ip->i_flags); |
@@ -480,12 +484,15 @@ out_quota_unlock: | |||
480 | gfs2_quota_unlock(ip); | 484 | gfs2_quota_unlock(ip); |
481 | out_unlock: | 485 | out_unlock: |
482 | gfs2_glock_dq(&gh); | 486 | gfs2_glock_dq(&gh); |
483 | out: | 487 | out_uninit: |
484 | gfs2_holder_uninit(&gh); | 488 | gfs2_holder_uninit(&gh); |
485 | if (ret == 0) { | 489 | if (ret == 0) { |
486 | set_page_dirty(page); | 490 | set_page_dirty(page); |
487 | wait_for_stable_page(page); | 491 | wait_for_stable_page(page); |
488 | } | 492 | } |
493 | out_write_access: | ||
494 | put_write_access(inode); | ||
495 | out: | ||
489 | sb_end_pagefault(inode->i_sb); | 496 | sb_end_pagefault(inode->i_sb); |
490 | return block_page_mkwrite_return(ret); | 497 | return block_page_mkwrite_return(ret); |
491 | } | 498 | } |
@@ -594,10 +601,10 @@ static int gfs2_release(struct inode *inode, struct file *file) | |||
594 | kfree(file->private_data); | 601 | kfree(file->private_data); |
595 | file->private_data = NULL; | 602 | file->private_data = NULL; |
596 | 603 | ||
597 | if ((file->f_mode & FMODE_WRITE) && | 604 | if (!(file->f_mode & FMODE_WRITE)) |
598 | (atomic_read(&inode->i_writecount) == 1)) | 605 | return 0; |
599 | gfs2_rs_delete(ip); | ||
600 | 606 | ||
607 | gfs2_rs_delete(ip); | ||
601 | return 0; | 608 | return 0; |
602 | } | 609 | } |
603 | 610 | ||
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 8833a4f264e3..62b484e4a9e4 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -189,6 +189,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, | |||
189 | return inode; | 189 | return inode; |
190 | 190 | ||
191 | fail_refresh: | 191 | fail_refresh: |
192 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | ||
192 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | 193 | ip->i_iopen_gh.gh_gl->gl_object = NULL; |
193 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 194 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
194 | fail_iopen: | 195 | fail_iopen: |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 68b4c8f1fce8..6c33d7b6e0c4 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -419,7 +419,9 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit, | |||
419 | if (total > limit) | 419 | if (total > limit) |
420 | num = limit; | 420 | num = limit; |
421 | gfs2_log_unlock(sdp); | 421 | gfs2_log_unlock(sdp); |
422 | page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA, num + 1, num); | 422 | page = gfs2_get_log_desc(sdp, |
423 | is_databuf ? GFS2_LOG_DESC_JDATA : | ||
424 | GFS2_LOG_DESC_METADATA, num + 1, num); | ||
423 | ld = page_address(page); | 425 | ld = page_address(page); |
424 | gfs2_log_lock(sdp); | 426 | gfs2_log_lock(sdp); |
425 | ptr = (__be64 *)(ld + 1); | 427 | ptr = (__be64 *)(ld + 1); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 5232525934ae..9809156e3d04 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) | |||
638 | */ | 638 | */ |
639 | void gfs2_rs_delete(struct gfs2_inode *ip) | 639 | void gfs2_rs_delete(struct gfs2_inode *ip) |
640 | { | 640 | { |
641 | struct inode *inode = &ip->i_inode; | ||
642 | |||
641 | down_write(&ip->i_rw_mutex); | 643 | down_write(&ip->i_rw_mutex); |
642 | if (ip->i_res) { | 644 | if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) { |
643 | gfs2_rs_deltree(ip->i_res); | 645 | gfs2_rs_deltree(ip->i_res); |
644 | BUG_ON(ip->i_res->rs_free); | 646 | BUG_ON(ip->i_res->rs_free); |
645 | kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); | 647 | kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 917c8e1eb4ae..e5639dec66c4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1444,6 +1444,7 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1444 | /* Must not read inode block until block type has been verified */ | 1444 | /* Must not read inode block until block type has been verified */ |
1445 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh); | 1445 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh); |
1446 | if (unlikely(error)) { | 1446 | if (unlikely(error)) { |
1447 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | ||
1447 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1448 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1448 | goto out; | 1449 | goto out; |
1449 | } | 1450 | } |
@@ -1514,8 +1515,10 @@ out_unlock: | |||
1514 | if (gfs2_rs_active(ip->i_res)) | 1515 | if (gfs2_rs_active(ip->i_res)) |
1515 | gfs2_rs_deltree(ip->i_res); | 1516 | gfs2_rs_deltree(ip->i_res); |
1516 | 1517 | ||
1517 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) | 1518 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { |
1519 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | ||
1518 | gfs2_glock_dq(&ip->i_iopen_gh); | 1520 | gfs2_glock_dq(&ip->i_iopen_gh); |
1521 | } | ||
1519 | gfs2_holder_uninit(&ip->i_iopen_gh); | 1522 | gfs2_holder_uninit(&ip->i_iopen_gh); |
1520 | gfs2_glock_dq_uninit(&gh); | 1523 | gfs2_glock_dq_uninit(&gh); |
1521 | if (error && error != GLR_TRYFAILED && error != -EROFS) | 1524 | if (error && error != GLR_TRYFAILED && error != -EROFS) |
@@ -1534,6 +1537,7 @@ out: | |||
1534 | ip->i_gl = NULL; | 1537 | ip->i_gl = NULL; |
1535 | if (ip->i_iopen_gh.gh_gl) { | 1538 | if (ip->i_iopen_gh.gh_gl) { |
1536 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | 1539 | ip->i_iopen_gh.gh_gl->gl_object = NULL; |
1540 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | ||
1537 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1541 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1538 | } | 1542 | } |
1539 | } | 1543 | } |