From: "Yan, Zheng" <zyan@redhat.com>
Date: Mon, 14 Aug 2017 10:50:50 +0800
Subject: ceph: fix -EOLDSNAPC handling
Git-commit: a5cd74ad388c1318554e24820b77ce335a27e0ef
Patch-mainline: v4.14-rc1
References: FATE#324714
Need to drop cap reference before retry. Besides, it's better to
redo file write checks for each retry because we re-lock inode.
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Acked-by: Luis Henriques <lhenriques@suse.com>
---
fs/ceph/file.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 0e8986c69639..1ce80f66e9e5 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1309,6 +1309,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (!prealloc_cf)
return -ENOMEM;
+retry_snap:
inode_lock(inode);
/* We can write back this queue in page reclaim */
@@ -1340,7 +1341,6 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
goto out;
}
-retry_snap:
/* FIXME: not complete since it doesn't account for being at quota */
if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
err = -ENOSPC;
@@ -1389,14 +1389,6 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
&prealloc_cf);
else
written = ceph_sync_write(iocb, &data, pos, snapc);
- if (written == -EOLDSNAPC) {
- dout("aio_write %p %llx.%llx %llu~%u"
- "got EOLDSNAPC, retrying\n",
- inode, ceph_vinop(inode),
- pos, (unsigned)count);
- inode_lock(inode);
- goto retry_snap;
- }
if (written > 0)
iov_iter_advance(from, written);
ceph_put_snap_context(snapc);
@@ -1430,10 +1422,15 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
ceph_cap_string(got));
ceph_put_cap_refs(ci, got);
+ if (written == -EOLDSNAPC) {
+ dout("aio_write %p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n",
+ inode, ceph_vinop(inode), pos, (unsigned)count);
+ goto retry_snap;
+ }
+
if (written >= 0) {
if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_NEARFULL))
iocb->ki_flags |= IOCB_DSYNC;
-
written = generic_write_sync(iocb, written);
}