From ac248f1a0045abe0b66ee9bf00160d6ff7015b01 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 19 Aug 2011 13:53:06 -0700 Subject: [PATCH] mds: update truncate_pending on O_TRUNC; pass old_size on O_TRUNC open 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 --- src/client/Client.cc | 1 + src/include/ceph_fs.h | 1 + src/mds/Server.cc | 28 ++++++++++++---------------- src/mds/mdstypes.h | 8 ++++++++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 86773af646554..c9975bc24d90e 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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); } diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index bfae4c6526f09..bea17f95bee0d 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -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; diff --git a/src/mds/Server.cc b/src/mds/Server.cc index b3fc2228da084..ab2d929f20439 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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)); } diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 4ec96c3820a3d..b607ee1148503 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -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; -- 2.39.5