]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: change args to ceph_readdirplus_r
authorJeff Layton <jlayton@redhat.com>
Mon, 24 Oct 2016 14:03:00 +0000 (10:03 -0400)
committerJeff Layton <jlayton@redhat.com>
Tue, 25 Oct 2016 17:06:29 +0000 (13:06 -0400)
Make ceph_readdirplus_r take a ceph_statx, a want and a flags parm. With
this, we can allow applications to express an interest in subset of the
attributes, and can allow for a "lazy" readdirplus.

Drop the stmask. It ends up returning the caps that the client holds on
the inode. That's not well defined, and we can now express that in a
better way via the stx_mask, which applications can use to tell which
fields in the ceph_statx are actually valid.

For now, the want mask is ignored. I don't see a way to ask for a set
of caps in a ceph readdir request on the wire. Maybe we could add that?

Signed-off-by: Jeff Layton <jlayton@redhat.com>
src/client/Client.cc
src/client/Client.h
src/client/fuse_ll.cc
src/client/hypertable/CephBroker.cc
src/include/cephfs/libcephfs.h
src/libcephfs.cc
src/test/libcephfs/test.cc

index 78504dffc4bb674197f184a1ae52f89f5fd0b23d..9667ecd0e253728ae27143dc38a43cae2c1459d2 100644 (file)
@@ -7360,21 +7360,21 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p, b
       continue;
     }
 
-    struct stat st;
+    struct ceph_statx stx;
     struct dirent de;
-    int stmask = fill_stat(dn->inode, &st);
+    fill_statx(dn->inode, lazy ? 0 : dn->inode->caps_issued(), &stx);
 
     uint64_t next_off = dn->offset + 1;
     ++pd;
     if (pd == dir->readdir_cache.end())
       next_off = dir_result_t::END;
 
-    fill_dirent(&de, dn->name.c_str(), st.st_mode, st.st_ino, next_off);
+    fill_dirent(&de, dn->name.c_str(), stx.stx_mode, stx.stx_ino, next_off);
 
     dn_name = dn->name; // fill in name while we have lock
 
     client_lock.Unlock();
-    int r = cb(p, &de, &st, stmask, next_off);  // _next_ offset
+    int r = cb(p, &de, &stx, next_off);  // _next_ offset
     client_lock.Lock();
     ldout(cct, 15) << " de " << de.d_name << " off " << hex << dn->offset << dec
                   << " = " << r << dendl;
@@ -7408,9 +7408,9 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p, bool lazy
                 << " hash_order=" << dirp->hash_order() << dendl;
 
   struct dirent de;
-  struct stat st;
+  struct ceph_statx stx;
   memset(&de, 0, sizeof(de));
-  memset(&st, 0, sizeof(st));
+  memset(&stx, 0, sizeof(stx));
 
   InodeRef& diri = dirp->inode;
 
@@ -7422,11 +7422,11 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p, bool lazy
     assert(diri->dn_set.size() < 2); // can't have multiple hard-links to a dir
     uint64_t next_off = 1;
 
-    fill_stat(diri, &st);
-    fill_dirent(&de, ".", S_IFDIR, st.st_ino, next_off);
+    fill_statx(diri, lazy ? 0 : diri->caps_issued(), &stx);
+    fill_dirent(&de, ".", S_IFDIR, stx.stx_ino, next_off);
 
     client_lock.Unlock();
-    int r = cb(p, &de, &st, -1, next_off);
+    int r = cb(p, &de, &stx, next_off);
     client_lock.Lock();
     if (r < 0)
       return r;
@@ -7444,11 +7444,11 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p, bool lazy
     else
       in = diri->get_first_parent()->inode;
 
-    fill_stat(in, &st);
-    fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off);
+    fill_statx(in, lazy ? 0 : in->caps_issued(), &stx);
+    fill_dirent(&de, "..", S_IFDIR, stx.stx_ino, next_off);
 
     client_lock.Unlock();
-    int r = cb(p, &de, &st, -1, next_off);
+    int r = cb(p, &de, &stx, next_off);
     client_lock.Lock();
     if (r < 0)
       return r;
@@ -7495,11 +7495,11 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p, bool lazy
       dir_result_t::dentry &entry = *it;
 
       uint64_t next_off = entry.offset + 1;
