diff --git a/lustre/include/lustre_export.h b/lustre/include/lustre_export.h
index cbe0074166c7c375c7198eaf12c8e2275e433e84..7ece7a25bfe96d2045e19398eb1a46eda17b0081 100644
--- a/lustre/include/lustre_export.h
+++ b/lustre/include/lustre_export.h
@@ -82,6 +82,7 @@ struct obd_export {
         struct obd_import        *exp_imp_reverse; /* to make RPCs backwards */
         struct nid_stat          *exp_nid_stats;
         struct lprocfs_stats     *exp_ldlm_stats;
+        struct lprocfs_stats     *exp_ops_stats;
         struct ptlrpc_connection *exp_connection;
         __u32                     exp_conn_cnt;
         struct ldlm_export_data   exp_ldlm_data;
diff --git a/lustre/mgc/Makefile.in b/lustre/mgc/Makefile.in
index 2d7cad5c8cfd2fbe659e45da65e2302a492bb810..8adca32e590a1a63e977e6aec8508e9e4986c224 100644
--- a/lustre/mgc/Makefile.in
+++ b/lustre/mgc/Makefile.in
@@ -1,4 +1,4 @@
 MODULES := mgc
-mgc-objs := mgc_request.o
+mgc-objs := mgc_request.o lproc_mgc.o
 
 @INCLUDE_RULES@
diff --git a/lustre/mgc/lproc_mgc.c b/lustre/mgc/lproc_mgc.c
new file mode 100644
index 0000000000000000000000000000000000000000..1b1fd1289d3e6c1f70d7cc8df331232efe45233c
--- /dev/null
+++ b/lustre/mgc/lproc_mgc.c
@@ -0,0 +1,53 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2002 Cluster File Systems, Inc.
+ *
+ * This file is part of the Lustre file system, http://www.lustre.org
+ * Lustre is a trademark of Cluster File Systems, Inc.
+ *
+ * You may have signed or agreed to another license before downloading
+ * this software.  If so, you are bound by the terms and conditions
+ * of that agreement, and the following does not apply to you.  See the
+ * LICENSE file included with this distribution for more information.
+ *
+ * If you did not agree to a different license, then this copy of Lustre
+ * is open source software; you can redistribute it and/or  modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In either case, Lustre is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * license text for more details.
+ *
+ */
+#define DEBUG_SUBSYSTEM S_CLASS
+
+#include <linux/version.h>
+#include <linux/vfs.h>
+#include <obd_class.h>
+#include <lprocfs_status.h>
+
+#ifdef LPROCFS
+
+static struct lprocfs_vars lprocfs_mgc_obd_vars[] = {
+        { "uuid",            lprocfs_rd_uuid,          0, 0 },
+        { "ping",            0, lprocfs_wr_ping,          0 },
+        { "connect_flags",   lprocfs_rd_connect_flags, 0, 0 },
+        { "mgs_server_uuid", lprocfs_rd_server_uuid,   0, 0 },
+        { "mgs_conn_uuid",   lprocfs_rd_conn_uuid,     0, 0 },
+        { 0 }
+};
+
+static struct lprocfs_vars lprocfs_mgc_module_vars[] = {
+        { "num_refs",        lprocfs_rd_numrefs,       0, 0 },
+        { 0 }
+};
+
+void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars)
+{
+        lvars->module_vars = lprocfs_mgc_module_vars;
+        lvars->obd_vars    = lprocfs_mgc_obd_vars;
+}
+#endif /* LPROCFS */
diff --git a/lustre/mgc/mgc_internal.h b/lustre/mgc/mgc_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..1edf122e3e867a95b950c518b33d8b266b07cd05
--- /dev/null
+++ b/lustre/mgc/mgc_internal.h
@@ -0,0 +1,24 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+
+#ifndef _MGC_INTERNAL_H
+#define _MGC_INTERNAL_H
+
+#include <libcfs/kp30.h>
+#include <lustre/lustre_idl.h>
+#include <lustre_lib.h>
+#include <lustre_dlm.h>
+#include <lustre_log.h>
+#include <lustre_export.h>
+
+#ifdef LPROCFS
+void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars);
+#else
+static void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars)
+{
+        memset(lvars, 0, sizeof(*lvars));
+}
+#endif  /* LPROCFS */
+
+#endif  /* _MGC_INTERNAL_H */
diff --git a/lustre/mgc/mgc_request.c b/lustre/mgc/mgc_request.c
index 2b3ae04b00e056726bfed09765ffb38f8dd0dcd9..54b39c3c1aae659d8c7ac2572689ffdca91c9c7f 100644
--- a/lustre/mgc/mgc_request.c
+++ b/lustre/mgc/mgc_request.c
@@ -41,9 +41,11 @@
 
 #include <obd_class.h>
 #include <lustre_dlm.h>
