configfs: accessing item hierarchy during rmdir(2)
Add a notification callback, ops->disconnect_notify(). It has the same prototype as ->drop_item(), but it will be called just before the item linkage is broken. This way, configfs users who want to do work while the object is still in the heirarchy have a chance. Client drivers will still need to config_item_put() in their ->drop_item(), if they implement it. They need do nothing in ->disconnect_notify(). They don't have to provide it if they don't care. But someone who wants to be notified before ci_parent is set to NULL can now be notified. Signed-off-by: Joel Becker <joel.becker@oracle.com> Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
This commit is contained in:
parent
6d748924b7
commit
299894cc90
|
@ -238,6 +238,8 @@ config_item_type.
|
|||
struct config_group *(*make_group)(struct config_group *group,
|
||||
const char *name);
|
||||
int (*commit_item)(struct config_item *item);
|
||||
void (*disconnect_notify)(struct config_group *group,
|
||||
struct config_item *item);
|
||||
void (*drop_item)(struct config_group *group,
|
||||
struct config_item *item);
|
||||
};
|
||||
|
@ -268,6 +270,16 @@ the item in other threads, the memory is safe. It may take some time
|
|||
for the item to actually disappear from the subsystem's usage. But it
|
||||
is gone from configfs.
|
||||
|
||||
When drop_item() is called, the item's linkage has already been torn
|
||||
down. It no longer has a reference on its parent and has no place in
|
||||
the item hierarchy. If a client needs to do some cleanup before this
|
||||
teardown happens, the subsystem can implement the
|
||||
ct_group_ops->disconnect_notify() method. The method is called after
|
||||
configfs has removed the item from the filesystem view but before the
|
||||
item is removed from its parent group. Like drop_item(),
|
||||
disconnect_notify() is void and cannot fail. Client subsystems should
|
||||
not drop any references here, as they still must do it in drop_item().
|
||||
|
||||
A config_group cannot be removed while it still has child items. This
|
||||
is implemented in the configfs rmdir(2) code. ->drop_item() will not be
|
||||
called, as the item has not been dropped. rmdir(2) will fail, as the
|
||||
|
|
|
@ -713,6 +713,28 @@ static void configfs_detach_group(struct config_item *item)
|
|||
configfs_detach_item(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* After the item has been detached from the filesystem view, we are
|
||||
* ready to tear it out of the hierarchy. Notify the client before
|
||||
* we do that so they can perform any cleanup that requires
|
||||
* navigating the hierarchy. A client does not need to provide this
|
||||
* callback. The subsystem semaphore MUST be held by the caller, and
|
||||
* references must be valid for both items. It also assumes the
|
||||
* caller has validated ci_type.
|
||||
*/
|
||||
static void client_disconnect_notify(struct config_item *parent_item,
|
||||
struct config_item *item)
|
||||
{
|
||||
struct config_item_type *type;
|
||||
|
||||
type = parent_item->ci_type;
|
||||
BUG_ON(!type);
|
||||
|
||||
if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
|
||||
type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
|
||||
item);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the initial reference from make_item()/make_group()
|
||||
* This function assumes that reference is held on item
|
||||
|
@ -842,11 +864,14 @@ out_unlink:
|
|||
if (ret) {
|
||||
/* Tear down everything we built up */
|
||||
mutex_lock(&subsys->su_mutex);
|
||||
|
||||
client_disconnect_notify(parent_item, item);
|
||||
if (group)
|
||||
unlink_group(group);
|
||||
else
|
||||
unlink_obj(item);
|
||||
client_drop_item(parent_item, item);
|
||||
|
||||
mutex_unlock(&subsys->su_mutex);
|
||||
|
||||
if (module_got)
|
||||
|
@ -911,11 +936,13 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
configfs_detach_group(item);
|
||||
|
||||
mutex_lock(&subsys->su_mutex);
|
||||
client_disconnect_notify(parent_item, item);
|
||||
unlink_group(to_config_group(item));
|
||||
} else {
|
||||
configfs_detach_item(item);
|
||||
|
||||
mutex_lock(&subsys->su_mutex);
|
||||
client_disconnect_notify(parent_item, item);
|
||||
unlink_obj(item);
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ struct configfs_group_operations {
|
|||
struct config_item *(*make_item)(struct config_group *group, const char *name);
|
||||
struct config_group *(*make_group)(struct config_group *group, const char *name);
|
||||
int (*commit_item)(struct config_item *item);
|
||||
void (*disconnect_notify)(struct config_group *group, struct config_item *item);
|
||||
void (*drop_item)(struct config_group *group, struct config_item *item);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue