]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix truncate bug
authorSage Weil <sage@newdream.net>
Mon, 2 Mar 2009 23:19:20 +0000 (15:19 -0800)
committerSage Weil <sage@newdream.net>
Tue, 3 Mar 2009 00:38:15 +0000 (16:38 -0800)
Use consistent conditional value to determine whether it is a
forward truncation or not.  Otherwise we get out of sync before vs
after journaling...

src/mds/MDCache.cc
src/mds/Server.cc

index 8ac83388fd2b367ac494bd4499c7108d9d024b20..ae0939937e4996171d1dfbcb52ab3b2263164061 100644 (file)
@@ -4123,7 +4123,7 @@ void MDCache::_truncate_inode(CInode *in, LogSegment *ls)
     snapc = &nullsnap;
     assert(in->last == CEPH_NOSNAP);
   }
-  dout(10) << "truncate_inode snapc " << snapc << " on " << *in << dendl;
+  dout(10) << "_truncate_inode  snapc " << snapc << " on " << *in << dendl;
   mds->filer->truncate(in->inode.ino, &in->inode.layout, *snapc,
                       pi->truncate_size, pi->truncate_from-pi->truncate_size, pi->truncate_seq, 0,
                       0, new C_MDC_TruncateFinish(this, in, ls));
index 41f40d81ca2e11cd60c578c0b6fb021ac6597e2d..8440b5d4e081d58d94266f231a89a59ff68b9da9 100644 (file)
@@ -4800,9 +4800,10 @@ class C_MDS_truncate_logged : public Context {
   MDS *mds;
   MDRequest *mdr;
   CInode *in;
+  bool smaller;
 public:
-  C_MDS_truncate_logged(MDS *m, MDRequest *r, CInode *i) :
-    mds(m), mdr(r), in(i) {}
+  C_MDS_truncate_logged(MDS *m, MDRequest *r, CInode *i, bool sm) :
+    mds(m), mdr(r), in(i), smaller(sm) {}
   void finish(int r) {
     assert(r == 0);
 
@@ -4812,7 +4813,7 @@ public:
 
     // notify any clients
     mds->locker->issue_truncate(in);
-    if (in->inode.is_truncating())
+    if (smaller && in->inode.is_truncating())
       mds->mdcache->truncate_inode(in, mdr->ls);
 
     mds->balancer->hit_inode(mdr->now, in, META_POP_IWR);   
@@ -4833,7 +4834,8 @@ void Server::handle_client_truncate(MDRequest *mdr)
   CInode *cur = rdlock_path_pin_ref(mdr, true);
   if (!cur) return;
 
-  dout(10) << "handle_client_truncate " << req->head.args.truncate.length << " on " << *cur << dendl;
+  dout(10) << "handle_client_truncate " << cur->get_projected_inode()->size << " -> " << req->head.args.truncate.length
+          << " on " << *cur << dendl;
 
   if (mdr->ref_snapid != CEPH_NOSNAP) {
     reply_request(mdr, -EINVAL);
@@ -4858,10 +4860,14 @@ void Server::handle_client_truncate(MDRequest *mdr)
     return;
   }
 
-  if (old_size > req->head.args.truncate.length && pi->is_truncating()) {
+  // trunc from bigger -> smaller
+  bool smaller = req->head.args.truncate.length < old_size;
+
+  if (smaller && pi->is_truncating()) {
     dout(10) << " waiting for pending truncate from " << pi->truncate_from
             << " to " << pi->truncate_size << " to complete on " << *cur << dendl;
     cur->add_waiter(CInode::WAIT_TRUNC, new C_MDS_RetryRequest(mdcache, mdr));
+    mds->mdlog->flush();
     return;
   }
 
@@ -4876,7 +4882,7 @@ void Server::handle_client_truncate(MDRequest *mdr)
   pi->mtime = ctime;
   pi->ctime = ctime;
   pi->version = pdv;
-  if (old_size > req->head.args.truncate.length) {
+  if (smaller) {
     // truncate to smaller size
     pi->truncate_from = old_size;
     pi->size = req->head.args.truncate.length;
@@ -4892,7 +4898,7 @@ void Server::handle_client_truncate(MDRequest *mdr)
   mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
   mdcache->journal_dirty_inode(mdr, &le->metablob, cur);
   
-  journal_and_reply(mdr, cur, 0, le, new C_MDS_truncate_logged(mds, mdr, cur));
+  journal_and_reply(mdr, cur, 0, le, new C_MDS_truncate_logged(mds, mdr, cur, smaller));
 }
 
 
@@ -5066,7 +5072,7 @@ void Server::handle_client_opent(MDRequest *mdr, int cmode)
   LogSegment *ls = mds->mdlog->get_current_segment();
   ls->open_files.push_back(&in->xlist_open_file);
   
-  journal_and_reply(mdr, in, 0, le, new C_MDS_truncate_logged(mds, mdr, in));
+  journal_and_reply(mdr, in, 0, le, new C_MDS_truncate_logged(mds, mdr, in, true));
 }