+#include <lprocfs_status.h>
 #include <lustre_log.h>
 #include <lustre_fsfilt.h>
 #include <lustre_disk.h>
+#include "mgc_internal.h"
 
 static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id)
 {
@@ -493,6 +495,7 @@ static int mgc_cleanup(struct obd_device *obd)
                 /* Only for the last mgc */
                 class_del_profiles();
 
+        lprocfs_obd_cleanup(obd);
         ptlrpcd_decref();
 
         rc = client_obd_cleanup(obd);
@@ -501,6 +504,7 @@ static int mgc_cleanup(struct obd_device *obd)
 
 static int mgc_setup(struct obd_device *obd, obd_count len, void *buf)
 {
+        struct lprocfs_static_vars lvars;
         int rc;
         ENTRY;
 
@@ -516,6 +520,9 @@ static int mgc_setup(struct obd_device *obd, obd_count len, void *buf)
                 GOTO(err_cleanup, rc);
         }
 
+        lprocfs_mgc_init_vars(&lvars);
+        lprocfs_obd_setup(obd, lvars.obd_vars);
+
         spin_lock(&config_list_lock);
         atomic_inc(&mgc_count);
         if (atomic_read(&mgc_count) == 1) {
diff --git a/lustre/mgs/lproc_mgs.c b/lustre/mgs/lproc_mgs.c
index 5ccb8a86d6262fbde7ad8985dcd20515e9d3a74e..66b2825b85d3c12d4cd5ee17a88c1c7428eae75b 100644
--- a/lustre/mgs/lproc_mgs.c
+++ b/lustre/mgs/lproc_mgs.c
@@ -87,10 +87,31 @@ int lproc_mgs_setup(struct obd_device *obd)
         rc = lprocfs_obd_seq_create(obd, "filesystems", 0444,
                                     &mgs_fs_fops, obd);
         mgs->mgs_proc_live = proc_mkdir("live", obd->obd_proc_entry);
+        obd->obd_proc_exports_entry = proc_mkdir("exports",
+                                                 obd->obd_proc_entry);
 
         return rc;
 }
 
+int lproc_mgs_cleanup(struct obd_device *obd)
+{
+        struct mgs_obd *mgs = &obd->u.mgs;
+
+        if (!obd)
+                return -EINVAL;
+
+        if (mgs->mgs_proc_live) {
+                /* Should be no live entries */
+                LASSERT(mgs->mgs_proc_live->subdir == NULL);
+                lprocfs_remove(&mgs->mgs_proc_live);
+                mgs->mgs_proc_live = NULL;
+        }
+        lprocfs_free_per_client_stats(obd);
+        lprocfs_free_obd_stats(obd);
+
+        return lprocfs_obd_cleanup(obd);
+}
+
 static int mgs_live_seq_show(struct seq_file *seq, void *v) 
 {
         struct fs_db *fsdb = seq->private;
@@ -142,6 +163,7 @@ struct lprocfs_vars lprocfs_mgs_obd_vars[] = {
         { "fstype",          lprocfs_rd_fstype,      0, 0 },
         { "mntdev",          lprocfs_mgs_rd_mntdev,  0, 0 },
         { "num_exports",     lprocfs_rd_num_exports, 0, 0 },
+        { "evict_client",    0, lprocfs_wr_evict_client, 0 },
         { 0 }
 };
 
@@ -149,6 +171,23 @@ struct lprocfs_vars lprocfs_mgs_module_vars[] = {
         { 0 }
 };
 
+void mgs_counter_incr(struct obd_export *exp, int opcode)
+{
+        lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode);
+        lprocfs_counter_incr(exp->exp_ops_stats, opcode);
+}
+
+void mgs_stats_counter_init(struct lprocfs_stats *stats)
+{
+        lprocfs_counter_init(stats, LPROC_MGS_CONNECT, 0, "connect", "reqs");
+        lprocfs_counter_init(stats, LPROC_MGS_DISCONNECT, 0, "disconnect",
+                             "reqs");
+        lprocfs_counter_init(stats, LPROC_MGS_EXCEPTION, 0, "exception",
+                             "reqs");
+        lprocfs_counter_init(stats, LPROC_MGS_TARGET_REG, 0, "tgtreg", "reqs");
+        lprocfs_counter_init(stats, LPROC_MGS_TARGET_DEL, 0, "tgtdel", "reqs");
+}
+
 void lprocfs_mgs_init_vars(struct lprocfs_static_vars *lvars)
 {
     lvars->module_vars  = lprocfs_mgs_module_vars;
diff --git a/lustre/mgs/mgs_fs.c b/lustre/mgs/mgs_fs.c
index e97a33502ff835aa45a75f4d01c3cc90a0f99a05..51abb0e03fc44a7828818d3786c7c5e6baa5788a 100644
--- a/lustre/mgs/mgs_fs.c
+++ b/lustre/mgs/mgs_fs.c
@@ -42,6 +42,44 @@
 #include <libcfs/list.h>
 #include "mgs_internal.h"
 
+
+static int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp)
+{
+        int rc, num_stats, newnid;
+
+        rc = lprocfs_exp_setup(exp, 0, &newnid);
+        if (rc)
+                return rc;
+
+        if (newnid) {
+                num_stats = (sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
+                             LPROC_MGS_LAST - 1;
+                exp->exp_ops_stats = lprocfs_alloc_stats(num_stats,
+                                                         LPROCFS_STATS_FLAG_NOPERCPU);
+                if (exp->exp_ops_stats == NULL)
+                        return -ENOMEM;
+                lprocfs_init_ops_stats(LPROC_MGS_LAST, exp->exp_ops_stats);
+                mgs_stats_counter_init(exp->exp_ops_stats);
+                lprocfs_register_stats(exp->exp_nid_stats->nid_proc, "stats", exp->exp_ops_stats);
+        }
+        return 0;
+}
+
+/* Add client export data to the MGS.  This data is currently NOT stored on
+ * disk in the last_rcvd file or anywhere else.  In the event of a MGS
+ * crash all connections are treated as new connections.
+ */
+int mgs_client_add(struct obd_device *obd, struct obd_export *exp)
+{
+        return mgs_export_stats_init(obd, exp);
+}
+
+/* Remove client export data from the MGS */
+int mgs_client_free(struct obd_export *exp)
+{
+        return lprocfs_exp_cleanup(exp);
+}
+
 /* Same as mds_fid2dentry */
 /* Look up an entry by inode number. */
 /* this function ONLY returns valid dget'd dentries with an initialized inode
diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c
index 79d43bd5a2d76fb91105e910f7b6f31ae020d0d8..6b7ba3ad496b54bca7ce0447b2b2a00fd4bc5552 100644
--- a/lustre/mgs/mgs_handler.c
+++ b/lustre/mgs/mgs_handler.c
@@ -65,12 +65,16 @@ static int mgs_connect(struct lustre_handle *conn, struct obd_device *obd,
         exp = class_conn2export(conn);
         LASSERT(exp);
 
+        mgs_counter_incr(exp, LPROC_MGS_CONNECT);
+
         if (data != NULL) {
                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
                 exp->exp_connect_flags = data->ocd_connect_flags;
                 data->ocd_version = LUSTRE_VERSION_CODE;
         }
 
+        rc = mgs_client_add(obd, exp);
+
         if (rc) {
                 class_disconnect(exp);
         } else {
@@ -86,7 +90,9 @@ static int mgs_disconnect(struct obd_export *exp)
         ENTRY;
 
         LASSERT(exp);
+
         class_export_get(exp);
+        mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
 
         /* Disconnect early so that clients can't keep using export */
         rc = class_disconnect(exp);
@@ -259,10 +265,7 @@ static int mgs_cleanup(struct obd_device *obd)
         ptlrpc_unregister_service(mgs->mgs_service);
 
         mgs_cleanup_fsdb_list(obd);
-
-        lprocfs_obd_cleanup(obd);
-        mgs->mgs_proc_live = NULL;
-
+        lproc_mgs_cleanup(obd);
         mgs_fs_cleanup(obd);
 
         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
@@ -350,6 +353,8 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req)
         int rc = 0, lockrc;
         ENTRY;
 
+        mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
+
         mti = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*mti),
                                  lustre_swab_mgs_target_info);
         
