libcephfs: introduce basic *at() calls

Signed-off-by: Venky Shankar <vshankar@redhat.com>
This commit is contained in:
Venky Shankar 2021-04-12 05:25:34 -04:00
parent 52c672350f
commit 3831aa12f3
5 changed files with 671 additions and 31 deletions

View File

@ -204,6 +204,21 @@ int Client::CommandHook::call(
// -------------
int Client::get_fd_inode(int fd, InodeRef *in) {
int r = 0;
if (fd == CEPHFS_AT_FDCWD) {
*in = cwd;
} else {
Fh *f = get_filehandle(fd);
if (!f) {
r = -CEPHFS_EBADF;
} else {
*in = f->inode;
}
}
return r;
}
dir_result_t::dir_result_t(Inode *in, const UserPerm& perms)
: inode(in), offset(0), next_offset(2),
release_count(0), ordered_count(0), cache_index(0), start_shared_gen(0),
@ -6916,25 +6931,30 @@ int Client::walk(std::string_view path, walk_dentry_result* wdr, const UserPerm&
}
int Client::path_walk(const filepath& origpath, InodeRef *end,
const UserPerm& perms, bool followsym, int mask)
const UserPerm& perms, bool followsym, int mask, InodeRef dirinode)
{
walk_dentry_result wdr;
int rc = path_walk(origpath, &wdr, perms, followsym, mask);
int rc = path_walk(origpath, &wdr, perms, followsym, mask, dirinode);
*end = std::move(wdr.in);
return rc;
}
int Client::path_walk(const filepath& origpath, walk_dentry_result* result, const UserPerm& perms, bool followsym, int mask)
int Client::path_walk(const filepath& origpath, walk_dentry_result* result, const UserPerm& perms,
bool followsym, int mask, InodeRef dirinode)
{
filepath path = origpath;
InodeRef cur;
std::string alternate_name;
if (origpath.absolute())
cur = root;
else
else if (!dirinode)
cur = cwd;
else {
cur = dirinode;
}
ceph_assert(cur);
ldout(cct, 20) << __func__ << " cur=" << *cur << dendl;
ldout(cct, 10) << __func__ << " " << path << dendl;
int symlinks = 0;
@ -7085,6 +7105,53 @@ int Client::unlink(const char *relpath, const UserPerm& perm)
return _unlink(dir.get(), name.c_str(), perm);
}
int Client::unlinkat(int dirfd, const char *relpath, int flags, const UserPerm& perm)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << flags << std::endl;
if (std::string(relpath) == "/") {
return flags & AT_REMOVEDIR ? -CEPHFS_EBUSY : -CEPHFS_EISDIR;
}
filepath path(relpath);
string name = path.last_dentry();
path.pop_dentry();
InodeRef dir;
std::scoped_lock lock(client_lock);
InodeRef dirinode;
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
r = path_walk(path, &dir, perm, true, 0, dirinode);
if (r < 0) {
return r;
}
if (cct->_conf->client_permissions) {
r = may_delete(dir.get(), name.c_str(), perm);
if (r < 0) {
return r;
}
}
if (flags & AT_REMOVEDIR) {
r = _rmdir(dir.get(), name.c_str(), perm);
} else {
r = _unlink(dir.get(), name.c_str(), perm);
}
return r;
}
int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm, std::string alternate_name)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
@ -7161,6 +7228,49 @@ int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm, std::s
return _mkdir(dir.get(), name.c_str(), mode, perm, 0, {}, std::move(alternate_name));
}
int Client::mkdirat(int dirfd, const char *relpath, mode_t mode, const UserPerm& perm,
std::string alternate_name)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied())
return -CEPHFS_ENOTCONN;
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << mode << std::endl;
ldout(cct, 10) << __func__ << ": " << relpath << dendl;
if (std::string(relpath) == "/") {
return -CEPHFS_EEXIST;
}
filepath path(relpath);
string name = path.last_dentry();
path.pop_dentry();
InodeRef dir;
std::scoped_lock lock(client_lock);
InodeRef dirinode;
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
r = path_walk(path, &dir, perm, true, 0, dirinode);
if (r < 0) {
return r;
}
if (cct->_conf->client_permissions) {
r = may_create(dir.get(), perm);
if (r < 0) {
return r;
}
}
return _mkdir(dir.get(), name.c_str(), mode, perm, 0, {}, std::move(alternate_name));
}
int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
@ -7310,6 +7420,48 @@ int Client::symlink(const char *target, const char *relpath, const UserPerm& per
return _symlink(dir.get(), name.c_str(), target, perms, std::move(alternate_name));
}
int Client::symlinkat(const char *target, int dirfd, const char *relpath, const UserPerm& perms,
std::string alternate_name)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << target << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
if (std::string(relpath) == "/") {
return -CEPHFS_EEXIST;
}
filepath path(relpath);
string name = path.last_dentry();
path.pop_dentry();
InodeRef dir;
std::scoped_lock lock(client_lock);
InodeRef dirinode;
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
r = path_walk(path, &dir, perms, true, 0, dirinode);
if (r < 0) {
return r;
}
if (cct->_conf->client_permissions) {
int r = may_create(dir.get(), perms);
if (r < 0) {
return r;
}
}
return _symlink(dir.get(), name.c_str(), target, perms, std::move(alternate_name));
}
int Client::readlink(const char *relpath, char *buf, loff_t size, const UserPerm& perms)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
@ -7330,6 +7482,33 @@ int Client::readlink(const char *relpath, char *buf, loff_t size, const UserPerm
return _readlink(in.get(), buf, size);
}
int Client::readlinkat(int dirfd, const char *relpath, char *buf, loff_t size, const UserPerm& perms) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
InodeRef dirinode;
std::scoped_lock lock(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
InodeRef in;
filepath path(relpath);
r = path_walk(path, &in, perms, false, 0, dirinode);
if (r < 0) {
return r;
}
return _readlink(in.get(), buf, size);
}
int Client::_readlink(Inode *in, char *buf, size_t size)
{
if (!in->is_symlink())
@ -8019,6 +8198,38 @@ int Client::fchmod(int fd, mode_t mode, const UserPerm& perms)
return _setattr(f->inode, &attr, CEPH_SETATTR_MODE, perms);
}
int Client::chmodat(int dirfd, const char *relpath, mode_t mode, int flags,
const UserPerm& perms) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << mode << std::endl;
tout(cct) << flags << std::endl;
filepath path(relpath);
InodeRef in;
InodeRef dirinode;
std::scoped_lock lock(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
if (r < 0) {
return r;
}
struct stat attr;
attr.st_mode = mode;
return _setattr(in, &attr, CEPH_SETATTR_MODE, perms);
}
int Client::lchmod(const char *relpath, mode_t mode, const UserPerm& perms)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
@ -8124,6 +8335,40 @@ int Client::lchown(const char *relpath, uid_t new_uid, gid_t new_gid,
return _setattr(in, &attr, mask, perms);
}
int Client::chownat(int dirfd, const char *relpath, uid_t new_uid, gid_t new_gid,
int flags, const UserPerm& perms) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << new_uid << std::endl;
tout(cct) << new_gid << std::endl;
tout(cct) << flags << std::endl;
filepath path(relpath);
InodeRef in;
InodeRef dirinode;
std::scoped_lock lock(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
if (r < 0) {
return r;
}
struct stat attr;
attr.st_uid = new_uid;
attr.st_gid = new_gid;
return _setattr(in, &attr, CEPH_SETATTR_UID|CEPH_SETATTR_GID, perms);
}
static void attr_set_atime_and_mtime(struct stat *attr,
const utime_t &atime,
const utime_t &mtime)
@ -8270,6 +8515,50 @@ int Client::futimens(int fd, struct timespec times[2], const UserPerm& perms)
return _setattr(f->inode, &attr, CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME, perms);
}
int Client::utimensat(int dirfd, const char *relpath, struct timespec times[2], int flags,
const UserPerm& perms) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << "atime: " << times[0].tv_sec << "." << times[0].tv_nsec
<< std::endl;
tout(cct) << "mtime: " << times[1].tv_sec << "." << times[1].tv_nsec
<< std::endl;
tout(cct) << flags << std::endl;
filepath path(relpath);
InodeRef in;
InodeRef dirinode;
std::scoped_lock lock(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
#if defined(__linux__) && defined(O_PATH)
if (flags & O_PATH) {
return -CEPHFS_EBADF;
}
#endif
r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
if (r < 0) {
return r;
}
struct stat attr;
utime_t atime(times[0]);
utime_t mtime(times[1]);
attr_set_atime_and_mtime(&attr, atime, mtime);
return _setattr(in, &attr, CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME, perms);
}
int Client::flock(int fd, int operation, uint64_t owner)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
@ -8317,6 +8606,36 @@ int Client::opendir(const char *relpath, dir_result_t **dirpp, const UserPerm& p
return r;
}
int Client::fdopendir(int dirfd, dir_result_t **dirpp, const UserPerm &perms) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << std::endl;
tout(cct) << dirfd << std::endl;
InodeRef dirinode;
std::scoped_lock locker(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
if (cct->_conf->client_permissions) {
r = may_open(dirinode.get(), O_RDONLY, perms);
if (r < 0) {
return r;
}
}
r = _opendir(dirinode.get(), dirpp, perms);
/* if ENOTDIR, dirpp will be an uninitialized point and it's very dangerous to access its value */
if (r != -CEPHFS_ENOTDIR) {
tout(cct) << (uintptr_t)*dirpp << std::endl;
}
return r;
}
int Client::_opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms)
{
if (!in->is_dir())
@ -9015,19 +9334,14 @@ int Client::getdir(const char *relpath, list<string>& contents,
/****** file i/o **********/
int Client::open(const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count,
int object_size, const char *data_pool, std::string alternate_name)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied())
return -CEPHFS_ENOTCONN;
// common parts for open and openat. call with client_lock locked.
int Client::create_and_open(std::optional<int> dirfd, const char *relpath, int flags,
const UserPerm& perms, mode_t mode, int stripe_unit,
int stripe_count, int object_size, const char *data_pool,
std::string alternate_name) {
ceph_assert(ceph_mutex_is_locked(client_lock));
int cflags = ceph_flags_sys2wire(flags);
ldout(cct, 3) << "open enter(" << relpath << ", " << cflags << "," << mode << ")" << dendl;
tout(cct) << "open" << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << cflags << std::endl;
Fh *fh = NULL;
@ -9047,16 +9361,22 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms,
bool followsym = !((flags & O_NOFOLLOW) || ((flags & O_CREAT) && (flags & O_EXCL)));
int mask = ceph_caps_for_mode(ceph_flags_to_mode(cflags));
std::scoped_lock lock(client_lock);
int r = path_walk(path, &in, perms, followsym, mask);
InodeRef dirinode = nullptr;
if (dirfd) {
int r = get_fd_inode(*dirfd, &dirinode);
if (r < 0) {
return r;
}
}
int r = path_walk(path, &in, perms, followsym, mask, dirinode);
if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
return -CEPHFS_EEXIST;
#if defined(__linux__) && defined(O_PATH)
if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW) && !(flags & O_PATH))
#else
if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW))
if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW))
#endif
return -CEPHFS_ELOOP;
@ -9066,13 +9386,14 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms,
dirpath.pop_dentry();
InodeRef dir;
r = path_walk(dirpath, &dir, perms, true,
cct->_conf->client_permissions ? CEPH_CAP_AUTH_SHARED : 0);
if (r < 0)
cct->_conf->client_permissions ? CEPH_CAP_AUTH_SHARED : 0, dirinode);
if (r < 0) {
goto out;
}
if (cct->_conf->client_permissions) {
r = may_create(dir.get(), perms);
if (r < 0)
goto out;
goto out;
}
r = _create(dir.get(), dname.c_str(), flags, mode, &in, &fh, stripe_unit,
stripe_count, object_size, data_pool, &created, perms,
@ -9086,7 +9407,7 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms,
if (cct->_conf->client_permissions) {
r = may_open(in.get(), flags, perms);
if (r < 0)
goto out;
goto out;
}
}
@ -9101,8 +9422,42 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms,
}
out:
return r;
}
int Client::open(const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count,
int object_size, const char *data_pool, std::string alternate_name)
{
return openat(CEPHFS_AT_FDCWD, relpath, flags, perms, mode, stripe_unit,
stripe_count, object_size, data_pool, alternate_name);
}
int Client::_openat(int dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode, std::string alternate_name) {
return create_and_open(dirfd, relpath, flags, perms, mode, 0, 0, 0, NULL, alternate_name);
}
int Client::openat(int dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count, int object_size,
const char *data_pool, std::string alternate_name) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
ldout(cct, 3) << "openat enter(" << relpath << ")" << dendl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
tout(cct) << flags << std::endl;
tout(cct) << mode << std::endl;
std::scoped_lock locker(client_lock);
int r = create_and_open(dirfd, relpath, flags, perms, mode, stripe_unit, stripe_count,
object_size, data_pool, alternate_name);
tout(cct) << r << std::endl;
ldout(cct, 3) << "open exit(" << path << ", " << cflags << ") = " << r << dendl;
ldout(cct, 3) << "openat exit(" << relpath << ")" << dendl;
return r;
}
@ -9434,17 +9789,12 @@ int Client::_renew_caps(Inode *in)
return ret;
}
int Client::close(int fd)
int Client::_close(int fd)
{
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied())
return -CEPHFS_ENOTCONN;
ldout(cct, 3) << "close enter(" << fd << ")" << dendl;
tout(cct) << "close" << std::endl;
tout(cct) << fd << std::endl;
std::scoped_lock lock(client_lock);
Fh *fh = get_filehandle(fd);
if (!fh)
return -CEPHFS_EBADF;
@ -9455,6 +9805,14 @@ int Client::close(int fd)
return err;
}
int Client::close(int fd) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied())
return -CEPHFS_ENOTCONN;
std::scoped_lock lock(client_lock);
return _close(fd);
}
// ------------
// read, write
@ -10518,6 +10876,44 @@ int Client::fstatx(int fd, struct ceph_statx *stx, const UserPerm& perms,
return r;
}
int Client::statxat(int dirfd, const char *relpath,
struct ceph_statx *stx, const UserPerm& perms,
unsigned int want, unsigned int flags) {
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
if (!mref_reader.is_state_satisfied()) {
return -CEPHFS_ENOTCONN;
}
tout(cct) << __func__ << " flags " << hex << flags << " want " << want << dec << std::endl;
tout(cct) << dirfd << std::endl;
tout(cct) << relpath << std::endl;
unsigned mask = statx_to_mask(flags, want);
InodeRef dirinode;
std::scoped_lock lock(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
if (r < 0) {
return r;
}
InodeRef in;
filepath path(relpath);
r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask, dirinode);
if (r < 0) {
return r;
}
r = _getattr(in, mask, perms);
if (r < 0) {
ldout(cct, 3) << __func__ << " exit on error!" << dendl;
return r;
}
fill_statx(in, mask, stx);
ldout(cct, 3) << __func__ << " dirfd" << dirfd << ", r= " << r << dendl;
return r;
}
// not written yet, but i want to link!
int Client::chdir(const char *relpath, std::string &new_cwd,

View File

@ -331,6 +331,7 @@ public:
// namespace ops
int opendir(const char *name, dir_result_t **dirpp, const UserPerm& perms);
int fdopendir(int dirfd, dir_result_t **dirpp, const UserPerm& perms);
int closedir(dir_result_t *dirp);
/**
@ -372,17 +373,23 @@ public:
int may_delete(const char *relpath, const UserPerm& perms);
int link(const char *existing, const char *newname, const UserPerm& perm, std::string alternate_name="");
int unlink(const char *path, const UserPerm& perm);
int unlinkat(int dirfd, const char *relpath, int flags, const UserPerm& perm);
int rename(const char *from, const char *to, const UserPerm& perm, std::string alternate_name="");
// dirs
int mkdir(const char *path, mode_t mode, const UserPerm& perm, std::string alternate_name="");
int mkdirat(int dirfd, const char *relpath, mode_t mode, const UserPerm& perm,
std::string alternate_name="");
int mkdirs(const char *path, mode_t mode, const UserPerm& perms);
int rmdir(const char *path, const UserPerm& perms);
// symlinks
int readlink(const char *path, char *buf, loff_t size, const UserPerm& perms);
int readlinkat(int dirfd, const char *relpath, char *buf, loff_t size, const UserPerm& perms);
int symlink(const char *existing, const char *newname, const UserPerm& perms, std::string alternate_name="");
int symlinkat(const char *target, int dirfd, const char *relpath, const UserPerm& perms,
std::string alternate_name="");
// path traversal for high-level interface
int walk(std::string_view path, struct walk_dentry_result* result, const UserPerm& perms, bool followsym=true);
@ -405,12 +412,15 @@ public:
int fsetattrx(int fd, struct ceph_statx *stx, int mask, const UserPerm& perms);
int chmod(const char *path, mode_t mode, const UserPerm& perms);
int fchmod(int fd, mode_t mode, const UserPerm& perms);
int chmodat(int dirfd, const char *relpath, mode_t mode, int flags, const UserPerm& perms);
int lchmod(const char *path, mode_t mode, const UserPerm& perms);
int chown(const char *path, uid_t new_uid, gid_t new_gid,
const UserPerm& perms);
int fchown(int fd, uid_t new_uid, gid_t new_gid, const UserPerm& perms);
int lchown(const char *path, uid_t new_uid, gid_t new_gid,
const UserPerm& perms);
int chownat(int dirfd, const char *relpath, uid_t new_uid, gid_t new_gid,
int flags, const UserPerm& perms);
int utime(const char *path, struct utimbuf *buf, const UserPerm& perms);
int lutime(const char *path, struct utimbuf *buf, const UserPerm& perms);
int futime(int fd, struct utimbuf *buf, const UserPerm& perms);
@ -418,21 +428,38 @@ public:
int lutimes(const char *relpath, struct timeval times[2], const UserPerm& perms);
int futimes(int fd, struct timeval times[2], const UserPerm& perms);
int futimens(int fd, struct timespec times[2], const UserPerm& perms);
int utimensat(int dirfd, const char *relpath, struct timespec times[2], int flags,
const UserPerm& perms);
int flock(int fd, int operation, uint64_t owner);
int truncate(const char *path, loff_t size, const UserPerm& perms);
// file ops
int mknod(const char *path, mode_t mode, const UserPerm& perms, dev_t rdev=0);
int create_and_open(std::optional<int> dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool,
std::string alternate_name);
int open(const char *path, int flags, const UserPerm& perms, mode_t mode=0, std::string alternate_name="") {
return open(path, flags, perms, mode, 0, 0, 0, NULL, alternate_name);
}
int open(const char *path, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count, int object_size,
const char *data_pool, std::string alternate_name="");
int _openat(int dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode=0, std::string alternate_name="");
int openat(int dirfd, const char *relpath, int flags, const UserPerm& perms,
mode_t mode, int stripe_unit, int stripe_count,
int object_size, const char *data_pool, std::string alternate_name);
int openat(int dirfd, const char *path, int flags, const UserPerm& perms, mode_t mode=0,
std::string alternate_name="") {
return openat(dirfd, path, flags, perms, mode, 0, 0, 0, NULL, alternate_name);
}
int lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name,
const UserPerm& perms);
int lookup_ino(inodeno_t ino, const UserPerm& perms, Inode **inode=NULL);
int lookup_name(Inode *in, Inode *parent, const UserPerm& perms);
int _close(int fd);
int close(int fd);
loff_t lseek(int fd, loff_t offset, int whence);
int read(int fd, char *buf, loff_t size, loff_t offset=-1);
@ -446,6 +473,9 @@ public:
int mask=CEPH_STAT_CAP_INODE_ALL);
int fstatx(int fd, struct ceph_statx *stx, const UserPerm& perms,
unsigned int want, unsigned int flags);
int statxat(int dirfd, const char *relpath,
struct ceph_statx *stx, const UserPerm& perms,
unsigned int want, unsigned int flags);
int fallocate(int fd, int mode, loff_t offset, loff_t length);
// full path xattr ops
@ -909,9 +939,10 @@ protected:
void handle_client_reply(const MConstRef<MClientReply>& reply);
bool is_dir_operation(MetaRequest *request);
int path_walk(const filepath& fp, struct walk_dentry_result* result, const UserPerm& perms, bool followsym=true, int mask=0);
int path_walk(const filepath& fp, struct walk_dentry_result* result, const UserPerm& perms, bool followsym=true, int mask=0,
InodeRef dirinode=nullptr);
int path_walk(const filepath& fp, InodeRef *end, const UserPerm& perms,
bool followsym=true, int mask=0);
bool followsym=true, int mask=0, InodeRef dirinode=nullptr);
// fake inode number for 32-bits ino_t
void _assign_faked_ino(Inode *in);
@ -950,6 +981,7 @@ protected:
return NULL;
return it->second;
}
int get_fd_inode(int fd, InodeRef *in);
// helpers
void wake_up_session_caps(MetaSession *s, bool reconnect);

View File

@ -533,6 +533,16 @@ int ceph_chdir(struct ceph_mount_info *cmount, const char *path);
*/
int ceph_opendir(struct ceph_mount_info *cmount, const char *name, struct ceph_dir_result **dirpp);
/**
* Open a directory referred to by a file descriptor
*
* @param cmount the ceph mount handle to use to open the directory
* @param dirfd open file descriptor for the directory
* @param dirpp the directory result pointer structure to fill in
* @returns 0 on success or negative error code otherwise
*/
int ceph_fdopendir(struct ceph_mount_info *cmount, int dirfd, struct ceph_dir_result **dirpp);
/**
* Close the open directory.
*
@ -651,6 +661,17 @@ void ceph_seekdir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
*/
int ceph_mkdir(struct ceph_mount_info *cmount, const char *path, mode_t mode);
/**
* Create a directory relative to a file descriptor
*
* @param cmount the ceph mount handle to use for making the directory.
* @param dirfd open file descriptor for a directory (or CEPHFS_AT_FDCWD)
* @param relpath the path of the directory to create.
* @param mode the permissions the directory should have once created.
* @returns 0 on success or a negative return code on error.
*/
int ceph_mkdirat(struct ceph_mount_info *cmount, int dirfd, const char *relpath, mode_t mode);
/**
* Create a snapshot
*
@ -727,6 +748,19 @@ int ceph_link(struct ceph_mount_info *cmount, const char *existing, const char *
*/
int ceph_readlink(struct ceph_mount_info *cmount, const char *path, char *buf, int64_t size);
/**
* Read a symbolic link relative to a file descriptor
*
* @param cmount the ceph mount handle to use for creating the link.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath the path to the symlink to read
* @param buf the buffer to hold the path of the file that the symlink points to.
* @param size the length of the buffer
* @returns number of bytes copied on success or negative error code on failure
*/
int ceph_readlinkat(struct ceph_mount_info *cmount, int dirfd, const char *relpath, char *buf,
int64_t size);
/**
* Creates a symbolic link.
*
@ -737,6 +771,18 @@ int ceph_readlink(struct ceph_mount_info *cmount, const char *path, char *buf, i
*/
int ceph_symlink(struct ceph_mount_info *cmount, const char *existing, const char *newname);
/**
* Creates a symbolic link relative to a file descriptor
*
* @param cmount the ceph mount handle to use for creating the symbolic link.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param existing the path to the existing file/directory to link to.
* @param newname the path to the new file/directory to link from.
* @returns 0 on success or a negative return code on failure.
*/
int ceph_symlinkat(struct ceph_mount_info *cmount, const char *existing, int dirfd,
const char *newname);
/** @} links */
/**
@ -766,6 +812,19 @@ int ceph_may_delete(struct ceph_mount_info *cmount, const char *path);
*/
int ceph_unlink(struct ceph_mount_info *cmount, const char *path);
/**
* Removes a file, link, or symbolic link relative to a file descriptor.
* If the file/link has multiple links to it, the file will not
* disappear from the namespace until all references to it are removed.
*
* @param cmount the ceph mount handle to use for performing the unlink.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath the path of the file or link to unlink.
* @param flags bitfield that can be used to set AT_* modifier flags (only AT_REMOVEDIR)
* @returns 0 on success or negative error code on failure.
*/
int ceph_unlinkat(struct ceph_mount_info *cmount, int dirfd, const char *relpath, int flags);
/**
* Rename a file or directory.
*
@ -789,6 +848,20 @@ int ceph_rename(struct ceph_mount_info *cmount, const char *from, const char *to
int ceph_fstatx(struct ceph_mount_info *cmount, int fd, struct ceph_statx *stx,
unsigned int want, unsigned int flags);
/**
* Get attributes of a file relative to a file descriptor
*
* @param cmount the ceph mount handle to use for performing the stat.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath to the file/directory to get statistics of
* @param stx the ceph_statx struct that will be filled in with the file's statistics.
* @param want bitfield of CEPH_STATX_* flags showing designed attributes
* @param flags bitfield that can be used to set AT_* modifier flags (only AT_NO_ATTR_SYNC and AT_SYMLINK_NOFOLLOW)
* @returns 0 on success or negative error code on failure.
*/
int ceph_statxat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
struct ceph_statx *stx, unsigned int want, unsigned int flags);
/**
* Get a file's extended statistics and attributes.
*
@ -896,6 +969,19 @@ int ceph_lchmod(struct ceph_mount_info *cmount, const char *path, mode_t mode);
*/
int ceph_fchmod(struct ceph_mount_info *cmount, int fd, mode_t mode);
/**
* Change the mode bits (permissions) of a file relative to a file descriptor.
*
* @param cmount the ceph mount handle to use for performing the chown.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath the relpath of the file/directory to change the ownership of.
* @param mode the new permissions to set.
* @param flags bitfield that can be used to set AT_* modifier flags (AT_SYMLINK_NOFOLLOW)
* @returns 0 on success or negative error code on failure.
*/
int ceph_chmodat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
mode_t mode, int flags);
/**
* Change the ownership of a file/directory.
*
@ -929,6 +1015,20 @@ int ceph_fchown(struct ceph_mount_info *cmount, int fd, int uid, int gid);
*/
int ceph_lchown(struct ceph_mount_info *cmount, const char *path, int uid, int gid);
/**
* Change the ownership of a file/directory releative to a file descriptor.
*
* @param cmount the ceph mount handle to use for performing the chown.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath the relpath of the file/directory to change the ownership of.
* @param uid the user id to set on the file/directory.
* @param gid the group id to set on the file/directory.
* @param flags bitfield that can be used to set AT_* modifier flags (AT_SYMLINK_NOFOLLOW)
* @returns 0 on success or negative error code on failure.
*/
int ceph_chownat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
uid_t uid, gid_t gid, int flags);
/**
* Change file/directory last access and modification times.
*
@ -989,6 +1089,21 @@ int ceph_futimes(struct ceph_mount_info *cmount, int fd, struct timeval times[2]
*/
int ceph_futimens(struct ceph_mount_info *cmount, int fd, struct timespec times[2]);
/**
* Change file/directory last access and modification times relative
* to a file descriptor.
*
* @param cmount the ceph mount handle to use for performing the utime.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath the relpath of the file/directory to change the ownership of.
* @param dirfd the fd of the open file/directory to set the time values of.
* @param times holding the access and modification times to set on the file.
* @param flags bitfield that can be used to set AT_* modifier flags (AT_SYMLINK_NOFOLLOW)
* @returns 0 on success or negative error code on failure.
*/
int ceph_utimensat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
struct timespec times[2], int flags);
/**
* Apply or remove an advisory lock.
*
@ -1041,6 +1156,20 @@ int ceph_mknod(struct ceph_mount_info *cmount, const char *path, mode_t mode, de
*/
int ceph_open(struct ceph_mount_info *cmount, const char *path, int flags, mode_t mode);
/**
* Create and/or open a file relative to a directory
*
* @param cmount the ceph mount handle to use for performing the open.
* @param dirfd open file descriptor (or CEPHFS_AT_FDCWD)
* @param relpath the path of the file to open. If the flags parameter includes O_CREAT,
* the file will first be created before opening.
* @param flags a set of option masks that control how the file is created/opened.
* @param mode the permissions to place on the file if the file does not exist and O_CREAT
* is specified in the flags.
* @returns a non-negative file descriptor number on success or a negative error code on failure.
*/
int ceph_openat(struct ceph_mount_info *cmount, int dirfd, const char *relpath, int flags, mode_t mode);
/**
* Create and/or open a file with a specific file layout.
*

View File

@ -46,6 +46,10 @@ class JSONObj;
#define CEPHFS_ETIME 62
#define CEPHFS_EOLDSNAPC 85
// taken from linux kernel: include/uapi/linux/fcntl.h
#define CEPHFS_AT_FDCWD -100 /* Special value used to indicate
openat should use the current
working directory. */
// --------------------------------------
// ino

