Whamcloud - gitweb
LU-6142 llite: remove ll_dir_chain
[fs/lustre-release.git] / lustre / llite / statahead.c
index e20dd4d..6745d08 100644 (file)
@@ -132,7 +132,7 @@ sa_unhash(struct ll_statahead_info *sai, struct sa_entry *entry)
 static inline int agl_should_run(struct ll_statahead_info *sai,
                                 struct inode *inode)
 {
-       return (inode && S_ISREG(inode->i_mode) && sai->sai_agl_valid);
+       return inode && S_ISREG(inode->i_mode) && sai->sai_agl_task;
 }
 
 static inline struct ll_inode_info *
@@ -432,7 +432,6 @@ static void ll_agl_add(struct ll_statahead_info *sai,
 {
        struct ll_inode_info *child  = ll_i2info(inode);
        struct ll_inode_info *parent = ll_i2info(sai->sai_dentry->d_inode);
-       int                   added  = 0;
 
        spin_lock(&child->lli_agl_lock);
        if (child->lli_agl_index == 0) {
@@ -441,13 +440,15 @@ static void ll_agl_add(struct ll_statahead_info *sai,
 
                LASSERT(list_empty(&child->lli_agl_list));
 
-               igrab(inode);
                spin_lock(&parent->lli_agl_lock);
-               if (agl_list_empty(sai))
-                       added = 1;
-               list_add_tail(&child->lli_agl_list, &sai->sai_agls);
-               if (added && sai->sai_agl_task)
-                       wake_up_process(sai->sai_agl_task);
+               /* Re-check under the lock */
+               if (agl_should_run(sai, inode)) {
+                       if (agl_list_empty(sai))
+                               wake_up_process(sai->sai_agl_task);
+                       igrab(inode);
+                       list_add_tail(&child->lli_agl_list, &sai->sai_agls);
+               } else
+                       child->lli_agl_index = 0;
                spin_unlock(&parent->lli_agl_lock);
        } else {
                spin_unlock(&child->lli_agl_lock);
@@ -901,10 +902,6 @@ static void sa_statahead(struct dentry *parent, const char *name, int len,
        EXIT;
 }
 
-#ifndef TASK_IDLE
-#define TASK_IDLE TASK_INTERRUPTIBLE
-#endif
-
 /* async glimpse (agl) thread main function */
 static int ll_agl_thread(void *arg)
 {
@@ -961,7 +958,6 @@ static void ll_stop_agl(struct ll_statahead_info *sai)
        kthread_stop(agl_task);
 
        spin_lock(&plli->lli_agl_lock);
-       sai->sai_agl_valid = 0;
        while (!agl_list_empty(sai)) {
                clli = agl_first_entry(sai);
                list_del_init(&clli->lli_agl_list);
@@ -979,8 +975,9 @@ static void ll_stop_agl(struct ll_statahead_info *sai)
 /* start agl thread */
 static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
 {
-       struct ll_inode_info  *plli;
-       struct task_struct    *task;
+       int node = cfs_cpt_spread_node(cfs_cpt_tab, CFS_CPT_ANY);
+       struct ll_inode_info *plli;
+       struct task_struct *task;
 
        ENTRY;
 
@@ -988,14 +985,13 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
               sai, parent);
 
        plli = ll_i2info(parent->d_inode);
-       task = kthread_create(ll_agl_thread, parent,
-                             "ll_agl_%u", plli->lli_opendir_pid);
+       task = kthread_create_on_node(ll_agl_thread, parent, node, "ll_agl_%d",
+                                     plli->lli_opendir_pid);
        if (IS_ERR(task)) {
                CERROR("can't start ll_agl thread, rc: %ld\n", PTR_ERR(task));
                RETURN_EXIT;
        }
        sai->sai_agl_task = task;
-       sai->sai_agl_valid = 1;
        atomic_inc(&ll_i2sbi(d_inode(parent))->ll_agl_total);
        /* Get an extra reference that the thread holds */
        ll_sai_get(d_inode(parent));
@@ -1015,7 +1011,6 @@ static int ll_statahead_thread(void *arg)
        struct ll_statahead_info *sai = lli->lli_sai;
        int first = 0;
        struct md_op_data *op_data;
-       struct ll_dir_chain chain;
        struct page *page = NULL;
        __u64 pos = 0;
        int rc = 0;
@@ -1029,7 +1024,6 @@ static int ll_statahead_thread(void *arg)
        if (!op_data)
                GOTO(out, rc = -ENOMEM);
 
-       ll_dir_chain_init(&chain);
        while (pos != MDS_DIR_END_OFF && sai->sai_task) {
                struct lu_dirpage *dp;
                struct lu_dirent  *ent;
@@ -1042,7 +1036,7 @@ static int ll_statahead_thread(void *arg)
                }
 
                sai->sai_in_readpage = 1;
-               page = ll_get_dir_page(dir, op_data, pos, &chain);
+               page = ll_get_dir_page(dir, op_data, pos);
                ll_unlock_md_op_lsm(op_data);
                sai->sai_in_readpage = 0;
                if (IS_ERR(page)) {
@@ -1155,7 +1149,6 @@ static int ll_statahead_thread(void *arg)
                        break;
                }
        }
-       ll_dir_chain_fini(&chain);
        ll_finish_md_op_data(op_data);
 
        if (rc < 0) {
@@ -1281,7 +1274,6 @@ enum {
 /* file is first dirent under @dir */
 static int is_first_dirent(struct inode *dir, struct dentry *dentry)
 {
-       struct ll_dir_chain   chain;
        struct qstr          *target = &dentry->d_name;
        struct md_op_data    *op_data;
        int                   dot_de;
@@ -1299,8 +1291,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
         *FIXME choose the start offset of the readdir
         */
 
-       ll_dir_chain_init(&chain);
-       page = ll_get_dir_page(dir, op_data, 0, &chain);
+       page = ll_get_dir_page(dir, op_data, 0);
 
        while (1) {
                struct lu_dirpage *dp;
@@ -1389,12 +1380,11 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
                         */
                        ll_release_page(dir, page, le32_to_cpu(dp->ldp_flags) &
                                              LDF_COLLIDE);
-                       page = ll_get_dir_page(dir, op_data, pos, &chain);
+                       page = ll_get_dir_page(dir, op_data, pos);
                }
        }
        EXIT;
 out:
-       ll_dir_chain_fini(&chain);
        ll_finish_md_op_data(op_data);
 
        return rc;
@@ -1551,14 +1541,17 @@ out:
  * \param[in] dir      parent directory
  * \param[in] dentry   dentry that triggers statahead, normally the first
  *                     dirent under @dir
+ * \param[in] agl      indicate whether AGL is needed
  * \retval             -EAGAIN on success, because when this function is
  *                     called, it's already in lookup call, so client should
  *                     do it itself instead of waiting for statahead thread
  *                     to do it asynchronously.
  * \retval             negative number upon error
  */
-static int start_statahead_thread(struct inode *dir, struct dentry *dentry)
+static int start_statahead_thread(struct inode *dir, struct dentry *dentry,
+                                 bool agl)
 {
+       int node = cfs_cpt_spread_node(cfs_cpt_tab, CFS_CPT_ANY);
        struct ll_inode_info *lli = ll_i2info(dir);
        struct ll_statahead_info *sai = NULL;
        struct dentry *parent = dentry->d_parent;
@@ -1605,8 +1598,8 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry)
        CDEBUG(D_READA, "start statahead thread: [pid %d] [parent %pd]\n",
               current->pid, parent);
 
-       task = kthread_create(ll_statahead_thread, parent, "ll_sa_%u",
-                             lli->lli_opendir_pid);
+       task = kthread_create_on_node(ll_statahead_thread, parent, node,
+                                     "ll_sa_%u", lli->lli_opendir_pid);
        if (IS_ERR(task)) {
                spin_lock(&lli->lli_sa_lock);
                lli->lli_sai = NULL;
@@ -1616,7 +1609,7 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry)
                GOTO(out, rc);
        }
 
-       if (ll_i2sbi(parent->d_inode)->ll_flags & LL_SBI_AGL_ENABLED)
+       if (ll_i2sbi(parent->d_inode)->ll_flags & LL_SBI_AGL_ENABLED && agl)
                ll_start_agl(parent, sai);
 
        atomic_inc(&ll_i2sbi(parent->d_inode)->ll_sa_total);
@@ -1647,6 +1640,26 @@ out:
        RETURN(rc);
 }
 
+/*
+ * Check whether statahead for @dir was started.
+ */
+static inline bool ll_statahead_started(struct inode *dir, bool agl)
+{
+       struct ll_inode_info *lli = ll_i2info(dir);
+       struct ll_statahead_info *sai;
+
+       spin_lock(&lli->lli_sa_lock);
+       sai = lli->lli_sai;
+       if (sai && (sai->sai_agl_task != NULL) != agl)
+               CDEBUG(D_READA,
+                      "%s: Statahead AGL hint changed from %d to %d\n",
+                      ll_i2sbi(dir)->ll_fsname,
+                      sai->sai_agl_task != NULL, agl);
+       spin_unlock(&lli->lli_sa_lock);
+
+       return !!sai;
+}
+
 /**
  * statahead entry function, this is called when client getattr on a file, it
  * will start statahead thread if this is the first dir entry, else revalidate
@@ -1654,6 +1667,26 @@ out:
  *
  * \param[in]  dir     parent directory
  * \param[out] dentryp dentry to getattr
+ * \param[in]  agl     whether start the agl thread
+ *
+ * \retval             1 on success
+ * \retval             0 revalidation from statahead cache failed, caller needs
+ *                     to getattr from server directly
+ * \retval             negative number on error, caller often ignores this and
+ *                     then getattr from server
+ */
+int ll_start_statahead(struct inode *dir, struct dentry *dentry, bool agl)
+{
+       if (!ll_statahead_started(dir, agl))
+               return start_statahead_thread(dir, dentry, agl);
+       return 0;
+}
+
+/**
+ * revalidate dentry from statahead cache.
+ *
+ * \param[in]  dir     parent directory
+ * \param[out] dentryp dentry to getattr
  * \param[in]  unplug  unplug statahead window only (normally for negative
  *                     dentry)
  * \retval             1 on success
@@ -1662,19 +1695,18 @@ out:
  * \retval             negative number on error, caller often ignores this and
  *                     then getattr from server
  */
-int ll_statahead(struct inode *dir, struct dentry **dentryp, bool unplug)
+int ll_revalidate_statahead(struct inode *dir, struct dentry **dentryp,
+                           bool unplug)
 {
        struct ll_statahead_info *sai;
+       int rc = 0;
 
        sai = ll_sai_get(dir);
        if (sai) {
-               int rc;
-
                rc = revalidate_statahead_dentry(dir, sai, dentryp, unplug);
                CDEBUG(D_READA, "revalidate statahead %pd: rc = %d.\n",
                       *dentryp, rc);
                ll_sai_put(sai);
-               return rc;
        }
-       return start_statahead_thread(dir, *dentryp);
+       return rc;
 }