aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2012-07-11 07:28:05 -0400
committerSteve French <smfrench@gmail.com>2012-07-17 00:57:02 -0400
commitffc61ccbb96809df8d97ed609ac86b509eaf9056 (patch)
tree6f97d985c640d7881aeb6ae888359e1c73213a1a /fs/cifs/transport.c
parent055c9fa8874fa7261eec7a268366565db84af474 (diff)
Initialise mid_q_entry before putting it on the pending queue
A user reported a crash in cifs_demultiplex_thread() caused by an incorrectly set mid_q_entry->callback() function. It appears that the callback assignment made in cifs_call_async() was not flushed back to memory suggesting that a memory barrier was required here. Changing the code to make sure that the mid_q_entry structure was completely initialised before it was added to the pending queue fixes the problem. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 3097ee58fd7d..f25d4ea14be4 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -365,16 +365,14 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
365 if (mid == NULL) 365 if (mid == NULL)
366 return -ENOMEM; 366 return -ENOMEM;
367 367
368 /* put it on the pending_mid_q */
369 spin_lock(&GlobalMid_Lock);
370 list_add_tail(&mid->qhead, &server->pending_mid_q);
371 spin_unlock(&GlobalMid_Lock);
372
373 rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); 368 rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
374 if (rc) 369 if (rc) {
375 delete_mid(mid); 370 DeleteMidQEntry(mid);
371 return rc;
372 }
373
376 *ret_mid = mid; 374 *ret_mid = mid;
377 return rc; 375 return 0;
378} 376}
379 377
380/* 378/*
@@ -407,17 +405,21 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
407 mid->callback_data = cbdata; 405 mid->callback_data = cbdata;
408 mid->mid_state = MID_REQUEST_SUBMITTED; 406 mid->mid_state = MID_REQUEST_SUBMITTED;
409 407
408 /* put it on the pending_mid_q */
409 spin_lock(&GlobalMid_Lock);
410 list_add_tail(&mid->qhead, &server->pending_mid_q);
411 spin_unlock(&GlobalMid_Lock);
412
413
410 cifs_in_send_inc(server); 414 cifs_in_send_inc(server);
411 rc = smb_sendv(server, iov, nvec); 415 rc = smb_sendv(server, iov, nvec);
412 cifs_in_send_dec(server); 416 cifs_in_send_dec(server);
413 cifs_save_when_sent(mid); 417 cifs_save_when_sent(mid);
414 mutex_unlock(&server->srv_mutex); 418 mutex_unlock(&server->srv_mutex);
415 419
416 if (rc) 420 if (rc == 0)
417 goto out_err; 421 return 0;
418 422
419 return rc;
420out_err:
421 delete_mid(mid); 423 delete_mid(mid);
422 add_credits(server, 1); 424 add_credits(server, 1);
423 wake_up(&server->request_q); 425 wake_up(&server->request_q);