Commit 1b17a46c authored by Eric Sandeen's avatar Eric Sandeen Committed by Jan Kara
Browse files

isofs: convert isofs to use the new mount API



This also renames iso9660_options to isofs_options, for
consistency.

Signed-off-by: default avatarEric Sandeen <sandeen@redhat.com>
cc: Jan Kara <jack@suse.cz>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Message-Id: <409e28da-9c19-427a-acfb-78788f0a23b8@redhat.com>
parent 5a6cb47e
Loading
Loading
Loading
Loading
+240 −233
Original line number Diff line number Diff line
@@ -21,11 +21,12 @@
#include <linux/ctype.h>
#include <linux/statfs.h>
#include <linux/cdrom.h>
#include <linux/parser.h>
#include <linux/mpage.h>
#include <linux/user_namespace.h>
#include <linux/seq_file.h>
#include <linux/blkdev.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>

#include "isofs.h"
#include "zisofs.h"
@@ -110,10 +111,10 @@ static void destroy_inodecache(void)
	kmem_cache_destroy(isofs_inode_cachep);
}

static int isofs_remount(struct super_block *sb, int *flags, char *data)
static int isofs_reconfigure(struct fs_context *fc)
{
	sync_filesystem(sb);
	if (!(*flags & SB_RDONLY))
	sync_filesystem(fc->root->d_sb);
	if (!(fc->sb_flags & SB_RDONLY))
		return -EROFS;
	return 0;
}
@@ -123,7 +124,6 @@ static const struct super_operations isofs_sops = {
	.free_inode	= isofs_free_inode,
	.put_super	= isofs_put_super,
	.statfs		= isofs_statfs,
	.remount_fs	= isofs_remount,
	.show_options	= isofs_show_options,
};

@@ -145,7 +145,7 @@ static const struct dentry_operations isofs_dentry_ops[] = {
#endif
};

