cifs: clear server inode number flag while autodisabling
[sfrench/cifs-2.6.git] / fs / cifs / misc.c
index e079a9190ec4f6ffd5bbae2061f41bc5711a914d..d27d4ec6579bb41d296b4796b163cd6110ea7158 100644 (file)
@@ -32,7 +32,6 @@
 
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
-extern struct task_struct *oplockThread;
 
 /* The xid serves as a useful identifier for each incoming vfs request,
    in a similar way to the mid which is useful to track each sent smb,
@@ -500,6 +499,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
        struct cifsTconInfo *tcon;
        struct cifsInodeInfo *pCifsInode;
        struct cifsFileInfo *netfile;
+       int rc;
 
        cFYI(1, ("Checking for oplock break or dnotify response"));
        if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
@@ -562,30 +562,40 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
                                continue;
 
                        cifs_stats_inc(&tcon->num_oplock_brks);
-                       write_lock(&GlobalSMBSeslock);
+                       read_lock(&GlobalSMBSeslock);
                        list_for_each(tmp2, &tcon->openFileList) {
                                netfile = list_entry(tmp2, struct cifsFileInfo,
                                                     tlist);
                                if (pSMB->Fid != netfile->netfid)
                                        continue;
 
-                               write_unlock(&GlobalSMBSeslock);
-                               read_unlock(&cifs_tcp_ses_lock);
+                               /*
+                                * don't do anything if file is about to be
+                                * closed anyway.
+                                */
+                               if (netfile->closePend) {
+                                       read_unlock(&GlobalSMBSeslock);
+                                       read_unlock(&cifs_tcp_ses_lock);
+                                       return true;
+                               }
+
                                cFYI(1, ("file id match, oplock break"));
                                pCifsInode = CIFS_I(netfile->pInode);
                                pCifsInode->clientCanCacheAll = false;
                                if (pSMB->OplockLevel == 0)
                                        pCifsInode->clientCanCacheRead = false;
-                               pCifsInode->oplockPending = true;
-                               AllocOplockQEntry(netfile->pInode,
-                                                 netfile->netfid, tcon);
-                               cFYI(1, ("about to wake up oplock thread"));
-                               if (oplockThread)
-                                       wake_up_process(oplockThread);
-
+                               rc = slow_work_enqueue(&netfile->oplock_break);
+                               if (rc) {
+                                       cERROR(1, ("failed to enqueue oplock "
+                                                  "break: %d\n", rc));
+                               } else {
+                                       netfile->oplock_break_cancelled = false;
+                               }
+                               read_unlock(&GlobalSMBSeslock);
+                               read_unlock(&cifs_tcp_ses_lock);
                                return true;
                        }
-                       write_unlock(&GlobalSMBSeslock);
+                       read_unlock(&GlobalSMBSeslock);
                        read_unlock(&cifs_tcp_ses_lock);
                        cFYI(1, ("No matching file for oplock break"));
                        return true;
@@ -705,3 +715,17 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
 ctoUCS_out:
        return i;
 }
+
+void
+cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
+{
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+               cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
+               cERROR(1, ("Autodisabling the use of server inode numbers on "
+                          "%s. This server doesn't seem to support them "
+                          "properly. Hardlinks will not be recognized on this "
+                          "mount. Consider mounting with the \"noserverino\" "
+                          "option to silence this message.",
+                          cifs_sb->tcon->treeName));
+       }
+}