SERVER-120968 Mark authorization/authentication commands as non-deprioritizable (#49165)

GitOrigin-RevId: 62a7a47c99e82ee0ed72881d8e849a8f607015ad
This commit is contained in:
wolfee
2026-03-09 18:20:39 +01:00
committed by MongoDB Bot
parent e1430923b7
commit 79ccf499d8
3 changed files with 52 additions and 10 deletions

View File

@@ -228,23 +228,50 @@ bool ExecutionAdmissionContext::_shouldRecordStats() {
}
admission::execution_control::ScopedTaskTypeModifierBase::ScopedTaskTypeModifierBase(
OperationContext* opCtx, ExecutionAdmissionContext::TaskType newValue)
OperationContext* opCtx, ExecutionAdmissionContext::TaskType newType)
: _opCtx(opCtx) {
dassert(ExecutionAdmissionContext::get(_opCtx).getTaskType() ==
ExecutionAdmissionContext::TaskType::Default);
dassert(ExecutionAdmissionContext::get(_opCtx).getPriority() ==
AdmissionContext::Priority::kNormal);
const auto currentType = ExecutionAdmissionContext::get(_opCtx).getTaskType();
const auto currentPrio = ExecutionAdmissionContext::get(_opCtx).getPriority();
dassert(currentType == newType || currentType == ExecutionAdmissionContext::TaskType::Default);
dassert(currentPrio == AdmissionContext::Priority::kExempt ||
currentPrio == AdmissionContext::Priority::kNormal);
dassert(!_opCtx->inMultiDocumentTransaction());
ExecutionAdmissionContext::get(_opCtx)._taskType.store(newValue);
ExecutionAdmissionContext::get(_opCtx)._taskType.store(newType);
// There is no need for mutex here, because the thread <-> operation context (and
// ExecutionAdmissionContext) is a 1 to 1 relation.
// Nobody should update the ExecutionAdmissionContext's counter from a different thread (sharing
// opCtx is prohibited).
const auto recursionCount =
++ExecutionAdmissionContext::get(_opCtx)._scopedTaskTypeModifierRecursion;
if (recursionCount < 1) {
LOGV2_WARNING(12096800,
"Inconsistency in _scopedTaskTypeModifierRecursion count. Resetting it to 1.",
"recursionCount"_attr = recursionCount);
dassert(false);
ExecutionAdmissionContext::get(_opCtx)._scopedTaskTypeModifierRecursion = 1;
}
LOGV2_DEBUG(12043501,
1,
"Changing task type on ExecutionAdmissionContext",
"newValue"_attr = to_string(newValue));
"newValue"_attr = to_string(newType));
}
admission::execution_control::ScopedTaskTypeModifierBase::~ScopedTaskTypeModifierBase() {
ExecutionAdmissionContext::get(_opCtx)._taskType.store(
ExecutionAdmissionContext::TaskType::Default);
// There is no need for mutex here, because the thread <-> operation context (and
// ExecutionAdmissionContext) is a 1 to 1 relation.
// Nobody should update the ExecutionAdmissionContext's counter from a different thread (sharing
// opCtx is prohibited).
const auto recursionCount =
--ExecutionAdmissionContext::get(_opCtx)._scopedTaskTypeModifierRecursion;
dassert(recursionCount >= 0);
if (recursionCount == 0) {
ExecutionAdmissionContext::get(_opCtx)._taskType.store(
ExecutionAdmissionContext::TaskType::Default);
}
}
admission::execution_control::ScopedTaskTypeBackground::ScopedTaskTypeBackground(

View File

@@ -275,6 +275,10 @@ private:
// True if the operation was ever in a multi-document transaction. Once set to true, stays true.
Atomic<bool> _wasInMultiDocTxn{false};
// ScopedTaskTypeModifier recursion counter to handle interleaving task type modifier
// destructions.
int _scopedTaskTypeModifierRecursion{0};
};
inline std::string to_string(ExecutionAdmissionContext::TaskType tt) {
@@ -305,7 +309,7 @@ public:
protected:
ScopedTaskTypeModifierBase(OperationContext* opCtx,
ExecutionAdmissionContext::TaskType newValue);
ExecutionAdmissionContext::TaskType newType);
private:
OperationContext* _opCtx;

View File

@@ -304,6 +304,8 @@ AuthorizationBackendLocal::RolesSnapshot AuthorizationBackendLocal::_snapshotRol
Status AuthorizationBackendLocal::rolesExist(OperationContext* opCtx,
const std::vector<RoleName>& roleNames) {
admission::execution_control::ScopedTaskTypeNonDeprioritizable deprioGuard(opCtx);
// Perform DB queries for user-defined roles (skipping builtin roles).
stdx::unordered_set<RoleName> unknownRoles;
for (const auto& roleName : roleNames) {
@@ -323,6 +325,8 @@ Status AuthorizationBackendLocal::rolesExist(OperationContext* opCtx,
StatusWith<ResolvedRoleData> AuthorizationBackendLocal::resolveRoles(
OperationContext* opCtx, const std::vector<RoleName>& roleNames, ResolveRoleOption option) try {
admission::execution_control::ScopedTaskTypeNonDeprioritizable deprioGuard(opCtx);
using RoleNameSet = typename decltype(ResolvedRoleData::roles)::value_type;
const bool processRoles = option.shouldMineRoles();
const bool processPrivs = option.shouldMinePrivileges();
@@ -462,6 +466,8 @@ StatusWith<User> AuthorizationBackendLocal::getUserObject(
OperationContext* opCtx,
const UserRequest& userReq,
const SharedUserAcquisitionStats& userAcquisitionStats) try {
admission::execution_control::ScopedTaskTypeNonDeprioritizable deprioGuard(opCtx);
std::vector<RoleName> directRoles;
User user(userReq.clone());
@@ -537,6 +543,8 @@ Status AuthorizationBackendLocal::getUserDescription(
const UserRequest& userReq,
BSONObj* result,
const SharedUserAcquisitionStats& userAcquisitionStats) try {
admission::execution_control::ScopedTaskTypeNonDeprioritizable deprioGuard(opCtx);
const UserName& userName = userReq.getUserName();
std::vector<RoleName> directRoles;
BSONObjBuilder resultBuilder;
@@ -635,6 +643,7 @@ Status AuthorizationBackendLocal::getRolesDescription(
PrivilegeFormat showPrivileges,
AuthenticationRestrictionsFormat showRestrictions,
std::vector<BSONObj>* result) {
admission::execution_control::ScopedTaskTypeNonDeprioritizable deprioGuard(opCtx);
if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {
// Shouldn't be called this way, but cope if we are.
@@ -704,6 +713,8 @@ Status AuthorizationBackendLocal::getRoleDescriptionsForDB(
AuthenticationRestrictionsFormat showRestrictions,
bool showBuiltinRoles,
std::vector<BSONObj>* result) {
admission::execution_control::ScopedTaskTypeNonDeprioritizable deprioGuard(opCtx);
auto option = makeResolveRoleOption(showPrivileges, showRestrictions);
if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {