Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b8df98f authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

GFS2: Fix metafs mounts



This patch is intended to fix the issues reported in bz #457798. Instead
of having the metafs as a separate filesystem, it becomes a second root
of gfs2. As a result it will appear as type gfs2 in /proc/mounts, but it
is still possible (for backwards compatibility purposes) to mount it as
type gfs2meta. A new mount flag "meta" is introduced so that its possible
to tell the two cases apart in /proc/mounts.

As a result it becomes possible to mount type gfs2 with -o meta and
get the same result as mounting type gfs2meta. So it is possible to
mount just the metafs on its own. Currently if you do this, its then
impossible to mount the "normal" root of the gfs2 filesystem without
first unmounting the metafs root. I'm not sure if thats a feature or
a bug :-)

Either way, this is a great improvement on the previous scheme and I've
verified that it works ok with bind mounts on both the "normal" root
and the metafs root in various combinations.

There were also a bunch of functions in super.c which didn't belong there,
so this moves them into ops_fstype.c where they can be static. Hopefully
the mount/umount sequence is now more obvious as a result.

Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
Cc: Alexander Viro <aviro@redhat.com>
parent c1e817d0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -400,6 +400,7 @@ struct gfs2_args {
	int ar_quota; /* off/account/on */
	int ar_suiddir; /* suiddir support */
	int ar_data; /* ordered/writeback */
	int ar_meta; /* mount metafs */
};

struct gfs2_tune {
@@ -461,7 +462,6 @@ struct gfs2_sb_host {

struct gfs2_sbd {
	struct super_block *sd_vfs;
	struct super_block *sd_vfs_meta;
	struct kobject sd_kobj;
	unsigned long sd_flags;	/* SDF_... */
	struct gfs2_sb_host sd_sb;
@@ -499,7 +499,9 @@ struct gfs2_sbd {

	/* Inode Stuff */

	struct inode *sd_master_dir;
	struct dentry *sd_master_dir;
	struct dentry *sd_root_dir;

	struct inode *sd_jindex;
	struct inode *sd_inum_inode;
	struct inode *sd_statfs_inode;
@@ -634,7 +636,6 @@ struct gfs2_sbd {
	/* Debugging crud */

	unsigned long sd_last_warning;
	struct vfsmount *sd_gfs2mnt;
	struct dentry *debugfs_dir;    /* debugfs directory */
	struct dentry *debugfs_dentry_glocks; /* for debugfs */
};
+7 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ enum {
	Opt_nosuiddir,
	Opt_data_writeback,
	Opt_data_ordered,
	Opt_meta,
	Opt_err,
};

@@ -66,6 +67,7 @@ static match_table_t tokens = {
	{Opt_nosuiddir, "nosuiddir"},
	{Opt_data_writeback, "data=writeback"},
	{Opt_data_ordered, "data=ordered"},
	{Opt_meta, "meta"},
	{Opt_err, NULL}
};

@@ -239,6 +241,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
		case Opt_data_ordered:
			args->ar_data = GFS2_DATA_ORDERED;
			break;
		case Opt_meta:
			if (remount && args->ar_meta != 1)
				goto cant_remount;
			args->ar_meta = 1;
			break;
		case Opt_err:
		default:
			fs_info(sdp, "unknown option: %s\n", o);
+389 −177

File changed.

Preview size limit exceeded, changes collapsed.

+48 −9
Original line number Diff line number Diff line
@@ -62,6 +62,39 @@ static int gfs2_write_inode(struct inode *inode, int sync)
	return 0;
}

/**
 * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one
 * @sdp: the filesystem
 *
 * Returns: errno
 */

static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
{
	struct gfs2_holder t_gh;
	int error;

	gfs2_quota_sync(sdp);
	gfs2_statfs_sync(sdp);

	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
				   &t_gh);
	if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
		return error;

	gfs2_meta_syncfs(sdp);
	gfs2_log_shutdown(sdp);

	clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);

	if (t_gh.gh_gl)
		gfs2_glock_dq_uninit(&t_gh);

	gfs2_quota_cleanup(sdp);

	return error;
}

/**
 * gfs2_put_super - Unmount the filesystem
 * @sb: The VFS superblock
@@ -73,12 +106,6 @@ static void gfs2_put_super(struct super_block *sb)
	struct gfs2_sbd *sdp = sb->s_fs_info;
	int error;

	if (!sdp)
		return;

	if (!strncmp(sb->s_type->name, "gfs2meta", 8))
		return; /* Nothing to do */

	/*  Unfreeze the filesystem, if we need to  */

	mutex_lock(&sdp->sd_freeze_lock);
@@ -101,7 +128,6 @@ static void gfs2_put_super(struct super_block *sb)

	/*  Release stuff  */

	iput(sdp->sd_master_dir);
	iput(sdp->sd_jindex);
	iput(sdp->sd_inum_inode);
	iput(sdp->sd_statfs_inode);
@@ -152,6 +178,7 @@ static void gfs2_write_super(struct super_block *sb)
 *
 * Flushes the log to disk.
 */

static int gfs2_sync_fs(struct super_block *sb, int wait)
{
	sb->s_dirt = 0;
@@ -295,6 +322,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
 * inode's blocks, or alternatively pass the baton on to another
 * node for later deallocation.
 */

static void gfs2_drop_inode(struct inode *inode)
{
	struct gfs2_inode *ip = GFS2_I(inode);
@@ -333,6 +361,16 @@ static void gfs2_clear_inode(struct inode *inode)
	}
}

static int is_ancestor(const struct dentry *d1, const struct dentry *d2)
{
	do {
		if (d1 == d2)
			return 1;
		d1 = d1->d_parent;
	} while (!IS_ROOT(d1));
	return 0;
}

/**
 * gfs2_show_options - Show mount options for /proc/mounts
 * @s: seq_file structure
@@ -346,6 +384,8 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
	struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info;
	struct gfs2_args *args = &sdp->sd_args;

	if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir))
		seq_printf(s, ",meta");
	if (args->ar_lockproto[0])
		seq_printf(s, ",lockproto=%s", args->ar_lockproto);
	if (args->ar_locktable[0])
@@ -414,6 +454,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
 * conversion on the iopen lock, but we can change that later. This
 * is safe, just less efficient.
 */

static void gfs2_delete_inode(struct inode *inode)
{
	struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
@@ -478,8 +519,6 @@ static void gfs2_delete_inode(struct inode *inode)
	clear_inode(inode);
}



static struct inode *gfs2_alloc_inode(struct super_block *sb)
{
	struct gfs2_inode *ip;
+0 −340

File changed.

Preview size limit exceeded, changes collapsed.

Loading