]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: update truncate_pending on O_TRUNC; pass old_size on O_TRUNC open
authorSage Weil <sage.weil@dreamhost.com>
Fri, 19 Aug 2011 20:53:06 +0000 (13:53 -0700)
committerSage Weil <sage.weil@dreamhost.com>
Fri, 19 Aug 2011 20:53:06 +0000 (13:53 -0700)
We were missing truncate_pending++ in O_TRUNC path.  Use a common helper.

Pass old_size on O_TRUNC open.  (This was the real bug we worked around in
79db9fc509933429f4a8f4aca6d3da5517c43d1f.)

Only do an actual truncate if old_size > 0.

Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/client/Client.cc
src/include/ceph_fs.h
src/mds/Server.cc
src/mds/mdstypes.h

index 86773af6465546b66d449e63bf384f328cfe4913..c9975bc24d90ead4d47845b19c1dd8968d563efe 100644 (file)
@@ -4840,6 +4840,7 @@ int Client::_open(Inode *in, int flags, mode_t mode, Fh **fhp, int uid, int gid)
     req->set_filepath(path); 
     req->head.args.open.flags = flags & ~O_CREAT;
     req->head.args.open.mode = mode;
+    req->head.args.open.old_size = in->size;   // for O_TRUNC
     req->inode = in;
     result = make_request(req, uid, gid);
   }
index bfae4c6526f095bf09ad0e693c2e29a114278414..bea17f95bee0d2c4d67eb2fdecf7b3c34e1eb8d3 100644 (file)
@@ -395,6 +395,7 @@ union ceph_mds_request_args {
                __le32 object_size;
                __le32 file_replication;
                __le32 preferred;
+               __le64 old_size;             /* if O_TRUNC */
        } __attribute__ ((packed)) open;
        struct {
                __le32 flags;
index b3fc2228da084417fda7b03557def21e89eb7101..ab2d929f20439287443846c07671a0395f127cb0 100644 (file)
@@ -3100,16 +3100,12 @@ void Server::handle_client_setattr(MDRequest *mdr)
     pi->time_warp_seq++;   // maybe not a timewarp, but still a serialization point.
   if (mask & CEPH_SETATTR_SIZE) {
     if (truncating_smaller) {
-      pi->truncate_from = old_size;
-      pi->size = req->head.args.setattr.size;
-      pi->truncate_size = pi->size;
-      pi->truncate_seq++;
-      pi->truncate_pending++;
+      pi->truncate(old_size, req->head.args.setattr.size);
       le->metablob.add_truncate_start(cur->ino());
     } else {
       pi->size = req->head.args.setattr.size;
+      pi->rstat.rbytes = pi->size;
     }
-    pi->rstat.rbytes = pi->size;
     pi->mtime = now;
 
     // adjust client's max_size?
@@ -3147,16 +3143,20 @@ void Server::do_open_truncate(MDRequest *mdr, int cmode)
 
   dout(10) << "do_open_truncate " << *in << dendl;
 
+  mdr->ls = mdlog->get_current_segment();
+  EUpdate *le = new EUpdate(mdlog, "open_truncate");
+  mdlog->start_entry(le);
+
   // prepare
   inode_t *pi = in->project_inode();
   pi->mtime = pi->ctime = ceph_clock_now(g_ceph_context);
   pi->version = in->pre_dirty();
 
-  pi->truncate_from = pi->size;
-  pi->size = 0;
-  pi->rstat.rbytes = 0;
-  pi->truncate_size = 0;
-  pi->truncate_seq++;
+  uint64_t old_size = MAX(pi->size, mdr->client_request->head.args.open.old_size);
+  if (old_size > 0) {
+    pi->truncate(old_size, 0);
+    le->metablob.add_truncate_start(in->ino());
+  }
 
   bool changed_ranges = false;
   if (cmode & CEPH_FILE_MODE_WR) {
@@ -3166,10 +3166,6 @@ void Server::do_open_truncate(MDRequest *mdr, int cmode)
     changed_ranges = true;
   }
   
-  mdr->ls = mdlog->get_current_segment();
-  EUpdate *le = new EUpdate(mdlog, "open_truncate");
-  mdlog->start_entry(le);
-  le->metablob.add_truncate_start(in->ino());
   le->metablob.add_client_req(mdr->reqid, mdr->client_request->get_oldest_client_tid());
 
   mdcache->predirty_journal_parents(mdr, &le->metablob, in, 0, PREDIRTY_PRIMARY, false);
@@ -3184,7 +3180,7 @@ void Server::do_open_truncate(MDRequest *mdr, int cmode)
   LogSegment *ls = mds->mdlog->get_current_segment();
   ls->open_files.push_back(&in->item_open_file);
   
-  journal_and_reply(mdr, in, 0, le, new C_MDS_inode_update_finish(mds, mdr, in, true,
+  journal_and_reply(mdr, in, 0, le, new C_MDS_inode_update_finish(mds, mdr, in, old_size > 0,
                                                                  changed_ranges));
 }
 
index 4ec96c3820a3ddb937e42cf6efcfedd1c7897ce1..b607ee11485039a165fdafd21d7acf0144d19837 100644 (file)
@@ -430,6 +430,14 @@ struct inode_t {
   bool is_file()    const { return (mode & S_IFMT) == S_IFREG; }
 
   bool is_truncating() const { return (truncate_pending > 0); }
+  void truncate(uint64_t old_size, uint64_t new_size) {
+    truncate_from = old_size;
+    size = new_size;
+    rstat.rbytes = new_size;
+    truncate_size = size;
+    truncate_seq++;
+    truncate_pending++;
+  }
 
   uint64_t get_layout_size_increment() {
     return layout.fl_object_size * layout.fl_stripe_count;