Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[fs/lustre-release.git] / lustre / ofd / ofd_obd.c
index f67ad47..15e5a2b 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/ofd/ofd_obd.c
  *
@@ -49,6 +48,7 @@
 #include <lustre_quota.h>
 #include <lustre_lfsck.h>
 #include <lustre_nodemap.h>
+#include <obd_support.h>
 
 /**
  * Initialize OFD per-export statistics.
@@ -65,7 +65,7 @@
  */
 static int ofd_export_stats_init(struct ofd_device *ofd,
                                 struct obd_export *exp,
-                                lnet_nid_t *client_nid)
+                                struct lnet_nid *client_nid)
 {
        struct obd_device       *obd = ofd_obd(ofd);
        struct nid_stat         *stats;
@@ -83,16 +83,16 @@ static int ofd_export_stats_init(struct ofd_device *ofd,
                RETURN(rc == -EALREADY ? 0 : rc);
 
        stats = exp->exp_nid_stats;
-       stats->nid_stats = lprocfs_alloc_stats(LPROC_OFD_STATS_LAST,
+       stats->nid_stats = lprocfs_stats_alloc(LPROC_OFD_STATS_LAST,
                                               LPROCFS_STATS_FLAG_NOPERCPU);
        if (!stats->nid_stats)
                RETURN(-ENOMEM);
 
-       ofd_stats_counter_init(stats->nid_stats);
+       ofd_stats_counter_init(stats->nid_stats, 0, LPROCFS_CNTR_HISTOGRAM);
 
-       rc = lprocfs_register_stats(stats->nid_proc, "stats", stats->nid_stats);
+       rc = lprocfs_stats_register(stats->nid_proc, "stats", stats->nid_stats);
        if (rc != 0) {
-               lprocfs_free_stats(&stats->nid_stats);
+               lprocfs_stats_free(&stats->nid_stats);
                GOTO(out, rc);
        }
 
@@ -105,93 +105,6 @@ out:
 }
 
 /**
- * Decide which checksums both client and OST support, possibly forcing
- * the use of T10PI checksums if the hardware supports this.
- *
- * The clients that have no T10-PI RPC checksum support will use the same
- * mechanism to select checksum type as before, and will not be affected by
- * the following logic.
- *
- * For the clients that have T10-PI RPC checksum support:
- *
- * If the OST supports T10-PI feature and T10-PI checksum is enforced, clients
- * will have no other choice for RPC checksum type other than using the T10PI
- * checksum type. This is useful for enforcing end-to-end integrity in the
- * whole system.
- *
- * If the OST doesn't support T10-PI feature and T10-PI checksum is enforced,
- * together with other checksum with reasonably good speeds (e.g. crc32,
- * crc32c, adler, etc.), all T10-PI checksum types understood by the client
- * (t10ip512, t10ip4K, t10crc512, t10crc4K) will be added to the available
- * checksum types, regardless of the speeds of T10-PI checksums. This is
- * useful for testing T10-PI checksum of RPC.
- *
- * If the OST supports T10-PI feature and T10-PI checksum is NOT enforced,
- * the corresponding T10-PI checksum type will be added to the checksum type
- * list, regardless of the speed of the T10-PI checksum. This provides clients
- * the flexibility to choose whether to enable end-to-end integrity or not.
- *
- * If the OST does NOT supports T10-PI feature and T10-PI checksum is NOT
- * enforced, together with other checksums with reasonably good speeds,
- * all the T10-PI checksum types with good speeds will be added into the
- * checksum type list. Note that a T10-PI checksum type with a speed worse
- * than half of Alder will NOT be added as a option. In this circumstance,
- * T10-PI checksum types has the same behavior like other normal checksum
- * types.
- *
- */
-static void
-ofd_mask_cksum_types(struct ofd_device *ofd, enum cksum_types *cksum_types)
-{
-       bool enforce = ofd->ofd_checksum_t10pi_enforce;
-       enum cksum_types ofd_t10_cksum_type;
-       enum cksum_types client_t10_types = *cksum_types & OBD_CKSUM_T10_ALL;
-       enum cksum_types server_t10_types;
-
-       /*
-        * The client set in ocd_cksum_types the checksum types it
-        * supports. We have to mask off the algorithms that we don't
-        * support. T10PI checksum types will be added later.
-        */
-       *cksum_types &= (ofd->ofd_cksum_types_supported & ~OBD_CKSUM_T10_ALL);
-       server_t10_types = ofd->ofd_cksum_types_supported & OBD_CKSUM_T10_ALL;
-       ofd_t10_cksum_type = ofd->ofd_lut.lut_dt_conf.ddp_t10_cksum_type;
-
-       /* Quick exit if no T10-PI support on client */
-       if (!client_t10_types)
-               return;
-
-       /*
-        * This OST has NO T10-PI feature. Add all supported T10-PI checksums
-        * as options if T10-PI checksum is enforced. If the T10-PI checksum is
-        * not enforced, only add them as options when speed is good.
-        */
-       if (ofd_t10_cksum_type == 0) {
-               /*
-                * Server allows all T10PI checksums, and server_t10_types
-                * include quick ones.
-                */
-               if (enforce)
-                       *cksum_types |= client_t10_types;
-               else
-                       *cksum_types |= client_t10_types & server_t10_types;
-               return;
-       }
-
-       /*
-        * This OST has T10-PI feature. Disable all other checksum types if
-        * T10-PI checksum is enforced. If the T10-PI checksum is not enforced,
-        * add the checksum type as an option.
-        */
-       if (client_t10_types & ofd_t10_cksum_type) {
-               if (enforce)
-                       *cksum_types = ofd_t10_cksum_type;
-               else
-                       *cksum_types |= ofd_t10_cksum_type;
-       }
-}
-
-/**
  * Match client and OST server connection feature flags.
  *
  * Compute the compatibility flags for a connection request based on
@@ -258,7 +171,7 @@ static int ofd_parse_connect_data(const struct lu_env *env,
                RETURN(-EPROTO);
 
        /* Determine optimal brw size before calculating grant */
-       if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_SIZE)) {
+       if (CFS_FAIL_CHECK(OBD_FAIL_OST_BRW_SIZE)) {
                data->ocd_brw_size = 65536;
        } else if (OCD_HAS_FLAG(data, BRW_SIZE)) {
                if (data->ocd_brw_size > ofd->ofd_brw_size)
@@ -323,7 +236,7 @@ static int ofd_parse_connect_data(const struct lu_env *env,
        if (data->ocd_connect_flags & OBD_CONNECT_CKSUM) {
                __u32 cksum_types = data->ocd_cksum_types;
 
-               ofd_mask_cksum_types(ofd, &data->ocd_cksum_types);
+               tgt_mask_cksum_types(&ofd->ofd_lut, &data->ocd_cksum_types);
 
                if (unlikely(data->ocd_cksum_types == 0)) {
                        CERROR("%s: Connect with checksum support but no ocd_cksum_types is set\n",
@@ -360,6 +273,9 @@ static int ofd_parse_connect_data(const struct lu_env *env,
                }
        }
 
+       if (!ofd->ofd_lut.lut_dt_conf.ddp_has_lseek_data_hole)
+               data->ocd_connect_flags2 &= ~OBD_CONNECT2_LSEEK;
+
        RETURN(0);
 }
 
@@ -382,9 +298,10 @@ static int ofd_parse_connect_data(const struct lu_env *env,
 static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp,
                             struct obd_device *obd, struct obd_uuid *cluuid,
                             struct obd_connect_data *data,
-                            void *client_nid)
+                            void *localdata)
 {
        struct ofd_device *ofd;
+       struct lnet_nid *client_nid = localdata;
        int rc;
 
        ENTRY;
@@ -392,7 +309,7 @@ static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp,
        if (!exp || !obd || !cluuid)
                RETURN(-EINVAL);
 
-       rc = nodemap_add_member(*(lnet_nid_t *)client_nid, exp);
+       rc = nodemap_add_member(client_nid, exp);
        if (rc != 0 && rc != -EEXIST)
                RETURN(rc);
 
@@ -431,6 +348,7 @@ static int ofd_obd_connect(const struct lu_env *env, struct obd_export **_exp,
        struct obd_export *exp;
        struct ofd_device *ofd;
        struct lustre_handle conn = { 0 };
+       struct lnet_nid *client_nid = localdata;
        int rc;
 
        ENTRY;
@@ -447,8 +365,8 @@ static int ofd_obd_connect(const struct lu_env *env, struct obd_export **_exp,
        exp = class_conn2export(&conn);
        LASSERT(exp != NULL);
 
-       if (localdata) {
-               rc = nodemap_add_member(*(lnet_nid_t *)localdata, exp);
+       if (client_nid) {
+               rc = nodemap_add_member(client_nid, exp);
                if (rc != 0 && rc != -EEXIST)
                        GOTO(out, rc);
        } else {
@@ -469,7 +387,7 @@ static int ofd_obd_connect(const struct lu_env *env, struct obd_export **_exp,
                rc = tgt_client_new(env, exp);
                if (rc != 0)
                        GOTO(out, rc);
-               ofd_export_stats_init(ofd, exp, localdata);
+               ofd_export_stats_init(ofd, exp, client_nid);
        }
 
        CDEBUG(D_HA, "%s: get connection from MDS %d\n", obd->obd_name,
@@ -508,13 +426,13 @@ int ofd_obd_disconnect(struct obd_export *exp)
        LASSERT(exp);
        class_export_get(exp);
 
-       if (!(exp->exp_flags & OBD_OPT_FORCE))
-               tgt_grant_sanity_check(ofd_obd(ofd), __func__);
-
        rc = server_disconnect_export(exp);
 
        tgt_grant_discard(exp);
 
+       if (!(exp->exp_flags & OBD_OPT_FORCE))
+               tgt_grant_sanity_check(ofd_obd(ofd), __func__);
+
        /* Do not erase record for recoverable client. */
        if (exp->exp_obd->obd_replayable &&
            (!exp->exp_obd->obd_fail || exp->exp_failed)) {
@@ -546,8 +464,6 @@ static int ofd_init_export(struct obd_export *exp)
 {
        int rc;
 
-       spin_lock_init(&exp->exp_filter_data.fed_lock);
-       INIT_LIST_HEAD(&exp->exp_filter_data.fed_mod_list);
        atomic_set(&exp->exp_filter_data.fed_soft_sync_count, 0);
        spin_lock(&exp->exp_lock);
        exp->exp_connecting = 1;
@@ -596,14 +512,11 @@ static int ofd_destroy_export(struct obd_export *exp)
        ldlm_destroy_export(exp);
        tgt_client_free(exp);
 
-       ofd_fmd_cleanup(exp);
-
        /*
         * discard grants once we're sure no more
         * interaction with the client is possible
         */
        tgt_grant_discard(exp);
-       ofd_fmd_cleanup(exp);
 
        if (exp_connect_flags(exp) & OBD_CONNECT_GRANT)
                ofd->ofd_lut.lut_tgd.tgd_tot_granted_clients--;
@@ -611,7 +524,6 @@ static int ofd_destroy_export(struct obd_export *exp)
        if (!(exp->exp_flags & OBD_OPT_FORCE))
                tgt_grant_sanity_check(exp->exp_obd, __func__);
 
-       LASSERT(list_empty(&exp->exp_filter_data.fed_mod_list));
        return 0;
 }
 
@@ -783,7 +695,7 @@ static int ofd_get_info(const struct lu_env *env, struct obd_export *exp,
  * \see  ofd_statfs_hdl() for request handler function.
  *
  * Report also the state of the OST to the caller in osfs->os_state
- * (OS_STATE_READONLY, OS_STATE_DEGRADED).
+ * (OS_STATFS_READONLY, OS_STATFS_DEGRADED).
  *
  * \param[in]  env     execution environment
  * \param[in]  exp     OBD export of OFD device
@@ -800,6 +712,7 @@ int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
        struct obd_device *obd = class_exp2obd(exp);
        struct ofd_device *ofd = ofd_exp(exp);
        struct tg_grants_data *tgd = &ofd->ofd_lut.lut_tgd;
+       int current_blockbits;
        int rc;
 
        ENTRY;
@@ -808,22 +721,30 @@ int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
        if (unlikely(rc))
                GOTO(out, rc);
 
+       /* tgd_blockbit is recordsize bits set during mkfs.
+        * This once set does not change. However, 'zfs set'
+        * can be used to change the OST blocksize. Instead
+        * of using cached value of 'tgd_blockbit' always
+        * calculate the blocksize bits which may have
+        * changed.
+        */
+       current_blockbits = fls64(osfs->os_bsize) - 1;
+
        /*
         * at least try to account for cached pages.  its still racy and
         * might be under-reporting if clients haven't announced their
         * caches with brw recently
         */
-
        CDEBUG(D_SUPER | D_CACHE,
               "blocks cached %llu granted %llu pending %llu free %llu avail %llu\n",
               tgd->tgd_tot_dirty, tgd->tgd_tot_granted,
               tgd->tgd_tot_pending,
-              osfs->os_bfree << tgd->tgd_blockbits,
-              osfs->os_bavail << tgd->tgd_blockbits);
+              osfs->os_bfree << current_blockbits,
+              osfs->os_bavail << current_blockbits);
 
        osfs->os_bavail -= min_t(u64, osfs->os_bavail,
                                 ((tgd->tgd_tot_dirty + tgd->tgd_tot_pending +
-                                  osfs->os_bsize - 1) >> tgd->tgd_blockbits));
+                                  osfs->os_bsize - 1) >> current_blockbits));
 
        /*
         * The QoS code on the MDS does not care about space reserved for
@@ -834,7 +755,7 @@ int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
 
                ted = &obd->obd_self_export->exp_target_data;
                osfs->os_granted = min_t(u64, osfs->os_bavail,
-                                         ted->ted_grant >> tgd->tgd_blockbits);
+                                         ted->ted_grant >> current_blockbits);
                osfs->os_bavail -= osfs->os_granted;
        }
 
@@ -844,19 +765,22 @@ int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
               osfs->os_blocks, osfs->os_bfree, osfs->os_bavail,
               osfs->os_files, osfs->os_ffree, osfs->os_state);
 
-       if (OBD_FAIL_CHECK_VALUE(OBD_FAIL_OST_ENOINO,
+       if (CFS_FAIL_CHECK_VALUE(OBD_FAIL_OST_ENOINO,
                                 ofd->ofd_lut.lut_lsd.lsd_osd_index)) {
                /* Reduce free inode count to zero, but keep "used" intact */
                osfs->os_files -= osfs->os_ffree;
                osfs->os_ffree -= osfs->os_ffree;
        }
 
-       /* OS_STATE_READONLY can be set by OSD already */
+       /* OS_STATFS_READONLY can be set by OSD already, only add flags */
        if (ofd->ofd_raid_degraded)
-               osfs->os_state |= OS_STATE_DEGRADED;
+               osfs->os_state |= OS_STATFS_DEGRADED;
+
+       if (ofd->ofd_lut.lut_no_create)
+               osfs->os_state |= OS_STATFS_NOCREATE;
 
        if (obd->obd_self_export != exp && !exp_grant_param_supp(exp) &&
-           tgd->tgd_blockbits > COMPAT_BSIZE_SHIFT) {
+           current_blockbits > COMPAT_BSIZE_SHIFT) {
                /*
                 * clients which don't support OBD_CONNECT_GRANT_PARAM
                 * should not see a block size > page size, otherwise
@@ -864,14 +788,14 @@ int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
                 * block size which is the biggest block size known to work
                 * with all client's page size.
                 */
-               osfs->os_blocks <<= tgd->tgd_blockbits - COMPAT_BSIZE_SHIFT;
-               osfs->os_bfree  <<= tgd->tgd_blockbits - COMPAT_BSIZE_SHIFT;
-               osfs->os_bavail <<= tgd->tgd_blockbits - COMPAT_BSIZE_SHIFT;
-               osfs->os_granted <<= tgd->tgd_blockbits - COMPAT_BSIZE_SHIFT;
+               osfs->os_blocks <<= current_blockbits - COMPAT_BSIZE_SHIFT;
+               osfs->os_bfree  <<= current_blockbits - COMPAT_BSIZE_SHIFT;
+               osfs->os_bavail <<= current_blockbits - COMPAT_BSIZE_SHIFT;
+               osfs->os_granted <<= current_blockbits - COMPAT_BSIZE_SHIFT;
                osfs->os_bsize    = 1 << COMPAT_BSIZE_SHIFT;
        }
 
-       if (OBD_FAIL_CHECK_VALUE(OBD_FAIL_OST_ENOSPC,
+       if (CFS_FAIL_CHECK_VALUE(OBD_FAIL_OST_ENOSPC,
                                 ofd->ofd_lut.lut_lsd.lsd_osd_index)) {
                /* Reduce free blocks count near zero, but keep "used" intact */
                osfs->os_bavail -= osfs->os_bavail - 2;
@@ -906,6 +830,7 @@ static int ofd_echo_setattr(const struct lu_env *env, struct obd_export *exp,
        struct ldlm_resource *res;
        struct ofd_object *fo;
        struct lu_fid *fid = &oa->o_oi.oi_fid;
+       ktime_t kstart = ktime_get();
        int rc = 0;
 
        ENTRY;
@@ -949,7 +874,8 @@ static int ofd_echo_setattr(const struct lu_env *env, struct obd_export *exp,
        if (rc)
                GOTO(out_unlock, rc);
 
-       ofd_counter_incr(exp, LPROC_OFD_STATS_SETATTR, NULL, 1);
+       ofd_counter_incr(exp, LPROC_OFD_STATS_SETATTR, NULL,
+                        ktime_us_delta(ktime_get(), kstart));
        EXIT;
 out_unlock:
        ofd_object_put(env, fo);
@@ -962,10 +888,9 @@ out:
                 * for 2nd lu_object_find() waiting for the first reference
                 * to go... deadlock!
                 */
-               res = ldlm_resource_get(ns, NULL, &info->fti_resid,
-                                       LDLM_EXTENT, 0);
+               res = ldlm_resource_get(ns, &info->fti_resid, LDLM_EXTENT, 0);
                if (!IS_ERR(res)) {
-                       ldlm_res_lvbo_update(env, res, NULL, 0);
+                       ldlm_res_lvbo_update(res, NULL, 0);
                        ldlm_resource_putref(res);
                }
        }
@@ -1108,6 +1033,9 @@ static int ofd_echo_create(const struct lu_env *env, struct obd_export *exp,
 
        ENTRY;
 
+       if (ofd->ofd_lut.lut_no_create)
+               return -EPERM;
+
        ofd_info_init(env, exp);
 
        LASSERT(seq == FID_SEQ_ECHO);
@@ -1150,7 +1078,7 @@ static int ofd_echo_create(const struct lu_env *env, struct obd_export *exp,
        next_id = ofd_seq_last_oid(oseq) + 1;
        count = ofd_precreate_batch(ofd, (int)diff);
 
-       rc = ofd_precreate_objects(env, ofd, next_id, oseq, count, 0);
+       rc = ofd_precreate_objects(env, ofd, next_id, oseq, count, 0, false);
        if (rc < 0) {
                CERROR("%s: unable to precreate: rc = %d\n",
                       ofd_name(ofd), rc);
@@ -1252,8 +1180,7 @@ static int ofd_ioc_get_obj_version(const struct lu_env *env,
        int rc = 0;
 
        ENTRY;
-
-       if (!data->ioc_inlbuf2 || data->ioc_inllen2 != sizeof(version))
+       if (!data || !data->ioc_inlbuf2 || data->ioc_inllen2 != sizeof(version))
                GOTO(out, rc = -EINVAL);
 
        if (data->ioc_inlbuf1 && data->ioc_inllen1 == sizeof(fid)) {
@@ -1323,47 +1250,52 @@ static int ofd_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
        struct lu_env env;
        struct ofd_device *ofd = ofd_exp(exp);
        struct obd_device *obd = ofd_obd(ofd);
+       struct obd_ioctl_data *data;
        int rc;
 
        ENTRY;
-
-       CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
+       CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
+              obd->obd_name, cmd, len, karg, uarg);
        rc = lu_env_init(&env, LCT_DT_THREAD);
        if (rc)
                RETURN(rc);
 
+       /* handle commands that don't use @karg first */
+       rc = -EINVAL;
        switch (cmd) {
        case OBD_IOC_ABORT_RECOVERY:
-               CERROR("%s: aborting recovery\n", obd->obd_name);
+               LCONSOLE_WARN("%s: Aborting recovery\n", obd->obd_name);
                obd->obd_abort_recovery = 1;
                target_stop_recovery_thread(obd);
-               break;
+               GOTO(out, rc);
        case OBD_IOC_SYNC:
                CDEBUG(D_RPCTRACE, "syncing ost %s\n", obd->obd_name);
                rc = dt_sync(&env, ofd->ofd_osd);
-               break;
+               GOTO(out, rc);
        case OBD_IOC_SET_READONLY:
                rc = dt_sync(&env, ofd->ofd_osd);
                if (rc == 0)
                        rc = dt_ro(&env, ofd->ofd_osd);
-               break;
+               GOTO(out, rc);
+       }
+
+       if (unlikely(karg == NULL)) {
+               OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", rc = -EINVAL);
+               GOTO(out, rc);
+       }
+       data = karg;
+
+       switch (cmd) {
        case OBD_IOC_START_LFSCK: {
-               struct obd_ioctl_data *data = karg;
                struct lfsck_start_param lsp;
 
-               if (unlikely(!data)) {
-                       rc = -EINVAL;
-                       break;
-               }
-
                lsp.lsp_start = (struct lfsck_start *)(data->ioc_inlbuf1);
                lsp.lsp_index_valid = 0;
                rc = lfsck_start(&env, ofd->ofd_osd, &lsp);
                break;
        }
        case OBD_IOC_STOP_LFSCK: {
-               struct obd_ioctl_data *data = karg;
-               struct lfsck_stop      stop;
+               struct lfsck_stop stop;
 
                stop.ls_status = LS_STOPPED;
                /* Old lfsck utils may pass NULL @stop. */
@@ -1371,7 +1303,7 @@ static int ofd_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                        stop.ls_flags = 0;
                else
                        stop.ls_flags =
-                       ((struct lfsck_stop *)(data->ioc_inlbuf1))->ls_flags;
+                          ((struct lfsck_stop *)(data->ioc_inlbuf1))->ls_flags;
 
                rc = lfsck_stop(&env, ofd->ofd_osd, &stop);
                break;
@@ -1380,10 +1312,10 @@ static int ofd_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                rc = ofd_ioc_get_obj_version(&env, ofd, karg);
                break;
        default:
-               CERROR("%s: not supported cmd = %#x\n", obd->obd_name, cmd);
-               rc = -ENOTTY;
+               rc = OBD_IOC_ERROR(obd->obd_name, cmd, "unrecognized", -ENOTTY);
+               break;
        }
-
+out:
        lu_env_fini(&env);
        RETURN(rc);
 }
@@ -1407,26 +1339,6 @@ static int ofd_precleanup(struct obd_device *obd)
 }
 
 /**
- * Implementation of obd_ops::o_ping.
- *
- * This is OFD-specific part of OBD_PING request handling.
- * It controls Filter Modification Data (FMD) expiration each time PING is
- * received.
- *
- * \see  ofd_fmd_expire() and ofd_fmd.c for details
- *
- * \param[in] env      execution environment
- * \param[in] exp      OBD export of client
- *
- * \retval             0
- */
-static int ofd_ping(const struct lu_env *env, struct obd_export *exp)
-{
-       ofd_fmd_expire(exp);
-       return 0;
-}
-
-/**
  * Implementation of obd_ops::o_health_check.
  *
  * This function checks the OFD device health - ability to respond on
@@ -1434,9 +1346,8 @@ static int ofd_ping(const struct lu_env *env, struct obd_export *exp)
  * - get statfs from the OSD. It checks just responsiveness of
  *   bottom device
  * - do write attempt on bottom device to check it is fully operational and
- *   is not stuck. This is expensive method and requires special configuration
- *   option --enable-health-write while building Lustre, it is turned off
- *   by default.
+ *   is not stuck. This is expensive method and must be manually enabled
+ *   by setting the enable_health_write sysfs parameter.
  *
  * \param[in] nul      not used
  * \param[in] obd      OBD device of OFD
@@ -1449,9 +1360,8 @@ static int ofd_health_check(const struct lu_env *nul, struct obd_device *obd)
        struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev);
        struct ofd_thread_info *info;
        struct lu_env env;
-#ifdef USE_HEALTH_CHECK_WRITE
        struct thandle *th;
-#endif
+       int rc1 = 0;
        int rc = 0;
 
        /* obd_proc_read_health pass NULL env, we need real one */
@@ -1464,10 +1374,12 @@ static int ofd_health_check(const struct lu_env *nul, struct obd_device *obd)
        if (unlikely(rc))
                GOTO(out, rc);
 
-       if (info->fti_u.osfs.os_state & OS_STATE_READONLY)
+       if (info->fti_u.osfs.os_state & OS_STATFS_READONLY)
                GOTO(out, rc = -EROFS);
 
-#ifdef USE_HEALTH_CHECK_WRITE
+       if (!obd_enable_health_write)
+               goto out;
+
        OBD_ALLOC(info->fti_buf.lb_buf, PAGE_SIZE);
        if (!info->fti_buf.lb_buf)
                GOTO(out, rc = -ENOMEM);
@@ -1481,27 +1393,34 @@ static int ofd_health_check(const struct lu_env *nul, struct obd_device *obd)
 
        rc = dt_declare_record_write(&env, ofd->ofd_health_check_file,
                                     &info->fti_buf, info->fti_off, th);
-       if (rc == 0) {
-               th->th_sync = 1; /* sync IO is needed */
-               rc = dt_trans_start_local(&env, ofd->ofd_osd, th);
-               if (rc == 0)
-                       rc = dt_record_write(&env, ofd->ofd_health_check_file,
-                                            &info->fti_buf, &info->fti_off,
-                                            th);
-       }
-       dt_trans_stop(&env, ofd->ofd_osd, th);
+       if (rc)
+               goto out_stop;
+
+       th->th_sync = 1; /* sync IO is needed */
+       rc = dt_trans_start_local(&env, ofd->ofd_osd, th);
+
+       if (rc)
+               goto out_stop;
+
+       rc = dt_record_write(&env, ofd->ofd_health_check_file,
+                            &info->fti_buf, &info->fti_off,
+                            th);
+
+out_stop:
+       rc1 = dt_trans_stop(&env, ofd->ofd_osd, th);
+       rc = rc ? rc : rc1;
 
        OBD_FREE(info->fti_buf.lb_buf, PAGE_SIZE);
 
        CDEBUG(D_INFO, "write 1 page synchronously for checking io rc %d\n",
               rc);
-#endif
+
 out:
        lu_env_fini(&env);
        return !!rc;
 }
 
-struct obd_ops ofd_obd_ops = {
+const struct obd_ops ofd_obd_ops = {
        .o_owner                = THIS_MODULE,
        .o_connect              = ofd_obd_connect,
        .o_reconnect            = ofd_obd_reconnect,
@@ -1518,7 +1437,6 @@ struct obd_ops ofd_obd_ops = {
        .o_getattr              = ofd_echo_getattr,
        .o_iocontrol            = ofd_iocontrol,
        .o_precleanup           = ofd_precleanup,
-       .o_ping                 = ofd_ping,
        .o_health_check         = ofd_health_check,
        .o_set_info_async       = ofd_set_info_async,
        .o_get_info             = ofd_get_info,