Merge pull request #11647 from ceph/wip-jlayton-cephfs

libcephfs client API overhaul and update

Reviewed-by: John Spray <john.spray@redhat.com>
This commit is contained in:
John Spray 2016-11-07 21:07:40 +01:00 committed by GitHub
commit f80c7a8f20
19 changed files with 711 additions and 467 deletions

View File

@ -218,7 +218,7 @@ Group: System Environment/Base
Requires: ceph-common = %{epoch}:%{version}-%{release}
Requires: librbd1 = %{epoch}:%{version}-%{release}
Requires: librados2 = %{epoch}:%{version}-%{release}
Requires: libcephfs1 = %{epoch}:%{version}-%{release}
Requires: libcephfs2 = %{epoch}:%{version}-%{release}
Requires: librgw2 = %{epoch}:%{version}-%{release}
%if 0%{with selinux}
Requires: ceph-selinux = %{epoch}:%{version}-%{release}
@ -247,7 +247,7 @@ Summary: Ceph Common
Group: System Environment/Base
Requires: librbd1 = %{epoch}:%{version}-%{release}
Requires: librados2 = %{epoch}:%{version}-%{release}
Requires: libcephfs1 = %{epoch}:%{version}-%{release}
Requires: libcephfs2 = %{epoch}:%{version}-%{release}
Requires: python-rados = %{epoch}:%{version}-%{release}
Requires: python-rbd = %{epoch}:%{version}-%{release}
Requires: python-cephfs = %{epoch}:%{version}-%{release}
@ -517,7 +517,7 @@ Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release}
This package contains Python 3 libraries for interacting with Cephs RADOS
block device.
%package -n libcephfs1
%package -n libcephfs2
Summary: Ceph distributed file system client library
Group: System Environment/Libraries
License: LGPL-2.0
@ -525,7 +525,7 @@ License: LGPL-2.0
Obsoletes: ceph-libs < %{epoch}:%{version}-%{release}
Obsoletes: ceph-libcephfs
%endif
%description -n libcephfs1
%description -n libcephfs2
Ceph is a distributed network file system designed to provide excellent
performance, reliability, and scalability. This is a shared library
allowing applications to access a Ceph distributed file system via a
@ -535,11 +535,11 @@ POSIX-like interface.
Summary: Ceph distributed file system headers
Group: Development/Libraries
License: LGPL-2.0
Requires: libcephfs1 = %{epoch}:%{version}-%{release}
Requires: libcephfs2 = %{epoch}:%{version}-%{release}
Requires: librados-devel = %{epoch}:%{version}-%{release}
Obsoletes: ceph-devel < %{epoch}:%{version}-%{release}
Provides: libcephfs1-devel = %{epoch}:%{version}-%{release}
Obsoletes: libcephfs1-devel < %{epoch}:%{version}-%{release}
Provides: libcephfs2-devel = %{epoch}:%{version}-%{release}
Obsoletes: libcephfs2-devel < %{epoch}:%{version}-%{release}
%description -n libcephfs-devel
This package contains libraries and headers needed to develop programs
that use Cephs distributed file system.
@ -548,7 +548,7 @@ that use Cephs distributed file system.
Summary: Python 2 libraries for Ceph distributed file system
Group: System Environment/Libraries
License: LGPL-2.0
Requires: libcephfs1 = %{epoch}:%{version}-%{release}
Requires: libcephfs2 = %{epoch}:%{version}-%{release}
Requires: python-rados = %{epoch}:%{version}-%{release}
Obsoletes: python-ceph < %{epoch}:%{version}-%{release}
%description -n python-cephfs
@ -559,7 +559,7 @@ file system.
Summary: Python 3 libraries for Ceph distributed file system
Group: System Environment/Libraries
License: LGPL-2.0
Requires: libcephfs1 = %{epoch}:%{version}-%{release}
Requires: libcephfs2 = %{epoch}:%{version}-%{release}
Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release}
%description -n python%{python3_pkgversion}-cephfs
This package contains Python 3 libraries for interacting with Cephs distributed
@ -593,7 +593,7 @@ Summary: Java Native Interface library for CephFS Java bindings
Group: System Environment/Libraries
License: LGPL-2.0
Requires: java
Requires: libcephfs1 = %{epoch}:%{version}-%{release}
Requires: libcephfs2 = %{epoch}:%{version}-%{release}
%description -n libcephfs_jni1
This package contains the Java Native Interface library for CephFS Java
bindings.
@ -1428,13 +1428,13 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1
%{python3_sitearch}/rbd.cpython*.so
%{python3_sitearch}/rbd-*.egg-info
%files -n libcephfs1
%files -n libcephfs2
%defattr(-,root,root,-)
%{_libdir}/libcephfs.so.*
%post -n libcephfs1 -p /sbin/ldconfig
%post -n libcephfs2 -p /sbin/ldconfig
%postun -n libcephfs1 -p /sbin/ldconfig
%postun -n libcephfs2 -p /sbin/ldconfig
%files -n libcephfs-devel
%defattr(-,root,root,-)

4
debian/.gitignore vendored
View File

