https://tracker.ceph.com/
https://tracker.ceph.com/favicon.ico
2020-12-10T15:15:15Z
Ceph
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=181060
2020-12-10T15:15:15Z
Backport Bot
<ul><li><strong>Copied from</strong> <i><a class="issue tracker-1 status-3 priority-4 priority-default closed" href="/issues/48410">Bug #48410</a>: rgw_file: common_prefixes returned out of lexical order</i> added</li></ul>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182186
2021-01-08T17:51:14Z
Nathan Cutler
ncutler@suse.cz
<ul><li><strong>Status</strong> changed from <i>New</i> to <i>Need More Info</i></li><li><strong>Assignee</strong> set to <i>Matt Benjamin</i></li></ul><p>non-trivial conflicts</p>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182188
2021-01-08T17:53:57Z
Matt Benjamin
mbenjamin@redhat.com
<ul></ul><p>commit c587ceb1a5408db9a428818bd029ac5bdf88b183<br />Author: Matt Benjamin <<a class="email" href="mailto:mbenjamin@redhat.com">mbenjamin@redhat.com</a>><br />Date: Tue Dec 1 07:53:56 2020 -0500</p>
<pre><code>rgw_file: return common_prefixes in lexical order</code></pre>
<pre><code>Since inception RGWReaddirRequest has sent all leaf objects first<br /> (in lexical order), then common_prefixes (in lexical order). In<br /> hindsight, an overall listing could trivially be returned out of<br /> lexical order, which can cause continued listing of large, mixed<br /> directories to fail.</code></pre>
<pre><code>RCA by Dan Gryniewicz.</code></pre>
<pre><code>Fixes: <a class="external" href="https://tracker.ceph.com/issues/48410">https://tracker.ceph.com/issues/48410</a><br /> Resolves: rhbz#1878250</code></pre>
<pre><code>Signed-off-by: Matt Benjamin &lt;<a class="email" href="mailto:mbenjamin@redhat.com">mbenjamin@redhat.com</a>&gt;<br /> (cherry picked from commit e561e98e5cca2678854e01c990f95e474022b7ed)</code></pre>
<p>diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h<br />index 7cdd7e1ff24..8987aeb6ab1 100644<br />--- a/src/rgw/rgw_file.h<br />+++ b/src/rgw/rgw_file.h<br /><code>@ -1559,94 +1559,191 </code>@ public:</p>
<pre><code>void send_response() override {<br /> struct req_state* s = get_state();<br />- for (const auto& iter : objs) {<br />+ auto cnow = real_clock::now();</code></pre>
<p>- boost::string_ref sref {iter.key.name};<br />+ /* enumerate objs and common_prefixes in parallel,<br />+ * avoiding increment on and end iterator, which is<br />+ * undefined */</p>
<p>- lsubdout(cct, rgw, 15) << "readdir objects prefix: " << prefix<br />- << " obj: " << sref << dendl;<br />+ class DirIterator<br />+ {<br />+ vector<rgw_bucket_dir_entry>& objs;<br />+ vector<rgw_bucket_dir_entry>::iterator obj_iter;</p>
<p>- size_t last_del = sref.find_last_of('/');<br />- if (last_del != string::npos)<br />- sref.remove_prefix(last_del+1);<br />+ map<string, bool>& common_prefixes;<br />+ map<string, bool>::iterator cp_iter;</p>
<p>- /* leaf directory? */<br />- if (sref.empty())<br />- continue;<br />+ boost::optional<boost::string_ref> obj_sref;<br />+ boost::optional<boost::string_ref> cp_sref;<br />+ bool _skip_cp;</p>
<p>- lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />- << <i>func</i> << " " <br />- << "list uri=" << s->relative_uri << " " <br />- << " prefix=" << prefix << " " <br />- << " obj path=" << iter.key.name<br />- << " (" << sref << ")" << "" <br />- << " mtime=" <br />- << real_clock::to_time_t(iter.meta.mtime)<br />- << " size=" << iter.meta.accounted_size<br />- << dendl;<br />+ public:</p>
<p>- if (! this->operator()(sref, next_marker, iter.meta.mtime,<br />- iter.meta.accounted_size, RGW_FS_TYPE_FILE)) {<br />- /* caller cannot accept more */<br />- lsubdout(cct, rgw, 5) << "readdir rcb failed" <br />- << " dirent=" << sref.data()<br />- << " call count=" << ix<br />- << dendl;<br />- rcb_eof = true;<br />- return;<br />+ DirIterator(vector<rgw_bucket_dir_entry>& objs,<br />+ map<string, bool>& common_prefixes)<br />+ : objs(objs), common_prefixes(common_prefixes), _skip_cp(false)<br />+ {<br />+ obj_iter = objs.begin();<br />+ parse_obj();<br />+ cp_iter = common_prefixes.begin();<br />+ parse_cp();<br />+ }<br /><ins><br /></ins> bool is_obj() {<br />+ return (obj_iter != objs.end());<br /> }<br />- ++ix;<br />- }</p>
<p>- auto cnow = real_clock::now();<br />- for (auto& iter : common_prefixes) {<br />+ bool is_cp(){<br />+ return (cp_iter != common_prefixes.end());<br />+ }</p>
<p>- lsubdout(cct, rgw, 15) << "readdir common prefixes prefix: " << prefix<br />- << " iter first: " << iter.first<br />- << " iter second: " << iter.second<br />- << dendl;<br />+ bool eof() {<br />+ return ((!is_obj()) && (!is_cp()));<br />+ }</p>
<p>- /* XXX aieee--I have seen this case! <strong>/<br />- if (iter.first == "/")<br />- continue;<br />+ void parse_obj() {<br />+ if (is_obj()) {<br />+ boost::string_ref sref{obj_iter->key.name};<br />+ size_t last_del = sref.find_last_of('/');<br />+ if (last_del != string::npos)<br />+ sref.remove_prefix(last_del+1);<br />+ obj_sref = sref;<br />+ }<br />+ } /</strong> parse_obj */</p>
<p>- /* it's safest to modify the element in place--a suffix-modifying<br />- * string_ref operation is problematic since ULP rgw_file callers<br />- * will ultimately need a c-string */<br />- if (iter.first.back() '/')<br />- const_cast&lt;std::string&&gt;(iter.first).pop_back();<br />+ void next_obj() {<br />+ +<ins>obj_iter;<br /></ins> parse_obj();<br />+ }</p>
<p>- boost::string_ref sref{iter.first};<br />+ void parse_cp() {<br />+ if (is_cp()) {<br />+ /* leading-/ skip case <strong>/<br />+ if (cp_iter->first "/") {<br />+ _skip_cp = true;<br />+ return;<br />+ } else<br />+ _skip_cp = false;<br /><ins><br /></ins> /</strong> it's safest to modify the element in place--a suffix-modifying<br />+ * string_ref operation is problematic since ULP rgw_file callers<br />+ * will ultimately need a c-string <strong>/<br />+ if (cp_iter->first.back() == '/')<br />+ const_cast<std::string&>(cp_iter->first).pop_back();<br /><ins><br /></ins> boost::string_ref sref{cp_iter->first};<br />+ size_t last_del = sref.find_last_of('/');<br />+ if (last_del != string::npos)<br />+ sref.remove_prefix(last_del+1);<br />+ cp_sref = sref;<br />+ } /</strong> is_cp <strong>/<br />+ } /</strong> parse_cp */<br /><ins><br /></ins> void next_cp() {<br />+ +<ins>cp_iter;<br /></ins> parse_cp();<br />+ }</p>
<p>- size_t last_del = sref.find_last_of('/');<br />- if (last_del != string::npos)<br />- sref.remove_prefix(last_del+1);<br />+ bool skip_cp() {<br />+ return _skip_cp;<br />+ }</p>
<p>- lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />- << <i>func</i> << " " <br />- << "list uri=" << s->relative_uri << " " <br />- << " prefix=" << prefix << " " <br />- << " cpref=" << sref<br />- << dendl;<br />+ bool entry_is_obj() {<br />+ return (is_obj() &&<br />+ ((! is_cp()) ||<br />+ (obj_sref.get() < cp_sref.get())));<br />+ }</p>
<p>- if (sref.empty()) {<br />- /* null path segment--could be created in S3 but has no NFS<br />- * interpretation */<br />- return;<br />+ boost::string_ref get_obj_sref() {<br />+ return obj_sref.get();<br /> }</p>
<p>- if (! this->operator()(sref, next_marker, cnow, 0,<br />- RGW_FS_TYPE_DIRECTORY)) {<br />- /* caller cannot accept more <strong>/<br />- lsubdout(cct, rgw, 5) << "readdir rcb failed" <br />- << " dirent=" << sref.data()<br />- << " call count=" << ix<br />- << dendl;<br />- rcb_eof = true;<br />- return;<br />+ boost::string_ref get_cp_sref() {<br />+ return cp_sref.get();<br /> }<br />- +<ins>ix;<br />- }<br /></ins><br />+ vector<rgw_bucket_dir_entry>::iterator& get_obj_iter() {<br />+ return obj_iter;<br />+ }<br /><ins><br /></ins> map<string, bool>::iterator& get_cp_iter() {<br />+ return cp_iter;<br />+ }<br /><ins><br /></ins> }; /</strong> DirIterator <strong>/<br /><ins><br /></ins> DirIterator di{objs, common_prefixes};<br /><ins><br /></ins> for (;;) {<br /><ins><br /></ins> if (di.eof()) {<br />+ break; // done<br />+ }<br /><ins><br /></ins> /</strong> assert: one of is_obj() || is_cp() holds <strong>/<br />+ if (di.entry_is_obj()) {<br />+ auto sref = di.get_obj_sref();<br />+ if (sref.empty()) {<br />+ /</strong> recursive list of a leaf dir (iirc), do nothing <strong>/<br />+ } else {<br />+ /</strong> send a file entry <strong>/<br />+ auto obj_entry = *(di.get_obj_iter());<br /><ins><br /></ins> lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />+ << <i>func</i> << " " <br />+ << "list uri=" << s->relative_uri << " " <br />+ << " prefix=" << prefix << " " <br />+ << " obj path=" << obj_entry.key.name<br />+ << " (" << sref << ")" << "" <br />+ << " mtime=" <br />+ << real_clock::to_time_t(obj_entry.meta.mtime)<br />+ << " size=" << obj_entry.meta.accounted_size<br />+ << dendl;<br /><ins><br /></ins> if (! this->operator()(sref, next_marker, obj_entry.meta.mtime,<br />+ obj_entry.meta.accounted_size,<br />+ RGW_FS_TYPE_FILE)) {<br />+ /</strong> caller cannot accept more <strong>/<br />+ lsubdout(cct, rgw, 5) << "readdir rcb caller signalled stop" <br />+ << " dirent=" << sref.data()<br />+ << " call count=" << ix<br />+ << dendl;<br />+ rcb_eof = true;<br />+ return;<br />+ }<br />+ }<br />+ di.next_obj(); // and advance object<br />+ } else {<br />+ /</strong> send a dir entry <strong>/<br />+ if (! di.skip_cp()) {<br />+ auto sref = di.get_cp_sref();<br /><ins><br /></ins> lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />+ << <i>func</i> << " " <br />+ << "list uri=" << s->relative_uri << " " <br />+ << " prefix=" << prefix << " " <br />+ << " cpref=" << sref<br />+ << dendl;<br /><ins><br /></ins> if (sref.empty()) {<br />+ /</strong> null path segment--could be created in S3 but has no NFS<br />+ * interpretation <strong>/<br />+ } else {<br />+ if (! this->operator()(sref, next_marker, cnow, 0,<br />+ RGW_FS_TYPE_DIRECTORY)) {<br />+ /</strong> caller cannot accept more <strong>/<br />+ lsubdout(cct, rgw, 5) << "readdir rcb caller signalled stop" <br />+ << " dirent=" << sref.data()<br />+ << " call count=" << ix<br />+ << dendl;<br />+ rcb_eof = true;<br />+ return;<br />+ }<br />+ }<br />+ }<br />+ di.next_cp(); // and advance common_prefixes<br />+ } /</strong> ! di.entry_is_obj() <strong>/<br />+ } /</strong> for (;;) */<br /> }</p>
<pre><code>virtual void send_versioned_response() {</code></pre>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182190
2021-01-08T17:54:30Z
Matt Benjamin
mbenjamin@redhat.com
<ul></ul><p>""" <br />commit c587ceb1a5408db9a428818bd029ac5bdf88b183<br />Author: Matt Benjamin <<a class="email" href="mailto:mbenjamin@redhat.com">mbenjamin@redhat.com</a>><br />Date: Tue Dec 1 07:53:56 2020 -0500</p>
<pre><code>rgw_file: return common_prefixes in lexical order</code></pre>
<pre><code>Since inception RGWReaddirRequest has sent all leaf objects first<br /> (in lexical order), then common_prefixes (in lexical order). In<br /> hindsight, an overall listing could trivially be returned out of<br /> lexical order, which can cause continued listing of large, mixed<br /> directories to fail.</code></pre>
<pre><code>RCA by Dan Gryniewicz.</code></pre>
<pre><code>Fixes: <a class="external" href="https://tracker.ceph.com/issues/48410">https://tracker.ceph.com/issues/48410</a><br /> Resolves: rhbz#1878250</code></pre>
<pre><code>Signed-off-by: Matt Benjamin &lt;<a class="email" href="mailto:mbenjamin@redhat.com">mbenjamin@redhat.com</a>&gt;<br /> (cherry picked from commit e561e98e5cca2678854e01c990f95e474022b7ed)</code></pre>
<p>diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h<br />index 7cdd7e1ff24..8987aeb6ab1 100644<br />--- a/src/rgw/rgw_file.h<br />+++ b/src/rgw/rgw_file.h<br /><code>@ -1559,94 +1559,191 </code>@ public:</p>
<pre><code>void send_response() override {<br /> struct req_state* s = get_state();<br />- for (const auto& iter : objs) {<br />+ auto cnow = real_clock::now();</code></pre>
<p>- boost::string_ref sref {iter.key.name};<br />+ /* enumerate objs and common_prefixes in parallel,<br />+ * avoiding increment on and end iterator, which is<br />+ * undefined */</p>
<p>- lsubdout(cct, rgw, 15) << "readdir objects prefix: " << prefix<br />- << " obj: " << sref << dendl;<br />+ class DirIterator<br />+ {<br />+ vector<rgw_bucket_dir_entry>& objs;<br />+ vector<rgw_bucket_dir_entry>::iterator obj_iter;</p>
<p>- size_t last_del = sref.find_last_of('/');<br />- if (last_del != string::npos)<br />- sref.remove_prefix(last_del+1);<br />+ map<string, bool>& common_prefixes;<br />+ map<string, bool>::iterator cp_iter;</p>
<p>- /* leaf directory? */<br />- if (sref.empty())<br />- continue;<br />+ boost::optional<boost::string_ref> obj_sref;<br />+ boost::optional<boost::string_ref> cp_sref;<br />+ bool _skip_cp;</p>
<p>- lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />- << <i>func</i> << " " <br />- << "list uri=" << s->relative_uri << " " <br />- << " prefix=" << prefix << " " <br />- << " obj path=" << iter.key.name<br />- << " (" << sref << ")" << "" <br />- << " mtime=" <br />- << real_clock::to_time_t(iter.meta.mtime)<br />- << " size=" << iter.meta.accounted_size<br />- << dendl;<br />+ public:</p>
<p>- if (! this->operator()(sref, next_marker, iter.meta.mtime,<br />- iter.meta.accounted_size, RGW_FS_TYPE_FILE)) {<br />- /* caller cannot accept more */<br />- lsubdout(cct, rgw, 5) << "readdir rcb failed" <br />- << " dirent=" << sref.data()<br />- << " call count=" << ix<br />- << dendl;<br />- rcb_eof = true;<br />- return;<br />+ DirIterator(vector<rgw_bucket_dir_entry>& objs,<br />+ map<string, bool>& common_prefixes)<br />+ : objs(objs), common_prefixes(common_prefixes), _skip_cp(false)<br />+ {<br />+ obj_iter = objs.begin();<br />+ parse_obj();<br />+ cp_iter = common_prefixes.begin();<br />+ parse_cp();<br />+ }<br /><ins><br /></ins> bool is_obj() {<br />+ return (obj_iter != objs.end());<br /> }<br />- ++ix;<br />- }</p>
<p>- auto cnow = real_clock::now();<br />- for (auto& iter : common_prefixes) {<br />+ bool is_cp(){<br />+ return (cp_iter != common_prefixes.end());<br />+ }</p>
<p>- lsubdout(cct, rgw, 15) << "readdir common prefixes prefix: " << prefix<br />- << " iter first: " << iter.first<br />- << " iter second: " << iter.second<br />- << dendl;<br />+ bool eof() {<br />+ return ((!is_obj()) && (!is_cp()));<br />+ }</p>
<p>- /* XXX aieee--I have seen this case! <strong>/<br />- if (iter.first == "/")<br />- continue;<br />+ void parse_obj() {<br />+ if (is_obj()) {<br />+ boost::string_ref sref{obj_iter->key.name};<br />+ size_t last_del = sref.find_last_of('/');<br />+ if (last_del != string::npos)<br />+ sref.remove_prefix(last_del+1);<br />+ obj_sref = sref;<br />+ }<br />+ } /</strong> parse_obj */</p>
<p>- /* it's safest to modify the element in place--a suffix-modifying<br />- * string_ref operation is problematic since ULP rgw_file callers<br />- * will ultimately need a c-string */<br />- if (iter.first.back() '/')<br />- const_cast&lt;std::string&&gt;(iter.first).pop_back();<br />+ void next_obj() {<br />+ +<ins>obj_iter;<br /></ins> parse_obj();<br />+ }</p>
<p>- boost::string_ref sref{iter.first};<br />+ void parse_cp() {<br />+ if (is_cp()) {<br />+ /* leading-/ skip case <strong>/<br />+ if (cp_iter->first "/") {<br />+ _skip_cp = true;<br />+ return;<br />+ } else<br />+ _skip_cp = false;<br /><ins><br /></ins> /</strong> it's safest to modify the element in place--a suffix-modifying<br />+ * string_ref operation is problematic since ULP rgw_file callers<br />+ * will ultimately need a c-string <strong>/<br />+ if (cp_iter->first.back() == '/')<br />+ const_cast<std::string&>(cp_iter->first).pop_back();<br /><ins><br /></ins> boost::string_ref sref{cp_iter->first};<br />+ size_t last_del = sref.find_last_of('/');<br />+ if (last_del != string::npos)<br />+ sref.remove_prefix(last_del+1);<br />+ cp_sref = sref;<br />+ } /</strong> is_cp <strong>/<br />+ } /</strong> parse_cp */<br /><ins><br /></ins> void next_cp() {<br />+ +<ins>cp_iter;<br /></ins> parse_cp();<br />+ }</p>
<p>- size_t last_del = sref.find_last_of('/');<br />- if (last_del != string::npos)<br />- sref.remove_prefix(last_del+1);<br />+ bool skip_cp() {<br />+ return _skip_cp;<br />+ }</p>
<p>- lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />- << <i>func</i> << " " <br />- << "list uri=" << s->relative_uri << " " <br />- << " prefix=" << prefix << " " <br />- << " cpref=" << sref<br />- << dendl;<br />+ bool entry_is_obj() {<br />+ return (is_obj() &&<br />+ ((! is_cp()) ||<br />+ (obj_sref.get() < cp_sref.get())));<br />+ }</p>
<p>- if (sref.empty()) {<br />- /* null path segment--could be created in S3 but has no NFS<br />- * interpretation */<br />- return;<br />+ boost::string_ref get_obj_sref() {<br />+ return obj_sref.get();<br /> }</p>
<p>- if (! this->operator()(sref, next_marker, cnow, 0,<br />- RGW_FS_TYPE_DIRECTORY)) {<br />- /* caller cannot accept more <strong>/<br />- lsubdout(cct, rgw, 5) << "readdir rcb failed" <br />- << " dirent=" << sref.data()<br />- << " call count=" << ix<br />- << dendl;<br />- rcb_eof = true;<br />- return;<br />+ boost::string_ref get_cp_sref() {<br />+ return cp_sref.get();<br /> }<br />- +<ins>ix;<br />- }<br /></ins><br />+ vector<rgw_bucket_dir_entry>::iterator& get_obj_iter() {<br />+ return obj_iter;<br />+ }<br /><ins><br /></ins> map<string, bool>::iterator& get_cp_iter() {<br />+ return cp_iter;<br />+ }<br /><ins><br /></ins> }; /</strong> DirIterator <strong>/<br /><ins><br /></ins> DirIterator di{objs, common_prefixes};<br /><ins><br /></ins> for (;;) {<br /><ins><br /></ins> if (di.eof()) {<br />+ break; // done<br />+ }<br /><ins><br /></ins> /</strong> assert: one of is_obj() || is_cp() holds <strong>/<br />+ if (di.entry_is_obj()) {<br />+ auto sref = di.get_obj_sref();<br />+ if (sref.empty()) {<br />+ /</strong> recursive list of a leaf dir (iirc), do nothing <strong>/<br />+ } else {<br />+ /</strong> send a file entry <strong>/<br />+ auto obj_entry = *(di.get_obj_iter());<br /><ins><br /></ins> lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />+ << <i>func</i> << " " <br />+ << "list uri=" << s->relative_uri << " " <br />+ << " prefix=" << prefix << " " <br />+ << " obj path=" << obj_entry.key.name<br />+ << " (" << sref << ")" << "" <br />+ << " mtime=" <br />+ << real_clock::to_time_t(obj_entry.meta.mtime)<br />+ << " size=" << obj_entry.meta.accounted_size<br />+ << dendl;<br /><ins><br /></ins> if (! this->operator()(sref, next_marker, obj_entry.meta.mtime,<br />+ obj_entry.meta.accounted_size,<br />+ RGW_FS_TYPE_FILE)) {<br />+ /</strong> caller cannot accept more <strong>/<br />+ lsubdout(cct, rgw, 5) << "readdir rcb caller signalled stop" <br />+ << " dirent=" << sref.data()<br />+ << " call count=" << ix<br />+ << dendl;<br />+ rcb_eof = true;<br />+ return;<br />+ }<br />+ }<br />+ di.next_obj(); // and advance object<br />+ } else {<br />+ /</strong> send a dir entry <strong>/<br />+ if (! di.skip_cp()) {<br />+ auto sref = di.get_cp_sref();<br /><ins><br /></ins> lsubdout(cct, rgw, 15) << "RGWReaddirRequest " <br />+ << <i>func</i> << " " <br />+ << "list uri=" << s->relative_uri << " " <br />+ << " prefix=" << prefix << " " <br />+ << " cpref=" << sref<br />+ << dendl;<br /><ins><br /></ins> if (sref.empty()) {<br />+ /</strong> null path segment--could be created in S3 but has no NFS<br />+ * interpretation <strong>/<br />+ } else {<br />+ if (! this->operator()(sref, next_marker, cnow, 0,<br />+ RGW_FS_TYPE_DIRECTORY)) {<br />+ /</strong> caller cannot accept more <strong>/<br />+ lsubdout(cct, rgw, 5) << "readdir rcb caller signalled stop" <br />+ << " dirent=" << sref.data()<br />+ << " call count=" << ix<br />+ << dendl;<br />+ rcb_eof = true;<br />+ return;<br />+ }<br />+ }<br />+ }<br />+ di.next_cp(); // and advance common_prefixes<br />+ } /</strong> ! di.entry_is_obj() <strong>/<br />+ } /</strong> for (;;) */<br /> }</p>
<pre><code>virtual void send_versioned_response() {<br />"""</code></pre>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182199
2021-01-08T18:29:41Z
Nathan Cutler
ncutler@suse.cz
<ul><li><strong>Status</strong> changed from <i>Need More Info</i> to <i>New</i></li><li><strong>Assignee</strong> changed from <i>Matt Benjamin</i> to <i>Nathan Cutler</i></li></ul>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182200
2021-01-08T18:29:58Z
Nathan Cutler
ncutler@suse.cz
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/182200/diff?detail_id=188318">diff</a>)</li><li><strong>Status</strong> changed from <i>New</i> to <i>In Progress</i></li></ul>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182895
2021-01-18T16:29:16Z
Yuri Weinstein
yweinste@redhat.com
<ul></ul><p>Backport Bot wrote:</p>
<blockquote>
<p><a class="external" href="https://github.com/ceph/ceph/pull/38828">https://github.com/ceph/ceph/pull/38828</a></p>
</blockquote>
<p>merged</p>
rgw - Backport #48543: nautilus: rgw_file: common_prefixes returned out of lexical order
https://tracker.ceph.com/issues/48543?journal_id=182909
2021-01-18T18:00:46Z
Nathan Cutler
ncutler@suse.cz
<ul><li><strong>Status</strong> changed from <i>In Progress</i> to <i>Resolved</i></li><li><strong>Target version</strong> set to <i>v14.2.17</i></li></ul><p>This update was made using the script "backport-resolve-issue".<br />backport PR <a class="external" href="https://github.com/ceph/ceph/pull/38828">https://github.com/ceph/ceph/pull/38828</a><br />merge commit 749e381c9ec6234b1b237f2f8b7513be0dc67ebd (v14.2.16-191-g749e381c9ec)</p>