fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / lib / kobject.c
index efe67fa..7ce6dc1 100644 (file)
@@ -111,14 +111,14 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
        len = get_kobj_path_length(kobj);
        if (len == 0)
                return NULL;
-       path = kmalloc(len, gfp_mask);
+       path = kzalloc(len, gfp_mask);
        if (!path)
                return NULL;
-       memset(path, 0x00, len);
        fill_kobj_path(kobj, path, len);
 
        return path;
 }
+EXPORT_SYMBOL_GPL(kobject_get_path);
 
 /**
  *     kobject_init - initialize object.
@@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj)
 {
        kref_init(&kobj->kref);
        INIT_LIST_HEAD(&kobj->entry);
+       init_waitqueue_head(&kobj->poll);
        kobj->kset = kset_get(kobj->kset);
 }
 
@@ -194,6 +195,17 @@ int kobject_add(struct kobject * kobj)
                unlink(kobj);
                if (parent)
                        kobject_put(parent);
+
+               /* be noisy on error issues */
+               if (error == -EEXIST)
+                       printk("kobject_add failed for %s with -EEXIST, "
+                              "don't try to register things with the "
+                              "same name in the same directory.\n",
+                              kobject_name(kobj));
+               else
+                       printk("kobject_add failed for %s (%d)\n",
+                              kobject_name(kobj), error);
+                dump_stack();
        }
 
        return error;
@@ -207,18 +219,13 @@ int kobject_add(struct kobject * kobj)
 
 int kobject_register(struct kobject * kobj)
 {
-       int error = 0;
+       int error = -EINVAL;
        if (kobj) {
                kobject_init(kobj);
                error = kobject_add(kobj);
-               if (error) {
-                       printk("kobject_register failed for %s (%d)\n",
-                              kobject_name(kobj),error);
-                       dump_stack();
-               } else
+               if (!error)
                        kobject_uevent(kobj, KOBJ_ADD);
-       } else
-               error = -EINVAL;
+       }
        return error;
 }
 
@@ -302,6 +309,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
        return error;
 }
 
+/**
+ *     kobject_move - move object to another parent
+ *     @kobj:  object in question.
+ *     @new_parent: object's new parent
+ */
+
+int kobject_move(struct kobject *kobj, struct kobject *new_parent)
+{
+       int error;
+       struct kobject *old_parent;
+       const char *devpath = NULL;
+       char *devpath_string = NULL;
+       char *envp[2];
+
+       kobj = kobject_get(kobj);
+       if (!kobj)
+               return -EINVAL;
+       new_parent = kobject_get(new_parent);
+       if (!new_parent) {
+               error = -EINVAL;
+               goto out;
+       }
+       /* old object path */
+       devpath = kobject_get_path(kobj, GFP_KERNEL);
+       if (!devpath) {
+               error = -ENOMEM;
+               goto out;
+       }
+       devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
+       if (!devpath_string) {
+               error = -ENOMEM;
+               goto out;
+       }
+       sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
+       envp[0] = devpath_string;
+       envp[1] = NULL;
+       error = sysfs_move_dir(kobj, new_parent);
+       if (error)
+               goto out;
+       old_parent = kobj->parent;
+       kobj->parent = new_parent;
+       kobject_put(old_parent);
+       kobject_uevent_env(kobj, KOBJ_MOVE, envp);
+out:
+       kobject_put(kobj);
+       kfree(devpath_string);
+       kfree(devpath);
+       return error;
+}
+
 /**
  *     kobject_del - unlink kobject from hierarchy.
  *     @kobj:  object.
@@ -379,6 +436,50 @@ void kobject_put(struct kobject * kobj)
 }
 
 
+static void dir_release(struct kobject *kobj)
+{
+       kfree(kobj);
+}
+
+static struct kobj_type dir_ktype = {
+       .release        = dir_release,
+       .sysfs_ops      = NULL,
+       .default_attrs  = NULL,
+};
+
+/**
+ *     kobject_add_dir - add sub directory of object.
+ *     @parent:        object in which a directory is created.
+ *     @name:  directory name.
+ *
+ *     Add a plain directory object as child of given object.
+ */
+struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
+{
+       struct kobject *k;
+       int ret;
+
+       if (!parent)
+               return NULL;
+
+       k = kzalloc(sizeof(*k), GFP_KERNEL);
+       if (!k)
+               return NULL;
+
+       k->parent = parent;
+       k->ktype = &dir_ktype;
+       kobject_set_name(k, name);
+       ret = kobject_register(k);
+       if (ret < 0) {
+               printk(KERN_WARNING "kobject_add_dir: "
+                       "kobject_register error: %d\n", ret);
+               kobject_del(k);
+               return NULL;
+       }
+
+       return k;
+}
+
 /**
  *     kset_init - initialize a kset for use
  *     @k:     kset 
@@ -524,7 +625,7 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
  *     @s:     subsystem.
  *     @a:     attribute desciptor.
  */
-
+#if 0
 void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
 {
        if (subsys_get(s)) {
@@ -532,6 +633,7 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
                subsys_put(s);
        }
 }
+#endif  /*  0  */
 
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
@@ -543,10 +645,7 @@ EXPORT_SYMBOL(kobject_del);
 
 EXPORT_SYMBOL(kset_register);
 EXPORT_SYMBOL(kset_unregister);
-EXPORT_SYMBOL(kset_find_obj);
 
-EXPORT_SYMBOL(subsystem_init);
 EXPORT_SYMBOL(subsystem_register);
 EXPORT_SYMBOL(subsystem_unregister);
 EXPORT_SYMBOL(subsys_create_file);
-EXPORT_SYMBOL(subsys_remove_file);