We need to add protocol specific calls to the oplock break thread.

Signed-off-by: Sachin Prabhu <[email protected]>
---
 fs/cifs/cifsglob.h  |  3 +--
 fs/cifs/cifsproto.h |  2 ++
 fs/cifs/file.c      | 53 +++--------------------------------------------------
 fs/cifs/smb1ops.c   | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2ops.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 106 insertions(+), 52 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index cf32f03..93a8762 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -402,6 +402,7 @@ struct smb_version_operations {
                        const struct cifs_fid *, u32 *);
        int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
                        int);
+       void (*oplock_break)(struct work_struct *);
 };
 
 struct smb_version_values {
@@ -1557,8 +1558,6 @@ GLOBAL_EXTERN spinlock_t uidsidlock;
 GLOBAL_EXTERN spinlock_t gidsidlock;
 #endif /* CONFIG_CIFS_ACL */
 
-void cifs_oplock_break(struct work_struct *work);
-
 extern const struct slow_work_ops cifs_oplock_break_ops;
 extern struct workqueue_struct *cifsiod_wq;
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index acc4ee8..e4d0add 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -130,6 +130,8 @@ extern void cifs_set_oplock_level(struct cifsInodeInfo 
*cinode, __u32 oplock);
 extern int cifs_unlock_range(struct cifsFileInfo *cfile,
                             struct file_lock *flock, const unsigned int xid);
 extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
+extern int cifs_push_locks(struct cifsFileInfo *cfile);
+bool cifs_has_mand_locks(struct cifsInodeInfo *cinode);
 
 extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid,
                                              struct file *file,
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 53c1507..998dec7 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -251,7 +251,7 @@ out:
        return rc;
 }
 
-static bool
+bool
 cifs_has_mand_locks(struct cifsInodeInfo *cinode)
 {
        struct cifs_fid_locks *cur;
@@ -304,7 +304,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        cfile->f_flags = file->f_flags;
        cfile->invalidHandle = false;
        cfile->tlink = cifs_get_tlink(tlink);
-       INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
+       INIT_WORK(&cfile->oplock_break, server->ops->oplock_break);
        mutex_init(&cfile->fh_mutex);
 
        cifs_sb_active(inode->i_sb);
@@ -1204,7 +1204,7 @@ err_out:
        goto out;
 }
 
-static int
+int
 cifs_push_locks(struct cifsFileInfo *cfile)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
@@ -3656,53 +3656,6 @@ static int cifs_launder_page(struct page *page)
        return rc;
 }
 
