]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: fix memory fragmentation problem reading data from client. 20724/head
authorMarcus Watts <mwatts@redhat.com>
Mon, 5 Mar 2018 21:10:29 +0000 (16:10 -0500)
committerMarcus Watts <mwatts@redhat.com>
Thu, 8 Mar 2018 19:55:40 +0000 (14:55 -0500)
mg_read returns 0 on EOF.  In some versions of civetweb, mg_read can
return "short" reads.  The logic in the rest of ceph depends on a read
always filling its buffer when possible.  So loop here and fill the
buffer.  Looping to fill the buffer means we must also track when
mg_read returns EOF, because after that further calls to mg_read will return -1.

Fixes: https://tracker.ceph.com/issues/23207
Signed-off-by: Marcus Watts <mwatts@redhat.com>
src/rgw/rgw_civetweb.cc
src/rgw/rgw_civetweb.h

index f4d17d721c18d5308504f21540d16727dbe93891..30f69406f18b8056c7ed4f5a07c469f2b4b664ad 100644 (file)
@@ -33,6 +33,7 @@ RGWCivetWeb::RGWCivetWeb(mg_connection* const conn)
   : conn(conn),
     explicit_keepalive(false),
     explicit_conn_close(false),
+    got_eof_on_read(false),
     txbuf(*this)
 {
     sockaddr *lsa = mg_get_local_addr(conn);
@@ -50,11 +51,21 @@ RGWCivetWeb::RGWCivetWeb(mg_connection* const conn)
 
 size_t RGWCivetWeb::read_data(char *buf, size_t len)
 {
-  const int ret = mg_read(conn, buf, len);
-  if (ret < 0) {
-    throw rgw::io::Exception(EIO, std::system_category());
+  int c, ret;
+  if (got_eof_on_read) {
+    return 0;
+  }
+  for (c = 0; c < len; c += ret) {
+    ret = mg_read(conn, buf, len);
+    if (ret < 0) {
+      throw rgw::io::Exception(EIO, std::system_category());
+    }
+    if (!ret) {
+      got_eof_on_read = true;
+      break;
+    }
   }
-  return ret;
+  return c;
 }
 
 void RGWCivetWeb::flush()
index 0160c03a42d981d97df6e79ee563e060c21b2910..b64eb1340bd07214eb371e2f98c2f0d44ed1b040 100644 (file)
@@ -19,6 +19,7 @@ class RGWCivetWeb : public rgw::io::RestfulClient,
 
   bool explicit_keepalive;
   bool explicit_conn_close;
+  bool got_eof_on_read;
 
   rgw::io::StaticOutputBufferer<> txbuf;