Whamcloud - gitweb
Branch b1_8
authoradilger <adilger>
Wed, 20 Aug 2008 16:46:57 +0000 (16:46 +0000)
committeradilger <adilger>
Wed, 20 Aug 2008 16:46:57 +0000 (16:46 +0000)
Revert patch landed to b1_8 but not b1_8_gate.
b=15927

16 files changed:
lustre/include/lustre/.cvsignore
lustre/include/lustre_disk.h
lustre/include/lustre_mds.h
lustre/ldlm/ldlm_resource.c
lustre/llite/dcache.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/rw.c
lustre/llite/statahead.c
lustre/lov/lov_qos.c
lustre/mdc/mdc_locks.c
lustre/mds/handler.c
lustre/mds/mds_reint.c
lustre/obdclass/genops.c
lustre/obdclass/lprocfs_status.c

index 282522d..ce13153 100644 (file)
@@ -1,2 +1,3 @@
+lustre_build_version.h
 Makefile
 Makefile.in
index 5dd36a3..1ab9b2e 100644 (file)
 #define LDD_F_PARAM         0x0400 /* process as lctl conf_param */
 
 enum ldd_mount_type {
-        LDD_MT_EXT3 = 0, 
+        LDD_MT_EXT3 = 0,
         LDD_MT_LDISKFS,
-        LDD_MT_SMFS,   
+        LDD_MT_SMFS,
         LDD_MT_REISERFS,
         LDD_MT_LDISKFS2,
         LDD_MT_LAST
 };