-      int stmask = fill_stat(entry.inode, &st);
-      fill_dirent(&de, entry.name.c_str(), st.st_mode, st.st_ino, next_off);
+      fill_statx(entry.inode, lazy ? 0 : entry.inode->caps_issued(), &stx);
+      fill_dirent(&de, entry.name.c_str(), stx.stx_mode, stx.stx_ino, next_off);
 
       client_lock.Unlock();
-      int r = cb(p, &de, &st, stmask, next_off);  // _next_ offset
+      int r = cb(p, &de, &stx, next_off);  // _next_ offset
       client_lock.Lock();
 
       ldout(cct, 15) << " de " << de.d_name << " off " << hex << next_off - 1 << dec
@@ -7549,7 +7549,7 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p, bool lazy
 
 int Client::readdir_r(dir_result_t *d, struct dirent *de)
 {  
-  return readdirplus_r(d, de, 0, 0);
+  return readdirplus_r(d, de, 0, 0, 0);
 }
 
 /*
@@ -7563,13 +7563,12 @@ int Client::readdir_r(dir_result_t *d, struct dirent *de)
 
 struct single_readdir {
   struct dirent *de;
-  struct stat *st;
-  int *stmask;
+  struct ceph_statx *stx;
   bool full;
 };
 
-static int _readdir_single_dirent_cb(void *p, struct dirent *de, struct stat *st,
-                                    int stmask, off_t off)
+static int _readdir_single_dirent_cb(void *p, struct dirent *de,
+                                    struct ceph_statx *stx, off_t off)
 {
   single_readdir *c = static_cast<single_readdir *>(p);
 
@@ -7577,10 +7576,8 @@ static int _readdir_single_dirent_cb(void *p, struct dirent *de, struct stat *st
     return -1;  // already filled this dirent
 
   *c->de = *de;
-  if (c->st)
-    *c->st = *st;
-  if (c->stmask)
-    *c->stmask = stmask;
+  if (c->stx)
+    *c->stx = *stx;
   c->full = true;
   return 1;
 }
@@ -7588,13 +7585,10 @@ static int _readdir_single_dirent_cb(void *p, struct dirent *de, struct stat *st
 struct dirent *Client::readdir(dir_result_t *d)
 {
   int ret;
-  static int stmask;
   static struct dirent de;
-  static struct stat st;
   single_readdir sr;
   sr.de = &de;
-  sr.st = &st;
-  sr.stmask = &stmask;
+  sr.stx = NULL;
   sr.full = false;
 
   // our callback fills the dirent and sets sr.full=true on first
@@ -7610,17 +7604,19 @@ struct dirent *Client::readdir(dir_result_t *d)
   return (dirent *) NULL;
 }
 
-int Client::readdirplus_r(dir_result_t *d, struct dirent *de, struct stat *st, int *stmask)
+int Client::readdirplus_r(dir_result_t *d, struct dirent *de,
+                         struct ceph_statx *stx, unsigned want,
+                         unsigned flags)
 {  
   single_readdir sr;
   sr.de = de;
-  sr.st = st;
-  sr.stmask = stmask;
+  sr.stx = stx;
   sr.full = false;
 
   // our callback fills the dirent and sets sr.full=true on first
   // call, and returns -1 the second time around.
-  int r = readdir_r_cb(d, _readdir_single_dirent_cb, (void *)&sr);
+  int r = readdir_r_cb(d, _readdir_single_dirent_cb, (void *)&sr,
+                      flags & AT_NO_ATTR_SYNC);
   if (r < -1)
     return r;
   if (sr.full)
@@ -7637,7 +7633,8 @@ struct getdents_result {
   bool fullent;
 };
 
-static int _readdir_getdent_cb(void *p, struct dirent *de, struct stat *st, int stmask, off_t off)
+static int _readdir_getdent_cb(void *p, struct dirent *de,
+                              struct ceph_statx *stx, off_t off)
 {
   struct getdents_result *c = static_cast<getdents_result *>(p);
 
@@ -7689,7 +7686,7 @@ struct getdir_result {
   int num;
 };
 
-static int _getdir_cb(void *p, struct dirent *de, struct stat *st, int stmask, off_t off)
+static int _getdir_cb(void *p, struct dirent *de, struct ceph_statx *stx, off_t off)
 {
   getdir_result *r = static_cast<getdir_result *>(p);
 
index b19f41434bd2f0d88b88f0a3c2b27f6aeb7536fa..05a9af8029ade67a816c9ff6ea64ca868e42fde3 100644 (file)
@@ -719,7 +719,7 @@ private:
   void fill_dirent(struct dirent *de, const char *name, int type, uint64_t ino, loff_t next_off);
 
   // some readdir helpers
-  typedef int (*add_dirent_cb_t)(void *p, struct dirent *de, struct stat *st, int stmask, off_t off);
+  typedef int (*add_dirent_cb_t)(void *p, struct dirent *de, struct ceph_statx *stx, off_t off);
 
   int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms);
   void _readdir_drop_dirp_buffer(dir_result_t *dirp);
@@ -956,7 +956,7 @@ public:
 
   struct dirent * readdir(dir_result_t *d);
   int readdir_r(dir_result_t *dirp, struct dirent *de);
-  int readdirplus_r(dir_result_t *dirp, struct dirent *de, struct stat *st, int *stmask);
+  int readdirplus_r(dir_result_t *dirp, struct dirent *de, struct ceph_statx *stx, unsigned want, unsigned flags);
 
   int getdir(const char *relpath, list<string>& names,
             const UserPerm& perms);  // get the whole dir at once.
index f63f9274af6bcd503ce9f08e85da5be63c297adb..9d6890041d893f70a190d306a5e15319755c4003 100644 (file)
@@ -32,6 +32,7 @@
 #include "ioctl.h"
 #include "common/config.h"
 #include "include/assert.h"
+#include "include/cephfs/ceph_statx.h"
 
 #include "fuse_ll.h"
 #include <fuse.h>
@@ -678,19 +679,20 @@ struct readdir_context {
 /*
  * return 0 on success, -1 if out of space
  */