View File

@ -634,6 +634,14 @@ extern "C" int ceph_opendir(struct ceph_mount_info *cmount,
return cmount->get_client()->opendir(name, (dir_result_t **)dirpp, cmount->default_perms);
}
extern "C" int ceph_fdopendir(struct ceph_mount_info *cmount, int dirfd,
struct ceph_dir_result **dirpp)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->fdopendir(dirfd, (dir_result_t **)dirpp, cmount->default_perms);
}
extern "C" int ceph_closedir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp)
{
if (!cmount->is_mounted())
@ -728,6 +736,13 @@ extern "C" int ceph_unlink(struct ceph_mount_info *cmount, const char *path)
return cmount->get_client()->unlink(path, cmount->default_perms);
}
extern "C" int ceph_unlinkat(struct ceph_mount_info *cmount, int dirfd, const char *relpath, int flags)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->unlinkat(dirfd, relpath, flags, cmount->default_perms);
}
extern "C" int ceph_rename(struct ceph_mount_info *cmount, const char *from,
const char *to)
{
@ -744,6 +759,14 @@ extern "C" int ceph_mkdir(struct ceph_mount_info *cmount, const char *path, mode
return cmount->get_client()->mkdir(path, mode, cmount->default_perms);
}
extern "C" int ceph_mkdirat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
mode_t mode)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->mkdirat(dirfd, relpath, mode, cmount->default_perms);
}
extern "C" int ceph_mksnap(struct ceph_mount_info *cmount, const char *path, const char *name,
mode_t mode, struct snap_metadata *snap_metadata, size_t nr_snap_metadata)
{
@ -788,6 +811,14 @@ extern "C" int ceph_readlink(struct ceph_mount_info *cmount, const char *path,
return cmount->get_client()->readlink(path, buf, size, cmount->default_perms);
}
extern "C" int ceph_readlinkat(struct ceph_mount_info *cmount, int dirfd,
const char *relpath, char *buf, int64_t size)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->readlinkat(dirfd, relpath, buf, size, cmount->default_perms);
}
extern "C" int ceph_symlink(struct ceph_mount_info *cmount, const char *existing,
const char *newname)
{
@ -796,6 +827,14 @@ extern "C" int ceph_symlink(struct ceph_mount_info *cmount, const char *existing
return cmount->get_client()->symlink(existing, newname, cmount->default_perms);
}
extern "C" int ceph_symlinkat(struct ceph_mount_info *cmount, const char *existing, int dirfd,
const char *newname)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->symlinkat(existing, dirfd, newname, cmount->default_perms);
}
extern "C" int ceph_fstatx(struct ceph_mount_info *cmount, int fd, struct ceph_statx *stx,
unsigned int want, unsigned int flags)
{
@ -807,6 +846,17 @@ extern "C" int ceph_fstatx(struct ceph_mount_info *cmount, int fd, struct ceph_s
want, flags);
}
extern "C" int ceph_statxat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
struct ceph_statx *stx, unsigned int want, unsigned int flags)
{
if (!cmount->is_mounted())
return -ENOTCONN;
if (flags & ~CEPH_REQ_FLAG_MASK)
return -EINVAL;
return cmount->get_client()->statxat(dirfd, relpath, stx, cmount->default_perms,
want, flags);
}
extern "C" int ceph_statx(struct ceph_mount_info *cmount, const char *path,
struct ceph_statx *stx, unsigned int want, unsigned int flags)
{
@ -964,6 +1014,14 @@ extern "C" int ceph_fchmod(struct ceph_mount_info *cmount, int fd, mode_t mode)
return -ENOTCONN;
return cmount->get_client()->fchmod(fd, mode, cmount->default_perms);
}
extern "C" int ceph_chmodat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
mode_t mode, int flags) {
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->chmodat(dirfd, relpath, mode, flags, cmount->default_perms);
}
extern "C" int ceph_chown(struct ceph_mount_info *cmount, const char *path,
int uid, int gid)
{
@ -986,6 +1044,12 @@ extern "C" int ceph_lchown(struct ceph_mount_info *cmount, const char *path,
return cmount->get_client()->lchown(path, uid, gid, cmount->default_perms);
}
extern "C" int ceph_chownat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
uid_t uid, gid_t gid, int flags) {
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->chownat(dirfd, relpath, uid, gid, flags, cmount->default_perms);
}
extern "C" int ceph_utime(struct ceph_mount_info *cmount, const char *path,
struct utimbuf *buf)
@ -1035,6 +1099,13 @@ extern "C" int ceph_futimens(struct ceph_mount_info *cmount, int fd,
return cmount->get_client()->futimens(fd, times, cmount->default_perms);
}
extern "C" int ceph_utimensat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
struct timespec times[2], int flags) {
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->utimensat(dirfd, relpath, times, flags, cmount->default_perms);
}
extern "C" int ceph_flock(struct ceph_mount_info *cmount, int fd, int operation,
uint64_t owner)
{
@ -1068,6 +1139,14 @@ extern "C" int ceph_open(struct ceph_mount_info *cmount, const char *path,
return cmount->get_client()->open(path, flags, cmount->default_perms, mode);
}
extern "C" int ceph_openat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
int flags, mode_t mode)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->openat(dirfd, relpath, flags, cmount->default_perms, mode);
}
extern "C" int ceph_open_layout(struct ceph_mount_info *cmount, const char *path, int flags,
mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool)
{