struct iso9660_options{
struct isofs_options{
	unsigned int rock:1;
	unsigned int joliet:1;
	unsigned int cruft:1;
@@ -289,88 +289,74 @@ isofs_dentry_cmpi_ms(const struct dentry *dentry,
#endif

enum {
	Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
	Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
	Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
	Opt_nocompress, Opt_hide, Opt_showassoc, Opt_dmode, Opt_overriderockperm,
	Opt_block, Opt_check, Opt_cruft, Opt_gid, Opt_ignore, Opt_iocharset,
	Opt_map, Opt_mode, Opt_nojoliet, Opt_norock, Opt_sb, Opt_session,
	Opt_uid, Opt_unhide, Opt_utf8, Opt_err, Opt_nocompress, Opt_hide,
	Opt_showassoc, Opt_dmode, Opt_overriderockperm,
};

static const match_table_t tokens = {
	{Opt_norock, "norock"},
	{Opt_nojoliet, "nojoliet"},
	{Opt_unhide, "unhide"},
	{Opt_hide, "hide"},
	{Opt_showassoc, "showassoc"},
	{Opt_cruft, "cruft"},
	{Opt_utf8, "utf8"},
	{Opt_iocharset, "iocharset=%s"},
	{Opt_map_a, "map=acorn"},
	{Opt_map_a, "map=a"},
	{Opt_map_n, "map=normal"},
	{Opt_map_n, "map=n"},
	{Opt_map_o, "map=off"},
	{Opt_map_o, "map=o"},
	{Opt_session, "session=%u"},
	{Opt_sb, "sbsector=%u"},
	{Opt_check_r, "check=relaxed"},
	{Opt_check_r, "check=r"},
	{Opt_check_s, "check=strict"},
	{Opt_check_s, "check=s"},
	{Opt_uid, "uid=%u"},
	{Opt_gid, "gid=%u"},
	{Opt_mode, "mode=%u"},
	{Opt_dmode, "dmode=%u"},
	{Opt_overriderockperm, "overriderockperm"},
	{Opt_block, "block=%u"},
	{Opt_ignore, "conv=binary"},
	{Opt_ignore, "conv=b"},
	{Opt_ignore, "conv=text"},
	{Opt_ignore, "conv=t"},
	{Opt_ignore, "conv=mtext"},
	{Opt_ignore, "conv=m"},
	{Opt_ignore, "conv=auto"},
	{Opt_ignore, "conv=a"},
	{Opt_nocompress, "nocompress"},
	{Opt_err, NULL}
static const struct constant_table isofs_param_map[] = {
	{"acorn",	'a'},
	{"a",		'a'},
	{"normal",	'n'},
	{"n",		'n'},
	{"off",		'o'},
	{"o",		'o'},
	{}
};

static int parse_options(char *options, struct iso9660_options *popt)
static const struct constant_table isofs_param_check[] = {
	{"relaxed",	'r'},
	{"r",		'r'},
	{"strict",	's'},
	{"s",		's'},
	{}
};

static const struct fs_parameter_spec isofs_param_spec[] = {
	fsparam_flag	("norock",		Opt_norock),
	fsparam_flag	("nojoliet",		Opt_nojoliet),
	fsparam_flag	("unhide",		Opt_unhide),
	fsparam_flag	("hide",		Opt_hide),
	fsparam_flag	("showassoc",		Opt_showassoc),
	fsparam_flag	("cruft",		Opt_cruft),
	fsparam_flag	("utf8",		Opt_utf8),
	fsparam_string	("iocharset",		Opt_iocharset),
	fsparam_enum	("map",			Opt_map, isofs_param_map),
	fsparam_u32	("session",		Opt_session),
	fsparam_u32	("sbsector",		Opt_sb),
	fsparam_enum	("check",		Opt_check, isofs_param_check),
	fsparam_u32	("uid",			Opt_uid),
	fsparam_u32	("gid",			Opt_gid),
	/* Note: mode/dmode historically accepted %u not strictly %o */
	fsparam_u32	("mode",		Opt_mode),
	fsparam_u32	("dmode",		Opt_dmode),
	fsparam_flag	("overriderockperm",	Opt_overriderockperm),
	fsparam_u32	("block",		Opt_block),
	fsparam_string	("conv",		Opt_ignore),
	fsparam_flag	("nocompress",		Opt_nocompress),
	{}
};

static int isofs_parse_param(struct fs_context *fc,
			       struct fs_parameter *param)
{
	char *p;
	int option;
	unsigned int uv;

	popt->map = 'n';
	popt->rock = 1;
	popt->joliet = 1;
	popt->cruft = 0;
	popt->hide = 0;
	popt->showassoc = 0;
	popt->check = 'u';		/* unset */
	popt->nocompress = 0;
	popt->blocksize = 1024;
	popt->fmode = popt->dmode = ISOFS_INVALID_MODE;
	popt->uid_set = 0;
	popt->gid_set = 0;
	popt->gid = GLOBAL_ROOT_GID;
	popt->uid = GLOBAL_ROOT_UID;
	popt->iocharset = NULL;
	popt->overriderockperm = 0;
	popt->session=-1;
	popt->sbsector=-1;
	if (!options)
		return 1;
	struct isofs_options *popt = fc->fs_private;
	struct fs_parse_result result;
	int opt;
	kuid_t uid;
	kgid_t gid;
	unsigned int n;

	while ((p = strsep(&options, ",")) != NULL) {
		int token;
		substring_t args[MAX_OPT_ARGS];
		unsigned n;
	/* There are no remountable options */
	if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
		return 0;

		if (!*p)
			continue;
	opt = fs_parse(fc, isofs_param_spec, param, &result);
	if (opt < 0)
		return opt;

		token = match_token(p, tokens, args);
		switch (token) {
	switch (opt) {
	case Opt_norock:
		popt->rock = 0;
		break;
@@ -392,94 +378,72 @@ static int parse_options(char *options, struct iso9660_options *popt)
		kfree(popt->iocharset);
		popt->iocharset = kstrdup("utf8", GFP_KERNEL);
		if (!popt->iocharset)
				return 0;
			return -ENOMEM;
		break;
	case Opt_iocharset:
		kfree(popt->iocharset);
			popt->iocharset = match_strdup(&args[0]);
		popt->iocharset = kstrdup(param->string, GFP_KERNEL);
		if (!popt->iocharset)
				return 0;
			return -ENOMEM;
		break;
#endif
		case Opt_map_a:
			popt->map = 'a';
			break;
		case Opt_map_o:
			popt->map = 'o';
			break;
		case Opt_map_n:
			popt->map = 'n';
	case Opt_map:
		popt->map = result.uint_32;
		break;
	case Opt_session:
			if (match_int(&args[0], &option))
				return 0;
			n = option;
		n = result.uint_32;
		/*
		 * Track numbers are supposed to be in range 1-99, the
		 * mount option starts indexing at 0.
		 */
		if (n >= 99)
				return 0;
			return -EINVAL;
		popt->session = n + 1;
		break;
	case Opt_sb:
			if (match_int(&args[0], &option))
				return 0;
			popt->sbsector = option;
		popt->sbsector = result.uint_32;
		break;
		case Opt_check_r:
			popt->check = 'r';
			break;
		case Opt_check_s:
			popt->check = 's';
	case Opt_check:
		popt->check = result.uint_32;
		break;
	case Opt_ignore:
		break;
	case Opt_uid:
			if (match_uint(&args[0], &uv))
				return 0;
			popt->uid = make_kuid(current_user_ns(), uv);
			if (!uid_valid(popt->uid))
				return 0;
		uid = make_kuid(current_user_ns(), result.uint_32);
		if (!uid_valid(uid))
			return -EINVAL;
		popt->uid = uid;
		popt->uid_set = 1;
		break;
	case Opt_gid:
			if (match_uint(&args[0], &uv))
				return 0;
			popt->gid = make_kgid(current_user_ns(), uv);
			if (!gid_valid(popt->gid))
				return 0;
		gid = make_kgid(current_user_ns(), result.uint_32);
		if (!gid_valid(gid))
			return -EINVAL;
		popt->gid = gid;
		popt->gid_set = 1;
		break;
	case Opt_mode:
			if (match_int(&args[0], &option))
				return 0;
			popt->fmode = option;
		popt->fmode = result.uint_32;
		break;
	case Opt_dmode:
			if (match_int(&args[0], &option))
				return 0;
			popt->dmode = option;
		popt->dmode = result.uint_32;
		break;
	case Opt_overriderockperm:
		popt->overriderockperm = 1;
		break;
	case Opt_block:
			if (match_int(&args[0], &option))
				return 0;
			n = option;
		n = result.uint_32;
		if (n != 512 && n != 1024 && n != 2048)
				return 0;
			return -EINVAL;
		popt->blocksize = n;
		break;
	case Opt_nocompress:
		popt->nocompress = 1;
		break;
	default:
			return 0;
		}
		return -EINVAL;
	}
	return 1;
	return 0;
}

/*
@@ -615,7 +579,7 @@ static bool rootdir_empty(struct super_block *sb, unsigned long block)
/*
 * Initialize the superblock and read the root inode.
 */
static int isofs_fill_super(struct super_block *s, void *data, int silent)
static int isofs_fill_super(struct super_block *s, struct fs_context *fc)
{
	struct buffer_head *bh = NULL, *pri_bh = NULL;
	struct hs_primary_descriptor *h_pri = NULL;
@@ -623,7 +587,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
	struct iso_supplementary_descriptor *sec = NULL;
	struct iso_directory_record *rootp;
	struct inode *inode;
	struct iso9660_options opt;
	struct isofs_options *opt = fc->fs_private;
	struct isofs_sb_info *sbi;
	unsigned long first_data_zone;
	int joliet_level = 0;
@@ -631,15 +595,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
	int orig_zonesize;
	int table, error = -EINVAL;
	unsigned int vol_desc_start;
	int silent = fc->sb_flags & SB_SILENT;

	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	s->s_fs_info = sbi;

	if (!parse_options((char *)data, &opt))
		goto out_freesbi;

	/*
	 * First of all, get the hardware blocksize for this device.
	 * If we don't know what it is, or the hardware blocksize is
@@ -655,14 +617,14 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
			bdev_logical_block_size(s->s_bdev));
		goto out_freesbi;
	}
	opt.blocksize = sb_min_blocksize(s, opt.blocksize);
	opt->blocksize = sb_min_blocksize(s, opt->blocksize);

	sbi->s_high_sierra = 0; /* default is iso9660 */
	sbi->s_session = opt.session;
	sbi->s_sbsector = opt.sbsector;
	sbi->s_session = opt->session;
	sbi->s_sbsector = opt->sbsector;

	vol_desc_start = (opt.sbsector != -1) ?
		opt.sbsector : isofs_get_last_session(s,opt.session);
	vol_desc_start = (opt->sbsector != -1) ?
		opt->sbsector : isofs_get_last_session(s, opt->session);

	for (iso_blknum = vol_desc_start+16;
		iso_blknum < vol_desc_start+100; iso_blknum++) {
@@ -696,7 +658,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
			else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
				sec = (struct iso_supplementary_descriptor *)vdp;
				if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
					if (opt.joliet) {
					if (opt->joliet) {
						if (sec->escape[2] == 0x40)
							joliet_level = 1;
						else if (sec->escape[2] == 0x43)
@@ -721,7 +683,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
					goto out_freebh;

				sbi->s_high_sierra = 1;
				opt.rock = 0;
				opt->rock = 0;
				h_pri = (struct hs_primary_descriptor *)vdp;
				goto root_found;
			}
@@ -749,7 +711,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
		goto out_freebh;
	}

	if (joliet_level && (!pri || !opt.rock)) {
	if (joliet_level && (!pri || !opt->rock)) {
		/* This is the case of Joliet with the norock mount flag.
		 * A disc with both Joliet and Rock Ridge is handled later
		 */
@@ -780,7 +742,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
	 * blocks that were 512 bytes (which should only very rarely
	 * happen.)
	 */
	if (orig_zonesize < opt.blocksize)
	if (orig_zonesize < opt->blocksize)
		goto out_bad_size;

	/* RDE: convert log zone size to bit shift */
@@ -865,10 +827,10 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)

#ifdef CONFIG_JOLIET
	if (joliet_level) {
		char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
		char *p = opt->iocharset ? opt->iocharset : CONFIG_NLS_DEFAULT;
		if (strcmp(p, "utf8") != 0) {
			sbi->s_nls_iocharset = opt.iocharset ?
				load_nls(opt.iocharset) : load_nls_default();
			sbi->s_nls_iocharset = opt->iocharset ?
				load_nls(opt->iocharset) : load_nls_default();
			if (!sbi->s_nls_iocharset)
				goto out_freesbi;
		}
@@ -876,29 +838,29 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
#endif
	s->s_op = &isofs_sops;
	s->s_export_op = &isofs_export_ops;
	sbi->s_mapping = opt.map;
	sbi->s_rock = (opt.rock ? 2 : 0);
	sbi->s_mapping = opt->map;
	sbi->s_rock = (opt->rock ? 2 : 0);
	sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
	sbi->s_cruft = opt.cruft;
	sbi->s_hide = opt.hide;
	sbi->s_showassoc = opt.showassoc;
	sbi->s_uid = opt.uid;
	sbi->s_gid = opt.gid;
	sbi->s_uid_set = opt.uid_set;
	sbi->s_gid_set = opt.gid_set;
	sbi->s_nocompress = opt.nocompress;
	sbi->s_overriderockperm = opt.overriderockperm;
	sbi->s_cruft = opt->cruft;
	sbi->s_hide = opt->hide;
	sbi->s_showassoc = opt->showassoc;
	sbi->s_uid = opt->uid;
	sbi->s_gid = opt->gid;
	sbi->s_uid_set = opt->uid_set;
	sbi->s_gid_set = opt->gid_set;
	sbi->s_nocompress = opt->nocompress;
	sbi->s_overriderockperm = opt->overriderockperm;
	/*
	 * It would be incredibly stupid to allow people to mark every file
	 * on the disk as suid, so we merely allow them to set the default
	 * permissions.
	 */
	if (opt.fmode != ISOFS_INVALID_MODE)
		sbi->s_fmode = opt.fmode & 0777;
	if (opt->fmode != ISOFS_INVALID_MODE)
		sbi->s_fmode = opt->fmode & 0777;
	else
		sbi->s_fmode = ISOFS_INVALID_MODE;
	if (opt.dmode != ISOFS_INVALID_MODE)
		sbi->s_dmode = opt.dmode & 0777;
	if (opt->dmode != ISOFS_INVALID_MODE)
		sbi->s_dmode = opt->dmode & 0777;
	else
		sbi->s_dmode = ISOFS_INVALID_MODE;

@@ -960,12 +922,12 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
		}
	}

	if (opt.check == 'u') {
	if (opt->check == 'u') {
		/* Only Joliet is case insensitive by default */
		if (joliet_level)
			opt.check = 'r';
			opt->check = 'r';
		else
			opt.check = 's';
			opt->check = 's';
	}
	sbi->s_joliet_level = joliet_level;

@@ -980,9 +942,9 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
	table = 0;
	if (joliet_level)
		table += 2;
	if (opt.check == 'r')
	if (opt->check == 'r')
		table++;
	sbi->s_check = opt.check;
	sbi->s_check = opt->check;

	if (table)
		s->s_d_op = &isofs_dentry_ops[table - 1];
@@ -994,7 +956,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
		goto out_no_inode;
	}

	kfree(opt.iocharset);
	kfree(opt->iocharset);

	return 0;

@@ -1023,7 +985,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
	goto out_freebh;
out_bad_size:
	printk(KERN_WARNING "ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n",
		orig_zonesize, opt.blocksize);
		orig_zonesize, opt->blocksize);
	goto out_freebh;
out_unknown_format:
	if (!silent)
@@ -1033,7 +995,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
	brelse(bh);
	brelse(pri_bh);
out_freesbi:
	kfree(opt.iocharset);
	kfree(opt->iocharset);
	kfree(sbi);
	s->s_fs_info = NULL;
	return error;
@@ -1567,18 +1529,63 @@ struct inode *__isofs_iget(struct super_block *sb,
	return inode;
}

static struct dentry *isofs_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
static int isofs_get_tree(struct fs_context *fc)
{
	return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
	return get_tree_bdev(fc, isofs_fill_super);
}

static void isofs_free_fc(struct fs_context *fc)
{
	kfree(fc->fs_private);
}

static const struct fs_context_operations isofs_context_ops = {
	.parse_param	= isofs_parse_param,
	.get_tree	= isofs_get_tree,
	.reconfigure	= isofs_reconfigure,
	.free		= isofs_free_fc,
};

static int isofs_init_fs_context(struct fs_context *fc)
{
	struct isofs_options *opt;

	opt = kzalloc(sizeof(*opt), GFP_KERNEL);
	if (!opt)
		return -ENOMEM;

	opt->map = 'n';
	opt->rock = 1;
	opt->joliet = 1;
	opt->cruft = 0;
	opt->hide = 0;
	opt->showassoc = 0;
	opt->check = 'u';		/* unset */
	opt->nocompress = 0;
	opt->blocksize = 1024;
	opt->fmode = opt->dmode = ISOFS_INVALID_MODE;
	opt->uid_set = 0;
	opt->gid_set = 0;
	opt->gid = GLOBAL_ROOT_GID;
	opt->uid = GLOBAL_ROOT_UID;
	opt->iocharset = NULL;
	opt->overriderockperm = 0;
	opt->session = -1;
	opt->sbsector = -1;

	fc->fs_private = opt;
	fc->ops = &isofs_context_ops;

	return 0;
}

static struct file_system_type iso9660_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "iso9660",
	.mount		= isofs_mount,
	.kill_sb	= kill_block_super,
	.fs_flags	= FS_REQUIRES_DEV,
	.init_fs_context = isofs_init_fs_context,
	.parameters	= isofs_param_spec,
};
MODULE_ALIAS_FS("iso9660");
MODULE_ALIAS("iso9660");