diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index 99819676425ae701929ec705ecb2841263d9621a..9ace837dd4a05b8260b7c71444f92f9a181a383a 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -46,6 +46,12 @@ Details    : The ldiskfs mballoc3 code was using a __u16 to store the group
 	     number, but with 8TB+ filesystems there are more than 65536
 	     groups, causing an oops.
 
+Severity   : normal
+Bugzilla   : 15576
+Description: Resolve device initialization race
+Details    : Prevent proc handler from accessing devices added to the
+             obd_devs array but yet be intialized.
+
 Severity   : enhancement
 Bugzilla   : 15308
 Description: Update to SLES10 SP2 kernel-2.6.16.60-0.23.
diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c
index 0834dbfa679ee0953a8c254966223bd0d9b6d672..f82c9babee932469537dd7da92d2892813d8b122 100644
--- a/lustre/obdclass/genops.c
+++ b/lustre/obdclass/genops.c
@@ -86,7 +86,7 @@ static void obd_device_free(struct obd_device *obd)
                  "%08x != %08x\n", obd, obd->obd_magic, OBD_DEVICE_MAGIC);
         if (obd->obd_namespace != NULL) {
                 CERROR("obd %p: namespace %p was not properly cleaned up "
-                       "(obd_force=%d)!\n", 
+                       "(obd_force=%d)!\n",
                        obd, obd->obd_namespace, obd->obd_force);
                 LBUG();
         }
@@ -118,7 +118,7 @@ struct obd_type *class_get_type(const char *name)
 #ifdef CONFIG_KMOD
         if (!type) {
                 const char *modname = name;
-                if (strcmp(modname, LUSTRE_MDT_NAME) == 0) 
+                if (strcmp(modname, LUSTRE_MDT_NAME) == 0)
                         modname = LUSTRE_MDS_NAME;
                 if (!request_module(modname)) {
                         CDEBUG(D_INFO, "Loaded module '%s'\n", modname);
@@ -218,7 +218,7 @@ int class_unregister_type(const char *name)
                 RETURN(-EBUSY);
         }
 
-        if (type->typ_procroot) 
+        if (type->typ_procroot)
                 lprocfs_remove(&type->typ_procroot);
 
         spin_lock(&obd_types_lock);
@@ -231,6 +231,17 @@ int class_unregister_type(const char *name)
         RETURN(0);
 } /* class_unregister_type */
 
+/**
+ * Create a new obd device.
+ *
+ * Find an empty slot in ::obd_devs[], create a new obd device in it.
+ *
+ * \param typename [in] obd device type string.
+ * \param name     [in] obd device name.
+ *
+ * \retval NULL if create fails, otherwise return the obd device
+ *         pointer created.
+ */
 struct obd_device *class_newdev(const char *type_name, const char *name)
 {
         struct obd_device *result = NULL;
@@ -239,7 +250,7 @@ struct obd_device *class_newdev(const char *type_name, const char *name)
         int i;
         int new_obd_minor = 0;
 
-        if (strlen(name) > MAX_OBD_NAME) {
+        if (strlen(name) >= MAX_OBD_NAME) {
                 CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME);
                 RETURN(ERR_PTR(-EINVAL));
         }
@@ -251,7 +262,7 @@ struct obd_device *class_newdev(const char *type_name, const char *name)
         }
 
         newdev = obd_device_alloc();
-        if (newdev == NULL) { 
+        if (newdev == NULL) {
                 class_put_type(type);
                 RETURN(ERR_PTR(-ENOMEM));
         }
@@ -281,18 +292,19 @@ struct obd_device *class_newdev(const char *type_name, const char *name)
                         result->obd_minor = i;
                         new_obd_minor = i;
                         result->obd_type = type;
-                        memcpy(result->obd_name, name, strlen(name));
+                        strncpy(result->obd_name, name,
+                                sizeof(result->obd_name) - 1);
                         obd_devs[i] = result;
                 }
         }
         spin_unlock(&obd_dev_lock);
