aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-07-11 03:53:30 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-07-12 04:15:46 -0400
commit3942ae5319640ced5844b75f44884e4bcb8a2f16 (patch)
treecc9eee61c37d18e1887f0723d338b121561dc0b9
parent1ce533686c7d40bf900dc346a7279c17a9ee8e0e (diff)
GFS2: Fix race during filesystem mount
There is a potential race during filesystem mounting which has recently been reported. It occurs when the userland gfs_controld is able to process requests fast enough that it tries to use the sysfs interface before the lock module is properly initialised. This is a pretty unusual case as normally the lock module initialisation is very quick compared with gfs_controld. This patch adds an interruptible completion which is used to ensure that userland will wait for the initialisation of the lock module to complete. There are other potential solutions to this problem, but this is the quickest at this stage and has been tested both with and without mount.gfs2 present in the system. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Reported-by: David Booher <dbooher@adams.net>
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/ops_fstype.c3
-rw-r--r--fs/gfs2/sys.c7
3 files changed, 11 insertions, 1 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 0a064e91ac70..81206e70cbf6 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -17,6 +17,7 @@
17#include <linux/buffer_head.h> 17#include <linux/buffer_head.h>
18#include <linux/rcupdate.h> 18#include <linux/rcupdate.h>
19#include <linux/rculist_bl.h> 19#include <linux/rculist_bl.h>
20#include <linux/completion.h>
20 21
21#define DIO_WAIT 0x00000010 22#define DIO_WAIT 0x00000010
22#define DIO_METADATA 0x00000020 23#define DIO_METADATA 0x00000020
@@ -546,6 +547,7 @@ struct gfs2_sbd {
546 struct gfs2_glock *sd_trans_gl; 547 struct gfs2_glock *sd_trans_gl;
547 wait_queue_head_t sd_glock_wait; 548 wait_queue_head_t sd_glock_wait;
548 atomic_t sd_glock_disposal; 549 atomic_t sd_glock_disposal;
550 struct completion sd_locking_init;
549 551
550 /* Inode Stuff */ 552 /* Inode Stuff */
551 553
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 8ac9ae189b53..2a77071fb7b6 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -72,6 +72,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
72 72
73 init_waitqueue_head(&sdp->sd_glock_wait); 73 init_waitqueue_head(&sdp->sd_glock_wait);
74 atomic_set(&sdp->sd_glock_disposal, 0); 74 atomic_set(&sdp->sd_glock_disposal, 0);
75 init_completion(&sdp->sd_locking_init);
75 spin_lock_init(&sdp->sd_statfs_spin); 76 spin_lock_init(&sdp->sd_statfs_spin);
76 77
77 spin_lock_init(&sdp->sd_rindex_spin); 78 spin_lock_init(&sdp->sd_rindex_spin);
@@ -1017,11 +1018,13 @@ hostdata_error:
1017 fsname++; 1018 fsname++;
1018 if (lm->lm_mount == NULL) { 1019 if (lm->lm_mount == NULL) {
1019 fs_info(sdp, "Now mounting FS...\n"); 1020 fs_info(sdp, "Now mounting FS...\n");
1021 complete(&sdp->sd_locking_init);
1020 return 0; 1022 return 0;
1021 } 1023 }
1022 ret = lm->lm_mount(sdp, fsname); 1024 ret = lm->lm_mount(sdp, fsname);
1023 if (ret == 0) 1025 if (ret == 0)
1024 fs_info(sdp, "Joined cluster. Now mounting FS...\n"); 1026 fs_info(sdp, "Joined cluster. Now mounting FS...\n");
1027 complete(&sdp->sd_locking_init);
1025 return ret; 1028 return ret;
1026} 1029}
1027 1030
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index e20eab37bc80..443cabcfcd23 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -338,6 +338,9 @@ static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
338 rv = sscanf(buf, "%u", &first); 338 rv = sscanf(buf, "%u", &first);
339 if (rv != 1 || first > 1) 339 if (rv != 1 || first > 1)
340 return -EINVAL; 340 return -EINVAL;
341 rv = wait_for_completion_killable(&sdp->sd_locking_init);
342 if (rv)
343 return rv;
341 spin_lock(&sdp->sd_jindex_spin); 344 spin_lock(&sdp->sd_jindex_spin);
342 rv = -EBUSY; 345 rv = -EBUSY;
343 if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) 346 if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
@@ -414,7 +417,9 @@ static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
414 rv = sscanf(buf, "%d", &jid); 417 rv = sscanf(buf, "%d", &jid);
415 if (rv != 1) 418 if (rv != 1)
416 return -EINVAL; 419 return -EINVAL;
417 420 rv = wait_for_completion_killable(&sdp->sd_locking_init);
421 if (rv)
422 return rv;
418 spin_lock(&sdp->sd_jindex_spin); 423 spin_lock(&sdp->sd_jindex_spin);
419 rv = -EINVAL; 424 rv = -EINVAL;
420 if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) 425 if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)