Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 231983
b: refs/heads/master
c: 2b84a36
h: refs/heads/master
i:
  231981: df64d3a
  231979: ecd9d5a
  231975: 1240a8b
  231967: 9101657
v: v3
  • Loading branch information
Jeff Layton authored and Steve French committed Jan 20, 2011
1 parent 6c22971 commit ceea30f
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 74dd92a881b62014ca3c754db6868e1f142f2fb9
refs/heads/master: 2b84a36c5529da136d28b268e75268892d09869c
8 changes: 4 additions & 4 deletions trunk/fs/cifs/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
cERROR(1, "State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->callback_data,
mid_entry->mid);
#ifdef CONFIG_CIFS_STATS2
cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld",
Expand Down Expand Up @@ -218,11 +218,11 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
mid_entry = list_entry(tmp3, struct mid_q_entry,
qhead);
seq_printf(m, "\tState: %d com: %d pid:"
" %d tsk: %p mid %d\n",
" %d cbdata: %p mid %d\n",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->callback_data,
mid_entry->mid);
}
spin_unlock(&GlobalMid_Lock);
Expand Down
15 changes: 14 additions & 1 deletion trunk/fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,18 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,

#endif

struct mid_q_entry;

/*
* This is the prototype for the mid callback function. When creating one,
* take special care to avoid deadlocks. Things to bear in mind:
*
* - it will be called by cifsd
* - the GlobalMid_Lock will be held
* - the mid will be removed from the pending_mid_q list
*/
typedef void (mid_callback_t)(struct mid_q_entry *mid);

/* one of these for every pending CIFS request to the server */
struct mid_q_entry {
struct list_head qhead; /* mids waiting on reply from this server */
Expand All @@ -519,7 +531,8 @@ struct mid_q_entry {
unsigned long when_sent; /* time when smb send finished */
unsigned long when_received; /* when demux complete (taken off wire) */
#endif
struct task_struct *tsk; /* task waiting for response */
mid_callback_t *callback; /* call completion callback */
void *callback_data; /* general purpose pointer for callback */
struct smb_hdr *resp_buf; /* response buffer */
int midState; /* wish this were enum but can not pass to wait_event */
__u8 command; /* smb command code */
Expand Down
53 changes: 25 additions & 28 deletions trunk/fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ cifs_reconnect(struct TCP_Server_Info *server)

/* before reconnecting the tcp session, mark the smb session (uid)
and the tid bad so they are not used until reconnected */
cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
spin_lock(&cifs_tcp_ses_lock);
list_for_each(tmp, &server->smb_ses_list) {
ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
Expand All @@ -163,7 +164,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
spin_unlock(&cifs_tcp_ses_lock);

/* do not want to be sending data on a socket we are freeing */
cFYI(1, "%s: tearing down socket", __func__);
mutex_lock(&server->srv_mutex);
if (server->ssocket) {
cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
Expand All @@ -180,22 +183,19 @@ cifs_reconnect(struct TCP_Server_Info *server)
kfree(server->session_key.response);
server->session_key.response = NULL;
server->session_key.len = 0;
mutex_unlock(&server->srv_mutex);

/* mark submitted MIDs for retry and issue callback */
cFYI(1, "%s: issuing mid callbacks", __func__);
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct
mid_q_entry,
qhead);
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
/* Mark other intransit requests as needing
retry so we do not immediately mark the
session bad again (ie after we reconnect
below) as they timeout too */
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if (mid_entry->midState == MID_REQUEST_SUBMITTED)
mid_entry->midState = MID_RETRY_NEEDED;
}
list_del_init(&mid_entry->qhead);
mid_entry->callback(mid_entry);
}
spin_unlock(&GlobalMid_Lock);
mutex_unlock(&server->srv_mutex);

while ((server->tcpStatus != CifsExiting) &&
(server->tcpStatus != CifsGood)) {
Expand All @@ -212,10 +212,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
if (server->tcpStatus != CifsExiting)
server->tcpStatus = CifsGood;
spin_unlock(&GlobalMid_Lock);
/* atomic_set(&server->inFlight,0);*/
wake_up(&server->response_q);
}
}

return rc;
}

Expand Down Expand Up @@ -345,7 +344,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
struct msghdr smb_msg;
struct kvec iov;
struct socket *csocket = server->ssocket;
struct list_head *tmp;
struct list_head *tmp, *tmp2;
struct task_struct *task_to_wake = NULL;
struct mid_q_entry *mid_entry;
char temp;
Expand Down Expand Up @@ -558,10 +557,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
continue;
}


task_to_wake = NULL;
mid_entry = NULL;
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);

if ((mid_entry->mid == smb_buffer->Mid) &&
Expand Down Expand Up @@ -602,8 +600,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
mid_entry->resp_buf = smb_buffer;
mid_entry->largeBuf = isLargeBuf;
multi_t2_fnd:
task_to_wake = mid_entry->tsk;
mid_entry->midState = MID_RESPONSE_RECEIVED;
list_del_init(&mid_entry->qhead);
mid_entry->callback(mid_entry);
#ifdef CONFIG_CIFS_STATS2
mid_entry->when_received = jiffies;
#endif
Expand All @@ -613,9 +612,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
server->lstrp = jiffies;
break;
}
mid_entry = NULL;
}
spin_unlock(&GlobalMid_Lock);
if (task_to_wake) {

if (mid_entry != NULL) {
/* Was previous buf put in mpx struct for multi-rsp? */
if (!isMultiRsp) {
/* smb buffer will be freed by user thread */
Expand All @@ -624,7 +625,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
else
smallbuf = NULL;
}
wake_up_process(task_to_wake);
} else if (!is_valid_oplock_break(smb_buffer, server) &&
!isMultiRsp) {
cERROR(1, "No task to wake, unknown frame received! "
Expand Down Expand Up @@ -678,15 +678,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)

if (!list_empty(&server->pending_mid_q)) {
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
cFYI(1, "Clearing Mid 0x%x - waking up ",
mid_entry->mid);
task_to_wake = mid_entry->tsk;
if (task_to_wake)
wake_up_process(task_to_wake);
}
cFYI(1, "Clearing Mid 0x%x - issuing callback",
mid_entry->mid);
list_del_init(&mid_entry->qhead);
mid_entry->callback(mid_entry);
}
spin_unlock(&GlobalMid_Lock);
/* 1/8th of sec is more than enough time for them to exit */
Expand Down
19 changes: 17 additions & 2 deletions trunk/fs/cifs/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@

extern mempool_t *cifs_mid_poolp;

static void
wake_up_task(struct mid_q_entry *mid)
{
wake_up_process(mid->callback_data);
}

static struct mid_q_entry *
AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
{
Expand All @@ -58,7 +64,13 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
/* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
/* when mid allocated can be before when sent */
temp->when_alloc = jiffies;
temp->tsk = current;

/*
* The default is for the mid to be synchronous, so the
* default callback just wakes up the current task.
*/
temp->callback = wake_up_task;
temp->callback_data = current;
}

atomic_inc(&midCount);
Expand Down Expand Up @@ -367,6 +379,9 @@ 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);
Expand All @@ -389,7 +404,7 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
}
spin_unlock(&GlobalMid_Lock);

delete_mid(mid);
DeleteMidQEntry(mid);
return rc;
}

Expand Down

0 comments on commit ceea30f

Please sign in to comment.