Commit 3942ae53 authored by Steven Whitehouse's avatar Steven Whitehouse

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: default avatarSteven Whitehouse <swhiteho@redhat.com>
Reported-by: default avatarDavid Booher <dbooher@adams.net>
parent 1ce53368
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/rculist_bl.h> #include <linux/rculist_bl.h>
#include <linux/completion.h>
#define DIO_WAIT 0x00000010 #define DIO_WAIT 0x00000010
#define DIO_METADATA 0x00000020 #define DIO_METADATA 0x00000020
...@@ -546,6 +547,7 @@ struct gfs2_sbd { ...@@ -546,6 +547,7 @@ struct gfs2_sbd {
struct gfs2_glock *sd_trans_gl; struct gfs2_glock *sd_trans_gl;
wait_queue_head_t sd_glock_wait; wait_queue_head_t sd_glock_wait;
atomic_t sd_glock_disposal; atomic_t sd_glock_disposal;
struct completion sd_locking_init;
/* Inode Stuff */ /* Inode Stuff */
......
...@@ -72,6 +72,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -72,6 +72,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
init_waitqueue_head(&sdp->sd_glock_wait); init_waitqueue_head(&sdp->sd_glock_wait);
atomic_set(&sdp->sd_glock_disposal, 0); atomic_set(&sdp->sd_glock_disposal, 0);
init_completion(&sdp->sd_locking_init);
spin_lock_init(&sdp->sd_statfs_spin); spin_lock_init(&sdp->sd_statfs_spin);
spin_lock_init(&sdp->sd_rindex_spin); spin_lock_init(&sdp->sd_rindex_spin);
...@@ -1017,11 +1018,13 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) ...@@ -1017,11 +1018,13 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
fsname++; fsname++;
if (lm->lm_mount == NULL) { if (lm->lm_mount == NULL) {
fs_info(sdp, "Now mounting FS...\n"); fs_info(sdp, "Now mounting FS...\n");
complete(&sdp->sd_locking_init);
return 0; return 0;
} }
ret = lm->lm_mount(sdp, fsname); ret = lm->lm_mount(sdp, fsname);
if (ret == 0) if (ret == 0)
fs_info(sdp, "Joined cluster. Now mounting FS...\n"); fs_info(sdp, "Joined cluster. Now mounting FS...\n");
complete(&sdp->sd_locking_init);
return ret; return ret;
} }
......
...@@ -338,6 +338,9 @@ static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len) ...@@ -338,6 +338,9 @@ static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
rv = sscanf(buf, "%u", &first); rv = sscanf(buf, "%u", &first);
if (rv != 1 || first > 1) if (rv != 1 || first > 1)
return -EINVAL; return -EINVAL;
rv = wait_for_completion_killable(&sdp->sd_locking_init);
if (rv)
return rv;
spin_lock(&sdp->sd_jindex_spin); spin_lock(&sdp->sd_jindex_spin);
rv = -EBUSY; rv = -EBUSY;
if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) 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,7 +417,9 @@ static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
rv = sscanf(buf, "%d", &jid); rv = sscanf(buf, "%d", &jid);
if (rv != 1) if (rv != 1)
return -EINVAL; return -EINVAL;
rv = wait_for_completion_killable(&sdp->sd_locking_init);
if (rv)
return rv;
spin_lock(&sdp->sd_jindex_spin); spin_lock(&sdp->sd_jindex_spin);
rv = -EINVAL; rv = -EINVAL;
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment