From 0d3338c2d2271bbf6f4c7774ad175f7ee42d07f6 Mon Sep 17 00:00:00 2001 From: Matt Benjamin Date: Thu, 8 Aug 2019 16:21:24 -0400 Subject: [PATCH] rgw_file: dont deadlock in advance_mtime() Fixes: https://tracker.ceph.com/issues/41173 Signed-off-by: Matt Benjamin --- src/rgw/rgw_file.cc | 17 ++++++++++++----- src/rgw/rgw_file.h | 8 ++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index b1ae5773cb3..da6c487a2b4 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -589,7 +589,7 @@ namespace rgw { /* save attrs */ rgw_fh->encode_attrs(ux_key, ux_attrs); if (st) - rgw_fh->stat(st); + rgw_fh->stat(st, RGWFileHandle::FLAG_LOCKED); get<0>(mkr) = rgw_fh; } else { get<1>(mkr) = -EIO; @@ -720,7 +720,7 @@ namespace rgw { parent->set_ctime(real_clock::to_timespec(t)); } if (st) - (void) rgw_fh->stat(st); + (void) rgw_fh->stat(st, RGWFileHandle::FLAG_LOCKED); rgw_fh->set_etag(*(req.get_attr(RGW_ATTR_ETAG))); rgw_fh->set_acls(*(req.get_attr(RGW_ATTR_ACL))); @@ -1264,8 +1264,11 @@ namespace rgw { } bool initial_off; + char* mk{nullptr}; + if (likely(!! get(&offset))) { - initial_off = ! get(offset); + mk = const_cast(get(offset)); + initial_off = !mk; } else { initial_off = (*get(offset) == 0); } @@ -1478,10 +1481,14 @@ namespace rgw { } } - void RGWFileHandle::advance_mtime() { + void RGWFileHandle::advance_mtime(uint32_t flags) { /* intended for use on directories, fast-forward mtime so as to * ensure a new, higher value for the change attribute */ - lock_guard guard(mtx); + unique_lock uniq(mtx, std::defer_lock); + if (likely(! (flags & RGWFileHandle::FLAG_LOCKED))) { + uniq.lock(); + } + /* advance mtime only if stored mtime is older than the * configured namespace expiration */ auto now = real_clock::now(); diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index fa8dfa00d58..1600df5cf1e 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -238,7 +238,7 @@ namespace rgw { }; void clear_state(); - void advance_mtime(); + void advance_mtime(uint32_t flags = FLAG_NONE); boost::variant variant_type; @@ -436,7 +436,7 @@ namespace rgw { state.ctime = st->st_ctim; } - int stat(struct stat* st) { + int stat(struct stat* st, uint32_t flags = FLAG_NONE) { /* partial Unix attrs */ memset(st, 0, sizeof(struct stat)); st->st_dev = state.dev; @@ -450,7 +450,7 @@ namespace rgw { switch (fh.fh_type) { case RGW_FS_TYPE_DIRECTORY: /* virtual directories are always invalid */ - advance_mtime(); + advance_mtime(flags); st->st_nlink = state.nlink; break; case RGW_FS_TYPE_FILE: @@ -1077,7 +1077,7 @@ namespace rgw { fh_key fhk = parent->make_fhk(obj_name); lsubdout(get_context(), rgw, 10) - << __func__ << " lookup called on " + << __func__ << " called on " << parent->object_name() << " for " << key_name << " (" << obj_name << ")" << " -> " << fhk