From fbb1648d31f5076a57aba95aef91fb26ebc2d100 Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Mon, 16 Nov 2020 10:56:00 +0000 Subject: [PATCH] Revert "client: optimize rename operation under different quota root" This reverts commit b8954e5734b3c53f90c47fbdbbbdb8a23747ef07. The possibility of doing a cross quota realms rename in the kernel client has been reverted because there was a corner case where it wasn't being handled correctly: mkdir files limit truncate files/file -s 10G setfattr limit -n ceph.quota.max_bytes -v 1000000 mv files limit/ The above would succeed because the kernel client won't immediately notify the MDSs with the new file size when doing a truncate(2), and thus the quota realms stats won't be updated. Although the fuse client doesn't have this issue, multi-client scenarios may be impacted. URL: https://tracker.ceph.com/issues/48203 Signed-off-by: Luis Henriques --- src/client/Client.cc | 69 +++++++------------------------------------- 1 file changed, 10 insertions(+), 59 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index aaf9db20c35..9b0dd2f069b 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -13184,6 +13184,15 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch else return -EROFS; } + if (fromdir != todir) { + Inode *fromdir_root = + fromdir->quota.is_enable() ? fromdir : get_quota_root(fromdir, perm); + Inode *todir_root = + todir->quota.is_enable() ? todir : get_quota_root(todir, perm); + if (fromdir_root != todir_root) { + return -EXDEV; + } + } InodeRef target; MetaRequest *req = new MetaRequest(op); @@ -13216,32 +13225,7 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch req->dentry_unless = CEPH_CAP_FILE_EXCL; InodeRef oldin, otherin; - Inode *fromdir_root = nullptr; - Inode *todir_root = nullptr; - int mask = 0; - bool quota_check = false; - if (fromdir != todir) { - fromdir_root = - fromdir->quota.is_enable() ? fromdir : get_quota_root(fromdir, perm); - todir_root = - todir->quota.is_enable() ? todir : get_quota_root(todir, perm); - - if (todir_root->quota.is_enable() && fromdir_root != todir_root) { - // use CEPH_STAT_RSTAT mask to force send getattr or lookup request - // to auth MDS to get latest rstat for todir_root and source dir - // even if their dentry caches and inode caps are satisfied. - res = _getattr(todir_root, CEPH_STAT_RSTAT, perm, true); - if (res < 0) - goto fail; - - quota_check = true; - if (oldde->inode && oldde->inode->is_dir()) { - mask |= CEPH_STAT_RSTAT; - } - } - } - - res = _lookup(fromdir, fromname, mask, &oldin, perm); + res = _lookup(fromdir, fromname, 0, &oldin, perm); if (res < 0) goto fail; @@ -13250,39 +13234,6 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch req->set_old_inode(oldinode); req->old_inode_drop = CEPH_CAP_LINK_SHARED; - if (quota_check) { - int64_t old_bytes, old_files; - if (oldinode->is_dir()) { - old_bytes = oldinode->rstat.rbytes; - old_files = oldinode->rstat.rsize(); - } else { - old_bytes = oldinode->size; - old_files = 1; - } - - bool quota_exceed = false; - if (todir_root && todir_root->quota.max_bytes && - (old_bytes + todir_root->rstat.rbytes) >= todir_root->quota.max_bytes) { - ldout(cct, 10) << "_rename (" << oldinode->ino << " bytes=" - << old_bytes << ") to (" << todir->ino - << ") will exceed quota on " << *todir_root << dendl; - quota_exceed = true; - } - - if (todir_root && todir_root->quota.max_files && - (old_files + todir_root->rstat.rsize()) >= todir_root->quota.max_files) { - ldout(cct, 10) << "_rename (" << oldinode->ino << " files=" - << old_files << ") to (" << todir->ino - << ") will exceed quota on " << *todir_root << dendl; - quota_exceed = true; - } - - if (quota_exceed) { - res = (oldinode->is_dir()) ? -EXDEV : -EDQUOT; - goto fail; - } - } - res = _lookup(todir, toname, 0, &otherin, perm); switch (res) { case 0: -- 2.39.5