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

Commit 8246a781 authored by Daniel Rosenberg's avatar Daniel Rosenberg
Browse files

ANDROID: sdcardfs: Add gid and mask to private mount data



Adds support for mount2, remount2, and the functions
to allocate/clone/copy the private data

The next patch will switch over to actually using it.

Change-Id: I8a43da26021d33401f655f0b2784ead161c575e3
Signed-off-by: default avatarDaniel Rosenberg <drosen@google.com>
parent b6045659
Loading
Loading
Loading
Loading
+91 −12
Original line number Diff line number Diff line
@@ -49,7 +49,8 @@ static const match_table_t sdcardfs_tokens = {
};

static int parse_options(struct super_block *sb, char *options, int silent,
				int *debug, struct sdcardfs_mount_options *opts)
				int *debug, struct sdcardfs_vfsmount_options *vfsopts,
				struct sdcardfs_mount_options *opts)
{
	char *p;
	substring_t args[MAX_OPT_ARGS];
@@ -58,9 +59,11 @@ static int parse_options(struct super_block *sb, char *options, int silent,
	/* by default, we use AID_MEDIA_RW as uid, gid */
	opts->fs_low_uid = AID_MEDIA_RW;
	opts->fs_low_gid = AID_MEDIA_RW;
	vfsopts->mask = 0;
	opts->mask = 0;
	opts->multiuser = false;
	opts->fs_user_id = 0;
	vfsopts->gid = 0;
	opts->gid = 0;
	/* by default, 0MB is reserved */
	opts->reserved_mb = 0;
@@ -95,6 +98,7 @@ static int parse_options(struct super_block *sb, char *options, int silent,
			if (match_int(&args[0], &option))
				return 0;
			opts->gid = option;
			vfsopts->gid = option;
			break;
		case Opt_userid:
			if (match_int(&args[0], &option))
@@ -105,6 +109,7 @@ static int parse_options(struct super_block *sb, char *options, int silent,
			if (match_int(&args[0], &option))
				return 0;
			opts->mask = option;
			vfsopts->mask = option;
			break;
		case Opt_multiuser:
			opts->multiuser = true;
@@ -135,6 +140,65 @@ static int parse_options(struct super_block *sb, char *options, int silent,
	return 0;
}

int parse_options_remount(struct super_block *sb, char *options, int silent,
				struct sdcardfs_vfsmount_options *vfsopts)
{
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;
	int debug;

	if (!options)
		return 0;

	while ((p = strsep(&options, ",")) != NULL) {
		int token;
		if (!*p)
			continue;

		token = match_token(p, sdcardfs_tokens, args);

		switch (token) {
		case Opt_debug:
			debug = 1;
			break;
		case Opt_gid:
			if (match_int(&args[0], &option))
				return 0;
			vfsopts->gid = option;

			break;
		case Opt_mask:
			if (match_int(&args[0], &option))
				return 0;
			vfsopts->mask = option;
			break;
		case Opt_multiuser:
		case Opt_userid:
		case Opt_fsuid:
		case Opt_fsgid:
		case Opt_reserved_mb:
			printk( KERN_WARNING "Option \"%s\" can't be changed during remount\n", p);
			break;
		/* unknown option */
		default:
			if (!silent) {
				printk( KERN_ERR "Unrecognized mount option \"%s\" "
						"or missing value", p);
			}
			return -EINVAL;
		}
	}

	if (debug) {
		printk( KERN_INFO "sdcardfs : options - debug:%d\n", debug);
		printk( KERN_INFO "sdcardfs : options - gid:%d\n", vfsopts->gid);
		printk( KERN_INFO "sdcardfs : options - mask:%d\n", vfsopts->mask);
	}

	return 0;
}

#if 0
/*
 * our custom d_alloc_root work-alike
@@ -172,14 +236,15 @@ EXPORT_SYMBOL_GPL(sdcardfs_super_list);
 * There is no need to lock the sdcardfs_super_info's rwsem as there is no
 * way anyone can have a reference to the superblock at this point in time.
 */
static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
						void *raw_data, int silent)
static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb,
		const char *dev_name, void *raw_data, int silent)
{
	int err = 0;
	int debug;
	struct super_block *lower_sb;
	struct path lower_path;
	struct sdcardfs_sb_info *sb_info;
	struct sdcardfs_vfsmount_options *mnt_opt = mnt->data;
	struct inode *inode;

	printk(KERN_INFO "sdcardfs version 2.0\n");
@@ -212,7 +277,7 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,

	sb_info = sb->s_fs_info;
	/* parse options */
	err = parse_options(sb, raw_data, silent, &debug, &sb_info->options);
	err = parse_options(sb, raw_data, silent, &debug, mnt_opt, &sb_info->options);
	if (err) {
		printk(KERN_ERR	"sdcardfs: invalid options\n");
		goto out_freesbi;
@@ -306,9 +371,9 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
}

/* A feature which supports mount_nodev() with options */
static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data,
        int (*fill_super)(struct super_block *, const char *, void *, int))
static struct dentry *mount_nodev_with_options(struct vfsmount *mnt,
	struct file_system_type *fs_type, int flags, const char *dev_name, void *data,
        int (*fill_super)(struct vfsmount *, struct super_block *, const char *, void *, int))

{
	int error;
@@ -319,7 +384,7 @@ static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type,

	s->s_flags = flags;

	error = fill_super(s, dev_name, data, flags & MS_SILENT ? 1 : 0);
	error = fill_super(mnt, s, dev_name, data, flags & MS_SILENT ? 1 : 0);
	if (error) {
		deactivate_locked_super(s);
		return ERR_PTR(error);
@@ -328,17 +393,29 @@ static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type,
	return dget(s->s_root);
}

struct dentry *sdcardfs_mount(struct file_system_type *fs_type, int flags,
static struct dentry *sdcardfs_mount(struct vfsmount *mnt,
		struct file_system_type *fs_type, int flags,
			    const char *dev_name, void *raw_data)
{
	/*
	 * dev_name is a lower_path_name,
	 * raw_data is a option string.
	 */
	return mount_nodev_with_options(fs_type, flags, dev_name,
	return mount_nodev_with_options(mnt, fs_type, flags, dev_name,
						raw_data, sdcardfs_read_super);
}

static struct dentry *sdcardfs_mount_wrn(struct file_system_type *fs_type, int flags,
		    const char *dev_name, void *raw_data)
{
	WARN(1, "sdcardfs does not support mount. Use mount2.\n");
	return ERR_PTR(-EINVAL);
}

void *sdcardfs_alloc_mnt_data(void) {
	return kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
}

void sdcardfs_kill_sb(struct super_block *sb) {
	struct sdcardfs_sb_info *sbi;
	if (sb->s_magic == SDCARDFS_SUPER_MAGIC) {
@@ -353,7 +430,9 @@ void sdcardfs_kill_sb(struct super_block *sb) {
static struct file_system_type sdcardfs_fs_type = {
	.owner		= THIS_MODULE,
	.name		= SDCARDFS_NAME,
	.mount		= sdcardfs_mount,
	.mount		= sdcardfs_mount_wrn,
	.mount2		= sdcardfs_mount,
	.alloc_mnt_data = sdcardfs_alloc_mnt_data,
	.kill_sb	= sdcardfs_kill_sb,
	.fs_flags	= 0,
};
+8 −0
Original line number Diff line number Diff line
@@ -193,6 +193,14 @@ struct sdcardfs_mount_options {
	unsigned int reserved_mb;
};

struct sdcardfs_vfsmount_options {
	gid_t gid;
	mode_t mask;
};

extern int parse_options_remount(struct super_block *sb, char *options, int silent,
		struct sdcardfs_vfsmount_options *vfsopts);

/* sdcardfs super-block data in memory */
struct sdcardfs_sb_info {
	struct super_block *sb;
+58 −6
Original line number Diff line number Diff line
@@ -108,6 +108,50 @@ static int sdcardfs_remount_fs(struct super_block *sb, int *flags, char *options
	return err;
}

/*
 * @mnt: mount point we are remounting
 * @sb: superblock we are remounting
 * @flags: numeric mount options
 * @options: mount options string
 */
static int sdcardfs_remount_fs2(struct vfsmount *mnt, struct super_block *sb,
						int *flags, char *options)
{
	int err = 0;

	/*
	 * The VFS will take care of "ro" and "rw" flags among others.  We
	 * can safely accept a few flags (RDONLY, MANDLOCK), and honor
	 * SILENT, but anything else left over is an error.
	 */
	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT | MS_REMOUNT)) != 0) {
		printk(KERN_ERR
		       "sdcardfs: remount flags 0x%x unsupported\n", *flags);
		err = -EINVAL;
	}
	printk(KERN_INFO "Remount options were %s for vfsmnt %p.\n", options, mnt);
	err = parse_options_remount(sb, options, *flags & ~MS_SILENT, mnt->data);


	return err;
}

static void* sdcardfs_clone_mnt_data(void *data) {
	struct sdcardfs_vfsmount_options* opt = kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
	struct sdcardfs_vfsmount_options* old = data;
	if(!opt) return NULL;
	opt->gid = old->gid;
	opt->mask = old->mask;
	return opt;
}

static void sdcardfs_copy_mnt_data(void *data, void *newdata) {
	struct sdcardfs_vfsmount_options* old = data;
	struct sdcardfs_vfsmount_options* new = newdata;
	old->gid = new->gid;
	old->mask = new->mask;
}

/*
 * Called by iput() when the inode reference count reached zero
 * and the inode is not hashed anywhere.  Used to clear anything
@@ -191,19 +235,24 @@ static void sdcardfs_umount_begin(struct super_block *sb)
		lower_sb->s_op->umount_begin(lower_sb);
}

static int sdcardfs_show_options(struct seq_file *m, struct dentry *root)
static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, struct dentry *root)
{
	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(root->d_sb);
	struct sdcardfs_mount_options *opts = &sbi->options;
	struct sdcardfs_vfsmount_options *vfsopts = mnt->data;

	if (opts->fs_low_uid != 0)
		seq_printf(m, ",uid=%u", opts->fs_low_uid);
		seq_printf(m, ",fsuid=%u", opts->fs_low_uid);
	if (opts->fs_low_gid != 0)
		seq_printf(m, ",gid=%u", opts->fs_low_gid);

		seq_printf(m, ",fsgid=%u", opts->fs_low_gid);
	if (vfsopts->gid != 0)
		seq_printf(m, ",gid=%u", vfsopts->gid);
	if (opts->multiuser)
		seq_printf(m, ",multiuser");

	if (vfsopts->mask)
		seq_printf(m, ",mask=%u", vfsopts->mask);
	if (opts->fs_user_id)
		seq_printf(m, ",userid=%u", opts->fs_user_id);
	if (opts->reserved_mb != 0)
		seq_printf(m, ",reserved=%uMB", opts->reserved_mb);

@@ -214,9 +263,12 @@ const struct super_operations sdcardfs_sops = {
	.put_super	= sdcardfs_put_super,
	.statfs		= sdcardfs_statfs,
	.remount_fs	= sdcardfs_remount_fs,
	.remount_fs2	= sdcardfs_remount_fs2,
	.clone_mnt_data	= sdcardfs_clone_mnt_data,
	.copy_mnt_data	= sdcardfs_copy_mnt_data,
	.evict_inode	= sdcardfs_evict_inode,
	.umount_begin	= sdcardfs_umount_begin,
	.show_options	= sdcardfs_show_options,
	.show_options2	= sdcardfs_show_options,
	.alloc_inode	= sdcardfs_alloc_inode,
	.destroy_inode	= sdcardfs_destroy_inode,
	.drop_inode	= generic_delete_inode,