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

4
debian/.gitignore vendored
View File

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

24
debian/control vendored
View File

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

View File

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

View File

@ -6568,10 +6568,12 @@ force_request:
CEPH_CAP_FILE_WR; CEPH_CAP_FILE_WR;
} }
if (mask & CEPH_SETATTR_SIZE) { 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; 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); put_request(req);
ldout(cct,10) << "unable to set size to " << stx->stx_size << ". Too large!" << dendl;
return -EFBIG; return -EFBIG;
} }
req->inode_drop |= CEPH_CAP_AUTH_SHARED | CEPH_CAP_FILE_RD | 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); 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, int Client::stat(const char *relpath, struct stat *stbuf, const UserPerm& perms,
frag_info_t *dirstat, int mask) 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()); assert(client_lock.is_locked());
ldout(cct, 10) << "_readdir_cache_cb " << dirp << " on " << dirp->inode->ino 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; continue;
} }
struct stat st; int r = _getattr(dn->inode, caps, dirp->perms);
if (r < 0)
return r;
struct ceph_statx stx;
struct dirent de; struct dirent de;
int stmask = fill_stat(dn->inode, &st); fill_statx(dn->inode, caps, &stx);
uint64_t next_off = dn->offset + 1; uint64_t next_off = dn->offset + 1;
++pd; ++pd;
if (pd == dir->readdir_cache.end()) if (pd == dir->readdir_cache.end())
next_off = dir_result_t::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 dn_name = dn->name; // fill in name while we have lock
client_lock.Unlock(); 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(); client_lock.Lock();
ldout(cct, 15) << " de " << de.d_name << " off " << hex << dn->offset << dec ldout(cct, 15) << " de " << de.d_name << " off " << hex << dn->offset << dec
<< " = " << r << dendl; << " = " << r << dendl;
@ -7380,8 +7409,11 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p)
return 0; 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); Mutex::Locker lock(client_lock);
dir_result_t *dirp = static_cast<dir_result_t*>(d); 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; << " hash_order=" << dirp->hash_order() << dendl;
struct dirent de; struct dirent de;
struct stat st; struct ceph_statx stx;
memset(&de, 0, sizeof(de)); memset(&de, 0, sizeof(de));
memset(&st, 0, sizeof(st)); memset(&stx, 0, sizeof(stx));
InodeRef& diri = dirp->inode; 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 assert(diri->dn_set.size() < 2); // can't have multiple hard-links to a dir
uint64_t next_off = 1; uint64_t next_off = 1;
fill_stat(diri, &st); int r;
fill_dirent(&de, ".", S_IFDIR, st.st_ino, next_off); 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(); client_lock.Unlock();
int r = cb(p, &de, &st, -1, next_off); r = cb(p, &de, &stx, next_off, inode);
client_lock.Lock(); client_lock.Lock();
if (r < 0) if (r < 0)
return r; return r;
@ -7427,11 +7470,22 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
else else
in = diri->get_first_parent()->inode; in = diri->get_first_parent()->inode;
fill_stat(in, &st); int r;
fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off); 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(); client_lock.Unlock();
int r = cb(p, &de, &st, -1, next_off); r = cb(p, &de, &stx, next_off, inode);
client_lock.Lock(); client_lock.Lock();
if (r < 0) if (r < 0)
return r; 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 && if (dirp->inode->snapid != CEPH_SNAPDIR &&
dirp->inode->is_complete_and_ordered() && dirp->inode->is_complete_and_ordered() &&
dirp->inode->caps_issued_mask(CEPH_CAP_FILE_SHARED)) { 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) if (err != -EAGAIN)
return err; 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()) if (dirp->at_end())
return 0; return 0;
bool check_caps = true;
if (!dirp->is_cached()) { if (!dirp->is_cached()) {
int r = _readdir_get_frag(dirp); int r = _readdir_get_frag(dirp);
if (r) if (r)
return r; return r;
// _readdir_get_frag () may updates dirp->offset if the replied dirfrag is // _readdir_get_frag () may updates dirp->offset if the replied dirfrag is
// different than the requested one. (our dirfragtree was outdated) // different than the requested one. (our dirfragtree was outdated)
check_caps = false;
} }
frag_t fg = dirp->buffer_frag; 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; dir_result_t::dentry &entry = *it;
uint64_t next_off = entry.offset + 1; 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(); 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(); client_lock.Lock();
ldout(cct, 15) << " de " << de.d_name << " off " << hex << next_off - 1 << dec 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) 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 single_readdir {
struct dirent *de; struct dirent *de;
struct stat *st; struct ceph_statx *stx;
int *stmask; Inode *inode;
bool full; bool full;
}; };
static int _readdir_single_dirent_cb(void *p, struct dirent *de, struct stat *st, static int _readdir_single_dirent_cb(void *p, struct dirent *de,
int stmask, off_t off) struct ceph_statx *stx, off_t off,
Inode *in)
{ {
single_readdir *c = static_cast<single_readdir *>(p); 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 return -1; // already filled this dirent
*c->de = *de; *c->de = *de;
if (c->st) if (c->stx)
*c->st = *st; *c->stx = *stx;
if (c->stmask) c->inode = in;
*c->stmask = stmask;
c->full = true; c->full = true;
return 1; 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) struct dirent *Client::readdir(dir_result_t *d)
{ {
int ret; int ret;
static int stmask;
static struct dirent de; static struct dirent de;
static struct stat st;
single_readdir sr; single_readdir sr;
sr.de = &de; sr.de = &de;
sr.st = &st; sr.stx = NULL;
sr.stmask = &stmask; sr.inode = NULL;
sr.full = false; sr.full = false;
// our callback fills the dirent and sets sr.full=true on first // 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; 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; single_readdir sr;
sr.de = de; sr.de = de;
sr.st = st; sr.stx = stx;
sr.stmask = stmask; sr.inode = NULL;
sr.full = false; sr.full = false;
// our callback fills the dirent and sets sr.full=true on first // our callback fills the dirent and sets sr.full=true on first
// call, and returns -1 the second time around. // 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) if (r < -1)
return r; return r;
if (out)
*out = sr.inode;
if (sr.full) if (sr.full)
return 1; return 1;
return 0; return 0;
@ -7620,7 +7692,8 @@ struct getdents_result {
bool fullent; 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); struct getdents_result *c = static_cast<getdents_result *>(p);
@ -7672,7 +7745,7 @@ struct getdir_result {
int num; 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); 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; return r;
} }
int Client::ll_walk(const char* name, Inode **out, struct stat *attr, int Client::ll_lookupx(Inode *parent, const char *name, Inode **out,
const UserPerm& perms) 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); Mutex::Locker lock(client_lock);
filepath fp(name, 0); filepath fp(name, 0);
InodeRef in; InodeRef in;
int rc; int rc;
unsigned mask = statx_to_mask(flags, want);
ldout(cct, 3) << "ll_walk" << name << dendl; ldout(cct, 3) << "ll_walk" << name << dendl;
tout(cct) << "ll_walk" << std::endl; tout(cct) << "ll_walk" << std::endl;
tout(cct) << name << 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) { if (rc < 0) {
attr->st_ino = 0; /* zero out mask, just in case... */
stx->stx_mask = 0;
stx->stx_ino = 0;
*out = NULL; *out = NULL;
return rc; return rc;
} else { } else {
assert(in); assert(in);
fill_stat(in, attr); fill_statx(in, mask, stx);
*out = in.get(); *out = in.get();
return 0; return 0;
} }
} }
void Client::_ll_get(Inode *in) void Client::_ll_get(Inode *in)
{ {
if (in->ll_ref == 0) { if (in->ll_ref == 0) {
@ -10846,6 +10958,42 @@ int Client::ll_mknod(Inode *parent, const char *name, mode_t mode,
return r; 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, int Client::_create(Inode *dir, const char *name, int flags, mode_t mode,
InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count, InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count,
int object_size, const char *data_pool, bool *created, 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; 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, int Client::_symlink(Inode *dir, const char *name, const char *target,
const UserPerm& perms, InodeRef *inp) const UserPerm& perms, InodeRef *inp)
{ {
@ -11106,6 +11290,40 @@ int Client::ll_symlink(Inode *parent, const char *name, const char *value,
return r; 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) int Client::_unlink(Inode *dir, const char *name, const UserPerm& perm)
{ {
ldout(cct, 3) << "_unlink(" << dir->ino << " " << name 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, 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); Mutex::Locker lock(client_lock);
@ -11422,25 +11640,19 @@ int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
InodeRef target; InodeRef target;
if (!cct->_conf->fuse_default_permissions) { if (!cct->_conf->fuse_default_permissions) {
if (S_ISDIR(in->mode)) { if (S_ISDIR(in->mode))
r = -EPERM; return -EPERM;
goto out;
}
r = may_hardlink(in, perm); r = may_hardlink(in, perm);
if (r < 0) if (r < 0)
goto out; return r;
r = may_create(newparent, perm); r = may_create(newparent, perm);
if (r < 0) if (r < 0)
goto out; return r;
} }
r = _link(in, newparent, newname, perm, &target); return _link(in, newparent, newname, perm, &target);
if (r == 0) {
assert(target);
fill_stat(target, attr);
}
out:
return r;
} }
int Client::ll_num_osds(void) 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; return r;
} }
int Client::ll_create(Inode *parent, const char *name, mode_t mode, int Client::_ll_create(Inode *parent, const char *name, mode_t mode,
int flags, struct stat *attr, Inode **outp, Fh **fhp, int flags, InodeRef *in, int caps, Fh **fhp,
const UserPerm& perms) const UserPerm& perms)
{ {
*fhp = NULL; *fhp = NULL;
Mutex::Locker lock(client_lock);
vinodeno_t vparent = _get_vino(parent); 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() mode << dec << " " << flags << ", uid " << perms.uid()
<< ", gid " << perms.gid() << dendl; << ", gid " << perms.gid() << dendl;
tout(cct) << "ll_create" << std::endl; 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; tout(cct) << flags << std::endl;
bool created = false; bool created = false;
InodeRef in; int r = _lookup(parent, name, caps, in, perms);
int r = _lookup(parent, name, CEPH_STAT_CAP_INODE_ALL, &in, perms);
if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL)) if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
return -EEXIST; return -EEXIST;
@ -11646,7 +11855,7 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode,
if (r < 0) if (r < 0)
goto out; 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); perms);
if (r < 0) if (r < 0)
goto out; goto out;
@ -11655,13 +11864,12 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode,
if (r < 0) if (r < 0)
goto out; goto out;
assert(in); assert(*in);
fill_stat(in, attr);
ldout(cct, 20) << "ll_create created = " << created << dendl; ldout(cct, 20) << "_ll_create created = " << created << dendl;
if (!created) { if (!created) {
if (!cct->_conf->fuse_default_permissions) { if (!cct->_conf->fuse_default_permissions) {
r = may_open(in.get(), flags, perms); r = may_open(in->get(), flags, perms);
if (r < 0) { if (r < 0) {
if (*fhp) { if (*fhp) {
int release_r = _release_fh(*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) { if (*fhp == NULL) {
r = _open(in.get(), flags, mode, fhp, perms); r = _open(in->get(), flags, mode, fhp, perms);
if (r < 0) if (r < 0)
goto out; goto out;
} }
} }
out: out:
if (r < 0)
attr->st_ino = 0;
if (*fhp) { if (*fhp) {
ll_unclosed_fh_set.insert(*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 ino_t ino = 0;
if (outp) { if (r >= 0) {
if (in) 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()); _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; return r;

View File

@ -48,6 +48,7 @@ using std::fstream;
#include "InodeRef.h" #include "InodeRef.h"
#include "UserPerm.h" #include "UserPerm.h"
#include "include/cephfs/ceph_statx.h"
class FSMap; class FSMap;
class FSMapUser; 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); void fill_dirent(struct dirent *de, const char *name, int type, uint64_t ino, loff_t next_off);
// some readdir helpers // 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); int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms);
void _readdir_drop_dirp_buffer(dir_result_t *dirp); void _readdir_drop_dirp_buffer(dir_result_t *dirp);
@ -727,7 +728,7 @@ private:
void _readdir_next_frag(dir_result_t *dirp); void _readdir_next_frag(dir_result_t *dirp);
void _readdir_rechoose_frag(dir_result_t *dirp); void _readdir_rechoose_frag(dir_result_t *dirp);
int _readdir_get_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); void _closedir(dir_result_t *dirp);
// other helpers // other helpers
@ -952,11 +953,13 @@ public:
* Returns 0 if it reached the end of the directory. * Returns 0 if it reached the end of the directory.
* If @a cb returns a negative error code, stop and return that. * 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); struct dirent * readdir(dir_result_t *d);
int readdir_r(dir_result_t *dirp, struct dirent *de); 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, int getdir(const char *relpath, list<string>& names,
const UserPerm& perms); // get the whole dir at once. 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, int setattrx(const char *relpath, struct ceph_statx *stx, int mask,
const UserPerm& perms, int flags=0); const UserPerm& perms, int flags=0);
int fsetattr(int fd, struct stat *attr, int mask, const UserPerm& perms); 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 chmod(const char *path, mode_t mode, const UserPerm& perms);
int fchmod(int fd, 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); int lchmod(const char *path, mode_t mode, const UserPerm& perms);
@ -1113,6 +1117,9 @@ public:
Inode *ll_get_inode(vinodeno_t vino); Inode *ll_get_inode(vinodeno_t vino);
int ll_lookup(Inode *parent, const char *name, struct stat *attr, int ll_lookup(Inode *parent, const char *name, struct stat *attr,
Inode **out, const UserPerm& perms); 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_forget(Inode *in, int count);
bool ll_put(Inode *in); bool ll_put(Inode *in);
int ll_getattr(Inode *in, struct stat *st, const UserPerm& perms); 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_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, int ll_mknod(Inode *in, const char *name, mode_t mode, dev_t rdev,
struct stat *attr, Inode **out, const UserPerm& perms); 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, int ll_mkdir(Inode *in, const char *name, mode_t mode, struct stat *attr,
Inode **out, const UserPerm& perm); 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, int ll_symlink(Inode *in, const char *name, const char *value,
struct stat *attr, Inode **out, const UserPerm& perms); 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_unlink(Inode *in, const char *name, const UserPerm& perm);
int ll_rmdir(Inode *in, const char *name, const UserPerm& perms); int ll_rmdir(Inode *in, const char *name, const UserPerm& perms);
int ll_rename(Inode *parent, const char *name, Inode *newparent, int ll_rename(Inode *parent, const char *name, Inode *newparent,
const char *newname, const UserPerm& perm); const char *newname, const UserPerm& perm);
int ll_link(Inode *in, Inode *newparent, const char *newname, 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_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, int ll_create(Inode *parent, const char *name, mode_t mode, int flags,
struct stat *attr, Inode **out, Fh **fhp, struct stat *attr, Inode **out, Fh **fhp,
const UserPerm& perms); 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, int ll_read_block(Inode *in, uint64_t blockid, char *buf, uint64_t offset,
uint64_t length, file_layout_t* layout); 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_commit_blocks(Inode *in, uint64_t offset, uint64_t length);
int ll_statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms); int ll_statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms);
int ll_walk(const char* name, Inode **i, struct stat *attr, int ll_walk(const char* name, Inode **i, struct ceph_statx *stx,
const UserPerm& perms); // XXX in? unsigned int want, unsigned int flags, const UserPerm& perms);
uint32_t ll_stripe_unit(Inode *in); uint32_t ll_stripe_unit(Inode *in);
int ll_file_layout(Inode *in, file_layout_t *layout); int ll_file_layout(Inode *in, file_layout_t *layout);
uint64_t ll_snap_seq(Inode *in); uint64_t ll_snap_seq(Inode *in);

View File

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

View File

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

View File

@ -32,6 +32,7 @@
#include "ioctl.h" #include "ioctl.h"
#include "common/config.h" #include "common/config.h"
#include "include/assert.h" #include "include/assert.h"
#include "include/cephfs/ceph_statx.h"
#include "fuse_ll.h" #include "fuse_ll.h"
#include <fuse.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); UserPerm perm(ctx->uid, ctx->gid);
GET_GROUPS(perm, req); 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) { if (r == 0) {
fe.ino = cfuse->make_fake_ino(fe.attr.st_ino, fe.attr.st_dev); r = cfuse->client->ll_getattr(in, &fe.attr, perm);
fe.attr.st_rdev = new_encode_dev(fe.attr.st_rdev); if (r == 0) {
fuse_reply_entry(req, &fe); fe.ino = cfuse->make_fake_ino(fe.attr.st_ino, fe.attr.st_dev);
} else { fe.attr.st_rdev = new_encode_dev(fe.attr.st_rdev);
fuse_reply_err(req, -r); fuse_reply_entry(req, &fe);
}
}
if (r != 0) {
/* /*
* Many ll operations in libcephfs return an extra inode reference, but * Many ll operations in libcephfs return an extra inode reference, but
* ll_link currently does not. Still, FUSE needs one for the new dentry, * 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. * On error however, we must put that reference.
*/ */
cfuse->iput(in); cfuse->iput(in);
fuse_reply_err(req, -r);
} }
cfuse->iput(nin); cfuse->iput(nin);
@ -669,19 +679,21 @@ struct readdir_context {
/* /*
* return 0 on success, -1 if out of space * return 0 on success, -1 if out of space
*/ */
static int fuse_ll_add_dirent(void *p, struct dirent *de, struct stat *st, static int fuse_ll_add_dirent(void *p, struct dirent *de,
int stmask, off_t next_off) struct ceph_statx *stx, off_t next_off,
Inode *in)
{ {
struct readdir_context *c = (struct readdir_context *)p; struct readdir_context *c = (struct readdir_context *)p;
CephFuse::Handle *cfuse = (CephFuse::Handle *)fuse_req_userdata(c->req); CephFuse::Handle *cfuse = (CephFuse::Handle *)fuse_req_userdata(c->req);
st->st_ino = cfuse->make_fake_ino(de->d_ino, c->snap); struct stat st;
st->st_mode = DTTOIF(de->d_type); st.st_ino = cfuse->make_fake_ino(stx->stx_ino, c->snap);
st->st_rdev = new_encode_dev(st->st_rdev); st.st_mode = stx->stx_mode;
st.st_rdev = new_encode_dev(stx->stx_rdev);
size_t room = c->size - c->pos; size_t room = c->size - c->pos;
size_t entrysize = fuse_add_direntry(c->req, c->buf + c->pos, room, 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) if (entrysize > room)
return -ENOSPC; return -ENOSPC;

View File

@ -384,17 +384,17 @@ void CephBroker::rmdir(ResponseCallback *cb, const char *dname) {
int CephBroker::rmdir_recursive(const char *directory) { int CephBroker::rmdir_recursive(const char *directory) {
struct ceph_dir_result *dirp; struct ceph_dir_result *dirp;
struct dirent de; struct dirent de;
struct stat st; struct ceph_statx stx;
int r; int r;
if ((r = ceph_opendir(cmount, directory, &dirp)) < 0) if ((r = ceph_opendir(cmount, directory, &dirp)) < 0)
return r; //failed to open 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; String new_dir = de.d_name;
if(!(new_dir.compare(".")==0 || new_dir.compare("..")==0)) { if(!(new_dir.compare(".")==0 || new_dir.compare("..")==0)) {
new_dir = directory; new_dir = directory;
new_dir += '/'; new_dir += '/';
new_dir += de.d_name; 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; if((r=rmdir_recursive(new_dir.c_str())) < 0) return r;
} else { //delete this file } else { //delete this file
if((r=ceph_unlink(cmount, new_dir.c_str())) < 0) return r; 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 */ #endif /* ! __cplusplus */
struct UserPerm;
typedef struct UserPerm UserPerm;
struct Inode; struct Inode;
typedef struct Inode Inode; typedef struct Inode Inode;
@ -121,6 +124,34 @@ struct CephContext;
# define CEPHFS_ERROR_NEW_CLIENT 1002 # define CEPHFS_ERROR_NEW_CLIENT 1002
# define CEPHFS_ERROR_MESSENGER_START 1003 # 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 * @defgroup libcephfs_h_init Setup and Teardown
* These are the first and last functions that should be called * 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); 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. * 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 * @param dirp the directory stream pointer from an opendir holding the state of the
* next entry to return. * next entry to return.
* @param de the directory entry pointer filled in with the next directory entry of the dirp state. * @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 stx 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 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, * @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. * and a negative error code on failure.
*/ */
int ceph_readdirplus_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, struct dirent *de, 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. * 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); 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. * 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, int ceph_statx(struct ceph_mount_info *cmount, const char *path, struct ceph_statx *stx,
unsigned int want, unsigned int flags); 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. * 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 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 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); 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. * 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, int ceph_fallocate(struct ceph_mount_info *cmount, int fd, int mode,
int64_t offset, int64_t length); 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. * 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, int ceph_ll_lookup_root(struct ceph_mount_info *cmount,
Inode **parent); Inode **parent);
int ceph_ll_lookup(struct ceph_mount_info *cmount, struct Inode *parent, int ceph_ll_lookup(struct ceph_mount_info *cmount, Inode *parent,
const char *name, struct stat *attr, const char *name, Inode **out, struct ceph_statx *stx,
Inode **out, int uid, int gid); unsigned want, unsigned flags, const UserPerm *perms);
int ceph_ll_put(struct ceph_mount_info *cmount, struct Inode *in); 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 ceph_ll_forget(struct ceph_mount_info *cmount, struct Inode *in,
int count); int count);
int ceph_ll_walk(struct ceph_mount_info *cmount, const char *name, int ceph_ll_walk(struct ceph_mount_info *cmount, const char* name, Inode **i,
struct Inode **i, struct ceph_statx *stx, unsigned int want, unsigned int flags,
struct stat *attr); const UserPerm *perms);
int ceph_ll_getattr(struct ceph_mount_info *cmount, struct Inode *in, 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, 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, int ceph_ll_setattr(struct ceph_mount_info *cmount, struct Inode *in,
struct stat *st, int mask, int uid, int gid); struct ceph_statx *stx, int mask, const UserPerm *perms);
int ceph_ll_setattrx(struct ceph_mount_info *cmount, struct Inode *in,
struct ceph_statx *stx, int mask, int uid, int gid);
int ceph_ll_open(struct ceph_mount_info *cmount, struct Inode *in, int flags, 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 ceph_ll_lseek(struct ceph_mount_info *cmount, struct Fh* filehandle,
off_t offset, int whence); off_t offset, int whence);
int ceph_ll_read(struct ceph_mount_info *cmount, struct Fh* filehandle, 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 name name of attribute
* @param value pointer to begin buffer * @param value pointer to begin buffer
* @param size buffer size * @param size buffer size
* @param uid user ID * @param perms pointer to UserPerms object
* @param gid group ID
* @returns size of returned buffer. Negative number in error case * @returns size of returned buffer. Negative number in error case
*/ */
int ceph_ll_getxattr(struct ceph_mount_info *cmount, struct Inode *in, int ceph_ll_getxattr(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, void *value, size_t size, int uid, const char *name, void *value, size_t size,
int gid); const UserPerm *perms);
int ceph_ll_setxattr(struct ceph_mount_info *cmount, struct Inode *in, int ceph_ll_setxattr(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, const void *value, size_t size, 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, 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, int ceph_ll_removexattr(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, int uid, int gid); const char *name, const UserPerm *perms);
int ceph_ll_create(struct ceph_mount_info *cmount, struct Inode *parent, int ceph_ll_create(struct ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, int flags, const char *name, mode_t mode, int oflags, Inode **outp,
struct stat *attr, struct Inode **out, Fh **fhp, Fh **fhp, struct ceph_statx *stx, unsigned want,
int uid, int gid); unsigned lflags, const UserPerm *perms);
int ceph_ll_mknod(struct ceph_mount_info *cmount, struct Inode *parent, int ceph_ll_mknod(struct ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, dev_t rdev, const char *name, mode_t mode, dev_t rdev, Inode **out,
struct stat *attr, struct Inode **out, struct ceph_statx *stx, unsigned want, unsigned flags,
int uid, int gid); const UserPerm *perms);
int ceph_ll_mkdir(struct ceph_mount_info *cmount, struct Inode *parent, int ceph_ll_mkdir(struct ceph_mount_info *cmount, Inode *parent,
const char *name, mode_t mode, struct stat *attr, const char *name, mode_t mode, Inode **out,
Inode **out, int uid, int gid); struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms);
int ceph_ll_link(struct ceph_mount_info *cmount, struct Inode *in, int ceph_ll_link(struct ceph_mount_info *cmount, struct Inode *in,
struct Inode *newparrent, const char *name, struct Inode *newparent, const char *name,
struct stat *attr, int uid, int gid); const UserPerm *perms);
int ceph_ll_truncate(struct ceph_mount_info *cmount, struct Inode *in,
uint64_t length, int uid, int gid);
int ceph_ll_opendir(struct ceph_mount_info *cmount, struct Inode *in, 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, int ceph_ll_releasedir(struct ceph_mount_info *cmount,
struct ceph_dir_result* dir); struct ceph_dir_result* dir);
int ceph_ll_rename(struct ceph_mount_info *cmount, struct Inode *parent, int ceph_ll_rename(struct ceph_mount_info *cmount, struct Inode *parent,
const char *name, struct Inode *newparent, 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, 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, int ceph_ll_statfs(struct ceph_mount_info *cmount, struct Inode *in,
struct statvfs *stbuf); struct statvfs *stbuf);
int ceph_ll_readlink(struct ceph_mount_info *cmount, struct Inode *in, int ceph_ll_readlink(struct ceph_mount_info *cmount, struct Inode *in,
char *buf, size_t bufsize, int uid, int gid); char *buf, size_t bufsize, const UserPerm *perms);
int ceph_ll_symlink(struct ceph_mount_info *cmount, struct Inode *parent, int ceph_ll_symlink(struct ceph_mount_info *cmount,
const char *name, const char *value, struct stat *attr, Inode *in, const char *name, const char *value,
struct Inode **in, int uid, int gid); 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, 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, uint32_t ceph_ll_stripe_unit(struct ceph_mount_info *cmount,
struct Inode *in); struct Inode *in);
uint32_t ceph_ll_file_layout(struct ceph_mount_info *cmount, 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(); *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) extern "C" const char *ceph_version(int *pmajor, int *pminor, int *ppatch)
{ {
int major, minor, patch; 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; 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, extern "C" int ceph_statfs(struct ceph_mount_info *cmount, const char *path,
struct statvfs *stbuf) 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, 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()) if (!cmount->is_mounted())
return -ENOTCONN; 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, 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); 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, extern "C" int ceph_statx(struct ceph_mount_info *cmount, const char *path,
struct ceph_statx *stx, unsigned int want, unsigned int flags) 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); want, flags);
} }
extern "C" int ceph_lstat(struct ceph_mount_info *cmount, const char *path, extern "C" int ceph_fsetattrx(struct ceph_mount_info *cmount, int fd,
struct stat *stbuf) struct ceph_statx *stx, int mask)
{ {
if (!cmount->is_mounted()) if (!cmount->is_mounted())
return -ENOTCONN; return -ENOTCONN;
return cmount->get_client()->lstat(path, stbuf, cmount->default_perms); return cmount->get_client()->fsetattrx(fd, stx, mask, 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);
} }
extern "C" int ceph_setattrx(struct ceph_mount_info *cmount, const char *relpath, 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); 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, extern "C" int ceph_fstatx(struct ceph_mount_info *cmount, int fd, struct ceph_statx *stx,
unsigned int want, unsigned int flags) unsigned int want, unsigned int flags)
{ {
@ -1418,13 +1403,13 @@ extern "C" int ceph_ll_lookup_inode(
return 0; return 0;
} }
extern "C" int ceph_ll_lookup(class ceph_mount_info *cmount, extern "C" int ceph_ll_lookup(struct ceph_mount_info *cmount,
struct Inode *parent, const char *name, Inode *parent, const char *name, Inode **out,
struct stat *attr, Inode **out, struct ceph_statx *stx, unsigned want,
int uid, int gid) unsigned flags, const UserPerm *perms)
{ {
UserPerm perms(uid, gid); return (cmount->get_client())->ll_lookupx(parent, name, out, stx, want,
return (cmount->get_client())->ll_lookup(parent, name, attr, out, perms); flags, *perms);
} }
extern "C" int ceph_ll_put(class ceph_mount_info *cmount, Inode *in) 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)); return (cmount->get_client()->ll_forget(in, count));
} }
extern "C" int ceph_ll_walk(class ceph_mount_info *cmount, const char *name, int ceph_ll_walk(struct ceph_mount_info *cmount, const char* name, Inode **i,
struct Inode **i, struct ceph_statx *stx, unsigned int want, unsigned int flags,
struct stat *attr) 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, extern "C" int ceph_ll_getattr(class ceph_mount_info *cmount,
Inode *in, struct stat *attr, Inode *in, struct ceph_statx *stx,
int uid, int gid) unsigned int want, unsigned int flags,
const UserPerm *perms)
{ {
UserPerm perms(uid, gid); return (cmount->get_client()->ll_getattrx(in, stx, want, flags, *perms));
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));
} }
extern "C" int ceph_ll_setattr(class ceph_mount_info *cmount, 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, 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, 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, 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, extern "C" int ceph_ll_create(class ceph_mount_info *cmount,
struct Inode *parent, const char *name, Inode *parent, const char *name, mode_t mode,
mode_t mode, int flags, struct stat *attr, int oflags, Inode **outp, Fh **fhp,
struct Inode **out, Fh **fhp, int uid, int gid) struct ceph_statx *stx, unsigned want,
unsigned lflags, const UserPerm *perms)
{ {
UserPerm perms(uid, gid); return (cmount->get_client())->ll_createx(parent, name, mode, oflags, outp,
return (cmount->get_client())->ll_create(parent, name, mode, flags, fhp, stx, want, lflags, *perms);
attr, out, fhp, perms);
} }
extern "C" int ceph_ll_mknod(class ceph_mount_info *cmount, extern "C" int ceph_ll_mknod(class ceph_mount_info *cmount, Inode *parent,
struct Inode *parent, const char *name, const char *name, mode_t mode, dev_t rdev,
mode_t mode, dev_t rdev, struct stat *attr, Inode **out, struct ceph_statx *stx,
struct Inode **out, int uid, int gid) unsigned want, unsigned flags,
const UserPerm *perms)
{ {
UserPerm perms(uid, gid); return (cmount->get_client())->ll_mknodx(parent, name, mode, rdev,
return (cmount->get_client())->ll_mknod(parent, name, mode, rdev, out, stx, want, flags, *perms);
attr, out, perms);
} }
extern "C" int ceph_ll_mkdir(class ceph_mount_info *cmount, extern "C" int ceph_ll_mkdir(class ceph_mount_info *cmount, Inode *parent,
Inode *parent, const char *name, const char *name, mode_t mode, Inode **out,
mode_t mode, struct stat *attr, Inode **out, struct ceph_statx *stx, unsigned want,
int uid, int gid) unsigned flags, const UserPerm *perms)
{ {
UserPerm perms(uid, gid); return cmount->get_client()->ll_mkdirx(parent, name, mode, out, stx, want,
return (cmount->get_client()->ll_mkdir(parent, name, mode, attr, out, perms)); flags, *perms);
} }
extern "C" int ceph_ll_link(class ceph_mount_info *cmount, extern "C" int ceph_ll_link(class ceph_mount_info *cmount,
Inode *in, Inode *newparent, Inode *in, Inode *newparent,
const char *name, struct stat *attr, int uid, const char *name, const UserPerm *perms)
int gid)
{ {
UserPerm perms(uid, gid); return cmount->get_client()->ll_link(in, newparent, name, *perms);
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));
} }
extern "C" int ceph_ll_opendir(class ceph_mount_info *cmount, extern "C" int ceph_ll_opendir(class ceph_mount_info *cmount,
Inode *in, Inode *in,
struct ceph_dir_result **dirpp, 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, 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, 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, extern "C" int ceph_ll_rename(class ceph_mount_info *cmount,
Inode *parent, const char *name, Inode *parent, const char *name,
Inode *newparent, const char *newname, 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,
return (cmount->get_client()->ll_rename(parent, name, newname, *perms);
newparent, newname, perms));
} }
extern "C" int ceph_ll_unlink(class ceph_mount_info *cmount, extern "C" int ceph_ll_unlink(class ceph_mount_info *cmount, Inode *in,
Inode *in, const char *name, const char *name, const UserPerm *perms)
int uid, int gid)
{ {
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, 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)); return (cmount->get_client()->ll_statfs(in, stbuf, cmount->default_perms));
} }
extern "C" int ceph_ll_readlink(class ceph_mount_info *cmount, extern "C" int ceph_ll_readlink(class ceph_mount_info *cmount, Inode *in,
Inode *in, char *buf, size_t bufsiz, int uid, char *buf, size_t bufsiz,
int gid) 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, extern "C" int ceph_ll_symlink(class ceph_mount_info *cmount,
Inode *in, const char *name, Inode *in, const char *name,
const char *value, struct stat *attr, const char *value, Inode **out,
Inode **out, int uid, int gid) struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{ {
UserPerm perms(uid, gid); return (cmount->get_client()->ll_symlinkx(in, name, value, out, stx, want,
return (cmount->get_client()->ll_symlink(in, name, value, attr, out, perms)); flags, *perms));
} }
extern "C" int ceph_ll_rmdir(class ceph_mount_info *cmount, extern "C" int ceph_ll_rmdir(class ceph_mount_info *cmount,
Inode *in, const char *name, 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, extern "C" int ceph_ll_getxattr(class ceph_mount_info *cmount,
Inode *in, const char *name, void *value, 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, extern "C" int ceph_ll_listxattr(struct ceph_mount_info *cmount,
Inode *in, char *list, 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) { if (res >= 0) {
*list_size = (size_t)res; *list_size = (size_t)res;
return 0; 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, extern "C" int ceph_ll_setxattr(class ceph_mount_info *cmount,
Inode *in, const char *name, Inode *in, const char *name,
const void *value, size_t size, 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, extern "C" int ceph_ll_removexattr(class ceph_mount_info *cmount,
Inode *in, const char *name, 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, 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()); sprintf(c_file, "recordlock_test_%d", getpid());
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
int rc; int rc;
struct flock lock1, lock2; struct flock lock1, lock2;
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode // Get the root inode
rc = ceph_ll_lookup_root(cmount, &root); rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr, rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, 0, 0); &inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// write lock twice // write lock twice
@ -228,7 +229,7 @@ TEST(LibCephFS, BasicRecordLocking) {
ASSERT_EQ(lock2.l_pid, getpid()); ASSERT_EQ(lock2.l_pid, getpid());
ASSERT_EQ(0, ceph_ll_close(cmount, fh)); 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(); CLEANUP_CEPH();
} }
@ -282,7 +283,7 @@ static void thread_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
struct ceph_mount_info *const cmount = s.cmount; struct ceph_mount_info *const cmount = s.cmount;
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
struct flock lock1; struct flock lock1;
int rc; int rc;
struct timespec ts; struct timespec ts;
@ -292,8 +293,8 @@ static void thread_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT, &attr, rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, 0, 0); &inode, &fh, &stx, 0, 0, ceph_mount_perms(cmount));
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
lock1.l_type = F_WRLCK; lock1.l_type = F_WRLCK;
@ -373,17 +374,18 @@ TEST(LibCephFS, ConcurrentRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid); sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
struct flock lock1; struct flock lock1;
int rc; int rc;
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode // Get the root inode
rc = ceph_ll_lookup_root(cmount, &root); rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr, rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, 0, 0); &inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Lock // Lock
@ -502,7 +504,7 @@ TEST(LibCephFS, ConcurrentRecordLocking) {
ASSERT_EQ(NULL, retval); ASSERT_EQ(NULL, retval);
s.sem_destroy(); s.sem_destroy();
ASSERT_EQ(0, ceph_ll_close(cmount, fh)); 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(); CLEANUP_CEPH();
} }
@ -515,17 +517,18 @@ TEST(LibCephFS, ThreesomeRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid); sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
struct flock lock1; struct flock lock1;
int rc; int rc;
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode // Get the root inode
rc = ceph_ll_lookup_root(cmount, &root); rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr, rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, 0, 0); &inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Lock // Lock
@ -648,7 +651,7 @@ TEST(LibCephFS, ThreesomeRecordLocking) {
ASSERT_EQ(NULL, retval); ASSERT_EQ(NULL, retval);
s.sem_destroy(); s.sem_destroy();
ASSERT_EQ(0, ceph_ll_close(cmount, fh)); 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(); CLEANUP_CEPH();
} }
@ -667,7 +670,7 @@ static void process_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
struct timespec ts; struct timespec ts;
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
int rc; int rc;
struct flock lock1; struct flock lock1;
@ -679,8 +682,8 @@ static void process_ConcurrentRecordLocking(str_ConcurrentRecordLocking& s) {
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT, &attr, rc = ceph_ll_create(cmount, root, s.file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, 0, 0); &inode, &fh, &stx, 0, 0, ceph_mount_perms(cmount));
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
WAIT_MAIN(1); // (R1) WAIT_MAIN(1); // (R1)
@ -758,7 +761,7 @@ TEST(LibCephFS, DISABLED_InterProcessRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid); sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
struct flock lock1; struct flock lock1;
int rc; int rc;
@ -782,14 +785,15 @@ TEST(LibCephFS, DISABLED_InterProcessRecordLocking) {
struct timespec ts; struct timespec ts;
struct ceph_mount_info *cmount; struct ceph_mount_info *cmount;
STARTUP_CEPH(); STARTUP_CEPH();
UserPerm *perms = ceph_mount_perms(cmount);
// Get the root inode // Get the root inode
rc = ceph_ll_lookup_root(cmount, &root); rc = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr, rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT,
&inode, &fh, 0, 0); &inode, &fh, &stx, 0, 0, perms);
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Lock // Lock
@ -906,7 +910,7 @@ TEST(LibCephFS, DISABLED_InterProcessRecordLocking) {
s.sem_destroy(); s.sem_destroy();
ASSERT_EQ(0, munmap(shs, sizeof(*shs))); ASSERT_EQ(0, munmap(shs, sizeof(*shs)));
ASSERT_EQ(0, ceph_ll_close(cmount, fh)); 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(); CLEANUP_CEPH();
} }
@ -919,7 +923,7 @@ TEST(LibCephFS, DISABLED_ThreesomeInterProcessRecordLocking) {
sprintf(c_file, "recordlock_test_%d", mypid); sprintf(c_file, "recordlock_test_%d", mypid);
Fh *fh = NULL; Fh *fh = NULL;
Inode *root = NULL, *inode = NULL; Inode *root = NULL, *inode = NULL;
struct stat attr; struct ceph_statx stx;
struct flock lock1; struct flock lock1;
int rc; int rc;
@ -956,8 +960,9 @@ TEST(LibCephFS, DISABLED_ThreesomeInterProcessRecordLocking) {
ASSERT_EQ(rc, 0); ASSERT_EQ(rc, 0);
// Get the inode and Fh corresponding to c_file // Get the inode and Fh corresponding to c_file
rc = ceph_ll_create(cmount, root, c_file, fileMode, O_RDWR | O_CREAT, &attr, UserPerm *perms = ceph_mount_perms(cmount);
&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); ASSERT_EQ(rc, 0);
// Lock // Lock
@ -1077,6 +1082,6 @@ TEST(LibCephFS, DISABLED_ThreesomeInterProcessRecordLocking) {
s.sem_destroy(); s.sem_destroy();
ASSERT_EQ(0, munmap(shs, sizeof(*shs))); ASSERT_EQ(0, munmap(shs, sizeof(*shs)));
ASSERT_EQ(0, ceph_ll_close(cmount, fh)); 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(); CLEANUP_CEPH();
} }

View File

@ -424,9 +424,9 @@ TEST(LibCephFS, DirLs) {
found.clear(); found.clear();
while (true) { while (true) {
struct dirent rdent; struct dirent rdent;
struct stat st; struct ceph_statx stx;
int stmask; int len = ceph_readdirplus_r(cmount, ls_dir, &rdent, &stx,
int len = ceph_readdirplus_r(cmount, ls_dir, &rdent, &st, &stmask); CEPH_STATX_SIZE, AT_NO_ATTR_SYNC, NULL);
if (len == 0) if (len == 0)
break; break;
ASSERT_EQ(len, 1); ASSERT_EQ(len, 1);
@ -434,8 +434,9 @@ TEST(LibCephFS, DirLs) {
found.push_back(name); found.push_back(name);
int size; int size;
sscanf(name, "dirf%d", &size); sscanf(name, "dirf%d", &size);
ASSERT_EQ(st.st_size, size); ASSERT_TRUE(stx.stx_mask & CEPH_STATX_SIZE);
ASSERT_EQ(st.st_ino, rdent.d_ino); 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(st.st_mode, (mode_t)0666);
} }
ASSERT_EQ(found, entries); ASSERT_EQ(found, entries);
@ -568,21 +569,25 @@ TEST(LibCephFS, Xattrs_ll) {
Inode *root = NULL; Inode *root = NULL;
Inode *existent_file_handle = NULL; Inode *existent_file_handle = NULL;
struct stat attr;
int res = ceph_ll_lookup_root(cmount, &root); int res = ceph_ll_lookup_root(cmount, &root);
ASSERT_EQ(res, 0); 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); ASSERT_EQ(res, 0);
const char *valid_name = "user.attrname"; const char *valid_name = "user.attrname";
const char *value = "attrvalue"; const char *value = "attrvalue";
char value_buf[256] = { 0 }; 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); 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)); ASSERT_EQ(res, (int)strlen(value));
value_buf[res] = '\0'; value_buf[res] = '\0';
@ -1132,10 +1137,8 @@ TEST(LibCephFS, UseUnmounted) {
struct dirent rdent; struct dirent rdent;
EXPECT_EQ(-ENOTCONN, ceph_readdir_r(cmount, dirp, &rdent)); EXPECT_EQ(-ENOTCONN, ceph_readdir_r(cmount, dirp, &rdent));
int stmask;
struct ceph_statx stx; struct ceph_statx stx;
struct stat st; EXPECT_EQ(-ENOTCONN, ceph_readdirplus_r(cmount, dirp, &rdent, &stx, 0, 0, NULL));
EXPECT_EQ(-ENOTCONN, ceph_readdirplus_r(cmount, dirp, &rdent, &st, &stmask));
EXPECT_EQ(-ENOTCONN, ceph_getdents(cmount, dirp, NULL, 0)); EXPECT_EQ(-ENOTCONN, ceph_getdents(cmount, dirp, NULL, 0));
EXPECT_EQ(-ENOTCONN, ceph_getdnames(cmount, dirp, NULL, 0)); EXPECT_EQ(-ENOTCONN, ceph_getdnames(cmount, dirp, NULL, 0));
EXPECT_EQ(-ENOTCONN, ceph_telldir(cmount, dirp)); 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_lremovexattr(cmount, "/path", "name"));
EXPECT_EQ(-ENOTCONN, ceph_setxattr(cmount, "/path", "name", NULL, 0, 0)); 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_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_chmod(cmount, "/path", 0));
EXPECT_EQ(-ENOTCONN, ceph_fchmod(cmount, 0, 0)); EXPECT_EQ(-ENOTCONN, ceph_fchmod(cmount, 0, 0));
EXPECT_EQ(-ENOTCONN, ceph_chown(cmount, "/path", 0, 0)); EXPECT_EQ(-ENOTCONN, ceph_chown(cmount, "/path", 0, 0));
@ -1392,20 +1395,23 @@ TEST(LibCephFS, Nlink) {
sprintf(filename, "nlinkorig%x", getpid()); sprintf(filename, "nlinkorig%x", getpid());
sprintf(linkname, "nlinklink%x", getpid()); sprintf(linkname, "nlinklink%x", getpid());
struct stat st; struct ceph_statx stx;
Fh *fh; 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, ASSERT_EQ(ceph_ll_create(cmount, dir, filename, 0666, O_RDWR|O_CREAT|O_EXCL,
&st, &file, &fh, getuid(), getgid()), 0); &file, &fh, &stx, CEPH_STATX_NLINK, 0, perms), 0);
ASSERT_EQ(st.st_nlink, (nlink_t)1); ASSERT_EQ(stx.stx_nlink, (nlink_t)1);
ASSERT_EQ(ceph_ll_link(cmount, file, dir, linkname, &st, getuid(), getgid()), 0); ASSERT_EQ(ceph_ll_link(cmount, file, dir, linkname, perms), 0);
ASSERT_EQ(st.st_nlink, (nlink_t)2); 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_unlink(cmount, dir, linkname, perms), 0);
ASSERT_EQ(ceph_ll_lookup(cmount, dir, filename, &st, &file, getuid(), getgid()), 0); ASSERT_EQ(ceph_ll_lookup(cmount, dir, filename, &file, &stx,
ASSERT_EQ(st.st_nlink, (nlink_t)1); CEPH_STATX_NLINK, 0, perms), 0);
ASSERT_EQ(stx.stx_nlink, (nlink_t)1);
ceph_shutdown(cmount); ceph_shutdown(cmount);
} }
@ -1558,30 +1564,31 @@ TEST(LibCephFS, LazyStatx) {
sprintf(filename, "lazystatx%x", getpid()); sprintf(filename, "lazystatx%x", getpid());
Inode *root1, *file1, *root2, *file2; Inode *root1, *file1, *root2, *file2;
struct stat st; struct ceph_statx stx;
Fh *fh; Fh *fh;
UserPerm *perms1 = ceph_mount_perms(cmount1);
UserPerm *perms2 = ceph_mount_perms(cmount2);
ASSERT_EQ(ceph_ll_lookup_root(cmount1, &root1), 0); 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, 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_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 * 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 * different ctime with a statx that uses AT_NO_ATTR_SYNC
*/ */
sleep(1); sleep(1);
st.st_mode = 0644; stx.stx_mode = 0644;
ASSERT_EQ(ceph_ll_setattr(cmount1, file1, &st, CEPH_SETATTR_MODE, getuid(), getgid()), 0); ASSERT_EQ(ceph_ll_setattr(cmount1, file1, &stx, CEPH_SETATTR_MODE, perms1), 0);
struct ceph_statx stx; ASSERT_EQ(ceph_ll_getattr(cmount2, file2, &stx, CEPH_STATX_CTIME, AT_NO_ATTR_SYNC, perms2), 0);
ASSERT_EQ(ceph_ll_getattrx(cmount2, file2, &stx, CEPH_STATX_CTIME, AT_NO_ATTR_SYNC, getuid(), getgid()), 0);
ASSERT_TRUE(stx.stx_mask & CEPH_STATX_CTIME); ASSERT_TRUE(stx.stx_mask & CEPH_STATX_CTIME);
ASSERT_TRUE(stx.stx_ctime.tv_sec == old_ctime.tv_sec && ASSERT_TRUE(stx.stx_ctime.tv_sec == old_ctime.tv_sec &&
stx.stx_ctime.tv_nsec == old_ctime.tv_nsec); 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); int fd = ceph_open(cmount, filename, O_RDWR|O_CREAT|O_EXCL, 0666);
ASSERT_LT(0, fd); ASSERT_LT(0, fd);
struct stat st; struct ceph_statx stx;
uint64_t size = 8388608; uint64_t size = 8388608;
st.st_size = (off_t)size; stx.stx_size = (off_t)size;
ASSERT_EQ(ceph_fsetattr(cmount, fd, &st, CEPH_SETATTR_SIZE), 0); ASSERT_EQ(ceph_fsetattrx(cmount, fd, &stx, CEPH_SETATTR_SIZE), 0);
ASSERT_EQ(ceph_fstatx(cmount, fd, &stx, CEPH_STATX_SIZE, 0), 0);
struct stat stbuf; ASSERT_EQ(stx.stx_size, (off_t)size);
ASSERT_EQ(ceph_fstat(cmount, fd, &stbuf), 0);
ASSERT_EQ(stbuf.st_size, (off_t)size);
ceph_close(cmount, fd); ceph_close(cmount, fd);
ceph_shutdown(cmount); ceph_shutdown(cmount);

View File

@ -69,9 +69,10 @@ void PgFiles::hit_dir(std::string const &path)
continue; continue;
} }
struct stat st; struct ceph_statx stx;
std::string de_path = (path + std::string("/") + de.d_name); 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) { if (r != 0) {
derr << "Failed to stat path " << de_path << ": " derr << "Failed to stat path " << de_path << ": "
<< cpp_strerror(r) << dendl; << cpp_strerror(r) << dendl;
@ -79,9 +80,9 @@ void PgFiles::hit_dir(std::string const &path)
continue; continue;
} }
if (S_ISREG(st.st_mode)) { if (S_ISREG(stx.stx_mode)) {
hit_file(de_path, st); hit_file(de_path, stx);
} else if (S_ISDIR(st.st_mode)) { } else if (S_ISDIR(stx.stx_mode)) {
hit_dir(de_path); hit_dir(de_path);
} else { } else {
dout(20) << "Skipping non reg/dir file: " << de_path << dendl; 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; dout(20) << "Hitting file '" << path << "'" << dendl;
@ -127,11 +128,11 @@ void PgFiles::hit_file(std::string const &path, struct stat const &st)
return; 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) { for (uint64_t i = 0; i < num_objects; ++i) {
char buf[32]; 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); (long long unsigned int)i);
dout(20) << " object " << std::string(buf) << dendl; dout(20) << " object " << std::string(buf) << dendl;

View File

@ -35,7 +35,7 @@ private:
std::set<pg_t> pgs; std::set<pg_t> pgs;
std::set<uint64_t> pools; 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); void hit_dir(std::string const &path);