summaryrefslogtreecommitdiffstats
path: root/src/client/Client.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/Client.cc')
-rw-r--r--src/client/Client.cc52
1 files changed, 41 insertions, 11 deletions
diff --git a/src/client/Client.cc b/src/client/Client.cc
index c404057b929..00b85a8e746 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -8907,7 +8907,6 @@ int Client::chownat(int dirfd, const char *relpath, uid_t new_uid, gid_t new_gid
tout(cct) << new_gid << std::endl;
tout(cct) << flags << std::endl;
- filepath path(relpath);
InodeRef in;
InodeRef dirinode;
@@ -8917,10 +8916,24 @@ int Client::chownat(int dirfd, const char *relpath, uid_t new_uid, gid_t new_gid
return r;
}
- r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
- if (r < 0) {
- return r;
+ if (!strcmp(relpath, "")) {
+#if defined(__linux__) && defined(AT_EMPTY_PATH)
+ if (flags & AT_EMPTY_PATH) {
+ in = dirinode;
+ goto out;
+ }
+#endif
+ return -CEPHFS_ENOENT;
+ } else {
+ filepath path(relpath);
+ r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
+ if (r < 0) {
+ return r;
+ }
}
+
+out:
+
struct stat attr;
attr.st_uid = new_uid;
attr.st_gid = new_gid;
@@ -11740,8 +11753,12 @@ int64_t Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
cond_iofinish = new C_SaferCond();
filer_iofinish.reset(cond_iofinish);
} else {
- //Register a wrapper callback for the C_Write_Finisher which takes 'client_lock'
- filer_iofinish.reset(new C_Lock_Client_Finisher(this, iofinish.get()));
+ //Register a wrapper callback C_Lock_Client_Finisher for the C_Write_Finisher which takes 'client_lock'.
+ //Use C_OnFinisher for callbacks. The op_cancel_writes has to be called without 'client_lock' held because
+ //the callback registered here needs to take it. This would cause incorrect lock order i.e., objecter->rwlock
+ //taken by objecter's op_cancel and then 'client_lock' taken by callback. To fix the lock order, queue
+ //the callback using the finisher
+ filer_iofinish.reset(new C_OnFinisher(new C_Lock_Client_Finisher(this, iofinish.get()), &objecter_finisher));
}
get_cap_ref(in, CEPH_CAP_FILE_BUFFER);
@@ -12230,6 +12247,7 @@ int Client::statxat(int dirfd, const char *relpath,
unsigned mask = statx_to_mask(flags, want);
+ InodeRef in;
InodeRef dirinode;
std::scoped_lock lock(client_lock);
int r = get_fd_inode(dirfd, &dirinode);
@@ -12237,12 +12255,24 @@ int Client::statxat(int dirfd, const char *relpath,
return r;
}
- InodeRef in;
- filepath path(relpath);
- r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask, dirinode);
- if (r < 0) {
- return r;
+ if (!strcmp(relpath, "")) {
+#if defined(__linux__) && defined(AT_EMPTY_PATH)
+ if (flags & AT_EMPTY_PATH) {
+ in = dirinode;
+ goto out;
+ }
+#endif
+ return -CEPHFS_ENOENT;
+ } else {
+ filepath path(relpath);
+ r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask, dirinode);
+ if (r < 0) {
+ return r;
+ }
}
+
+out:
+
r = _getattr(in, mask, perms);
if (r < 0) {
ldout(cct, 3) << __func__ << " exit on error!" << dendl;