Whamcloud - gitweb
LU-13377 llite: fix dead loop for short write
[fs/lustre-release.git] / lustre / llite / vvp_io.c
index 94f9899..98bc985 100644 (file)
@@ -1181,6 +1181,7 @@ static int vvp_io_write_start(const struct lu_env *env,
        size_t                   cnt = io->u.ci_wr.wr.crw_count;
        bool                     lock_inode = !IS_NOSEC(inode);
        size_t nob = io->ci_nob;
+       struct iov_iter iter;
        size_t written = 0;
 
        ENTRY;
@@ -1243,6 +1244,7 @@ static int vvp_io_write_start(const struct lu_env *env,
                 * trucates, etc. is handled in the higher layers of lustre.
                 */
                lock_inode = !IS_NOSEC(inode);
+               iter = *vio->vui_iter;
 
                if (unlikely(lock_inode))
                        inode_lock(inode);
@@ -1269,12 +1271,20 @@ static int vvp_io_write_start(const struct lu_env *env,
 
        if (result > 0) {
                result = vvp_io_write_commit(env, io);
+               /* Simulate short commit */
+               if (CFS_FAULT_CHECK(OBD_FAIL_LLITE_SHORT_COMMIT)) {
+                       vio->u.write.vui_written >>= 1;
+                       if (vio->u.write.vui_written > 0)
+                               io->ci_need_restart = 1;
+               }
                if (vio->u.write.vui_written > 0) {
                        result = vio->u.write.vui_written;
                        CDEBUG(D_VFSTRACE, "%s: write nob %zd, result: %zd\n",
                                file_dentry(file)->d_name.name,
                                io->ci_nob, result);
                        io->ci_nob += result;
+               } else {
+                       io->ci_continue = 0;
                }
        }
        if (vio->vui_iocb->ki_pos != (pos + io->ci_nob - nob)) {
@@ -1284,8 +1294,16 @@ static int vvp_io_write_start(const struct lu_env *env,
                       file_dentry(file)->d_name.name,
                       vio->vui_iocb->ki_pos, pos + io->ci_nob - nob,
                       written, io->ci_nob - nob, result);
-               /* rewind ki_pos to where it has successfully committed */
+               /*
+                * Rewind ki_pos and vui_iter to where it has
+                * successfully committed.
+                */
                vio->vui_iocb->ki_pos = pos + io->ci_nob - nob;
+               iov_iter_advance(&iter, io->ci_nob - nob);
+               vio->vui_iter->iov = iter.iov;
+               vio->vui_iter->nr_segs = iter.nr_segs;
+               vio->vui_iter->iov_offset = iter.iov_offset;
+               vio->vui_iter->count = iter.count;
        }
        if (result > 0 || result == -EIOCBQUEUED) {
                ll_file_set_flag(ll_i2info(inode), LLIF_DATA_MODIFIED);