@ -21,9 +21,9 @@
/*.debhelper
/ceph
/files
/libcephfs1-dbg
/libcephfs2-dbg
/libcephfs-dev
/libcephfs1
/libcephfs2
/librados2-dbg
/librados-dev
/librados2

24
debian/control vendored
View File

@ -120,7 +120,7 @@ Depends: ceph-base (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
Recommends: ceph-fuse (= ${binary:Version}),
libcephfs1 (= ${binary:Version})
libcephfs2 (= ${binary:Version})
Replaces: ceph (<< 0.93-417)
Breaks: ceph (<< 0.93-417)
Description: metadata server for the ceph distributed file system
@ -516,7 +516,7 @@ Description: RADOS block device client library (development files)
This package contains development files needed for building applications that
link against librbd1.
Package: libcephfs1
Package: libcephfs2
Conflicts: libceph, libceph1, libcephfs
Replaces: libceph, libceph1, libcephfs
Architecture: linux-any
@ -529,28 +529,28 @@ Description: Ceph distributed file system client library
shared library allowing applications to access a Ceph distributed
file system via a POSIX-like interface.
Package: libcephfs1-dbg
Package: libcephfs2-dbg
Architecture: linux-any
Section: debug
Priority: extra
Depends: libcephfs1 (= ${binary:Version}), ${misc:Depends}
Depends: libcephfs2 (= ${binary:Version}), ${misc:Depends}
Conflicts: libceph1-dbg
Replaces: libceph1-dbg
Description: debugging symbols for libcephfs1
Description: debugging symbols for libcephfs2
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage. This is a
shared library allowing applications to access a Ceph distributed
file system via a POSIX-like interface.
.
This package contains debugging symbols for libcephfs1.
This package contains debugging symbols for libcephfs2.
Package: libcephfs-dev
Architecture: linux-any
Section: libdevel
Depends: libcephfs1 (= ${binary:Version}), ${misc:Depends}
Conflicts: libceph-dev, libceph1-dev, libcephfs1-dev
Replaces: libceph-dev, libceph1-dev, libcephfs1-dev
Depends: libcephfs2 (= ${binary:Version}), ${misc:Depends}
Conflicts: libceph-dev, libceph1-dev, libcephfs2-dev
Replaces: libceph-dev, libceph1-dev, libcephfs2-dev
Description: Ceph distributed file system client library (development files)
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@ -726,7 +726,7 @@ Description: Python 3 libraries for the Ceph librbd library
Package: python-cephfs
Architecture: linux-any
Section: python
Depends: libcephfs1 (= ${binary:Version}),
Depends: libcephfs2 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
${python:Depends}
@ -743,7 +743,7 @@ Description: Python 2 libraries for the Ceph libcephfs library
Package: python3-cephfs
Architecture: linux-any
Section: python
Depends: libcephfs1 (= ${binary:Version}),
Depends: libcephfs2 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
${python3:Depends}
@ -776,6 +776,6 @@ Description: Java libraries for the Ceph File System
Package: libcephfs-jni
Architecture: linux-any
Section: java
Depends: libcephfs1 (= ${binary:Version}), ${java:Depends},
Depends: libcephfs2 (= ${binary:Version}), ${java:Depends},
${misc:Depends}, ${shlibs:Depends}
Description: Java Native Interface library for CephFS Java bindings

2
debian/rules vendored
View File

@ -130,7 +130,7 @@ override_dh_strip:
dh_strip -plibrados2 --dbg-package=librados2-dbg
dh_strip -plibradosstriper1 --dbg-package=libradosstriper1-dbg
dh_strip -plibrbd1 --dbg-package=librbd1-dbg
dh_strip -plibcephfs1 --dbg-package=libcephfs1-dbg
dh_strip -plibcephfs2 --dbg-package=libcephfs2-dbg
dh_strip -plibrgw2 --dbg-package=librgw2-dbg
dh_strip -pradosgw --dbg-package=radosgw-dbg
dh_strip -pceph-test --dbg-package=ceph-test-dbg

View File

@ -19,8 +19,8 @@ sudo apt-get -y purge librados-dev
sudo apt-get -y purge librbd1
sudo apt-get -y purge librbd1-dbg
sudo apt-get -y purge librbd-dev
sudo apt-get -y purge libcephfs1
sudo apt-get -y purge libcephfs1-dbg
sudo apt-get -y purge libcephfs2
sudo apt-get -y purge libcephfs2-dbg
sudo apt-get -y purge libcephfs-dev
sudo apt-get -y purge radosgw
sudo apt-get -y purge radosgw-dbg

View File

@ -806,8 +806,8 @@ if(WITH_LIBCEPHFS)
endforeach()
set_target_properties(cephfs PROPERTIES
OUTPUT_NAME cephfs
VERSION 1.0.0
SOVERSION 1
VERSION 2.0.0
SOVERSION 2
LINK_FLAGS ${CEPHFS_LINK_FLAGS})
endif(ENABLE_SHARED)
install(TARGETS cephfs DESTINATION ${CMAKE_INSTALL_LIBDIR})

View File

@ -6568,10 +6568,12 @@ force_request:
CEPH_CAP_FILE_WR;
}
if (mask & CEPH_SETATTR_SIZE) {
if ((unsigned long)stx->stx_size < mdsmap->get_max_filesize())
if ((unsigned long)stx->stx_size < mdsmap->get_max_filesize()) {
req->head.args.setattr.size = stx->stx_size;
else { //too big!
ldout(cct,10) << "changing size to " << stx->stx_size << dendl;
} else { //too big!
put_request(req);
ldout(cct,10) << "unable to set size to " << stx->stx_size << ". Too large!" << dendl;
return -EFBIG;
}
req->inode_drop |= CEPH_CAP_AUTH_SHARED | CEPH_CAP_FILE_RD |
@ -6682,6 +6684,23 @@ int Client::fsetattr(int fd, struct stat *attr, int mask, const UserPerm& perms)
return _setattr(f->inode, attr, mask, perms);
}
int Client::fsetattrx(int fd, struct ceph_statx *stx, int mask, const UserPerm& perms)
{
Mutex::Locker lock(client_lock);
tout(cct) << "fsetattr" << std::endl;
tout(cct) << fd << std::endl;
tout(cct) << mask << std::endl;
Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
#if defined(__linux__) && defined(O_PATH)
if (f->flags & O_PATH)
return -EBADF;
#endif
return _setattrx(f->inode, stx, mask, perms);
}
int Client::stat(const char *relpath, struct stat *stbuf, const UserPerm& perms,
frag_info_t *dirstat, int mask)
{
@ -7307,7 +7326,8 @@ struct dentry_off_lt {
}
};
int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p)
int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
int caps, bool getref)
{
assert(client_lock.is_locked());
ldout(cct, 10) << "_readdir_cache_cb " << dirp << " on " << dirp->inode->ino
@ -7343,21 +7363,30 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p)
continue;
}
struct stat st;
int r = _getattr(dn->inode, caps, dirp->perms);
if (r < 0)
return r;
struct ceph_statx stx;
struct dirent de;
int stmask = fill_stat(dn->inode, &st);
fill_statx(dn->inode, caps, &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);
Inode *in = NULL;
fill_dirent(&de, dn->name.c_str(), stx.stx_mode, stx.stx_ino, next_off);
if (getref) {
in = dn->inode.get();
_ll_get(in);
}
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
r = cb(p, &de, &stx, next_off, in); // _next_ offset
client_lock.Lock();
ldout(cct, 15) << " de " << de.d_name << " off " << hex << dn->offset << dec
<< " = " << r << dendl;
@ -7380,8 +7409,11 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p)
return 0;
}
int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p,
unsigned want, unsigned flags, bool getref)
{
int caps = statx_to_mask(flags, want);
Mutex::Locker lock(client_lock);
dir_result_t *dirp = static_cast<dir_result_t*>(d);
@ -7391,9 +7423,9 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
<< " 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;
@ -7405,11 +7437,22 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
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);
int r;
r = _getattr(diri, caps, dirp->perms);
if (r < 0)
return r;
fill_statx(diri, caps, &stx);
fill_dirent(&de, ".", S_IFDIR, stx.stx_ino, next_off);
Inode *inode = NULL;
if (getref) {
inode = diri.get();
_ll_get(inode);
}
client_lock.Unlock();
int r = cb(p, &de, &st, -1, next_off);
r = cb(p, &de, &stx, next_off, inode);
client_lock.Lock();
if (r < 0)
return r;
@ -7427,11 +7470,22 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
else
in = diri->get_first_parent()->inode;
fill_stat(in, &st);
fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off);
int r;
r = _getattr(diri, caps, dirp->perms);
if (r < 0)
return r;
fill_statx(in, caps, &stx);
fill_dirent(&de, "..", S_IFDIR, stx.stx_ino, next_off);
Inode *inode = NULL;
if (getref) {
inode = in.get();
_ll_get(inode);
}
client_lock.Unlock();
int r = cb(p, &de, &st, -1, next_off);
r = cb(p, &de, &stx, next_off, inode);
client_lock.Lock();
if (r < 0)
return r;
@ -7450,7 +7504,7 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
if (dirp->inode->snapid != CEPH_SNAPDIR &&
dirp->inode->is_complete_and_ordered() &&
dirp->inode->caps_issued_mask(CEPH_CAP_FILE_SHARED)) {
int err = _readdir_cache_cb(dirp, cb, p);
int err = _readdir_cache_cb(dirp, cb, p, caps, getref);
if (err != -EAGAIN)
return err;
}
@ -7459,12 +7513,14 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
if (dirp->at_end())
return 0;
bool check_caps = true;
if (!dirp->is_cached()) {
int r = _readdir_get_frag(dirp);
if (r)
return r;
// _readdir_get_frag () may updates dirp->offset if the replied dirfrag is
// different than the requested one. (our dirfragtree was outdated)
check_caps = false;
}
frag_t fg = dirp->buffer_frag;
@ -7478,11 +7534,25 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
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);
int r;
if (check_caps) {
r = _getattr(entry.inode, caps, dirp->perms);
if (r < 0)
return r;
}
fill_statx(entry.inode, caps, &stx);
fill_dirent(&de, entry.name.c_str(), stx.stx_mode, stx.stx_ino, next_off);
Inode *inode = NULL;
if (getref) {
inode = entry.inode.get();
_ll_get(inode);
}
client_lock.Unlock();
int r = cb(p, &de, &st, stmask, next_off); // _next_ offset
r = cb(p, &de, &stx, next_off, inode); // _next_ offset
client_lock.Lock();
ldout(cct, 15) << " de " << de.d_name << " off " << hex << next_off - 1 << dec
@ -7532,7 +7602,7 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
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, NULL);
}
/*
@ -7546,13 +7616,14 @@ 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;
Inode *inode;
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,
Inode *in)
{
single_readdir *c = static_cast<single_readdir *>(p);
@ -7560,10 +7631,9 @@ 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->inode = in;
c->full = true;
return 1;
}
@ -7571,13 +7641,11 @@ 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.inode = NULL;
sr.full = false;
// our callback fills the dirent and sets sr.full=true on first
@ -7593,19 +7661,23 @@ 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, Inode **out)
{
single_readdir sr;
sr.de = de;
sr.st = st;
sr.stmask = stmask;
sr.stx = stx;
sr.inode = NULL;
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, want, flags, out);
if (r < -1)
return r;
if (out)
*out = sr.inode;
if (sr.full)
return 1;
return 0;
@ -7620,7 +7692,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, Inode *in)
{
struct getdents_result *c = static_cast<getdents_result *>(p);
@ -7672,7 +7745,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, Inode *in)
{
getdir_result *r = static_cast<getdir_result *>(p);
@ -9769,32 +9842,71 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr,
return r;
}
int Client::ll_walk(const char* name, Inode **out, struct stat *attr,
const UserPerm& perms)
int Client::ll_lookupx(Inode *parent, const char *name, Inode **out,
struct ceph_statx *stx, unsigned want, unsigned flags,
const UserPerm& perms)
{
Mutex::Locker lock(client_lock);
ldout(cct, 3) << "ll_lookupx " << parent << " " << name << dendl;
tout(cct) << "ll_lookupx" << std::endl;
tout(cct) << name << std::endl;
int r = 0;
if (!cct->_conf->fuse_default_permissions) {
r = may_lookup(parent, perms);
if (r < 0)
return r;
}
string dname(name);
InodeRef in;
unsigned mask = statx_to_mask(flags, want);
r = _lookup(parent, dname, mask, &in, perms);
if (r < 0) {
stx->stx_ino = 0;
stx->stx_mask = 0;
} else {
assert(in);
fill_statx(in, mask, stx);
_ll_get(in.get());
}
ldout(cct, 3) << "ll_lookupx " << parent << " " << name
<< " -> " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
tout(cct) << stx->stx_ino << std::endl;
*out = in.get();
return r;
}
int Client::ll_walk(const char* name, Inode **out, struct ceph_statx *stx,
unsigned int want, unsigned int flags, const UserPerm& perms)
{
Mutex::Locker lock(client_lock);
filepath fp(name, 0);
InodeRef in;
int rc;
unsigned mask = statx_to_mask(flags, want);
ldout(cct, 3) << "ll_walk" << name << dendl;
tout(cct) << "ll_walk" << std::endl;
tout(cct) << name << std::endl;
rc = path_walk(fp, &in, perms, false, CEPH_STAT_CAP_INODE_ALL);
rc = path_walk(fp, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask);
if (rc < 0) {
attr->st_ino = 0;
/* zero out mask, just in case... */
stx->stx_mask = 0;
stx->stx_ino = 0;
*out = NULL;
return rc;
} else {
assert(in);
fill_stat(in, attr);
fill_statx(in, mask, stx);
*out = in.get();
return 0;
}
}
void Client::_ll_get(Inode *in)
{
if (in->ll_ref == 0) {
@ -10846,6 +10958,42 @@ int Client::ll_mknod(Inode *parent, const char *name, mode_t mode,
return r;
}
int Client::ll_mknodx(Inode *parent, const char *name, mode_t mode,
dev_t rdev, Inode **out,
struct ceph_statx *stx, unsigned want, unsigned flags,
const UserPerm& perms)
{
unsigned caps = statx_to_mask(flags, want);
Mutex::Locker lock(client_lock);
vinodeno_t vparent = _get_vino(parent);
ldout(cct, 3) << "ll_mknodx " << vparent << " " << name << dendl;
tout(cct) << "ll_mknodx" << std::endl;
tout(cct) << vparent.ino.val << std::endl;
tout(cct) << name << std::endl;
tout(cct) << mode << std::endl;
tout(cct) << rdev << std::endl;
if (!cct->_conf->fuse_default_permissions) {
int r = may_create(parent, perms);
if (r < 0)
return r;
}
InodeRef in;
int r = _mknod(parent, name, mode, rdev, perms, &in);
if (r == 0) {
fill_statx(in, caps, stx);
_ll_get(in.get());
}
tout(cct) << stx->stx_ino << std::endl;
ldout(cct, 3) << "ll_mknodx " << vparent << " " << name
<< " = " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
*out = in.get();
return r;
}
int Client::_create(Inode *dir, const char *name, int flags, mode_t mode,
InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count,
int object_size, const char *data_pool, bool *created,
@ -11027,6 +11175,42 @@ int Client::ll_mkdir(Inode *parent, const char *name, mode_t mode,
return r;
}
int Client::ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out,
struct ceph_statx *stx, unsigned want, unsigned flags,
const UserPerm& perms)
{
Mutex::Locker lock(client_lock);
vinodeno_t vparent = _get_vino(parent);
ldout(cct, 3) << "ll_mkdirx " << vparent << " " << name << dendl;
tout(cct) << "ll_mkdirx" << std::endl;
tout(cct) << vparent.ino.val << std::endl;
tout(cct) << name << std::endl;
tout(cct) << mode << std::endl;
if (!cct->_conf->fuse_default_permissions) {
int r = may_create(parent, perms);
if (r < 0)
return r;
}
InodeRef in;
int r = _mkdir(parent, name, mode, perms, &in);
if (r == 0) {
fill_statx(in, statx_to_mask(flags, want), stx);
_ll_get(in.get());
} else {
stx->stx_ino = 0;
stx->stx_mask = 0;
}
tout(cct) << stx->stx_ino << std::endl;
ldout(cct, 3) << "ll_mkdirx " << vparent << " " << name
<< " = " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
*out = in.get();
return r;
}
int Client::_symlink(Inode *dir, const char *name, const char *target,
const UserPerm& perms, InodeRef *inp)
{
@ -11106,6 +11290,40 @@ int Client::ll_symlink(Inode *parent, const char *name, const char *value,
return r;
}
int Client::ll_symlinkx(Inode *parent, const char *name, const char *value,
Inode **out, struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm& perms)
{
Mutex::Locker lock(client_lock);
vinodeno_t vparent = _get_vino(parent);
ldout(cct, 3) << "ll_symlinkx " << vparent << " " << name << " -> " << value
<< dendl;
tout(cct) << "ll_symlinkx" << std::endl;
tout(cct) << vparent.ino.val << std::endl;
tout(cct) << name << std::endl;
tout(cct) << value << std::endl;
if (!cct->_conf->fuse_default_permissions) {
int r = may_create(parent, perms);
if (r < 0)
return r;
}
InodeRef in;
int r = _symlink(parent, name, value, perms, &in);
if (r == 0) {
fill_statx(in, statx_to_mask(flags, want), stx);
_ll_get(in.get());
}
tout(cct) << stx->stx_ino << std::endl;
ldout(cct, 3) << "ll_symlinkx " << vparent << " " << name
<< " = " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
*out = in.get();
return r;
}
int Client::_unlink(Inode *dir, const char *name, const UserPerm& perm)
{
ldout(cct, 3) << "_unlink(" << dir->ino << " " << name
@ -11404,7 +11622,7 @@ int Client::_link(Inode *in, Inode *dir, const char *newname, const UserPerm& pe
}
int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
struct stat *attr, const UserPerm& perm)
const UserPerm& perm)
{
Mutex::Locker lock(client_lock);
@ -11422,25 +11640,19 @@ int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
InodeRef target;
if (!cct->_conf->fuse_default_permissions) {
if (S_ISDIR(in->mode)) {
r = -EPERM;
goto out;
}
if (S_ISDIR(in->mode))
return -EPERM;
r = may_hardlink(in, perm);
if (r < 0)
goto out;
return r;
r = may_create(newparent, perm);
if (r < 0)
goto out;
return r;
}
r = _link(in, newparent, newname, perm, &target);
if (r == 0) {
assert(target);
fill_stat(target, attr);
}
out:
return r;
return _link(in, newparent, newname, perm, &target);
}
int Client::ll_num_osds(void)
@ -11614,17 +11826,15 @@ int Client::ll_open(Inode *in, int flags, Fh **fhp, const UserPerm& perms)
return r;
}
int Client::ll_create(Inode *parent, const char *name, mode_t mode,
int flags, struct stat *attr, Inode **outp, Fh **fhp,
int Client::_ll_create(Inode *parent, const char *name, mode_t mode,
int flags, InodeRef *in, int caps, Fh **fhp,
const UserPerm& perms)
{
*fhp = NULL;
Mutex::Locker lock(client_lock);
vinodeno_t vparent = _get_vino(parent);
ldout(cct, 3) << "ll_create " << vparent << " " << name << " 0" << oct <<
ldout(cct, 3) << "_ll_create " << vparent << " " << name << " 0" << oct <<
mode << dec << " " << flags << ", uid " << perms.uid()
<< ", gid " << perms.gid() << dendl;
tout(cct) << "ll_create" << std::endl;
@ -11634,8 +11844,7 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode,
tout(cct) << flags << std::endl;
bool created = false;
InodeRef in;
int r = _lookup(parent, name, CEPH_STAT_CAP_INODE_ALL, &in, perms);
int r = _lookup(parent, name, caps, in, perms);
if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
return -EEXIST;
@ -11646,7 +11855,7 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode,
if (r < 0)
goto out;
}
r = _create(parent, name, flags, mode, &in, fhp, 0, 0, 0, NULL, &created,
r = _create(parent, name, flags, mode, in, fhp, 0, 0, 0, NULL, &created,
perms);
if (r < 0)
goto out;
@ -11655,13 +11864,12 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode,
if (r < 0)
goto out;
assert(in);
fill_stat(in, attr);
assert(*in);
ldout(cct, 20) << "ll_create created = " << created << dendl;
ldout(cct, 20) << "_ll_create created = " << created << dendl;
if (!created) {
if (!cct->_conf->fuse_default_permissions) {
r = may_open(in.get(), flags, perms);
r = may_open(in->get(), flags, perms);
if (r < 0) {
if (*fhp) {
int release_r = _release_fh(*fhp);
@ -11671,30 +11879,82 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode,
}
}
if (*fhp == NULL) {
r = _open(in.get(), flags, mode, fhp, perms);
r = _open(in->get(), flags, mode, fhp, perms);
if (r < 0)
goto out;
}
}
out:
if (r < 0)
attr->st_ino = 0;
if (*fhp) {
ll_unclosed_fh_set.insert(*fhp);
}
tout(cct) << (unsigned long)*fhp << std::endl;
tout(cct) << attr->st_ino << std::endl;
ldout(cct, 3) << "ll_create " << parent << " " << name << " 0" << oct <<
mode << dec << " " << flags << " = " << r << " (" << *fhp << " " <<
hex << attr->st_ino << dec << ")" << dendl;
// passing an Inode in outp requires an additional ref
if (outp) {
if (in)
ino_t ino = 0;
if (r >= 0) {
Inode *inode = in->get();
if (use_faked_inos())
ino = inode->faked_ino;
else
ino = inode->ino;
}
tout(cct) << (unsigned long)*fhp << std::endl;
tout(cct) << ino << std::endl;
ldout(cct, 3) << "_ll_create " << parent << " " << name << " 0" << oct <<
mode << dec << " " << flags << " = " << r << " (" << *fhp << " " <<
hex << ino << dec << ")" << dendl;
return r;
}
int Client::ll_create(Inode *parent, const char *name, mode_t mode,
int flags, struct stat *attr, Inode **outp, Fh **fhp,
const UserPerm& perms)
{
InodeRef in;
Mutex::Locker lock(client_lock);
int r = _ll_create(parent, name, mode, flags, &in, CEPH_STAT_CAP_INODE_ALL,
fhp, perms);
if (r >= 0) {
assert(in);
// passing an Inode in outp requires an additional ref
if (outp) {
_ll_get(in.get());
*outp = in.get();
*outp = in.get();
}
fill_stat(in, attr);
} else {
attr->st_ino = 0;
}
return r;
}
int Client::ll_createx(Inode *parent, const char *name, mode_t mode,
int oflags, Inode **outp, Fh **fhp,
struct ceph_statx *stx, unsigned want, unsigned lflags,
const UserPerm& perms)
{
unsigned caps = statx_to_mask(lflags, want);
InodeRef in;
Mutex::Locker lock(client_lock);
int r = _ll_create(parent, name, mode, oflags, &in, caps, fhp, perms);
if (r >= 0) {
assert(in);
// passing an Inode in outp requires an additional ref
if (outp) {
_ll_get(in.get());
*outp = in.get();
}
fill_statx(in, caps, stx);
} else {
stx->stx_ino = 0;
stx->stx_mask = 0;
}
return r;

View File

@ -48,6 +48,7 @@ using std::fstream;
#include "InodeRef.h"
#include "UserPerm.h"
#include "include/cephfs/ceph_statx.h"
class FSMap;
class FSMapUser;
@ -719,7 +720,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, Inode *in);
int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms);
void _readdir_drop_dirp_buffer(dir_result_t *dirp);
@ -727,7 +728,7 @@ private:
void _readdir_next_frag(dir_result_t *dirp);
void _readdir_rechoose_frag(dir_result_t *dirp);
int _readdir_get_frag(dir_result_t *dirp);
int _readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p);
int _readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p, int caps, bool getref);
void _closedir(dir_result_t *dirp);
// other helpers
@ -952,11 +953,13 @@ public:
* Returns 0 if it reached the end of the directory.
* If @a cb returns a negative error code, stop and return that.
*/
int readdir_r_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p);
int readdir_r_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
unsigned want=0, unsigned flags=AT_NO_ATTR_SYNC,
bool getref=false);
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, Inode **out);
int getdir(const char *relpath, list<string>& names,
const UserPerm& perms); // get the whole dir at once.
@ -1007,6 +1010,7 @@ public:
int setattrx(const char *relpath, struct ceph_statx *stx, int mask,
const UserPerm& perms, int flags=0);
int fsetattr(int fd, struct stat *attr, int mask, const UserPerm& perms);
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 lchmod(const char *path, mode_t mode, const UserPerm& perms);
@ -1113,6 +1117,9 @@ public:
Inode *ll_get_inode(vinodeno_t vino);
int ll_lookup(Inode *parent, const char *name, struct stat *attr,
Inode **out, const UserPerm& perms);
int ll_lookupx(Inode *parent, const char *name, Inode **out,
struct ceph_statx *stx, unsigned want, unsigned flags,
const UserPerm& perms);
bool ll_forget(Inode *in, int count);
bool ll_put(Inode *in);
int ll_getattr(Inode *in, struct stat *st, const UserPerm& perms);
@ -1135,20 +1142,36 @@ public:
int ll_readlink(Inode *in, char *buf, size_t bufsize, const UserPerm& perms);
int ll_mknod(Inode *in, const char *name, mode_t mode, dev_t rdev,
struct stat *attr, Inode **out, const UserPerm& perms);
int ll_mknodx(Inode *parent, const char *name, mode_t mode, dev_t rdev,
Inode **out, struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm& perms);
int ll_mkdir(Inode *in, const char *name, mode_t mode, struct stat *attr,
Inode **out, const UserPerm& perm);
int ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out,
struct ceph_statx *stx, unsigned want, unsigned flags,
const UserPerm& perms);
int ll_symlink(Inode *in, const char *name, const char *value,
struct stat *attr, Inode **out, const UserPerm& perms);
int ll_symlinkx(Inode *parent, const char *name, const char *value,
Inode **out, struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm& perms);
int ll_unlink(Inode *in, const char *name, const UserPerm& perm);
int ll_rmdir(Inode *in, const char *name, const UserPerm& perms);
int ll_rename(Inode *parent, const char *name, Inode *newparent,
const char *newname, const UserPerm& perm);
int ll_link(Inode *in, Inode *newparent, const char *newname,
struct stat *attr, const UserPerm& perm);
const UserPerm& perm);
int ll_open(Inode *in, int flags, Fh **fh, const UserPerm& perms);
int _ll_create(Inode *parent, const char *name, mode_t mode,
int flags, InodeRef *in, int caps, Fh **fhp,
const UserPerm& perms);
int ll_create(Inode *parent, const char *name, mode_t mode, int flags,
struct stat *attr, Inode **out, Fh **fhp,
const UserPerm& perms);
int ll_createx(Inode *parent, const char *name, mode_t mode,
int oflags, Inode **outp, Fh **fhp,
struct ceph_statx *stx, unsigned want, unsigned lflags,
const UserPerm& perms);
int ll_read_block(Inode *in, uint64_t blockid, char *buf, uint64_t offset,
uint64_t length, file_layout_t* layout);
@ -1159,8 +1182,8 @@ public:
int ll_commit_blocks(Inode *in, uint64_t offset, uint64_t length);
int ll_statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms);
int ll_walk(const char* name, Inode **i, struct stat *attr,
const UserPerm& perms); // XXX in?
int ll_walk(const char* name, Inode **i, struct ceph_statx *stx,
unsigned int want, unsigned int flags, const UserPerm& perms);
uint32_t ll_stripe_unit(Inode *in);
int ll_file_layout(Inode *in, file_layout_t *layout);
uint64_t ll_snap_seq(Inode *in);

