diff options
| author | Sachin Prabhu <sprabhu@redhat.com> | 2012-07-11 07:28:05 -0400 |
|---|---|---|
| committer | Steve French <smfrench@gmail.com> | 2012-07-17 00:57:02 -0400 |
| commit | ffc61ccbb96809df8d97ed609ac86b509eaf9056 (patch) | |
| tree | 6f97d985c640d7881aeb6ae888359e1c73213a1a | |
| parent | 055c9fa8874fa7261eec7a268366565db84af474 (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>
| -rw-r--r-- | fs/cifs/transport.c | 26 |
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; | ||
| 420 | out_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); |
