Whamcloud - gitweb
Branch HEAD
authorfanyong <fanyong>
Sat, 1 Aug 2009 04:55:51 +0000 (04:55 +0000)
committerfanyong <fanyong>
Sat, 1 Aug 2009 04:55:51 +0000 (04:55 +0000)
b=18902
i=alexey.lyashkov
i=vladimir.saveliev

1) do not reset statahead if conflict was found when opendir
2) do not release "sai" if someone else want to use it for race condition
3) patch from bug 20139
4) increase timeout value for racer killing threads to process client evicted case

There are race conditions for statahead:
1) just before statahead thread is triggered, the first item of the dentry many moved to other
directory, which will cause the statahead thread to be triggered for different directory, and then
cause the original "ls -l" thread which is waiting for the expected directory can not be waken up.
2) when some items are in statahead, such items maybe move to other directory, then the interpret
call maybe find different dentry under such changed directory, and left the original original "ls
-l" thread which is waiting for the expected directory can not be waken up.
3) lli_fid should be set just after vfs inode created on client-side, to prevent the same inode was
created multiple times by statahead thread and other stat thread.

lustre/include/obd.h
lustre/llite/dcache.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/namei.c
lustre/llite/statahead.c
lustre/tests/runracer

index 2c2c492..6807efd 100644 (file)
@@ -1257,6 +1257,7 @@ struct md_enqueue_info {
         struct lookup_intent    mi_it;
         struct lustre_handle    mi_lockh;
         struct dentry          *mi_dentry;
+        struct inode           *mi_dir;
         md_enqueue_cb_t         mi_cb;
         unsigned int            mi_generation;
         void                   *mi_cbdata;
index 2ef00a9..d685990 100644 (file)
@@ -362,7 +362,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
         struct ptlrpc_request *req = NULL;
         struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
         struct obd_export *exp;
-        struct inode *parent;
+        struct inode *parent = de->d_parent->d_inode;
         int rc, first = 0;
 
         ENTRY;
@@ -383,8 +383,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
                         RETURN(0);
 #endif
 
-                rc = ll_have_md_lock(de->d_parent->d_inode,
-                                     MDS_INODELOCK_UPDATE);
+                rc = ll_have_md_lock(parent, MDS_INODELOCK_UPDATE);
                 GOTO(out_sa, rc);
         }
 
@@ -406,7 +405,6 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
         OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
         ll_frob_intent(&it, &lookup_it);
         LASSERT(it);
-        parent = de->d_parent->d_inode;
 
         op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
                                      de->d_name.name, de->d_name.len,
@@ -464,7 +462,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
         }
 
         if (it->it_op == IT_GETATTR)
-                first = ll_statahead_enter(de->d_parent->d_inode, &de, 0);
+                first = ll_statahead_enter(parent, &de, 0);
 
 do_lock:
         it->it_create_mode &= ~current->fs->umask;
@@ -478,9 +476,9 @@ do_lock:
                 /* If there are too many locks on client-side, then some
                  * locks taken by statahead maybe dropped automatically
                  * before the real "revalidate" using them. */
-                ll_statahead_exit(de, req == NULL ? rc : 0);
+                ll_statahead_exit(parent, de, req == NULL ? rc : 0);
         else if (first == -EEXIST)
-                ll_statahead_mark(de);
+                ll_statahead_mark(parent, de);
 
         /* If req is NULL, then md_intent_lock only tried to do a lock match;
          * if all was well, it will return 1 if it found locks, 0 otherwise. */
@@ -613,11 +611,11 @@ out_sa:
          * statahead windows; for rc == 0 case, the "lookup" will be done later.
          */
         if (it && it->it_op == IT_GETATTR && rc == 1) {
-                first = ll_statahead_enter(de->d_parent->d_inode, &de, 0);
+                first = ll_statahead_enter(parent, &de, 0);
                 if (!first)
-                        ll_statahead_exit(de, 1);
+                        ll_statahead_exit(parent, de, 1);
                 else if (first == -EEXIST)
-                        ll_statahead_mark(de);
+                        ll_statahead_mark(parent, de);
         }
 
         return rc;
index 2116864..cd94c7d 100644 (file)
@@ -507,29 +507,12 @@ int ll_file_open(struct inode *inode, struct file *file)
 
         fd->fd_file = file;
         if (S_ISDIR(inode->i_mode)) {
-again:
                 spin_lock(&lli->lli_lock);
                 if (lli->lli_opendir_key == NULL && lli->lli_opendir_pid == 0) {
                         LASSERT(lli->lli_sai == NULL);
                         lli->lli_opendir_key = fd;
                         lli->lli_opendir_pid = cfs_curproc_pid();
                         opendir_set = 1;
-                } else if (unlikely(lli->lli_opendir_pid == cfs_curproc_pid() &&
-                                    lli->lli_opendir_key != NULL)) {
-                        /* Two cases for this:
-                         * (1) The same process open such directory many times.
-                         * (2) The old process opened the directory, and exited
-                         *     before its children processes. Then new process
-                         *     with the same pid opens such directory before the
-                         *     old process's children processes exit.
-                         * reset stat ahead for such cases. */
-                        spin_unlock(&lli->lli_lock);
-                        CDEBUG(D_INFO, "Conflict statahead for %.*s "DFID
-                               " reset it.\n", file->f_dentry->d_name.len,
-                               file->f_dentry->d_name.name,
-                               PFID(&lli->lli_fid));
-                        ll_stop_statahead(inode, lli->lli_opendir_key);
-                        goto again;
                 }
                 spin_unlock(&lli->lli_lock);
         }
index 6476098..50faf6e 100644 (file)
@@ -1078,15 +1078,20 @@ struct ll_statahead_info {
 };
 
 int do_statahead_enter(struct inode *dir, struct dentry **dentry, int lookup);
-void ll_statahead_exit(struct dentry *dentry, int result);
+void ll_statahead_exit(struct inode *dir, struct dentry *dentry, int result);
 void ll_stop_statahead(struct inode *inode, void *key);
 
 static inline