View File

@ -37,6 +37,7 @@ using namespace std;
#include "common/errno.h"
#include "include/assert.h"
#include "include/cephfs/ceph_statx.h"
#define dout_subsys ceph_subsys_client
#undef dout_prefix
@ -1023,11 +1024,11 @@ int SyntheticClient::play_trace(Trace& t, string& prefix, bool metadata_only)
const char *p = prefix.c_str();
if (prefix.length()) {
client->mkdir(prefix.c_str(), 0755, perms);
struct stat attr;
struct ceph_statx stx;
i1 = client->ll_get_inode(vinodeno_t(1, CEPH_NOSNAP));
if (client->ll_lookup(i1, prefix.c_str(), &attr, &i2, perms) == 0) {
ll_inos[1] = attr.st_ino;
dout(5) << "'root' ino is " << inodeno_t(attr.st_ino) << dendl;
if (client->ll_lookupx(i1, prefix.c_str(), &i2, &stx, CEPH_STATX_INO, 0, perms) == 0) {
ll_inos[1] = stx.stx_ino;
dout(5) << "'root' ino is " << inodeno_t(stx.stx_ino) << dendl;
client->ll_put(i1);
} else {
dout(0) << "warning: play_trace couldn't lookup up my per-client directory" << dendl;
@ -1227,11 +1228,11 @@ int SyntheticClient::play_trace(Trace& t, string& prefix, bool metadata_only)
int64_t i = t.get_int();
const char *name = t.get_string(buf, p);
int64_t r = t.get_int();
struct stat attr;
struct ceph_statx stx;
if (ll_inos.count(i)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
if (client->ll_lookup(i1, name, &attr, &i2, perms) == 0)
ll_inos[r] = attr.st_ino;
if (client->ll_lookupx(i1, name, &i2, &stx, CEPH_STATX_INO, 0, perms) == 0)
ll_inos[r] = stx.stx_ino;
client->ll_put(i1);
}
} else if (strcmp(op, "ll_forget") == 0) {
@ -1343,12 +1344,11 @@ int SyntheticClient::play_trace(Trace& t, string& prefix, bool metadata_only)
int64_t i = t.get_int();
int64_t ni = t.get_int();
const char *nn = t.get_string(buf, p);
struct stat attr;
if (ll_inos.count(i) &&
ll_inos.count(ni)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
i2 = client->ll_get_inode(vinodeno_t(ll_inos[ni],CEPH_NOSNAP));
client->ll_link(i1, i2, nn, &attr, perms);
client->ll_link(i1, i2, nn, perms);
client->ll_put(i1);
client->ll_put(i2);
}

View File

@ -42,8 +42,9 @@ private:
public:
UserPerm() : m_uid(-1), m_gid(-1), gid_count(0),
gids(NULL), alloced_gids(false) {}
UserPerm(int uid, int gid) : m_uid(uid), m_gid(gid), gid_count(0),
gids(NULL), alloced_gids(false) {}
UserPerm(uid_t uid, gid_t gid, int ngids=0, gid_t *gidlist=NULL) :
m_uid(uid), m_gid(gid), gid_count(ngids),
gids(gidlist), alloced_gids(false) {}
UserPerm(const UserPerm& o) : UserPerm() {
deep_copy_from(o);
}

View File

@ -32,6 +32,7 @@
#include "ioctl.h"
#include "common/config.h"
#include "include/assert.h"
#include "include/cephfs/ceph_statx.h"
#include "fuse_ll.h"
#include <fuse.h>
@ -515,14 +516,22 @@ static void fuse_ll_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
UserPerm perm(ctx->uid, ctx->gid);
GET_GROUPS(perm, req);
int r = cfuse->client->ll_link(in, nin, newname, &fe.attr, perm);
/*
* Note that we could successfully link, but then fail the subsequent
* getattr and return an error. Perhaps we should ignore getattr errors,
* but then how do we tell FUSE that the attrs are bogus?
*/
int r = cfuse->client->ll_link(in, nin, newname, perm);
if (r == 0) {
fe.ino = cfuse->make_fake_ino(fe.attr.st_ino, fe.attr.st_dev);
fe.attr.st_rdev = new_encode_dev(fe.attr.st_rdev);
fuse_reply_entry(req, &fe);
} else {
fuse_reply_err(req, -r);
r = cfuse->client->ll_getattr(in, &fe.attr, perm);
if (r == 0) {
fe.ino = cfuse->make_fake_ino(fe.attr.st_ino, fe.attr.st_dev);
fe.attr.st_rdev = new_encode_dev(fe.attr.st_rdev);
fuse_reply_entry(req, &fe);
}
}
if (r != 0) {
/*
* Many ll operations in libcephfs return an extra inode reference, but
* ll_link currently does not. Still, FUSE needs one for the new dentry,
@ -530,6 +539,7 @@ static void fuse_ll_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
* On error however, we must put that reference.
*/
cfuse->iput(in);
fuse_reply_err(req, -r);
}
cfuse->iput(nin);
@ -669,19 +679,21 @@ 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,
Inode *in)
{
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;

View File

@ -384,17 +384,17 @@ void CephBroker::rmdir(ResponseCallback *cb, const char *dname) {
int CephBroker::rmdir_recursive(const char *directory) {
struct ceph_dir_result *dirp;
struct dirent de;
struct stat st;
struct ceph_statx stx;
int r;
if ((r = ceph_opendir(cmount, directory, &dirp)) < 0)
return r; //failed to open
while ((r = ceph_readdirplus_r(cmount, dirp, &de, &st, 0)) > 0) {
while ((r = ceph_readdirplus_r(cmount, dirp, &de, &stx, CEPH_STATX_INO, AT_NO_ATTR_SYNC, NULL)) > 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;

View File

@ -97,6 +97,9 @@ typedef struct vinodeno_t vinodeno;
#endif /* ! __cplusplus */
struct UserPerm;
typedef struct UserPerm UserPerm;
struct Inode;
typedef struct Inode Inode;
@ -121,6 +124,34 @@ struct CephContext;
# define CEPHFS_ERROR_NEW_CLIENT 1002
# define CEPHFS_ERROR_MESSENGER_START 1003
/**
* Create a UserPerm credential object.
*
* Some calls (most notably, the ceph_ll_* ones), take a credential object
* that represents the credentials that the calling program is using. This
* function creates a new credential object for this purpose. Returns a
* pointer to the object, or NULL if it can't be allocated.
*
* Note that the gidlist array is used directly and is not copied. It must
* remain valid over the lifetime of the created UserPerm object.
*
* @param uid uid to be used
* @param gid gid to be used
* @param ngids number of gids in supplemental grouplist
* @param gidlist array of gid_t's in the list of groups
*/
UserPerm *ceph_userperm_new(uid_t uid, gid_t gid, int ngids, gid_t *gidlist);
/**
* Destroy a UserPerm credential object.
*
* @param perm pointer to object to be destroyed
*
* Currently this just frees the object. Note that the gidlist array is not
* freed. The caller must do so if it's necessary.
*/
void ceph_userperm_destroy(UserPerm *perm);
/**
* @defgroup libcephfs_h_init Setup and Teardown
* These are the first and last functions that should be called
@ -200,6 +231,8 @@ int ceph_init(struct ceph_mount_info *cmount);
int ceph_mount(struct ceph_mount_info *cmount, const char *root);
struct UserPerm *ceph_mount_perms(struct ceph_mount_info *cmount);
/**
* Execute a management command remotely on an MDS.
*
@ -447,13 +480,16 @@ 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
* @param out optional returned Inode argument. If non-NULL, then a reference will be taken on
* the inode and the pointer set on success.
* @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, struct Inode **out);
/**
* Gets multiple directory entries.
@ -611,16 +647,6 @@ int ceph_unlink(struct ceph_mount_info *cmount, const char *path);
*/
int ceph_rename(struct ceph_mount_info *cmount, const char *from, const char *to);
/**
* Get a file's statistics and attributes.
*
* @param cmount the ceph mount handle to use for performing the stat.
* @param path the file or directory to get the statistics of.
* @param stbuf the stat struct that will be filled in with the file's statistics.
* @returns 0 on success or negative error code on failure.
*/
int ceph_stat(struct ceph_mount_info *cmount, const char *path, struct stat *stbuf);
/**
* Get a file's extended statistics and attributes.
*
@ -634,40 +660,8 @@ int ceph_stat(struct ceph_mount_info *cmount, const char *path, struct stat *stb
int ceph_statx(struct ceph_mount_info *cmount, const char *path, struct ceph_statx *stx,
unsigned int want, unsigned int flags);
/**
* Get a file's statistics and attributes, without following symlinks.
*
* @param cmount the ceph mount handle to use for performing the stat.
* @param path the file or directory to get the statistics of.
* @param stbuf the stat struct that will be filled in with the file's statistics.
* @returns 0 on success or negative error code on failure.
*/
int ceph_lstat(struct ceph_mount_info *cmount, const char *path, struct stat *stbuf);
/**
* Set a file's attributes.
*
* @param cmount the ceph mount handle to use for performing the setattr.
* @param relpath the path to the file/directory to set the attributes of.
* @param attr the stat struct that must include attribute values to set on the file.
* @param mask a mask of all the CEPH_SETATTR_* values that have been set in the stat struct.
* @returns 0 on success or negative error code on failure.
*/
int ceph_setattr(struct ceph_mount_info *cmount, const char *relpath, struct stat *attr, int mask);
/**
* Set a file's attributes.
*
* @param cmount the ceph mount handle to use for performing the setattr.
* @param fd the fd of the open file/directory to set the attributes of.
* @param attr the stat struct that must include attribute values to set on the file.
* @param mask a mask of all the stat values that have been set on the stat struct.
* @returns 0 on success or negative error code on failure.
*/
int ceph_fsetattr(struct ceph_mount_info *cmount, int fd, struct stat *attr, int mask);
/**
* Set a file's attributes (extended version).
*
* @param cmount the ceph mount handle to use for performing the setattr.
* @param relpath the path to the file/directory to set the attributes of.
@ -678,6 +672,17 @@ int ceph_fsetattr(struct ceph_mount_info *cmount, int fd, struct stat *attr, int
*/
int ceph_setattrx(struct ceph_mount_info *cmount, const char *relpath, struct ceph_statx *stx, int mask, int flags);
/**
* Set a file's attributes (extended version).
*
* @param cmount the ceph mount handle to use for performing the setattr.
* @param fd the fd of the open file/directory to set the attributes of.
* @param stx the statx struct that must include attribute values to set on the file.
* @param mask a mask of all the stat values that have been set on the stat struct.
* @returns 0 on success or negative error code on failure.
*/
int ceph_fsetattrx(struct ceph_mount_info *cmount, int fd, struct ceph_statx *stx, int mask);
/**
* Change the mode bits (permissions) of a file/directory.
*
@ -928,17 +933,6 @@ int ceph_fsync(struct ceph_mount_info *cmount, int fd, int syncdataonly);
int ceph_fallocate(struct ceph_mount_info *cmount, int fd, int mode,
int64_t offset, int64_t length);
/**
* Get the open file's statistics.
*
* @param cmount the ceph mount handle to use for performing the fstat.
* @param fd the file descriptor of the file to get statistics of.
* @param stbuf the stat struct of the file's statistics, filled in by the
* function.
* @returns 0 on success or a negative error code on failure
*/
int ceph_fstat(struct ceph_mount_info *cmount, int fd, struct stat *stbuf);
/**
* Get an open file's extended statistics and attributes.
*
@ -1434,26 +1428,22 @@ int ceph_ll_lookup_inode(
*/
int ceph_ll_lookup_root(struct ceph_mount_info *cmount,
Inode **parent);
int ceph_ll_lookup(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, struct stat *attr,
Inode **out, int uid, int gid);
int ceph_ll_lookup(struct ceph_mount_info *cmount, Inode *parent,
const char *name, Inode **out, struct ceph_statx *stx,
unsigned want, unsigned flags, const UserPerm *perms);
int ceph_ll_put(struct ceph_mount_info *cmount, struct Inode *in);
int ceph_ll_forget(struct ceph_mount_info *cmount, struct Inode *in,
int count);
int ceph_ll_walk(struct ceph_mount_info *cmount, const char *name,
struct Inode **i,
struct stat *attr);
int ceph_ll_walk(struct ceph_mount_info *cmount, const char* name, Inode **i,
struct ceph_statx *stx, unsigned int want, unsigned int flags,
const UserPerm *perms);
int ceph_ll_getattr(struct ceph_mount_info *cmount, struct Inode *in,
struct stat *attr, int uid, int gid);
int ceph_ll_getattrx(struct ceph_mount_info *cmount, struct Inode *in,
struct ceph_statx *stx, unsigned int want, unsigned int flags,
int uid, int gid);
const UserPerm *perms);
int ceph_ll_setattr(struct ceph_mount_info *cmount, struct Inode *in,
struct stat *st, int mask, int uid, int gid);
int ceph_ll_setattrx(struct ceph_mount_info *cmount, struct Inode *in,
struct ceph_statx *stx, int mask, int uid, int gid);
struct ceph_statx *stx, int mask, const UserPerm *perms);
int ceph_ll_open(struct ceph_mount_info *cmount, struct Inode *in, int flags,
struct Fh **fh, int uid, int gid);
struct Fh **fh, const UserPerm *perms);
off_t ceph_ll_lseek(struct ceph_mount_info *cmount, struct Fh* filehandle,
off_t offset, int whence);
int ceph_ll_read(struct ceph_mount_info *cmount, struct Fh* filehandle,
@ -1476,54 +1466,55 @@ int ceph_ll_iclose(struct ceph_mount_info *cmount, struct Inode *in, int mode);
* @param name name of attribute
* @param value pointer to begin buffer
* @param size buffer size
* @param uid user ID
* @param gid group ID
* @param perms pointer to UserPerms object
* @returns size of returned buffer. Negative number in error case
*/
int ceph_ll_getxattr(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, void *value, size_t size, int uid,
int gid);
const char *name, void *value, size_t size,
const UserPerm *perms);
int ceph_ll_setxattr(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, const void *value, size_t size,
int flags, int uid, int gid);
int flags, const UserPerm *perms);
int ceph_ll_listxattr(struct ceph_mount_info *cmount, struct Inode *in,
char *list, size_t buf_size, size_t *list_size, int uid, int gid);
char *list, size_t buf_size, size_t *list_size,
const UserPerm *perms);
int ceph_ll_removexattr(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, int uid, int gid);
int ceph_ll_create(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, mode_t mode, int flags,
struct stat *attr, struct Inode **out, Fh **fhp,
int uid, int gid);
int ceph_ll_mknod(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, mode_t mode, dev_t rdev,
struct stat *attr, struct Inode **out,
int uid, int gid);
int ceph_ll_mkdir(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, mode_t mode, struct stat *attr,
Inode **out, int uid, int gid);
const char *name, const UserPerm *perms);
int ceph_ll_create(struct ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, int oflags, Inode **outp,
Fh **fhp, struct ceph_statx *stx, unsigned want,
unsigned lflags, const UserPerm *perms);
int ceph_ll_mknod(struct ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, dev_t rdev, Inode **out,
struct ceph_statx *stx, unsigned want, unsigned flags,
const UserPerm *perms);
int ceph_ll_mkdir(struct ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, Inode **out,
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms);
int ceph_ll_link(struct ceph_mount_info *cmount, struct Inode *in,
struct Inode *newparrent, const char *name,
struct stat *attr, int uid, int gid);
int ceph_ll_truncate(struct ceph_mount_info *cmount, struct Inode *in,
uint64_t length, int uid, int gid);
struct Inode *newparent, const char *name,
const UserPerm *perms);
int ceph_ll_opendir(struct ceph_mount_info *cmount, struct Inode *in,
struct ceph_dir_result **dirpp, int uid, int gid);
struct ceph_dir_result **dirpp, const UserPerm *perms);
int ceph_ll_releasedir(struct ceph_mount_info *cmount,
struct ceph_dir_result* dir);
int ceph_ll_rename(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, struct Inode *newparent,
const char *newname, int uid, int gid);
const char *newname, const UserPerm *perms);
int ceph_ll_unlink(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, int uid, int gid);
const char *name, const UserPerm *perms);
int ceph_ll_statfs(struct ceph_mount_info *cmount, struct Inode *in,
struct statvfs *stbuf);
int ceph_ll_readlink(struct ceph_mount_info *cmount, struct Inode *in,
char *buf, size_t bufsize, int uid, int gid);
int ceph_ll_symlink(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, const char *value, struct stat *attr,
struct Inode **in, int uid, int gid);
char *buf, size_t bufsize, const UserPerm *perms);
int ceph_ll_symlink(struct ceph_mount_info *cmount,
Inode *in, const char *name, const char *value,
Inode **out, struct ceph_statx *stx,
unsigned want, unsigned flags,
const UserPerm *perms);
int ceph_ll_rmdir(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, int uid, int gid);
const char *name, const UserPerm *perms);
uint32_t ceph_ll_stripe_unit(struct ceph_mount_info *cmount,
struct Inode *in);
uint32_t ceph_ll_file_layout(struct ceph_mount_info *cmount,

View File

@ -284,6 +284,17 @@ static void do_out_buffer(string& outbl, char **outbuf, size_t *outbuflen)
*outbuflen = outbl.length();
}
extern "C" UserPerm *ceph_userperm_new(uid_t uid, gid_t gid, int ngids,
gid_t *gidlist)
{
return new (std::nothrow) UserPerm(uid, gid, ngids, gidlist);
}
extern "C" void ceph_userperm_destroy(UserPerm *perm)
{
delete perm;
}
extern "C" const char *ceph_version(int *pmajor, int *pminor, int *ppatch)
{
int major, minor, patch;
@ -441,6 +452,11 @@ extern "C" int ceph_is_mounted(struct ceph_mount_info *cmount)
return cmount->is_mounted() ? 1 : 0;
}
extern "C" struct UserPerm *ceph_mount_perms(struct ceph_mount_info *cmount)
{
return &cmount->default_perms;
}
extern "C" int ceph_statfs(struct ceph_mount_info *cmount, const char *path,
struct statvfs *stbuf)
{
@ -501,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, struct Inode **out)
{
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, out);
}
extern "C" int ceph_getdents(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
@ -607,15 +624,6 @@ extern "C" int ceph_symlink(struct ceph_mount_info *cmount, const char *existing
return cmount->get_client()->symlink(existing, newname, cmount->default_perms);
}
// inode stuff
extern "C" int ceph_stat(struct ceph_mount_info *cmount, const char *path,
struct stat *stbuf)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->stat(path, stbuf, cmount->default_perms);
}
extern "C" int ceph_statx(struct ceph_mount_info *cmount, const char *path,
struct ceph_statx *stx, unsigned int want, unsigned int flags)
{
@ -625,28 +633,12 @@ extern "C" int ceph_statx(struct ceph_mount_info *cmount, const char *path,
want, flags);
}
extern "C" int ceph_lstat(struct ceph_mount_info *cmount, const char *path,
struct stat *stbuf)
extern "C" int ceph_fsetattrx(struct ceph_mount_info *cmount, int fd,
struct ceph_statx *stx, int mask)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->lstat(path, stbuf, cmount->default_perms);
}
extern "C" int ceph_setattr(struct ceph_mount_info *cmount, const char *relpath,
struct stat *attr, int mask)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->setattr(relpath, attr, mask, cmount->default_perms);
}
extern "C" int ceph_fsetattr(struct ceph_mount_info *cmount, int fd,
struct stat *attr, int mask)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->fsetattr(fd, attr, mask, cmount->default_perms);
return cmount->get_client()->fsetattrx(fd, stx, mask, cmount->default_perms);
}
extern "C" int ceph_setattrx(struct ceph_mount_info *cmount, const char *relpath,
@ -901,13 +893,6 @@ extern "C" int ceph_fallocate(struct ceph_mount_info *cmount, int fd, int mode,
return cmount->get_client()->fallocate(fd, mode, offset, length);
}
extern "C" int ceph_fstat(struct ceph_mount_info *cmount, int fd, struct stat *stbuf)
{
if (!cmount->is_mounted())
return -ENOTCONN;
return cmount->get_client()->fstat(fd, stbuf, 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)
{
@ -1418,13 +1403,13 @@ extern "C" int ceph_ll_lookup_inode(
return 0;
}
extern "C" int ceph_ll_lookup(class ceph_mount_info *cmount,
struct Inode *parent, const char *name,
struct stat *attr, Inode **out,
int uid, int gid)
extern "C" int ceph_ll_lookup(struct ceph_mount_info *cmount,
Inode *parent, const char *name, Inode **out,
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client())->ll_lookup(parent, name, attr, out, perms);
return (cmount->get_client())->ll_lookupx(parent, name, out, stx, want,
flags, *perms);
}
extern "C" int ceph_ll_put(class ceph_mount_info *cmount, Inode *in)
@ -1438,51 +1423,32 @@ extern "C" int ceph_ll_forget(class ceph_mount_info *cmount, Inode *in,
return (cmount->get_client()->ll_forget(in, count));
}
extern "C" int ceph_ll_walk(class ceph_mount_info *cmount, const char *name,
struct Inode **i,
struct stat *attr)
int ceph_ll_walk(struct ceph_mount_info *cmount, const char* name, Inode **i,
struct ceph_statx *stx, unsigned int want, unsigned int flags,
const UserPerm *perms)
{
return (cmount->get_client()->ll_walk(name, i, attr, cmount->default_perms));
return(cmount->get_client()->ll_walk(name, i, stx, want, flags, *perms));
}
extern "C" int ceph_ll_getattr(class ceph_mount_info *cmount,
Inode *in, struct stat *attr,
int uid, int gid)
Inode *in, struct ceph_statx *stx,
unsigned int want, unsigned int flags,
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_getattr(in, attr, perms));
}
extern "C" int ceph_ll_getattrx(class ceph_mount_info *cmount,
Inode *in, struct ceph_statx *stx,
unsigned int want, unsigned int flags,
int uid, int gid)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_getattrx(in, stx, want, flags, perms));
return (cmount->get_client()->ll_getattrx(in, stx, want, flags, *perms));
}
extern "C" int ceph_ll_setattr(class ceph_mount_info *cmount,
Inode *in, struct stat *st,
int mask, int uid, int gid)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_setattr(in, st, mask, perms));
}
extern "C" int ceph_ll_setattrx(class ceph_mount_info *cmount,
Inode *in, struct ceph_statx *stx,
int mask, int uid, int gid)
int mask, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_setattrx(in, stx, mask, perms));
return (cmount->get_client()->ll_setattrx(in, stx, mask, *perms));
}
extern "C" int ceph_ll_open(class ceph_mount_info *cmount, Inode *in,
int flags, Fh **fh, int uid, int gid)
int flags, Fh **fh, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_open(in, flags, fh, perms));
return (cmount->get_client()->ll_open(in, flags, fh, *perms));
}
extern "C" int ceph_ll_read(class ceph_mount_info *cmount, Fh* filehandle,
@ -1573,62 +1539,48 @@ extern "C" int ceph_ll_close(class ceph_mount_info *cmount, Fh* fh)
}
extern "C" int ceph_ll_create(class ceph_mount_info *cmount,
struct Inode *parent, const char *name,
mode_t mode, int flags, struct stat *attr,
struct Inode **out, Fh **fhp, int uid, int gid)
Inode *parent, const char *name, mode_t mode,
int oflags, Inode **outp, Fh **fhp,
struct ceph_statx *stx, unsigned want,
unsigned lflags, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client())->ll_create(parent, name, mode, flags,
attr, out, fhp, perms);
return (cmount->get_client())->ll_createx(parent, name, mode, oflags, outp,
fhp, stx, want, lflags, *perms);
}
extern "C" int ceph_ll_mknod(class ceph_mount_info *cmount,
struct Inode *parent, const char *name,
mode_t mode, dev_t rdev, struct stat *attr,
struct Inode **out, int uid, int gid)
extern "C" int ceph_ll_mknod(class ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, dev_t rdev,
Inode **out, struct ceph_statx *stx,
unsigned want, unsigned flags,
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client())->ll_mknod(parent, name, mode, rdev,
attr, out, perms);
return (cmount->get_client())->ll_mknodx(parent, name, mode, rdev,
out, stx, want, flags, *perms);
}
extern "C" int ceph_ll_mkdir(class ceph_mount_info *cmount,
Inode *parent, const char *name,
mode_t mode, struct stat *attr, Inode **out,
int uid, int gid)
extern "C" int ceph_ll_mkdir(class ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, Inode **out,
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_mkdir(parent, name, mode, attr, out, perms));
return cmount->get_client()->ll_mkdirx(parent, name, mode, out, stx, want,
flags, *perms);
}
extern "C" int ceph_ll_link(class ceph_mount_info *cmount,
Inode *in, Inode *newparent,
const char *name, struct stat *attr, int uid,
int gid)
const char *name, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_link(in, newparent, name, attr, perms));
}
extern "C" int ceph_ll_truncate(class ceph_mount_info *cmount,
Inode *in, uint64_t length, int uid,
int gid)
{
struct stat st;
st.st_size=length;
UserPerm perms(uid, gid);
return(cmount->get_client()->ll_setattr(in, &st, CEPH_SETATTR_SIZE, perms));
return cmount->get_client()->ll_link(in, newparent, name, *perms);
}
extern "C" int ceph_ll_opendir(class ceph_mount_info *cmount,
Inode *in,
struct ceph_dir_result **dirpp,
int uid, int gid)
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_opendir(in, O_RDONLY, (dir_result_t**) dirpp,
perms));
*perms));
}
extern "C" int ceph_ll_releasedir(class ceph_mount_info *cmount,
@ -1641,19 +1593,16 @@ extern "C" int ceph_ll_releasedir(class ceph_mount_info *cmount,
extern "C" int ceph_ll_rename(class ceph_mount_info *cmount,
Inode *parent, const char *name,
Inode *newparent, const char *newname,
int uid, int gid)
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_rename(parent, name,
newparent, newname, perms));
return cmount->get_client()->ll_rename(parent, name, newparent,
newname, *perms);
}
extern "C" int ceph_ll_unlink(class ceph_mount_info *cmount,
Inode *in, const char *name,
int uid, int gid)
extern "C" int ceph_ll_unlink(class ceph_mount_info *cmount, Inode *in,
const char *name, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_unlink(in, name, perms));
return cmount->get_client()->ll_unlink(in, name, *perms);
}
extern "C" int ceph_ll_statfs(class ceph_mount_info *cmount,
@ -1662,44 +1611,43 @@ extern "C" int ceph_ll_statfs(class ceph_mount_info *cmount,
return (cmount->get_client()->ll_statfs(in, stbuf, cmount->default_perms));
}
extern "C" int ceph_ll_readlink(class ceph_mount_info *cmount,
Inode *in, char *buf, size_t bufsiz, int uid,
int gid)
extern "C" int ceph_ll_readlink(class ceph_mount_info *cmount, Inode *in,
char *buf, size_t bufsiz,
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_readlink(in, buf, bufsiz, perms));
return cmount->get_client()->ll_readlink(in, buf, bufsiz, *perms);
}
extern "C" int ceph_ll_symlink(class ceph_mount_info *cmount,
Inode *in, const char *name,
const char *value, struct stat *attr,
Inode **out, int uid, int gid)
const char *value, Inode **out,
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_symlink(in, name, value, attr, out, perms));
return (cmount->get_client()->ll_symlinkx(in, name, value, out, stx, want,
flags, *perms));
}
extern "C" int ceph_ll_rmdir(class ceph_mount_info *cmount,
Inode *in, const char *name,
int uid, int gid)
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_rmdir(in, name, perms));
return cmount->get_client()->ll_rmdir(in, name, *perms);
}
extern "C" int ceph_ll_getxattr(class ceph_mount_info *cmount,
Inode *in, const char *name, void *value,
size_t size, int uid, int gid)
size_t size, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_getxattr(in, name, value, size, perms));
return (cmount->get_client()->ll_getxattr(in, name, value, size, *perms));
}
extern "C" int ceph_ll_listxattr(struct ceph_mount_info *cmount,
Inode *in, char *list,
size_t buf_size, size_t *list_size, int uid, int gid)
size_t buf_size, size_t *list_size,
const UserPerm *perms)
{
UserPerm perms(uid, gid);
int res = cmount->get_client()->ll_listxattr(in, list, buf_size, perms);
int res = cmount->get_client()->ll_listxattr(in, list, buf_size, *perms);
if (res >= 0) {
*list_size = (size_t)res;
return 0;
@ -1710,18 +1658,16 @@ extern "C" int ceph_ll_listxattr(struct ceph_mount_info *cmount,
extern "C" int ceph_ll_setxattr(class ceph_mount_info *cmount,
Inode *in, const char *name,
const void *value, size_t size,
int flags, int uid, int gid)
int flags, const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_setxattr(in, name, value, size, flags, perms));
return (cmount->get_client()->ll_setxattr(in, name, value, size, flags, *perms));
}
extern "C" int ceph_ll_removexattr(class ceph_mount_info *cmount,
Inode *in, const char *name,
int uid, int gid)
const UserPerm *perms)
{
UserPerm perms(uid, gid);
return (cmount->get_client()->ll_removexattr(in, name, perms));
return (cmount->get_client()->ll_removexattr(in, name, *perms));
}
extern "C" int ceph_ll_getlk(struct ceph_mount_info *cmount,

View File

@ -80,17 +80,18 @@ TEST(LibCephFS, BasicRecordLocking) {
sprintf(c_file, "recordlock_test_%d", getpid());
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
int rc;
struct flock lock1, lock2;
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode
rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0);
// write lock twice
@ -228,7 +229,7 @@ TEST(LibCephFS, BasicRecordLocking) {
ASSERT_EQ(lock2.l_pid, getpid());
ASSERT_EQ(0, ceph_ll_close(cmount, fh));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, 0, 0));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, perms));
CLEANUP_CEPH();
}
@ -282,7 +283,7 @@ static void thread_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
struct ceph_mount_info *const cmount = s.cmount;
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
struct flock lock1;
int rc;
struct timespec ts;
@ -292,8 +293,8 @@ static void thread_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, ceph_mount_perms(cmount));
ASSERT_EQ(rc, 0);
lock1.l_type = F_WRLCK;
@ -373,17 +374,18 @@ TEST(LibCephFS, ConcurrentRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
struct flock lock1;
int rc;
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode
rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0);
// Lock
@ -502,7 +504,7 @@ TEST(LibCephFS, ConcurrentRecordLocking) {
ASSERT_EQ(NULL, retval);
s.sem_destroy();
ASSERT_EQ(0, ceph_ll_close(cmount, fh));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, 0, 0));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, perms));
CLEANUP_CEPH();
}
@ -515,17 +517,18 @@ TEST(LibCephFS, ThreesomeRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
struct flock lock1;
int rc;
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode
rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0);
// Lock
@ -648,7 +651,7 @@ TEST(LibCephFS, ThreesomeRecordLocking) {
ASSERT_EQ(NULL, retval);
s.sem_destroy();
ASSERT_EQ(0, ceph_ll_close(cmount, fh));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, 0, 0));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, perms));
CLEANUP_CEPH();
}
@ -667,7 +670,7 @@ static void process_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
struct timespec ts;
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
int rc;
struct flock lock1;
@ -679,8 +682,8 @@ static void process_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, ceph_mount_perms(cmount));
ASSERT_EQ(rc, 0);
WAIT_MAIN(1); // (R1)
@ -758,7 +761,7 @@ TEST(LibCephFS, DISABLED_InterProcessRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
struct flock lock1;
int rc;
@ -782,14 +785,15 @@ TEST(LibCephFS, DISABLED_InterProcessRecordLocking) {
struct timespec ts;
struct ceph_mount_info *cmount;
STARTUP_CEPH();
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode
rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0);
// Lock
@ -906,7 +910,7 @@ TEST(LibCephFS, DISABLED_InterProcessRecordLocking) {
s.sem_destroy();
ASSERT_EQ(0, munmap(shs, sizeof(*shs)));
ASSERT_EQ(0, ceph_ll_close(cmount, fh));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, 0, 0));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, perms));
CLEANUP_CEPH();
}
@ -919,7 +923,7 @@ TEST(LibCephFS, DISABLED_ThreesomeInterProcessRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL;
Inode *root = NULL, *inode = NULL;
struct stat attr;
struct ceph_statx stx;
struct flock lock1;
int rc;
@ -956,8 +960,9 @@ TEST(LibCephFS, DISABLED_ThreesomeInterProcessRecordLocking) {
ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr,
&inode, &fh, 0, 0);
UserPerm *perms = ceph_mount_perms(cmount);
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0);
// Lock
@ -1077,6 +1082,6 @@ TEST(LibCephFS, DISABLED_ThreesomeInterProcessRecordLocking) {
s.sem_destroy();
ASSERT_EQ(0, munmap(shs, sizeof(*shs)));
ASSERT_EQ(0, ceph_ll_close(cmount, fh));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, 0, 0));
ASSERT_EQ(0, ceph_ll_unlink(cmount, root, c_file, perms));
CLEANUP_CEPH();
}

