mirror of
https://github.com/ceph/ceph
synced 2025-04-01 00:26:47 +00:00
libcephfs: introduce basic *at() calls
Signed-off-by: Venky Shankar <vshankar@redhat.com>
This commit is contained in:
parent
52c672350f
commit
3831aa12f3
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user