[linux-cifs-client] [PATCH 4/5] cifs: take reference to inode for oplock breaks

Steve French smfrench at gmail.com
Thu Aug 20 18:42:42 MDT 2009


Why don't we have a reference to this inode already?   We can't have an
oplock break unless the file is open, if the file is open then we have a
reference to the inode ...

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
>
>


-- 
Thanks,

Steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.samba.org/pipermail/linux-cifs-client/attachments/20090820/f4b96c08/attachment-0001.html>


More information about the linux-cifs-client mailing list