From ca5a939b33166a9f5a2556e6c4ec031524852ba2 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Tue, 31 Jul 2007 18:31:12 +0800 Subject: [GFS2] use the declaration of gfs2_dops in the header file instead Signed-off-by: Denis Cheng Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index cf5aa50..9a5e840 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -28,6 +28,7 @@ #include "lm.h" #include "mount.h" #include "ops_fstype.h" +#include "ops_dentry.h" #include "ops_super.h" #include "recovery.h" #include "rgrp.h" @@ -38,8 +39,6 @@ #define DO 0 #define UNDO 1 -extern struct dentry_operations gfs2_dops; - static struct gfs2_sbd *init_sbd(struct super_block *sb) { struct gfs2_sbd *sdp; -- cgit v1.1 From 8fbbfd214c853102b614f4705c1904ed14f5a808 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Aug 2007 13:57:10 +0100 Subject: [GFS2] Reduce number of gfs2_scand processes to one We only need a single gfs2_scand process rather than the one per filesystem which we had previously. As a result the parameter determining the frequency of gfs2_scand runs becomes a module parameter rather than a mount parameter as it was before. Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 9a5e840..58c730b 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -160,14 +160,6 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, if (undo) goto fail_trans; - p = kthread_run(gfs2_scand, sdp, "gfs2_scand"); - error = IS_ERR(p); - if (error) { - fs_err(sdp, "can't start scand thread: %d\n", error); - return error; - } - sdp->sd_scand_process = p; - for (sdp->sd_glockd_num = 0; sdp->sd_glockd_num < sdp->sd_args.ar_num_glockd; sdp->sd_glockd_num++) { @@ -228,7 +220,6 @@ fail: while (sdp->sd_glockd_num--) kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); - kthread_stop(sdp->sd_scand_process); return error; } -- cgit v1.1 From 75be73a8246ef96f7fa3f05a6a1450159fbb7a64 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Wed, 8 Aug 2007 17:08:14 -0500 Subject: [GFS2] Ensure journal file cache is flushed after recovery This is for bugzilla bug #248176: GFS2: invalid metadata block Patches 1 thru 3 were accepted upstream, but there were problems with 4 and 5. Those issues have been resolved and now the recovery tests are passing without errors. This code has gone through 41 * 3 successful gfs2 recovery tests before it hit an unrelated (openais) problem. I'm continuing to test it. This is a complete rewrite of patch 5 for bug #248176, written by Steve Whitehouse. This is referred to in the bugzilla record as "new 6" and "a different solution". The problem was that the journal inodes, although protected by a glock, were not synched with the other nodes because they don't use the inode glock synch operations (i.e. no "glops" were defined). Therefore, journal recovery on a journal-recovering node were causing the blocks to get out of sync with the node that was actually trying to use that journal as it comes back up from a reboot. There are two possible solutions: (1) To make the journals use the normal inode glock sync operations, or (2) To make the journal operations take effect immediately (i.e. no caching). Although option 1 works, it turns out to be a lot more code. Steve opted for option 2, which is much simpler and therefore less prone to regression errors. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse -- --- fs/gfs2/ops_fstype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 58c730b..f0bcaa2 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -358,7 +358,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ip = GFS2_I(sdp->sd_jdesc->jd_inode); error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, - LM_FLAG_NOEXP | GL_EXACT, + LM_FLAG_NOEXP | GL_EXACT | GL_NOCACHE, &sdp->sd_jinode_gh); if (error) { fs_err(sdp, "can't acquire journal inode glock: %d\n", -- cgit v1.1 From adb4ec13cdddb6ab8280e4c7808ba30f46504e1d Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Sat, 11 Aug 2007 10:27:07 +0800 Subject: [GFS2] use list_for_each_entry instead Signed-off-by: Denis Cheng Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index f0bcaa2..32b2859 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -808,7 +808,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name) struct nameidata nd; struct file_system_type *fstype; struct super_block *sb = NULL, *s; - struct list_head *l; int error; error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); @@ -820,8 +819,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name) error = vfs_getattr(nd.mnt, nd.dentry, &stat); fstype = get_fs_type("gfs2"); - list_for_each(l, &fstype->fs_supers) { - s = list_entry(l, struct super_block, s_instances); + list_for_each_entry(s, &fstype->fs_supers, s_instances) { if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || (S_ISDIR(stat.mode) && s == nd.dentry->d_inode->i_sb)) { sb = s; -- cgit v1.1 From 2d3ba1ea97d839e60d742ccf9a6de5bf039c0b53 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Sat, 11 Aug 2007 10:27:08 +0800 Subject: [GFS2] unneeded typecast sb->s_fs_info is a void pointer, thus the type cast is not needed. Signed-off-by: Denis Cheng Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 32b2859..25cfab9 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -849,7 +849,7 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, error = -ENOENT; goto error; } - sdp = (struct gfs2_sbd*) sb->s_fs_info; + sdp = sb->s_fs_info; if (sdp->sd_vfs_meta) { printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n"); error = -EBUSY; -- cgit v1.1 From 5d35e31f43c4910d0b6afc5160728a84bbaf86f0 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Mon, 13 Aug 2007 11:01:58 +0800 Subject: [GFS2] better code for translating characters the original code could work, but I think this code could work better. Signed-off-by: Denis Cheng Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 25cfab9..6c820cb 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -144,7 +144,8 @@ static int init_names(struct gfs2_sbd *sdp, int silent) snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto); snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table); - while ((table = strchr(sdp->sd_table_name, '/'))) + table = sdp->sd_table_name; + while ((table = strchr(table, '/'))) *table = '_'; out: -- cgit v1.1 From 34eaae398e29dadeed95efd30f1eb694e5932b34 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Wed, 15 Aug 2007 23:54:44 +0800 Subject: [GFS2] fixed a NULL pointer assignment BUG Signed-off-by: Denis Cheng Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 6c820cb..c1c6672 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -292,8 +292,9 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) fs_err(sdp, "can't get root dentry\n"); error = -ENOMEM; iput(inode); - } - sb->s_root->d_op = &gfs2_dops; + } else + sb->s_root->d_op = &gfs2_dops; + out: gfs2_glock_dq_uninit(&sb_gh); return error; -- cgit v1.1 From bb3b0e3df5420fdf2c6bbb4417525c6d2ef55bbb Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 16 Aug 2007 16:03:57 +0100 Subject: [GFS2] Clean up invalidatepage/releasepage This patch fixes some bugs relating to journaled data files by cleaning up the gfs2_invalidatepage() and gfs2_releasepage() functions. We now never block during gfs2_releasepage(), instead we always either release or refuse to release depending on the status of the buffers. This fixes Red Hat bugzillas #248969 and #252392. Signed-off-by: Steven Whitehouse Cc: Bob Peterson --- fs/gfs2/ops_fstype.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index c1c6672..9e0e9be 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -35,6 +35,7 @@ #include "super.h" #include "sys.h" #include "util.h" +#include "log.h" #define DO 0 #define UNDO 1 @@ -887,6 +888,7 @@ error: static void gfs2_kill_sb(struct super_block *sb) { gfs2_delete_debugfs_file(sb->s_fs_info); + gfs2_meta_syncfs(sb->s_fs_info); kill_block_super(sb); } -- cgit v1.1 From d1e2777d4f419a865ddccdb9b3412021d0e4de51 Mon Sep 17 00:00:00 2001 From: Abhijith Das Date: Thu, 23 Aug 2007 13:33:01 -0500 Subject: [GFS2] panic after can't parse mount arguments When you try to mount gfs2 with -o garbage, the mount fails and the gfs2 superblock is deallocated and becomes NULL. The vfs comes around later on and calls gfs2_kill_sb. At this point the hidden gfs2 superblock pointer (sb->s_fs_info) is NULL and dereferencing it through gfs2_meta_syncfs causes the panic. (the other function call to gfs2_delete_debugfs_file() succeeds because this function already checks for a NULL pointer) Signed-off-by: Abhijith Das Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 9e0e9be..314c113 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -887,8 +887,10 @@ error: static void gfs2_kill_sb(struct super_block *sb) { - gfs2_delete_debugfs_file(sb->s_fs_info); - gfs2_meta_syncfs(sb->s_fs_info); + if (sb->s_fs_info) { + gfs2_delete_debugfs_file(sb->s_fs_info); + gfs2_meta_syncfs(sb->s_fs_info); + } kill_block_super(sb); } -- cgit v1.1 From d7b616e252b125f12b007c392f7644053bb6f140 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Sun, 2 Sep 2007 10:48:13 +0100 Subject: [GFS2] Clean up ordered write code The following patch removes the ordered write processing from databuf_lo_before_commit() and moves it to log.c. This has the effect of greatly simplyfying databuf_lo_before_commit() and well as potentially making the ordered write code more efficient. As a side effect of this, its now possible to remove ordered buffers from the ordered buffer list at any time, so we now make use of this in invalidatepage and releasepage to ensure timely release of these buffers. Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 314c113..35f3dfa 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -82,6 +82,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) INIT_LIST_HEAD(&sdp->sd_log_le_revoke); INIT_LIST_HEAD(&sdp->sd_log_le_rg); INIT_LIST_HEAD(&sdp->sd_log_le_databuf); + INIT_LIST_HEAD(&sdp->sd_log_le_ordered); mutex_init(&sdp->sd_log_reserve_mutex); INIT_LIST_HEAD(&sdp->sd_ail1_list); -- cgit v1.1 From 16615be18cadf53ee6f8a4f0bdd647f0753421b1 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 17 Sep 2007 10:59:52 +0100 Subject: [GFS2] Clean up journaled data writing This patch cleans up the code for writing journaled data into the log. It also removes the need to allocate a small "tag" structure for each block written into the log. Instead we just keep count of the outstanding I/O so that we can be sure that its all been written at the correct time. Another result of this patch is that a number of ll_rw_block() calls have become submit_bh() calls, closing some races at the same time. Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 35f3dfa..1ac9afa 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -89,7 +89,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) INIT_LIST_HEAD(&sdp->sd_ail2_list); init_rwsem(&sdp->sd_log_flush_lock); - INIT_LIST_HEAD(&sdp->sd_log_flush_list); + atomic_set(&sdp->sd_log_in_flight, 0); + init_waitqueue_head(&sdp->sd_log_flush_wait); INIT_LIST_HEAD(&sdp->sd_revoke_list); -- cgit v1.1 From 7a9f53b3c1875bef22ad4588e818bc046ef183da Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 18 Sep 2007 13:33:18 -0500 Subject: [GFS2] Alternate gfs2_iget to avoid looking up inodes being freed There is a possible deadlock between two processes on the same node, where one process is deleting an inode, and another process is looking for allocated but unused inodes to delete in order to create more space. process A does an iput() on inode X, and it's i_count drops to 0. This causes iput_final() to be called, which puts an inode into state I_FREEING at generic_delete_inode(). There no point between when iput_final() is called, and when I_FREEING is set where GFS2 could acquire any glocks. Once I_FREEING is set, no other process on that node can successfully look up that inode until the delete finishes. process B locks the the resource group for the same inode in get_local_rgrp(), which is called by gfs2_inplace_reserve_i() process A tries to lock the resource group for the inode in gfs2_dinode_dealloc(), but it's already locked by process B process B waits in find_inode for the inode to have the I_FREEING state cleared. Deadlock. This patch solves the problem by adding an alternative to gfs2_iget(), gfs2_iget_skip(), that simply skips any inodes that are in the I_FREEING state.o The alternate test function is just like the original one, except that it fails if the inode is being freed, and sets a skipped flag. The alternate set function is just like the original, except that it fails if the skipped flag is set. Only try_rgrp_unlink() calls gfs2_iget_skip() instead of gfs2_iget(). Signed-off-by: Benjamin E. Marzinski Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/gfs2/ops_fstype.c') diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 1ac9afa..17de58e 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -230,7 +230,7 @@ fail: static inline struct inode *gfs2_lookup_root(struct super_block *sb, u64 no_addr) { - return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0); + return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); } static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) -- cgit v1.1