]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: include 'last', 'complete' flags in readdir reply
authorSage Weil <sage@newdream.net>
Wed, 1 Apr 2009 17:54:48 +0000 (10:54 -0700)
committerSage Weil <sage@newdream.net>
Wed, 1 Apr 2009 19:39:52 +0000 (12:39 -0700)
src/include/ceph_fs.h
src/kernel/dir.c
src/kernel/mds_client.c
src/kernel/mds_client.h
src/mds/Server.cc

index 744feaba938acd89a4d7f5a9b5cd4084eb4389dc..37f7b5ddbc2afd293510578b9616e39b7acd27bc 100644 (file)
@@ -44,7 +44,7 @@
 #define CEPH_MDS_PROTOCOL     7 /* cluster internal */
 #define CEPH_MON_PROTOCOL     4 /* cluster internal */
 #define CEPH_OSDC_PROTOCOL    6 /* public/client */
-#define CEPH_MDSC_PROTOCOL   15 /* public/client */
+#define CEPH_MDSC_PROTOCOL   16 /* public/client */
 #define CEPH_MONC_PROTOCOL   11 /* public/client */
 
 
@@ -769,6 +769,7 @@ union ceph_mds_request_args {
        } __attribute__ ((packed)) fstat;
        struct {
                __le32 frag;
+               __le32 max_entries;
        } __attribute__ ((packed)) readdir;
        struct {
                __le32 mode;
index 029682e4f651effddc8e923b91f8c24a3ce804cc..7fffac050dd2d5c0c4071e313f40e54164590853 100644 (file)
@@ -58,6 +58,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
        int err;
        u32 ftype;
        struct ceph_mds_reply_info_parsed *rinfo;
+       int complete = 0;
 
        /* set I_READDIR at start of readdir */
        if (filp->f_pos == 0)
@@ -97,7 +98,11 @@ nextfrag:
                        return err;
                }
                dout(10, "readdir got and parsed readdir result=%d"
-                    " on frag %x\n", err, frag);
+                    " on frag %x, end=%d, complete=%d\n", err, frag,
+                    (int)req->r_reply_info.dir_complete,
+                    (int)req->r_reply_info.dir_end);
+               if (req->r_reply_info.dir_complete)
+                       complete = 1;
                fi->last_readdir = req;
        }
 
@@ -163,7 +168,7 @@ nextfrag:
         * dir contents in our cache.
         */
        spin_lock(&inode->i_lock);
-       if (ci->i_ceph_flags & CEPH_I_READDIR) {
+       if (complete && (ci->i_ceph_flags & CEPH_I_READDIR)) {
                dout(10, " marking %p complete\n", inode);
                ci->i_ceph_flags |= CEPH_I_COMPLETE;
                ci->i_ceph_flags &= ~CEPH_I_READDIR;
index 3426cc185293bb1f0d34791ab38cb46bfb292f3e..2164e03e5f903ef1082f5bfb3a1413f04bc4dd52 100644 (file)
@@ -124,7 +124,10 @@ static int parse_reply_info_dir(void **p, void *end,
        if (*p > end)
                goto bad;
 
-       ceph_decode_32_safe(p, end, num, bad);
+       ceph_decode_need(p, end, sizeof(num) + 2, bad);
+       ceph_decode_32(p, num);
+       ceph_decode_8(p, info->dir_end);
+       ceph_decode_8(p, info->dir_complete);
        if (num == 0)
                goto done;
 
index d7f8b7d2c599aaa777c61968211d2ec0441b7bd8..143aa10b3be611cc7ddbf2e8d248acc6e00f9172 100644 (file)
@@ -86,6 +86,7 @@ struct ceph_mds_reply_info_parsed {
        u32                           *dir_dname_len;
        struct ceph_mds_reply_lease   **dir_dlease;
        struct ceph_mds_reply_info_in *dir_in;
+       u8                            dir_complete, dir_end;
 
        /* encoded blob describing snapshot contexts for certain
           operations (e.g., open) */
index 0f48fb550833a7bd02ff740ea4fe3a1937387834..da746305cf72a26523ee93f9d3d0571f6a24864c 100644 (file)
@@ -2152,12 +2152,23 @@ void Server::handle_client_readdir(MDRequest *mdr)
   bufferlist dirbl, dnbl;
   dir->encode_dirstat(dirbl, mds->get_nodeid());
 
-  __u32 numfiles = 0;
   CDir::map_t::iterator it = dir->begin(); 
-  while (it != dir->end()) {
+
+  unsigned max = req->head.args.readdir.max_entries;
+  if (!max)
+    max = dir->get_num_any();  // whatever, something big.
+
+  nstring offset_str = req->get_path2();
+  const char *offset = offset_str.length() ? offset_str.c_str() : 0;
+
+  __u32 numfiles = 0;
+  while (it != dir->end() && numfiles < max) {
     CDentry *dn = it->second;
     it++;
 
+    if (offset && strcmp(dn->get_name().c_str(), offset) <= 0)
+      continue;
+
     bool dnp = dn->use_projected(client, mdr);
     CDentry::linkage_t *dnl = dnp ? dn->get_projected_linkage() : dn->get_linkage();
 
@@ -2212,7 +2223,14 @@ void Server::handle_client_readdir(MDRequest *mdr)
     // touch dn
     mdcache->lru.lru_touch(dn);
   }
+  
+  __u8 end = (it == dir->end());
+  __u8 complete = (end && !offset);
+
+  // final blob
   ::encode(numfiles, dirbl);
+  ::encode(end, dirbl);
+  ::encode(complete, dirbl);
   dirbl.claim_append(dnbl);
   
   if (snaps)
@@ -2221,7 +2239,8 @@ void Server::handle_client_readdir(MDRequest *mdr)
   // yay, reply
   MClientReply *reply = new MClientReply(req, 0);
   reply->set_dir_bl(dirbl);
-  dout(10) << "reply to " << *req << " readdir " << numfiles << " files" << dendl;
+  dout(10) << "reply to " << *req << " readdir num=" << numfiles << " end=" << (int)end
+          << " complete=" << (int)complete << dendl;
 
   // bump popularity.  NOTE: this doesn't quite capture it.
   mds->balancer->hit_dir(g_clock.now(), dir, META_POP_IRD, -1, numfiles);