commit_thread.create();
finisher_thread.create();
- dout(1) << "mounted " << dev.get_num_blocks() << " blocks, " << nice_blocks(dev.get_num_blocks()) << endl;
+ dout(1) << "mounted " << dev.get_device_name() << " " << dev.get_num_blocks() << " blocks, " << nice_blocks(dev.get_num_blocks()) << endl;
mounted = true;
ebofs_lock.Unlock();
dev.close();
- dout(1) << "mkfs: " << dev.get_num_blocks() << " blocks, " << nice_blocks(dev.get_num_blocks()) << endl;
+ dout(1) << "mkfs: " << dev.get_device_name() << " " << dev.get_num_blocks() << " blocks, " << nice_blocks(dev.get_num_blocks()) << endl;
ebofs_lock.Unlock();
return 0;
}
int Ebofs::truncate(object_t oid, off_t size)
{
+ ebofs_lock.Lock();
dout(7) << "truncate " << hex << oid << dec << " size " << size << endl;
- assert(0);
+
+ Onode *on = get_onode(oid);
+ if (!on) {
+ ebofs_lock.Unlock();
+ return -ENOENT;
+ }
+
+ int r = 0;
+ if (size > on->object_size) {
+ r = -EINVAL; // whatever
+ }
+ else if (size < on->object_size) {
+ // change size
+ on->object_size = size;
+ dirty_onode(on);
+
+ // free blocks
+ block_t nblocks = 0;
+ if (size) nblocks = 1 + (size-1) / EBOFS_BLOCK_SIZE;
+ if (on->object_blocks > nblocks) {
+ vector<Extent> extra;
+ on->truncate_extents(nblocks, extra);
+ for (unsigned i=0; i<extra.size(); i++)
+ allocator.release(extra[i]);
+ }
+ }
+ else {
+ assert(size == on->object_size);
+ }
+
+ put_onode(on);
+ ebofs_lock.Unlock();
+ return r;
}
return 0;
}
+ int truncate_extents(block_t len, vector<Extent>& extra) {
+ verify_extents();
+
+ map<block_t,Extent>::iterator p = extent_map.lower_bound(len);
+ if (p != extent_map.begin() &&
+ (p == extent_map.end() || p->first > len && p->first)) {
+ p--;
+ if (p->second.length > len - p->first) {
+ Extent ex;
+ ex.start = p->second.start + (len - p->first);
+ ex.length = p->second.length - (len - p->first);
+ extra.push_back(ex);
+
+ p->second.length = len - p->first;
+ assert(p->second.length > 0);
+
+ //cout << " got (tail of?) " << p->second << " : " << ex << endl;
+ }
+ p++;
+ }
+
+ while (p != extent_map.end()) {
+ assert(p->first >= len);
+ extra.push_back(p->second);
+ map<block_t,Extent>::iterator n = p;
+ n++;
+ extent_map.erase(p);
+ p = n;
+ }
+
+ object_blocks = len;
+ verify_extents();
+ return 0;
+ }
+
/* map_alloc_regions(start, len, map)
* map range into regions that need to be (re)allocated on disk