]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: respect max_entries/max_bytes of lssnap request 6095/head
authorYan, Zheng <zyan@redhat.com>
Mon, 28 Sep 2015 13:22:57 +0000 (21:22 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 28 Sep 2015 13:26:20 +0000 (21:26 +0800)
Fixes: #13256
Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/mds/Server.cc

index 7dfaaa24e07e475dc95319b4f8ccbe98a8aa67cd..26baab9262b86d373e14556cd7802e781a8f07d3 100644 (file)
@@ -7641,29 +7641,58 @@ void Server::handle_client_lssnap(MDRequestRef& mdr)
   map<snapid_t,SnapInfo*> infomap;
   realm->get_snap_info(infomap, diri->get_oldest_snap());
 
+  unsigned max_entries = req->head.args.readdir.max_entries;
+  if (!max_entries)
+    max_entries = infomap.size();
+  int max_bytes = req->head.args.readdir.max_bytes;
+  if (!max_bytes)
+    max_bytes = 512 << 10;
+
+  __u64 last_snapid = 0;
+  string offset_str = req->get_path2();
+  if (!offset_str.empty())
+    last_snapid = realm->resolve_snapname(offset_str, diri->ino());
+
+  bufferlist dirbl;
+  encode_empty_dirstat(dirbl);
+
+  max_bytes -= dirbl.length() - sizeof(__u32) + sizeof(__u8) * 2;
+
   __u32 num = 0;
   bufferlist dnbl;
-  for (map<snapid_t,SnapInfo*>::iterator p = infomap.begin();
-       p != infomap.end();
-       ++p) {
+  map<snapid_t,SnapInfo*>::iterator p = infomap.upper_bound(last_snapid);
+  for (; p != infomap.end() && num < max_entries; ++p) {
     dout(10) << p->first << " -> " << *p->second << dendl;
 
     // actual
+    string snap_name;
     if (p->second->ino == diri->ino())
-      ::encode(p->second->name, dnbl);
+      snap_name = p->second->name;
     else
-      ::encode(p->second->get_long_name(), dnbl);
+      snap_name = p->second->get_long_name();
+
+    unsigned start_len = dnbl.length();
+    if (int(start_len + snap_name.length() + sizeof(__u32) + sizeof(LeaseStat)) > max_bytes)
+      break;
+
+    ::encode(snap_name, dnbl);
     encode_infinite_lease(dnbl);
-    diri->encode_inodestat(dnbl, mdr->session, realm, p->first);
-    num++;
+
+    int r = diri->encode_inodestat(dnbl, mdr->session, realm, p->first, max_bytes - (int)dnbl.length());
+    if (r < 0) {
+      bufferlist keep;
+      keep.substr_of(dnbl, 0, start_len);
+      dnbl.swap(keep);
+      break;
+    }
+    ++num;
   }
 
-  bufferlist dirbl;
-  encode_empty_dirstat(dirbl);
   ::encode(num, dirbl);
-  __u8 t = 1;
-  ::encode(t, dirbl);  // end
-  ::encode(t, dirbl);  // complete
+  __u8 end = (p == infomap.end());
+  ::encode(end, dirbl);  // end
+  __u8 complete = end && last_snapid == 0;
+  ::encode(complete, dirbl);  // complete
   dirbl.claim_append(dnbl);
   
   mdr->reply_extra_bl = dirbl;