From patchwork Mon Aug 17 12:16:07 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 42019 Received: from lists.samba.org (fn.samba.org [216.83.154.106]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n7HCGMkX011577 for ; Mon, 17 Aug 2009 12:16:22 GMT Received: from fn.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id B0A60AD0AF; Mon, 17 Aug 2009 06:10:03 -0600 (MDT) X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on fn.samba.org X-Spam-Level: X-Spam-Status: No, score=-6.0 required=3.8 tests=AWL,BAYES_00, RCVD_IN_DNSWL_MED, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.2.5 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org Received: from mx2.redhat.com (mx2.redhat.com [66.187.237.31]) by lists.samba.org (Postfix) with ESMTP id BFF6CAD02A for ; Mon, 17 Aug 2009 06:09:52 -0600 (MDT) Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n7HCGA7j003954; Mon, 17 Aug 2009 08:16:10 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n7HCG9ML030135; Mon, 17 Aug 2009 08:16:10 -0400 Received: from localhost.localdomain (vpn-12-141.rdu.redhat.com [10.11.12.141]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n7HCG8pf015393; Mon, 17 Aug 2009 08:16:09 -0400 From: Jeff Layton To: smfrench@gmail.com Date: Mon, 17 Aug 2009 08:16:07 -0400 Message-Id: <1250511368-9812-4-git-send-email-jlayton@redhat.com> In-Reply-To: <1250511368-9812-1-git-send-email-jlayton@redhat.com> References: <1250511368-9812-1-git-send-email-jlayton@redhat.com> X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Cc: linux-cifs-client@lists.samba.org Subject: [linux-cifs-client] [PATCH 3/4] cifs: take reference to inode for oplock breaks X-BeenThere: linux-cifs-client@lists.samba.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: The Linux CIFS VFS client List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-cifs-client-bounces@lists.samba.org Errors-To: linux-cifs-client-bounces@lists.samba.org When an oplock break comes in, cifs needs to do things like writeback the inode. It doesn't hold a reference to that inode in this case however. Get an active reference to the inode when an oplock break comes in. If we don't get a reference, we still need to create an oplock queue entry so that the oplock release call gets done, but we'll want to skip writeback in that case. Signed-off-by: Jeff Layton --- fs/cifs/cifsfs.c | 33 +++++++++++++++------------------ fs/cifs/misc.c | 9 +++++---- fs/cifs/transport.c | 1 + 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ab4b373..4c724d5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -977,6 +977,7 @@ static int cifs_oplock_thread(void *dummyarg) { struct oplock_q_entry *oplock_item; struct cifsTconInfo *tcon; + struct cifsInodeInfo *cifsi; struct inode *inode; __u16 netfid; int rc, waitrc = 0; @@ -1004,33 +1005,29 @@ static int cifs_oplock_thread(void *dummyarg) list_del(&oplock_item->qhead); kmem_cache_free(cifs_oplock_cachep, oplock_item); mutex_unlock(&cifs_oplock_mutex); - /* can not grab inode sem here since it would - deadlock when oplock received on delete - since vfs_unlink holds the i_mutex across - the call */ - /* mutex_lock(&inode->i_mutex);*/ - if (S_ISREG(inode->i_mode)) { + + if (inode && S_ISREG(inode->i_mode)) { + cifsi = CIFS_I(inode); #ifdef CONFIG_CIFS_EXPERIMENTAL - if (CIFS_I(inode)->clientCanCacheAll == 0) + if (cifsi->clientCanCacheAll == 0) break_lease(inode, FMODE_READ); - else if (CIFS_I(inode)->clientCanCacheRead == 0) + else if (cifsi->clientCanCacheRead == 0) break_lease(inode, FMODE_WRITE); #endif rc = filemap_fdatawrite(inode->i_mapping); - if (CIFS_I(inode)->clientCanCacheRead == 0) { + if (cifsi->clientCanCacheRead == 0) { waitrc = filemap_fdatawait( inode->i_mapping); + if (rc == 0) + rc = waitrc; invalidate_remote_inode(inode); } - if (rc == 0) - rc = waitrc; - } else - rc = 0; - /* mutex_unlock(&inode->i_mutex);*/ - if (rc) - CIFS_I(inode)->write_behind_rc = rc; - cFYI(1, ("Oplock flush inode %p rc %d", - inode, rc)); + if (rc) + cifsi->write_behind_rc = rc; + cFYI(1, ("Oplock flush inode %p rc %d", + inode, rc)); + } + iput(inode); /* releasing stale oplock after recent reconnect of smb session using a now incorrect file diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index e079a91..5bdd81c 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -500,6 +500,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) struct cifsTconInfo *tcon; struct cifsInodeInfo *pCifsInode; struct cifsFileInfo *netfile; + struct inode *inode; cFYI(1, ("Checking for oplock break or dnotify response")); if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && @@ -569,16 +570,16 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) if (pSMB->Fid != netfile->netfid) continue; - write_unlock(&GlobalSMBSeslock); - read_unlock(&cifs_tcp_ses_lock); 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); + inode = igrab(netfile->pInode); + write_unlock(&GlobalSMBSeslock); + read_unlock(&cifs_tcp_ses_lock); + AllocOplockQEntry(inode, netfile->netfid, tcon); cFYI(1, ("about to wake up oplock thread")); if (oplockThread) wake_up_process(oplockThread); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 59f0e95..c52d27c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -133,6 +133,7 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) mutex_lock(&cifs_oplock_mutex); list_for_each_entry_safe(entry, next, &cifs_oplock_list, qhead) { if (entry->tcon && entry->tcon == tcon) { + iput(entry->inode); list_del(&entry->qhead); kmem_cache_free(cifs_oplock_cachep, entry); }