summaryrefslogtreecommitdiff
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-05-22 07:09:13 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-24 03:11:33 +0000
commit3c1105df699188a70f5c17dc0795affea388bca7 (patch)
treebfbcfaaae2fdfd16b2fcdb57710b9affbf183c49 /fs/cifs/transport.c
parent724d9f1cfba0cb16a7151333b501e8f7885450d8 (diff)
cifs: don't call mid_q_entry->callback under the Global_MidLock (try #5)
Minor revision to the last version of this patch -- the only difference is the fix to the cFYI statement in cifs_reconnect. Holding the spinlock while we call this function means that it can't sleep, which really limits what it can do. Taking it out from under the spinlock also means less contention for this global lock. Change the semantics such that the Global_MidLock is not held when the callback is called. To do this requires that we take extra care not to have sync_mid_result remove the mid from the list when the mid is in a state where that has already happened. This prevents list corruption when the mid is sitting on a private list for reconnect or when cifsd is coming down. Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c23
1 files changed, 8 insertions, 15 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 16bcc0725cee..d1998b6086ef 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -426,7 +426,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
}
static int
-sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
+cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
{
int rc = 0;
@@ -434,28 +434,21 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
mid->mid, mid->midState);
spin_lock(&GlobalMid_Lock);
- /* ensure that it's no longer on the pending_mid_q */
- list_del_init(&mid->qhead);
-
switch (mid->midState) {
case MID_RESPONSE_RECEIVED:
spin_unlock(&GlobalMid_Lock);
return rc;
- case MID_REQUEST_SUBMITTED:
- /* socket is going down, reject all calls */
- if (server->tcpStatus == CifsExiting) {
- cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
- __func__, mid->mid, mid->command, mid->midState);
- rc = -EHOSTDOWN;
- break;
- }
case MID_RETRY_NEEDED:
rc = -EAGAIN;
break;
case MID_RESPONSE_MALFORMED:
rc = -EIO;
break;
+ case MID_SHUTDOWN:
+ rc = -EHOSTDOWN;
+ break;
default:
+ list_del_init(&mid->qhead);
cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
mid->mid, mid->midState);
rc = -EIO;
@@ -618,7 +611,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
cifs_small_buf_release(in_buf);
- rc = sync_mid_result(midQ, ses->server);
+ rc = cifs_sync_mid_result(midQ, ses->server);
if (rc != 0) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
@@ -739,7 +732,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
spin_unlock(&GlobalMid_Lock);
}
- rc = sync_mid_result(midQ, ses->server);
+ rc = cifs_sync_mid_result(midQ, ses->server);
if (rc != 0) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
@@ -914,7 +907,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
rstart = 1;
}
- rc = sync_mid_result(midQ, ses->server);
+ rc = cifs_sync_mid_result(midQ, ses->server);
if (rc != 0)
return rc;