-void ll_statahead_mark(struct dentry *dentry)
+void ll_statahead_mark(struct inode *dir, struct dentry *dentry)
 {
-        struct ll_inode_info *lli = ll_i2info(dentry->d_parent->d_inode);
+        struct ll_inode_info  *lli;
         struct ll_dentry_data *ldd = ll_d2d(dentry);
 
+        /* dentry has been move to other directory, no need mark */
+        if (unlikely(dir != dentry->d_parent->d_inode))
+                return;
+
+        lli = ll_i2info(dir);
         /* not the same process, don't mark */
         if (lli->lli_opendir_pid != cfs_curproc_pid())
                 return;
@@ -1100,16 +1105,19 @@ void ll_statahead_mark(struct dentry *dentry)
 static inline
 int ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
 {
-        struct ll_sb_info        *sbi = ll_i2sbi(dir);
-        struct ll_inode_info     *lli = ll_i2info(dir);
-        struct ll_dentry_data    *ldd = ll_d2d(*dentryp);
+        struct ll_inode_info  *lli;
+        struct ll_dentry_data *ldd = ll_d2d(*dentryp);
 
-        if (sbi->ll_sa_max == 0)
+        if (unlikely(dir == NULL))
+                return -EAGAIN;
+
+        if (ll_i2sbi(dir)->ll_sa_max == 0)
                 return -ENOTSUPP;
 
+        lli = ll_i2info(dir);
         /* not the same process, don't statahead */
         if (lli->lli_opendir_pid != cfs_curproc_pid())
-                return -EBADF;
+                return -EAGAIN;
 
         /*
          * When "ls" a dentry, the system trigger more than once "revalidate" or
index c921b28..acf6593 100644 (file)
@@ -104,6 +104,15 @@ static int ll_test_inode(struct inode *inode, void *opaque)
 
 static int ll_set_inode(struct inode *inode, void *opaque)
 {
+        struct ll_inode_info *lli = ll_i2info(inode);
+        struct mdt_body *body = ((struct lustre_md *)opaque)->body;
+
+        if (unlikely(!(body->valid & OBD_MD_FLID))) {
+                CERROR("MDS body missing FID\n");
+                return -EINVAL;
+        }
+
+        lli->lli_fid = body->fid1;
         return 0;
 }
 
@@ -115,7 +124,6 @@ static int ll_set_inode(struct inode *inode, void *opaque)
 struct inode *ll_iget(struct super_block *sb, ino_t hash,
                       struct lustre_md *md)
 {
-        struct ll_inode_info *lli;
         struct inode         *inode;
         ENTRY;
 
@@ -123,7 +131,6 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash,
         inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md);
 
         if (inode) {
-                lli = ll_i2info(inode);
                 if (inode->i_state & I_NEW) {
                         int rc;
 
@@ -416,7 +423,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
 }
 
 int ll_lookup_it_finish(struct ptlrpc_request *request,
-                     struct lookup_intent *it, void *data)
+                        struct lookup_intent *it, void *data)
 {
         struct it_cb_data *icbd = data;
         struct dentry **de = icbd->icbd_childp;
@@ -535,7 +542,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         if (it->it_op == IT_GETATTR) {
                 first = ll_statahead_enter(parent, &dentry, 1);
                 if (first >= 0) {
-                        ll_statahead_exit(dentry, first);
+                        ll_statahead_exit(parent, dentry, first);
                         if (first == 1)
                                 RETURN(retval = dentry);
                 }
@@ -571,7 +578,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         }
 
         if (first == -EEXIST)
-                ll_statahead_mark(dentry);
+                ll_statahead_mark(parent, dentry);
 
         if ((it->it_op & IT_OPEN) && dentry->d_inode &&
             !S_ISREG(dentry->d_inode->i_mode) &&
index c853210..52ba057 100644 (file)
@@ -117,7 +117,7 @@ static inline int sa_is_stopped(struct ll_statahead_info *sai)
  */
 static inline int sa_low_hit(struct ll_statahead_info *sai)
 {
-        return ((sai->sai_hit < 4 * sai->sai_miss && sai->sai_hit > 7) ||
+        return ((sai->sai_hit > 7 && sai->sai_hit < 4 * sai->sai_miss) ||
                 (sai->sai_consecutive_miss > 8));
 }
 
@@ -130,18 +130,16 @@ static inline int sa_low_hit(struct ll_statahead_info *sai)
  */
 static void ll_sai_entry_cleanup(struct ll_sai_entry *entry, int free)
 {
-        struct ptlrpc_request  *req = entry->se_req;
         struct md_enqueue_info *minfo = entry->se_minfo;
+        struct ptlrpc_request  *req = entry->se_req;
         ENTRY;
 
         if (minfo) {
-                struct dentry        *dentry = minfo->mi_dentry;
-                struct lookup_intent *it = &minfo->mi_it;
-
                 entry->se_minfo = NULL;
-                ll_intent_release(it);
+                ll_intent_release(&minfo->mi_it);
+                dput(minfo->mi_dentry);
+                iput(minfo->mi_dir);
                 OBD_FREE_PTR(minfo);
-                dput(dentry);
         }
         if (req) {
                 entry->se_req = NULL;
@@ -194,9 +192,20 @@ static void ll_sai_put(struct ll_statahead_info *sai)
 
         LASSERT(inode != NULL);
         lli = ll_i2info(inode);
-        if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_lock)) {
+        LASSERT(lli->lli_sai == sai);
+
+        if (atomic_dec_and_test(&sai->sai_refcount)) {
                 struct ll_sai_entry *entry, *next;
 
+                spin_lock(&lli->lli_lock);
+                if (unlikely(atomic_read(&sai->sai_refcount) > 0)) {
+                        /* It is race case, the interpret callback just hold
+                         * a reference count */
+                        spin_unlock(&lli->lli_lock);
+                        EXIT;
+                        return;
+                }
+
                 LASSERT(lli->lli_opendir_key == NULL);
                 lli->lli_sai = NULL;
                 lli->lli_opendir_pid = 0;
@@ -225,8 +234,8 @@ static void ll_sai_put(struct ll_statahead_info *sai)
                         list_del_init(&entry->se_list);
                         ll_sai_entry_cleanup(entry, 1);
                 }
-                OBD_FREE_PTR(sai);
                 iput(inode);
+                OBD_FREE_PTR(sai);
         }
         EXIT;
 }
@@ -370,8 +379,8 @@ static int do_statahead_interpret(struct ll_statahead_info *sai)
         struct ll_sai_entry    *entry;
         struct ptlrpc_request  *req;
         struct md_enqueue_info *minfo;
-        struct dentry          *dentry;
         struct lookup_intent   *it;
+        struct dentry          *dentry;
         int                     rc = 0;
         struct mdt_body        *body;
         ENTRY;
@@ -384,6 +393,8 @@ static int do_statahead_interpret(struct ll_statahead_info *sai)
         spin_unlock(&lli->lli_lock);
 
         if (unlikely(entry->se_index < sai->sai_index_next)) {
+                CWARN("Found stale entry: [index %u] [next %u]\n",
+                      entry->se_index, sai->sai_index_next);
                 ll_sai_entry_cleanup(entry, 1);
                 RETURN(0);
         }
@@ -393,8 +404,8 @@ static int do_statahead_interpret(struct ll_statahead_info *sai)
 
         req = entry->se_req;
         minfo = entry->se_minfo;
-        dentry = minfo->mi_dentry;
         it = &minfo->mi_it;
+        dentry = minfo->mi_dentry;
 
         body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
         if (body == NULL)
@@ -406,7 +417,7 @@ static int do_statahead_interpret(struct ll_statahead_info *sai)
                  */
                 struct dentry    *save = dentry;
                 struct it_cb_data icbd = {
-                        .icbd_parent   = dentry->d_parent->d_inode,
+                        .icbd_parent   = minfo->mi_dir,
                         .icbd_childp   = &dentry
                 };
 
@@ -473,9 +484,9 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
                                   struct md_enqueue_info *minfo,
                                   int rc)
 {
-        struct dentry            *dentry = minfo->mi_dentry;
         struct lookup_intent     *it = &minfo->mi_it;
-        struct inode             *dir = dentry->d_parent->d_inode;
+        struct dentry            *dentry = minfo->mi_dentry;
+        struct inode             *dir = minfo->mi_dir;
         struct ll_inode_info     *lli = ll_i2info(dir);
         struct ll_statahead_info *sai;
         struct ll_sai_entry      *entry;
@@ -490,13 +501,11 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
                 spin_unlock(&lli->lli_lock);
                 ll_intent_release(it);
                 dput(dentry);
+                iput(dir);
                 OBD_FREE_PTR(minfo);
                 RETURN(-ESTALE);
         } else {
                 sai = ll_sai_get(lli->lli_sai);
-                if (rc || dir == NULL)
-                        rc = -ESTALE;
-
                 entry = ll_sai_entry_set(sai,
                                          (unsigned int)(long)minfo->mi_cbdata,
                                          rc ? SA_ENTRY_UNSTATED :
@@ -523,6 +532,7 @@ static void sa_args_fini(struct md_enqueue_info *minfo,
                          struct ldlm_enqueue_info *einfo)
 {
         LASSERT(minfo && einfo);
+        iput(minfo->mi_dir);
         capa_put(minfo->mi_data.op_capa1);
         capa_put(minfo->mi_data.op_capa2);
         OBD_FREE_PTR(minfo);
@@ -569,6 +579,7 @@ static int sa_args_init(struct inode *dir, struct dentry *dentry,
 
         minfo->mi_it.it_op = IT_GETATTR;
         minfo->mi_dentry = dentry;
+        minfo->mi_dir = igrab(dir);
         minfo->mi_cb = ll_statahead_interpret;
         minfo->mi_generation = lli->lli_sai->sai_generation;
         minfo->mi_cbdata = (void *)(long)lli->lli_sai->sai_index;
@@ -620,10 +631,9 @@ static int do_sa_lookup(struct inode *dir, struct dentry *dentry)
  * \retval      0 -- will send stat-ahead request
  * \retval others -- prepare stat-ahead request failed
  */
-static int do_sa_revalidate(struct dentry *dentry)
+static int do_sa_revalidate(struct inode *dir, struct dentry *dentry)
 {
         struct inode             *inode = dentry->d_inode;
-        struct inode             *dir = dentry->d_parent->d_inode;
         struct lookup_intent      it = { .it_op = IT_GETATTR };
         struct md_enqueue_info   *minfo;
         struct ldlm_enqueue_info *einfo;
@@ -707,7 +717,7 @@ static int ll_statahead_one(struct dentry *parent, const char* entry_name,
                         GOTO(out, rc = -ENOMEM);
                 }
         } else {
-                rc = do_sa_revalidate(dentry);
+                rc = do_sa_revalidate(dir, dentry);
                 if (rc)
                         dput(dentry);
         }
@@ -729,20 +739,14 @@ out:
         return rc;
 }
 
-struct ll_sa_thread_args {
-        struct dentry   *sta_parent;
-        pid_t            sta_pid;
-};
-
 static int ll_statahead_thread(void *arg)
 {
-        struct ll_sa_thread_args *sta = arg;
-        struct dentry            *parent = dget(sta->sta_parent);
+        struct dentry            *parent = (struct dentry *)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;
-        struct ptlrpc_thread     *thread;
+        struct ll_statahead_info *sai = ll_sai_get(lli->lli_sai);
+        struct ptlrpc_thread     *thread = &sai->sai_thread;
         struct page              *page;
         __u64                     pos = 0;
         int                       first = 0;
@@ -750,23 +754,12 @@ 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);
+                snprintf(pname, 15, "ll_sa_%u", lli->lli_opendir_pid);
                 cfs_daemonize(pname);
         }
 
-        thread = &sai->sai_thread;
         sbi->ll_sa_total++;
         spin_lock(&lli->lli_lock);
         thread->t_flags = SVC_RUNNING;
@@ -1071,17 +1064,21 @@ out:
  */
 int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
 {
-        struct ll_sb_info        *sbi = ll_i2sbi(dir);
-        struct ll_inode_info     *lli = ll_i2info(dir);
-        struct ll_statahead_info *sai = lli->lli_sai;
-        struct ll_sa_thread_args  sta;
+        struct ll_inode_info     *lli;
+        struct ll_statahead_info *sai;
+        struct dentry            *parent;
         struct l_wait_info        lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
         int                       rc = 0;
         ENTRY;
 
+        LASSERT(dir != NULL);
+        lli = ll_i2info(dir);
         LASSERT(lli->lli_opendir_pid == cfs_curproc_pid());
+        sai = lli->lli_sai;
 
         if (sai) {
+                struct ll_sb_info *sbi;
+
                 if (unlikely(sa_is_stopped(sai) &&
                              list_empty(&sai->sai_entries_stated)))
                         RETURN(-EBADFD);
@@ -1113,6 +1110,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
                         }
                 }
 
+                sbi = ll_i2sbi(dir);
                 if (ll_sai_entry_stated(sai)) {
                         sbi->ll_sa_cached++;
                 } else {
@@ -1145,26 +1143,15 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
                 RETURN(rc);
         }
 
-         /*
-          * I am the "lli_opendir_pid" owner, only me can set "lli_sai".
-          */ 
-        LASSERT(lli->lli_sai == NULL);
-
+        /* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */ 
         rc = is_first_dirent(dir, *dentryp);
-        if (rc == LS_NONE_FIRST_DE) {
-                /*
-                 * It is not "ls -{a}l" operation, no need statahead for it.
-                 */
-                spin_lock(&lli->lli_lock);
-                lli->lli_opendir_key = NULL;
-                lli->lli_opendir_pid = 0;
-                spin_unlock(&lli->lli_lock);
-                RETURN(-EBADF);
-        }
+        if (rc == LS_NONE_FIRST_DE)
+                /* It is not "ls -{a}l" operation, no need statahead for it. */
+                GOTO(out, rc = -EAGAIN);
 
         sai = ll_sai_alloc();
         if (sai == NULL)
-                RETURN(-ENOMEM);
+                GOTO(out, rc = -ENOMEM);
 
         sai->sai_ls_all = (rc == LS_FIRST_DOT_DE);
         sai->sai_inode = igrab(dir);
@@ -1172,18 +1159,29 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
                 CWARN("Do not start stat ahead on dying inode "DFID" .\n",
                       PFID(&lli->lli_fid));
                 OBD_FREE_PTR(sai);
-                RETURN(-ESTALE);
+                GOTO(out, rc = -ESTALE);
         }
 
-        LASSERT(sai->sai_inode == (*dentryp)->d_parent->d_inode);
+        /* get parent reference count here, and put it in ll_statahead_thread */
+        parent = dget((*dentryp)->d_parent);
+        if (unlikely(sai->sai_inode != parent->d_inode)) {
+                struct ll_inode_info *nlli = ll_i2info(parent->d_inode);
 
-        sta.sta_parent = (*dentryp)->d_parent;
-        sta.sta_pid    = cfs_curproc_pid();
+                CWARN("Race condition, someone changed %.*s just now: "
+                      "old parent "DFID", new parent "DFID" .\n",
+                      (*dentryp)->d_name.len, (*dentryp)->d_name.name,
+                      PFID(&lli->lli_fid), PFID(&nlli->lli_fid));
+                dput(parent);
+                iput(sai->sai_inode);
+                OBD_FREE_PTR(sai);
+                RETURN(-EAGAIN);
+        }
 
         lli->lli_sai = sai;
-        rc = cfs_kernel_thread(ll_statahead_thread, &sta, 0);
+        rc = cfs_kernel_thread(ll_statahead_thread, parent, 0);
         if (rc < 0) {
                 CERROR("can't start ll_sa thread, rc: %d\n", rc);
+                dput(parent);
                 lli->lli_opendir_key = NULL;
                 sai->sai_thread.t_flags = SVC_STOPPED;
                 ll_sai_put(sai);
@@ -1200,52 +1198,62 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
          * lookup, and -EEXIST also indicates that this is the first dirent.
          */
         RETURN(-EEXIST);
+
+out:
+        spin_lock(&lli->lli_lock);
+        lli->lli_opendir_key = NULL;
+        lli->lli_opendir_pid = 0;
+        spin_unlock(&lli->lli_lock);
+        return rc;
 }
 
 /**
  * update hit/miss count.
  */
-void ll_statahead_exit(struct dentry *dentry, int result)
+void ll_statahead_exit(struct inode *dir, 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);
-        struct ll_statahead_info *sai = lli->lli_sai;
+        struct ll_inode_info     *lli;
+        struct ll_statahead_info *sai;
+        struct ll_sb_info        *sbi;
         struct ll_dentry_data    *ldd = ll_d2d(dentry);
         ENTRY;
 
-        if (lli->lli_opendir_pid == cfs_curproc_pid() && sai) {
-                if (result >= 1) {
-                        sbi->ll_sa_hit++;
-                        sai->sai_hit++;
-                        sai->sai_consecutive_miss = 0;
-                        sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max);
-                } else {
-                        sbi->ll_sa_miss++;
-                        sai->sai_miss++;
-                        sai->sai_consecutive_miss++;
-                        if (sa_low_hit(sai) && sa_is_running(sai)) {
-                                sbi->ll_sa_wrong++;
-                                CDEBUG(D_READA, "statahead for dir %.*s hit "
-                                       "ratio too low: hit/miss %u/%u, "
-                                       "sent/replied %u/%u. stopping statahead "
-                                       "thread: pid %d\n",
-                                       parent->d_name.len, parent->d_name.name,
-                                       sai->sai_hit, sai->sai_miss,
-                                       sai->sai_sent, sai->sai_replied,
-                                       cfs_curproc_pid());
-                                spin_lock(&lli->lli_lock);
-                                if (!sa_is_stopped(sai))
-                                        sai->sai_thread.t_flags = SVC_STOPPING;
-                                spin_unlock(&lli->lli_lock);
-                        }
+        LASSERT(dir != NULL);
+        lli = ll_i2info(dir);
+        LASSERT(lli->lli_opendir_pid == cfs_curproc_pid());
+        sai = lli->lli_sai;
+        LASSERT(sai != NULL);
+        sbi = ll_i2sbi(dir);
+
+        if (result >= 1) {
+                sbi->ll_sa_hit++;
+                sai->sai_hit++;
+                sai->sai_consecutive_miss = 0;
+                sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max);
+        } else {
+                sbi->ll_sa_miss++;
+                sai->sai_miss++;
+                sai->sai_consecutive_miss++;
+                if (sa_low_hit(sai) && sa_is_running(sai)) {
+                        sbi->ll_sa_wrong++;
+                        CDEBUG(D_READA, "Statahead for dir "DFID" hit ratio "
+                               "too low: hit/miss %u/%u, sent/replied %u/%u, "
+                               "stopping statahead thread: pid %d\n",
+                               PFID(&lli->lli_fid), sai->sai_hit,
+                               sai->sai_miss, sai->sai_sent,
+                               sai->sai_replied, cfs_curproc_pid());
+                        spin_lock(&lli->lli_lock);
+                        if (!sa_is_stopped(sai))
+                                sai->sai_thread.t_flags = SVC_STOPPING;
+                        spin_unlock(&lli->lli_lock);
                 }
-
-                if (!sa_is_stopped(sai))
-                        cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);
-                ll_sai_entry_fini(sai);
-                if (likely(ldd != NULL))
-                        ldd->lld_sa_generation = sai->sai_generation;
         }
+
+        if (!sa_is_stopped(sai))
+                cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);
+        ll_sai_entry_fini(sai);
+        if (likely(ldd != NULL))
+                ldd->lld_sa_generation = sai->sai_generation;
+
         EXIT;
 }
