[linux-cifs-client] [PATCH 3/5] cifs: clean up cifs_oplock_thread loop

Shirish Pargaonkar shirishpargaonkar at gmail.com
Sat Aug 29 07:04:13 MDT 2009


On Tue, Aug 18, 2009 at 1:07 PM, Jeff Layton<jlayton at redhat.com> wrote:
> Minor cleanups and optimizations mostly. Also fix it so that if a
> kthread_stop races in at the right time, it won't make the thread
> sleep unnecessarily for 39s.
>
> Signed-off-by: Jeff Layton <jlayton at redhat.com>
> ---
>  fs/cifs/cifsfs.c |   66 +++++++++++++++++++++++++++++------------------------
>  1 files changed, 36 insertions(+), 30 deletions(-)
>
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index 7ce8dcd..2fcc722 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -972,10 +972,10 @@ cifs_destroy_mids(void)
>
>  static int cifs_oplock_thread(void *dummyarg)
>  {
> -       struct oplock_q_entry *oplock_item;
> -       struct cifsTconInfo *pTcon;
> +       struct oplock_q_entry *oplock;
> +       struct cifsTconInfo *tcon;
>        struct inode *inode;
> -       __u16  netfid;
> +       struct cifsInodeInfo *cifsi;
>        int rc, waitrc = 0;
>
>        set_freezable();
> @@ -984,34 +984,30 @@ static int cifs_oplock_thread(void *dummyarg)
>                        continue;
>
>                spin_lock(&cifs_oplock_lock);
> -               if (list_empty(&cifs_oplock_list)) {
> +               while(!list_empty(&cifs_oplock_list)) {
> +                       oplock = list_entry(cifs_oplock_list.next,
> +                                           struct oplock_q_entry, qhead);
> +                       list_del(&oplock->qhead);
>                        spin_unlock(&cifs_oplock_lock);
> -                       set_current_state(TASK_INTERRUPTIBLE);
> -                       schedule_timeout(39*HZ);
> -               } else {
> -                       oplock_item = list_entry(cifs_oplock_list.next,
> -                                               struct oplock_q_entry, qhead);
> +
>                        cFYI(1, ("found oplock item to write out"));
> -                       pTcon = oplock_item->tcon;
> -                       inode = oplock_item->pinode;
> -                       netfid = oplock_item->netfid;
> -                       list_del(&oplock_item->qhead);
> -                       spin_unlock(&cifs_oplock_lock);
> -                       kmem_cache_free(cifs_oplock_cachep, oplock_item);
> +                       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)) {
>  #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);
>                                        invalidate_remote_inode(inode);
> @@ -1022,27 +1018,37 @@ static int cifs_oplock_thread(void *dummyarg)
>                                rc = 0;
>                        /* mutex_unlock(&inode->i_mutex);*/
>                        if (rc)
> -                               CIFS_I(inode)->write_behind_rc = rc;
> +                               cifsi->write_behind_rc = rc;
>                        cFYI(1, ("Oplock flush inode %p rc %d",
>                                inode, 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 in that case */
> -                       if (!pTcon->need_reconnect) {
> -                               rc = CIFSSMBLock(0, pTcon, netfid,
> +                       /*
> +                        * 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 in that case
> +                        */
> +                       if (!tcon->need_reconnect) {
> +                               rc = CIFSSMBLock(0, tcon, oplock->netfid,
>                                                0 /* len */ , 0 /* offset */, 0,
>                                                0, LOCKING_ANDX_OPLOCK_RELEASE,
>                                                false /* wait flag */);
>                                cFYI(1, ("Oplock release rc = %d", rc));
>                        }
> -                       cifs_put_tcon(pTcon);
> -                       set_current_state(TASK_INTERRUPTIBLE);
> -                       schedule_timeout(1);  /* yield in case q were corrupt */
> +                       cifs_put_tcon(tcon);
> +                       kmem_cache_free(cifs_oplock_cachep, oplock);
> +                       spin_lock(&cifs_oplock_lock);
> +               }
> +               spin_unlock(&cifs_oplock_lock);
> +               set_current_state(TASK_INTERRUPTIBLE);
> +               if (kthread_should_stop()) {
> +                       set_current_state(TASK_RUNNING);
> +                       break;
>                }
> +               /* FIXME: Why 39s here? This should be a named constant. */
> +               schedule_timeout(39*HZ);
>        } while (!kthread_should_stop());
>
>        return 0;
> --
> 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