From patchwork Fri Mar 7 13:29:19 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sachin Prabhu X-Patchwork-Id: 3791451 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id F1DED9F369 for ; Fri, 7 Mar 2014 13:34:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 212C2202B4 for ; Fri, 7 Mar 2014 13:34:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7294F202BE for ; Fri, 7 Mar 2014 13:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752027AbaCGNei (ORCPT ); Fri, 7 Mar 2014 08:34:38 -0500 Received: from mx1.redhat.com ([209.132.183.28]:2748 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752075AbaCGNeh (ORCPT ); Fri, 7 Mar 2014 08:34:37 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s27DYati007266 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 7 Mar 2014 08:34:36 -0500 Received: from sachin-laptop.redhat.com (vpn1-7-59.ams2.redhat.com [10.36.7.59]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s27DYWsW010587 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 7 Mar 2014 08:34:35 -0500 From: Sachin Prabhu To: linux-cifs Subject: [PATCH 1/2] Add oplock_break to smb_version_operations Date: Fri, 7 Mar 2014 13:29:19 +0000 Message-Id: <1394198960-7585-2-git-send-email-sprabhu@redhat.com> In-Reply-To: <1394198960-7585-1-git-send-email-sprabhu@redhat.com> References: <1394198960-7585-1-git-send-email-sprabhu@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We need to add protocol specific calls to the oplock break thread. Signed-off-by: Sachin Prabhu --- 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 = {