@@ -499,6 +504,23 @@ static int mgs_set_info_rpc(struct ptlrpc_request *req)
         RETURN(rc);
 }
 
+/* Called whenever a target cleans up. */
+/* XXX - Currently unused */
+static int mgs_handle_target_del(struct ptlrpc_request *req)
+{
+        ENTRY;
+        mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
+        RETURN(0);
+}
+
+/* XXX - Currently unused */
+static int mgs_handle_exception(struct ptlrpc_request *req)
+{
+        ENTRY;
+        mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
+        RETURN(0);
+}
+
 int mgs_handle(struct ptlrpc_request *req)
 {
         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
@@ -534,13 +556,17 @@ int mgs_handle(struct ptlrpc_request *req)
                 rc = target_handle_disconnect(req);
                 req->rq_status = rc;            /* superfluous? */
                 break;
+        case MGS_EXCEPTION:
+                DEBUG_REQ(D_MGS, req, "exception");
+                rc = mgs_handle_exception(req);
+                break;
         case MGS_TARGET_REG:
                 DEBUG_REQ(D_MGS, req, "target add");
                 rc = mgs_handle_target_reg(req);
                 break;
         case MGS_TARGET_DEL:
                 DEBUG_REQ(D_MGS, req, "target del");
-                //rc = mgs_handle_target_del(req);
+                rc = mgs_handle_target_del(req);
                 break;
         case MGS_SET_INFO:
                 rc = mgs_set_info_rpc(req);
@@ -608,6 +634,7 @@ static inline int mgs_destroy_export(struct obd_export *exp)
         ENTRY;
 
         target_destroy_export(exp);
+        mgs_client_free(exp);
 
         RETURN(0);
 }
