]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: Make truncation work properly
authorGreg Farnum <gregf@hq.newdream.net>
Thu, 26 Aug 2010 21:04:45 +0000 (14:04 -0700)
committerGreg Farnum <gregf@hq.newdream.net>
Thu, 16 Sep 2010 23:54:46 +0000 (16:54 -0700)
The previous if block didn't work because inode->size was usually
changed well before handle_cap_trunc was ever invoked, so it never
did the truncation in the objectcacher! This was okay if you just truncated
a file and then closed it, but if you wrote a file, truncated part of it out,
and then wrote past the (new) end you would get reads that returned
the previously-truncated data out of what should have been a hole.

Now, we do the actual objectcacher truncation in update_inode_file_bits,
because all methods of truncation will move through there and this maintains
proper ordering.

src/client/Client.cc

index ce15ebdfdef8bf9b238b68cb2cfe2ffba24e6eb9..d9fa6aa384006dee8f30614aa6ea04c44a5cb7b4 100644 (file)
@@ -357,6 +357,8 @@ void Client::update_inode_file_bits(Inode *in,
   dout(25) << "truncate_seq: mds " << truncate_seq <<  " local "
           << in->truncate_seq << " time_warp_seq: mds " << time_warp_seq
           << " local " << in->time_warp_seq << dendl;
+  uint64_t prior_size = in->size;
+
   if (truncate_seq > in->truncate_seq ||
       (truncate_seq == in->truncate_seq && size > in->size)) {
     dout(10) << "size " << in->size << " -> " << size << dendl;
@@ -375,6 +377,13 @@ void Client::update_inode_file_bits(Inode *in,
             << truncate_size << dendl;
     in->truncate_size = truncate_size;
     in->oset.truncate_size = truncate_size;
+    if (g_conf.client_oc) { //do actual truncation
+      vector<ObjectExtent> ls;
+      filer->file_to_extents(in->ino, &in->layout,
+                             truncate_size, prior_size - truncate_size,
+                             ls);
+      objectcacher->truncate_set(&in->oset, ls);
+    }
   }
   
   // be careful with size, mtime, atime
@@ -2619,18 +2628,13 @@ void Client::handle_cap_trunc(Inode *in, MClientCaps *m)
   dout(10) << "handle_cap_trunc on ino " << *in
           << " size " << in->size << " -> " << m->get_size()
           << dendl;
-  // trim filecache?
-  if (g_conf.client_oc &&
-      m->get_size() < in->size) {
-    // map range to objects
-    vector<ObjectExtent> ls;
-    filer->file_to_extents(in->ino, &in->layout, 
-                          m->get_size(), in->size - m->get_size(),
-                          ls);
-    objectcacher->truncate_set(&in->oset, ls);
-  }
   
-  in->reported_size = in->size = m->get_size(); 
+  int implemented = 0;
+  int issued = in->caps_issued(&implemented) | in->caps_dirty();
+  issued |= implemented;
+  update_inode_file_bits(in, m->get_truncate_seq(), m->get_truncate_size(),
+                         m->get_size(), m->get_time_warp_seq(), m->get_ctime(),
+                         m->get_mtime(), m->get_atime(), issued);
   m->put();
 }