+static void class_sysfs_release(struct kobject *kobj)
+{
+ struct obd_type *type = container_of(kobj, struct obd_type, typ_kobj);
+
+ debugfs_remove_recursive(type->typ_debugfs_entry);
+ type->typ_debugfs_entry = NULL;
+
+ if (type->typ_lu)
+ lu_device_type_fini(type->typ_lu);
+
+#ifdef CONFIG_PROC_FS
+ if (type->typ_name && type->typ_procroot)
+ remove_proc_subtree(type->typ_name, proc_lustre_root);
+#endif
+ if (type->typ_md_ops)
+ OBD_FREE_PTR(type->typ_md_ops);
+ if (type->typ_dt_ops)
+ OBD_FREE_PTR(type->typ_dt_ops);
+
+ OBD_FREE(type, sizeof(*type));
+}
+
+static struct kobj_type class_ktype = {
+ .sysfs_ops = &lustre_sysfs_ops,
+ .release = class_sysfs_release,
+};
+
+#ifdef HAVE_SERVER_SUPPORT
+struct obd_type *class_add_symlinks(const char *name, bool enable_proc)
+{
+ struct dentry *symlink;
+ struct obd_type *type;
+ int rc;
+
+ type = class_search_type(name);
+ if (type) {
+ kobject_put(&type->typ_kobj);
+ return ERR_PTR(-EEXIST);
+ }
+
+ OBD_ALLOC(type, sizeof(*type));
+ if (!type)
+ return ERR_PTR(-ENOMEM);
+
+ type->typ_kobj.kset = lustre_kset;
+ rc = kobject_init_and_add(&type->typ_kobj, &class_ktype,
+ &lustre_kset->kobj, "%s", name);
+ if (rc)
+ return ERR_PTR(rc);
+
+ symlink = debugfs_create_dir(name, debugfs_lustre_root);
+ if (IS_ERR_OR_NULL(symlink)) {
+ rc = symlink ? PTR_ERR(symlink) : -ENOMEM;
+ kobject_put(&type->typ_kobj);
+ return ERR_PTR(rc);
+ }
+ type->typ_debugfs_entry = symlink;
+ type->typ_sym_filter = true;
+
+ if (enable_proc) {
+ type->typ_procroot = lprocfs_register(name, proc_lustre_root,
+ NULL, NULL);
+ if (IS_ERR(type->typ_procroot)) {
+ CERROR("%s: can't create compat proc entry: %d\n",
+ name, (int)PTR_ERR(type->typ_procroot));
+ type->typ_procroot = NULL;
+ }
+ }
+
+ return type;
+}
+EXPORT_SYMBOL(class_add_symlinks);
+#endif /* HAVE_SERVER_SUPPORT */
+