ACK - (although an extra oplock break on an incorrect file handle is not a big deal, slightly slower, and would be very rare - this approach is cleaner)<br><br><div class="gmail_quote">On Tue, Aug 18, 2009 at 1:07 PM, Jeff Layton <span dir="ltr"><<a href="mailto:jlayton@redhat.com">jlayton@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">cifs_oplock_thread has a check for pTcon->needs_reconnect and will skip<br>
the CIFSSMBLock call if it's set.<br>
<br>
Problem: what if the tcon has this set and then gets reconnected before<br>
the call goes out on the wire? The oplock release isn't needed and could<br>
be a bad thing at that point if the filehandle was reclaimed.<br>
<br>
Cancel oplock release calls during a reconnect event.<br>
<br>
Signed-off-by: Jeff Layton <<a href="mailto:jlayton@redhat.com">jlayton@redhat.com</a>><br>
---<br>
fs/cifs/cifsfs.c | 2 +-<br>
fs/cifs/cifsglob.h | 1 +<br>
fs/cifs/connect.c | 9 +++++++++<br>
fs/cifs/misc.c | 1 +<br>
4 files changed, 12 insertions(+), 1 deletions(-)<br>
<br>
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c<br>
index 647c5bc..92e06c1 100644<br>
--- a/fs/cifs/cifsfs.c<br>
+++ b/fs/cifs/cifsfs.c<br>
@@ -1024,7 +1024,7 @@ static int cifs_oplock_thread(void *dummyarg)<br>
* to server still is disconnected since oplock<br>
* already released by the server in that case<br>
*/<br>
- if (!tcon->need_reconnect) {<br>
+ if (!oplock->cancel) {<br>
rc = CIFSSMBLock(0, tcon, oplock->netfid,<br>
0 /* len */ , 0 /* offset */, 0,<br>
0, LOCKING_ANDX_OPLOCK_RELEASE,<br>
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h<br>
index 363dbcf..676c107 100644<br>
--- a/fs/cifs/cifsglob.h<br>
+++ b/fs/cifs/cifsglob.h<br>
@@ -448,6 +448,7 @@ struct oplock_q_entry {<br>
struct inode *pinode;<br>
struct cifsTconInfo *tcon;<br>
__u16 netfid;<br>
+ bool cancel;<br>
};<br>
<br>
/* for pending dnotify requests */<br>
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c<br>
index f49304d..b7b67e9 100644<br>
--- a/fs/cifs/connect.c<br>
+++ b/fs/cifs/connect.c<br>
@@ -121,6 +121,7 @@ cifs_reconnect(struct TCP_Server_Info *server)<br>
struct cifsSesInfo *ses;<br>
struct cifsTconInfo *tcon;<br>
struct mid_q_entry *mid_entry;<br>
+ struct oplock_q_entry *oplock;<br>
<br>
spin_lock(&GlobalMid_Lock);<br>
if (server->tcpStatus == CifsExiting) {<br>
@@ -137,6 +138,7 @@ cifs_reconnect(struct TCP_Server_Info *server)<br>
<br>
/* before reconnecting the tcp session, mark the smb session (uid)<br>
and the tid bad so they are not used until reconnected */<br>
+ spin_lock(&cifs_oplock_lock);<br>
read_lock(&cifs_tcp_ses_lock);<br>
list_for_each(tmp, &server->smb_ses_list) {<br>
ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);<br>
@@ -145,9 +147,16 @@ cifs_reconnect(struct TCP_Server_Info *server)<br>
list_for_each(tmp2, &ses->tcon_list) {<br>
tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);<br>
tcon->need_reconnect = true;<br>
+ list_for_each_entry(oplock, &cifs_oplock_list, qhead) {<br>
+ if (oplock->tcon == tcon)<br>
+ oplock->cancel = true;<br>
+ }<br>
}<br>
+<br>
}<br>
read_unlock(&cifs_tcp_ses_lock);<br>
+ spin_unlock(&cifs_oplock_lock);<br>
+<br>
/* do not want to be sending data on a socket we are freeing */<br>
mutex_lock(&server->srv_mutex);<br>
if (server->ssocket) {<br>
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c<br>
index 3bf3a52..4a2d297 100644<br>
--- a/fs/cifs/misc.c<br>
+++ b/fs/cifs/misc.c<br>
@@ -612,6 +612,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,<br>
oplock->tcon = tcon;<br>
oplock->pinode = inode;<br>
oplock->netfid = netfile->netfid;<br>
+ oplock->cancel = false;<br>
spin_lock(&cifs_oplock_lock);<br>
list_add_tail(&oplock->qhead,<br>
&cifs_oplock_list);<br>
<font color="#888888">--<br>
1.6.0.6<br>
<br>
</font></blockquote></div><br><br clear="all"><br>-- <br>Thanks,<br><br>Steve<br>