+LPROC_SEQ_FOPS(lprocfs_nid_stats_clear);
+
+LUSTRE_OBD_UINT_PARAM_ATTR(at_min);
+LUSTRE_OBD_UINT_PARAM_ATTR(at_max);
+LUSTRE_OBD_UINT_PARAM_ATTR(at_history);
+
+static struct attribute *ofd_attrs[] = {
+ &lustre_attr_access_log_mask.attr,
+ &lustre_attr_access_log_size.attr,
+ &lustre_attr_atime_diff.attr,
+ &lustre_attr_checksum_t10pi_enforce.attr,
+ &lustre_attr_degraded.attr,
+ &lustre_attr_eviction_count.attr,
+ &lustre_attr_fstype.attr,
+ &lustre_attr_grant_check_threshold.attr,
+ &lustre_attr_grant_compat_disable.attr,
+ &lustre_attr_grant_precreate.attr,
+ &lustre_attr_instance.attr,
+ &lustre_attr_ir_factor.attr,
+ &lustre_attr_job_cleanup_interval.attr,
+ &lustre_attr_lfsck_speed_limit.attr,
+ &lustre_attr_no_create.attr,
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 20, 53, 0)
+ &lustre_attr_no_precreate.attr,
+#endif
+ &lustre_attr_num_exports.attr,
+ &lustre_attr_precreate_batch.attr,
+ &lustre_attr_recovery_time_hard.attr,
+ &lustre_attr_recovery_time_soft.attr,
+ &lustre_attr_seqs_allocated.attr,
+ &lustre_attr_tot_dirty.attr,
+ &lustre_attr_tot_granted.attr,
+ &lustre_attr_tot_pending.attr,
+ &lustre_attr_soft_sync_limit.attr,
+ &lustre_attr_sync_journal.attr,
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 16, 53, 0)
+ &lustre_attr_sync_on_lock_cancel.attr,
+#endif
+ &lustre_attr_at_min.attr,
+ &lustre_attr_at_max.attr,
+ &lustre_attr_at_history.attr,
+ NULL,
+};
+
+KOBJ_ATTRIBUTE_GROUPS(ofd); /* creates ofd_groups from ofd_attrs */
+
+/**
+ * Initialize all needed procfs entries for OFD device.
+ *
+ * \param[in] ofd OFD device
+ *
+ * \retval 0 if successful
+ * \retval negative value on error
+ */
+int ofd_tunables_init(struct ofd_device *ofd)
+{
+ struct obd_device *obd = ofd_obd(ofd);
+ struct proc_dir_entry *entry;
+ int rc = 0;
+
+ ENTRY;
+ /* lprocfs must be setup before the ofd so state can be safely added
+ * to /proc incrementally as the ofd is setup
+ */
+ obd->obd_ktype.default_groups = KOBJ_ATTR_GROUPS(ofd);
+ obd->obd_vars = lprocfs_ofd_obd_vars;
+ rc = lprocfs_obd_setup(obd, false);
+ if (rc) {
+ CERROR("%s: lprocfs_obd_setup failed: %d.\n",
+ obd->obd_name, rc);
+ RETURN(rc);
+ }
+ ldebugfs_add_vars(obd->obd_debugfs_entry, ldebugfs_ofd_obd_vars, obd);
+
+ rc = tgt_tunables_init(&ofd->ofd_lut);
+ if (rc) {
+ CERROR("%s: tgt_tunables_init failed: rc = %d\n",
+ obd->obd_name, rc);
+ GOTO(obd_cleanup, rc);
+ }
+
+ rc = lprocfs_alloc_obd_stats(obd, LPROC_OFD_STATS_LAST);
+ if (rc) {
+ CERROR("%s: lprocfs_alloc_obd_stats failed: %d.\n",
+ obd->obd_name, rc);
+ GOTO(tgt_cleanup, rc);
+ }
+
+ obd->obd_debugfs_gss_dir = debugfs_create_dir("gss",
+ obd->obd_debugfs_entry);
+ if (obd->obd_debugfs_gss_dir)
+ ldebugfs_add_vars(obd->obd_debugfs_gss_dir,
+ ldebugfs_ofd_gss_vars, obd);
+
+ entry = lprocfs_register("exports", obd->obd_proc_entry, NULL, NULL);
+ if (IS_ERR(entry)) {
+ rc = PTR_ERR(entry);
+ CERROR("%s: error %d setting up lprocfs for %s\n",
+ obd->obd_name, rc, "exports");
+ GOTO(obd_free_stats, rc);
+ }
+ obd->obd_proc_exports_entry = entry;
+
+ entry = lprocfs_add_simple(obd->obd_proc_exports_entry, "clear",
+ obd, &lprocfs_nid_stats_clear_fops);
+ if (IS_ERR(entry)) {
+ rc = PTR_ERR(entry);
+ CERROR("%s: add proc entry 'clear' failed: %d.\n",
+ obd->obd_name, rc);
+ GOTO(obd_free_stats, rc);
+ }
+
+ ofd_stats_counter_init(obd->obd_stats, 0, LPROCFS_CNTR_HISTOGRAM);
+
+ rc = lprocfs_job_stats_init(obd, LPROC_OFD_STATS_LAST,
+ ofd_stats_counter_init);
+ if (rc)
+ GOTO(obd_free_stats, rc);
+
+ RETURN(0);
+
+obd_free_stats:
+ lprocfs_free_obd_stats(obd);
+tgt_cleanup:
+ tgt_tunables_fini(&ofd->ofd_lut);
+obd_cleanup:
+ lprocfs_obd_cleanup(obd);
+
+ return rc;
+}
+#endif /* CONFIG_PROC_FS */