[linux-cifs-client] [PATCH 4/5] cifs: take reference to inode for oplock breaks
Shirish Pargaonkar
shirishpargaonkar at gmail.com
Fri Aug 28 13:53:19 MDT 2009
On Tue, Aug 18, 2009 at 1:07 PM, Jeff Layton<jlayton at redhat.com> wrote:
> When an oplock break comes in, cifs needs to do things like write out
> dirty data for it. 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 <jlayton at redhat.com>
> ---
> fs/cifs/cifsfs.c | 26 ++++++++++----------------
> fs/cifs/misc.c | 4 +++-
> 2 files changed, 13 insertions(+), 17 deletions(-)
>
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index 2fcc722..647c5bc 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -993,13 +993,8 @@ static int cifs_oplock_thread(void *dummyarg)
> cFYI(1, ("found oplock item to write out"));
> tcon = oplock->tcon;
> inode = oplock->pinode;
> - /* 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);*/
> - cifsi = CIFS_I(inode);
> - if (S_ISREG(inode->i_mode)) {
> + if (inode && S_ISREG(inode->i_mode)) {
> + cifsi = CIFS_I(inode);
> #ifdef CONFIG_CIFS_EXPERIMENTAL
> if (cifsi->clientCanCacheAll == 0)
> break_lease(inode, FMODE_READ);
> @@ -1010,17 +1005,16 @@ static int cifs_oplock_thread(void *dummyarg)
> 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)
> - cifsi->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
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 7221af9..3bf3a52 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -502,6 +502,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,
> struct cifsInodeInfo *pCifsInode;
> struct cifsFileInfo *netfile;
> struct oplock_q_entry *oplock;
> + struct inode *inode;
>
> cFYI(1, ("Checking for oplock break or dnotify response"));
> if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
> @@ -600,6 +601,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,
> pCifsInode->clientCanCacheAll = false;
> if (pSMB->OplockLevel == 0)
> pCifsInode->clientCanCacheRead = false;
> + inode = igrab(netfile->pInode);
>
> if (!oplock) {
> cERROR(1, ("Unable to allocate "
> @@ -608,7 +610,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,
> }
>
> oplock->tcon = tcon;
> - oplock->pinode = netfile->pInode;
> + oplock->pinode = inode;
> oplock->netfid = netfile->netfid;
> spin_lock(&cifs_oplock_lock);
> list_add_tail(&oplock->qhead,
> --
> 1.6.0.6
>
> _______________________________________________
> linux-cifs-client mailing list
> linux-cifs-client at lists.samba.org
> https://lists.samba.org/mailman/listinfo/linux-cifs-client
>
Acked-by: Shirish Pargaonkar <shirishpargaonkar at gmail.com>
More information about the linux-cifs-client
mailing list