+static int ofd_ioc_get_obj_version(const struct lu_env *env,
+ struct ofd_device *ofd, void *karg)
+{
+ struct obd_ioctl_data *data = karg;
+ struct lu_fid fid;
+ struct ofd_object *fo;
+ dt_obj_version_t version;
+ int rc = 0;
+
+ ENTRY;
+
+ if (data->ioc_inlbuf2 == NULL || data->ioc_inllen2 != sizeof(version))
+ GOTO(out, rc = -EINVAL);
+
+ if (data->ioc_inlbuf1 != NULL && data->ioc_inllen1 == sizeof(fid)) {
+ fid = *(struct lu_fid *)data->ioc_inlbuf1;
+ } else if (data->ioc_inlbuf3 != NULL &&
+ data->ioc_inllen3 == sizeof(__u64) &&
+ data->ioc_inlbuf4 != NULL &&
+ data->ioc_inllen4 == sizeof(__u64)) {
+ struct ost_id ostid;
+
+ ostid_set_seq(&ostid, *(__u64 *)data->ioc_inlbuf4);
+ ostid_set_id(&ostid, *(__u64 *)data->ioc_inlbuf3);
+ rc = ostid_to_fid(&fid, &ostid,
+ ofd->ofd_lut.lut_lsd.lsd_osd_index);
+ if (rc != 0)
+ GOTO(out, rc);
+ } else {
+ GOTO(out, rc = -EINVAL);
+ }
+
+ if (!fid_is_sane(&fid))
+ GOTO(out, rc = -EINVAL);
+
+ fo = ofd_object_find(env, ofd, &fid);
+ if (IS_ERR(fo))
+ GOTO(out, rc = PTR_ERR(fo));
+
+ if (!ofd_object_exists(fo))
+ GOTO(out_fo, rc = -ENOENT);
+
+ if (lu_object_remote(&fo->ofo_obj.do_lu))
+ GOTO(out_fo, rc = -EREMOTE);
+
+ version = dt_version_get(env, ofd_object_child(fo));
+ if (version == 0)
+ GOTO(out_fo, rc = -EIO);
+
+ *(dt_obj_version_t *)data->ioc_inlbuf2 = version;
+
+ EXIT;
+out_fo:
+ ofd_object_put(env, fo);
+out:
+ return rc;
+}
+