History

Merge tag '6.17-rc1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French: - Fix unlink race and rename races - SMB3.1.1 compression fix - Avoid unneeded strlen calls in cifs_get_spnego_key - Fix slab out of bounds in parse_server_interfaces() - Fix mid leak and server buffer leak - smbdirect send error path fix - update internal version # - Fix unneeded response time update in negotiate protocol * tag '6.17-rc1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb: client: remove redundant lstrp update in negotiate protocol cifs: update internal version number smb: client: don't wait for info->send_pending == 0 on error smb: client: fix mid_q_entry memleak leak with per-mid locking smb3: fix for slab out of bounds on mount to ksmbd cifs: avoid extra calls to strlen() in cifs_get_spnego_key() cifs: Fix collect_sample() to handle any iterator type smb: client: fix race with concurrent opens in rename(2) smb: client: fix race with concurrent opens in unlink(2)

Linus Torvalds committed 1 year ago

Commit 55ddcff2 parents d7ee5bd e19d8dd11 files · +128 −110Browse files

Unified · Split

11 files
  1. fs/smb/client/cifs_spnego.c +18 −29
  2. fs/smb/client/cifsfs.h +2 −2
  3. fs/smb/client/cifsglob.h +21 −0
  4. fs/smb/client/cifstransport.c +9 −10
  5. fs/smb/client/compress.c +21 −50
  6. fs/smb/client/connect.c +4 −5
  7. fs/smb/client/inode.c +32 −2
  8. fs/smb/client/smb2ops.c +12 −3
  9. fs/smb/client/smb2transport.c +1 −0
  10. fs/smb/client/smbdirect.c +5 −5
  11. fs/smb/client/transport.c +3 −4
