···212212 return;213213}214214215215-/*216216- * Find a free multiplex id (SMB mid). Otherwise there could be217217- * mid collisions which might cause problems, demultiplexing the218218- * wrong response to this request. Multiplex ids could collide if219219- * one of a series requests takes much longer than the others, or220220- * if a very large number of long lived requests (byte range221221- * locks or FindNotify requests) are pending. No more than222222- * 64K-1 requests can be outstanding at one time. If no223223- * mids are available, return zero. A future optimization224224- * could make the combination of mids and uid the key we use225225- * to demultiplex on (rather than mid alone).226226- * In addition to the above check, the cifs demultiplex227227- * code already used the command code as a secondary228228- * check of the frame and if signing is negotiated the229229- * response would be discarded if the mid were the same230230- * but the signature was wrong. Since the mid is not put in the231231- * pending queue until later (when it is about to be dispatched)232232- * we do have to limit the number of outstanding requests233233- * to somewhat less than 64K-1 although it is hard to imagine234234- * so many threads being in the vfs at one time.235235- */236236-__u64 GetNextMid(struct TCP_Server_Info *server)237237-{238238- __u64 mid = 0;239239- __u16 last_mid, cur_mid;240240- bool collision;241241-242242- spin_lock(&GlobalMid_Lock);243243-244244- /* mid is 16 bit only for CIFS/SMB */245245- cur_mid = (__u16)((server->CurrentMid) & 0xffff);246246- /* we do not want to loop forever */247247- last_mid = cur_mid;248248- cur_mid++;249249-250250- /*251251- * This nested loop looks more expensive than it is.252252- * In practice the list of pending requests is short,253253- * fewer than 50, and the mids are likely to be unique254254- * on the first pass through the loop unless some request255255- * takes longer than the 64 thousand requests before it256256- * (and it would also have to have been a request that257257- * did not time out).258258- */259259- while (cur_mid != last_mid) {260260- struct mid_q_entry *mid_entry;261261- unsigned int num_mids;262262-263263- collision = false;264264- if (cur_mid == 0)265265- cur_mid++;266266-267267- num_mids = 0;268268- list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {269269- ++num_mids;270270- if (mid_entry->mid == cur_mid &&271271- mid_entry->mid_state == MID_REQUEST_SUBMITTED) {272272- /* This mid is in use, try a different one */273273- collision = true;274274- break;275275- }276276- }277277-278278- /*279279- * if we have more than 32k mids in the list, then something280280- * is very wrong. Possibly a local user is trying to DoS the281281- * box by issuing long-running calls and SIGKILL'ing them. If282282- * we get to 2^16 mids then we're in big trouble as this283283- * function could loop forever.284284- *285285- * Go ahead and assign out the mid in this situation, but force286286- * an eventual reconnect to clean out the pending_mid_q.287287- */288288- if (num_mids > 32768)289289- server->tcpStatus = CifsNeedReconnect;290290-291291- if (!collision) {292292- mid = (__u64)cur_mid;293293- server->CurrentMid = mid;294294- break;295295- }296296- cur_mid++;297297- }298298- spin_unlock(&GlobalMid_Lock);299299- return mid;300300-}301301-302215/* NB: MID can not be set if treeCon not passed in, in that303216 case it is responsbility of caller to set the mid */304217void···247334248335 /* Uid is not converted */249336 buffer->Uid = treeCon->ses->Suid;250250- buffer->Mid = GetNextMid(treeCon->ses->server);337337+ buffer->Mid = get_next_mid(treeCon->ses->server);251338 }252339 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)253340 buffer->Flags2 |= SMBFLG2_DFS;
+89
fs/cifs/smb1ops.c
···125125 return &server->credits;126126}127127128128+/*129129+ * Find a free multiplex id (SMB mid). Otherwise there could be130130+ * mid collisions which might cause problems, demultiplexing the131131+ * wrong response to this request. Multiplex ids could collide if132132+ * one of a series requests takes much longer than the others, or133133+ * if a very large number of long lived requests (byte range134134+ * locks or FindNotify requests) are pending. No more than135135+ * 64K-1 requests can be outstanding at one time. If no136136+ * mids are available, return zero. A future optimization137137+ * could make the combination of mids and uid the key we use138138+ * to demultiplex on (rather than mid alone).139139+ * In addition to the above check, the cifs demultiplex140140+ * code already used the command code as a secondary141141+ * check of the frame and if signing is negotiated the142142+ * response would be discarded if the mid were the same143143+ * but the signature was wrong. Since the mid is not put in the144144+ * pending queue until later (when it is about to be dispatched)145145+ * we do have to limit the number of outstanding requests146146+ * to somewhat less than 64K-1 although it is hard to imagine147147+ * so many threads being in the vfs at one time.148148+ */149149+static __u64150150+cifs_get_next_mid(struct TCP_Server_Info *server)151151+{152152+ __u64 mid = 0;153153+ __u16 last_mid, cur_mid;154154+ bool collision;155155+156156+ spin_lock(&GlobalMid_Lock);157157+158158+ /* mid is 16 bit only for CIFS/SMB */159159+ cur_mid = (__u16)((server->CurrentMid) & 0xffff);160160+ /* we do not want to loop forever */161161+ last_mid = cur_mid;162162+ cur_mid++;163163+164164+ /*165165+ * This nested loop looks more expensive than it is.166166+ * In practice the list of pending requests is short,167167+ * fewer than 50, and the mids are likely to be unique168168+ * on the first pass through the loop unless some request169169+ * takes longer than the 64 thousand requests before it170170+ * (and it would also have to have been a request that171171+ * did not time out).172172+ */173173+ while (cur_mid != last_mid) {174174+ struct mid_q_entry *mid_entry;175175+ unsigned int num_mids;176176+177177+ collision = false;178178+ if (cur_mid == 0)179179+ cur_mid++;180180+181181+ num_mids = 0;182182+ list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {183183+ ++num_mids;184184+ if (mid_entry->mid == cur_mid &&185185+ mid_entry->mid_state == MID_REQUEST_SUBMITTED) {186186+ /* This mid is in use, try a different one */187187+ collision = true;188188+ break;189189+ }190190+ }191191+192192+ /*193193+ * if we have more than 32k mids in the list, then something194194+ * is very wrong. Possibly a local user is trying to DoS the195195+ * box by issuing long-running calls and SIGKILL'ing them. If196196+ * we get to 2^16 mids then we're in big trouble as this197197+ * function could loop forever.198198+ *199199+ * Go ahead and assign out the mid in this situation, but force200200+ * an eventual reconnect to clean out the pending_mid_q.201201+ */202202+ if (num_mids > 32768)203203+ server->tcpStatus = CifsNeedReconnect;204204+205205+ if (!collision) {206206+ mid = (__u64)cur_mid;207207+ server->CurrentMid = mid;208208+ break;209209+ }210210+ cur_mid++;211211+ }212212+ spin_unlock(&GlobalMid_Lock);213213+ return mid;214214+}215215+128216struct smb_version_operations smb1_operations = {129217 .send_cancel = send_nt_cancel,130218 .compare_fids = cifs_compare_fids,···221133 .add_credits = cifs_add_credits,222134 .set_credits = cifs_set_credits,223135 .get_credits_field = cifs_get_credits_field,136136+ .get_next_mid = cifs_get_next_mid,224137 .read_data_offset = cifs_read_data_offset,225138 .read_data_length = cifs_read_data_length,226139 .map_error = map_smb_to_linux_error,