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

Commit d4076ac5 authored by Sukadev Bhattiprolu's avatar Sukadev Bhattiprolu Committed by Linus Torvalds
Browse files

Define get_init_pts_sb()



See comments in the function header for details. The new interface will
be used in a follow-on patch.

Changelog [v2]:
	[Dave Hansen] Replace get_sb_ref() in fs/super.c with get_init_pts_sb()
	and make the new interface private to devpts

Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1f8f1e29
Loading
Loading
Loading
Loading
+54 −1
Original line number Diff line number Diff line
@@ -305,10 +305,63 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
	return -ENOMEM;
}

static int compare_init_pts_sb(struct super_block *s, void *p)
{
	if (devpts_mnt)
		return devpts_mnt->mnt_sb == s;

	return 0;
}

/*
 * get_init_pts_sb()
 *
 *     This interface is needed to support multiple namespace semantics in
 *     devpts while preserving backward compatibility of the current 'single-
 *     namespace' semantics. i.e all mounts of devpts without the 'newinstance'
 *     mount option should bind to the initial kernel mount, like
 *     get_sb_single().
 *
 *     Mounts with 'newinstance' option create a new private namespace.
 *
 *     But for single-mount semantics, devpts cannot use get_sb_single(),
 *     because get_sb_single()/sget() find and use the super-block from
 *     the most recent mount of devpts. But that recent mount may be a
 *     'newinstance' mount and get_sb_single() would pick the newinstance
 *     super-block instead of the initial super-block.
 *
 *     This interface is identical to get_sb_single() except that it
 *     consistently selects the 'single-namespace' superblock even in the
 *     presence of the private namespace (i.e 'newinstance') super-blocks.
 */
static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
		void *data, struct vfsmount *mnt)
{
        struct super_block *s;
        int error;

        s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);
        if (IS_ERR(s))
                return PTR_ERR(s);

        if (!s->s_root) {
                s->s_flags = flags;
                error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
                if (error) {
                        up_write(&s->s_umount);
                        deactivate_super(s);
                        return error;
                }
                s->s_flags |= MS_ACTIVE;
        }
        do_remount_sb(s, flags, data, 0);
        return simple_set_mnt(mnt, s);
}

static int devpts_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
	return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
	return get_init_pts_sb(fs_type, flags, data, mnt);
}

static void devpts_kill_sb(struct super_block *sb)