diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 091530d..cbc93ea 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -508,7 +508,6 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
 	struct ceph_snap_context *snapc;
 	struct ceph_vino vino;
 	struct ceph_osd_request *req;
-	int num_ops = 1;
 	struct page **pages;
 	int num_pages;
 	u64 len;
@@ -516,9 +515,10 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
 	int flags;
 	int check_caps = 0;
 	int page_align;
-	int ret, i;
+	int ret;
 	struct timespec mtime = CURRENT_TIME;
 	loff_t pos = iocb->ki_pos;
+	struct iov_iter i;
 
 	if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
 		return -EROFS;
@@ -539,21 +539,20 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
 	flags = CEPH_OSD_FLAG_ORDERSNAP |
 		CEPH_OSD_FLAG_ONDISK |
 		CEPH_OSD_FLAG_WRITE;
-	num_ops++;	/* Also include a 'startsync' command. */
 
-	for (i = 0; i < nr_segs && count; i++) {
-		void __user *data = iov[i].iov_base;
-		size_t left;
+	iov_iter_init(&i, iov, nr_segs, count, 0);
+
+	for (iov_iter_count(&i) > 0) {
+		void __user *data = i.iov->iov_base + i.iov_offset;
+		u64 len = i.iov->iov_len - i.iov_offset;
 
-		left = min(count, iov[i].iov_len);
-more:
 		page_align = (unsigned long)data & ~PAGE_MASK;
-		len = left;
 
 		snapc = ci->i_snap_realm->cached_context;
 		vino = ceph_vino(inode);
 		req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
-					    vino, pos, &len, num_ops,
+					    vino, pos, &len,
+					    2, /* include a 'startsync' command */
 					    CEPH_OSD_OP_WRITE, flags, snapc,
 					    ci->i_truncate_seq,
 					    ci->i_truncate_size,
@@ -593,13 +592,8 @@ out:
 		if (ret == 0) {
 			pos += len;
 			written += len;
-			left -= len;
-			count -= len;
-			data += len;
-			if (left)
-				goto more;
+			iov_iter_advance(&i, (size_t)len);
 
-			ret = written;
 			if (pos > i_size_read(inode))
 				check_caps = ceph_inode_set_size(inode, pos);
 				if (check_caps)
@@ -607,14 +601,14 @@ out:
 							CHECK_CAPS_AUTHONLY,
 							NULL);
 		} else {
-			if (ret != -EOLDSNAPC && written > 0)
-				ret = written;
 			break;
 		}
 	}
 
-	if (ret > 0)
+	if (ret != -EOLDSNAPC && written > 0) {
 		iocb->ki_pos = pos;
+		ret = written;
+	}
 	return ret;
 }
 
@@ -636,10 +630,9 @@ static ssize_t ceph_sync_write(struct kiocb *iocb, const struct iovec *iov,
 	struct ceph_snap_context *snapc;
 	struct ceph_vino vino;
 	struct ceph_osd_request *req;
-	int num_ops = 1;
 	struct page **pages;
-	int num_pages;
 	u64 len;
+	int num_pages;
 	int written = 0;
 	int flags;
 	int check_caps = 0;
@@ -670,18 +663,14 @@ static ssize_t ceph_sync_write(struct kiocb *iocb, const struct iovec *iov,
 
 	iov_iter_init(&i, iov, nr_segs, count, 0);
 
-	while (i.count) {
-		void __user *data;
+	while ((len = iov_iter_count(&i)) > 0) {
 		size_t left;
-
-		left = i.count;
-more:
-		len = left;
+		int n;
 
 		snapc = ci->i_snap_realm->cached_context;
 		vino = ceph_vino(inode);
 		req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
-					    vino, pos, &len, num_ops,
+					    vino, pos, &len, 1,
 					    CEPH_OSD_OP_WRITE, flags, snapc,
 					    ci->i_truncate_seq,
 					    ci->i_truncate_size,
@@ -702,42 +691,17 @@ more:
 			ret = PTR_ERR(pages);
 			goto out;
 		}
-		if (len <= i.iov[0].iov_len - i.iov_offset) {
-			data = i.iov[0].iov_base + i.iov_offset;
-			ret = ceph_copy_user_to_page_vector(pages,
-							    data, 0, len);
 
-			if (ret > 0)
-				iov_iter_advance(&i, ret);
-		} else {
-			int l, k = 0, copyed = 0;
-			size_t tmp = len;
-
-			while (tmp) {
-				data = i.iov[0].iov_base + i.iov_offset;
-				l = i.iov[0].iov_len - i.iov_offset;
-
-				if (tmp < l) {
-					ret = ceph_copy_user_to_page_vector(&pages[k],
-									    data,
-									    copyed,
-									    tmp);
-					if (ret > 0)
-						iov_iter_advance(&i, ret);
-					break;
-				} else if (l) {
-					ret = ceph_copy_user_to_page_vector(&pages[k],
-									    data,
-									    copyed,
-									    l);
-					if (ret < 0)
-						break;
-					iov_iter_advance(&i, ret);
-					copyed += ret;
-					tmp -= ret;
-					k = calc_pages_for(0, copyed + 1) - 1;
-				}
+		left = len;
+		for (n = 0; n < num_pages; n++) {
+			size_t plen = min(left, PAGE_SIZE);
+			ret = iov_iter_copy_from_user(pages[n], &i, 0, l);
+			if (ret != plen) {
+				ret = -EFAULT;
+				break;
 			}
+			left -= ret;
+			iov_iter_advance(&i, ret);
 		}
 
 		if (ret < 0) {
@@ -764,26 +728,23 @@ out:
 		if (ret == 0) {
 			pos += len;
 			written += len;
-			left -= len;
-			if (left)
-				goto more;
 
-			ret = written;
-			if (pos > i_size_read(inode))
+			if (pos > i_size_read(inode)) {
 				check_caps = ceph_inode_set_size(inode, pos);
 				if (check_caps)
 					ceph_check_caps(ceph_inode(inode),
 							CHECK_CAPS_AUTHONLY,
 							NULL);
+			}
 		} else {
-			if (ret != -EOLDSNAPC && written > 0)
-				ret = written;
 			break;
 		}
 	}
 
-	if (ret > 0)
+	if (ret != -EOLDSNAPC && written > 0) {
+		ret = written;
 		iocb->ki_pos = pos;
+	}
 	return ret;
 }
 
