Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=299894cc9001b09e3e9685f2709b49e7e1092ccc
Commit:     299894cc9001b09e3e9685f2709b49e7e1092ccc
Parent:     6d748924b753d63a57dad130fdf11f64c27ff54b
Author:     Joel Becker <[EMAIL PROTECTED]>
AuthorDate: Fri Oct 6 17:33:23 2006 -0700
Committer:  Mark Fasheh <[EMAIL PROTECTED]>
CommitDate: Tue Jul 10 17:11:01 2007 -0700

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Mark Fasheh <[EMAIL PROTECTED]>
---
 Documentation/filesystems/configfs/configfs.txt |   12 +++++++++
 fs/configfs/dir.c                               |   29 ++++++++++++++++++++++-
 include/linux/configfs.h                        |    1 +
 3 files changed, 41 insertions(+), 1 deletions(-)

diff --git a/Documentation/filesystems/configfs/configfs.txt 
b/Documentation/filesystems/configfs/configfs.txt
index 21f038e..aef74cd 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -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
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index d3b1dbb..1259547 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -714,6 +714,28 @@ static void configfs_detach_group(struct config_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
  * and that item holds a valid reference to the parent.  Also, it
@@ -733,7 +755,7 @@ static void client_drop_item(struct config_item 
*parent_item,
         */
        if (type->ct_group_ops && type->ct_group_ops->drop_item)
                type->ct_group_ops->drop_item(to_config_group(parent_item),
-                                               item);
+                                             item);
        else
                config_item_put(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);
        }
 
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index 5ce0fc4..8227e73 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -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);
 };
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to