diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 18:34:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 18:34:29 -0500 |
commit | 1715ac63d36b52b2932c17bf8ceccf058f02e57b (patch) | |
tree | df84fd2162b4c59a5be95abf0d56bcbfd4ce23d4 | |
parent | 08e2fb6ce69857f71ef846ba69af025ca4ad09c4 (diff) | |
parent | ec7d879c457611e540cb465c25f3040facbd1185 (diff) |
Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
Pull GFS2 update from Steven Whitehouse:
"In contrast to recent merge windows, there are a number of interesting
features this time:
There is a set of patches to improve performance in relation to block
reservations. Some correctness fixes for fallocate, and an update to
the freeze/thaw code which greatly simplyfies this code path. In
addition there is a set of clean ups from Al Viro too"
* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
GFS2: gfs2_atomic_open(): simplify the use of finish_no_open()
GFS2: gfs2_dir_get_hash_table(): avoiding deferred vfree() is easy here...
GFS2: use kvfree() instead of open-coding it
GFS2: gfs2_create_inode(): don't bother with d_splice_alias()
GFS2: bugger off early if O_CREAT open finds a directory
GFS2: Deletion of unnecessary checks before two function calls
GFS2: update freeze code to use freeze/thaw_super on all nodes
fs: add freeze_super/thaw_super fs hooks
GFS2: Update timestamps on fallocate
GFS2: Update i_size properly on fallocate
GFS2: Use inode_newsize_ok and get_write_access in fallocate
GFS2: If we use up our block reservation, request more next time
GFS2: Only increase rs_sizehint
GFS2: Set of distributed preferences for rgrps
GFS2: directly return gfs2_dir_check()
-rw-r--r-- | fs/block_dev.c | 10 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 39 | ||||
-rw-r--r-- | fs/gfs2/file.c | 83 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 3 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 26 | ||||
-rw-r--r-- | fs/gfs2/glops.h | 2 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 19 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 72 | ||||
-rw-r--r-- | fs/gfs2/log.c | 42 | ||||
-rw-r--r-- | fs/gfs2/main.c | 11 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 18 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 9 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 69 | ||||
-rw-r--r-- | fs/gfs2/rgrp.h | 1 | ||||
-rw-r--r-- | fs/gfs2/super.c | 112 | ||||
-rw-r--r-- | fs/gfs2/super.h | 1 | ||||
-rw-r--r-- | fs/gfs2/trans.c | 17 | ||||
-rw-r--r-- | fs/ioctl.c | 6 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
19 files changed, 315 insertions, 227 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 1d9c9f3754f8..b48c41bf0f86 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -235,7 +235,10 @@ struct super_block *freeze_bdev(struct block_device *bdev) | |||
235 | sb = get_active_super(bdev); | 235 | sb = get_active_super(bdev); |
236 | if (!sb) | 236 | if (!sb) |
237 | goto out; | 237 | goto out; |
238 | error = freeze_super(sb); | 238 | if (sb->s_op->freeze_super) |
239 | error = sb->s_op->freeze_super(sb); | ||
240 | else | ||
241 | error = freeze_super(sb); | ||
239 | if (error) { | 242 | if (error) { |
240 | deactivate_super(sb); | 243 | deactivate_super(sb); |
241 | bdev->bd_fsfreeze_count--; | 244 | bdev->bd_fsfreeze_count--; |
@@ -272,7 +275,10 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb) | |||
272 | if (!sb) | 275 | if (!sb) |
273 | goto out; | 276 | goto out; |
274 | 277 | ||
275 | error = thaw_super(sb); | 278 | if (sb->s_op->thaw_super) |
279 | error = sb->s_op->thaw_super(sb); | ||
280 | else | ||
281 | error = thaw_super(sb); | ||
276 | if (error) { | 282 | if (error) { |
277 | bdev->bd_fsfreeze_count++; | 283 | bdev->bd_fsfreeze_count++; |
278 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | 284 | mutex_unlock(&bdev->bd_fsfreeze_mutex); |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 5d4261ff5d23..c5a34f09e228 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -365,23 +365,17 @@ static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip) | |||
365 | 365 | ||
366 | ret = gfs2_dir_read_data(ip, hc, hsize); | 366 | ret = gfs2_dir_read_data(ip, hc, hsize); |
367 | if (ret < 0) { | 367 | if (ret < 0) { |
368 | if (is_vmalloc_addr(hc)) | 368 | kvfree(hc); |
369 | vfree(hc); | ||
370 | else | ||
371 | kfree(hc); | ||
372 | return ERR_PTR(ret); | 369 | return ERR_PTR(ret); |
373 | } | 370 | } |
374 | 371 | ||
375 | spin_lock(&inode->i_lock); | 372 | spin_lock(&inode->i_lock); |
376 | if (ip->i_hash_cache) { | 373 | if (likely(!ip->i_hash_cache)) { |
377 | if (is_vmalloc_addr(hc)) | ||
378 | vfree(hc); | ||
379 | else | ||
380 | kfree(hc); | ||
381 | } else { | ||
382 | ip->i_hash_cache = hc; | 374 | ip->i_hash_cache = hc; |
375 | hc = NULL; | ||
383 | } | 376 | } |
384 | spin_unlock(&inode->i_lock); | 377 | spin_unlock(&inode->i_lock); |
378 | kvfree(hc); | ||
385 | 379 | ||
386 | return ip->i_hash_cache; | 380 | return ip->i_hash_cache; |
387 | } | 381 | } |
@@ -396,10 +390,7 @@ void gfs2_dir_hash_inval(struct gfs2_inode *ip) | |||
396 | { | 390 | { |
397 | __be64 *hc = ip->i_hash_cache; | 391 | __be64 *hc = ip->i_hash_cache; |
398 | ip->i_hash_cache = NULL; | 392 | ip->i_hash_cache = NULL; |
399 | if (is_vmalloc_addr(hc)) | 393 | kvfree(hc); |
400 | vfree(hc); | ||
401 | else | ||
402 | kfree(hc); | ||
403 | } | 394 | } |
404 | 395 | ||
405 | static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) | 396 | static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) |
@@ -1168,10 +1159,7 @@ fail: | |||
1168 | gfs2_dinode_out(dip, dibh->b_data); | 1159 | gfs2_dinode_out(dip, dibh->b_data); |
1169 | brelse(dibh); | 1160 | brelse(dibh); |
1170 | out_kfree: | 1161 | out_kfree: |
1171 | if (is_vmalloc_addr(hc2)) | 1162 | kvfree(hc2); |
1172 | vfree(hc2); | ||
1173 | else | ||
1174 | kfree(hc2); | ||
1175 | return error; | 1163 | return error; |
1176 | } | 1164 | } |
1177 | 1165 | ||
@@ -1302,14 +1290,6 @@ static void *gfs2_alloc_sort_buffer(unsigned size) | |||
1302 | return ptr; | 1290 | return ptr; |
1303 | } | 1291 | } |
1304 | 1292 | ||
1305 | static void gfs2_free_sort_buffer(void *ptr) | ||
1306 | { | ||
1307 | if (is_vmalloc_addr(ptr)) | ||
1308 | vfree(ptr); | ||
1309 | else | ||
1310 | kfree(ptr); | ||
1311 | } | ||
1312 | |||
1313 | static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, | 1293 | static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, |
1314 | int *copied, unsigned *depth, | 1294 | int *copied, unsigned *depth, |
1315 | u64 leaf_no) | 1295 | u64 leaf_no) |
@@ -1393,7 +1373,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, | |||
1393 | out_free: | 1373 | out_free: |
1394 | for(i = 0; i < leaf; i++) | 1374 | for(i = 0; i < leaf; i++) |
1395 | brelse(larr[i]); | 1375 | brelse(larr[i]); |
1396 | gfs2_free_sort_buffer(larr); | 1376 | kvfree(larr); |
1397 | out: | 1377 | out: |
1398 | return error; | 1378 | return error; |
1399 | } | 1379 | } |
@@ -2004,10 +1984,7 @@ out_rlist: | |||
2004 | gfs2_rlist_free(&rlist); | 1984 | gfs2_rlist_free(&rlist); |
2005 | gfs2_quota_unhold(dip); | 1985 | gfs2_quota_unhold(dip); |
2006 | out: | 1986 | out: |
2007 | if (is_vmalloc_addr(ht)) | 1987 | kvfree(ht); |
2008 | vfree(ht); | ||
2009 | else | ||
2010 | kfree(ht); | ||
2011 | return error; | 1988 | return error; |
2012 | } | 1989 | } |
2013 | 1990 | ||
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 80dd44dca028..6e600abf694a 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -337,7 +337,8 @@ static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) | |||
337 | size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift; | 337 | size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift; |
338 | int hint = min_t(size_t, INT_MAX, blks); | 338 | int hint = min_t(size_t, INT_MAX, blks); |
339 | 339 | ||
340 | atomic_set(&ip->i_res->rs_sizehint, hint); | 340 | if (hint > atomic_read(&ip->i_res->rs_sizehint)) |
341 | atomic_set(&ip->i_res->rs_sizehint, hint); | ||
341 | } | 342 | } |
342 | 343 | ||
343 | /** | 344 | /** |
@@ -728,7 +729,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | |||
728 | struct gfs2_inode *ip = GFS2_I(inode); | 729 | struct gfs2_inode *ip = GFS2_I(inode); |
729 | struct buffer_head *dibh; | 730 | struct buffer_head *dibh; |
730 | int error; | 731 | int error; |
731 | loff_t size = len; | ||
732 | unsigned int nr_blks; | 732 | unsigned int nr_blks; |
733 | sector_t lblock = offset >> inode->i_blkbits; | 733 | sector_t lblock = offset >> inode->i_blkbits; |
734 | 734 | ||
@@ -762,11 +762,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | |||
762 | goto out; | 762 | goto out; |
763 | } | 763 | } |
764 | } | 764 | } |
765 | if (offset + size > inode->i_size && !(mode & FALLOC_FL_KEEP_SIZE)) | ||
766 | i_size_write(inode, offset + size); | ||
767 | |||
768 | mark_inode_dirty(inode); | ||
769 | |||
770 | out: | 765 | out: |
771 | brelse(dibh); | 766 | brelse(dibh); |
772 | return error; | 767 | return error; |
@@ -796,8 +791,7 @@ static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len, | |||
796 | } | 791 | } |
797 | } | 792 | } |
798 | 793 | ||
799 | static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | 794 | static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t len) |
800 | loff_t len) | ||
801 | { | 795 | { |
802 | struct inode *inode = file_inode(file); | 796 | struct inode *inode = file_inode(file); |
803 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 797 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
@@ -811,14 +805,9 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | |||
811 | loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1); | 805 | loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1); |
812 | loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; | 806 | loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; |
813 | loff_t max_chunk_size = UINT_MAX & bsize_mask; | 807 | loff_t max_chunk_size = UINT_MAX & bsize_mask; |
814 | struct gfs2_holder gh; | ||
815 | 808 | ||
816 | next = (next + 1) << sdp->sd_sb.sb_bsize_shift; | 809 | next = (next + 1) << sdp->sd_sb.sb_bsize_shift; |
817 | 810 | ||
818 | /* We only support the FALLOC_FL_KEEP_SIZE mode */ | ||
819 | if (mode & ~FALLOC_FL_KEEP_SIZE) | ||
820 | return -EOPNOTSUPP; | ||
821 | |||
822 | offset &= bsize_mask; | 811 | offset &= bsize_mask; |
823 | 812 | ||
824 | len = next - offset; | 813 | len = next - offset; |
@@ -829,17 +818,6 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | |||
829 | if (bytes == 0) | 818 | if (bytes == 0) |
830 | bytes = sdp->sd_sb.sb_bsize; | 819 | bytes = sdp->sd_sb.sb_bsize; |
831 | 820 | ||
832 | error = gfs2_rs_alloc(ip); | ||
833 | if (error) | ||
834 | return error; | ||
835 | |||
836 | mutex_lock(&inode->i_mutex); | ||
837 | |||
838 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
839 | error = gfs2_glock_nq(&gh); | ||
840 | if (unlikely(error)) | ||
841 | goto out_uninit; | ||
842 | |||
843 | gfs2_size_hint(file, offset, len); | 821 | gfs2_size_hint(file, offset, len); |
844 | 822 | ||
845 | while (len > 0) { | 823 | while (len > 0) { |
@@ -852,8 +830,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | |||
852 | } | 830 | } |
853 | error = gfs2_quota_lock_check(ip); | 831 | error = gfs2_quota_lock_check(ip); |
854 | if (error) | 832 | if (error) |
855 | goto out_unlock; | 833 | return error; |
856 | |||
857 | retry: | 834 | retry: |
858 | gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks); | 835 | gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks); |
859 | 836 | ||
@@ -895,20 +872,64 @@ retry: | |||
895 | gfs2_quota_unlock(ip); | 872 | gfs2_quota_unlock(ip); |
896 | } | 873 | } |
897 | 874 | ||
898 | if (error == 0) | 875 | if (!(mode & FALLOC_FL_KEEP_SIZE) && (pos + count) > inode->i_size) { |
899 | error = generic_write_sync(file, pos, count); | 876 | i_size_write(inode, pos + count); |
900 | goto out_unlock; | 877 | /* Marks the inode as dirty */ |
878 | file_update_time(file); | ||
879 | } | ||
880 | |||
881 | return generic_write_sync(file, pos, count); | ||
901 | 882 | ||
902 | out_trans_fail: | 883 | out_trans_fail: |
903 | gfs2_inplace_release(ip); | 884 | gfs2_inplace_release(ip); |
904 | out_qunlock: | 885 | out_qunlock: |
905 | gfs2_quota_unlock(ip); | 886 | gfs2_quota_unlock(ip); |
887 | return error; | ||
888 | } | ||
889 | |||
890 | static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | ||
891 | { | ||
892 | struct inode *inode = file_inode(file); | ||
893 | struct gfs2_inode *ip = GFS2_I(inode); | ||
894 | struct gfs2_holder gh; | ||
895 | int ret; | ||
896 | |||
897 | if (mode & ~FALLOC_FL_KEEP_SIZE) | ||
898 | return -EOPNOTSUPP; | ||
899 | |||
900 | mutex_lock(&inode->i_mutex); | ||
901 | |||
902 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
903 | ret = gfs2_glock_nq(&gh); | ||
904 | if (ret) | ||
905 | goto out_uninit; | ||
906 | |||
907 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | ||
908 | (offset + len) > inode->i_size) { | ||
909 | ret = inode_newsize_ok(inode, offset + len); | ||
910 | if (ret) | ||
911 | goto out_unlock; | ||
912 | } | ||
913 | |||
914 | ret = get_write_access(inode); | ||
915 | if (ret) | ||
916 | goto out_unlock; | ||
917 | |||
918 | ret = gfs2_rs_alloc(ip); | ||
919 | if (ret) | ||
920 | goto out_putw; | ||
921 | |||
922 | ret = __gfs2_fallocate(file, mode, offset, len); | ||
923 | if (ret) | ||
924 | gfs2_rs_deltree(ip->i_res); | ||
925 | out_putw: | ||
926 | put_write_access(inode); | ||
906 | out_unlock: | 927 | out_unlock: |
907 | gfs2_glock_dq(&gh); | 928 | gfs2_glock_dq(&gh); |
908 | out_uninit: | 929 | out_uninit: |
909 | gfs2_holder_uninit(&gh); | 930 | gfs2_holder_uninit(&gh); |
910 | mutex_unlock(&inode->i_mutex); | 931 | mutex_unlock(&inode->i_mutex); |
911 | return error; | 932 | return ret; |
912 | } | 933 | } |
913 | 934 | ||
914 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM | 935 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 8f0c19d1d943..a23524aa3eac 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -836,8 +836,7 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder * | |||
836 | gh->gh_flags = flags; | 836 | gh->gh_flags = flags; |
837 | gh->gh_iflags = 0; | 837 | gh->gh_iflags = 0; |
838 | gh->gh_ip = _RET_IP_; | 838 | gh->gh_ip = _RET_IP_; |
839 | if (gh->gh_owner_pid) | 839 | put_pid(gh->gh_owner_pid); |
840 | put_pid(gh->gh_owner_pid); | ||
841 | gh->gh_owner_pid = get_pid(task_pid(current)); | 840 | gh->gh_owner_pid = get_pid(task_pid(current)); |
842 | } | 841 | } |
843 | 842 | ||
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 1cc0bba6313f..fe91951c3361 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include "trans.h" | 28 | #include "trans.h" |
29 | #include "dir.h" | 29 | #include "dir.h" |
30 | 30 | ||
31 | struct workqueue_struct *gfs2_freeze_wq; | ||
32 | |||
31 | static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) | 33 | static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) |
32 | { | 34 | { |
33 | fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n", | 35 | fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n", |
@@ -94,11 +96,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
94 | * on the stack */ | 96 | * on the stack */ |
95 | tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); | 97 | tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); |
96 | tr.tr_ip = _RET_IP_; | 98 | tr.tr_ip = _RET_IP_; |
97 | sb_start_intwrite(sdp->sd_vfs); | 99 | if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0) |
98 | if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0) { | ||
99 | sb_end_intwrite(sdp->sd_vfs); | ||
100 | return; | 100 | return; |
101 | } | ||
102 | WARN_ON_ONCE(current->journal_info); | 101 | WARN_ON_ONCE(current->journal_info); |
103 | current->journal_info = &tr; | 102 | current->journal_info = &tr; |
104 | 103 | ||
@@ -469,20 +468,19 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
469 | 468 | ||
470 | static void freeze_go_sync(struct gfs2_glock *gl) | 469 | static void freeze_go_sync(struct gfs2_glock *gl) |
471 | { | 470 | { |
471 | int error = 0; | ||
472 | struct gfs2_sbd *sdp = gl->gl_sbd; | 472 | struct gfs2_sbd *sdp = gl->gl_sbd; |
473 | DEFINE_WAIT(wait); | ||
474 | 473 | ||
475 | if (gl->gl_state == LM_ST_SHARED && | 474 | if (gl->gl_state == LM_ST_SHARED && |
476 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { | 475 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
477 | atomic_set(&sdp->sd_log_freeze, 1); | 476 | atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE); |
478 | wake_up(&sdp->sd_logd_waitq); | 477 | error = freeze_super(sdp->sd_vfs); |
479 | do { | 478 | if (error) { |
480 | prepare_to_wait(&sdp->sd_log_frozen_wait, &wait, | 479 | printk(KERN_INFO "GFS2: couldn't freeze filesystem: %d\n", error); |
481 | TASK_UNINTERRUPTIBLE); | 480 | gfs2_assert_withdraw(sdp, 0); |
482 | if (atomic_read(&sdp->sd_log_freeze)) | 481 | } |
483 | io_schedule(); | 482 | queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work); |
484 | } while(atomic_read(&sdp->sd_log_freeze)); | 483 | gfs2_log_flush(sdp, NULL, FREEZE_FLUSH); |
485 | finish_wait(&sdp->sd_log_frozen_wait, &wait); | ||
486 | } | 484 | } |
487 | } | 485 | } |
488 | 486 | ||
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h index 7455d2629bcb..8ed1857c1a8d 100644 --- a/fs/gfs2/glops.h +++ b/fs/gfs2/glops.h | |||
@@ -12,6 +12,8 @@ | |||
12 | 12 | ||
13 | #include "incore.h" | 13 | #include "incore.h" |
14 | 14 | ||
15 | extern struct workqueue_struct *gfs2_freeze_wq; | ||
16 | |||
15 | extern const struct gfs2_glock_operations gfs2_meta_glops; | 17 | extern const struct gfs2_glock_operations gfs2_meta_glops; |
16 | extern const struct gfs2_glock_operations gfs2_inode_glops; | 18 | extern const struct gfs2_glock_operations gfs2_inode_glops; |
17 | extern const struct gfs2_glock_operations gfs2_rgrp_glops; | 19 | extern const struct gfs2_glock_operations gfs2_rgrp_glops; |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 39e7e9959b74..7a2dbbc0d634 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -97,6 +97,7 @@ struct gfs2_rgrpd { | |||
97 | #define GFS2_RDF_CHECK 0x10000000 /* check for unlinked inodes */ | 97 | #define GFS2_RDF_CHECK 0x10000000 /* check for unlinked inodes */ |
98 | #define GFS2_RDF_UPTODATE 0x20000000 /* rg is up to date */ | 98 | #define GFS2_RDF_UPTODATE 0x20000000 /* rg is up to date */ |
99 | #define GFS2_RDF_ERROR 0x40000000 /* error in rg */ | 99 | #define GFS2_RDF_ERROR 0x40000000 /* error in rg */ |
100 | #define GFS2_RDF_PREFERRED 0x80000000 /* This rgrp is preferred */ | ||
100 | #define GFS2_RDF_MASK 0xf0000000 /* mask for internal flags */ | 101 | #define GFS2_RDF_MASK 0xf0000000 /* mask for internal flags */ |
101 | spinlock_t rd_rsspin; /* protects reservation related vars */ | 102 | spinlock_t rd_rsspin; /* protects reservation related vars */ |
102 | struct rb_root rd_rstree; /* multi-block reservation tree */ | 103 | struct rb_root rd_rstree; /* multi-block reservation tree */ |
@@ -587,6 +588,12 @@ enum { | |||
587 | SDF_SKIP_DLM_UNLOCK = 8, | 588 | SDF_SKIP_DLM_UNLOCK = 8, |
588 | }; | 589 | }; |
589 | 590 | ||
591 | enum gfs2_freeze_state { | ||
592 | SFS_UNFROZEN = 0, | ||
593 | SFS_STARTING_FREEZE = 1, | ||
594 | SFS_FROZEN = 2, | ||
595 | }; | ||
596 | |||
590 | #define GFS2_FSNAME_LEN 256 | 597 | #define GFS2_FSNAME_LEN 256 |
591 | 598 | ||
592 | struct gfs2_inum_host { | 599 | struct gfs2_inum_host { |
@@ -684,6 +691,7 @@ struct gfs2_sbd { | |||
684 | struct gfs2_holder sd_live_gh; | 691 | struct gfs2_holder sd_live_gh; |
685 | struct gfs2_glock *sd_rename_gl; | 692 | struct gfs2_glock *sd_rename_gl; |
686 | struct gfs2_glock *sd_freeze_gl; | 693 | struct gfs2_glock *sd_freeze_gl; |
694 | struct work_struct sd_freeze_work; | ||
687 | wait_queue_head_t sd_glock_wait; | 695 | wait_queue_head_t sd_glock_wait; |
688 | atomic_t sd_glock_disposal; | 696 | atomic_t sd_glock_disposal; |
689 | struct completion sd_locking_init; | 697 | struct completion sd_locking_init; |
@@ -788,6 +796,9 @@ struct gfs2_sbd { | |||
788 | wait_queue_head_t sd_log_flush_wait; | 796 | wait_queue_head_t sd_log_flush_wait; |
789 | int sd_log_error; | 797 | int sd_log_error; |
790 | 798 | ||
799 | atomic_t sd_reserving_log; | ||
800 | wait_queue_head_t sd_reserving_log_wait; | ||
801 | |||
791 | unsigned int sd_log_flush_head; | 802 | unsigned int sd_log_flush_head; |
792 | u64 sd_log_flush_wrapped; | 803 | u64 sd_log_flush_wrapped; |
793 | 804 | ||
@@ -797,12 +808,8 @@ struct gfs2_sbd { | |||
797 | 808 | ||
798 | /* For quiescing the filesystem */ | 809 | /* For quiescing the filesystem */ |
799 | struct gfs2_holder sd_freeze_gh; | 810 | struct gfs2_holder sd_freeze_gh; |
800 | struct gfs2_holder sd_freeze_root_gh; | 811 | atomic_t sd_freeze_state; |
801 | struct gfs2_holder sd_thaw_gh; | 812 | struct mutex sd_freeze_mutex; |
802 | atomic_t sd_log_freeze; | ||
803 | atomic_t sd_frozen_root; | ||
804 | wait_queue_head_t sd_frozen_root_wait; | ||
805 | wait_queue_head_t sd_log_frozen_wait; | ||
806 | 813 | ||
807 | char sd_fsname[GFS2_FSNAME_LEN]; | 814 | char sd_fsname[GFS2_FSNAME_LEN]; |
808 | char sd_table_name[GFS2_FSNAME_LEN]; | 815 | char sd_table_name[GFS2_FSNAME_LEN]; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index c4ed823d150e..9054002ebe70 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -596,7 +596,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
596 | struct gfs2_inode *dip = GFS2_I(dir), *ip; | 596 | struct gfs2_inode *dip = GFS2_I(dir), *ip; |
597 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 597 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
598 | struct gfs2_glock *io_gl; | 598 | struct gfs2_glock *io_gl; |
599 | struct dentry *d; | ||
600 | int error, free_vfs_inode = 0; | 599 | int error, free_vfs_inode = 0; |
601 | u32 aflags = 0; | 600 | u32 aflags = 0; |
602 | unsigned blocks = 1; | 601 | unsigned blocks = 1; |
@@ -624,22 +623,18 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
624 | inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); | 623 | inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); |
625 | error = PTR_ERR(inode); | 624 | error = PTR_ERR(inode); |
626 | if (!IS_ERR(inode)) { | 625 | if (!IS_ERR(inode)) { |
627 | d = d_splice_alias(inode, dentry); | 626 | if (S_ISDIR(inode->i_mode)) { |
628 | error = PTR_ERR(d); | 627 | iput(inode); |
629 | if (IS_ERR(d)) { | 628 | inode = ERR_PTR(-EISDIR); |
630 | inode = ERR_CAST(d); | ||
631 | goto fail_gunlock; | 629 | goto fail_gunlock; |
632 | } | 630 | } |
631 | d_instantiate(dentry, inode); | ||
633 | error = 0; | 632 | error = 0; |
634 | if (file) { | 633 | if (file) { |
635 | if (S_ISREG(inode->i_mode)) { | 634 | if (S_ISREG(inode->i_mode)) |
636 | WARN_ON(d != NULL); | ||
637 | error = finish_open(file, dentry, gfs2_open_common, opened); | 635 | error = finish_open(file, dentry, gfs2_open_common, opened); |
638 | } else { | 636 | else |
639 | error = finish_no_open(file, d); | 637 | error = finish_no_open(file, NULL); |
640 | } | ||
641 | } else { | ||
642 | dput(d); | ||
643 | } | 638 | } |
644 | gfs2_glock_dq_uninit(ghs); | 639 | gfs2_glock_dq_uninit(ghs); |
645 | return error; | 640 | return error; |
@@ -1045,11 +1040,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
1045 | if (error) | 1040 | if (error) |
1046 | return error; | 1041 | return error; |
1047 | 1042 | ||
1048 | error = gfs2_dir_check(&dip->i_inode, name, ip); | 1043 | return gfs2_dir_check(&dip->i_inode, name, ip); |
1049 | if (error) | ||
1050 | return error; | ||
1051 | |||
1052 | return 0; | ||
1053 | } | 1044 | } |
1054 | 1045 | ||
1055 | /** | 1046 | /** |
@@ -1254,11 +1245,8 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1254 | if (d != NULL) | 1245 | if (d != NULL) |
1255 | dentry = d; | 1246 | dentry = d; |
1256 | if (dentry->d_inode) { | 1247 | if (dentry->d_inode) { |
1257 | if (!(*opened & FILE_OPENED)) { | 1248 | if (!(*opened & FILE_OPENED)) |
1258 | if (d == NULL) | 1249 | return finish_no_open(file, d); |
1259 | dget(dentry); | ||
1260 | return finish_no_open(file, dentry); | ||
1261 | } | ||
1262 | dput(d); | 1250 | dput(d); |
1263 | return 0; | 1251 | return 0; |
1264 | } | 1252 | } |
@@ -1622,26 +1610,18 @@ int gfs2_permission(struct inode *inode, int mask) | |||
1622 | { | 1610 | { |
1623 | struct gfs2_inode *ip; | 1611 | struct gfs2_inode *ip; |
1624 | struct gfs2_holder i_gh; | 1612 | struct gfs2_holder i_gh; |
1625 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1626 | int error; | 1613 | int error; |
1627 | int unlock = 0; | 1614 | int unlock = 0; |
1628 | int frozen_root = 0; | ||
1629 | 1615 | ||
1630 | 1616 | ||
1631 | ip = GFS2_I(inode); | 1617 | ip = GFS2_I(inode); |
1632 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | 1618 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
1633 | if (unlikely(gfs2_glock_is_held_excl(sdp->sd_freeze_gl) && | 1619 | if (mask & MAY_NOT_BLOCK) |
1634 | inode == sdp->sd_root_dir->d_inode && | 1620 | return -ECHILD; |
1635 | atomic_inc_not_zero(&sdp->sd_frozen_root))) | 1621 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); |
1636 | frozen_root = 1; | 1622 | if (error) |
1637 | else { | 1623 | return error; |
1638 | if (mask & MAY_NOT_BLOCK) | 1624 | unlock = 1; |
1639 | return -ECHILD; | ||
1640 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | ||
1641 | if (error) | ||
1642 | return error; | ||
1643 | unlock = 1; | ||
1644 | } | ||
1645 | } | 1625 | } |
1646 | 1626 | ||
1647 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | 1627 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) |
@@ -1650,8 +1630,6 @@ int gfs2_permission(struct inode *inode, int mask) | |||
1650 | error = generic_permission(inode, mask); | 1630 | error = generic_permission(inode, mask); |
1651 | if (unlock) | 1631 | if (unlock) |
1652 | gfs2_glock_dq_uninit(&i_gh); | 1632 | gfs2_glock_dq_uninit(&i_gh); |
1653 | else if (frozen_root && atomic_dec_and_test(&sdp->sd_frozen_root)) | ||
1654 | wake_up(&sdp->sd_frozen_root_wait); | ||
1655 | 1633 | ||
1656 | return error; | 1634 | return error; |
1657 | } | 1635 | } |
@@ -1824,29 +1802,19 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1824 | struct inode *inode = dentry->d_inode; | 1802 | struct inode *inode = dentry->d_inode; |
1825 | struct gfs2_inode *ip = GFS2_I(inode); | 1803 | struct gfs2_inode *ip = GFS2_I(inode); |
1826 | struct gfs2_holder gh; | 1804 | struct gfs2_holder gh; |
1827 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1828 | int error; | 1805 | int error; |
1829 | int unlock = 0; | 1806 | int unlock = 0; |
1830 | int frozen_root = 0; | ||
1831 | 1807 | ||
1832 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | 1808 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
1833 | if (unlikely(gfs2_glock_is_held_excl(sdp->sd_freeze_gl) && | 1809 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); |
1834 | inode == sdp->sd_root_dir->d_inode && | 1810 | if (error) |
1835 | atomic_inc_not_zero(&sdp->sd_frozen_root))) | 1811 | return error; |
1836 | frozen_root = 1; | 1812 | unlock = 1; |
1837 | else { | ||
1838 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
1839 | if (error) | ||
1840 | return error; | ||
1841 | unlock = 1; | ||
1842 | } | ||
1843 | } | 1813 | } |
1844 | 1814 | ||
1845 | generic_fillattr(inode, stat); | 1815 | generic_fillattr(inode, stat); |
1846 | if (unlock) | 1816 | if (unlock) |
1847 | gfs2_glock_dq_uninit(&gh); | 1817 | gfs2_glock_dq_uninit(&gh); |
1848 | else if (frozen_root && atomic_dec_and_test(&sdp->sd_frozen_root)) | ||
1849 | wake_up(&sdp->sd_frozen_root_wait); | ||
1850 | 1818 | ||
1851 | return 0; | 1819 | return 0; |
1852 | } | 1820 | } |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 3966fadbcebd..536e7a6252cd 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -339,6 +339,7 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) | |||
339 | 339 | ||
340 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | 340 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) |
341 | { | 341 | { |
342 | int ret = 0; | ||
342 | unsigned reserved_blks = 7 * (4096 / sdp->sd_vfs->s_blocksize); | 343 | unsigned reserved_blks = 7 * (4096 / sdp->sd_vfs->s_blocksize); |
343 | unsigned wanted = blks + reserved_blks; | 344 | unsigned wanted = blks + reserved_blks; |
344 | DEFINE_WAIT(wait); | 345 | DEFINE_WAIT(wait); |
@@ -362,9 +363,13 @@ retry: | |||
362 | } while(free_blocks <= wanted); | 363 | } while(free_blocks <= wanted); |
363 | finish_wait(&sdp->sd_log_waitq, &wait); | 364 | finish_wait(&sdp->sd_log_waitq, &wait); |
364 | } | 365 | } |
366 | atomic_inc(&sdp->sd_reserving_log); | ||
365 | if (atomic_cmpxchg(&sdp->sd_log_blks_free, free_blocks, | 367 | if (atomic_cmpxchg(&sdp->sd_log_blks_free, free_blocks, |
366 | free_blocks - blks) != free_blocks) | 368 | free_blocks - blks) != free_blocks) { |
369 | if (atomic_dec_and_test(&sdp->sd_reserving_log)) | ||
370 | wake_up(&sdp->sd_reserving_log_wait); | ||
367 | goto retry; | 371 | goto retry; |
372 | } | ||
368 | trace_gfs2_log_blocks(sdp, -blks); | 373 | trace_gfs2_log_blocks(sdp, -blks); |
369 | 374 | ||
370 | /* | 375 | /* |
@@ -377,9 +382,11 @@ retry: | |||
377 | down_read(&sdp->sd_log_flush_lock); | 382 | down_read(&sdp->sd_log_flush_lock); |
378 | if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) { | 383 | if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) { |
379 | gfs2_log_release(sdp, blks); | 384 | gfs2_log_release(sdp, blks); |
380 | return -EROFS; | 385 | ret = -EROFS; |
381 | } | 386 | } |
382 | return 0; | 387 | if (atomic_dec_and_test(&sdp->sd_reserving_log)) |
388 | wake_up(&sdp->sd_reserving_log_wait); | ||
389 | return ret; | ||
383 | } | 390 | } |
384 | 391 | ||
385 | /** | 392 | /** |
@@ -652,9 +659,12 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) | |||
652 | u32 hash; | 659 | u32 hash; |
653 | int rw = WRITE_FLUSH_FUA | REQ_META; | 660 | int rw = WRITE_FLUSH_FUA | REQ_META; |
654 | struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); | 661 | struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); |
662 | enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); | ||
655 | lh = page_address(page); | 663 | lh = page_address(page); |
656 | clear_page(lh); | 664 | clear_page(lh); |
657 | 665 | ||
666 | gfs2_assert_withdraw(sdp, (state != SFS_FROZEN)); | ||
667 | |||
658 | tail = current_tail(sdp); | 668 | tail = current_tail(sdp); |
659 | 669 | ||
660 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 670 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
@@ -695,6 +705,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | |||
695 | enum gfs2_flush_type type) | 705 | enum gfs2_flush_type type) |
696 | { | 706 | { |
697 | struct gfs2_trans *tr; | 707 | struct gfs2_trans *tr; |
708 | enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); | ||
698 | 709 | ||
699 | down_write(&sdp->sd_log_flush_lock); | 710 | down_write(&sdp->sd_log_flush_lock); |
700 | 711 | ||
@@ -713,8 +724,12 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | |||
713 | INIT_LIST_HEAD(&tr->tr_ail1_list); | 724 | INIT_LIST_HEAD(&tr->tr_ail1_list); |
714 | INIT_LIST_HEAD(&tr->tr_ail2_list); | 725 | INIT_LIST_HEAD(&tr->tr_ail2_list); |
715 | tr->tr_first = sdp->sd_log_flush_head; | 726 | tr->tr_first = sdp->sd_log_flush_head; |
727 | if (unlikely (state == SFS_FROZEN)) | ||
728 | gfs2_assert_withdraw(sdp, !tr->tr_num_buf_new && !tr->tr_num_databuf_new); | ||
716 | } | 729 | } |
717 | 730 | ||
731 | if (unlikely(state == SFS_FROZEN)) | ||
732 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | ||
718 | gfs2_assert_withdraw(sdp, | 733 | gfs2_assert_withdraw(sdp, |
719 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); | 734 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); |
720 | 735 | ||
@@ -745,8 +760,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | |||
745 | spin_unlock(&sdp->sd_ail_lock); | 760 | spin_unlock(&sdp->sd_ail_lock); |
746 | gfs2_log_unlock(sdp); | 761 | gfs2_log_unlock(sdp); |
747 | 762 | ||
748 | if (atomic_read(&sdp->sd_log_freeze)) | ||
749 | type = FREEZE_FLUSH; | ||
750 | if (type != NORMAL_FLUSH) { | 763 | if (type != NORMAL_FLUSH) { |
751 | if (!sdp->sd_log_idle) { | 764 | if (!sdp->sd_log_idle) { |
752 | for (;;) { | 765 | for (;;) { |
@@ -763,21 +776,8 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | |||
763 | } | 776 | } |
764 | if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH) | 777 | if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH) |
765 | gfs2_log_shutdown(sdp); | 778 | gfs2_log_shutdown(sdp); |
766 | if (type == FREEZE_FLUSH) { | 779 | if (type == FREEZE_FLUSH) |
767 | int error; | 780 | atomic_set(&sdp->sd_freeze_state, SFS_FROZEN); |
768 | |||
769 | atomic_set(&sdp->sd_log_freeze, 0); | ||
770 | wake_up(&sdp->sd_log_frozen_wait); | ||
771 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, | ||
772 | LM_ST_SHARED, 0, | ||
773 | &sdp->sd_thaw_gh); | ||
774 | if (error) { | ||
775 | printk(KERN_INFO "GFS2: couln't get freeze lock : %d\n", error); | ||
776 | gfs2_assert_withdraw(sdp, 0); | ||
777 | } | ||
778 | else | ||
779 | gfs2_glock_dq_uninit(&sdp->sd_thaw_gh); | ||
780 | } | ||
781 | } | 781 | } |
782 | 782 | ||
783 | trace_gfs2_log_flush(sdp, 0); | 783 | trace_gfs2_log_flush(sdp, 0); |
@@ -888,7 +888,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) | |||
888 | 888 | ||
889 | static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) | 889 | static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) |
890 | { | 890 | { |
891 | return (atomic_read(&sdp->sd_log_pinned) >= atomic_read(&sdp->sd_log_thresh1) || atomic_read(&sdp->sd_log_freeze)); | 891 | return (atomic_read(&sdp->sd_log_pinned) >= atomic_read(&sdp->sd_log_thresh1)); |
892 | } | 892 | } |
893 | 893 | ||
894 | static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp) | 894 | static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp) |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 82b6ac829656..241a399bf83d 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "quota.h" | 30 | #include "quota.h" |
31 | #include "recovery.h" | 31 | #include "recovery.h" |
32 | #include "dir.h" | 32 | #include "dir.h" |
33 | #include "glops.h" | ||
33 | 34 | ||
34 | struct workqueue_struct *gfs2_control_wq; | 35 | struct workqueue_struct *gfs2_control_wq; |
35 | 36 | ||
@@ -161,9 +162,14 @@ static int __init init_gfs2_fs(void) | |||
161 | if (!gfs2_control_wq) | 162 | if (!gfs2_control_wq) |
162 | goto fail_recovery; | 163 | goto fail_recovery; |
163 | 164 | ||
165 | gfs2_freeze_wq = alloc_workqueue("freeze_workqueue", 0, 0); | ||
166 | |||
167 | if (!gfs2_freeze_wq) | ||
168 | goto fail_control; | ||
169 | |||
164 | gfs2_page_pool = mempool_create_page_pool(64, 0); | 170 | gfs2_page_pool = mempool_create_page_pool(64, 0); |
165 | if (!gfs2_page_pool) | 171 | if (!gfs2_page_pool) |
166 | goto fail_control; | 172 | goto fail_freeze; |
167 | 173 | ||
168 | gfs2_register_debugfs(); | 174 | gfs2_register_debugfs(); |
169 | 175 | ||
@@ -171,6 +177,8 @@ static int __init init_gfs2_fs(void) | |||
171 | 177 | ||
172 | return 0; | 178 | return 0; |
173 | 179 | ||
180 | fail_freeze: | ||
181 | destroy_workqueue(gfs2_freeze_wq); | ||
174 | fail_control: | 182 | fail_control: |
175 | destroy_workqueue(gfs2_control_wq); | 183 | destroy_workqueue(gfs2_control_wq); |
176 | fail_recovery: | 184 | fail_recovery: |
@@ -224,6 +232,7 @@ static void __exit exit_gfs2_fs(void) | |||
224 | unregister_filesystem(&gfs2meta_fs_type); | 232 | unregister_filesystem(&gfs2meta_fs_type); |
225 | destroy_workqueue(gfs_recovery_wq); | 233 | destroy_workqueue(gfs_recovery_wq); |
226 | destroy_workqueue(gfs2_control_wq); | 234 | destroy_workqueue(gfs2_control_wq); |
235 | destroy_workqueue(gfs2_freeze_wq); | ||
227 | list_lru_destroy(&gfs2_qd_lru); | 236 | list_lru_destroy(&gfs2_qd_lru); |
228 | 237 | ||
229 | rcu_barrier(); | 238 | rcu_barrier(); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index d3eae244076e..b5803acb8818 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -129,11 +129,11 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
129 | 129 | ||
130 | init_rwsem(&sdp->sd_log_flush_lock); | 130 | init_rwsem(&sdp->sd_log_flush_lock); |
131 | atomic_set(&sdp->sd_log_in_flight, 0); | 131 | atomic_set(&sdp->sd_log_in_flight, 0); |
132 | atomic_set(&sdp->sd_reserving_log, 0); | ||
133 | init_waitqueue_head(&sdp->sd_reserving_log_wait); | ||
132 | init_waitqueue_head(&sdp->sd_log_flush_wait); | 134 | init_waitqueue_head(&sdp->sd_log_flush_wait); |
133 | init_waitqueue_head(&sdp->sd_log_frozen_wait); | 135 | atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN); |
134 | atomic_set(&sdp->sd_log_freeze, 0); | 136 | mutex_init(&sdp->sd_freeze_mutex); |
135 | atomic_set(&sdp->sd_frozen_root, 0); | ||
136 | init_waitqueue_head(&sdp->sd_frozen_root_wait); | ||
137 | 137 | ||
138 | return sdp; | 138 | return sdp; |
139 | } | 139 | } |
@@ -760,15 +760,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
760 | set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); | 760 | set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); |
761 | gfs2_glock_dq_uninit(&ji_gh); | 761 | gfs2_glock_dq_uninit(&ji_gh); |
762 | jindex = 0; | 762 | jindex = 0; |
763 | if (!sdp->sd_args.ar_spectator) { | 763 | INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func); |
764 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, | ||
765 | &sdp->sd_thaw_gh); | ||
766 | if (error) { | ||
767 | fs_err(sdp, "can't acquire freeze glock: %d\n", error); | ||
768 | goto fail_jinode_gh; | ||
769 | } | ||
770 | } | ||
771 | gfs2_glock_dq_uninit(&sdp->sd_thaw_gh); | ||
772 | return 0; | 764 | return 0; |
773 | 765 | ||
774 | fail_jinode_gh: | 766 | fail_jinode_gh: |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 64b29f7f6b4c..c8b148bbdc8b 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -1360,13 +1360,8 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp) | |||
1360 | 1360 | ||
1361 | gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_quota_count)); | 1361 | gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_quota_count)); |
1362 | 1362 | ||
1363 | if (sdp->sd_quota_bitmap) { | 1363 | kvfree(sdp->sd_quota_bitmap); |
1364 | if (is_vmalloc_addr(sdp->sd_quota_bitmap)) | 1364 | sdp->sd_quota_bitmap = NULL; |
1365 | vfree(sdp->sd_quota_bitmap); | ||
1366 | else | ||
1367 | kfree(sdp->sd_quota_bitmap); | ||
1368 | sdp->sd_quota_bitmap = NULL; | ||
1369 | } | ||
1370 | } | 1365 | } |
1371 | 1366 | ||
1372 | static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error) | 1367 | static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error) |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 7474c413ffd1..9150207f365c 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -936,7 +936,7 @@ static int read_rindex_entry(struct gfs2_inode *ip) | |||
936 | rgd->rd_gl->gl_vm.start = rgd->rd_addr * bsize; | 936 | rgd->rd_gl->gl_vm.start = rgd->rd_addr * bsize; |
937 | rgd->rd_gl->gl_vm.end = rgd->rd_gl->gl_vm.start + (rgd->rd_length * bsize) - 1; | 937 | rgd->rd_gl->gl_vm.end = rgd->rd_gl->gl_vm.start + (rgd->rd_length * bsize) - 1; |
938 | rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr; | 938 | rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr; |
939 | rgd->rd_flags &= ~GFS2_RDF_UPTODATE; | 939 | rgd->rd_flags &= ~(GFS2_RDF_UPTODATE | GFS2_RDF_PREFERRED); |
940 | if (rgd->rd_data > sdp->sd_max_rg_data) | 940 | if (rgd->rd_data > sdp->sd_max_rg_data) |
941 | sdp->sd_max_rg_data = rgd->rd_data; | 941 | sdp->sd_max_rg_data = rgd->rd_data; |
942 | spin_lock(&sdp->sd_rindex_spin); | 942 | spin_lock(&sdp->sd_rindex_spin); |
@@ -955,6 +955,36 @@ fail: | |||
955 | } | 955 | } |
956 | 956 | ||
957 | /** | 957 | /** |
958 | * set_rgrp_preferences - Run all the rgrps, selecting some we prefer to use | ||
959 | * @sdp: the GFS2 superblock | ||
960 | * | ||
961 | * The purpose of this function is to select a subset of the resource groups | ||
962 | * and mark them as PREFERRED. We do it in such a way that each node prefers | ||
963 | * to use a unique set of rgrps to minimize glock contention. | ||
964 | */ | ||
965 | static void set_rgrp_preferences(struct gfs2_sbd *sdp) | ||
966 | { | ||
967 | struct gfs2_rgrpd *rgd, *first; | ||
968 | int i; | ||
969 | |||
970 | /* Skip an initial number of rgrps, based on this node's journal ID. | ||
971 | That should start each node out on its own set. */ | ||
972 | rgd = gfs2_rgrpd_get_first(sdp); | ||
973 | for (i = 0; i < sdp->sd_lockstruct.ls_jid; i++) | ||
974 | rgd = gfs2_rgrpd_get_next(rgd); | ||
975 | first = rgd; | ||
976 | |||
977 | do { | ||
978 | rgd->rd_flags |= GFS2_RDF_PREFERRED; | ||
979 | for (i = 0; i < sdp->sd_journals; i++) { | ||
980 | rgd = gfs2_rgrpd_get_next(rgd); | ||
981 | if (rgd == first) | ||
982 | break; | ||
983 | } | ||
984 | } while (rgd != first); | ||
985 | } | ||
986 | |||
987 | /** | ||
958 | * gfs2_ri_update - Pull in a new resource index from the disk | 988 | * gfs2_ri_update - Pull in a new resource index from the disk |
959 | * @ip: pointer to the rindex inode | 989 | * @ip: pointer to the rindex inode |
960 | * | 990 | * |
@@ -973,6 +1003,8 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
973 | if (error < 0) | 1003 | if (error < 0) |
974 | return error; | 1004 | return error; |
975 | 1005 | ||
1006 | set_rgrp_preferences(sdp); | ||
1007 | |||
976 | sdp->sd_rindex_uptodate = 1; | 1008 | sdp->sd_rindex_uptodate = 1; |
977 | return 0; | 1009 | return 0; |
978 | } | 1010 | } |
@@ -1891,6 +1923,25 @@ static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *b | |||
1891 | } | 1923 | } |
1892 | 1924 | ||
1893 | /** | 1925 | /** |
1926 | * fast_to_acquire - determine if a resource group will be fast to acquire | ||
1927 | * | ||
1928 | * If this is one of our preferred rgrps, it should be quicker to acquire, | ||
1929 | * because we tried to set ourselves up as dlm lock master. | ||
1930 | */ | ||
1931 | static inline int fast_to_acquire(struct gfs2_rgrpd *rgd) | ||
1932 | { | ||
1933 | struct gfs2_glock *gl = rgd->rd_gl; | ||
1934 | |||
1935 | if (gl->gl_state != LM_ST_UNLOCKED && list_empty(&gl->gl_holders) && | ||
1936 | !test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags) && | ||
1937 | !test_bit(GLF_DEMOTE, &gl->gl_flags)) | ||
1938 | return 1; | ||
1939 | if (rgd->rd_flags & GFS2_RDF_PREFERRED) | ||
1940 | return 1; | ||
1941 | return 0; | ||
1942 | } | ||
1943 | |||
1944 | /** | ||
1894 | * gfs2_inplace_reserve - Reserve space in the filesystem | 1945 | * gfs2_inplace_reserve - Reserve space in the filesystem |
1895 | * @ip: the inode to reserve space for | 1946 | * @ip: the inode to reserve space for |
1896 | * @ap: the allocation parameters | 1947 | * @ap: the allocation parameters |
@@ -1932,10 +1983,15 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a | |||
1932 | rg_locked = 0; | 1983 | rg_locked = 0; |
1933 | if (skip && skip--) | 1984 | if (skip && skip--) |
1934 | goto next_rgrp; | 1985 | goto next_rgrp; |
1935 | if (!gfs2_rs_active(rs) && (loops < 2) && | 1986 | if (!gfs2_rs_active(rs)) { |
1936 | gfs2_rgrp_used_recently(rs, 1000) && | 1987 | if (loops == 0 && |
1937 | gfs2_rgrp_congested(rs->rs_rbm.rgd, loops)) | 1988 | !fast_to_acquire(rs->rs_rbm.rgd)) |
1938 | goto next_rgrp; | 1989 | goto next_rgrp; |
1990 | if ((loops < 2) && | ||
1991 | gfs2_rgrp_used_recently(rs, 1000) && | ||
1992 | gfs2_rgrp_congested(rs->rs_rbm.rgd, loops)) | ||
1993 | goto next_rgrp; | ||
1994 | } | ||
1939 | error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl, | 1995 | error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl, |
1940 | LM_ST_EXCLUSIVE, flags, | 1996 | LM_ST_EXCLUSIVE, flags, |
1941 | &rs->rs_rgd_gh); | 1997 | &rs->rs_rgd_gh); |
@@ -2195,6 +2251,9 @@ static void gfs2_adjust_reservation(struct gfs2_inode *ip, | |||
2195 | trace_gfs2_rs(rs, TRACE_RS_CLAIM); | 2251 | trace_gfs2_rs(rs, TRACE_RS_CLAIM); |
2196 | if (rs->rs_free && !ret) | 2252 | if (rs->rs_free && !ret) |
2197 | goto out; | 2253 | goto out; |
2254 | /* We used up our block reservation, so we should | ||
2255 | reserve more blocks next time. */ | ||
2256 | atomic_add(RGRP_RSRV_ADDBLKS, &rs->rs_sizehint); | ||
2198 | } | 2257 | } |
2199 | __rs_deltree(rs); | 2258 | __rs_deltree(rs); |
2200 | } | 2259 | } |
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index 5d8f085f7ade..b104f4af3afd 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #define RGRP_RSRV_MINBYTES 8 | 21 | #define RGRP_RSRV_MINBYTES 8 |
22 | #define RGRP_RSRV_MINBLKS ((u32)(RGRP_RSRV_MINBYTES * GFS2_NBBY)) | 22 | #define RGRP_RSRV_MINBLKS ((u32)(RGRP_RSRV_MINBYTES * GFS2_NBBY)) |
23 | #define RGRP_RSRV_ADDBLKS 64 | ||
23 | 24 | ||
24 | struct gfs2_rgrpd; | 25 | struct gfs2_rgrpd; |
25 | struct gfs2_sbd; | 26 | struct gfs2_sbd; |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index a346f56c4c6d..5b327f837de7 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/wait.h> | 26 | #include <linux/wait.h> |
27 | #include <linux/writeback.h> | 27 | #include <linux/writeback.h> |
28 | #include <linux/backing-dev.h> | 28 | #include <linux/backing-dev.h> |
29 | #include <linux/kernel.h> | ||
29 | 30 | ||
30 | #include "gfs2.h" | 31 | #include "gfs2.h" |
31 | #include "incore.h" | 32 | #include "incore.h" |
@@ -399,7 +400,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) | |||
399 | { | 400 | { |
400 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); | 401 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); |
401 | struct gfs2_glock *j_gl = ip->i_gl; | 402 | struct gfs2_glock *j_gl = ip->i_gl; |
402 | struct gfs2_holder thaw_gh; | 403 | struct gfs2_holder freeze_gh; |
403 | struct gfs2_log_header_host head; | 404 | struct gfs2_log_header_host head; |
404 | int error; | 405 | int error; |
405 | 406 | ||
@@ -408,7 +409,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) | |||
408 | return error; | 409 | return error; |
409 | 410 | ||
410 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, | 411 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, |
411 | &thaw_gh); | 412 | &freeze_gh); |
412 | if (error) | 413 | if (error) |
413 | goto fail_threads; | 414 | goto fail_threads; |
414 | 415 | ||
@@ -434,13 +435,13 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) | |||
434 | 435 | ||
435 | set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); | 436 | set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); |
436 | 437 | ||
437 | gfs2_glock_dq_uninit(&thaw_gh); | 438 | gfs2_glock_dq_uninit(&freeze_gh); |
438 | 439 | ||
439 | return 0; | 440 | return 0; |
440 | 441 | ||
441 | fail: | 442 | fail: |
442 | thaw_gh.gh_flags |= GL_NOCACHE; | 443 | freeze_gh.gh_flags |= GL_NOCACHE; |
443 | gfs2_glock_dq_uninit(&thaw_gh); | 444 | gfs2_glock_dq_uninit(&freeze_gh); |
444 | fail_threads: | 445 | fail_threads: |
445 | kthread_stop(sdp->sd_quotad_process); | 446 | kthread_stop(sdp->sd_quotad_process); |
446 | kthread_stop(sdp->sd_logd_process); | 447 | kthread_stop(sdp->sd_logd_process); |
@@ -580,14 +581,15 @@ int gfs2_statfs_sync(struct super_block *sb, int type) | |||
580 | struct buffer_head *m_bh, *l_bh; | 581 | struct buffer_head *m_bh, *l_bh; |
581 | int error; | 582 | int error; |
582 | 583 | ||
584 | sb_start_write(sb); | ||
583 | error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, | 585 | error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, |
584 | &gh); | 586 | &gh); |
585 | if (error) | 587 | if (error) |
586 | return error; | 588 | goto out; |
587 | 589 | ||
588 | error = gfs2_meta_inode_buffer(m_ip, &m_bh); | 590 | error = gfs2_meta_inode_buffer(m_ip, &m_bh); |
589 | if (error) | 591 | if (error) |
590 | goto out; | 592 | goto out_unlock; |
591 | 593 | ||
592 | spin_lock(&sdp->sd_statfs_spin); | 594 | spin_lock(&sdp->sd_statfs_spin); |
593 | gfs2_statfs_change_in(m_sc, m_bh->b_data + | 595 | gfs2_statfs_change_in(m_sc, m_bh->b_data + |
@@ -615,8 +617,10 @@ out_bh2: | |||
615 | brelse(l_bh); | 617 | brelse(l_bh); |
616 | out_bh: | 618 | out_bh: |
617 | brelse(m_bh); | 619 | brelse(m_bh); |
618 | out: | 620 | out_unlock: |
619 | gfs2_glock_dq_uninit(&gh); | 621 | gfs2_glock_dq_uninit(&gh); |
622 | out: | ||
623 | sb_end_write(sb); | ||
620 | return error; | 624 | return error; |
621 | } | 625 | } |
622 | 626 | ||
@@ -643,14 +647,8 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, | |||
643 | struct lfcc *lfcc; | 647 | struct lfcc *lfcc; |
644 | LIST_HEAD(list); | 648 | LIST_HEAD(list); |
645 | struct gfs2_log_header_host lh; | 649 | struct gfs2_log_header_host lh; |
646 | struct gfs2_inode *dip = GFS2_I(sdp->sd_root_dir->d_inode); | ||
647 | int error; | 650 | int error; |
648 | 651 | ||
649 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, | ||
650 | &sdp->sd_freeze_root_gh); | ||
651 | if (error) | ||
652 | return error; | ||
653 | atomic_set(&sdp->sd_frozen_root, 1); | ||
654 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { | 652 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { |
655 | lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL); | 653 | lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL); |
656 | if (!lfcc) { | 654 | if (!lfcc) { |
@@ -692,11 +690,6 @@ out: | |||
692 | gfs2_glock_dq_uninit(&lfcc->gh); | 690 | gfs2_glock_dq_uninit(&lfcc->gh); |
693 | kfree(lfcc); | 691 | kfree(lfcc); |
694 | } | 692 | } |
695 | if (error) { | ||
696 | atomic_dec(&sdp->sd_frozen_root); | ||
697 | wait_event(sdp->sd_frozen_root_wait, atomic_read(&sdp->sd_frozen_root) == 0); | ||
698 | gfs2_glock_dq_uninit(&sdp->sd_freeze_root_gh); | ||
699 | } | ||
700 | return error; | 693 | return error; |
701 | } | 694 | } |
702 | 695 | ||
@@ -834,18 +827,14 @@ out: | |||
834 | 827 | ||
835 | static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | 828 | static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) |
836 | { | 829 | { |
837 | struct gfs2_holder thaw_gh; | 830 | struct gfs2_holder freeze_gh; |
838 | int error; | 831 | int error; |
839 | 832 | ||
840 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, GL_NOCACHE, | 833 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, GL_NOCACHE, |
841 | &thaw_gh); | 834 | &freeze_gh); |
842 | if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | 835 | if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) |
843 | return error; | 836 | return error; |
844 | 837 | ||
845 | down_write(&sdp->sd_log_flush_lock); | ||
846 | clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); | ||
847 | up_write(&sdp->sd_log_flush_lock); | ||
848 | |||
849 | kthread_stop(sdp->sd_quotad_process); | 838 | kthread_stop(sdp->sd_quotad_process); |
850 | kthread_stop(sdp->sd_logd_process); | 839 | kthread_stop(sdp->sd_logd_process); |
851 | 840 | ||
@@ -853,11 +842,16 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
853 | gfs2_quota_sync(sdp->sd_vfs, 0); | 842 | gfs2_quota_sync(sdp->sd_vfs, 0); |
854 | gfs2_statfs_sync(sdp->sd_vfs, 0); | 843 | gfs2_statfs_sync(sdp->sd_vfs, 0); |
855 | 844 | ||
845 | down_write(&sdp->sd_log_flush_lock); | ||
846 | clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); | ||
847 | up_write(&sdp->sd_log_flush_lock); | ||
848 | |||
856 | gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH); | 849 | gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH); |
850 | wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0); | ||
857 | gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); | 851 | gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); |
858 | 852 | ||
859 | if (thaw_gh.gh_gl) | 853 | if (freeze_gh.gh_gl) |
860 | gfs2_glock_dq_uninit(&thaw_gh); | 854 | gfs2_glock_dq_uninit(&freeze_gh); |
861 | 855 | ||
862 | gfs2_quota_cleanup(sdp); | 856 | gfs2_quota_cleanup(sdp); |
863 | 857 | ||
@@ -943,11 +937,41 @@ static int gfs2_sync_fs(struct super_block *sb, int wait) | |||
943 | struct gfs2_sbd *sdp = sb->s_fs_info; | 937 | struct gfs2_sbd *sdp = sb->s_fs_info; |
944 | 938 | ||
945 | gfs2_quota_sync(sb, -1); | 939 | gfs2_quota_sync(sb, -1); |
946 | if (wait && sdp && !atomic_read(&sdp->sd_log_freeze)) | 940 | if (wait && sdp) |
947 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); | 941 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
948 | return 0; | 942 | return 0; |
949 | } | 943 | } |
950 | 944 | ||
945 | void gfs2_freeze_func(struct work_struct *work) | ||
946 | { | ||
947 | int error; | ||
948 | struct gfs2_holder freeze_gh; | ||
949 | struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_freeze_work); | ||
950 | struct super_block *sb = sdp->sd_vfs; | ||
951 | |||
952 | atomic_inc(&sb->s_active); | ||
953 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, | ||
954 | &freeze_gh); | ||
955 | if (error) { | ||
956 | printk(KERN_INFO "GFS2: couln't get freeze lock : %d\n", error); | ||
957 | gfs2_assert_withdraw(sdp, 0); | ||
958 | } | ||
959 | else { | ||
960 | atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN); | ||
961 | error = thaw_super(sb); | ||
962 | if (error) { | ||
963 | printk(KERN_INFO "GFS2: couldn't thaw filesystem: %d\n", | ||
964 | error); | ||
965 | gfs2_assert_withdraw(sdp, 0); | ||
966 | } | ||
967 | if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) | ||
968 | freeze_gh.gh_flags |= GL_NOCACHE; | ||
969 | gfs2_glock_dq_uninit(&freeze_gh); | ||
970 | } | ||
971 | deactivate_super(sb); | ||
972 | return; | ||
973 | } | ||
974 | |||
951 | /** | 975 | /** |
952 | * gfs2_freeze - prevent further writes to the filesystem | 976 | * gfs2_freeze - prevent further writes to the filesystem |
953 | * @sb: the VFS structure for the filesystem | 977 | * @sb: the VFS structure for the filesystem |
@@ -957,10 +981,16 @@ static int gfs2_sync_fs(struct super_block *sb, int wait) | |||
957 | static int gfs2_freeze(struct super_block *sb) | 981 | static int gfs2_freeze(struct super_block *sb) |
958 | { | 982 | { |
959 | struct gfs2_sbd *sdp = sb->s_fs_info; | 983 | struct gfs2_sbd *sdp = sb->s_fs_info; |
960 | int error; | 984 | int error = 0; |
961 | 985 | ||
962 | if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | 986 | mutex_lock(&sdp->sd_freeze_mutex); |
963 | return -EINVAL; | 987 | if (atomic_read(&sdp->sd_freeze_state) != SFS_UNFROZEN) |
988 | goto out; | ||
989 | |||
990 | if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) { | ||
991 | error = -EINVAL; | ||
992 | goto out; | ||
993 | } | ||
964 | 994 | ||
965 | for (;;) { | 995 | for (;;) { |
966 | error = gfs2_lock_fs_check_clean(sdp, &sdp->sd_freeze_gh); | 996 | error = gfs2_lock_fs_check_clean(sdp, &sdp->sd_freeze_gh); |
@@ -980,7 +1010,10 @@ static int gfs2_freeze(struct super_block *sb) | |||
980 | fs_err(sdp, "retrying...\n"); | 1010 | fs_err(sdp, "retrying...\n"); |
981 | msleep(1000); | 1011 | msleep(1000); |
982 | } | 1012 | } |
983 | return 0; | 1013 | error = 0; |
1014 | out: | ||
1015 | mutex_unlock(&sdp->sd_freeze_mutex); | ||
1016 | return error; | ||
984 | } | 1017 | } |
985 | 1018 | ||
986 | /** | 1019 | /** |
@@ -993,10 +1026,15 @@ static int gfs2_unfreeze(struct super_block *sb) | |||
993 | { | 1026 | { |
994 | struct gfs2_sbd *sdp = sb->s_fs_info; | 1027 | struct gfs2_sbd *sdp = sb->s_fs_info; |
995 | 1028 | ||
1029 | mutex_lock(&sdp->sd_freeze_mutex); | ||
1030 | if (atomic_read(&sdp->sd_freeze_state) != SFS_FROZEN || | ||
1031 | sdp->sd_freeze_gh.gh_gl == NULL) { | ||
1032 | mutex_unlock(&sdp->sd_freeze_mutex); | ||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
996 | gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); | 1036 | gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); |
997 | atomic_dec(&sdp->sd_frozen_root); | 1037 | mutex_unlock(&sdp->sd_freeze_mutex); |
998 | wait_event(sdp->sd_frozen_root_wait, atomic_read(&sdp->sd_frozen_root) == 0); | ||
999 | gfs2_glock_dq_uninit(&sdp->sd_freeze_root_gh); | ||
1000 | return 0; | 1038 | return 0; |
1001 | } | 1039 | } |
1002 | 1040 | ||
@@ -1618,8 +1656,8 @@ const struct super_operations gfs2_super_ops = { | |||
1618 | .evict_inode = gfs2_evict_inode, | 1656 | .evict_inode = gfs2_evict_inode, |
1619 | .put_super = gfs2_put_super, | 1657 | .put_super = gfs2_put_super, |
1620 | .sync_fs = gfs2_sync_fs, | 1658 | .sync_fs = gfs2_sync_fs, |
1621 | .freeze_fs = gfs2_freeze, | 1659 | .freeze_super = gfs2_freeze, |
1622 | .unfreeze_fs = gfs2_unfreeze, | 1660 | .thaw_super = gfs2_unfreeze, |
1623 | .statfs = gfs2_statfs, | 1661 | .statfs = gfs2_statfs, |
1624 | .remount_fs = gfs2_remount_fs, | 1662 | .remount_fs = gfs2_remount_fs, |
1625 | .drop_inode = gfs2_drop_inode, | 1663 | .drop_inode = gfs2_drop_inode, |
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 90e3322ffa10..73c97dccae21 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
@@ -45,6 +45,7 @@ extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, | |||
45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | 45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, |
46 | struct buffer_head *l_bh); | 46 | struct buffer_head *l_bh); |
47 | extern int gfs2_statfs_sync(struct super_block *sb, int type); | 47 | extern int gfs2_statfs_sync(struct super_block *sb, int type); |
48 | extern void gfs2_freeze_func(struct work_struct *work); | ||
48 | 49 | ||
49 | extern struct file_system_type gfs2_fs_type; | 50 | extern struct file_system_type gfs2_fs_type; |
50 | extern struct file_system_type gfs2meta_fs_type; | 51 | extern struct file_system_type gfs2meta_fs_type; |
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 42bfd3361979..88bff2430669 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
@@ -89,14 +89,17 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
89 | { | 89 | { |
90 | struct gfs2_trans *tr = current->journal_info; | 90 | struct gfs2_trans *tr = current->journal_info; |
91 | s64 nbuf; | 91 | s64 nbuf; |
92 | int alloced = tr->tr_alloced; | ||
93 | |||
92 | BUG_ON(!tr); | 94 | BUG_ON(!tr); |
93 | current->journal_info = NULL; | 95 | current->journal_info = NULL; |
94 | 96 | ||
95 | if (!tr->tr_touched) { | 97 | if (!tr->tr_touched) { |
96 | gfs2_log_release(sdp, tr->tr_reserved); | 98 | gfs2_log_release(sdp, tr->tr_reserved); |
97 | if (tr->tr_alloced) | 99 | if (alloced) { |
98 | kfree(tr); | 100 | kfree(tr); |
99 | sb_end_intwrite(sdp->sd_vfs); | 101 | sb_end_intwrite(sdp->sd_vfs); |
102 | } | ||
100 | return; | 103 | return; |
101 | } | 104 | } |
102 | 105 | ||
@@ -109,13 +112,14 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
109 | gfs2_print_trans(tr); | 112 | gfs2_print_trans(tr); |
110 | 113 | ||
111 | gfs2_log_commit(sdp, tr); | 114 | gfs2_log_commit(sdp, tr); |
112 | if (tr->tr_alloced && !tr->tr_attached) | 115 | if (alloced && !tr->tr_attached) |
113 | kfree(tr); | 116 | kfree(tr); |
114 | up_read(&sdp->sd_log_flush_lock); | 117 | up_read(&sdp->sd_log_flush_lock); |
115 | 118 | ||
116 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) | 119 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) |
117 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); | 120 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
118 | sb_end_intwrite(sdp->sd_vfs); | 121 | if (alloced) |
122 | sb_end_intwrite(sdp->sd_vfs); | ||
119 | } | 123 | } |
120 | 124 | ||
121 | static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, | 125 | static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, |
@@ -192,6 +196,7 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | |||
192 | { | 196 | { |
193 | struct gfs2_meta_header *mh; | 197 | struct gfs2_meta_header *mh; |
194 | struct gfs2_trans *tr; | 198 | struct gfs2_trans *tr; |
199 | enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); | ||
195 | 200 | ||
196 | tr = current->journal_info; | 201 | tr = current->journal_info; |
197 | tr->tr_touched = 1; | 202 | tr->tr_touched = 1; |
@@ -205,6 +210,10 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | |||
205 | (unsigned long long)bd->bd_bh->b_blocknr); | 210 | (unsigned long long)bd->bd_bh->b_blocknr); |
206 | BUG(); | 211 | BUG(); |
207 | } | 212 | } |
213 | if (unlikely(state == SFS_FROZEN)) { | ||
214 | printk(KERN_INFO "GFS2:adding buf while frozen\n"); | ||
215 | gfs2_assert_withdraw(sdp, 0); | ||
216 | } | ||
208 | gfs2_pin(sdp, bd->bd_bh); | 217 | gfs2_pin(sdp, bd->bd_bh); |
209 | mh->__pad0 = cpu_to_be64(0); | 218 | mh->__pad0 = cpu_to_be64(0); |
210 | mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); | 219 | mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); |
diff --git a/fs/ioctl.c b/fs/ioctl.c index 8ac3fad36192..77c9a7812542 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -518,10 +518,12 @@ static int ioctl_fsfreeze(struct file *filp) | |||
518 | return -EPERM; | 518 | return -EPERM; |
519 | 519 | ||
520 | /* If filesystem doesn't support freeze feature, return. */ | 520 | /* If filesystem doesn't support freeze feature, return. */ |
521 | if (sb->s_op->freeze_fs == NULL) | 521 | if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL) |
522 | return -EOPNOTSUPP; | 522 | return -EOPNOTSUPP; |
523 | 523 | ||
524 | /* Freeze */ | 524 | /* Freeze */ |
525 | if (sb->s_op->freeze_super) | ||
526 | return sb->s_op->freeze_super(sb); | ||
525 | return freeze_super(sb); | 527 | return freeze_super(sb); |
526 | } | 528 | } |
527 | 529 | ||
@@ -533,6 +535,8 @@ static int ioctl_fsthaw(struct file *filp) | |||
533 | return -EPERM; | 535 | return -EPERM; |
534 | 536 | ||
535 | /* Thaw */ | 537 | /* Thaw */ |
538 | if (sb->s_op->thaw_super) | ||
539 | return sb->s_op->thaw_super(sb); | ||
536 | return thaw_super(sb); | 540 | return thaw_super(sb); |
537 | } | 541 | } |
538 | 542 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 9ab779e8a63c..b4a1d73c0d5d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1577,7 +1577,9 @@ struct super_operations { | |||
1577 | void (*evict_inode) (struct inode *); | 1577 | void (*evict_inode) (struct inode *); |
1578 | void (*put_super) (struct super_block *); | 1578 | void (*put_super) (struct super_block *); |
1579 | int (*sync_fs)(struct super_block *sb, int wait); | 1579 | int (*sync_fs)(struct super_block *sb, int wait); |
1580 | int (*freeze_super) (struct super_block *); | ||
1580 | int (*freeze_fs) (struct super_block *); | 1581 | int (*freeze_fs) (struct super_block *); |
1582 | int (*thaw_super) (struct super_block *); | ||
1581 | int (*unfreeze_fs) (struct super_block *); | 1583 | int (*unfreeze_fs) (struct super_block *); |
1582 | int (*statfs) (struct dentry *, struct kstatfs *); | 1584 | int (*statfs) (struct dentry *, struct kstatfs *); |
1583 | int (*remount_fs) (struct super_block *, int *, char *); | 1585 | int (*remount_fs) (struct super_block *, int *, char *); |