atomic_inc(&sbi->ll_agl_total);
        spin_lock(&plli->lli_agl_lock);
        sai->sai_agl_valid = 1;
-       thread_set_flags(thread, SVC_RUNNING);
+       if (thread_is_init(thread))
+               /* If someone else has changed the thread state
+                * (e.g. already changed to SVC_STOPPING), we can't just
+                * blindly overwrite that setting. */
+               thread_set_flags(thread, SVC_RUNNING);
        spin_unlock(&plli->lli_agl_lock);
        wake_up(&thread->t_ctl_waitq);
 
 
        atomic_inc(&sbi->ll_sa_total);
        spin_lock(&plli->lli_sa_lock);
-       thread_set_flags(thread, SVC_RUNNING);
+       if (thread_is_init(thread))
+               /* If someone else has changed the thread state
+                * (e.g. already changed to SVC_STOPPING), we can't just
+                * blindly overwrite that setting. */
+               thread_set_flags(thread, SVC_RUNNING);
        spin_unlock(&plli->lli_sa_lock);
        wake_up(&thread->t_ctl_waitq);
 
        CDEBUG(D_READA, "start statahead thread: [pid %d] [parent %.*s]\n",
               current_pid(), parent->d_name.len, parent->d_name.name);
 
+       /* The sai buffer already has one reference taken at allocation time,
+        * but as soon as we expose the sai by attaching it to the lli that
+        * default reference can be dropped by another thread calling
+        * ll_stop_statahead. We need to take a local reference to protect
+        * the sai buffer while we intend to access it. */
+       ll_sai_get(sai);
        lli->lli_sai = sai;
 
        plli = ll_i2info(parent->d_inode);
                lli->lli_opendir_key = NULL;
                thread_set_flags(thread, SVC_STOPPED);
                thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED);
+               /* Drop both our own local reference and the default
+                * reference from allocation time. */
+               ll_sai_put(sai);
                ll_sai_put(sai);
                LASSERT(lli->lli_sai == NULL);
                return -EAGAIN;
        l_wait_event(thread->t_ctl_waitq,
                     thread_is_running(thread) || thread_is_stopped(thread),
                     &lwi);
+       ll_sai_put(sai);
 
        /*
         * We don't stat-ahead for the first dirent since we are already in