From e8ec0c427bba241444c46d40c6dec7011c5ff78e Mon Sep 17 00:00:00 2001 From: sageweil Date: Fri, 23 Nov 2007 23:50:04 +0000 Subject: [PATCH] fixed bufferlist c_ptr() weirdness with ebofs buffer duping git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@2115 29311d96-e01e-0410-9327-a35deaab8ce9 --- trunk/ceph/ebofs/Ebofs.cc | 6 ++-- trunk/ceph/include/buffer.h | 55 ++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/trunk/ceph/ebofs/Ebofs.cc b/trunk/ceph/ebofs/Ebofs.cc index b1f6ab7539467..92d92482869b9 100644 --- a/trunk/ceph/ebofs/Ebofs.cc +++ b/trunk/ceph/ebofs/Ebofs.cc @@ -1682,9 +1682,8 @@ void Ebofs::apply_write(Onode *on, off_t off, size_t len, const bufferlist& bl) bufferlist sb; sb.substr_of(bl, blpos, len_in_bh-z); // substr in existing buffer - bufferlist cp; - cp.append(sb.c_str(), len_in_bh-z); // copy the partial bit! - bh->add_partial(off_in_bh, cp); + sb.rebuild(); // recopy into properly sized buffer, so that we drop references to user buffer + bh->add_partial(off_in_bh, sb); left -= len_in_bh-z; blpos += len_in_bh-z; opos += len_in_bh-z; @@ -1726,7 +1725,6 @@ void Ebofs::apply_write(Onode *on, off_t off, size_t len, const bufferlist& bl) bc.bh_queue_partial_write(on, bh); // queue the eventual write } - } else { assert(bh->is_clean() || bh->is_dirty() || bh->is_tx()); diff --git a/trunk/ceph/include/buffer.h b/trunk/ceph/include/buffer.h index 5e48b6ce91bf6..6b34240f7eb4c 100644 --- a/trunk/ceph/include/buffer.h +++ b/trunk/ceph/include/buffer.h @@ -287,13 +287,16 @@ public: return _raw->clone(); } + void clone_in_place() { + raw *newraw = _raw->clone(); + release(); + newraw->nref++; + _raw = newraw; + } bool do_cow() { if (_raw->nref > 1) { //std::cout << "doing cow on " << _raw << " len " << _len << std::endl; - raw *newraw = _raw->clone(); - release(); - newraw->nref++; - _raw = newraw; + clone_in_place(); return true; } else return false; @@ -642,6 +645,33 @@ public: it++) it->zero(); } + void do_cow() { + for (std::list::iterator it = _buffers.begin(); + it != _buffers.end(); + it++) + it->do_cow(); + } + void clone_in_place() { + for (std::list::iterator it = _buffers.begin(); + it != _buffers.end(); + it++) + it->clone_in_place(); + } + + + void rebuild() { + ptr nb(_len); + unsigned pos = 0; + for (std::list::iterator it = _buffers.begin(); + it != _buffers.end(); + it++) { + nb.copy_in(pos, it->length(), it->c_str()); + pos += it->length(); + } + _buffers.clear(); + _buffers.push_back(nb); + } + // sort-of-like-assignment-op void claim(list& bl) { @@ -777,19 +807,12 @@ public: * return a contiguous ptr to whole bufferlist contents. */ char *c_str() { - if (_buffers.size() == 1) { - return _buffers.front().c_str(); // good, we're already contiguous. - } - else if (_buffers.size() == 0) { + if (_buffers.size() == 0) return 0; // no buffers - } - else { - ptr newbuf = create(length()); // make one new contiguous buffer. - copy(0, length(), newbuf.c_str()); // copy myself into it. - clear(); - push_back(newbuf); - return newbuf.c_str(); // now it'll work. - } + if (_buffers.size() > 1) + rebuild(); + assert(_buffers.size() == 1); + return _buffers.front().c_str(); // good, we're already contiguous. } void substr_of(const list& other, unsigned off, unsigned len) { -- 2.39.5