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">&lt;<a href="mailto:jlayton@redhat.com">jlayton@redhat.com</a>&gt;</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-&gt;needs_reconnect and will skip<br>
the CIFSSMBLock call if it&#39;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&#39;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 &lt;<a href="mailto:jlayton@redhat.com">jlayton@redhat.com</a>&gt;<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-&gt;need_reconnect) {<br>
+                       if (!oplock-&gt;cancel) {<br>
                                rc = CIFSSMBLock(0, tcon, oplock-&gt;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(&amp;GlobalMid_Lock);<br>
        if (server-&gt;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(&amp;cifs_oplock_lock);<br>
        read_lock(&amp;cifs_tcp_ses_lock);<br>
        list_for_each(tmp, &amp;server-&gt;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, &amp;ses-&gt;tcon_list) {<br>
                        tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);<br>
                        tcon-&gt;need_reconnect = true;<br>
+                       list_for_each_entry(oplock, &amp;cifs_oplock_list, qhead) {<br>
+                               if (oplock-&gt;tcon == tcon)<br>
+                                       oplock-&gt;cancel = true;<br>
+                       }<br>
                }<br>
+<br>
        }<br>
        read_unlock(&amp;cifs_tcp_ses_lock);<br>
+       spin_unlock(&amp;cifs_oplock_lock);<br>
+<br>
        /* do not want to be sending data on a socket we are freeing */<br>
        mutex_lock(&amp;server-&gt;srv_mutex);<br>
        if (server-&gt;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-&gt;tcon = tcon;<br>
                                oplock-&gt;pinode = inode;<br>
                                oplock-&gt;netfid = netfile-&gt;netfid;<br>
+                               oplock-&gt;cancel = false;<br>
                                spin_lock(&amp;cifs_oplock_lock);<br>
                                list_add_tail(&amp;oplock-&gt;qhead,<br>
                                              &amp;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>