Skip to content
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.

Commit

Permalink
configfs: allow dynamic group creation
Browse files Browse the repository at this point in the history
This patchset introduces IIO software triggers, offers a way of configuring
them via configfs and adds the IIO hrtimer based interrupt source to be used
with software triggers.

The architecture is now split in 3 parts, to remove all IIO trigger specific
parts from IIO configfs core:

(1) IIO configfs - creates the root of the IIO configfs subsys.
(2) IIO software triggers - software trigger implementation, dynamically
    creating /config/iio/triggers group.
(3) IIO hrtimer trigger - is the first interrupt source for software triggers
    (with syfs to follow). Each trigger type can implement its own set of
    attributes.

Lockdep seems to be happy with the locking in configfs patch.

This patch (of 5):

We don't want to hardcode default groups at subsystem
creation time. We export:
	* configfs_register_group
	* configfs_unregister_group
to allow drivers to programatically create/destroy groups
later, after module init time.

This is needed for IIO configfs support.

(akpm: the other 4 patches to be merged via the IIO tree)

Signed-off-by: Daniel Baluta <[email protected]>
Suggested-by: Lars-Peter Clausen <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Acked-by: Joel Becker <[email protected]>
Cc: Hartmut Knaack <[email protected]>
Cc: Octavian Purdila <[email protected]>
Cc: Paul Bolle <[email protected]>
Cc: Adriana Reus <[email protected]>
Cc: Cristina Opriceana <[email protected]>
Cc: Peter Meerwald <[email protected]>
Cc: Alexander Viro <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Daniel Baluta authored and torvalds committed Nov 21, 2015
1 parent dd7d664 commit 5cf6a51
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
110 changes: 110 additions & 0 deletions fs/configfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,116 @@ const struct file_operations configfs_dir_operations = {
.iterate = configfs_readdir,
};

/**
* configfs_register_group - creates a parent-child relation between two groups
* @parent_group: parent group
* @group: child group
*
* link groups, creates dentry for the child and attaches it to the
* parent dentry.
*
* Return: 0 on success, negative errno code on error
*/
int configfs_register_group(struct config_group *parent_group,
struct config_group *group)
{
struct configfs_subsystem *subsys = parent_group->cg_subsys;
struct dentry *parent;
int ret;

mutex_lock(&subsys->su_mutex);
link_group(parent_group, group);
mutex_unlock(&subsys->su_mutex);

parent = parent_group->cg_item.ci_dentry;

mutex_lock_nested(&d_inode(parent)->i_mutex, I_MUTEX_PARENT);
ret = create_default_group(parent_group, group);
if (!ret) {
spin_lock(&configfs_dirent_lock);
configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata);
spin_unlock(&configfs_dirent_lock);
}
mutex_unlock(&d_inode(parent)->i_mutex);
return ret;
}
EXPORT_SYMBOL(configfs_register_group);

/**
* configfs_unregister_group() - unregisters a child group from its parent
* @group: parent group to be unregistered
*
* Undoes configfs_register_group()
*/
void configfs_unregister_group(struct config_group *group)
{
struct configfs_subsystem *subsys = group->cg_subsys;
struct dentry *dentry = group->cg_item.ci_dentry;
struct dentry *parent = group->cg_item.ci_parent->ci_dentry;

mutex_lock_nested(&d_inode(parent)->i_mutex, I_MUTEX_PARENT);
spin_lock(&configfs_dirent_lock);
configfs_detach_prep(dentry, NULL);
spin_unlock(&configfs_dirent_lock);

configfs_detach_group(&group->cg_item);
d_inode(dentry)->i_flags |= S_DEAD;
dont_mount(dentry);
d_delete(dentry);
mutex_unlock(&d_inode(parent)->i_mutex);

dput(dentry);

mutex_lock(&subsys->su_mutex);
unlink_group(group);
mutex_unlock(&subsys->su_mutex);
}
EXPORT_SYMBOL(configfs_unregister_group);

/**
* configfs_register_default_group() - allocates and registers a child group
* @parent_group: parent group
* @name: child group name
* @item_type: child item type description
*
* boilerplate to allocate and register a child group with its parent. We need
* kzalloc'ed memory because child's default_group is initially empty.
*
* Return: allocated config group or ERR_PTR() on error
*/
struct config_group *
configfs_register_default_group(struct config_group *parent_group,
const char *name,
struct config_item_type *item_type)
{
int ret;
struct config_group *group;

group = kzalloc(sizeof(*group), GFP_KERNEL);
if (!group)
return ERR_PTR(-ENOMEM);
config_group_init_type_name(group, name, item_type);

ret = configfs_register_group(parent_group, group);
if (ret) {
kfree(group);
return ERR_PTR(ret);
}
return group;
}
EXPORT_SYMBOL(configfs_register_default_group);

/**
* configfs_unregister_default_group() - unregisters and frees a child group
* @group: the group to act on
*/
void configfs_unregister_default_group(struct config_group *group)
{
configfs_unregister_group(group);
kfree(group);
}
EXPORT_SYMBOL(configfs_unregister_default_group);

int configfs_register_subsystem(struct configfs_subsystem *subsys)
{
int err;
Expand Down
10 changes: 10 additions & 0 deletions include/linux/configfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@ static inline struct configfs_subsystem *to_configfs_subsystem(struct config_gro
int configfs_register_subsystem(struct configfs_subsystem *subsys);
void configfs_unregister_subsystem(struct configfs_subsystem *subsys);

int configfs_register_group(struct config_group *parent_group,
struct config_group *group);
void configfs_unregister_group(struct config_group *group);

struct config_group *
configfs_register_default_group(struct config_group *parent_group,
const char *name,
struct config_item_type *item_type);
void configfs_unregister_default_group(struct config_group *group);

/* These functions can sleep and can alloc with GFP_KERNEL */
/* WARNING: These cannot be called underneath configfs callbacks!! */
int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
Expand Down

0 comments on commit 5cf6a51

Please sign in to comment.