-        
+
         if (result == NULL && i >= class_devno_max()) {
                 CERROR("all %u OBD devices used, increase MAX_OBD_DEVICES\n",
                        class_devno_max());
                 result = ERR_PTR(-EOVERFLOW);
         }
-        
+
         if (IS_ERR(result)) {
                 obd_device_free(newdev);
                 class_put_type(type);
@@ -385,15 +397,22 @@ struct obd_device *class_uuid2obd(struct obd_uuid *uuid)
         return class_num2obd(dev);
 }
 
+/**
+ * Get obd device from ::obd_devs[]
+ *
+ * \param num [in] array index
+ *
+ * \retval NULL if ::obd_devs[\a num] does not contains an obd device
+ *         otherwise return the obd device there.
+ */
 struct obd_device *class_num2obd(int num)
 {
         struct obd_device *obd = NULL;
 
         if (num < class_devno_max()) {
                 obd = obd_devs[num];
-                if (obd == NULL) {
+                if (obd == NULL)
                         return NULL;
-                }
 
                 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
                          "%p obd_magic %08x != %08x\n",
@@ -537,7 +556,7 @@ int obd_init_caches(void)
 
         LASSERT(obd_device_cachep == NULL);
         obd_device_cachep = cfs_mem_cache_create("ll_obd_dev_cache",
-                                                 sizeof(struct obd_device), 
+                                                 sizeof(struct obd_device),
                                                  0, 0);
         if (!obd_device_cachep)
                 GOTO(out, -ENOMEM);
@@ -631,7 +650,7 @@ void __class_export_put(struct obd_export *exp)
 
                 CDEBUG(D_IOCTL, "final put %p/%s\n",
                        exp, exp->exp_client_uuid.uuid);
-        
+
                 spin_lock(&obd_zombie_impexp_lock);
                 list_add(&exp->exp_obd_chain, &obd_zombie_exports);
                 spin_unlock(&obd_zombie_impexp_lock);
@@ -698,7 +717,7 @@ struct obd_export *class_new_export(struct obd_device *obd,
         obd_init_export(export);
 
         if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) {
-               rc = lustre_hash_additem_unique(obd->obd_uuid_hash_body, cluuid, 
+               rc = lustre_hash_additem_unique(obd->obd_uuid_hash_body, cluuid,
                                                &export->exp_uuid_hash);
                if (rc != 0) {
                        CWARN("%s: denying duplicate export for %s\n",
@@ -729,7 +748,7 @@ void class_unlink_export(struct obd_export *exp)
         spin_lock(&exp->exp_obd->obd_dev_lock);
         /* delete an uuid-export hashitem from hashtables */
         if (!hlist_unhashed(&exp->exp_uuid_hash)) {
-                lustre_hash_delitem(exp->exp_obd->obd_uuid_hash_body, 
+                lustre_hash_delitem(exp->exp_obd->obd_uuid_hash_body,
                                     &exp->exp_client_uuid, &exp->exp_uuid_hash);
         }
         list_del_init(&exp->exp_obd_chain);
@@ -772,7 +791,7 @@ void class_import_put(struct obd_import *import)
         if (atomic_dec_and_test(&import->imp_refcount)) {
 
                 CDEBUG(D_INFO, "final put import %p\n", import);
-                
+
                 spin_lock(&obd_zombie_impexp_lock);
                 list_add(&import->imp_zombie_chain, &obd_zombie_imports);
                 spin_unlock(&obd_zombie_impexp_lock);
@@ -787,7 +806,7 @@ EXPORT_SYMBOL(class_import_put);
 void class_import_destroy(struct obd_import *import)
 {
         ENTRY;
-        
+
         CDEBUG(D_IOCTL, "destroying import %p\n", import);
 
         LASSERT(atomic_read(&import->imp_refcount) == 0);
@@ -1223,7 +1242,7 @@ char *obd_export_nid2str(struct obd_export *exp)
 {
         if (exp->exp_connection != NULL)
                 return libcfs_nid2str(exp->exp_connection->c_peer.nid);
-        
+
         return "(no nid)";
 }
 EXPORT_SYMBOL(obd_export_nid2str);
@@ -1246,7 +1265,7 @@ int obd_export_evict_by_nid(struct obd_device *obd, char *nid)
                          "nid %s found, wanted nid %s, requested nid %s\n",
                          obd_export_nid2str(doomed_exp),
                          libcfs_nid2str(nid_key), nid);
-        
+
                 exports_evicted++;
                 CDEBUG(D_HA, "%s: evict NID '%s' (%s) #%d at adminstrative request\n",
                        obd->obd_name, nid, doomed_exp->exp_client_uuid.uuid,
@@ -1274,7 +1293,7 @@ int obd_export_evict_by_uuid(struct obd_device *obd, char *uuid)
                 return exports_evicted;
         }
 
-        doomed_exp = lustre_hash_get_object_by_key(obd->obd_uuid_hash_body, 
+        doomed_exp = lustre_hash_get_object_by_key(obd->obd_uuid_hash_body,
                                                    &doomed);
 
         if (doomed_exp == NULL) {
diff --git a/lustre/obdclass/linux/linux-module.c b/lustre/obdclass/linux/linux-module.c
index 57ccf93ca922d57fa479c136794121fdf27b28db..c71184218efc6ca3196725f4e35eecf89f9d262a 100644
--- a/lustre/obdclass/linux/linux-module.c
+++ b/lustre/obdclass/linux/linux-module.c
@@ -99,7 +99,7 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg)
         ENTRY;
 
         err = copy_from_user(&hdr, (void *)arg, sizeof(hdr));
-        if ( err ) 
+        if ( err )
                 RETURN(err);
 
         if (hdr.ioc_version != OBD_IOCTL_VERSION) {
@@ -167,8 +167,8 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg)
 
 int obd_ioctl_popdata(void *arg, void *data, int len)
 {
-        int err; 
-        
+        int err;
+
         err = copy_to_user(arg, data, len);
         if (err)
                 err = -EFAULT;
@@ -262,6 +262,21 @@ int obd_proc_read_pinger(char *page, char **start, off_t off, int count,
                        );
 }
 
+/**
+ * Check all obd devices health
+ *
+ * \param page
+ * \param start
+ * \param off
+ * \param count
+ * \param eof
+ * \param data
+ *                  proc read function parameters, please refer to kernel
+ *                  code fs/proc/generic.c proc_file_read()
+ * \param data [in] unused
+ *
+ * \retval number of characters printed
+ */
 static int obd_proc_read_health(char *page, char **start, off_t off,
                                 int count, int *eof, void *data)
 {
@@ -276,7 +291,7 @@ static int obd_proc_read_health(char *page, char **start, off_t off,
                 struct obd_device *obd;
 
                 obd = class_num2obd(i);
-                if (obd == NULL)
+                if (obd == NULL || !obd->obd_attached || !obd->obd_set_up)
                         continue;
 
                 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
@@ -330,7 +345,7 @@ static void obd_device_list_seq_stop(struct seq_file *p, void *v)
 }
 
 static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos)
-{      
+{
         ++*pos;
         if (*pos >= class_devno_max())
                 return NULL;
@@ -427,7 +442,7 @@ int class_procfs_init(void)
 int class_procfs_clean(void)
 {
         ENTRY;
-        if (proc_lustre_root) 
+        if (proc_lustre_root)
                 lprocfs_remove(&proc_lustre_root);
         RETURN(0);
 }
diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c
index 302e45ad466ca7a5f2283335966de9d80f4e8238..1b4de2c80877f7453d8a01ffcfdc9c40c6bf1b28 100644
--- a/lustre/obdclass/obd_mount.c
+++ b/lustre/obdclass/obd_mount.c
@@ -198,7 +198,7 @@ int server_put_mount(char *name, struct vfsmount *mnt)
 
         /* This might be the last one, can't deref after this */
         unlock_mntput(mnt);
-        
+
         down(&lustre_mount_info_lock);
         lmi = server_find_mount(name);
         up(&lustre_mount_info_lock);
@@ -394,7 +394,7 @@ int lustre_process_log(struct super_block *sb, char *logname,
                                    "communication errors between this node and "
                                    "the MGS, a bad configuration, or other "
                                    "errors. See the syslog for more "
-                                   "information.\n", mgc->obd_name, logname, 
+                                   "information.\n", mgc->obd_name, logname,
                                    rc);
 
         /* class_obd_list(); */
@@ -505,7 +505,7 @@ static int server_start_mgs(struct super_block *sb)
 
         if (rc)
                 LCONSOLE_ERROR_MSG(0x15e, "Failed to start MGS '%s' (%d).  Is "
-                                   "the 'mgs' module loaded?\n", 
+                                   "the 'mgs' module loaded?\n",
                                    LUSTRE_MGS_OBDNAME, rc);
 
         RETURN(rc);
@@ -534,7 +534,12 @@ static int server_stop_mgs(struct super_block *sb)
 
 DECLARE_MUTEX(mgc_start_lock);
 
-/* Set up a mgcobd to process startup logs */
+/** Set up a mgc obd to process startup logs
+ *
+ * \param sb [in] super block of the mgc obd
+ *
+ * \retval 0 success, otherwise error code
+ */
 static int lustre_start_mgc(struct super_block *sb)
 {
         struct lustre_handle mgc_conn = {0, };
@@ -591,7 +596,7 @@ static int lustre_start_mgc(struct super_block *sb)
         mutex_down(&mgc_start_lock);
 
         obd = class_name2obd(mgcname);
-        if (obd) {
+        if (obd && !obd->obd_stopping) {
                 /* Re-using an existing MGC */
                 atomic_inc(&obd->u.cli.cl_mgc_refcount);
 
@@ -772,7 +777,7 @@ static int lustre_stop_mgc(struct super_block *sb)
                 GOTO(out, rc = -EBUSY);
         }
 
-        /* The MGC has no recoverable data in any case. 
+        /* The MGC has no recoverable data in any case.
          * force shotdown set in umount_begin */
         obd->obd_no_recov = 1;
 
@@ -1086,7 +1091,7 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
         if (rc == -EINVAL) {
                 LCONSOLE_ERROR_MSG(0x160, "The MGS is refusing to allow this "
                                    "server (%s) to start.  Please see messages "
-                                   "on the MGS node.\n", 
+                                   "on the MGS node.\n",
                                    lsi->lsi_ldd->ldd_svname);
                 GOTO(out_mgc, rc);
         }
@@ -1371,7 +1376,7 @@ static void server_put_super(struct super_block *sb)
         CDEBUG(D_MOUNT, "server put_super %s\n", tmpname);
 
         /* Stop the target */
-        if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC) && 
+        if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC) &&
             (IS_MDT(lsi->lsi_ldd) || IS_OST(lsi->lsi_ldd))) {
                 struct lustre_profile *lprof = NULL;
 
@@ -1591,7 +1596,7 @@ static int server_fill_super(struct super_block *sb)
         if (class_name2obd(lsi->lsi_ldd->ldd_svname)) {
                 LCONSOLE_ERROR_MSG(0x161, "The target named %s is already "
                                    "running. Double-mount may have compromised "
-                                   "the disk journal.\n", 
+                                   "the disk journal.\n",
                                    lsi->lsi_ldd->ldd_svname);
                 unlock_mntput(mnt);
                 lustre_put_lsi(sb);