From: Jeff Layton Date: Mon, 24 Oct 2016 14:03:00 +0000 (-0400) Subject: client: change args to ceph_readdirplus_r X-Git-Tag: v11.1.0~383^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=183cc07d4afaf1b7a0f52be9b23fbed715510e36;p=ceph.git client: change args to ceph_readdirplus_r 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 --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 78504dffc4bb..9667ecd0e253 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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(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(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(p); diff --git a/src/client/Client.h b/src/client/Client.h index b19f41434bd2..05a9af8029ad 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -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& names, const UserPerm& perms); // get the whole dir at once. diff --git a/src/client/fuse_ll.cc b/src/client/fuse_ll.cc index f63f9274af6b..9d6890041d89 100644 --- a/src/client/fuse_ll.cc +++ b/src/client/fuse_ll.cc @@ -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 @@ -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; diff --git a/src/client/hypertable/CephBroker.cc b/src/client/hypertable/CephBroker.cc index 74766c063bf0..6c8ce64de7c0 100644 --- a/src/client/hypertable/CephBroker.cc +++ b/src/client/hypertable/CephBroker.cc @@ -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; diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h index f54302a65e22..13078412032a 100644 --- a/src/include/cephfs/libcephfs.h +++ b/src/include/cephfs/libcephfs.h @@ -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. diff --git a/src/libcephfs.cc b/src/libcephfs.cc index 0b4934704a04..7b7e7c517dc0 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -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(dirp), de, st, stmask); + return cmount->get_client()->readdirplus_r(reinterpret_cast(dirp), de, stx, want, flags); } extern "C" int ceph_getdents(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, diff --git a/src/test/libcephfs/test.cc b/src/test/libcephfs/test.cc index bcadc73d3f4d..5a38cf8c7dc1 100644 --- a/src/test/libcephfs/test.cc +++ b/src/test/libcephfs/test.cc @@ -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));