From: Haomai Wang Date: Tue, 25 Nov 2014 05:44:43 +0000 (+0800) Subject: FileStore: Fix _do_sparse_copy_range don't truncate zero sections X-Git-Tag: v0.91~54^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cabb57a23a736b031ddb015ac99084dc3ca6ac16;p=ceph.git FileStore: Fix _do_sparse_copy_range don't truncate zero sections If calling clone_range and zero filled sections is at the ending of src range, the target fd won't write zero filled sections. If target's origin size shorter than needed, it will cause inconsistence between two fd's desired range. Signed-off-by: Haomai Wang --- diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc index dd12cf125ab4..285b63dc1137 100644 --- a/src/os/FileStore.cc +++ b/src/os/FileStore.cc @@ -3183,6 +3183,7 @@ int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t extent->fe_logical = srcoff; } + int64_t written = 0; uint64_t i = 0; while (i < fiemap->fm_mapped_extents) { @@ -3256,18 +3257,23 @@ int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t op += (r-op); } if (r < 0) - break; + goto out; pos += r; } + written += end; i++; extent++; } - if (r >= 0 && m_filestore_sloppy_crc) { - int rc = backend->_crc_update_clone_range(from, to, srcoff, len, dstoff); - assert(rc >= 0); + if (r >= 0) { + r = written; + if (m_filestore_sloppy_crc) { + int rc = backend->_crc_update_clone_range(from, to, srcoff, len, dstoff); + assert(rc >= 0); + } } + out: dout(20) << __func__ << " " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; return r; } @@ -3353,6 +3359,7 @@ int FileStore::_clone_range(coll_t cid, const ghobject_t& oldoid, const ghobject int r; FDRef o, n; + struct stat st; r = lfn_open(cid, oldoid, false, &o); if (r < 0) { goto out2; @@ -3362,10 +3369,30 @@ int FileStore::_clone_range(coll_t cid, const ghobject_t& oldoid, const ghobject goto out; } r = _do_clone_range(**o, **n, srcoff, len, dstoff); + if (r < 0) { + r = -errno; + goto out3; + } + + r = ::fstat(**n, &st); + if (r < 0) { + r = -errno; + derr << __func__ << ": fstat error at " << **n << " "<< cpp_strerror(r) << dendl; + goto out3; + } + if (st.st_size < (int)(dstoff + len)) { + r = ::ftruncate(**n, dstoff + len); + if (r < 0) { + r = -errno; + derr << __func__ << ": ftruncate error at " << dstoff + len << ", " << cpp_strerror(r) << dendl; + goto out3; + } + } // clone is non-idempotent; record our work. _set_replay_guard(**n, spos, &newoid); + out3: lfn_close(n); out: lfn_close(o);