[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] GFS2: Allow all meta/normal mount combinations



This patch enables the mounting of a GFS2 filesystem both by
specifying a block device, and by specifying an inode on an
existing GFS2 filesystem.

The "meta" option is now supported as a per vfsmnt option, rather
than a per sb option. This means that it is now possible to mount
the GFS2 filesystem normally or with the meta flag and in any order
(meta mounts relative to normal mounts).

The userland tools don't currently allow this feature to work in
clustered mode (they can be updated to do so) but in the mean
time the feature is available for single node filesystems.

I've tested this with all the combinations I can think of, and they
appear to work correctly.

Signed-off-by: Steven Whitehouse <swhiteho redhat com>
Cc: Christoph Hellwig <hch infradead org>

diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 9da161c..ed1d997 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1267,12 +1267,6 @@ fail:
 	return error;
 }
 
-static int gfs2_get_sb(struct file_system_type *fs_type, int flags,
-		       const char *dev_name, void *data, struct vfsmount *mnt)
-{
-	return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt);
-}
-
 static int test_meta_super(struct super_block *s, void *ptr)
 {
 	struct block_device *bdev = ptr;
@@ -1294,7 +1288,7 @@ static struct super_block *get_gfs2_sb(const char *dev_name)
 	if (error) {
 		printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n",
 		       dev_name, error);
-		return ERR_PTR(-ENOENT);
+		return ERR_PTR(error);
 	}
 	s = sget(&gfs2_fs_type, test_meta_super, set_meta_super,
 		 path.dentry->d_inode->i_sb->s_bdev);
@@ -1302,6 +1296,53 @@ static struct super_block *get_gfs2_sb(const char *dev_name)
 	return s;
 }
 
+/**
+ * gfs2_is_meta_fs
+ * @options: The options to parse
+ *
+ * The meta option is per mnt not per sb
+ */
+
+static int gfs2_is_meta_fs(char *options)
+{
+	char *o;
+
+	while(1) {
+		o = strsep(&options, ",");
+		if (o == NULL)
+			break;
+		if (strcmp(o, "meta") == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int gfs2_get_sb(struct file_system_type *fs_type, int flags,
+		       const char *dev_name, void *data, struct vfsmount *mnt)
+{
+	struct super_block *s;
+	struct gfs2_sbd *sdp;
+	int ret;
+
+	/* First we assume its a block device */
+	ret = get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt);
+	if (ret != -ENOTBLK)
+		return ret;
+
+	/* If that fails, we assume its a GFS2 inode on an existing sb */
+	s = get_gfs2_sb(dev_name);
+	if (IS_ERR(s)) {
+		printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n");
+		return PTR_ERR(s);
+	}
+	sdp = s->s_fs_info;
+	mnt->mnt_sb = s;
+	mnt->mnt_root = gfs2_is_meta_fs(data) ? dget(sdp->sd_master_dir) :
+						dget(sdp->sd_root_dir);
+	return 0;
+}
+
 static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
 			    const char *dev_name, void *data, struct vfsmount *mnt)
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]