-       
+
 static inline char *mt_str(enum ldd_mount_type mt)
 {
         static char *mount_type_string[] = {
@@ -84,7 +84,7 @@ struct lustre_disk_data {
         __u32      ldd_feature_compat;  /* compatible feature flags */
         __u32      ldd_feature_rocompat;/* read-only compatible feature flags */
         __u32      ldd_feature_incompat;/* incompatible feature flags */
-        
+
         __u32      ldd_config_ver;      /* config rewrite count - not used */
         __u32      ldd_flags;           /* LDD_SV_TYPE */
         __u32      ldd_svindex;         /* server index (0001), must match 
@@ -93,7 +93,7 @@ struct lustre_disk_data {
         char       ldd_fsname[64];      /* filesystem this server is part of */
         char       ldd_svname[64];      /* this server's name (lustre-mdt0001)*/
         __u8       ldd_uuid[40];        /* server UUID (COMPAT_146) */
-   
+
 /*200*/ char       ldd_userdata[1024 - 200]; /* arbitrary user string */
 /*1024*/__u8       ldd_padding[4096 - 1024];
 /*4096*/char       ldd_mount_opts[4096]; /* target fs mount opts */
@@ -169,7 +169,7 @@ struct lustre_mount_data {
  * 2^n * CFS_PAGE_SIZE * 8 for the number of bits that fit an order-n allocation. */
 #define LR_MAX_CLIENTS (CFS_PAGE_SIZE * 8)
 
-                                                                                
+
 /* COMPAT_146 */
 #define OBD_COMPAT_OST          0x00000002 /* this is an OST (temporary) */
 #define OBD_COMPAT_MDT          0x00000004 /* this is an MDT (temporary) */
index b41465a..47d5073 100644 (file)
@@ -237,6 +237,7 @@ typedef int (* md_enqueue_cb_t)(struct obd_export *exp,
                                 int rc);
 
 struct md_enqueue_info {
+        struct obd_export      *mi_exp;
         struct mdc_op_data      mi_data;
         struct lookup_intent    mi_it;
         struct lustre_handle    mi_lockh;
@@ -246,4 +247,9 @@ struct md_enqueue_info {
         void                   *mi_cbdata;
 };
 
+struct mdc_enqueue_args {
+        struct md_enqueue_info   *ma_mi;
+        struct ldlm_enqueue_info *ma_ei;
+};
+
 #endif
index d7b80a8..cf8405e 100644 (file)
@@ -136,12 +136,14 @@ static int lprocfs_wr_lru_size(struct file *file, const char *buffer,
                                unsigned long count, void *data)
 {
         struct ldlm_namespace *ns = data;
-        char dummy[MAX_STRING_SIZE + 1], *end;
+        char dummy[MAX_STRING_SIZE + 1] = { '\0' }, *end;
         unsigned long tmp;
         int lru_resize;
 
-        dummy[MAX_STRING_SIZE] = '\0';
-        if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
+        if (count >= sizeof(dummy) || count == 0)
+                return -EINVAL;
+
+        if (copy_from_user(dummy, buffer, count))
                 return -EFAULT;
 
         if (strncmp(dummy, "clear", 5) == 0) {
@@ -346,7 +348,6 @@ ldlm_namespace_new(struct obd_device *obd, char *name,
                 CFS_INIT_LIST_HEAD(bucket);
 
         CFS_INIT_LIST_HEAD(&ns->ns_unused_list);
-        CFS_INIT_LIST_HEAD(&ns->ns_list_chain);
         ns->ns_nr_unused = 0;
         ns->ns_max_unused = LDLM_DEFAULT_LRU_SIZE;
         ns->ns_max_age = LDLM_DEFAULT_MAX_ALIVE;
@@ -365,7 +366,6 @@ ldlm_namespace_new(struct obd_device *obd, char *name,
         }
 
         at_init(&ns->ns_at_estimate, ldlm_enqueue_min, 0);
-
         ldlm_namespace_register(ns, client);
         RETURN(ns);
 out_proc:
@@ -395,6 +395,7 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
         int local_only = (flags & LDLM_FL_LOCAL_ONLY);
         ENTRY;
 
+
         do {
                 struct ldlm_lock *lock = NULL;
 
index b49d782..96e01b1 100644 (file)
@@ -35,7 +35,7 @@
 #include "llite_internal.h"
 
 /* should NOT be called with the dcache lock, see fs/dcache.c */
-void ll_release(struct dentry *de)
+static void ll_release(struct dentry *de)
 {
         struct ll_dentry_data *lld;
         ENTRY;
index 2031dc4..66e4f8a 100644 (file)
@@ -1169,7 +1169,7 @@ static int ll_file_get_tree_lock_iov(struct ll_lock_tree *tree,
         int rc;
         struct inode * inode = file->f_dentry->d_inode;
 
-        append = (rw == WRITE) && (file->f_flags & O_APPEND);
+        append = (rw == OBD_BRW_WRITE) && (file->f_flags & O_APPEND);
 
         if (append || !ll_is_file_contended(file)) {
                 struct ll_lock_tree_node *node;
@@ -1467,7 +1467,8 @@ repeat:
         if (sbi->ll_max_rw_chunk != 0) {
                 /* first, let's know the end of the current stripe */
                 end = *ppos;
-                obd_extent_calc(sbi->ll_osc_exp, lsm, OBD_CALC_STRIPE_END, &end);
+                obd_extent_calc(sbi->ll_osc_exp, lsm, OBD_CALC_STRIPE_END,
+                                (obd_off *)&end);
 
                 /* correct, the end is beyond the request */
                 if (end > *ppos + count - 1)
index 0eab8b3..5605f8c 100644 (file)
@@ -650,7 +650,6 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmm,
 extern struct dentry_operations ll_init_d_ops;
 extern struct dentry_operations ll_d_ops;
 extern struct dentry_operations ll_fini_d_ops;
-void ll_release(struct dentry *de);
 void ll_intent_drop_lock(struct lookup_intent *);
 void ll_intent_release(struct lookup_intent *);
 extern void ll_set_dd(struct dentry *de);
@@ -860,7 +859,6 @@ int ll_removexattr(struct dentry *dentry, const char *name);
 /* per inode struct, for dir only */
 struct ll_statahead_info {
         struct inode           *sai_inode;
-        struct dentry          *sai_first;      /* first dentry item */
         unsigned int            sai_generation; /* generation for statahead */
         atomic_t                sai_refcount;   /* when access this struct, hold
                                                  * refcount */
@@ -869,8 +867,6 @@ struct ll_statahead_info {
                                                  * reply */
         unsigned int            sai_max;        /* max ahead of lookup */
         unsigned int            sai_index;      /* index of statahead entry */
-        unsigned int            sai_index_next; /* index for the next statahead
-                                                 * entry to be stated */
         unsigned int            sai_hit;        /* hit count */
         unsigned int            sai_miss;       /* miss count:
                                                  * for "ls -al" case, it includes
@@ -888,13 +884,11 @@ struct ll_statahead_info {
                                                  * hidden entries */
         cfs_waitq_t             sai_waitq;      /* stat-ahead wait queue */
         struct ptlrpc_thread    sai_thread;     /* stat-ahead thread */
-        struct list_head        sai_entries_sent;     /* entries sent out */
-        struct list_head        sai_entries_received; /* entries returned */
-        struct list_head        sai_entries_stated;   /* entries stated */
+        struct list_head        sai_entries;    /* stat-ahead entries */
 };
 
 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
index 8fe8acd..669c50d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/random.h>
 #include <linux/version.h>
-#include <linux/mm.h>
 
 #include <lustre_lite.h>
 #include <lustre_ha.h>
@@ -54,8 +53,6 @@ extern struct address_space_operations ll_dir_aops;
 static struct ll_sb_info *ll_init_sbi(void)
 {
         struct ll_sb_info *sbi = NULL;
-        unsigned long pages;
-        struct sysinfo si;
         class_uuid_t uuid;
         int i;
         ENTRY;
@@ -70,13 +67,10 @@ static struct ll_sb_info *ll_init_sbi(void)
         spin_lock_init(&sbi->ll_process_lock);
         sbi->ll_rw_stats_on = 0;
         INIT_LIST_HEAD(&sbi->ll_pglist);
-
-        si_meminfo(&si);
-        pages = si.totalram - si.totalhigh;
-        if (pages >> (20 - CFS_PAGE_SHIFT) < 512)
-                sbi->ll_async_page_max = pages / 2;
+        if (num_physpages >> (20 - CFS_PAGE_SHIFT) < 512)
+                sbi->ll_async_page_max = num_physpages / 2;
         else
-                sbi->ll_async_page_max = (pages / 4) * 3;
+                sbi->ll_async_page_max = (num_physpages / 4) * 3;
         sbi->ll_ra_info.ra_max_pages = min(num_physpages / 8,
                                            SBI_DEFAULT_READAHEAD_MAX);
         sbi->ll_ra_info.ra_max_read_ahead_whole_pages =
index 0e7466b..e79fa25 100644 (file)
@@ -325,9 +325,6 @@ static int ll_ap_make_ready(void *data, int cmd)
         llap = LLAP_FROM_COOKIE(data);
         page = llap->llap_page;
 
-        LASSERTF(!(cmd & OBD_BRW_READ), "cmd %x page %p ino %lu index %lu\n", cmd, page,
-                 page->mapping->host->i_ino, page->index);
-
         /* we're trying to write, but the page is locked.. come back later */
         if (TryLockPage(page))
                 RETURN(-EAGAIN);
index 0c39ed1..6262dd0 100644 (file)
@@ -38,8 +38,6 @@ struct ll_sai_entry {
         struct list_head        se_list;
         unsigned int            se_index;
         int                     se_stat;
-        struct ptlrpc_request  *se_req;
-        struct md_enqueue_info *se_minfo;
 };
 
 enum {
@@ -47,100 +45,9 @@ enum {
         SA_ENTRY_STATED
 };
 
-struct dentry_operations ll_sai_d_ops = {
-        .d_release = ll_release,
-};
-
 static unsigned int sai_generation = 0;
 static spinlock_t sai_generation_lock = SPIN_LOCK_UNLOCKED;
 
-/**
- * Check whether first entry was stated already or not.
- * No need to hold lli_lock, for:
- * (1) it is me that remove entry from the list
- * (2) the statahead thread only add new entry to the list
- */
-static int ll_sai_entry_stated(struct ll_statahead_info *sai)
-{
-        struct ll_sai_entry  *entry;
-        int                   rc = 0;
-
-        if (!list_empty(&sai->sai_entries_stated)) {
-                entry = list_entry(sai->sai_entries_stated.next,
-                                   struct ll_sai_entry, se_list);
-                if (entry->se_index == sai->sai_index_next)
-                        rc = 1;
-        }
-        return rc;
-}
-
-static inline int sa_received_empty(struct ll_statahead_info *sai)
-{
-        return list_empty(&sai->sai_entries_received);
-}
-
-static inline int sa_not_full(struct ll_statahead_info *sai)
-{
-        return sai->sai_index < sai->sai_hit + sai->sai_miss + sai->sai_max;
-}
-
-static inline int sa_is_running(struct ll_statahead_info *sai)
-{
-        return !!(sai->sai_thread.t_flags & SVC_RUNNING);
-}
-
-static inline int sa_is_stopping(struct ll_statahead_info *sai)
-{
-        return !!(sai->sai_thread.t_flags & SVC_STOPPING);
-}
-
-static inline int sa_is_stopped(struct ll_statahead_info *sai)
-{
-        return !!(sai->sai_thread.t_flags & SVC_STOPPED);
-}
-
-/**
- * (1) hit ratio less than 80%
- * or
- * (2) consecutive miss more than 8
- */
-static inline int sa_low_hit(struct ll_statahead_info *sai)
-{
-        return ((sai->sai_hit < 4 * sai->sai_miss && sai->sai_hit > 7) ||
-                (sai->sai_consecutive_miss > 8));
-}
-
-/**
- * process the deleted entry's member and free the entry.
- * (1) release intent
- * (2) free md_enqueue_info
- * (3) drop dentry's ref count
- * (4) release request's ref count
- */
-static void ll_sai_entry_cleanup(struct ll_sai_entry *entry)
-{
-        struct ptlrpc_request  *req = entry->se_req;
-        struct md_enqueue_info *minfo = entry->se_minfo;
-        ENTRY;
-
-        if (minfo) {
-                struct dentry        *dentry = minfo->mi_dentry;
-                struct lookup_intent *it = &minfo->mi_it;
-
-                entry->se_minfo = NULL;
-                ll_intent_release(it);
-                OBD_FREE_PTR(minfo);
-                dput(dentry);
-        }
-        if (req) {
-                entry->se_req = NULL;
-                ptlrpc_req_finished(req);
-        }
-        OBD_FREE_PTR(entry);
-
-        EXIT;
-}
-
 static struct ll_statahead_info *ll_sai_alloc(void)
 {
         struct ll_statahead_info *sai;
@@ -158,9 +65,7 @@ static struct ll_statahead_info *ll_sai_alloc(void)
         sai->sai_max = LL_SA_RPC_MIN;
         cfs_waitq_init(&sai->sai_waitq);
         cfs_waitq_init(&sai->sai_thread.t_ctl_waitq);
-        CFS_INIT_LIST_HEAD(&sai->sai_entries_sent);
-        CFS_INIT_LIST_HEAD(&sai->sai_entries_received);
-        CFS_INIT_LIST_HEAD(&sai->sai_entries_stated);
+        CFS_INIT_LIST_HEAD(&sai->sai_entries);
         return sai;
 }
 
@@ -184,7 +89,7 @@ static void ll_sai_put(struct ll_statahead_info *sai)
                 lli->lli_sai = NULL;
                 spin_unlock(&lli->lli_lock);
 
-                LASSERT(sa_is_stopped(sai));
+                LASSERT(sai->sai_thread.t_flags & SVC_STOPPED);
 
                 if (sai->sai_sent > sai->sai_replied)
                         CDEBUG(D_READA,"statahead for dir %lu/%u does not "
@@ -192,33 +97,19 @@ static void ll_sai_put(struct ll_statahead_info *sai)
                               inode->i_ino, inode->i_generation,
                               sai->sai_sent, sai->sai_replied);
 
-                list_for_each_entry_safe(entry, next, &sai->sai_entries_sent,
+                list_for_each_entry_safe(entry, next, &sai->sai_entries,
                                          se_list) {
                         list_del(&entry->se_list);
-                        ll_sai_entry_cleanup(entry);
-                }
-                list_for_each_entry_safe(entry, next, &sai->sai_entries_received,
-                                         se_list) {
-                        list_del(&entry->se_list);
-                        ll_sai_entry_cleanup(entry);
-                }
-                list_for_each_entry_safe(entry, next, &sai->sai_entries_stated,
-                                         se_list) {
-                        list_del(&entry->se_list);
-                        ll_sai_entry_cleanup(entry);
+                        OBD_FREE_PTR(entry);
                 }
-                dput(sai->sai_first);
                 OBD_FREE_PTR(sai);
                 iput(inode);
         }
         EXIT;
 }
 
-/**
- * insert it into sai_entries_sent tail when init.
- */
 static struct ll_sai_entry *
-ll_sai_entry_init(struct ll_statahead_info *sai, unsigned int index)
+ll_sai_entry_get(struct ll_statahead_info *sai, unsigned int index, int stat)
 {
         struct ll_inode_info *lli = ll_i2info(sai->sai_inode);
         struct ll_sai_entry  *entry;
@@ -227,183 +118,148 @@ ll_sai_entry_init(struct ll_statahead_info *sai, unsigned int index)
         OBD_ALLOC_PTR(entry);
         if (entry == NULL)
                 RETURN(ERR_PTR(-ENOMEM));
-
-        CDEBUG(D_READA, "alloc sai entry %p index %u\n",
-               entry, index);
+        
+        CDEBUG(D_READA, "alloc sai entry %p index %u, stat %d\n",
+               entry, index, stat);
         entry->se_index = index;
-        entry->se_stat  = SA_ENTRY_UNSTATED;
+        entry->se_stat  = stat;
 
         spin_lock(&lli->lli_lock);
-        list_add_tail(&entry->se_list, &sai->sai_entries_sent);
+        list_add_tail(&entry->se_list, &sai->sai_entries);
         spin_unlock(&lli->lli_lock);
 
         RETURN(entry);
 }
 
-/**
- * delete it from sai_entries_stated head when fini, it need not
- * to process entry's member.
+/*
+ * inside lli_lock
+ * return value:
+ *  0: can not find the entry with the index
+ *  1: it is the first entry
+ *  2: it is not the first entry
  */
-static void ll_sai_entry_fini(struct ll_statahead_info *sai)
+static int
+ll_sai_entry_set(struct ll_statahead_info *sai, unsigned int index, int stat)
 {
-        struct ll_inode_info *lli = ll_i2info(sai->sai_inode);
-        struct ll_sai_entry  *entry;
+        struct ll_sai_entry *entry;
+        int                  rc = 0;
         ENTRY;
-        
-        spin_lock(&lli->lli_lock);
-        sai->sai_index_next++;
-        if (likely(!list_empty(&sai->sai_entries_stated))) {
-                entry = list_entry(sai->sai_entries_stated.next,
-                                   struct ll_sai_entry, se_list);
-                if (entry->se_index < sai->sai_index_next) {
-                        list_del(&entry->se_list);
-                        OBD_FREE_PTR(entry);
-                }
-        } else
-                LASSERT(sa_is_stopped(sai));
-        spin_unlock(&lli->lli_lock);
+
+        if (list_empty(&sai->sai_entries))
+                RETURN(0);
+
+        entry = list_entry(sai->sai_entries.next, struct ll_sai_entry, se_list);
+        if (entry->se_index == index)
+                GOTO(out, rc = 1);
+
+        while (entry->se_list.next != &sai->sai_entries &&
+               entry->se_index < index) {
+                entry = list_entry(entry->se_list.next, struct ll_sai_entry,
+                                   se_list);
+                if (entry->se_index == index)
+                        GOTO(out, rc = 2);
+        }
 
         EXIT;
+
+out:
+        if (rc) {
+                LASSERT(entry->se_stat == SA_ENTRY_UNSTATED);
+                entry->se_stat = stat;
+        }
+
+        return rc;
 }
 
-/**
- * inside lli_lock.
- * \retval NULL : can not find the entry in sai_entries_sent with the index
- * \retval entry: find the entry in sai_entries_sent with the index
+/*
+ * Check whether first entry was stated already or not.
+ * No need to hold lli_lock, for:
+ * (1) it is me that remove entry from the list
+ * (2) the statahead thread only add new entry to the list tail
  */
-static struct ll_sai_entry *
-ll_sai_entry_set(struct ll_statahead_info *sai, unsigned int index, int stat,
-                 struct ptlrpc_request *req, struct md_enqueue_info *minfo)
+static int ll_sai_entry_stated(struct ll_statahead_info *sai)
 {
-        struct ll_sai_entry *entry;
+        struct ll_sai_entry  *entry;
+        int                   rc = 0;
         ENTRY;
 
-        if (!list_empty(&sai->sai_entries_sent)) {
-                list_for_each_entry(entry, &sai->sai_entries_sent,
-                                    se_list) {
-                        if (entry->se_index == index) {
-                                entry->se_stat = stat;
-                                entry->se_req = ptlrpc_request_addref(req);
-                                entry->se_minfo = minfo;
-                                RETURN(entry);
-                        } else if (entry->se_index > index)
-                                RETURN(NULL);
-                }
+        if (!list_empty(&sai->sai_entries)) {
+                entry = list_entry(sai->sai_entries.next, struct ll_sai_entry,
+                                   se_list);
+                rc = (entry->se_stat != SA_ENTRY_UNSTATED);
         }
-        RETURN(NULL);
-}
 
-/**
- * inside lli_lock.
- * Move entry to sai_entries_received and
- * insert it into sai_entries_received tail.
- */
-static inline void
-ll_sai_entry_to_received(struct ll_statahead_info *sai, struct ll_sai_entry *entry)
-{
-        if (!list_empty(&entry->se_list))
-                list_del_init(&entry->se_list);
-        list_add_tail(&entry->se_list, &sai->sai_entries_received);
+        RETURN(rc);
 }
 
-/**
- * Move entry to sai_entries_stated and
- * sort with the index.
- */
-static int
-ll_sai_entry_to_stated(struct ll_statahead_info *sai, struct ll_sai_entry *entry)
+static void ll_sai_entry_put(struct ll_statahead_info *sai)
 {
         struct ll_inode_info *lli = ll_i2info(sai->sai_inode);
-        struct ll_sai_entry  *se;
+        struct ll_sai_entry  *entry;
         ENTRY;
-
+        
         spin_lock(&lli->lli_lock);
-        if (!list_empty(&entry->se_list))
-                list_del_init(&entry->se_list);
-
-        if (unlikely(entry->se_index < sai->sai_index_next)) {
-                spin_unlock(&lli->lli_lock);
-                ll_sai_entry_cleanup(entry);
-                RETURN(0);
-        }
-
-        list_for_each_entry_reverse(se, &sai->sai_entries_stated, se_list) {
-                if (se->se_index < entry->se_index) {
-                        list_add(&entry->se_list, &se->se_list);
-                        spin_unlock(&lli->lli_lock);
-                        RETURN(1);
-                }
+        if (!list_empty(&sai->sai_entries)) {
+                entry = list_entry(sai->sai_entries.next,
+                                   struct ll_sai_entry, se_list);
+                list_del(&entry->se_list);
+                OBD_FREE_PTR(entry);
         }
-
-        /*
-         * I am the first entry.
-         */
-        list_add(&entry->se_list, &sai->sai_entries_stated);
         spin_unlock(&lli->lli_lock);
-        RETURN(1);
+
+        EXIT;
 }
 
-/**
- * finish lookup/revalidate.
- */
-static int do_statahead_interpret(struct ll_statahead_info *sai)
+/* finish lookup/revalidate */
+static int ll_statahead_interpret(struct obd_export *exp,
+                                  struct ptlrpc_request *req,
+                                  struct md_enqueue_info *minfo,
+                                  int rc)
 {
-        struct ll_inode_info   *lli = ll_i2info(sai->sai_inode);
-        struct ll_sai_entry    *entry;
-        struct ptlrpc_request  *req;
-        struct md_enqueue_info *minfo;
-        struct dentry          *dentry;
-        struct lookup_intent   *it;
-        int                     rc = 0;
+        struct lookup_intent     *it = &minfo->mi_it;
+        struct dentry            *dentry = minfo->mi_dentry;
+        struct inode             *dir = dentry->d_parent->d_inode;
+        struct ll_inode_info     *lli = ll_i2info(dir);
+        struct ll_statahead_info *sai = NULL;
         ENTRY;
 
-        spin_lock(&lli->lli_lock);
-        LASSERT(!sa_received_empty(sai));
-        entry = list_entry(sai->sai_entries_received.next, struct ll_sai_entry,
-                           se_list);
-        list_del_init(&entry->se_list);
-        spin_unlock(&lli->lli_lock);
+        CDEBUG(D_READA, "interpret statahead %.*s rc %d\n",
+               dentry->d_name.len, dentry->d_name.name, rc);
 
-        if (unlikely(entry->se_index < sai->sai_index_next)) {
-                ll_sai_entry_cleanup(entry);
-                RETURN(0);
+        spin_lock(&lli->lli_lock);
+        if (unlikely(lli->lli_sai == NULL ||
+            lli->lli_sai->sai_generation != minfo->mi_generation)) {
+                spin_unlock(&lli->lli_lock);
+                GOTO(out_free, rc = -ESTALE);
+        } else {
+                sai = ll_sai_get(lli->lli_sai);
+                spin_unlock(&lli->lli_lock);
         }
 
-        req = entry->se_req;
-        minfo = entry->se_minfo;
-        dentry = minfo->mi_dentry;
-        it = &minfo->mi_it;
-
-        if (entry->se_stat != SA_ENTRY_STATED)
-                GOTO(out, rc = entry->se_stat);
+        if (rc || dir == NULL)
+                GOTO(out, rc);
 
         if (dentry->d_inode == NULL) {
-                /*
-                 * lookup.
-                 */
+                /* lookup */
                 struct dentry    *save = dentry;
                 struct it_cb_data icbd = {
-                        .icbd_parent   = dentry->d_parent->d_inode,
+                        .icbd_parent   = dir,
                         .icbd_childp   = &dentry
                 };
 
                 rc = lookup_it_finish(req, DLM_REPLY_REC_OFF, it, &icbd);
                 if (!rc)
-                        /*
+                        /* 
                          * Here dentry->d_inode might be NULL,
                          * because the entry may have been removed before
                          * we start doing stat ahead.
                          */
                         ll_lookup_finish_locks(it, dentry);
 
-                if (dentry != save) {
-                        minfo->mi_dentry = dentry;
+                if (dentry != save)
                         dput(save);
-                }
         } else {
-                /*
-                 * revalidate.
-                 */
+                /* revalidate */
                 struct mds_body *body;
 
                 body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF,
@@ -435,66 +291,36 @@ static int do_statahead_interpret(struct ll_statahead_info *sai)
         EXIT;
 
 out:
-        if (likely(ll_sai_entry_to_stated(sai, entry))) {
-                entry->se_minfo = NULL;
-                entry->se_req = NULL;
-                cfs_waitq_signal(&sai->sai_waitq);
-                ll_intent_release(it);
-                OBD_FREE_PTR(minfo);
-                dput(dentry);
-                ptlrpc_req_finished(req);
-        }
-        return rc;
-}
+        if (sai != NULL) {
+                int first;
 
-static int ll_statahead_interpret(struct obd_export *exp,
-                                  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 ll_inode_info     *lli = ll_i2info(dir);
-        struct ll_statahead_info *sai;
-        struct ll_sai_entry      *entry;
-        ENTRY;
-
-        CDEBUG(D_READA, "interpret statahead %.*s rc %d\n",
-               dentry->d_name.len, dentry->d_name.name, rc);
-
-        spin_lock(&lli->lli_lock);
-        if (unlikely(lli->lli_sai == NULL ||
-            lli->lli_sai->sai_generation != minfo->mi_generation)) {
+                sai->sai_replied++;
+                spin_lock(&lli->lli_lock);
+                first = ll_sai_entry_set(sai,
+                                         (unsigned int)(long)minfo->mi_cbdata,
+                                         SA_ENTRY_STATED);
+                /*
+                 * wake up the "ls -l" process only when the first entry
+                 * returned.
+                 */
                 spin_unlock(&lli->lli_lock);
-                ll_intent_release(it);
-                dput(dentry);
-                OBD_FREE_PTR(minfo);
-                RETURN(-ESTALE);
-        } else {
-                sai = lli->lli_sai;
-                if (rc || dir == NULL)
-                        rc = -ESTALE;
+                if (first == 1)
+                        cfs_waitq_signal(&sai->sai_waitq);
+                else if (first == 0)
+                        CDEBUG(D_READA, "can't find sai entry for dir "
+                               "%lu/%u generation %u index %d\n",
+                               dir->i_ino, dir->i_generation,
+                               minfo->mi_generation,
+                               (unsigned int)(long)minfo->mi_cbdata);
 
-                entry = ll_sai_entry_set(sai,
-                                         (unsigned int)(long)minfo->mi_cbdata,
-                                         rc ? SA_ENTRY_UNSTATED :
-                                         SA_ENTRY_STATED, req, minfo);
-                LASSERT(entry != NULL);
-                if (likely(sa_is_running(sai))) {
-                        ll_sai_entry_to_received(sai, entry);
-                        sai->sai_replied++;
-                        spin_unlock(&lli->lli_lock);
-                        cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);
-                } else {
-                        if (!list_empty(&entry->se_list))
-                                list_del_init(&entry->se_list);
-                        sai->sai_replied++;
-                        spin_unlock(&lli->lli_lock);
-                        ll_sai_entry_cleanup(entry);
-                }
-                RETURN(rc);
+                ll_sai_put(sai);
         }
+out_free:
+        ll_intent_release(it);
+        OBD_FREE_PTR(minfo);
+
+        dput(dentry);
+        return rc;
 }
 
 static void sa_args_fini(struct md_enqueue_info *minfo,
@@ -523,6 +349,7 @@ static int sa_args_prep(struct inode *dir, struct dentry *dentry,
                 return -ENOMEM;
         }
 
+        minfo->mi_exp = ll_i2mdcexp(dir);
         minfo->mi_it.it_op = IT_GETATTR;
         minfo->mi_dentry = dentry;
         minfo->mi_cb = ll_statahead_interpret;
@@ -542,9 +369,7 @@ static int sa_args_prep(struct inode *dir, struct dentry *dentry,
         return 0;
 }
 
-/**
- * similar to ll_lookup_it().
- */
+/* similar to ll_lookup_it(). */
 static int do_sa_lookup(struct inode *dir, struct dentry *dentry)
 {
         struct md_enqueue_info   *minfo;
@@ -560,7 +385,7 @@ static int do_sa_lookup(struct inode *dir, struct dentry *dentry)
                                     dentry->d_name.name, dentry->d_name.len, 0,
                                     NULL);
         if (rc == 0)
-                rc = mdc_intent_getattr_async(ll_i2mdcexp(dir), minfo, einfo);
+                rc = mdc_intent_getattr_async(minfo->mi_exp, minfo, einfo);
 
         if (rc)
                 sa_args_fini(minfo, einfo);
@@ -568,16 +393,16 @@ static int do_sa_lookup(struct inode *dir, struct dentry *dentry)
         RETURN(rc);
 }
 
-/**
+/* 
  * similar to ll_revalidate_it().
- * \retval      1 -- dentry valid
- * \retval      0 -- will send stat-ahead request
- * \retval others -- prepare stat-ahead request failed
+ * return value:
+ *  1      -- dentry valid
+ *  0      -- will send stat-ahead request
+ *  others -- prepare stat-ahead request failed
  */
 static int do_sa_revalidate(struct dentry *dentry)
 {
         struct inode             *inode = dentry->d_inode;
-        struct inode             *dir = dentry->d_parent->d_inode;
         struct ll_fid             fid;
         struct lookup_intent      it = { .it_op = IT_GETATTR };
         struct md_enqueue_info   *minfo;
@@ -596,13 +421,13 @@ static int do_sa_revalidate(struct dentry *dentry)
 
         ll_inode2fid(&fid, inode);
 
-        rc = mdc_revalidate_lock(ll_i2mdcexp(dir), &it, &fid);
+        rc = mdc_revalidate_lock(ll_i2mdcexp(inode), &it, &fid);
         if (rc == 1) {
                 ll_intent_release(&it);
                 RETURN(1);
         }
 
-        rc = sa_args_prep(dir, dentry, &minfo, &einfo);
+        rc = sa_args_prep(dentry->d_parent->d_inode, dentry, &minfo, &einfo);
         if (rc)
                 RETURN(rc);
 
@@ -610,7 +435,7 @@ static int do_sa_revalidate(struct dentry *dentry)
                                     inode, dentry->d_name.name,
                                     dentry->d_name.len, 0, NULL);
         if (rc == 0)
-                rc = mdc_intent_getattr_async(ll_i2mdcexp(dir), minfo, einfo);
+                rc = mdc_intent_getattr_async(minfo->mi_exp, minfo, einfo);
 
         if (rc)
                 sa_args_fini(minfo, einfo);
@@ -634,13 +459,12 @@ static inline void ll_name2qstr(struct qstr *this, const char *name, int namelen
 
 static int ll_statahead_one(struct dentry *parent, struct ll_dir_entry *de)
 {
-        struct inode             *dir = parent->d_inode;
-        struct ll_inode_info     *lli = ll_i2info(dir);
-        struct ll_statahead_info *sai = lli->lli_sai;
-        struct qstr               name;
-        struct dentry            *dentry;
-        struct ll_sai_entry      *se;
-        int                       rc;
+        struct inode           *dir = parent->d_inode;
+        struct ll_inode_info   *lli = ll_i2info(dir);
+        struct qstr             name;
+        struct dentry          *dentry;
+        struct ll_sai_entry    *se;
+        int                     rc;
         ENTRY;
 
 #ifdef DCACHE_LUSTRE_INVALID
@@ -654,7 +478,8 @@ static int ll_statahead_one(struct dentry *parent, struct ll_dir_entry *de)
                 RETURN(-EINVAL);
         }
 
-        se = ll_sai_entry_init(sai, sai->sai_index);
+        se = ll_sai_entry_get(lli->lli_sai, lli->lli_sai->sai_index,
+                              SA_ENTRY_UNSTATED);
         if (IS_ERR(se))
                 RETURN(PTR_ERR(se));
 
@@ -682,15 +507,34 @@ out:
                 CDEBUG(D_READA, "set sai entry %p index %u stat %d rc %d\n",
                        se, se->se_index, se->se_stat, rc);
                 se->se_stat = rc;
-                if (ll_sai_entry_to_stated(sai, se))
-                        cfs_waitq_signal(&sai->sai_waitq);
+                cfs_waitq_signal(&lli->lli_sai->sai_waitq);
         } else {
-                sai->sai_sent++;
+                lli->lli_sai->sai_sent++;
         }
 
-        sai->sai_index++;
+        lli->lli_sai->sai_index++;
         return rc;
 }
+                
+static inline int sa_check_stop(struct ll_statahead_info *sai)
+{
+        return !!(sai->sai_thread.t_flags & SVC_STOPPING);
+}
+
+static inline int sa_not_full(struct ll_statahead_info *sai)
+{
+        return sai->sai_index < sai->sai_hit + sai->sai_miss + sai->sai_max;
+}
+
+/* (1) hit ratio less than 80%
+ * or
+ * (2) consecutive miss more than 8
+ */
+static inline int sa_low_hit(struct ll_statahead_info *sai)
+{
+        return ((sai->sai_hit < 4 * sai->sai_miss && sai->sai_hit > 7) ||
+                (sai->sai_consecutive_miss > 8));
+}
 
 struct ll_sa_thread_args {
         struct dentry   *sta_parent;
@@ -729,25 +573,11 @@ static int ll_statahead_thread(void *arg)
                 struct page *page;
 
                 npages = dir_pages(dir);
-                /*
-                 * reach the end of dir.
-                 */
+                /* reach the end of dir */
                 if (index >= npages) {
                         CDEBUG(D_READA, "reach end, index/npages %lu/%lu\n",
                                index, npages);
-
-                        while (1) {
-                                l_wait_event(thread->t_ctl_waitq,
-                                             !sa_is_running(sai) ||
-                                             !sa_received_empty(sai) ||
-                                             sai->sai_sent == sai->sai_replied,
-                                             &lwi);
-                                if (!sa_received_empty(sai) &&
-                                    sa_is_running(sai))
-                                        do_statahead_interpret(sai);
-                                else
-                                        GOTO(out, rc);
-                        }
+                        break;
                 }
 
                 page = ll_get_dir_page(dir, index);
@@ -763,56 +593,35 @@ static int ll_statahead_thread(void *arg)
                 limit = kaddr + CFS_PAGE_SIZE - ll_dir_rec_len(1);
                 de = (struct ll_dir_entry *)kaddr;
                 if (!index) {
-                        /*
-                         * skip "."
-                         */
-                        de = ll_dir_next_entry(de);
-                        /*
-                         * skip ".."
-                         */
-                        de = ll_dir_next_entry(de);
+                        de = ll_dir_next_entry(de); /* skip "." */
+                        de = ll_dir_next_entry(de); /* skip ".." */
                 }
 
                 for (; (char*)de <= limit; de = ll_dir_next_entry(de)) {
-                        if (de->lde_inode == 0)
+                        if (!de->lde_inode)
                                 continue;
 
                         if (de->lde_name[0] == '.' && !sai->sai_ls_all) {
-                                /*
-                                 * skip hidden files..
-                                 */
+                                /* skip hidden files */
                                 sai->sai_skip_hidden++;
                                 continue;
                         }
 
-                        /*
-                         * don't stat-ahead first entry.
-                         */
+                        /* don't stat-ahead first entry */
                         if (unlikely(!first)) {
                                 first++;
                                 continue;
                         }
 
-keep_de:
                         l_wait_event(thread->t_ctl_waitq,
-                                     !sa_is_running(sai) || sa_not_full(sai) ||
-                                     !sa_received_empty(sai),
+                                     sa_check_stop(sai) || sa_not_full(sai),
                                      &lwi);
 
-                        while (!sa_received_empty(sai) && sa_is_running(sai))
-                                do_statahead_interpret(sai);
-
-                        if (unlikely(!sa_is_running(sai))) {
+                        if (unlikely(sa_check_stop(sai))) {
                                 ll_put_page(page);
                                 GOTO(out, rc);
                         }
 
-                        if (!sa_not_full(sai))
-                                /*
-                                 * do not skip the current de.
-                                 */
-                                goto keep_de;
-
                         rc = ll_statahead_one(parent, de);
                         if (rc < 0) {
                                 ll_put_page(page);
@@ -823,7 +632,6 @@ keep_de:
                 index++;
         }
         EXIT;
-
 out:
         spin_lock(&lli->lli_lock);
         thread->t_flags = SVC_STOPPED;
@@ -837,9 +645,7 @@ out:
         return rc;
 }
 
-/**
- * called in ll_file_release().
- */
+/* called in ll_file_release() */
 void ll_stop_statahead(struct inode *inode, void *key)
 {
         struct ll_inode_info *lli = ll_i2info(inode);
@@ -859,7 +665,7 @@ void ll_stop_statahead(struct inode *inode, void *key)
                 struct l_wait_info lwi = { 0 };
 
                 thread = &lli->lli_sai->sai_thread;
-                if (!sa_is_stopped(lli->lli_sai)) {
+                if (!(thread->t_flags & SVC_STOPPED)) {
                         thread->t_flags = SVC_STOPPING;
                         spin_unlock(&lli->lli_lock);
                         cfs_waitq_signal(&thread->t_ctl_waitq);
@@ -867,7 +673,7 @@ void ll_stop_statahead(struct inode *inode, void *key)
                         CDEBUG(D_READA, "stopping statahead thread, pid %d\n",
                                cfs_curproc_pid());
                         l_wait_event(thread->t_ctl_waitq,
-                                     sa_is_stopped(lli->lli_sai),
+                                     thread->t_flags & SVC_STOPPED,
                                      &lwi);
                 } else {
                         spin_unlock(&lli->lli_lock);
@@ -885,18 +691,9 @@ void ll_stop_statahead(struct inode *inode, void *key)
 }
 
 enum {
-        /*
-         * not first dirent, or is "."
-         */
-        LS_NONE_FIRST_DE = 0,
-        /*
-         * the first non-hidden dirent
-         */
-        LS_FIRST_DE,
-        /*
-         * the first hidden dirent, that is ".xxx
-         */
-        LS_FIRST_DOT_DE
+        LS_NONE_FIRST_DE = 0,   /* not first dirent, or is "." */
+        LS_FIRST_DE,            /* the first non-hidden dirent */
+        LS_FIRST_DOT_DE         /* the first hidden dirent, that is ".xxx" */
 };
 
 static int is_first_dirent(struct inode *dir, struct dentry *dentry)
@@ -911,9 +708,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
 
         while (1) {
                 npages = dir_pages(dir);
-                /*
-                 * reach the end of dir.
-                 */
+                /* reach the end of dir */
                 if (index >= npages) {
                         CDEBUG(D_READA, "reach end, index/npages %lu/%lu\n",
                                index, npages);
@@ -936,18 +731,14 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
                                        strncmp(de->lde_name, ".", 1) == 0)))
                                 CWARN("Maybe got bad on-disk dir: %lu\n",
                                       dir->i_ino);
-                        /*
-                         * skip "." or ingore bad entry.
-                         */
+                        /* skip "." or ingore bad entry */
                         de = ll_dir_next_entry(de);
 
                         if (unlikely(!(de->lde_name_len == 2 &&
                                        strncmp(de->lde_name, "..", 2) == 0)))
                                 CWARN("Maybe got bad on-disk dir: %lu\n",
                                       dir->i_ino);
-                        /*
-                         * skip ".." or ingore bad entry.
-                         */
+                        /* skip ".." or ingore bad entry */
                         de = ll_dir_next_entry(de);
                 }
 
@@ -981,14 +772,14 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
         RETURN(rc);
 }
 
-/**
- * Start statahead thread if this is the first dir entry.
+/* Start statahead thread if this is the first dir entry.
  * Otherwise if a thread is started already, wait it until it is ahead of me.
- * \retval 0       -- stat ahead thread process such dentry, for lookup, it miss
- * \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 others  -- error
+ * Return value: 
+ *  0       -- miss
+ *  1       -- hit
+ *  -EEXIST -- stat ahead thread started, and this is the first dentry
+ *  -EBADFD -- statahead thread exit and not dentry available
+ *  others  -- error
  */
 int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
 {
@@ -1003,20 +794,10 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
         LASSERT(lli->lli_opendir_pid == cfs_curproc_pid());
 
         if (sai) {
-                if (unlikely(sa_is_stopped(sai) &&
-                             list_empty(&sai->sai_entries_stated)))
+                if (unlikely(sai->sai_thread.t_flags & SVC_STOPPED &&
+                             list_empty(&sai->sai_entries)))
                         RETURN(-EBADFD);
 
-                /*
-                 * skip the first dentry.
-                 */
-                if (unlikely((*dentryp)->d_name.len ==
-                             sai->sai_first->d_name.len &&
-                             !strncmp((*dentryp)->d_name.name,
-                                      sai->sai_first->d_name.name,
-                                      sai->sai_first->d_name.len)))
-                        RETURN(-EEXIST);
-
                 if ((*dentryp)->d_name.name[0] == '.') {
                         if (likely(sai->sai_ls_all ||
                             sai->sai_miss_hidden >= sai->sai_skip_hidden)) {
@@ -1048,11 +829,10 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
                         sbi->ll_sa_cached++;
                 } else {
                         sbi->ll_sa_blocked++;
-                        /*
-                         * thread started already, avoid double-stat.
-                         */
+                        /* thread started already, avoid double-stat */
                         l_wait_event(sai->sai_waitq,
-                                     ll_sai_entry_stated(sai) || sa_is_stopped(sai),
+                                     ll_sai_entry_stated(sai) ||
+                                     sai->sai_thread.t_flags & SVC_STOPPED,
                                      &lwi);
                 }
 
@@ -1068,22 +848,16 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
                                 RETURN(1);
                         }
                 }
-                /*
-                 * do nothing for revalidate.
-                 */
+                /* do nothing for revalidate */
                 RETURN(0);
         }
 
-         /*
-          * I am the "lli_opendir_pid" owner, only me can set "lli_sai".
-          */ 
+         /* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */ 
         LASSERT(lli->lli_sai == NULL);
 
         rc = is_first_dirent(dir, *dentryp);
         if (rc == LS_NONE_FIRST_DE) {
-                /*
-                 * It is not "ls -{a}l" operation, no need statahead for it.
-                 */
+                /* 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;
@@ -1094,9 +868,8 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
         sai = ll_sai_alloc();
         if (sai == NULL)
                 RETURN(-ENOMEM);
-
+        
         sai->sai_inode  = igrab(dir);
-        sai->sai_first = dget(*dentryp);
         sai->sai_ls_all = (rc == LS_FIRST_DOT_DE);
 
         sta.sta_parent = (*dentryp)->d_parent;
@@ -1113,7 +886,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
         }
 
         l_wait_event(sai->sai_thread.t_ctl_waitq, 
-                     sa_is_running(sai) || sa_is_stopped(sai),
+                     sai->sai_thread.t_flags & (SVC_RUNNING | SVC_STOPPED),
                      &lwi);
 
         /*
@@ -1123,24 +896,21 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
         RETURN(-EEXIST);
 }
 
-/**
- * update hit/miss count.
- */
-int ll_statahead_exit(struct dentry *dentry, int result)
+/* update hit/miss count */
+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);
         struct ll_dentry_data *ldd = ll_d2d(dentry);
-        ENTRY;
 
         if (lli->lli_opendir_pid != cfs_curproc_pid())
-                RETURN(-EBADFD);
+                return;
 
         if (lli->lli_sai) {
                 struct ll_statahead_info *sai = lli->lli_sai;
 
-                if (result >= 1) {
+                if (result == 1) {
                         sbi->ll_sa_hit++;
                         sai->sai_hit++;
                         sai->sai_consecutive_miss = 0;
@@ -1149,7 +919,8 @@ int ll_statahead_exit(struct dentry *dentry, int result)
                         sbi->ll_sa_miss++;
                         sai->sai_miss++;
                         sai->sai_consecutive_miss++;
-                        if (sa_low_hit(sai) && sa_is_running(sai)) {
+                        if (sa_low_hit(sai) &&
+                            sai->sai_thread.t_flags & SVC_RUNNING) {
                                 sbi->ll_sa_wrong++;
                                 CDEBUG(D_READA, "statahead for dir %.*s hit "
                                        "ratio too low: hit/miss %u/%u, "
@@ -1160,30 +931,16 @@ int ll_statahead_exit(struct dentry *dentry, int result)
                                        sai->sai_sent, sai->sai_replied,
                                        cfs_curproc_pid());
                                 spin_lock(&lli->lli_lock);
-                                if (!sa_is_stopped(sai))
+                                if (!(sai->sai_thread.t_flags & SVC_STOPPED))
                                         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 (unlikely(ldd == NULL)) {
-                        ll_set_dd(dentry);
-                        ldd = ll_d2d(dentry);
-                        if (ldd != NULL && dentry->d_op == NULL) {
-                                lock_dentry(dentry);
-                                dentry->d_op = dentry->d_op ? : &ll_sai_d_ops;
-                                unlock_dentry(dentry);
-                        }
-                }
+                cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);
+                ll_sai_entry_put(sai);
 
                 if (likely(ldd != NULL))
                         ldd->lld_sa_generation = sai->sai_generation;
-                else
-                        RETURN(-ENOMEM);
         }
-        RETURN(0);
 }
index fe92246..695704d 100644 (file)
@@ -311,8 +311,8 @@ static int qos_used(struct lov_obd *lov, __u32 index, __u64 *total_wt)
                        lov->lov_tgts[i]->ltd_qos.ltq_penalty_per_obj >> 10,
                        lov->lov_tgts[i]->ltd_qos.ltq_penalty >> 10,
                        lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_penalty_per_obj>>10,
-                       lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_penalty>>10,
-                       lov->lov_tgts[i]->ltd_qos.ltq_weight>>10);
+                       lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_penalty >> 10,
+                       lov->lov_tgts[i]->ltd_qos.ltq_weight >> 10);
 #endif
         }
 
@@ -333,6 +333,7 @@ static int qos_calc_rr(struct lov_obd *lov)
                 RETURN(0);
         }
 
+        /* Do actual allocation. */
         down_write(&lov->lov_qos.lq_rw_sem);
         ost_count = lov->desc.ld_tgt_count;
 
@@ -360,7 +361,7 @@ static int qos_calc_rr(struct lov_obd *lov)
                 int j = 0;
                 for (i = 0; i < ost_count; i++) {
                         if (lov->lov_tgts[i] &&
-                            (lov->lov_tgts[i]->ltd_qos.ltq_oss == oss)) {
+                            lov->lov_tgts[i]->ltd_qos.ltq_oss == oss) {
                               /* Evenly space these OSTs across arrayspace */
                               int next = j * ost_count / oss->lqo_ost_count;
                               while (lov->lov_qos.lq_rr_array[next] !=
@@ -380,7 +381,7 @@ static int qos_calc_rr(struct lov_obd *lov)
         if (placed != real_count) {
                 /* This should never happen */
                 LCONSOLE_ERROR_MSG(0x14e, "Failed to place all OSTs in the "
-                                   "round-robin list (%d of %d).\n", 
+                                   "round-robin list (%d of %d).\n",
                                    placed, real_count);
                 for (i = 0; i < ost_count; i++) {
                         LCONSOLE(D_WARNING, "rr #%d ost idx=%d\n", i,
@@ -524,7 +525,7 @@ static int alloc_rr(struct lov_obd *lov, int *idx_arr, int *stripe_cnt,
         down_read(&lov->lov_qos.lq_rw_sem);
         ost_start_idx_temp = lov->lov_start_idx;
 
-repeat_find :
+repeat_find:
         array_idx = (lov->lov_start_idx + lov->lov_offset_idx) % ost_count;
         idx_pos = idx_arr;
 #ifdef QOS_DEBUG
@@ -600,7 +601,7 @@ repeat_find:
                         continue;
 
                 /* Drop slow OSCs if we can, but not for requested start idx */
-                if (obd_precreate(lov->lov_tgts[ost_idx]->ltd_exp) > speed &&
+                if ((obd_precreate(lov->lov_tgts[ost_idx]->ltd_exp) > speed) &&
                     (i != 0 || speed < 2))
                         continue;
 
@@ -928,7 +929,6 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
                         CDEBUG(D_INODE, "stripe %d has size "LPU64"/"LPU64"\n",
                                i, req->rq_oi.oi_oa->o_size, src_oa->o_size);
                 }
-
         }
         LASSERT(set->set_count == stripes);
 
index 596a49d..d06c739 100644 (file)
@@ -812,15 +812,21 @@ EXPORT_SYMBOL(mdc_intent_lock);
 static int mdc_intent_getattr_async_interpret(struct ptlrpc_request *req,
                                               void *unused, int rc)
 {
-        struct obd_export        *exp = req->rq_async_args.pointer_arg[0];
-        struct md_enqueue_info   *minfo = req->rq_async_args.pointer_arg[1];
-        struct ldlm_enqueue_info *einfo = req->rq_async_args.pointer_arg[2];
+        struct mdc_enqueue_args  *ma;
+        struct md_enqueue_info   *minfo;
+        struct ldlm_enqueue_info *einfo;
+        struct obd_export        *exp;
         struct lookup_intent     *it;
         struct lustre_handle     *lockh;
         struct obd_device        *obddev;
         int                       flags = LDLM_FL_HAS_INTENT;
         ENTRY;
 
+        ma = (struct mdc_enqueue_args *)&req->rq_async_args;
+        minfo = ma->ma_mi;
+        einfo = ma->ma_ei;
+
+        exp   = minfo->mi_exp;
         it    = &minfo->mi_it;
         lockh = &minfo->mi_lockh;
 
@@ -868,6 +874,7 @@ int mdc_intent_getattr_async(struct obd_export *exp,
         ldlm_policy_data_t       policy = {
                                         .l_inodebits = { MDS_INODELOCK_LOOKUP }
                                  };
+        struct mdc_enqueue_args *aa;
         int                      rc;
         int                      flags = LDLM_FL_HAS_INTENT;
         ENTRY;
@@ -888,9 +895,10 @@ int mdc_intent_getattr_async(struct obd_export *exp,
                 RETURN(rc);
         }
 
-        req->rq_async_args.pointer_arg[0] = exp;
-        req->rq_async_args.pointer_arg[1] = minfo;
-        req->rq_async_args.pointer_arg[2] = einfo;
+        CLASSERT(sizeof(*aa) < sizeof(req->rq_async_args));
+        aa = (struct mdc_enqueue_args *)&req->rq_async_args;
+        aa->ma_mi = minfo;
+        aa->ma_ei = einfo;
         req->rq_interpret_reply = mdc_intent_getattr_async_interpret;
         ptlrpcd_add_req(req);
 
index 26d3ce2..7d70520 100644 (file)
@@ -1830,7 +1830,7 @@ int mds_handle(struct ptlrpc_request *req)
         /* If we're DISCONNECTing, the mds_export_data is already freed */
         if (!rc && lustre_msg_get_opc(req->rq_reqmsg) != MDS_DISCONNECT) {
                 struct mds_export_data *med = &req->rq_export->exp_mds_data;
-                
+
                 /* I don't think last_xid is used for anyway, so I'm not sure
                    if we need to care about last_close_xid here.*/
                 lustre_msg_set_last_xid(req->rq_repmsg,
index 08af2f4..e12d6a0 100644 (file)
@@ -781,7 +781,7 @@ static void reconstruct_reint_create(struct mds_update_record *rec, int offset,
                 mds_export_evict(exp);
                 EXIT;
                 return;
-        }       
+        }
 
         body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
         mds_pack_inode2fid(&body->fid1, child->d_inode);
index 83053ae..34ad584 100644 (file)
@@ -768,6 +768,7 @@ void class_import_put(struct obd_import *import)
 
         EXIT;
 }
+EXPORT_SYMBOL(class_import_put);
 
 void class_import_destroy(struct obd_import *import)
 {
@@ -793,7 +794,6 @@ void class_import_destroy(struct obd_import *import)
         OBD_FREE_RCU(import, sizeof(*import), &import->imp_handle);
         EXIT;
 }
-EXPORT_SYMBOL(class_import_put);
 
 static void init_imp_at(struct imp_at *at) {
         int i;
index 4e9b212..c80e811 100644 (file)
@@ -1507,7 +1507,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
         __u64 whole, frac = 0, units;
         unsigned frac_d = 1;
 
-        if (count > (sizeof(kernbuf) - 1) )
+        if (count > (sizeof(kernbuf) - 1))
                 return -EINVAL;
 
         if (copy_from_user(kernbuf, buffer, count))