summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-10-11 14:03:13 +0800
committerYan, Zheng <zheng.z.yan@intel.com>2013-10-11 14:26:47 +0800
commitb9e2aab80707b22e617a4a0ec337d75f6ccefa8d (patch)
tree49f0f621a7035791450bc7af36d75bd5f0c56294
parentcb9ebd6f363fb571ecb770eab9ab1313cb407108 (diff)
downloadceph-b9e2aab80707b22e617a4a0ec337d75f6ccefa8d.tar.gz
mds: avoid leaking objects after purging file.wip-truncate2
The filer implementation does not delete stripe objects that are truncated to zero. When purging a deleted file, we need to purge stripe objects up to the max size the file has ever been. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
-rw-r--r--src/mds/MDCache.cc8
-rw-r--r--src/mds/mdstypes.cc5
-rw-r--r--src/mds/mdstypes.h6
3 files changed, 15 insertions, 4 deletions
diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc
index 9dc1229fbb9..d3980b3766b 100644
--- a/src/mds/MDCache.cc
+++ b/src/mds/MDCache.cc
@@ -9354,8 +9354,12 @@ void MDCache::purge_stray(CDentry *dn)
if (in->is_file()) {
uint64_t period = (uint64_t)in->inode.layout.fl_object_size *
(uint64_t)in->inode.layout.fl_stripe_count;
- uint64_t cur_max_size = in->inode.get_max_size();
- uint64_t to = MAX(in->inode.size, cur_max_size);
+ uint64_t to = in->inode.get_max_size();
+ to = MAX(in->inode.size, to);
+ // when truncating a file, the filer does not delete stripe objects that are
+ // truncated to zero. so we need to purge stripe objects up to the max size
+ // the file has ever been.
+ to = MAX(in->inode.max_size_ever, to);
if (to && period) {
uint64_t num = (to + period - 1) / period;
dout(10) << "purge_stray 0~" << to << " objects 0~" << num
diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc
index 6886786f27e..362f74774c4 100644
--- a/src/mds/mdstypes.cc
+++ b/src/mds/mdstypes.cc
@@ -204,7 +204,7 @@ ostream& operator<<(ostream& out, const client_writeable_range_t& r)
*/
void inode_t::encode(bufferlist &bl) const
{
- ENCODE_START(7, 6, bl);
+ ENCODE_START(8, 6, bl);
::encode(ino, bl);
::encode(rdev, bl);
@@ -238,6 +238,7 @@ void inode_t::encode(bufferlist &bl) const
::encode(xattr_version, bl);
::encode(backtrace_version, bl);
::encode(old_pools, bl);
+ ::encode(max_size_ever, bl);
ENCODE_FINISH(bl);
}
@@ -294,6 +295,8 @@ void inode_t::decode(bufferlist::iterator &p)
::decode(backtrace_version, p);
if (struct_v >= 7)
::decode(old_pools, p);
+ if (struct_v >= 8)
+ ::decode(max_size_ever, p);
DECODE_FINISH(p);
}
diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h
index 2a3874818b7..bd53c85b48d 100644
--- a/src/mds/mdstypes.h
+++ b/src/mds/mdstypes.h
@@ -329,6 +329,7 @@ struct inode_t {
ceph_file_layout layout;
vector <int64_t> old_pools;
uint64_t size; // on directory, # dentries
+ uint64_t max_size_ever; // max size the file has ever been
uint32_t truncate_seq;
uint64_t truncate_size, truncate_from;
uint32_t truncate_pending;
@@ -353,7 +354,8 @@ struct inode_t {
inode_t() : ino(0), rdev(0),
mode(0), uid(0), gid(0),
nlink(0), anchored(false),
- size(0), truncate_seq(0), truncate_size(0), truncate_from(0),
+ size(0), max_size_ever(0),
+ truncate_seq(0), truncate_size(0), truncate_from(0),
truncate_pending(0),
time_warp_seq(0),
version(0), file_data_version(0), xattr_version(0), backtrace_version(0) {
@@ -369,6 +371,8 @@ struct inode_t {
bool is_truncating() const { return (truncate_pending > 0); }
void truncate(uint64_t old_size, uint64_t new_size) {
assert(new_size < old_size);
+ if (old_size > max_size_ever)
+ max_size_ever = old_size;
truncate_from = old_size;
size = new_size;
rstat.rbytes = new_size;