-void cifs_oplock_break(struct work_struct *work)
-{
-       struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
-                                                 oplock_break);
-       struct inode *inode = cfile->dentry->d_inode;
-       struct cifsInodeInfo *cinode = CIFS_I(inode);
-       struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-       int rc = 0;
-
-       if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
-                                               cifs_has_mand_locks(cinode)) {
-               cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand 
locks\n",
-                        inode);
-               cinode->oplock = 0;
-       }
-
-       if (inode && S_ISREG(inode->i_mode)) {
-               if (CIFS_CACHE_READ(cinode))
-                       break_lease(inode, O_RDONLY);
-               else
-                       break_lease(inode, O_WRONLY);
-               rc = filemap_fdatawrite(inode->i_mapping);
-               if (!CIFS_CACHE_READ(cinode)) {
-                       rc = filemap_fdatawait(inode->i_mapping);
-                       mapping_set_error(inode->i_mapping, rc);
-                       cifs_invalidate_mapping(inode);
-               }
-               cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
-       }
-
-       rc = cifs_push_locks(cfile);
-       if (rc)
-               cifs_dbg(VFS, "Push locks rc = %d\n", rc);
-
-       /*
-        * releasing stale oplock after recent reconnect of smb session using
-        * a now incorrect file handle is not a data integrity issue but do
-        * not bother sending an oplock release if session to server still is
-        * disconnected since oplock already released by the server
-        */
-       if (!cfile->oplock_break_cancelled) {
-               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
-                                                            cinode);
-               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
-       }
-}
-
 /*
  * The presence of cifs_direct_io() in the address space ops vector
  * allowes open() O_DIRECT flags which would have failed otherwise.
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 526fb89..346ee2a 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -23,6 +23,7 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifspdu.h"
+#include "cifsfs.h"
 
 /*
  * An NT cancel request header looks just like the original request except:
@@ -999,6 +1000,53 @@ cifs_is_read_op(__u32 oplock)
        return oplock == OPLOCK_READ;
 }
 
+static void cifs_oplock_break(struct work_struct *work)
+{
+       struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
+                                                 oplock_break);
+       struct inode *inode = cfile->dentry->d_inode;
+       struct cifsInodeInfo *cinode = CIFS_I(inode);
+       struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+       int rc = 0;
+
+       if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
+                                               cifs_has_mand_locks(cinode)) {
+               cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand 
locks\n",
+                        inode);
+               cinode->oplock = 0;
+       }
+
+       if (inode && S_ISREG(inode->i_mode)) {
+               if (CIFS_CACHE_READ(cinode))
+                       break_lease(inode, O_RDONLY);
+               else
+                       break_lease(inode, O_WRONLY);
+               rc = filemap_fdatawrite(inode->i_mapping);
+               if (!CIFS_CACHE_READ(cinode)) {
+                       rc = filemap_fdatawait(inode->i_mapping);
+                       mapping_set_error(inode->i_mapping, rc);
+                       cifs_invalidate_mapping(inode);
+               }
+               cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
+       }
+
+       rc = cifs_push_locks(cfile);
+       if (rc)
+               cifs_dbg(VFS, "Push locks rc = %d\n", rc);
+
+       /*
+        * releasing stale oplock after recent reconnect of smb session using
+        * a now incorrect file handle is not a data integrity issue but do
+        * not bother sending an oplock release if session to server still is
+        * disconnected since oplock already released by the server
+        */
+       if (!cfile->oplock_break_cancelled) {
+               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
+                                                            cinode);
+               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+       }
+}
+
 struct smb_version_operations smb1_operations = {
        .send_cancel = send_nt_cancel,
        .compare_fids = cifs_compare_fids,
@@ -1067,6 +1115,7 @@ struct smb_version_operations smb1_operations = {
        .query_mf_symlink = cifs_query_mf_symlink,
        .create_mf_symlink = cifs_create_mf_symlink,
        .is_read_op = cifs_is_read_op,
+       .oplock_break = cifs_oplock_break,
 #ifdef CONFIG_CIFS_XATTR
        .query_all_EAs = CIFSSMBQAllEAs,
        .set_EA = CIFSSMBSetEA,
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 192f51a..e7081cd 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -27,6 +27,7 @@
 #include "cifs_unicode.h"
 #include "smb2status.h"
 #include "smb2glob.h"
+#include "cifsfs.h"
 
 static int
 change_conf(struct TCP_Server_Info *server)
@@ -904,6 +905,53 @@ smb2_query_symlink(const unsigned int xid, struct 
cifs_tcon *tcon,
        return rc;
 }
 
+static void smb2_oplock_break(struct work_struct *work)
+{
+       struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
+                                                 oplock_break);
+       struct inode *inode = cfile->dentry->d_inode;
+       struct cifsInodeInfo *cinode = CIFS_I(inode);
+       struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+       int rc = 0;
+
+       if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
+                                               cifs_has_mand_locks(cinode)) {
+               cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand 
locks\n",
+                        inode);
+               cinode->oplock = 0;
+       }
+
+       if (inode && S_ISREG(inode->i_mode)) {
+               if (CIFS_CACHE_READ(cinode))
+                       break_lease(inode, O_RDONLY);
+               else
+                       break_lease(inode, O_WRONLY);
+               rc = filemap_fdatawrite(inode->i_mapping);
+               if (!CIFS_CACHE_READ(cinode)) {
+                       rc = filemap_fdatawait(inode->i_mapping);
+                       mapping_set_error(inode->i_mapping, rc);
+                       cifs_invalidate_mapping(inode);
+               }
+               cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
+       }
+
+       rc = cifs_push_locks(cfile);
+       if (rc)
+               cifs_dbg(VFS, "Push locks rc = %d\n", rc);
+
+       /*
+        * releasing stale oplock after recent reconnect of smb session using
+        * a now incorrect file handle is not a data integrity issue but do
+        * not bother sending an oplock release if session to server still is
+        * disconnected since oplock already released by the server
+        */
+       if (!cfile->oplock_break_cancelled) {
+               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
+                                                            cinode);
+               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+       }
+}
+
 static void
 smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
                      unsigned int epoch, bool *purge_cache)
@@ -1163,6 +1211,7 @@ struct smb_version_operations smb20_operations = {
        .create_lease_buf = smb2_create_lease_buf,
        .parse_lease_buf = smb2_parse_lease_buf,
        .clone_range = smb2_clone_range,
+       .oplock_break = smb2_oplock_break,
 };
 
 struct smb_version_operations smb21_operations = {
@@ -1237,6 +1286,7 @@ struct smb_version_operations smb21_operations = {
        .create_lease_buf = smb2_create_lease_buf,
        .parse_lease_buf = smb2_parse_lease_buf,
        .clone_range = smb2_clone_range,
+       .oplock_break = smb2_oplock_break,
 };
 
 struct smb_version_operations smb30_operations = {
@@ -1314,6 +1364,7 @@ struct smb_version_operations smb30_operations = {
        .parse_lease_buf = smb3_parse_lease_buf,
        .clone_range = smb2_clone_range,
        .validate_negotiate = smb3_validate_negotiate,
+       .oplock_break = smb2_oplock_break,
 };
 
 struct smb_version_values smb20_values = {
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to