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;
<< " 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;
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;
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;
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
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);
}
/*
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);
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;
}
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
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)
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);
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);
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);
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.
#include "ioctl.h"
#include "common/config.h"
#include "include/assert.h"
+#include "include/cephfs/ceph_statx.h"
#include "fuse_ll.h"
#include <fuse.h>
/*
* 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;
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;
* @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.
}
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,
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);
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);
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));