From: xie xingguo Date: Sat, 20 Feb 2016 07:33:27 +0000 (+0800) Subject: os/filestore: fix result code if sanity check failed during copy_range X-Git-Tag: v10.1.0~250^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9644df6ddd892d1aad241f8e981d76b49c2182a8;p=ceph.git os/filestore: fix result code if sanity check failed during copy_range According to Linux Man Page, the lseek() system call returns -1 and sets errno only if it indeed encouters some error. The problem here is if lseek64() returns a positive answer, which is not strictly equal to the expected answer however, then errno may not be set and we return success instead, which is wrong. This commit solves the above problem by checking against the returned value of lseek64(), if -1 then we reset result code to errno, otherwise we reset result code to -EINVAL to indicate that it is sanity check not passed is the real relevant issue. One more thing, as _do_copy_range() may return customized error code, caller shall not redirect result code to errno on failure, which is also shall be considered as wrong action. Fixes: #14827 Signed-off-by: xie xingguo --- diff --git a/src/os/filestore/FileStore.cc b/src/os/filestore/FileStore.cc index a35c78149777..581c72563f87 100644 --- a/src/os/filestore/FileStore.cc +++ b/src/os/filestore/FileStore.cc @@ -3381,7 +3381,6 @@ int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t uint64_t it_off = miter->first - srcoff + dstoff; r = _do_copy_range(from, to, miter->first, miter->second, it_off, true); if (r < 0) { - r = -errno; derr << "FileStore::_do_copy_range: copy error at " << miter->first << "~" << miter->second << " to " << it_off << ", " << cpp_strerror(r) << dendl; break; @@ -3470,13 +3469,19 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u actual = ::lseek64(from, srcoff, SEEK_SET); if (actual != (int64_t)srcoff) { - r = -errno; + if (actual < 0) + r = -errno; + else + r = -EINVAL; derr << "lseek64 to " << srcoff << " got " << cpp_strerror(r) << dendl; return r; } actual = ::lseek64(to, dstoff, SEEK_SET); if (actual != (int64_t)dstoff) { - r = -errno; + if (actual < 0) + r = -errno; + else + r = -EINVAL; derr << "lseek64 to " << dstoff << " got " << cpp_strerror(r) << dendl; return r; }