From: Xiubo Li Date: Wed, 29 Jun 2022 09:11:36 +0000 (+0800) Subject: client: specify the quota type when finding the root quota realm X-Git-Tag: v18.0.0~164^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=dde1a19d4105f1db41477752a71d8fe40c45cd7f;p=ceph.git client: specify the quota type when finding the root quota realm Currently if only the quota.files is enabled for the statfs it will use the wrong quota realm when finding the root quota realm. And vice versa for the rename. This will specify the quota type for different cases. This is from Luis' kernel client's fix. Fixes: https://tracker.ceph.com/issues/56414 Signed-off-by: Xiubo Li --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 539b7b2d5a16..24318e601c89 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -11214,7 +11214,7 @@ int Client::statfs(const char *path, struct statvfs *stbuf, // quota but we can see a parent of it that does have a quota, we'll // respect that one instead. ceph_assert(root != nullptr); - InodeRef quota_root = root->quota.is_enable() ? root : get_quota_root(root.get(), perms); + InodeRef quota_root = root->quota.is_enable(QUOTA_MAX_BYTES) ? root : get_quota_root(root.get(), perms, QUOTA_MAX_BYTES); // get_quota_root should always give us something if client quotas are // enabled @@ -14076,9 +14076,9 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch } if (cct->_conf.get_val("client_quota") && fromdir != todir) { Inode *fromdir_root = - fromdir->quota.is_enable() ? fromdir : get_quota_root(fromdir, perm); + fromdir->quota.is_enable(QUOTA_MAX_FILES) ? fromdir : get_quota_root(fromdir, perm, QUOTA_MAX_FILES); Inode *todir_root = - todir->quota.is_enable() ? todir : get_quota_root(todir, perm); + todir->quota.is_enable(QUOTA_MAX_FILES) ? todir : get_quota_root(todir, perm, QUOTA_MAX_FILES); if (fromdir_root != todir_root) { return -CEPHFS_EXDEV; } @@ -15461,7 +15461,7 @@ bool Client::ms_handle_refused(Connection *con) return false; } -Inode *Client::get_quota_root(Inode *in, const UserPerm& perms) +Inode *Client::get_quota_root(Inode *in, const UserPerm& perms, quota_max_t type) { Inode *quota_in = root_ancestor; SnapRealm *realm = in->snaprealm; @@ -15476,7 +15476,7 @@ Inode *Client::get_quota_root(Inode *in, const UserPerm& perms) if (p == inode_map.end()) break; - if (p->second->quota.is_enable()) { + if (p->second->quota.is_enable(type)) { quota_in = p->second; break; } diff --git a/src/client/Client.h b/src/client/Client.h index e0e055b6dd1c..f84bef5d7fa8 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1072,7 +1072,7 @@ protected: int authenticate(); - Inode* get_quota_root(Inode *in, const UserPerm& perms); + Inode* get_quota_root(Inode *in, const UserPerm& perms, quota_max_t type=QUOTA_ANY); bool check_quota_condition(Inode *in, const UserPerm& perms, std::function test); bool is_quota_files_exceeded(Inode *in, const UserPerm& perms); diff --git a/src/include/cephfs/types.h b/src/include/cephfs/types.h index 92cb3acb468d..6709e9632dc2 100644 --- a/src/include/cephfs/types.h +++ b/src/include/cephfs/types.h @@ -217,6 +217,12 @@ inline bool operator<(const vinodeno_t &l, const vinodeno_t &r) { (l.ino == r.ino && l.snapid < r.snapid); } +typedef enum { + QUOTA_MAX_FILES, + QUOTA_MAX_BYTES, + QUOTA_ANY +} quota_max_t; + struct quota_info_t { void encode(ceph::buffer::list& bl) const { @@ -238,8 +244,16 @@ struct quota_info_t bool is_valid() const { return max_bytes >=0 && max_files >=0; } - bool is_enable() const { - return max_bytes || max_files; + bool is_enable(quota_max_t type=QUOTA_ANY) const { + switch (type) { + case QUOTA_MAX_FILES: + return !!max_files; + case QUOTA_MAX_BYTES: + return !!max_bytes; + case QUOTA_ANY: + default: + return !!max_bytes || !!max_files; + } } void decode_json(JSONObj *obj);