+ rc = lprocfs_seq_create(sbi->ll_proc_root, "extents_stats_per_process",
+ 0644, &ll_rw_extents_stats_pp_fops, sbi);
+ if (rc)
+ CWARN("Error adding the extents_stats_per_process file\n");
+
+ rc = lprocfs_seq_create(sbi->ll_proc_root, "offset_stats", 0644,
+ &ll_rw_offset_stats_fops, sbi);
+ if (rc)
+ CWARN("Error adding the offset_stats file\n");
+
+ /* File operations stats */
+ sbi->ll_stats = lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES,
+ LPROCFS_STATS_FLAG_NONE);
+ if (sbi->ll_stats == NULL)
+ GOTO(out_proc, err = -ENOMEM);
+
+ /* do counter init */
+ for (id = 0; id < LPROC_LL_FILE_OPCODES; id++) {
+ __u32 type = llite_opcode_table[id].type;
+ void *ptr = NULL;
+ if (type & LPROCFS_TYPE_REGS)
+ ptr = "regs";
+ else if (type & LPROCFS_TYPE_BYTES)
+ ptr = "bytes";
+ else if (type & LPROCFS_TYPE_PAGES)
+ ptr = "pages";
+ lprocfs_counter_init(sbi->ll_stats,
+ llite_opcode_table[id].opcode,
+ (type & LPROCFS_CNTR_AVGMINMAX),
+ llite_opcode_table[id].opname, ptr);
+ }
+
+ err = lprocfs_register_stats(sbi->ll_proc_root, "stats", sbi->ll_stats);
+ if (err)
+ GOTO(out_stats, err);
+
+ sbi->ll_ra_stats = lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string),
+ LPROCFS_STATS_FLAG_NONE);
+ if (sbi->ll_ra_stats == NULL)
+ GOTO(out_stats, err = -ENOMEM);
+
+ for (id = 0; id < ARRAY_SIZE(ra_stat_string); id++)
+ lprocfs_counter_init(sbi->ll_ra_stats, id, 0,
+ ra_stat_string[id], "pages");
+ err = lprocfs_register_stats(sbi->ll_proc_root, "read_ahead_stats",
+ sbi->ll_ra_stats);
+ if (err)
+ GOTO(out_ra_stats, err);
+
+ err = lprocfs_add_vars(sbi->ll_proc_root, lprocfs_llite_obd_vars, sb);
+ if (err)
+ GOTO(out_ra_stats, err);
+
+ /* Yes we also register sysfs mount kset here as well */
+ sbi->ll_kset.kobj.parent = llite_kobj;
+ sbi->ll_kset.kobj.ktype = &llite_ktype;
+ init_completion(&sbi->ll_kobj_unregister);
+ err = kobject_set_name(&sbi->ll_kset.kobj, "%s", name);
+ if (err)
+ GOTO(out_ra_stats, err);
+
+ err = kset_register(&sbi->ll_kset);
+ if (err)
+ GOTO(out_ra_stats, err);
+
+ lsi->lsi_kobj = kobject_get(&sbi->ll_kset.kobj);
+
+ RETURN(0);
+out_ra_stats:
+ lprocfs_free_stats(&sbi->ll_ra_stats);
+out_stats:
+ lprocfs_free_stats(&sbi->ll_stats);
+out_proc:
+ lprocfs_remove(&sbi->ll_proc_root);
+
+ RETURN(err);
+}
+
+int lprocfs_ll_register_obd(struct super_block *sb, const char *obdname)
+{
+ struct lprocfs_vars lvars[2];
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
+ struct obd_device *obd;
+ struct proc_dir_entry *dir;
+ char name[MAX_STRING_SIZE + 1];
+ int err;
+ ENTRY;
+
+ memset(lvars, 0, sizeof(lvars));
+
+ name[MAX_STRING_SIZE] = '\0';
+ lvars[0].name = name;
+
+ LASSERT(sbi != NULL);
+ LASSERT(obdname != NULL);
+
+ obd = class_name2obd(obdname);
+
+ LASSERT(obd != NULL);
+ LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
+ LASSERT(obd->obd_type->typ_name != NULL);
+
+ dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root);
+ if (dir == NULL)
+ GOTO(out, err = -ENOMEM);
+
+ snprintf(name, MAX_STRING_SIZE, "common_name");
+ lvars[0].fops = &llite_name_fops;
+ err = lprocfs_add_vars(dir, lvars, obd);
+ if (err)
+ GOTO(out, err);
+
+ snprintf(name, MAX_STRING_SIZE, "uuid");
+ lvars[0].fops = &llite_uuid_fops;
+ err = lprocfs_add_vars(dir, lvars, obd);
+ if (err)
+ GOTO(out, err);