Commit c7747faf authored by Al Viro's avatar Al Viro
Browse files

functionfs: switch to simple_remove_by_name()



No need to return dentry from ffs_sb_create_file() or keep it around
afterwards.

To avoid subtle issues with getting to ffs from epfiles in
ffs_epfiles_destroy(), pass the superblock as explicit argument.
Callers have it anyway.

Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e5bf5ee2
Loading
Loading
Loading
Loading
+22 −29
Original line number Diff line number Diff line
@@ -160,8 +160,6 @@ struct ffs_epfile {
	struct ffs_data			*ffs;
	struct ffs_ep			*ep;	/* P: ffs->eps_lock */

	struct dentry			*dentry;

	/*
	 * Buffer for holding data from partial reads which may happen since
	 * we’re rounding user read requests to a multiple of a max packet size.
@@ -271,11 +269,11 @@ struct ffs_desc_helper {
};

static int  __must_check ffs_epfiles_create(struct ffs_data *ffs);
static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
static void ffs_epfiles_destroy(struct super_block *sb,
				struct ffs_epfile *epfiles, unsigned count);

static struct dentry *
ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
		   const struct file_operations *fops);
static int ffs_sb_create_file(struct super_block *sb, const char *name,
			      void *data, const struct file_operations *fops);

/* Devices management *******************************************************/

@@ -1894,9 +1892,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
}

/* Create "regular" file */
static struct dentry *ffs_sb_create_file(struct super_block *sb,
					const char *name, void *data,
					const struct file_operations *fops)
static int ffs_sb_create_file(struct super_block *sb, const char *name,
			      void *data, const struct file_operations *fops)
{
	struct ffs_data	*ffs = sb->s_fs_info;
	struct dentry	*dentry;
@@ -1904,16 +1901,16 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,

	dentry = d_alloc_name(sb->s_root, name);
	if (!dentry)
		return NULL;
		return -ENOMEM;

	inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms);
	if (!inode) {
		dput(dentry);
		return NULL;
		return -ENOMEM;
	}

	d_add(dentry, inode);
	return dentry;
	return 0;
}

/* Super block */
@@ -1956,10 +1953,7 @@ static int ffs_sb_fill(struct super_block *sb, struct fs_context *fc)
		return -ENOMEM;

	/* EP0 file */
	if (!ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations))
		return -ENOMEM;

	return 0;
	return ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations);
}

enum {
@@ -2196,7 +2190,7 @@ static void ffs_data_closed(struct ffs_data *ffs)
							flags);

			if (epfiles)
				ffs_epfiles_destroy(epfiles,
				ffs_epfiles_destroy(ffs->sb, epfiles,
						 ffs->eps_count);

			if (ffs->setup_state == FFS_SETUP_PENDING)
@@ -2255,7 +2249,7 @@ static void ffs_data_clear(struct ffs_data *ffs)
	 * copy of epfile will save us from use-after-free.
	 */
	if (epfiles) {
		ffs_epfiles_destroy(epfiles, ffs->eps_count);
		ffs_epfiles_destroy(ffs->sb, epfiles, ffs->eps_count);
		ffs->epfiles = NULL;
	}

@@ -2352,6 +2346,7 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
{
	struct ffs_epfile *epfile, *epfiles;
	unsigned i, count;
	int err;

	count = ffs->eps_count;
	epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
@@ -2368,12 +2363,11 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
			sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
		else
			sprintf(epfile->name, "ep%u", i);
		epfile->dentry = ffs_sb_create_file(ffs->sb, epfile->name,
						 epfile,
						 &ffs_epfile_operations);
		if (!epfile->dentry) {
			ffs_epfiles_destroy(epfiles, i - 1);
			return -ENOMEM;
		err = ffs_sb_create_file(ffs->sb, epfile->name,
					 epfile, &ffs_epfile_operations);
		if (err) {
			ffs_epfiles_destroy(ffs->sb, epfiles, i - 1);
			return err;
		}
	}

@@ -2386,16 +2380,15 @@ static void clear_one(struct dentry *dentry)
	smp_store_release(&dentry->d_inode->i_private, NULL);
}

static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
static void ffs_epfiles_destroy(struct super_block *sb,
				struct ffs_epfile *epfiles, unsigned count)
{
	struct ffs_epfile *epfile = epfiles;
	struct dentry *root = sb->s_root;

	for (; count; --count, ++epfile) {
		BUG_ON(mutex_is_locked(&epfile->mutex));
		if (epfile->dentry) {
			simple_recursive_removal(epfile->dentry, clear_one);
			epfile->dentry = NULL;
		}
		simple_remove_by_name(root, epfile->name, clear_one);
	}

	kfree(epfiles);