2006-10-05 05:39:29 +00:00
|
|
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
2007-06-01 19:51:31 +00:00
|
|
|
// vim: ts=8 sw=2 smarttab
|
2006-02-12 06:53:23 +00:00
|
|
|
/*
|
|
|
|
* Ceph - scalable distributed file system
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
|
|
|
|
*
|
2006-02-21 17:54:38 +00:00
|
|
|
* This is free software; you can redistribute it and/or
|
2006-02-12 06:53:23 +00:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
2006-02-21 17:54:38 +00:00
|
|
|
* License version 2.1, as published by the Free Software
|
|
|
|
* Foundation. See file COPYING.
|
2006-02-12 06:53:23 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2006-02-21 17:54:38 +00:00
|
|
|
|
2005-11-28 19:37:51 +00:00
|
|
|
#ifndef __EBOFS_ONODE_H
|
|
|
|
#define __EBOFS_ONODE_H
|
|
|
|
|
|
|
|
#include "include/lru.h"
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include "BufferCache.h"
|
|
|
|
|
2005-12-10 00:40:04 +00:00
|
|
|
#include "include/interval_set.h"
|
|
|
|
|
2008-11-20 21:22:37 +00:00
|
|
|
#include "include/nstring.h"
|
2005-12-10 00:40:04 +00:00
|
|
|
|
2005-12-06 01:11:02 +00:00
|
|
|
/*
|
|
|
|
* object node (like an inode)
|
|
|
|
*
|
|
|
|
* holds object metadata, including
|
|
|
|
* size
|
|
|
|
* allocation (extent list)
|
|
|
|
* attributes
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
struct ExtentCsum {
|
2008-01-11 01:16:27 +00:00
|
|
|
extent_t ex;
|
2007-12-19 18:16:22 +00:00
|
|
|
vector<csum_t> csum;
|
|
|
|
|
|
|
|
void resize_tail() {
|
|
|
|
unsigned old = csum.size();
|
|
|
|
csum.resize(ex.length);
|
|
|
|
for (block_t j=old; j<ex.length; j++)
|
|
|
|
csum[j] = 0;
|
|
|
|
}
|
|
|
|
void resize_head() {
|
|
|
|
if (ex.length < csum.size()) {
|
|
|
|
memmove(&csum[0], &csum[csum.size()-ex.length], ex.length*sizeof(csum_t));
|
|
|
|
csum.resize(ex.length);
|
|
|
|
} else if (ex.length > csum.size()) {
|
|
|
|
int old = csum.size();
|
|
|
|
csum.resize(ex.length);
|
|
|
|
memmove(&csum[ex.length-old], &csum[0], ex.length*sizeof(csum_t));
|
|
|
|
for (block_t b = 0; b<ex.length-old; b++)
|
|
|
|
csum[b] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
inline ostream& operator<<(ostream& out, ExtentCsum &ec) {
|
|
|
|
out << ec.ex;
|
|
|
|
out << '=';
|
|
|
|
out << hex << ec.csum << dec;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2005-11-28 19:37:51 +00:00
|
|
|
class Onode : public LRUObject {
|
|
|
|
private:
|
|
|
|
int ref;
|
|
|
|
|
|
|
|
public:
|
2007-12-19 18:16:22 +00:00
|
|
|
pobject_t object_id;
|
2005-12-14 21:22:45 +00:00
|
|
|
version_t version; // incremented on each modify.
|
2005-11-28 19:37:51 +00:00
|
|
|
|
|
|
|
// data
|
2008-01-11 01:16:27 +00:00
|
|
|
extent_t onode_loc;
|
2007-12-19 18:16:22 +00:00
|
|
|
epoch_t last_alloc_epoch; // epoch i last allocated for
|
|
|
|
|
2008-05-23 23:28:20 +00:00
|
|
|
__u64 object_size;
|
2007-12-19 18:16:22 +00:00
|
|
|
__u64 alloc_blocks, last_block;
|
|
|
|
csum_t data_csum;
|
|
|
|
bool readonly;
|
2005-11-28 19:37:51 +00:00
|
|
|
|
|
|
|
// onode
|
2006-07-26 20:44:47 +00:00
|
|
|
set<coll_t> collections;
|
2008-11-20 21:22:37 +00:00
|
|
|
map<nstring, bufferptr> attr;
|
2007-12-19 18:16:22 +00:00
|
|
|
|
|
|
|
map<block_t, ExtentCsum> extent_map;
|
2008-05-23 23:28:20 +00:00
|
|
|
interval_set<__u64> bad_byte_extents;
|
2005-11-28 19:37:51 +00:00
|
|
|
|
2005-12-10 00:40:04 +00:00
|
|
|
interval_set<block_t> uncommitted;
|
|
|
|
|
2005-11-28 19:37:51 +00:00
|
|
|
ObjectCache *oc;
|
|
|
|
|
2005-12-05 23:22:31 +00:00
|
|
|
bool dirty;
|
2005-12-18 08:27:55 +00:00
|
|
|
bool dangling; // not in onode_map
|
|
|
|
bool deleted; // deleted
|
2005-12-14 21:22:45 +00:00
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
//list<Context*> commit_waiters;
|
2005-11-28 19:37:51 +00:00
|
|
|
|
|
|
|
public:
|
2007-12-19 18:16:22 +00:00
|
|
|
Onode(pobject_t oid) : ref(0), object_id(oid), version(0), last_alloc_epoch(0),
|
|
|
|
object_size(0), alloc_blocks(0), last_block(0), data_csum(0),
|
|
|
|
readonly(0),
|
2007-09-29 00:17:34 +00:00
|
|
|
oc(0),
|
2006-12-01 21:44:02 +00:00
|
|
|
dirty(false), dangling(false), deleted(false) {
|
2008-08-06 18:15:41 +00:00
|
|
|
onode_loc.start = 0;
|
2006-10-05 05:39:29 +00:00
|
|
|
onode_loc.length = 0;
|
2005-11-28 19:37:51 +00:00
|
|
|
}
|
2005-12-03 19:18:33 +00:00
|
|
|
~Onode() {
|
2006-10-05 05:39:29 +00:00
|
|
|
if (oc) delete oc;
|
2005-12-03 19:18:33 +00:00
|
|
|
}
|
2005-11-28 19:37:51 +00:00
|
|
|
|
|
|
|
block_t get_onode_id() { return onode_loc.start; }
|
|
|
|
int get_onode_len() { return onode_loc.length; }
|
|
|
|
|
2005-12-14 21:22:45 +00:00
|
|
|
int get_ref_count() { return ref; }
|
2005-11-28 19:37:51 +00:00
|
|
|
void get() {
|
2006-10-05 05:39:29 +00:00
|
|
|
if (ref == 0) lru_pin();
|
|
|
|
ref++;
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << "ebofs.onode.get " << hex << object_id << dec << " " << ref << std::endl;
|
2005-11-28 19:37:51 +00:00
|
|
|
}
|
|
|
|
void put() {
|
2006-10-05 05:39:29 +00:00
|
|
|
ref--;
|
|
|
|
if (ref == 0) lru_unpin();
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << "ebofs.onode.put " << hex << object_id << dec << " " << ref << std::endl;
|
2005-11-28 19:37:51 +00:00
|
|
|
}
|
2005-12-05 23:22:31 +00:00
|
|
|
|
|
|
|
void mark_dirty() {
|
2006-10-05 05:39:29 +00:00
|
|
|
if (!dirty) {
|
|
|
|
dirty = true;
|
|
|
|
get();
|
|
|
|
}
|
2005-12-05 23:22:31 +00:00
|
|
|
}
|
|
|
|
void mark_clean() {
|
2006-10-05 05:39:29 +00:00
|
|
|
if (dirty) {
|
|
|
|
dirty = false;
|
|
|
|
put();
|
|
|
|
}
|
2005-12-05 23:22:31 +00:00
|
|
|
}
|
|
|
|
bool is_dirty() { return dirty; }
|
2005-12-18 08:27:55 +00:00
|
|
|
bool is_deleted() { return deleted; }
|
|
|
|
bool is_dangling() { return dangling; }
|
2005-12-05 23:22:31 +00:00
|
|
|
|
2005-12-03 19:54:56 +00:00
|
|
|
|
2007-01-17 23:02:29 +00:00
|
|
|
bool have_oc() {
|
|
|
|
return oc != 0;
|
|
|
|
}
|
2005-12-03 19:54:56 +00:00
|
|
|
ObjectCache *get_oc(BufferCache *bc) {
|
2006-10-05 05:39:29 +00:00
|
|
|
if (!oc) {
|
|
|
|
oc = new ObjectCache(object_id, this, bc);
|
|
|
|
oc->get();
|
|
|
|
get();
|
|
|
|
}
|
|
|
|
return oc;
|
2005-12-03 19:54:56 +00:00
|
|
|
}
|
|
|
|
void close_oc() {
|
2006-10-05 05:39:29 +00:00
|
|
|
if (oc) {
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << "close_oc on " << object_id << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
assert(oc->is_empty());
|
|
|
|
if (oc->put() == 0){
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << "************************* hosing oc" << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
delete oc;
|
|
|
|
}
|
|
|
|
oc = 0;
|
|
|
|
put();
|
|
|
|
}
|
2005-12-03 19:54:56 +00:00
|
|
|
}
|
|
|
|
|
2005-11-28 19:37:51 +00:00
|
|
|
|
2005-12-03 19:18:33 +00:00
|
|
|
// allocation
|
2005-12-14 05:19:22 +00:00
|
|
|
void verify_extents() {
|
2008-01-24 09:47:03 +00:00
|
|
|
if (0) { // do crazy stupid sanity checking
|
2007-12-19 18:16:22 +00:00
|
|
|
block_t count = 0, pos = 0;
|
2006-10-05 05:39:29 +00:00
|
|
|
interval_set<block_t> is;
|
2007-12-19 18:16:22 +00:00
|
|
|
csum_t csum = 0;
|
2006-10-05 05:39:29 +00:00
|
|
|
|
|
|
|
set<block_t> s;
|
2007-12-19 18:16:22 +00:00
|
|
|
//cout << "verify_extentsing. data_csum=" << hex << data_csum << dec << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
for (map<block_t,ExtentCsum>::iterator p = extent_map.begin();
|
2006-10-05 05:39:29 +00:00
|
|
|
p != extent_map.end();
|
|
|
|
p++) {
|
2007-12-19 18:16:22 +00:00
|
|
|
//cout << " verify_extents " << p->first << ": " << p->second << std::endl;
|
|
|
|
assert(pos == p->first);
|
|
|
|
pos += p->second.ex.length;
|
|
|
|
if (p->second.ex.start) {
|
|
|
|
count += p->second.ex.length;
|
|
|
|
for (unsigned j=0;j<p->second.ex.length;j++) {
|
|
|
|
assert(s.count(p->second.ex.start+j) == 0);
|
|
|
|
s.insert(p->second.ex.start+j);
|
|
|
|
csum += p->second.csum[j];
|
|
|
|
}
|
|
|
|
}
|
2006-10-05 05:39:29 +00:00
|
|
|
}
|
2007-12-19 18:16:22 +00:00
|
|
|
//cout << " verify_extents got csum " << hex << csum << " want " << data_csum << dec << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
|
|
|
|
assert(s.size() == count);
|
2007-12-19 18:16:22 +00:00
|
|
|
assert(count == alloc_blocks);
|
|
|
|
assert(pos == last_block);
|
|
|
|
assert(csum == data_csum);
|
2006-10-05 05:39:29 +00:00
|
|
|
}
|
2005-12-14 05:19:22 +00:00
|
|
|
}
|
2007-12-19 18:16:22 +00:00
|
|
|
|
|
|
|
csum_t *get_extent_csum_ptr(block_t offset, block_t len) {
|
|
|
|
map<block_t,ExtentCsum>::iterator p = extent_map.lower_bound(offset);
|
|
|
|
if (p == extent_map.end() || p->first > offset)
|
|
|
|
p--;
|
|
|
|
assert(p->first <= offset);
|
|
|
|
assert(p->second.ex.start != 0);
|
|
|
|
assert(offset+len <= p->first + p->second.ex.length);
|
|
|
|
return &p->second.csum[offset-p->first];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set_extent - adjust extent map.
|
|
|
|
* assume new extent will have csum of 0.
|
|
|
|
* factor clobbered extents out of csums.
|
|
|
|
*/
|
2008-01-11 01:16:27 +00:00
|
|
|
void set_extent(block_t offset, extent_t ex) {
|
2007-12-19 18:16:22 +00:00
|
|
|
//cout << "set_extent " << offset << " -> " << ex << " ... " << last_block << std::endl;
|
|
|
|
|
2006-10-05 05:39:29 +00:00
|
|
|
verify_extents();
|
|
|
|
|
|
|
|
// at the end?
|
2007-12-19 18:16:22 +00:00
|
|
|
if (offset == last_block) {
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << " appending " << ex << std::endl;
|
2007-12-19 18:16:22 +00:00
|
|
|
if (!extent_map.empty() &&
|
|
|
|
((extent_map.rbegin()->first &&
|
|
|
|
ex.start &&
|
|
|
|
extent_map.rbegin()->second.ex.end() == ex.start) ||
|
|
|
|
(!extent_map.rbegin()->first &&
|
|
|
|
!ex.start))) {
|
|
|
|
extent_map.rbegin()->second.ex.length += ex.length;
|
|
|
|
if (ex.start)
|
|
|
|
extent_map.rbegin()->second.resize_tail();
|
|
|
|
} else {
|
|
|
|
extent_map[last_block].ex = ex;
|
|
|
|
if (ex.start)
|
|
|
|
extent_map[last_block].resize_tail();
|
|
|
|
}
|
|
|
|
last_block += ex.length;
|
|
|
|
if (ex.start)
|
|
|
|
alloc_blocks += ex.length;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// past the end?
|
|
|
|
if (offset > last_block) {
|
|
|
|
if (ex.start) {
|
|
|
|
extent_map[last_block].ex.start = 0;
|
|
|
|
extent_map[last_block].ex.length = offset - last_block;
|
|
|
|
extent_map[offset].ex = ex;
|
|
|
|
extent_map[offset].resize_tail();
|
|
|
|
last_block = offset+ex.length;
|
|
|
|
alloc_blocks += ex.length;
|
|
|
|
} else {
|
|
|
|
// ignore attempt to set a trailing "hole"
|
|
|
|
}
|
2006-10-05 05:39:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
// remove any extent bits we overwrite
|
2006-10-05 05:39:29 +00:00
|
|
|
if (!extent_map.empty()) {
|
|
|
|
// preceeding extent?
|
2007-12-19 18:16:22 +00:00
|
|
|
map<block_t,ExtentCsum>::iterator p = extent_map.lower_bound(offset);
|
2006-10-05 05:39:29 +00:00
|
|
|
if (p != extent_map.begin()) {
|
|
|
|
p--;
|
2007-12-19 18:16:22 +00:00
|
|
|
ExtentCsum &left = p->second;
|
|
|
|
if (p->first + left.ex.length > offset) {
|
|
|
|
//cout << " preceeding left was " << left << std::endl;
|
|
|
|
block_t newlen = offset - p->first;
|
|
|
|
if (p->first + left.ex.length > offset+ex.length) {
|
|
|
|
// cutting chunk out of middle, add trailing bit
|
|
|
|
ExtentCsum &right = extent_map[offset+ex.length] = left;
|
|
|
|
right.ex.length -= offset+ex.length - p->first;
|
|
|
|
if (right.ex.start) {
|
|
|
|
right.ex.start += offset+ex.length - p->first;
|
|
|
|
alloc_blocks += right.ex.length;
|
|
|
|
right.resize_head();
|
|
|
|
for (unsigned j=0; j<right.ex.length; j++)
|
|
|
|
data_csum += right.csum[j];
|
|
|
|
}
|
|
|
|
//cout << " tail right is " << right << std::endl;
|
|
|
|
}
|
|
|
|
if (left.ex.start) {
|
|
|
|
alloc_blocks -= left.ex.length - newlen;
|
|
|
|
for (unsigned i=newlen; i<left.ex.length; i++)
|
|
|
|
data_csum -= left.csum[i];
|
|
|
|
}
|
|
|
|
left.ex.length = newlen; // cut tail off preceeding extent
|
|
|
|
if (left.ex.start)
|
|
|
|
left.resize_tail();
|
|
|
|
//cout << " preceeding left now " << left << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
}
|
|
|
|
p++;
|
2007-12-19 18:16:22 +00:00
|
|
|
}
|
2006-10-05 05:39:29 +00:00
|
|
|
|
|
|
|
// overlapping extents
|
|
|
|
while (p != extent_map.end() &&
|
|
|
|
p->first < offset + ex.length) {
|
2007-12-19 18:16:22 +00:00
|
|
|
map<block_t,ExtentCsum>::iterator next = p;
|
2006-10-05 05:39:29 +00:00
|
|
|
next++;
|
|
|
|
|
|
|
|
// completely subsumed?
|
2007-12-19 18:16:22 +00:00
|
|
|
ExtentCsum &o = p->second;
|
|
|
|
if (p->first + o.ex.length <= offset+ex.length) {
|
|
|
|
//cout << " erasing " << o << std::endl;
|
|
|
|
if (o.ex.start) {
|
|
|
|
alloc_blocks -= o.ex.length;
|
|
|
|
for (unsigned i=0; i<o.ex.length; i++)
|
|
|
|
data_csum -= o.csum[i];
|
|
|
|
}
|
2006-10-05 05:39:29 +00:00
|
|
|
extent_map.erase(p);
|
|
|
|
p = next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
// spans next extent, cut off head
|
|
|
|
ExtentCsum &n = extent_map[ offset+ex.length ] = o;
|
|
|
|
//cout << " cutting head off " << o;
|
|
|
|
unsigned overlap = offset+ex.length - p->first;
|
|
|
|
n.ex.length -= overlap;
|
|
|
|
if (n.ex.start) {
|
|
|
|
n.ex.start += overlap;
|
|
|
|
alloc_blocks -= overlap;
|
|
|
|
for (unsigned j=0; j<overlap; j++)
|
|
|
|
data_csum -= n.csum[j];
|
|
|
|
n.resize_head();
|
|
|
|
}
|
2006-10-05 05:39:29 +00:00
|
|
|
extent_map.erase(p);
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << ", now " << n << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
// add ourselves
|
|
|
|
ExtentCsum &n = extent_map[ offset ];
|
|
|
|
n.ex = ex;
|
|
|
|
if (ex.start) {
|
|
|
|
alloc_blocks += ex.length;
|
|
|
|
n.resize_tail();
|
|
|
|
}
|
2006-10-05 05:39:29 +00:00
|
|
|
|
|
|
|
// extend object?
|
2007-12-19 18:16:22 +00:00
|
|
|
if (offset + ex.length > last_block)
|
|
|
|
last_block = offset+ex.length;
|
2006-10-05 05:39:29 +00:00
|
|
|
|
|
|
|
verify_extents();
|
2005-12-10 00:40:04 +00:00
|
|
|
}
|
|
|
|
|
2008-01-11 01:16:27 +00:00
|
|
|
int truncate_extents(block_t len, vector<extent_t>& extra) {
|
2007-12-19 18:16:22 +00:00
|
|
|
//cout << " truncate to " << len << " .. last_block " << last_block << std::endl;
|
|
|
|
|
|
|
|
verify_extents();
|
|
|
|
|
|
|
|
map<block_t,ExtentCsum>::iterator p = extent_map.lower_bound(len);
|
|
|
|
if (p != extent_map.begin() &&
|
2008-07-23 16:16:13 +00:00
|
|
|
(p == extent_map.end() ||( p->first > len && p->first))) {
|
2007-12-19 18:16:22 +00:00
|
|
|
p--;
|
|
|
|
ExtentCsum &o = p->second;
|
|
|
|
if (o.ex.length > len - p->first) {
|
|
|
|
int newlen = len - p->first;
|
|
|
|
if (o.ex.start) {
|
2008-01-11 01:16:27 +00:00
|
|
|
extent_t ex;
|
2007-12-19 18:16:22 +00:00
|
|
|
ex.start = o.ex.start + newlen;
|
|
|
|
ex.length = o.ex.length - newlen;
|
|
|
|
//cout << " truncating ex " << p->second.ex << " to " << newlen << ", releasing " << ex << std::endl;
|
|
|
|
for (unsigned i=newlen; i<o.ex.length; i++)
|
|
|
|
data_csum -= o.csum[i];
|
|
|
|
o.ex.length = newlen;
|
|
|
|
o.resize_tail();
|
|
|
|
extra.push_back(ex);
|
|
|
|
alloc_blocks -= ex.length;
|
|
|
|
} else
|
|
|
|
o.ex.length = newlen;
|
|
|
|
assert(o.ex.length > 0);
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (p != extent_map.end()) {
|
|
|
|
assert(p->first >= len);
|
|
|
|
ExtentCsum &o = p->second;
|
|
|
|
if (o.ex.start) {
|
|
|
|
for (unsigned i=0; i<o.ex.length; i++)
|
|
|
|
data_csum -= o.csum[i];
|
|
|
|
extra.push_back(o.ex);
|
|
|
|
alloc_blocks -= o.ex.length;
|
|
|
|
}
|
|
|
|
map<block_t,ExtentCsum>::iterator n = p;
|
|
|
|
n++;
|
|
|
|
extent_map.erase(p);
|
|
|
|
p = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_block = len;
|
|
|
|
verify_extents();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-12-10 00:40:04 +00:00
|
|
|
|
|
|
|
/* map_extents(start, len, ls)
|
2007-12-19 18:16:22 +00:00
|
|
|
* map teh given page range into extents (and csums) on disk.
|
2005-12-10 00:40:04 +00:00
|
|
|
*/
|
2008-01-11 01:16:27 +00:00
|
|
|
int map_extents(block_t start, block_t len, vector<extent_t>& ls, vector<csum_t> *csum) {
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << "map_extents " << start << " " << len << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
verify_extents();
|
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
map<block_t,ExtentCsum>::iterator p;
|
2007-09-29 00:17:34 +00:00
|
|
|
|
|
|
|
// hack hack speed up common cases!
|
|
|
|
if (start == 0) {
|
|
|
|
p = extent_map.begin();
|
2007-12-19 18:16:22 +00:00
|
|
|
} else if (start+len == last_block && len == 1 && !extent_map.empty()) {
|
2007-09-29 00:17:34 +00:00
|
|
|
// append hack.
|
|
|
|
p = extent_map.end();
|
|
|
|
p--;
|
|
|
|
if (p->first < start) p++;
|
|
|
|
} else {
|
|
|
|
// normal
|
|
|
|
p = extent_map.lower_bound(start);
|
|
|
|
}
|
|
|
|
|
2006-10-05 05:39:29 +00:00
|
|
|
if (p != extent_map.begin() &&
|
2008-07-23 16:16:13 +00:00
|
|
|
(p == extent_map.end() || (p->first > start && p->first))) {
|
2006-10-05 05:39:29 +00:00
|
|
|
p--;
|
2007-12-19 18:16:22 +00:00
|
|
|
if (p->second.ex.length > start - p->first) {
|
2008-01-11 01:16:27 +00:00
|
|
|
extent_t ex;
|
2007-12-19 18:16:22 +00:00
|
|
|
int off = (start - p->first);
|
|
|
|
ex.length = MIN(len, p->second.ex.length - off);
|
|
|
|
if (p->second.ex.start) {
|
|
|
|
ex.start = p->second.ex.start + off;
|
|
|
|
if (csum)
|
|
|
|
for (unsigned i=off; i<ex.length; i++)
|
|
|
|
csum->push_back(p->second.csum[i]);
|
|
|
|
} else
|
|
|
|
ex.start = 0;
|
2006-10-05 05:39:29 +00:00
|
|
|
ls.push_back(ex);
|
|
|
|
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << " got (tail of?) " << p->second << " : " << ex << std::endl;
|
2006-10-05 05:39:29 +00:00
|
|
|
|
|
|
|
start += ex.length;
|
|
|
|
len -= ex.length;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (len > 0 &&
|
|
|
|
p != extent_map.end()) {
|
|
|
|
assert(p->first == start);
|
2007-12-19 18:16:22 +00:00
|
|
|
ExtentCsum e = p->second;
|
|
|
|
e.ex.length = MIN(len, e.ex.length);
|
|
|
|
ls.push_back(e.ex);
|
|
|
|
if (e.ex.start && csum)
|
|
|
|
for (unsigned i=0; i<e.ex.length; i++)
|
|
|
|
csum->push_back(p->second.csum[i]);
|
2007-08-25 20:22:10 +00:00
|
|
|
//cout << " got (head of?) " << p->second << " : " << ex << std::endl;
|
2007-12-19 18:16:22 +00:00
|
|
|
start += e.ex.length;
|
|
|
|
len -= e.ex.length;
|
2006-10-05 05:39:29 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2005-12-03 19:18:33 +00:00
|
|
|
}
|
|
|
|
|
2006-07-28 19:07:47 +00:00
|
|
|
|
2005-12-10 00:40:04 +00:00
|
|
|
|
|
|
|
/* map_alloc_regions(start, len, map)
|
|
|
|
* map range into regions that need to be (re)allocated on disk
|
|
|
|
* because they overlap "safe" (or unallocated) parts of the object
|
|
|
|
*/
|
2006-09-14 18:48:57 +00:00
|
|
|
/*
|
2005-12-10 00:40:04 +00:00
|
|
|
void map_alloc_regions(block_t start, block_t len,
|
2006-10-05 05:39:29 +00:00
|
|
|
interval_set<block_t>& alloc) {
|
|
|
|
interval_set<block_t> already_uncom;
|
2005-12-10 00:40:04 +00:00
|
|
|
|
2006-10-05 05:39:29 +00:00
|
|
|
alloc.insert(start, len); // start with whole range
|
|
|
|
already_uncom.intersection_of(alloc, uncommitted);
|
|
|
|
alloc.subtract(already_uncom); // take out the bits that aren't yet committed
|
2005-11-28 19:37:51 +00:00
|
|
|
}
|
2006-09-14 18:48:57 +00:00
|
|
|
*/
|
2005-12-10 00:40:04 +00:00
|
|
|
|
2007-12-19 18:16:22 +00:00
|
|
|
block_t get_first_block() {
|
|
|
|
if (!alloc_blocks) return 0;
|
|
|
|
map<block_t,ExtentCsum>::iterator p = extent_map.begin();
|
|
|
|
while (1) {
|
|
|
|
if (p->second.ex.start)
|
|
|
|
return p->second.ex.start;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
2005-12-10 00:40:04 +00:00
|
|
|
|
2005-11-28 19:37:51 +00:00
|
|
|
|
|
|
|
// pack/unpack
|
2007-12-19 18:16:22 +00:00
|
|
|
int get_ondisk_bytes() {
|
|
|
|
return sizeof(ebofs_onode) +
|
|
|
|
get_collection_bytes() +
|
|
|
|
get_attr_bytes() +
|
|
|
|
get_extent_bytes() +
|
|
|
|
get_bad_byte_bytes();
|
|
|
|
}
|
2006-06-27 17:27:57 +00:00
|
|
|
int get_collection_bytes() {
|
2006-10-05 05:39:29 +00:00
|
|
|
return sizeof(coll_t) * collections.size();
|
2006-06-27 17:27:57 +00:00
|
|
|
}
|
2005-11-28 19:37:51 +00:00
|
|
|
int get_attr_bytes() {
|
2006-10-05 05:39:29 +00:00
|
|
|
int s = 0;
|
2008-11-20 21:22:37 +00:00
|
|
|
for (map<nstring, bufferptr>::iterator i = attr.begin();
|
2006-10-05 05:39:29 +00:00
|
|
|
i != attr.end();
|
|
|
|
i++) {
|
|
|
|
s += i->first.length() + 1;
|
|
|
|
s += i->second.length() + sizeof(int);
|
|
|
|
}
|
|
|
|
return s;
|
2005-11-28 19:37:51 +00:00
|
|
|
}
|
|
|
|
int get_extent_bytes() {
|
2008-01-11 01:16:27 +00:00
|
|
|
return sizeof(extent_t) * extent_map.size() + sizeof(csum_t)*alloc_blocks;
|
2007-12-19 18:16:22 +00:00
|
|
|
}
|
|
|
|
int get_bad_byte_bytes() {
|
2008-01-11 01:16:27 +00:00
|
|
|
return sizeof(extent_t) * bad_byte_extents.m.size();
|
2005-11-28 19:37:51 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-12-03 19:18:33 +00:00
|
|
|
inline ostream& operator<<(ostream& out, Onode& on)
|
|
|
|
{
|
2005-12-18 08:27:55 +00:00
|
|
|
out << "onode(" << hex << on.object_id << dec << " len=" << on.object_size;
|
|
|
|
out << " ref=" << on.get_ref_count();
|
|
|
|
if (on.is_dirty()) out << " dirty";
|
|
|
|
if (on.is_dangling()) out << " dangling";
|
|
|
|
if (on.is_deleted()) out << " deleted";
|
2006-03-01 07:17:05 +00:00
|
|
|
out << " uncom=" << on.uncommitted;
|
2007-12-19 18:16:22 +00:00
|
|
|
if (!on.bad_byte_extents.empty()) out << " badbytes=" << on.bad_byte_extents;
|
2005-12-23 03:53:08 +00:00
|
|
|
// out << " " << &on;
|
2005-12-18 08:27:55 +00:00
|
|
|
out << ")";
|
2005-12-03 19:18:33 +00:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-28 19:37:51 +00:00
|
|
|
|
|
|
|
#endif
|