+ return 0;
+}
+
+static void vvp_io_write_iter_fini(const struct lu_env *env,
+ const struct cl_io_slice *ios)
+{
+ struct vvp_io *vio = cl2vvp_io(env, ios);
+
+ LASSERT(vio->u.write.vui_queue.pl_nr == 0);
+}
+
+static int vvp_io_fault_iter_init(const struct lu_env *env,
+ const struct cl_io_slice *ios)
+{
+ struct vvp_io *vio = cl2vvp_io(env, ios);
+ struct inode *inode = vvp_object_inode(ios->cis_obj);
+
+ LASSERT(inode == file_inode(vio->vui_fd->fd_file));
+ vio->u.fault.ft_mtime = inode->i_mtime.tv_sec;
+
+ return 0;
+}
+
+static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios)
+{
+ struct cl_io *io = ios->cis_io;
+ struct cl_object *obj = io->ci_obj;
+ struct vvp_io *vio = cl2vvp_io(env, ios);
+ struct inode *inode = vvp_object_inode(obj);
+ int rc;
+
+ CLOBINVRNT(env, obj, vvp_object_invariant(obj));
+
+ CDEBUG(D_VFSTRACE, DFID" ignore/verify layout %d/%d, layout version %d "
+ "need write layout %d, restore needed %d\n",
+ PFID(lu_object_fid(&obj->co_lu)),
+ io->ci_ignore_layout, io->ci_verify_layout,
+ vio->vui_layout_gen, io->ci_need_write_intent,
+ io->ci_restore_needed);
+
+ if (io->ci_restore_needed) {
+ /* file was detected release, we need to restore it
+ * before finishing the io
+ */
+ rc = ll_layout_restore(inode, 0, OBD_OBJECT_EOF);
+ /* if restore registration failed, no restart,
+ * we will return -ENODATA */
+ /* The layout will change after restore, so we need to
+ * block on layout lock held by the MDT
+ * as MDT will not send new layout in lvb (see LU-3124)
+ * we have to explicitly fetch it, all this will be done
+ * by ll_layout_refresh()
+ */
+ if (rc == 0) {
+ io->ci_restore_needed = 0;
+ io->ci_need_restart = 1;
+ io->ci_verify_layout = 1;
+ } else {
+ io->ci_restore_needed = 1;
+ io->ci_need_restart = 0;
+ io->ci_verify_layout = 0;
+ io->ci_result = rc;
+ }
+ }
+
+ /**
+ * dynamic layout change needed, send layout intent
+ * RPC.
+ */
+ if (io->ci_need_write_intent) {
+ loff_t start = 0;
+ loff_t end = OBD_OBJECT_EOF;
+
+ io->ci_need_write_intent = 0;
+
+ LASSERT(io->ci_type == CIT_WRITE ||
+ cl_io_is_trunc(io) || cl_io_is_mkwrite(io));
+
+ if (io->ci_type == CIT_WRITE) {
+ if (!cl_io_is_append(io)) {
+ start = io->u.ci_rw.rw_range.cir_pos;
+ end = start + io->u.ci_rw.rw_range.cir_count;
+ }
+ } else if (cl_io_is_trunc(io)) {
+ end = io->u.ci_setattr.sa_attr.lvb_size;
+ } else { /* mkwrite */
+ pgoff_t index = io->u.ci_fault.ft_index;
+
+ start = cl_offset(io->ci_obj, index);
+ end = cl_offset(io->ci_obj, index + 1);
+ }
+
+ CDEBUG(D_VFSTRACE, DFID" write layout, type %u [%llu, %llu)\n",
+ PFID(lu_object_fid(&obj->co_lu)), io->ci_type,
+ start, end);
+ rc = ll_layout_write_intent(inode, start, end);
+ io->ci_result = rc;
+ if (!rc)
+ io->ci_need_restart = 1;
+ }
+
+ if (!io->ci_ignore_layout && io->ci_verify_layout) {
+ __u32 gen = 0;
+
+ /* check layout version */
+ ll_layout_refresh(inode, &gen);
+ io->ci_need_restart = vio->vui_layout_gen != gen;
+ if (io->ci_need_restart) {
+ CDEBUG(D_VFSTRACE,
+ DFID" layout changed from %d to %d.\n",
+ PFID(lu_object_fid(&obj->co_lu)),
+ vio->vui_layout_gen, gen);
+ /* today successful restore is the only possible
+ * case */
+ /* restore was done, clear restoring state */
+ ll_file_clear_flag(ll_i2info(vvp_object_inode(obj)),
+ LLIF_FILE_RESTORING);
+ }
+ }