diff --git a/lustre/mgs/mgs_internal.h b/lustre/mgs/mgs_internal.h
index f3f82efcb1bf9bf8cddc6b768598decec8b20c70..5fbe4488ce215e8b428ddea9272237da6d0e7ff6 100644
--- a/lustre/mgs/mgs_internal.h
+++ b/lustre/mgs/mgs_internal.h
@@ -51,6 +51,8 @@ int mgs_erase_logs(struct obd_device *obd, char *fsname);
 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname);
 
 /* mgs_fs.c */
+int mgs_client_add(struct obd_device *obd, struct obd_export *exp);
+int mgs_client_free(struct obd_export *exp);
 int mgs_fs_setup(struct obd_device *obd, struct vfsmount *mnt);
 int mgs_fs_cleanup(struct obd_device *obddev);
 
@@ -58,15 +60,18 @@ int mgs_fs_cleanup(struct obd_device *obddev);
 
 #ifdef LPROCFS
 int lproc_mgs_setup(struct obd_device *dev);
+int lproc_mgs_cleanup(struct obd_device *obd);
 int lproc_mgs_add_live(struct obd_device *obd, struct fs_db *fsdb);
 int lproc_mgs_del_live(struct obd_device *obd, struct fs_db *fsdb);
 void lprocfs_mgs_init_vars(struct lprocfs_static_vars *lvars);
 #else
 static inline int lproc_mgs_setup(struct obd_device *dev) 
 {return 0;}
-static int lproc_mgs_add_live(struct obd_device *obd, struct fs_db *fsdb)
+static inline int lproc_mgs_cleanup(struct obd_device *obd)
 {return 0;}
-static int lproc_mgs_del_live(struct obd_device *obd, struct fs_db *fsdb)
+static inline int lproc_mgs_add_live(struct obd_device *obd, struct fs_db *fsdb)
+{return 0;}
+static inline int lproc_mgs_del_live(struct obd_device *obd, struct fs_db *fsdb)
 {return 0;}
 static void lprocfs_mgs_init_vars(struct lprocfs_static_vars *lvars)
 {
@@ -74,6 +79,17 @@ static void lprocfs_mgs_init_vars(struct lprocfs_static_vars *lvars)
 }
 #endif
 
+/* mgs/lproc_mgs.c */
+enum {
+        LPROC_MGS_CONNECT = 0,
+        LPROC_MGS_DISCONNECT,
+        LPROC_MGS_EXCEPTION,
+        LPROC_MGS_TARGET_REG,
+        LPROC_MGS_TARGET_DEL,
+        LPROC_MGS_LAST
+};
+void mgs_counter_incr(struct obd_export *exp, int opcode);
+void mgs_stats_counter_init(struct lprocfs_stats *stats);
 
 #endif /* _MGS_INTERNAL_H */
 
diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c
index 30927e881f84e98b8853bab4eafdc143b6866e30..7f3cea3232d8627e7f7092a495bb63ebdd8cb6db 100644
--- a/lustre/obdclass/lprocfs_status.c
+++ b/lustre/obdclass/lprocfs_status.c
@@ -1349,6 +1349,8 @@ int lprocfs_exp_cleanup(struct obd_export *exp)
         CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
 
         exp->exp_nid_stats = NULL;
+        lprocfs_free_stats(&exp->exp_ldlm_stats);
+        lprocfs_free_stats(&exp->exp_ops_stats);
 
         return 0;
 }