Whamcloud - gitweb
Branch HEAD
authorfanyong <fanyong>
Thu, 20 Nov 2008 05:51:00 +0000 (05:51 +0000)
committerfanyong <fanyong>
Thu, 20 Nov 2008 05:51:00 +0000 (05:51 +0000)
b=16947
i=h.huang
i=yury.umanets

Hold lli_lock when access lli_sai to prevent NULL pointer.

lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/statahead.c

index 35c1d87..9850774 100644 (file)
@@ -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;
index 22b5981..a03e1bf 100644 (file)
@@ -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
index e5fff85..e341675 100644 (file)
@@ -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;
 }