index feca24b..b67a819 100644 (file)
@@ -37,6 +37,7 @@ do_racer_cleanup () {
        local INTERVAL=5
         local pids
        local rc=0
+       local TMAX
 
        local RDIR=$1
 
@@ -45,11 +46,19 @@ do_racer_cleanup () {
        # Check if all processes are killed
 
        local clients=$CLIENTS
+       local num_clients=$(get_node_count ${clients//,/ })
 
+        if at_is_enabled; then
+            TMAX=$(at_max_get mds)
+        else
+            TMAX=$(lctl get_param -n timeout)
+        fi
+
+       [ $TMAX -gt $((num_clients * 60)) ] || TMAX=$((num_clients * 60))
        # 1.Let chance to racer to kill all it's processes
        # FIXME: not sure how long does it take for racer to kill all processes
        # 80 is sometimes are enough for 2 clients; sometimes it takes more than 150 sec
-       while [ $WAIT -lt 90 ]; do
+       while [ $WAIT -lt $TMAX ]; do
                running=$(do_nodes $clients "ps uax | grep $RDIR " | egrep -v "(acceptance|grep|pdsh|bash)" || true)
                [ -z "$running" ] && rc=0 && break
                echo "clients $clients are still running the racer processes. Waited $WAIT secs"
@@ -68,8 +77,8 @@ do_racer_cleanup () {
                                echo "client $C still running racer processes after $WAIT seconds. Killing $pids"
                                do_node $C "ps uax | grep $RDIR " | egrep -v "(acceptance|grep|PATH)"
                                do_node $C kill -TERM $pids || true
-                               # let processes to be killed
-                               sleep 2
+                               # let processes to be killed, there maybe many threads to be killed, so give 20 sec gap
+                               sleep 20
        # 3. Check if the processes were killed
        # exit error if the processes still exist
                                for pid in $pids; do