-static int fuse_ll_add_dirent(void *p, struct dirent *de, struct stat *st,
-                             int stmask, off_t next_off)
+static int fuse_ll_add_dirent(void *p, struct dirent *de,
+                             struct ceph_statx *stx, off_t next_off)
 {
   struct readdir_context *c = (struct readdir_context *)p;
   CephFuse::Handle *cfuse = (CephFuse::Handle *)fuse_req_userdata(c->req);
 
-  st->st_ino = cfuse->make_fake_ino(de->d_ino, c->snap);
-  st->st_mode = DTTOIF(de->d_type);
-  st->st_rdev = new_encode_dev(st->st_rdev);
+  struct stat st;
+  st.st_ino = cfuse->make_fake_ino(stx->stx_ino, c->snap);
+  st.st_mode = stx->stx_mode;
+  st.st_rdev = new_encode_dev(stx->stx_rdev);
 
   size_t room = c->size - c->pos;
   size_t entrysize = fuse_add_direntry(c->req, c->buf + c->pos, room,
-                                      de->d_name, st, next_off);
+                                      de->d_name, &st, next_off);
   if (entrysize > room)
     return -ENOSPC;
 
index 74766c063bf0848e0933bce62beec7423a6ea478..6c8ce64de7c07484bb2586c20713e3c38b5044ac 100644 (file)
@@ -384,17 +384,17 @@ void CephBroker::rmdir(ResponseCallback *cb, const char *dname) {
 int CephBroker::rmdir_recursive(const char *directory) {
   struct ceph_dir_result *dirp;
   struct dirent de;
-  struct stat st;
+  struct ceph_statx stx;
   int r;
   if ((r = ceph_opendir(cmount, directory, &dirp)) < 0)
     return r; //failed to open
-  while ((r = ceph_readdirplus_r(cmount, dirp, &de, &st, 0)) > 0) {
+  while ((r = ceph_readdirplus_r(cmount, dirp, &de, &stx, CEPH_STATX_INO, AT_NO_ATTR_SYNC)) > 0) {
     String new_dir = de.d_name;
     if(!(new_dir.compare(".")==0 || new_dir.compare("..")==0)) {
       new_dir = directory;
       new_dir += '/';
       new_dir += de.d_name;
-      if (S_ISDIR(st.st_mode)) { //it's a dir, clear it out...
+      if (S_ISDIR(stx.stx_mode)) { //it's a dir, clear it out...
        if((r=rmdir_recursive(new_dir.c_str())) < 0) return r;
       } else { //delete this file
        if((r=ceph_unlink(cmount, new_dir.c_str())) < 0) return r;
index f54302a65e22867620bd70deb50db798c9bbdd30..13078412032a174717a8c475ce0eefe88f3f8a2b 100644 (file)
@@ -480,13 +480,14 @@ int ceph_readdir_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
  * @param dirp the directory stream pointer from an opendir holding the state of the
  *        next entry to return.
  * @param de the directory entry pointer filled in with the next directory entry of the dirp state.
- * @param st the stats of the file/directory of the entry returned
- * @param stmask a mask that gets filled in with the stats fields that are being set in the st parameter.
+ * @param stx the stats of the file/directory of the entry returned
+ * @param want mask showing desired inode attrs for returned entry
+ * @param flags bitmask of flags to use when filling out attributes
  * @returns 1 if the next entry was filled in, 0 if the end of the directory stream was reached,
  *          and a negative error code on failure.
  */
 int ceph_readdirplus_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, struct dirent *de,
-                      struct stat *st, int *stmask);
+                      struct ceph_statx *stx, unsigned want, unsigned flags);
 
 /**
  * Gets multiple directory entries.
index 0b4934704a041248db01fb8f6be0cfa53f878748..7b7e7c517dc043993894d44ce39043445119c1d1 100644 (file)
@@ -517,11 +517,12 @@ extern "C" int ceph_readdir_r(struct ceph_mount_info *cmount, struct ceph_dir_re
 }
 
 extern "C" int ceph_readdirplus_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
-                                 struct dirent *de, struct stat *st, int *stmask)
+                                 struct dirent *de, struct ceph_statx *stx, unsigned want,
+                                 unsigned flags)
 {
   if (!cmount->is_mounted())
     return -ENOTCONN;
-  return cmount->get_client()->readdirplus_r(reinterpret_cast<dir_result_t*>(dirp), de, st, stmask);
+  return cmount->get_client()->readdirplus_r(reinterpret_cast<dir_result_t*>(dirp), de, stx, want, flags);
 }
 
 extern "C" int ceph_getdents(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
index bcadc73d3f4d4cda7d87d496774706674165cf61..5a38cf8c7dc1e43518da804717878b15e9a32a84 100644 (file)
@@ -424,9 +424,9 @@ TEST(LibCephFS, DirLs) {
   found.clear();
   while (true) {
     struct dirent rdent;
-    struct stat st;
-    int stmask;
-    int len = ceph_readdirplus_r(cmount, ls_dir, &rdent, &st, &stmask);
+    struct ceph_statx stx;
+    int len = ceph_readdirplus_r(cmount, ls_dir, &rdent, &stx,
+                                CEPH_STATX_SIZE, AT_NO_ATTR_SYNC);
     if (len == 0)
       break;
     ASSERT_EQ(len, 1);
@@ -434,8 +434,9 @@ TEST(LibCephFS, DirLs) {
     found.push_back(name);
     int size;
     sscanf(name, "dirf%d", &size);
-    ASSERT_EQ(st.st_size, size);
-    ASSERT_EQ(st.st_ino, rdent.d_ino);
+    ASSERT_TRUE(stx.stx_mask & CEPH_STATX_SIZE);
+    ASSERT_EQ(stx.stx_size, (size_t)size);
+    ASSERT_EQ(stx.stx_ino, rdent.d_ino);
     //ASSERT_EQ(st.st_mode, (mode_t)0666);
   }
   ASSERT_EQ(found, entries);
@@ -1136,10 +1137,8 @@ TEST(LibCephFS, UseUnmounted) {
   struct dirent rdent;
   EXPECT_EQ(-ENOTCONN, ceph_readdir_r(cmount, dirp, &rdent));
 
-  int stmask;
   struct ceph_statx stx;
-  struct stat st;
-  EXPECT_EQ(-ENOTCONN, ceph_readdirplus_r(cmount, dirp, &rdent, &st, &stmask));
+  EXPECT_EQ(-ENOTCONN, ceph_readdirplus_r(cmount, dirp, &rdent, &stx, 0, 0));
   EXPECT_EQ(-ENOTCONN, ceph_getdents(cmount, dirp, NULL, 0));
   EXPECT_EQ(-ENOTCONN, ceph_getdnames(cmount, dirp, NULL, 0));
   EXPECT_EQ(-ENOTCONN, ceph_telldir(cmount, dirp));