+ * FLR: verify the layout version of object.
+ *
+ * \param[in] env execution environment
+ * \param[in] fo OFD object
+ * \param[in] oa OBDO structure with layout version
+ *
+ * \retval 0 on successful verification
+ * \retval -EINPROGRESS layout version is in transfer
+ * \retval -ESTALE the layout version on client is stale
+ */
+int ofd_verify_layout_version(const struct lu_env *env,
+ struct ofd_object *fo, const struct obdo *oa)
+{
+ int rc;
+ ENTRY;
+
+ if (unlikely(CFS_FAIL_CHECK(OBD_FAIL_OST_SKIP_LV_CHECK)))
+ GOTO(out, rc = 0);
+
+ rc = ofd_object_ff_load(env, fo);
+ if (rc < 0) {
+ if (rc == -ENODATA)
+ rc = 0;
+ GOTO(out, rc);
+ }
+
+ /**
+ * this update is not legitimate, whose layout version is older than
+ * that on the disk.
+ */
+ if (ofd_layout_version_less(oa->o_layout_version,
+ fo->ofo_ff.ff_layout_version))
+ GOTO(out, rc = -ESTALE);
+
+out:
+ CDEBUG(D_INODE, DFID " verify layout version: %u vs. %u/%u: rc = %d\n",
+ PFID(lu_object_fid(&fo->ofo_obj.do_lu)),
+ oa->o_layout_version, fo->ofo_ff.ff_layout_version,
+ fo->ofo_ff.ff_range, rc);
+ RETURN(rc);
+
+}
+
+/*
+ * Handle multiple attrs at once:
+ *
+ * Lazy ATIME update to refresh atime every ofd_atime_diff
+ * seconds so that external scanning tool can see it actual
+ * within that period and be able to identify accessed files
+ *
+ * Update enc flag on OST object
+ * OSD layer will find out if this is really necessary.
+ */
+static void ofd_handle_attrs(const struct lu_env *env, struct ofd_device *ofd,
+ struct ofd_object *fo, struct obdo *oa)
+{
+ bool need_atime = (oa->o_valid & OBD_MD_FLATIME);
+ bool need_encfl = (oa->o_valid & OBD_MD_FLFLAGS &&
+ oa->o_flags & LUSTRE_ENCRYPT_FL);
+ struct lu_attr *la;
+ struct dt_object *o;
+ struct thandle *th;
+ int rc;
+
+ if (need_atime && ofd->ofd_atime_diff == 0)
+ need_atime = false;
+
+ if (need_encfl && CFS_FAIL_CHECK(OBD_FAIL_LFSCK_NO_ENCFLAG))
+ need_encfl = false;
+
+ if (!need_atime && !need_encfl)
+ return;
+
+ la = &ofd_info(env)->fti_attr2;
+ o = ofd_object_child(fo);
+
+ if (need_atime) {
+ if (unlikely(fo->ofo_atime_ondisk == 0)) {
+ rc = dt_attr_get(env, o, la);
+ if (unlikely(rc)) {
+ need_atime = false;
+ GOTO(trans, rc);
+ }
+ LASSERT(la->la_valid & LA_ATIME);
+ if (la->la_atime == 0)
+ la->la_atime = la->la_mtime;
+ fo->ofo_atime_ondisk = la->la_atime;
+ }
+ if (oa->o_atime - fo->ofo_atime_ondisk < ofd->ofd_atime_diff) {
+ need_atime = false;
+ GOTO(trans, rc = 0);
+ }
+
+ /* atime hasn't been updated too long, update it */
+ fo->ofo_atime_ondisk = oa->o_atime;
+ }
+
+trans:
+ if (!need_atime && !need_encfl)
+ return;
+
+ th = ofd_trans_create(env, ofd);
+ if (IS_ERR(th)) {
+ CERROR("%s: cannot create transaction: rc = %d\n",
+ ofd_name(ofd), (int)PTR_ERR(th));
+ return;
+ }
+
+ la->la_valid = 0;
+ if (need_atime) {
+ la->la_valid |= LA_ATIME;
+ la->la_atime = fo->ofo_atime_ondisk;
+ }
+ if (need_encfl) {
+ la->la_valid |= LA_FLAGS;
+ la->la_flags = LUSTRE_ENCRYPT_FL;
+ }
+
+ rc = dt_declare_attr_set(env, o, la, th);
+ if (rc)
+ GOTO(out_tx, rc);
+
+ rc = dt_trans_start_local(env, ofd->ofd_osd , th);
+ if (rc) {
+ CERROR("%s: cannot start transaction: rc = %d\n",
+ ofd_name(ofd), rc);
+ GOTO(out_tx, rc);
+ }
+
+ ofd_read_lock(env, fo);
+ if (ofd_object_exists(fo))
+ rc = dt_attr_set(env, o, la, th);
+ ofd_read_unlock(env, fo);
+
+out_tx:
+ ofd_trans_stop(env, ofd, th, rc);
+}
+
+/**