diff options
author | Yan, Zheng <zyan@redhat.com> | 2017-08-14 05:50:50 +0300 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2017-09-06 20:56:47 +0300 |
commit | a5cd74ad388c1318554e24820b77ce335a27e0ef (patch) | |
tree | 97781934d5c34dd1b6dec0afb6867e7939004c45 /fs/ceph/file.c | |
parent | 5d37ca1480a70f437e4c425ee5723c760cf6afac (diff) | |
download | linux-a5cd74ad388c1318554e24820b77ce335a27e0ef.tar.xz |
ceph: fix -EOLDSNAPC handling
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>
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r-- | fs/ceph/file.c | 17 |
1 files 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 @@ retry_snap: &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 @@ retry_snap: 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); } |