diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h
index 1a9071e87bb53c98cc9e1049ebaa104145a8ac3b..a6a7146ea650aeb5609f7781ec358d267a05c2db 100644
--- a/lustre/include/linux/obd.h
+++ b/lustre/include/linux/obd.h
@@ -360,12 +360,19 @@ struct client_obd {
 
         /* debug stuff */
         struct timeval           cl_last_write_time;
-        long                     cl_write_gap_sum;
-        long                     cl_write_gaps;
-        long                     cl_write_num;
-        long                     cl_read_num;
-        long                     cl_cache_wait_num;
-        long                     cl_cache_wait_sum;
+        unsigned long            cl_write_gap_sum;
+        unsigned long            cl_write_gaps;
+        unsigned long            cl_write_num;
+        unsigned long            cl_read_num;
+        unsigned long            cl_cache_wait_num;
+        unsigned long            cl_cache_wait_sum;
+
+        unsigned long            cl_dirty_num;
+        unsigned long            cl_dirty_sum;
+        unsigned long            cl_dirty_av;
+        
+        unsigned long            cl_dirty_dmax;
+        unsigned long            cl_dirty_dmin;
 };
 
 /* Like a client, with some hangers-on.  Keep mc_client_obd first so that we
diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c
index 9fe909510c1a7f0fa67dd76a2e4f8719d2bedd55..c4f5f606421835c538e55c5421887a6a1f42e71c 100644
--- a/lustre/ldlm/ldlm_lib.c
+++ b/lustre/ldlm/ldlm_lib.c
@@ -256,6 +256,7 @@ int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf)
 
         memset(&cli->cl_last_write_time, 0,
                sizeof(cli->cl_last_write_time));
+        
         cli->cl_write_gap_sum = 0;
         cli->cl_write_gaps = 0;
         cli->cl_write_num = 0;
@@ -263,6 +264,12 @@ int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf)
         cli->cl_cache_wait_num = 0;
         cli->cl_cache_wait_sum = 0;
 
+        cli->cl_dirty_num = 0;
+        cli->cl_dirty_sum = 0;
+        cli->cl_dirty_av = 0;
+        cli->cl_dirty_dmax = 0;
+        cli->cl_dirty_dmin = 0;
+
         if (num_physpages >> (20 - PAGE_SHIFT) <= 128) { /* <= 128 MB */
                 cli->cl_max_pages_per_rpc = PTLRPC_MAX_BRW_PAGES / 4;
                 cli->cl_max_rpcs_in_flight = OSC_MAX_RIF_DEFAULT / 4;
@@ -374,28 +381,40 @@ int client_obd_cleanup(struct obd_device *obddev, int flags)
                 symbol_put("mgmtcli_deregister_for_events");
         }
 
