From: Christopher Hoffman Date: Thu, 28 Sep 2023 01:59:56 +0000 (+0000) Subject: mds: Implement remove for ceph vxattrs X-Git-Tag: v20.0.0~1640^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=1f0a099e4c41f62b55cfa3fd620ac06be34488da;p=ceph.git mds: Implement remove for ceph vxattrs For a variety of ceph xattrs, the setfattr remove isn't handled and "No such attribute" is returned. Add support to remove xattrs to match where docs say to clear value, one can remove or set to X value. When removing, add "default" value back to xattr depending on xattr name. Simplify current code to make clearer and minimize code reuse. Fixes: https://tracker.ceph.com/issues/62793 Signed-off-by: Christopher Hoffman --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 3dd2cc615601..14fdb3785c0f 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -6017,6 +6017,7 @@ int Server::check_layout_vxattr(const MDRequestRef& mdr, file_layout_t *layout) { const cref_t &req = mdr->client_request; + bool is_rmxattr = (req->get_op() == CEPH_MDS_OP_RMXATTR); epoch_t epoch; int r; @@ -6026,7 +6027,12 @@ int Server::check_layout_vxattr(const MDRequestRef& mdr, }); if (r == -CEPHFS_ENOENT) { + if (is_rmxattr) { + r = -CEPHFS_EINVAL; + respond_to_request(mdr, r); + return r; + } // we don't have the specified pool, make sure our map // is newer than or as new as the client. epoch_t req_epoch = req->get_osdmap_epoch(); @@ -6066,14 +6072,15 @@ int Server::check_layout_vxattr(const MDRequestRef& mdr, return 0; } -void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) +void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur) { const cref_t &req = mdr->client_request; + bool is_rmxattr = (req->get_op() == CEPH_MDS_OP_RMXATTR); MutationImpl::LockOpVec lov; string name(req->get_path2()); bufferlist bl = req->get_data(); string value (bl.c_str(), bl.length()); - dout(10) << "handle_set_vxattr " << name + dout(10) << "handle_client_setvxattr " << name << " val " << value.length() << " bytes on " << *cur << dendl; @@ -6115,19 +6122,44 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) else layout = mdcache->default_file_layout; - rest = name.substr(name.find("layout")); - if (check_layout_vxattr(mdr, rest, value, &layout) < 0) - return; + if (is_rmxattr && name == "ceph.dir.layout") { + lov.add_xlock(&cur->policylock); + if (!mds->locker->acquire_locks(mdr, lov)) { + return; + } + if (!cur->get_projected_inode()->has_layout()) { + respond_to_request(mdr, 0); + return; + } + auto pi = cur->project_inode(mdr); + + if (cur->is_root()) { + pi.inode->layout = mdcache->default_file_layout; + } else { + pi.inode->clear_layout(); + pi.inode->version = cur->pre_dirty(); + } + pip = pi.inode.get(); + } else { + rest = name.substr(name.find("layout")); + if (check_layout_vxattr(mdr, rest, value, &layout) < 0) + return; + + auto pi = cur->project_inode(mdr); + pi.inode->layout = layout; + pip = pi.inode.get(); + } - auto pi = cur->project_inode(mdr); - pi.inode->layout = layout; mdr->no_early_reply = true; - pip = pi.inode.get(); } else if (name.compare(0, 16, "ceph.file.layout") == 0) { if (!cur->is_file()) { respond_to_request(mdr, -CEPHFS_EINVAL); return; } + if (!cur->get_projected_inode()->has_layout()) { + respond_to_request(mdr, 0); + return; + } if (cur->get_projected_inode()->size || cur->get_projected_inode()->truncate_seq > 1) { respond_to_request(mdr, -CEPHFS_ENOTEMPTY); @@ -6160,6 +6192,13 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) } quota_info_t quota = cur->get_projected_inode()->quota; + if (is_rmxattr) { + if (!quota.is_enabled()) { + respond_to_request(mdr, 0); + return; + } + value = "0"; + } rest = name.substr(name.find("quota")); int r = parse_quota_vxattr(rest, value, "a); @@ -6245,6 +6284,14 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) bool val; try { + if (is_rmxattr) { + const auto srnode = cur->get_projected_srnode(); + if (!srnode->is_subvolume()) { + respond_to_request(mdr, 0); + return; + } + value = "0"; + } val = boost::lexical_cast(value); } catch (boost::bad_lexical_cast const&) { dout(10) << "bad vxattr value, unable to parse bool for " << name << dendl; @@ -6318,6 +6365,13 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) mds_rank_t rank; try { + if (is_rmxattr) { + if (cur->get_projected_inode()->export_pin == -1) { + respond_to_request(mdr, 0); + return; + } + value = "-1"; + } rank = boost::lexical_cast(value); if (rank < 0) rank = MDS_RANK_NONE; else if (rank >= MAX_MDS) { @@ -6344,6 +6398,13 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) double val; try { + if (is_rmxattr) { + if (cur->get_projected_inode()->export_ephemeral_random_pin == 0.0) { + respond_to_request(mdr, 0); + return; + } + value = "0"; + } val = boost::lexical_cast(value); } catch (boost::bad_lexical_cast const&) { dout(10) << "bad vxattr value, unable to parse float for " << name << dendl; @@ -6373,6 +6434,13 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) bool val; try { + if (is_rmxattr) { + if (cur->get_projected_inode()->get_ephemeral_distributed_pin() == 0) { + respond_to_request(mdr, 0); + return; + } + value = "0"; + } val = boost::lexical_cast(value); } catch (boost::bad_lexical_cast const&) { dout(10) << "bad vxattr value, unable to parse bool for " << name << dendl; @@ -6412,61 +6480,6 @@ void Server::handle_set_vxattr(const MDRequestRef& mdr, CInode *cur) return; } -void Server::handle_remove_vxattr(const MDRequestRef& mdr, CInode *cur) -{ - const cref_t &req = mdr->client_request; - string name(req->get_path2()); - - dout(10) << __func__ << " " << name << " on " << *cur << dendl; - - if (name == "ceph.dir.layout") { - if (!cur->is_dir()) { - respond_to_request(mdr, -CEPHFS_ENODATA); - return; - } - if (cur->is_root()) { - dout(10) << "can't remove layout policy on the root directory" << dendl; - respond_to_request(mdr, -CEPHFS_EINVAL); - return; - } - - if (!cur->get_projected_inode()->has_layout()) { - respond_to_request(mdr, -CEPHFS_ENODATA); - return; - } - - MutationImpl::LockOpVec lov; - lov.add_xlock(&cur->policylock); - if (!mds->locker->acquire_locks(mdr, lov)) - return; - - auto pi = cur->project_inode(mdr); - pi.inode->clear_layout(); - pi.inode->version = cur->pre_dirty(); - - // log + wait - mdr->ls = mdlog->get_current_segment(); - EUpdate *le = new EUpdate(mdlog, "remove dir layout vxattr"); - le->metablob.add_client_req(req->get_reqid(), req->get_oldest_client_tid()); - mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY); - mdcache->journal_dirty_inode(mdr.get(), &le->metablob, cur); - - mdr->no_early_reply = true; - journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(this, mdr, cur)); - return; - } else if (name == "ceph.dir.layout.pool_namespace" - || name == "ceph.file.layout.pool_namespace") { - // Namespace is the only layout field that has a meaningful - // null/none value (empty string, means default layout). Is equivalent - // to a setxattr with empty string: pass through the empty payload of - // the rmxattr request to do this. - handle_set_vxattr(mdr, cur); - return; - } - - respond_to_request(mdr, -CEPHFS_ENODATA); -} - const Server::XattrHandler Server::xattr_handlers[] = { { xattr_name: Server::DEFAULT_HANDLER, @@ -6657,7 +6670,7 @@ void Server::handle_client_setxattr(const MDRequestRef& mdr) if (!cur) return; - handle_set_vxattr(mdr, cur); + handle_client_setvxattr(mdr, cur); return; } @@ -6754,7 +6767,7 @@ void Server::handle_client_removexattr(const MDRequestRef& mdr) if (!cur) return; - handle_remove_vxattr(mdr, cur); + handle_client_setvxattr(mdr, cur); return; } diff --git a/src/mds/Server.h b/src/mds/Server.h index cbfe5c8cf5dd..1b3380886d42 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -232,8 +232,7 @@ public: std::string name, std::string value, file_layout_t *layout); - void handle_set_vxattr(const MDRequestRef& mdr, CInode *cur); - void handle_remove_vxattr(const MDRequestRef& mdr, CInode *cur); + void handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur); void handle_client_getvxattr(const MDRequestRef& mdr); void handle_client_setxattr(const MDRequestRef& mdr); void handle_client_removexattr(const MDRequestRef& mdr);