diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2009-06-05 02:18:57 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2009-06-05 03:35:15 -0400 |
commit | f6d03139d745198b434f65a28aabed524f415a4c (patch) | |
tree | e308567651c18954de9acd0fa8a359221680d3c1 /fs/gfs2 | |
parent | e09f9446b94ac64b27d37e98c1110f29d712cdad (diff) |
GFS2: Fix locking issue mounting gfs2meta fs
This patch uses sget() to get a reference to the
existing gfs2 sb when mouting the gfs2meta filesystem
(in fact thats just another mount of the gfs2
filesystem with a different root and this interface
is for backward compatibility).
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Reported-by: Benjamin Marzinski <bmarzins@redhat.com>
Tested-by: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/ops_fstype.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 2cd1164c88d7..9da161cbb30f 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -1273,9 +1273,20 @@ static int gfs2_get_sb(struct file_system_type *fs_type, int flags, | |||
1273 | return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); | 1273 | return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | static int test_meta_super(struct super_block *s, void *ptr) | ||
1277 | { | ||
1278 | struct block_device *bdev = ptr; | ||
1279 | return (bdev == s->s_bdev); | ||
1280 | } | ||
1281 | |||
1282 | static int set_meta_super(struct super_block *s, void *ptr) | ||
1283 | { | ||
1284 | return -EINVAL; | ||
1285 | } | ||
1286 | |||
1276 | static struct super_block *get_gfs2_sb(const char *dev_name) | 1287 | static struct super_block *get_gfs2_sb(const char *dev_name) |
1277 | { | 1288 | { |
1278 | struct super_block *sb; | 1289 | struct super_block *s; |
1279 | struct path path; | 1290 | struct path path; |
1280 | int error; | 1291 | int error; |
1281 | 1292 | ||
@@ -1283,30 +1294,27 @@ static struct super_block *get_gfs2_sb(const char *dev_name) | |||
1283 | if (error) { | 1294 | if (error) { |
1284 | printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", | 1295 | printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", |
1285 | dev_name, error); | 1296 | dev_name, error); |
1286 | return NULL; | 1297 | return ERR_PTR(-ENOENT); |
1287 | } | 1298 | } |
1288 | sb = path.dentry->d_inode->i_sb; | 1299 | s = sget(&gfs2_fs_type, test_meta_super, set_meta_super, |
1289 | if (sb && (sb->s_type == &gfs2_fs_type)) | 1300 | path.dentry->d_inode->i_sb->s_bdev); |
1290 | atomic_inc(&sb->s_active); | ||
1291 | else | ||
1292 | sb = NULL; | ||
1293 | path_put(&path); | 1301 | path_put(&path); |
1294 | return sb; | 1302 | return s; |
1295 | } | 1303 | } |
1296 | 1304 | ||
1297 | static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, | 1305 | static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, |
1298 | const char *dev_name, void *data, struct vfsmount *mnt) | 1306 | const char *dev_name, void *data, struct vfsmount *mnt) |
1299 | { | 1307 | { |
1300 | struct super_block *sb = NULL; | 1308 | struct super_block *s; |
1301 | struct gfs2_sbd *sdp; | 1309 | struct gfs2_sbd *sdp; |
1302 | 1310 | ||
1303 | sb = get_gfs2_sb(dev_name); | 1311 | s = get_gfs2_sb(dev_name); |
1304 | if (!sb) { | 1312 | if (IS_ERR(s)) { |
1305 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); | 1313 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); |
1306 | return -ENOENT; | 1314 | return PTR_ERR(s); |
1307 | } | 1315 | } |
1308 | sdp = sb->s_fs_info; | 1316 | sdp = s->s_fs_info; |
1309 | mnt->mnt_sb = sb; | 1317 | mnt->mnt_sb = s; |
1310 | mnt->mnt_root = dget(sdp->sd_master_dir); | 1318 | mnt->mnt_root = dget(sdp->sd_master_dir); |
1311 | return 0; | 1319 | return 0; |
1312 | } | 1320 | } |