[snip] > > - if (credits_requested > 0) { > + /* We must grant 0 credit for the final response of an asynchronous > + * operation. > + */ > + if ((hdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) && !work->multiRsp) { Can you elaborate what is this check ? especially this !work->multiRsp.. > + credits_granted = 0; > + } else { > + /* according to smb2.credits smbtorture, Windows server > + * 2016 or later grant up to 8192 credits at one. > + */ > aux_credits = credits_requested - 1; > - aux_max = 32; > if (hdr->Command == SMB2_NEGOTIATE) > aux_max = 0; > - aux_credits = (aux_credits < aux_max) ? aux_credits : aux_max; > - credits_granted = aux_credits + credit_charge; > + else > + aux_max = conn->max_credits - credit_charge; > + aux_credits = min_t(unsigned short, aux_credits, aux_max); > + credits_granted = credit_charge + aux_credits; > + > + if (conn->max_credits - conn->total_credits < credits_granted) > + credits_granted = conn->max_credits - > + conn->total_credits; > > - /* if credits granted per client is getting bigger than default > - * minimum credits then we should wrap it up within the limits. > - */ > - if ((conn->total_credits + credits_granted) > min_credits) > - credits_granted = min_credits - conn->total_credits; > /* > * TODO: Need to adjuct CreditRequest value according to > * current cpu load > */ > - } else if (conn->total_credits == 0) { > - credits_granted = 1; > } > > conn->total_credits += credits_granted; > @@ -371,7 +358,6 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) > /* Update CreditRequest in last request */ > hdr->CreditRequest = cpu_to_le16(work->credits_granted); > } > -out: > ksmbd_debug(SMB, > "credits: requested[%d] granted[%d] total_granted[%d]\n", > credits_requested, credits_granted, > @@ -692,13 +678,18 @@ int setup_async_work(struct ksmbd_work *work, void > (*fn)(void **), void **arg) > > void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status) > { > - struct smb2_hdr *rsp_hdr; > + struct smb2_hdr *rsp_hdr = work->response_buf; > + > + work->multiRsp = 1; > + if (status != STATUS_CANCELLED) { > + spin_lock(&work->conn->credits_lock); > + smb2_set_rsp_credits(work); Can you explain why this code is needed in smb2_send_interim_resp() ? > + spin_unlock(&work->conn->credits_lock); > + } > > - rsp_hdr = work->response_buf; > smb2_set_err_rsp(work); > rsp_hdr->Status = status; > > - work->multiRsp = 1; > ksmbd_conn_write(work); > rsp_hdr->Status = 0; > work->multiRsp = 0; > @@ -1233,6 +1224,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work) > > conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode); > ksmbd_conn_set_need_negotiate(work); > + conn->total_credits = 0; This line is needed ? Thanks! > > err_out: > if (rc < 0) > -- > 2.25.1 > >