From 0cce0a5e991b789c2ff31fb8c14b3925b0ffc2ee Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 2 Jun 2011 09:19:39 -0700 Subject: [PATCH] filestore: allow clone_range to different offsets The old OP_CLONERANGE would only clone a range of bytes at the same offset in both objects. Add an OP_CLONERANGE2 op code that adds a dst offset. Continue to support the old op code so that we can decode old transactions. Signed-off-by: Sage Weil --- src/os/FileStore.cc | 48 ++++++++++++++++++++++++++--------------- src/os/FileStore.h | 4 ++-- src/os/ObjectStore.h | 11 ++++++---- src/osd/ReplicatedPG.cc | 2 +- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc index 8aa1bafd4cfb6..fde1187b43f05 100644 --- a/src/os/FileStore.cc +++ b/src/os/FileStore.cc @@ -1308,7 +1308,7 @@ int FileStore::_detect_fs() // clone_range? if (g_conf.filestore_btrfs_clone_range) { btrfs_clone_range = true; - int r = _do_clone_range(fsid_fd, -1, 0, 1); + int r = _do_clone_range(fsid_fd, -1, 0, 1, 0); if (r == -EBADF) { dout(0) << "mount btrfs CLONE_RANGE ioctl is supported" << dendl; } else { @@ -2442,7 +2442,19 @@ unsigned FileStore::_do_transaction(Transaction& t) sobject_t noid = t.get_oid(); uint64_t off = t.get_length(); uint64_t len = t.get_length(); - r = _clone_range(cid, oid, noid, off, len); + r = _clone_range(cid, oid, noid, off, len, off); + } + break; + + case Transaction::OP_CLONERANGE2: + { + coll_t cid = t.get_cid(); + sobject_t oid = t.get_oid(); + sobject_t noid = t.get_oid(); + uint64_t srcoff = t.get_length(); + uint64_t len = t.get_length(); + uint64_t dstoff = t.get_length(); + r = _clone_range(cid, oid, noid, srcoff, len, dstoff); } break; @@ -2795,7 +2807,7 @@ int FileStore::_clone(coll_t cid, const sobject_t& oldoid, const sobject_t& newo struct stat st; ::fstat(o, &st); dout(10) << "clone " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " READ+WRITE" << dendl; - r = _do_clone_range(o, n, 0, st.st_size); + r = _do_clone_range(o, n, 0, st.st_size, 0); } if (r < 0) r = -errno; @@ -2808,28 +2820,28 @@ int FileStore::_clone(coll_t cid, const sobject_t& oldoid, const sobject_t& newo return 0; } -int FileStore::_do_clone_range(int from, int to, uint64_t off, uint64_t len) +int FileStore::_do_clone_range(int from, int to, uint64_t srcoff, uint64_t len, uint64_t dstoff) { - dout(20) << "_do_clone_range " << off << "~" << len << dendl; + dout(20) << "_do_clone_range " << srcoff << "~" << len << " to " << dstoff << dendl; int r = 0; if (btrfs_clone_range) { btrfs_ioctl_clone_range_args a; a.src_fd = from; - a.src_offset = off; + a.src_offset = srcoff; a.src_length = len; - a.dest_offset = off; + a.dest_offset = dstoff; r = ::ioctl(to, BTRFS_IOC_CLONE_RANGE, &a); if (r >= 0) return r; return -errno; } - ::lseek64(from, off, SEEK_SET); - ::lseek64(to, off, SEEK_SET); - - loff_t pos = off; - loff_t end = off + len; + ::lseek64(from, srcoff, SEEK_SET); + ::lseek64(to, dstoff, SEEK_SET); + + loff_t pos = srcoff; + loff_t end = srcoff + len; int buflen = 4096*32; char buf[buflen]; while (pos < end) { @@ -2865,13 +2877,14 @@ int FileStore::_do_clone_range(int from, int to, uint64_t off, uint64_t len) break; pos += r; } - dout(20) << "_do_clone_range " << off << "~" << len << " = " << r << dendl; + dout(20) << "_do_clone_range " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; return r; } -int FileStore::_clone_range(coll_t cid, const sobject_t& oldoid, const sobject_t& newoid, uint64_t off, uint64_t len) +int FileStore::_clone_range(coll_t cid, const sobject_t& oldoid, const sobject_t& newoid, + uint64_t srcoff, uint64_t len, uint64_t dstoff) { - dout(15) << "clone_range " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " " << off << "~" << len << dendl; + dout(15) << "clone_range " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " " << srcoff << "~" << len << " to " << dstoff << dendl; int r; int o, n; @@ -2885,12 +2898,13 @@ int FileStore::_clone_range(coll_t cid, const sobject_t& oldoid, const sobject_t r = -errno; goto out; } - r = _do_clone_range(o, n, off, len); + r = _do_clone_range(o, n, srcoff, len, dstoff); ::close(n); out: ::close(o); out2: - dout(10) << "clone_range " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " " << off << "~" << len << " = " << r << dendl; + dout(10) << "clone_range " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " " + << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; return r; } diff --git a/src/os/FileStore.h b/src/os/FileStore.h index 9f884bf283433..eaf20a8ef6790 100644 --- a/src/os/FileStore.h +++ b/src/os/FileStore.h @@ -293,8 +293,8 @@ public: int _zero(coll_t cid, const sobject_t& oid, uint64_t offset, size_t len); int _truncate(coll_t cid, const sobject_t& oid, uint64_t size); int _clone(coll_t cid, const sobject_t& oldoid, const sobject_t& newoid); - int _clone_range(coll_t cid, const sobject_t& oldoid, const sobject_t& newoid, uint64_t off, uint64_t len); - int _do_clone_range(int from, int to, uint64_t off, uint64_t len); + int _clone_range(coll_t cid, const sobject_t& oldoid, const sobject_t& newoid, uint64_t srcoff, uint64_t len, uint64_t dstoff); + int _do_clone_range(int from, int to, uint64_t srcoff, uint64_t len, uint64_t dstoff); int _remove(coll_t cid, const sobject_t& oid); void _start_sync(); diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h index 22f563f1be923..2ab80ef9d89b3 100644 --- a/src/os/ObjectStore.h +++ b/src/os/ObjectStore.h @@ -135,6 +135,7 @@ public: static const int OP_RMATTR = 16; // cid, oid, attrname static const int OP_CLONE = 17; // cid, oid, newoid static const int OP_CLONERANGE = 18; // cid, oid, newoid, offset, len + static const int OP_CLONERANGE2 = 30; // cid, oid, newoid, srcoff, len, dstoff static const int OP_TRIMCACHE = 19; // cid, oid, offset, len @@ -390,14 +391,16 @@ public: ::encode(noid, tbl); ops++; } - void clone_range(coll_t cid, const sobject_t& oid, sobject_t noid, uint64_t off, uint64_t len) { - __u32 op = OP_CLONERANGE; + void clone_range(coll_t cid, const sobject_t& oid, sobject_t noid, + uint64_t srcoff, uint64_t srclen, uint64_t dstoff) { + __u32 op = OP_CLONERANGE2; ::encode(op, tbl); ::encode(cid, tbl); ::encode(oid, tbl); ::encode(noid, tbl); - ::encode(off, tbl); - ::encode(len, tbl); + ::encode(srcoff, tbl); + ::encode(srclen, tbl); + ::encode(dstoff, tbl); ops++; } void create_collection(coll_t cid) { diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index ac071bd7b9f9b..4aba1de52c044 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -3985,7 +3985,7 @@ void ReplicatedPG::sub_op_push(MOSDSubOp *op) dout(15) << " clone_range " << p->first << " " << q.get_start() << "~" << q.get_len() << dendl; t->clone_range(coll, p->first, soid, - q.get_start(), q.get_len()); + q.get_start(), q.get_len(), q.get_start()); } } -- 2.39.5