-        /* Here we try to drop the security structure after destroy import,
-         * to avoid issue of "sleep in spinlock".
-         */
-        class_import_get(cli->cl_import);
-        class_destroy_import(cli->cl_import);
-        ptlrpcs_import_drop_sec(cli->cl_import);
-        class_import_put(cli->cl_import);
-        cli->cl_import = NULL;
-
         if (cli->cl_write_gaps) {
-                CWARN("%s: (write num: %lu, read num: %lu): %lu write gaps: %lu "
+                CWARN("%s: [writes num: %lu, reads num: %lu]: %lu write gaps: %lu "
                       "av. (usec), %lu total (usec)\n", obddev->obd_name,
                       cli->cl_write_num, cli->cl_read_num, cli->cl_write_gaps,
                       cli->cl_write_gap_sum / cli->cl_write_gaps,
                       cli->cl_write_gap_sum);
         }
+        
         if (cli->cl_cache_wait_num) {
-                CWARN("%s: cache wait num: %lu, cache wait av. %lu (usec)\n",
+                CWARN("%s: [cache waits num: %lu]: cache wait av. %lu (usec)\n",
                       obddev->obd_name, cli->cl_cache_wait_num,
                       cli->cl_cache_wait_sum / cli->cl_cache_wait_num);
         }
 
+        if (cli->cl_dirty_av) {
+                CWARN("%s: pipe loading av. %lu (b), max pipe space %lu (b), pipe "
+                      "loading ratio %lu%%\n", obddev->obd_name, cli->cl_dirty_av,
+                      cli->cl_dirty_max, (cli->cl_dirty_av * 100) / cli->cl_dirty_max);
+        }
+
+        if (cli->cl_dirty_dmax) {
+                CWARN("%s: pipe dirty max %lu (b), pipe dirty min %lu (b)\n",
+                      obddev->obd_name, cli->cl_dirty_dmax, cli->cl_dirty_dmin);
+        }
+
+        /* Here we try to drop the security structure after destroy import,
+         * to avoid issue of "sleep in spinlock".
+         */
+        class_import_get(cli->cl_import);
+        class_destroy_import(cli->cl_import);
+        ptlrpcs_import_drop_sec(cli->cl_import);
+        class_import_put(cli->cl_import);
+        cli->cl_import = NULL;
+
         ldlm_put_ref(flags & OBD_OPT_FORCE);
         RETURN(0);
 }
diff --git a/lustre/llite/file.c b/lustre/llite/file.c
index 494b562da25a0b79d1effd3c7df16437c72e70f7..8b3e32ced5ff6c8b7b0a503e990cd754860e6121 100644
--- a/lustre/llite/file.c
+++ b/lustre/llite/file.c
@@ -200,7 +200,6 @@ int ll_md_real_close(struct obd_export *md_exp,
         och = *och_p;
         *och_p = NULL;
 
-
         up(&lli->lli_och_sem);
 
         /*
diff --git a/lustre/llite/llite_capa.c b/lustre/llite/llite_capa.c
index a19ac2f55fdb32c84d9e2047a21af60e4584a623..717f6bde060b976b4eeb9f33add63f83140fb86d 100644
--- a/lustre/llite/llite_capa.c
+++ b/lustre/llite/llite_capa.c
@@ -32,8 +32,9 @@
 #include <linux/lustre_lite.h>
 #include "llite_internal.h"
 
-static struct ptlrpc_thread ll_capa_thread;
 static struct list_head *ll_capa_list = &capa_list[CLIENT_CAPA];
+static struct ptlrpc_thread capa_thread;
+
 static struct thread_ctl {
         struct completion ctl_starting;
         struct completion ctl_finishing;
@@ -66,7 +67,7 @@ static inline int have_expired_capa(void)
 
 static int inline ll_capa_check_stop(void)
 {
-        return (ll_capa_thread.t_flags & SVC_STOPPING) ? 1: 0;
+        return (capa_thread.t_flags & SVC_STOPPING) ? 1: 0;
 }
 
 static int ll_renew_capa(struct obd_capa *ocapa)
@@ -89,7 +90,7 @@ static int ll_renew_capa(struct obd_capa *ocapa)
         RETURN(rc);
 }
 
-static int ll_capa_thread_main(void *arg)
+static int ll_capa_thread(void *arg)
 {
         struct thread_ctl *ctl = arg;
         unsigned long flags;
@@ -110,7 +111,7 @@ static int ll_capa_thread_main(void *arg)
          * letting starting function know, that we are ready and control may be
          * returned.
          */
-        ll_capa_thread.t_flags = SVC_RUNNING;
+        capa_thread.t_flags = SVC_RUNNING;
         complete(&ctl->ctl_starting);
 
         while (1) {
@@ -118,7 +119,7 @@ static int ll_capa_thread_main(void *arg)
                 struct obd_capa *ocapa, *next = NULL;
                 unsigned long expiry, sleep = CAPA_PRE_EXPIRY;
 
-                l_wait_event(ll_capa_thread.t_ctl_waitq,
+                l_wait_event(capa_thread.t_ctl_waitq,
                              (have_expired_capa() || ll_capa_check_stop()),
                              &lwi);
 
@@ -154,7 +155,7 @@ static int ll_capa_thread_main(void *arg)
                 schedule_timeout(sleep * HZ);
         }
 
-        ll_capa_thread.t_flags = SVC_STOPPED;
+        capa_thread.t_flags = SVC_STOPPED;
 
         /* this is SMP-safe way to finish thread. */
         complete_and_exit(&ctl->ctl_finishing, 0);
@@ -165,21 +166,21 @@ static int ll_capa_thread_main(void *arg)
 void ll_capa_timer_callback(unsigned long unused)
 {
         ENTRY;
-        wake_up(&ll_capa_thread.t_ctl_waitq);
+        wake_up(&capa_thread.t_ctl_waitq);
         EXIT;
 }
 
-int ll_capa_start_thread(void)
+int ll_capa_thread_start(void)
 {
         int rc;
         ENTRY;
 
-        LASSERT(ll_capa_thread.t_flags == 0);
+        LASSERT(capa_thread.t_flags == 0);
         init_completion(&ll_capa_ctl.ctl_starting);
         init_completion(&ll_capa_ctl.ctl_finishing);
-        init_waitqueue_head(&ll_capa_thread.t_ctl_waitq);
+        init_waitqueue_head(&capa_thread.t_ctl_waitq);
 
-        rc = kernel_thread(ll_capa_thread_main, &ll_capa_ctl,
+        rc = kernel_thread(ll_capa_thread, &ll_capa_ctl,
                            (CLONE_VM | CLONE_FILES));
         if (rc < 0) {
                 CERROR("cannot start expired capa thread, "
@@ -187,19 +188,19 @@ int ll_capa_start_thread(void)
                 RETURN(rc);
         }
         wait_for_completion(&ll_capa_ctl.ctl_starting);
-        LASSERT(ll_capa_thread.t_flags == SVC_RUNNING);
+        LASSERT(capa_thread.t_flags == SVC_RUNNING);
         RETURN(0);
 }
 
-void ll_capa_stop_thread(void)
+void ll_capa_thread_stop(void)
 {
         ENTRY;
 
-        ll_capa_thread.t_flags = SVC_STOPPING;
-        wake_up(&ll_capa_thread.t_ctl_waitq);
+        capa_thread.t_flags = SVC_STOPPING;
+        wake_up(&capa_thread.t_ctl_waitq);
         wait_for_completion(&ll_capa_ctl.ctl_finishing);
-        LASSERT(ll_capa_thread.t_flags == SVC_STOPPED);
-        ll_capa_thread.t_flags = 0;
+        LASSERT(capa_thread.t_flags == SVC_STOPPED);
+        capa_thread.t_flags = 0;
 
         EXIT;
 }
diff --git a/lustre/llite/llite_gns.c b/lustre/llite/llite_gns.c
index 4109a083d1cdbfb23fdc60b9c2ca1b091c98d089..d2bdb1521eb54d1183da5b384f31e6a5e3a53892 100644
--- a/lustre/llite/llite_gns.c
+++ b/lustre/llite/llite_gns.c
@@ -522,7 +522,7 @@ void ll_gns_del_timer(struct ll_sb_info *sbi)
  * starts GNS control thread and waits for a signal it is up and work may be
  * continued.
  */
-int ll_gns_start_thread(void)
+int ll_gns_thread_start(void)
 {
         int rc;
         ENTRY;
@@ -545,7 +545,7 @@ int ll_gns_start_thread(void)
 }
 
 /* stops GNS control thread and waits its actual stop. */
-void ll_gns_stop_thread(void)
+void ll_gns_thread_stop(void)
 {
         ENTRY;
         gns_thread.t_flags = SVC_STOPPING;
diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h
index 1826223415a00f6bbf53581a18ec539e73db19de..dcf501bb3dfbd80dce9239e93d655fd7c5faf9b2 100644
--- a/lustre/llite/llite_internal.h
+++ b/lustre/llite/llite_internal.h
@@ -355,11 +355,12 @@ void ll_stime_record(struct ll_sb_info *sbi, struct timeval *start,
                      struct obd_service_time *stime);
 
 /* llite_capa.c */
+int ll_capa_thread_start(void);
+void ll_capa_thread_stop(void);
+
 void ll_capa_timer_callback(unsigned long unused);
-int ll_capa_start_thread(void);
-void ll_capa_stop_thread(void);
 int ll_set_och_capa(struct inode *inode, struct lookup_intent *it,
-                           struct obd_client_handle *och);
+                    struct obd_client_handle *och);
 
 /* llite/dcache.c */
 void ll_intent_drop_lock(struct lookup_intent *);
@@ -375,8 +376,8 @@ int revalidate_it_finish(struct ptlrpc_request *request, int offset,
 
 
 /* llite/llite_gns.c */
-int ll_gns_start_thread(void);
-void ll_gns_stop_thread(void);
+int ll_gns_thread_start(void);
+void ll_gns_thread_stop(void);
 
 int ll_gns_mount_object(struct dentry *dentry,
                         struct vfsmount *mnt);
diff --git a/lustre/llite/super.c b/lustre/llite/super.c
index 1f9a484931cb383c27ff7cece2fdc5612edaac6f..d5d1be4ae426943c61160142075014c011e83973 100644
--- a/lustre/llite/super.c
+++ b/lustre/llite/super.c
@@ -129,7 +129,7 @@ static int __init init_lustre_lite(void)
                 goto out;
         cleanup = 2;
 
-        rc = ll_gns_start_thread();
+        rc = ll_gns_thread_start();
         if (rc)
                 goto out;
 
@@ -137,7 +137,7 @@ static int __init init_lustre_lite(void)
         ll_capa_timer.data = 0;
         init_timer(&ll_capa_timer);        
 
-        rc = ll_capa_start_thread();
+        rc = ll_capa_thread_start();
         if (rc)
                 goto out;
 
@@ -162,8 +162,8 @@ static void __exit exit_lustre_lite(void)
         unregister_filesystem(&lustre_fs_type);
 
         del_timer(&ll_capa_timer);
-        ll_capa_stop_thread();
-        ll_gns_stop_thread();
+        ll_capa_thread_stop();
+        ll_gns_thread_stop();
 
         LASSERTF(kmem_cache_destroy(ll_file_data_slab) == 0,
                  "couldn't destroy ll_file_data slab\n");
diff --git a/lustre/llite/super25.c b/lustre/llite/super25.c
index e758f21a5ed09d3997e1a4874f9bff4d2dac3ede..0d55f057c67f93ea05a932892db80d2a764f91b7 100644
--- a/lustre/llite/super25.c
+++ b/lustre/llite/super25.c
@@ -175,7 +175,7 @@ static int __init init_lustre_lite(void)
                 goto out;
         cleanup = 2;
 
-        rc = ll_gns_start_thread();
+        rc = ll_gns_thread_start();
         if (rc)
                 goto out;
 
@@ -183,7 +183,7 @@ static int __init init_lustre_lite(void)
         ll_capa_timer.data = 0;
         init_timer(&ll_capa_timer);        
 
-        rc = ll_capa_start_thread();
+        rc = ll_capa_thread_start();
         if (rc)
                 goto out;
 
@@ -206,8 +206,8 @@ static void __exit exit_lustre_lite(void)
         unregister_filesystem(&lustre_lite_fs_type);
 
         del_timer(&ll_capa_timer);
-        ll_capa_stop_thread();
-        ll_gns_stop_thread();
+        ll_capa_thread_stop();
+        ll_gns_thread_stop();
         ll_destroy_inodecache();
         
         LASSERTF(kmem_cache_destroy(ll_file_data_slab) == 0,
diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c
index 529b06474a0553b3d3d5b39168184d609a6ce416..b2463ac83ae019aa829b369c876ee006ad1c8b03 100644
--- a/lustre/osc/osc_request.c
+++ b/lustre/osc/osc_request.c
@@ -1314,6 +1314,7 @@ static int brw_interpret_oap(struct ptlrpc_request *request,
         CDEBUG(D_INODE, "request %p aa %p rc %d\n", request, aa, rc);
 
         cli = aa->aa_cli;
+
         /* in failout recovery we ignore writeback failure and want
          * to just tell llite to unlock the page and continue */
         if (request->rq_reqmsg->opc == OST_WRITE &&
@@ -1333,8 +1334,6 @@ static int brw_interpret_oap(struct ptlrpc_request *request,
                 lprocfs_stime_record(&cli->cl_read_stime, &now,
                                      &request->rq_rpcd_start);
 
-
-
         /* We need to decrement before osc_ap_completion->osc_wake_cache_waiters
          * is called so we know whether to go to sync BRWs or wait for more
          * RPCs to complete */
@@ -1870,6 +1869,24 @@ static int osc_enter_cache(struct client_obd *cli, struct lov_oinfo *loi,
         if (cli->cl_dirty_max < PAGE_SIZE)
                 return(-EDQUOT);
 
+        if (~0ul - cli->cl_dirty_sum <= cli->cl_dirty) {
+                cli->cl_dirty_av = (cli->cl_dirty_av +
+                                    (cli->cl_dirty_sum / cli->cl_dirty_num)) / 2;
+                cli->cl_dirty_num = 0;
+                cli->cl_dirty_sum = 0;
+        } else {
+                if (cli->cl_dirty_num)
+                        cli->cl_dirty_av = (cli->cl_dirty_sum / cli->cl_dirty_num);
+        }
+        
+        cli->cl_dirty_num++;
+        cli->cl_dirty_sum += cli->cl_dirty;
+
+        if (cli->cl_dirty > cli->cl_dirty_dmax)
+                cli->cl_dirty_dmax = cli->cl_dirty;
+        if (cli->cl_dirty < cli->cl_dirty_dmin)
+                cli->cl_dirty_dmin = cli->cl_dirty;
+
         /* Hopefully normal case - cache space and write credits available */
         if (cli->cl_dirty + PAGE_SIZE <= cli->cl_dirty_max &&
             cli->cl_avail_grant >= PAGE_SIZE) {
@@ -1924,6 +1941,24 @@ static void osc_exit_cache(struct client_obd *cli, struct osc_async_page *oap,
                 return;
         }
 
+        if (~0ul - cli->cl_dirty_sum <= cli->cl_dirty) {
+                cli->cl_dirty_av = (cli->cl_dirty_av +
+                                    (cli->cl_dirty_sum / cli->cl_dirty_num)) / 2;
+                cli->cl_dirty_num = 0;
+                cli->cl_dirty_sum = 0;
+        } else {
+                if (cli->cl_dirty_num)
+                        cli->cl_dirty_av = (cli->cl_dirty_sum / cli->cl_dirty_num);
+        }
+        
+        cli->cl_dirty_num++;
+        cli->cl_dirty_sum += cli->cl_dirty;
+
+        if (cli->cl_dirty > cli->cl_dirty_dmax)
+                cli->cl_dirty_dmax = cli->cl_dirty;
+        if (cli->cl_dirty < cli->cl_dirty_dmin)
+                cli->cl_dirty_dmin = cli->cl_dirty;
+
         oap->oap_brw_flags &= ~OBD_BRW_FROM_GRANT;
         cli->cl_dirty -= PAGE_SIZE;
         if (!sent) {