View File

@ -424,9 +424,9 @@ TEST(LibCephFS, DirLs) {
found.clear();
while (true) {
struct dirent rdent;
struct stat st;
int stmask;
int len = ceph_readdirplus_r(cmount, ls_dir, &rdent, &st, &stmask);
struct ceph_statx stx;
int len = ceph_readdirplus_r(cmount, ls_dir, &rdent, &stx,
CEPH_STATX_SIZE, AT_NO_ATTR_SYNC, NULL);
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);
@ -568,21 +569,25 @@ TEST(LibCephFS, Xattrs_ll) {
Inode *root = NULL;
Inode *existent_file_handle = NULL;
struct stat attr;
int res = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(res, 0);
res = ceph_ll_lookup(cmount, root, test_xattr_file, &attr, &existent_file_handle, 0, 0);
UserPerm *perms = ceph_mount_perms(cmount);
struct ceph_statx stx;
res = ceph_ll_lookup(cmount, root, test_xattr_file, &existent_file_handle,
&stx, 0, 0, perms);
ASSERT_EQ(res, 0);
const char *valid_name = "user.attrname";
const char *value = "attrvalue";
char value_buf[256] = { 0 };
res = ceph_ll_setxattr(cmount, existent_file_handle, valid_name, value, strlen(value), 0, 0, 0);
res = ceph_ll_setxattr(cmount, existent_file_handle, valid_name, value, strlen(value), 0, perms);
ASSERT_EQ(res, 0);
res = ceph_ll_getxattr(cmount, existent_file_handle, valid_name, value_buf, 256, 0, 0);
res = ceph_ll_getxattr(cmount, existent_file_handle, valid_name, value_buf, 256, perms);
ASSERT_EQ(res, (int)strlen(value));
value_buf[res] = '\0';
@ -1132,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, NULL));
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));
@ -1157,7 +1160,7 @@ TEST(LibCephFS, UseUnmounted) {
EXPECT_EQ(-ENOTCONN, ceph_lremovexattr(cmount, "/path", "name"));
EXPECT_EQ(-ENOTCONN, ceph_setxattr(cmount, "/path", "name", NULL, 0, 0));
EXPECT_EQ(-ENOTCONN, ceph_lsetxattr(cmount, "/path", "name", NULL, 0, 0));
EXPECT_EQ(-ENOTCONN, ceph_fsetattr(cmount, 0, &st, 0));
EXPECT_EQ(-ENOTCONN, ceph_fsetattrx(cmount, 0, &stx, 0));
EXPECT_EQ(-ENOTCONN, ceph_chmod(cmount, "/path", 0));
EXPECT_EQ(-ENOTCONN, ceph_fchmod(cmount, 0, 0));
EXPECT_EQ(-ENOTCONN, ceph_chown(cmount, "/path", 0, 0));
@ -1392,20 +1395,23 @@ TEST(LibCephFS, Nlink) {
sprintf(filename, "nlinkorig%x", getpid());
sprintf(linkname, "nlinklink%x", getpid());
struct stat st;
struct ceph_statx stx;
Fh *fh;
UserPerm *perms = ceph_mount_perms(cmount);
ASSERT_EQ(ceph_ll_mkdir(cmount, root, dirname, 0755, &st, &dir, getuid(), getgid()), 0);
ASSERT_EQ(ceph_ll_mkdir(cmount, root, dirname, 0755, &dir, &stx, 0, 0, perms), 0);
ASSERT_EQ(ceph_ll_create(cmount, dir, filename, 0666, O_RDWR|O_CREAT|O_EXCL,
&st, &file, &fh, getuid(), getgid()), 0);
ASSERT_EQ(st.st_nlink, (nlink_t)1);
&file, &fh, &stx, CEPH_STATX_NLINK, 0, perms), 0);
ASSERT_EQ(stx.stx_nlink, (nlink_t)1);
ASSERT_EQ(ceph_ll_link(cmount, file, dir, linkname, &st, getuid(), getgid()), 0);
ASSERT_EQ(st.st_nlink, (nlink_t)2);
ASSERT_EQ(ceph_ll_link(cmount, file, dir, linkname, perms), 0);
ASSERT_EQ(ceph_ll_getattr(cmount, file, &stx, CEPH_STATX_NLINK, 0, perms), 0);
ASSERT_EQ(stx.stx_nlink, (nlink_t)2);
ASSERT_EQ(ceph_ll_unlink(cmount, dir, linkname, getuid(), getgid()), 0);
ASSERT_EQ(ceph_ll_lookup(cmount, dir, filename, &st, &file, getuid(), getgid()), 0);
ASSERT_EQ(st.st_nlink, (nlink_t)1);
ASSERT_EQ(ceph_ll_unlink(cmount, dir, linkname, perms), 0);
ASSERT_EQ(ceph_ll_lookup(cmount, dir, filename, &file, &stx,
CEPH_STATX_NLINK, 0, perms), 0);
ASSERT_EQ(stx.stx_nlink, (nlink_t)1);
ceph_shutdown(cmount);
}
@ -1558,30 +1564,31 @@ TEST(LibCephFS, LazyStatx) {
sprintf(filename, "lazystatx%x", getpid());
Inode *root1, *file1, *root2, *file2;
struct stat st;
struct ceph_statx stx;
Fh *fh;
UserPerm *perms1 = ceph_mount_perms(cmount1);
UserPerm *perms2 = ceph_mount_perms(cmount2);
ASSERT_EQ(ceph_ll_lookup_root(cmount1, &root1), 0);
ceph_ll_unlink(cmount1, root1, filename, getuid(), getgid());
ceph_ll_unlink(cmount1, root1, filename, perms1);
ASSERT_EQ(ceph_ll_create(cmount1, root1, filename, 0666, O_RDWR|O_CREAT|O_EXCL,
&st, &file1, &fh, getuid(), getgid()), 0);
&file1, &fh, &stx, 0, 0, perms1), 0);
ASSERT_EQ(ceph_ll_lookup_root(cmount2, &root2), 0);
ASSERT_EQ(ceph_ll_lookup(cmount2, root2, filename, &st, &file2, getuid(), getgid()), 0);
struct timespec old_ctime = st.st_ctim;
ASSERT_EQ(ceph_ll_lookup(cmount2, root2, filename, &file2, &stx, CEPH_STATX_CTIME, 0, perms2), 0);
struct timespec old_ctime = stx.stx_ctime;
/*
* Now sleep, do a chmod on the first client and the see whether we get a
* different ctime with a statx that uses AT_NO_ATTR_SYNC
*/
sleep(1);
st.st_mode = 0644;
ASSERT_EQ(ceph_ll_setattr(cmount1, file1, &st, CEPH_SETATTR_MODE, getuid(), getgid()), 0);
stx.stx_mode = 0644;
ASSERT_EQ(ceph_ll_setattr(cmount1, file1, &stx, CEPH_SETATTR_MODE, perms1), 0);
struct ceph_statx stx;
ASSERT_EQ(ceph_ll_getattrx(cmount2, file2, &stx, CEPH_STATX_CTIME, AT_NO_ATTR_SYNC, getuid(), getgid()), 0);
ASSERT_EQ(ceph_ll_getattr(cmount2, file2, &stx, CEPH_STATX_CTIME, AT_NO_ATTR_SYNC, perms2), 0);
ASSERT_TRUE(stx.stx_mask & CEPH_STATX_CTIME);
ASSERT_TRUE(stx.stx_ctime.tv_sec == old_ctime.tv_sec &&
stx.stx_ctime.tv_nsec == old_ctime.tv_nsec);
@ -1685,14 +1692,12 @@ TEST(LibCephFS, SetSize) {
int fd = ceph_open(cmount, filename, O_RDWR|O_CREAT|O_EXCL, 0666);
ASSERT_LT(0, fd);
struct stat st;
struct ceph_statx stx;
uint64_t size = 8388608;
st.st_size = (off_t)size;
ASSERT_EQ(ceph_fsetattr(cmount, fd, &st, CEPH_SETATTR_SIZE), 0);
struct stat stbuf;
ASSERT_EQ(ceph_fstat(cmount, fd, &stbuf), 0);
ASSERT_EQ(stbuf.st_size, (off_t)size);
stx.stx_size = (off_t)size;
ASSERT_EQ(ceph_fsetattrx(cmount, fd, &stx, CEPH_SETATTR_SIZE), 0);
ASSERT_EQ(ceph_fstatx(cmount, fd, &stx, CEPH_STATX_SIZE, 0), 0);
ASSERT_EQ(stx.stx_size, (off_t)size);
ceph_close(cmount, fd);
ceph_shutdown(cmount);

View File

@ -69,9 +69,10 @@ void PgFiles::hit_dir(std::string const &path)
continue;
}
struct stat st;
struct ceph_statx stx;
std::string de_path = (path + std::string("/") + de.d_name);
r = ceph_stat(cmount, de_path.c_str(), &st);
r = ceph_statx(cmount, de_path.c_str(), &stx,
CEPH_STATX_INO|CEPH_STATX_SIZE, 0);
if (r != 0) {
derr << "Failed to stat path " << de_path << ": "
<< cpp_strerror(r) << dendl;
@ -79,9 +80,9 @@ void PgFiles::hit_dir(std::string const &path)
continue;
}
if (S_ISREG(st.st_mode)) {
hit_file(de_path, st);
} else if (S_ISDIR(st.st_mode)) {
if (S_ISREG(stx.stx_mode)) {
hit_file(de_path, stx);
} else if (S_ISDIR(stx.stx_mode)) {
hit_dir(de_path);
} else {
dout(20) << "Skipping non reg/dir file: " << de_path << dendl;
@ -95,9 +96,9 @@ void PgFiles::hit_dir(std::string const &path)
}
}
void PgFiles::hit_file(std::string const &path, struct stat const &st)
void PgFiles::hit_file(std::string const &path, const struct ceph_statx &stx)
{
assert(S_ISREG(st.st_mode));
assert(S_ISREG(stx.stx_mode));
dout(20) << "Hitting file '" << path << "'" << dendl;
@ -127,11 +128,11 @@ void PgFiles::hit_file(std::string const &path, struct stat const &st)
return;
}
auto num_objects = Striper::get_num_objects(layout, st.st_size);
auto num_objects = Striper::get_num_objects(layout, stx.stx_size);
for (uint64_t i = 0; i < num_objects; ++i) {
char buf[32];
snprintf(buf, sizeof(buf), "%llx.%08llx", (long long unsigned)st.st_ino,
snprintf(buf, sizeof(buf), "%llx.%08llx", (long long unsigned)stx.stx_ino,
(long long unsigned int)i);
dout(20) << " object " << std::string(buf) << dendl;

View File

@ -35,7 +35,7 @@ private:
std::set<pg_t> pgs;
std::set<uint64_t> pools;
void hit_file(std::string const &path, const struct stat &st);
void hit_file(std::string const &path, const struct ceph_statx &stx);
void hit_dir(std::string const &path);