fs/smb/client/cifs_spnego.c+18−29
@@ -124,55 +124,44 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo, · 123 unmodified lines
124124 dp = description;
125125 /* start with version and hostname portion of UNC string */
126126 spnego_key = ERR_PTR(-EINVAL);
127− sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
128− hostname);
129− dp = description + strlen(description);
127+ dp += sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
128+ hostname);
130129
131130 /* add the server address */
132131 if (server->dstaddr.ss_family == AF_INET)
133− sprintf(dp, "ip4=%pI4", &sa->sin_addr);
132+ dp += sprintf(dp, "ip4=%pI4", &sa->sin_addr);
134133 else if (server->dstaddr.ss_family == AF_INET6)
135− sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
134+ dp += sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
136135 else
137136 goto out;
138137
139− dp = description + strlen(description);
140−
141138 /* for now, only sec=krb5 and sec=mskrb5 and iakerb are valid */
142139 if (server->sec_kerberos)
143− sprintf(dp, ";sec=krb5");
140+ dp += sprintf(dp, ";sec=krb5");
144141 else if (server->sec_mskerberos)
145− sprintf(dp, ";sec=mskrb5");
142+ dp += sprintf(dp, ";sec=mskrb5");
146143 else if (server->sec_iakerb)
147− sprintf(dp, ";sec=iakerb");
144+ dp += sprintf(dp, ";sec=iakerb");
148145 else {
149146 cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
150− sprintf(dp, ";sec=krb5");
147+ dp += sprintf(dp, ";sec=krb5");
151148 }
152149
153− dp = description + strlen(description);
154− sprintf(dp, ";uid=0x%x",
155− from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
150+ dp += sprintf(dp, ";uid=0x%x",
151+ from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
156152
157− dp = description + strlen(description);
158− sprintf(dp, ";creduid=0x%x",
153+ dp += sprintf(dp, ";creduid=0x%x",
159154 from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
160155
161− if (sesInfo->user_name) {
162− dp = description + strlen(description);
163− sprintf(dp, ";user=%s", sesInfo->user_name);
164− }
156+ if (sesInfo->user_name)
157+ dp += sprintf(dp, ";user=%s", sesInfo->user_name);
165158
166− dp = description + strlen(description);
167− sprintf(dp, ";pid=0x%x", current->pid);
159+ dp += sprintf(dp, ";pid=0x%x", current->pid);
168160
169− if (sesInfo->upcall_target == UPTARGET_MOUNT) {
170− dp = description + strlen(description);
171− sprintf(dp, ";upcall_target=mount");
172− } else {
173− dp = description + strlen(description);
174− sprintf(dp, ";upcall_target=app");
175− }
161+ if (sesInfo->upcall_target == UPTARGET_MOUNT)
162+ dp += sprintf(dp, ";upcall_target=mount");
163+ else
164+ dp += sprintf(dp, ";upcall_target=app");
176165
177166 cifs_dbg(FYI, "key description = %s\n", description);
178167 saved_cred = override_creds(spnego_cred);
fs/smb/client/cifsfs.h+2−2
@@ -145,6 +145,6 @@ extern const struct export_operations cifs_export_ops; · 144 unmodified lines
145145 #endif /* CONFIG_CIFS_NFSD_EXPORT */
146146
147147 /* when changing internal version - update following two lines at same time */
148−#define SMB3_PRODUCT_BUILD 55
149−#define CIFS_VERSION "2.55"
148+#define SMB3_PRODUCT_BUILD 56
149+#define CIFS_VERSION "2.56"
150150 #endif /* _CIFSFS_H */
fs/smb/client/cifsglob.h+21−0
@@ -1732,6 +1732,7 @@ struct mid_q_entry { · 1731 unmodified lines
17321732 int mid_rc; /* rc for MID_RC */
17331733 __le16 command; /* smb command code */
17341734 unsigned int optype; /* operation type */
1735+ spinlock_t mid_lock;
17351736 bool wait_cancelled:1; /* Cancelled while waiting for response */
17361737 bool deleted_from_q:1; /* Whether Mid has been dequeued frem pending_mid_q */
17371738 bool large_buf:1; /* if valid response, is pointer to large buf */
@@ -2036,6 +2037,9 @@ require use of the stronger protocol */ · 298 unmodified lines
20362037 * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
20372038 * ->invalidHandle initiate_cifs_search
20382039 * ->oplock_break_cancelled
2040+ * mid_q_entry->mid_lock mid_q_entry->callback alloc_mid
2041+ * smb2_mid_entry_alloc
2042+ * (Any fields of mid_q_entry that will need protection)
20392043 ****************************************************************************/
20402044
20412045 #ifdef DECLARE_GLOBALS_HERE
@@ -2375,6 +2379,23 @@ static inline bool cifs_netbios_name(const char *name, size_t namelen) · 333 unmodified lines
23752379 return ret;
23762380 }
23772381
2382+/*
2383+ * Execute mid callback atomically - ensures callback runs exactly once
2384+ * and prevents sleeping in atomic context.
2385+ */
2386+static inline void mid_execute_callback(struct mid_q_entry *mid)
2387+{
2388+ void (*callback)(struct mid_q_entry *mid);
2389+
2390+ spin_lock(&mid->mid_lock);
2391+ callback = mid->callback;
2392+ mid->callback = NULL; /* Mark as executed, */
2393+ spin_unlock(&mid->mid_lock);
2394+
2395+ if (callback)
2396+ callback(mid);
2397+}
2398+
23782399 #define CIFS_REPARSE_SUPPORT(tcon) \
23792400 ((tcon)->posix_extensions || \
23802401 (le32_to_cpu((tcon)->fsAttrInfo.Attributes) & \
fs/smb/client/cifstransport.c+9−10
@@ -46,6 +46,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) · 45 unmodified lines
4646 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
4747 memset(temp, 0, sizeof(struct mid_q_entry));
4848 kref_init(&temp->refcount);
49+ spin_lock_init(&temp->mid_lock);
4950 temp->mid = get_mid(smb_buffer);
5051 temp->pid = current->pid;
5152 temp->command = cpu_to_le16(smb_buffer->Command);
@@ -345,16 +346,15 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 293 unmodified lines
345346 rc = wait_for_response(server, midQ);
346347 if (rc != 0) {
347348 send_cancel(server, &rqst, midQ);
348− spin_lock(&server->mid_queue_lock);
349− if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
350− midQ->mid_state == MID_RESPONSE_RECEIVED) {
349+ spin_lock(&midQ->mid_lock);
350+ if (midQ->callback) {
351351 /* no longer considered to be "in-flight" */
352352 midQ->callback = release_mid;
353− spin_unlock(&server->mid_queue_lock);
353+ spin_unlock(&midQ->mid_lock);
354354 add_credits(server, &credits, 0);
355355 return rc;
356356 }
357− spin_unlock(&server->mid_queue_lock);
357+ spin_unlock(&midQ->mid_lock);
358358 }
359359
360360 rc = cifs_sync_mid_result(midQ, server);
@@ -527,15 +527,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 166 unmodified lines
527527 rc = wait_for_response(server, midQ);
528528 if (rc) {
529529 send_cancel(server, &rqst, midQ);
530− spin_lock(&server->mid_queue_lock);
531− if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
532− midQ->mid_state == MID_RESPONSE_RECEIVED) {
530+ spin_lock(&midQ->mid_lock);
531+ if (midQ->callback) {
533532 /* no longer considered to be "in-flight" */
534533 midQ->callback = release_mid;
535− spin_unlock(&server->mid_queue_lock);
534+ spin_unlock(&midQ->mid_lock);
536535 return rc;
537536 }
538− spin_unlock(&server->mid_queue_lock);
537+ spin_unlock(&midQ->mid_lock);
539538 }
540539
541540 /* We got the response - restart system call. */
fs/smb/client/compress.c+21−50
@@ -155,58 +155,29 @@ static int cmp_bkt(const void *_a, const void *_b) · 154 unmodified lines
155155 }
156156
157157 /*
158− * TODO:
159− * Support other iter types, if required.
160− * Only ITER_XARRAY is supported for now.
158+ * Collect some 2K samples with 2K gaps between.
161159 */
162−static int collect_sample(const struct iov_iter *iter, ssize_t max, u8 *sample)
160+static int collect_sample(const struct iov_iter *source, ssize_t max, u8 *sample)
163161 {
164− struct folio *folios[16], *folio;
165− unsigned int nr, i, j, npages;
166− loff_t start = iter->xarray_start + iter->iov_offset;
167− pgoff_t last, index = start / PAGE_SIZE;
168− size_t len, off, foff;
169− void *p;
170− int s = 0;
171−
172− last = (start + max - 1) / PAGE_SIZE;
173− do {
174− nr = xa_extract(iter->xarray, (void **)folios, index, last, ARRAY_SIZE(folios),
175− XA_PRESENT);
176− if (nr == 0)
177− return -EIO;
178−
179− for (i = 0; i < nr; i++) {
180− folio = folios[i];
181− npages = folio_nr_pages(folio);
182− foff = start - folio_pos(folio);
183− off = foff % PAGE_SIZE;
184−
185− for (j = foff / PAGE_SIZE; j < npages; j++) {
186− size_t len2;
187−
188− len = min_t(size_t, max, PAGE_SIZE - off);
189− len2 = min_t(size_t, len, SZ_2K);
190−
191− p = kmap_local_page(folio_page(folio, j));
192− memcpy(&sample[s], p, len2);
193− kunmap_local(p);
194−
195− s += len2;
196−
197− if (len2 < SZ_2K || s >= max - SZ_2K)
198− return s;
199−
200− max -= len;
201− if (max <= 0)
202− return s;
203−
204− start += len;
205− off = 0;
206− index++;
207− }
208− }
209− } while (nr == ARRAY_SIZE(folios));
162+ struct iov_iter iter = *source;
163+ size_t s = 0;
164+
165+ while (iov_iter_count(&iter) >= SZ_2K) {
166+ size_t part = umin(umin(iov_iter_count(&iter), SZ_2K), max);
167+ size_t n;
168+
169+ n = copy_from_iter(sample + s, part, &iter);
170+ if (n != part)
171+ return -EFAULT;
172+
173+ s += n;
174+ max -= n;
175+
176+ if (iov_iter_count(&iter) < PAGE_SIZE - SZ_2K)
177+ break;
178+
179+ iov_iter_advance(&iter, SZ_2K);
180+ }
210181
211182 return s;
212183 }
fs/smb/client/connect.c+4−5
@@ -335,7 +335,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) · 334 unmodified lines
335335 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
336336 list_for_each_entry_safe(mid, nmid, &retry_list, qhead) {
337337 list_del_init(&mid->qhead);
338− mid->callback(mid);
338+ mid_execute_callback(mid);
339339 release_mid(mid);
340340 }
341341
@@ -919,7 +919,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) · 577 unmodified lines
919919 list_del_init(&mid->qhead);
920920 mid->mid_rc = mid_rc;
921921 mid->mid_state = MID_RC;
922− mid->callback(mid);
922+ mid_execute_callback(mid);
923923 release_mid(mid);
924924 }
925925
@@ -1117,7 +1117,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) · 191 unmodified lines
11171117 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
11181118 cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid);
11191119 list_del_init(&mid_entry->qhead);
1120− mid_entry->callback(mid_entry);
1120+ mid_execute_callback(mid_entry);
11211121 release_mid(mid_entry);
11221122 }
11231123 /* 1/8th of sec is more than enough time for them to exit */
@@ -1394,7 +1394,7 @@ next_pdu: · 270 unmodified lines
13941394 }
13951395
13961396 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1397− mids[i]->callback(mids[i]);
1397+ mid_execute_callback(mids[i]);
13981398
13991399 release_mid(mids[i]);
14001400 } else if (server->ops->is_oplock_break &&
@@ -4205,7 +4205,6 @@ retry: · 2804 unmodified lines
42054205 return 0;
42064206 }
42074207
4208− server->lstrp = jiffies;
42094208 server->tcpStatus = CifsInNegotiate;
42104209 server->neg_start = jiffies;
42114210 spin_unlock(&server->srv_lock);
fs/smb/client/inode.c+32−2
@@ -1943,15 +1943,24 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) · 1942 unmodified lines
19431943 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
19441944 struct tcon_link *tlink;
19451945 struct cifs_tcon *tcon;
1946+ __u32 dosattr = 0, origattr = 0;
19461947 struct TCP_Server_Info *server;
19471948 struct iattr *attrs = NULL;
1948− __u32 dosattr = 0, origattr = 0;
1949+ bool rehash = false;
19491950
19501951 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
19511952
19521953 if (unlikely(cifs_forced_shutdown(cifs_sb)))
19531954 return -EIO;
19541955
1956+ /* Unhash dentry in advance to prevent any concurrent opens */
1957+ spin_lock(&dentry->d_lock);
1958+ if (!d_unhashed(dentry)) {
1959+ __d_drop(dentry);
1960+ rehash = true;
1961+ }
1962+ spin_unlock(&dentry->d_lock);
1963+
19551964 tlink = cifs_sb_tlink(cifs_sb);
19561965 if (IS_ERR(tlink))
19571966 return PTR_ERR(tlink);
@@ -2003,7 +2012,8 @@ psx_del_no_retry: · 45 unmodified lines
20032012 cifs_drop_nlink(inode);
20042013 }
20052014 } else if (rc == -ENOENT) {
2006− d_drop(dentry);
2015+ if (simple_positive(dentry))
2016+ d_delete(dentry);
20072017 } else if (rc == -EBUSY) {
20082018 if (server->ops->rename_pending_delete) {
20092019 rc = server->ops->rename_pending_delete(full_path,
@@ -2056,6 +2066,8 @@ unlink_out: · 46 unmodified lines
20562066 kfree(attrs);
20572067 free_xid(xid);
20582068 cifs_put_tlink(tlink);
2069+ if (rehash)
2070+ d_rehash(dentry);
20592071 return rc;
20602072 }
20612073
@@ -2462,6 +2474,7 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 400 unmodified lines
24622474 struct cifs_sb_info *cifs_sb;
24632475 struct tcon_link *tlink;
24642476 struct cifs_tcon *tcon;
2477+ bool rehash = false;
24652478 unsigned int xid;
24662479 int rc, tmprc;
24672480 int retry_count = 0;
@@ -2477,6 +2490,17 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 9 unmodified lines
24772490 if (unlikely(cifs_forced_shutdown(cifs_sb)))
24782491 return -EIO;
24792492
2493+ /*
2494+ * Prevent any concurrent opens on the target by unhashing the dentry.
2495+ * VFS already unhashes the target when renaming directories.
2496+ */
2497+ if (d_is_positive(target_dentry) && !d_is_dir(target_dentry)) {
2498+ if (!d_unhashed(target_dentry)) {
2499+ d_drop(target_dentry);
2500+ rehash = true;
2501+ }
2502+ }
2503+
24802504 tlink = cifs_sb_tlink(cifs_sb);
24812505 if (IS_ERR(tlink))
24822506 return PTR_ERR(tlink);
@@ -2518,6 +2542,8 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 35 unmodified lines
25182542 }
25192543 }
25202544
2545+ if (!rc)
2546+ rehash = false;
25212547 /*
25222548 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
25232549 */
@@ -2576,12 +2602,16 @@ unlink_target: · 52 unmodified lines
25762602 goto cifs_rename_exit;
25772603 rc = cifs_do_rename(xid, source_dentry, from_name,
25782604 target_dentry, to_name);
2605+ if (!rc)
2606+ rehash = false;
25792607 }
25802608
25812609 /* force revalidate to go get info when needed */
25822610 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
25832611
25842612 cifs_rename_exit:
2613+ if (rehash)
2614+ d_rehash(target_dentry);
25852615 kfree(info_buf_source);
25862616 free_dentry_path(page2);
25872617 free_dentry_path(page1);
fs/smb/client/smb2ops.c+12−3
@@ -772,6 +772,13 @@ next_iface: · 771 unmodified lines
772772 bytes_left -= sizeof(*p);
773773 break;
774774 }
775+ /* Validate that Next doesn't point beyond the buffer */
776+ if (next > bytes_left) {
777+ cifs_dbg(VFS, "%s: invalid Next pointer %zu > %zd\n",
778+ __func__, next, bytes_left);
779+ rc = -EINVAL;
780+ goto out;
781+ }
775782 p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
776783 bytes_left -= next;
777784 }
@@ -783,7 +790,9 @@ next_iface: · 5 unmodified lines
783790 }
784791
785792 /* Azure rounds the buffer size up 8, to a 16 byte boundary */
786− if ((bytes_left > 8) || p->Next)
793+ if ((bytes_left > 8) ||
794+ (bytes_left >= offsetof(struct network_interface_info_ioctl_rsp, Next)
795+ + sizeof(p->Next) && p->Next))
787796 cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
788797
789798 ses->iface_last_update = jiffies;
@@ -4805,7 +4814,7 @@ static void smb2_decrypt_offload(struct work_struct *work) · 4015 unmodified lines
48054814 dw->server->ops->is_network_name_deleted(dw->buf,
48064815 dw->server);
48074816
4808− mid->callback(mid);
4817+ mid_execute_callback(mid);
48094818 } else {
48104819 spin_lock(&dw->server->srv_lock);
48114820 if (dw->server->tcpStatus == CifsNeedReconnect) {
@@ -4813,7 +4822,7 @@ static void smb2_decrypt_offload(struct work_struct *work) · 1 unmodified line
48134822 mid->mid_state = MID_RETRY_NEEDED;
48144823 spin_unlock(&dw->server->mid_queue_lock);
48154824 spin_unlock(&dw->server->srv_lock);
4816− mid->callback(mid);
4825+ mid_execute_callback(mid);
48174826 } else {
48184827 spin_lock(&dw->server->mid_queue_lock);
48194828 mid->mid_state = MID_REQUEST_SUBMITTED;
fs/smb/client/smb2transport.c+1−0
@@ -771,6 +771,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, · 770 unmodified lines
771771 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
772772 memset(temp, 0, sizeof(struct mid_q_entry));
773773 kref_init(&temp->refcount);
774+ spin_lock_init(&temp->mid_lock);
774775 temp->mid = le64_to_cpu(shdr->MessageId);
775776 temp->credits = credits > 0 ? credits : 1;
776777 temp->pid = current->pid;
fs/smb/client/smbdirect.c+5−5
@@ -1337,10 +1337,6 @@ void smbd_destroy(struct TCP_Server_Info *server) · 1336 unmodified lines
13371337 log_rdma_event(INFO, "cancelling idle timer\n");
13381338 cancel_delayed_work_sync(&info->idle_timer_work);
13391339
1340− log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
1341− wait_event(info->wait_send_pending,
1342− atomic_read(&info->send_pending) == 0);
1343−
13441340 /* It's not possible for upper layer to get to reassembly */
13451341 log_rdma_event(INFO, "drain the reassembly queue\n");
13461342 do {
@@ -1986,7 +1982,11 @@ int smbd_send(struct TCP_Server_Info *server, · 639 unmodified lines
19861982 */
19871983
19881984 wait_event(info->wait_send_pending,
1989− atomic_read(&info->send_pending) == 0);
1985+ atomic_read(&info->send_pending) == 0 ||
1986+ sc->status != SMBDIRECT_SOCKET_CONNECTED);
1987+
1988+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED && rc == 0)
1989+ rc = -EAGAIN;
19901990
19911991 return rc;
19921992 }
fs/smb/client/transport.c+3−4
@@ -1005,15 +1005,14 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 1004 unmodified lines
10051005 cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",
10061006 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
10071007 send_cancel(server, &rqst[i], midQ[i]);
1008− spin_lock(&server->mid_queue_lock);
1008+ spin_lock(&midQ[i]->mid_lock);
10091009 midQ[i]->wait_cancelled = true;
1010− if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED ||
1011− midQ[i]->mid_state == MID_RESPONSE_RECEIVED) {
1010+ if (midQ[i]->callback) {
10121011 midQ[i]->callback = cifs_cancelled_callback;
10131012 cancelled_mid[i] = true;
10141013 credits[i].value = 0;
10151014 }
1016− spin_unlock(&server->mid_queue_lock);
1015+ spin_unlock(&midQ[i]->mid_lock);
10171016 }
10181017 }
10191018