From 8366fbd10d6644f87e9332d27d544b231e0e6966 Mon Sep 17 00:00:00 2001
From: fanyong <fanyong>
Date: Thu, 20 Nov 2008 05:51:00 +0000
Subject: [PATCH] Branch HEAD b=16947 i=h.huang i=yury.umanets

Hold lli_lock when access lli_sai to prevent NULL pointer.
---
 lustre/llite/file.c           |  4 ++--
 lustre/llite/llite_internal.h | 18 +++++++--------
 lustre/llite/statahead.c      | 41 +++++++++++++++++++++--------------
 3 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/lustre/llite/file.c b/lustre/llite/file.c
index 35c1d8713e..9850774e44 100644
--- a/lustre/llite/file.c
+++ b/lustre/llite/file.c
@@ -331,7 +331,7 @@ int ll_file_release(struct inode *inode, struct file *file)
          * Different processes can open the same dir, "ll_opendir_key" means:
          * it is me that should stop the statahead thread. */
         if (lli->lli_opendir_key == fd && lli->lli_opendir_pid != 0)
-                ll_stop_statahead(inode, fd);
+                ll_stop_statahead(inode, lli->lli_opendir_key);
 
         if (inode->i_sb->s_root == file->f_dentry) {
                 LUSTRE_FPRIVATE(file) = NULL;
@@ -690,7 +690,7 @@ out_och_free:
                 up(&lli->lli_och_sem);
 out_openerr:
                 if (opendir_set != 0)
-                        ll_stop_statahead(inode, fd);
+                        ll_stop_statahead(inode, lli->lli_opendir_key);
         }
 
         return rc;
diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h
index 22b5981250..a03e1bf82e 100644
--- a/lustre/llite/llite_internal.h
+++ b/lustre/llite/llite_internal.h
@@ -1069,23 +1069,23 @@ struct ll_statahead_info {
 };
 
 int do_statahead_enter(struct inode *dir, struct dentry **dentry, int lookup);
-int ll_statahead_exit(struct dentry *dentry, int result);
+void ll_statahead_exit(struct dentry *dentry, int result);
 void ll_stop_statahead(struct inode *inode, void *key);
 
 static inline
-int ll_statahead_mark(struct dentry *dentry)
+void ll_statahead_mark(struct dentry *dentry)
 {
         struct ll_inode_info *lli = ll_i2info(dentry->d_parent->d_inode);
-        struct ll_statahead_info *sai = lli->lli_sai;
         struct ll_dentry_data *ldd = ll_d2d(dentry);
-        int rc = 0;
 
-        if (likely(ldd != NULL))
-                ldd->lld_sa_generation = sai->sai_generation;
-        else
-                rc = -ENOMEM;
+        /* not the same process, don't mark */
+        if (lli->lli_opendir_pid != cfs_curproc_pid())
+                return;
 
-        return rc;
+        spin_lock(&lli->lli_lock);
+        if (likely(lli->lli_sai != NULL && ldd != NULL))
+                ldd->lld_sa_generation = lli->lli_sai->sai_generation;
+        spin_unlock(&lli->lli_lock);
 }
 
 static inline
diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c
index e5fff85a5c..e3416758b5 100644
--- a/lustre/llite/statahead.c
+++ b/lustre/llite/statahead.c
@@ -741,8 +741,8 @@ static int ll_statahead_thread(void *arg)
         struct inode             *dir = parent->d_inode;
         struct ll_inode_info     *lli = ll_i2info(dir);
         struct ll_sb_info        *sbi = ll_i2sbi(dir);
-        struct ll_statahead_info *sai = ll_sai_get(lli->lli_sai);
-        struct ptlrpc_thread     *thread = &sai->sai_thread;
+        struct ll_statahead_info *sai;
+        struct ptlrpc_thread     *thread;
         struct page              *page;
         __u64                     pos = 0;
         int                       first = 0;
@@ -750,12 +750,23 @@ static int ll_statahead_thread(void *arg)
         struct ll_dir_chain       chain;
         ENTRY;
 
+        spin_lock(&lli->lli_lock);
+        if (unlikely(lli->lli_sai == NULL)) {
+                spin_unlock(&lli->lli_lock);
+                dput(parent);
+                RETURN(-EAGAIN);
+        } else {
+                sai = ll_sai_get(lli->lli_sai);
+                spin_unlock(&lli->lli_lock);
+        }
+
         {
                 char pname[16];
                 snprintf(pname, 15, "ll_sa_%u", sta->sta_pid);
                 cfs_daemonize(pname);
         }
 
+        thread = &sai->sai_thread;
         sbi->ll_sa_total++;
         spin_lock(&lli->lli_lock);
         thread->t_flags = SVC_RUNNING;
@@ -1055,6 +1066,7 @@ out:
  * \retval 1       -- stat ahead thread process such dentry, for lookup, it hit
  * \retval -EEXIST -- stat ahead thread started, and this is the first dentry
  * \retval -EBADFD -- statahead thread exit and not dentry available
+ * \retval -EAGAIN -- try to stat by caller
  * \retval others  -- error
  */
 int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
@@ -1175,7 +1187,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
                 sai->sai_thread.t_flags = SVC_STOPPED;
                 ll_sai_put(sai);
                 LASSERT(lli->lli_sai == NULL);
-                RETURN(rc);
+                RETURN(-EAGAIN);
         }
 
         l_wait_event(sai->sai_thread.t_ctl_waitq, 
@@ -1192,20 +1204,16 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
 /**
  * update hit/miss count.
  */
-int ll_statahead_exit(struct dentry *dentry, int result)
+void ll_statahead_exit(struct dentry *dentry, int result)
 {
-        struct dentry         *parent = dentry->d_parent;
-        struct ll_inode_info  *lli = ll_i2info(parent->d_inode);
-        struct ll_sb_info     *sbi = ll_i2sbi(parent->d_inode);
-        int                    rc = 0;
+        struct dentry            *parent = dentry->d_parent;
+        struct ll_inode_info     *lli = ll_i2info(parent->d_inode);
+        struct ll_sb_info        *sbi = ll_i2sbi(parent->d_inode);
+        struct ll_statahead_info *sai = lli->lli_sai;
+        struct ll_dentry_data    *ldd = ll_d2d(dentry);
         ENTRY;
 
-        if (lli->lli_opendir_pid != cfs_curproc_pid())
-                RETURN(-EBADFD);
-
-        if (lli->lli_sai) {
-                struct ll_statahead_info *sai = lli->lli_sai;
-
+        if (lli->lli_opendir_pid == cfs_curproc_pid() && sai) {
                 if (result >= 1) {
                         sbi->ll_sa_hit++;
                         sai->sai_hit++;
@@ -1235,7 +1243,8 @@ int ll_statahead_exit(struct dentry *dentry, int result)
                 if (!sa_is_stopped(sai))
                         cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);
                 ll_sai_entry_fini(sai);
-                rc = ll_statahead_mark(dentry);
+                if (likely(ldd != NULL))
+                        ldd->lld_sa_generation = sai->sai_generation;
         }
-        RETURN(rc);
+        EXIT;
 }
-- 
GitLab