Whamcloud - gitweb
LU-6499 obdclass: obdclass module cleanup upon load error 44/22544/13
authorBruno Faccini <bruno.faccini@intel.com>
Fri, 16 Sep 2016 08:15:06 +0000 (10:15 +0200)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 15 Feb 2017 01:03:11 +0000 (01:03 +0000)
Fix obdclass_init() error paths to proceed with cleanup.
This will particularly allow to no longer crash upon next
load attempt and this due to previous miscdevice not been
deregistered and thus still referenced in misc_list when
unmapped.

conf-sanity/test_102 has been created to verify correct
behavior/cleanup.

Signed-off-by: Bruno Faccini <bruno.faccini@intel.com>
Change-Id: I6f65cf651251cf92427e2bab3ff6b51ebb98d699
Reviewed-on: https://review.whamcloud.com/22544
Reviewed-by: Patrick Farrell <paf@cray.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/obd_support.h
lustre/obdclass/class_obd.c
lustre/tests/conf-sanity.sh

index d1d5b47..4faba88 100644 (file)
@@ -434,6 +434,7 @@ extern char obd_jobid_var[];
 #define OBD_FAIL_OBD_IDX_READ_NET        0x607
 #define OBD_FAIL_OBD_IDX_READ_BREAK     0x608
 #define OBD_FAIL_OBD_NO_LRU             0x609
+#define OBD_FAIL_OBDCLASS_MODULE_LOAD   0x60a
 
 #define OBD_FAIL_TGT_REPLY_NET           0x700
 #define OBD_FAIL_TGT_CONN_RACE           0x701
index cf38cde..d70d496 100644 (file)
@@ -513,7 +513,8 @@ static int __init obdclass_init(void)
                                         LPROCFS_STATS_FLAG_IRQ_SAFE);
        if (obd_memory == NULL) {
                CERROR("kmalloc of 'obd_memory' failed\n");
-               RETURN(-ENOMEM);
+               err = -ENOMEM;
+               goto cleanup_zombie_impexp;
        }
 
        lprocfs_counter_init(obd_memory, OBD_MEMORY_STAT,
@@ -522,19 +523,19 @@ static int __init obdclass_init(void)
 #endif
        err = obd_init_checks();
        if (err == -EOVERFLOW)
-               return err;
+               goto cleanup_zombie_impexp;
 
        class_init_uuidlist();
        err = class_handle_init();
        if (err)
-               return err;
+               goto cleanup_uuidlist;
 
        INIT_LIST_HEAD(&obd_types);
 
        err = misc_register(&obd_psdev);
        if (err) {
                CERROR("cannot register %d err %d\n", OBD_DEV_MINOR, err);
-               return err;
+               goto cleanup_class_handle;
        }
 
        /* This struct is already zeroed for us (static global) */
@@ -551,35 +552,91 @@ static int __init obdclass_init(void)
 
        err = obd_init_caches();
        if (err)
-               return err;
+               goto cleanup_deregister;
+
        err = class_procfs_init();
        if (err)
-               return err;
+               goto cleanup_caches;
 
        err = lu_global_init();
        if (err)
-               return err;
+               goto cleanup_class_procfs;
 
        err = cl_global_init();
        if (err != 0)
-               return err;
+               goto cleanup_lu_global;
 
 #ifdef HAVE_SERVER_SUPPORT
        err = dt_global_init();
        if (err != 0)
-               return err;
+               goto cleanup_cl_global;
 
        err = lu_ucred_global_init();
        if (err != 0)
-               return err;
+               goto cleanup_dt_global;
 #endif /* HAVE_SERVER_SUPPORT */
 
        err = llog_info_init();
        if (err)
-               return err;
+#ifdef HAVE_SERVER_SUPPORT
+               goto cleanup_lu_ucred_global;
+#else /* !HAVE_SERVER_SUPPORT */
+               goto cleanup_cl_global;
+#endif /* HAVE_SERVER_SUPPORT */
 
        err = lustre_register_fs();
 
+       /* simulate a late OOM situation now to require all
+        * alloc'ed/initialized resources to be freed */
+       if (OBD_FAIL_CHECK(OBD_FAIL_OBDCLASS_MODULE_LOAD)) {
+               /* fake error but filesystem has been registered */
+               lustre_unregister_fs();
+               /* force error to ensure module will be unloaded/cleaned */
+               err = -ENOMEM;
+       }
+
+       if (err)
+               goto cleanup_llog_info;
+
+       goto out_success;
+
+cleanup_llog_info:
+       llog_info_fini();
+
+#ifdef HAVE_SERVER_SUPPORT
+cleanup_lu_ucred_global:
+       lu_ucred_global_fini();
+
+cleanup_dt_global:
+       dt_global_fini();
+#endif /* HAVE_SERVER_SUPPORT */
+
+cleanup_cl_global:
+       cl_global_fini();
+
+cleanup_lu_global:
+       lu_global_fini();
+
+cleanup_class_procfs:
+       obd_sysctl_clean();
+       class_procfs_clean();
+
+cleanup_caches:
+       obd_cleanup_caches();
+
+cleanup_deregister:
+       misc_deregister(&obd_psdev);
+
+cleanup_class_handle:
+       class_handle_cleanup();
+
+cleanup_uuidlist:
+       class_exit_uuidlist();
+
+cleanup_zombie_impexp:
+       obd_zombie_impexp_stop();
+
+out_success:
        return err;
 }
 
index 02e2a61..037a782 100755 (executable)
@@ -7028,6 +7028,43 @@ test_101() {
 }
 run_test 101 "Race MDT->OST reconnection with create"
 
+test_102() {
+       cleanup || error "cleanup failed with $?"
+
+       local mds1dev=$(mdsdevname 1)
+       local mds1mnt=$(facet_mntpt mds1)
+       local mds1fstype=$(facet_fstype mds1)
+       local mds1opts=$MDS_MOUNT_OPTS
+
+       if [ $mds1fstype == ldiskfs ] &&
+          ! do_facet mds1 test -b $mds1dev; then
+               mds1opts=$(csa_add "$mds1opts" -o loop)
+       fi
+       if [[ $mds1fstype == zfs ]]; then
+               import_zpool mds1 || return ${PIPESTATUS[0]}
+       fi
+
+       # unload all and only load libcfs to allow fail_loc setting
+       do_facet mds1 lustre_rmmod || error "unable to unload modules"
+       do_facet mds1 modprobe libcfs || error "libcfs not loaded"
+       do_facet mds1 lsmod \| grep libcfs || error "libcfs not loaded"
+
+       #define OBD_FAIL_OBDCLASS_MODULE_LOAD    0x60a
+       do_facet mds1 "$LCTL set_param fail_loc=0x8000060a"
+
+       do_facet mds1 $MOUNT_CMD $mds1dev $mds1mnt $mds1opts &&
+               error "mdt start must fail"
+       do_facet mds1 lsmod \| grep  obdclass && error "obdclass must not load"
+
+       do_facet mds1 "$LCTL set_param fail_loc=0x0"
+
+       do_facet mds1 $MOUNT_CMD $mds1dev $mds1mnt $mds1opts ||
+               error "mdt start must not fail"
+
+       cleanup || error "cleanup failed with $?"
+}
+run_test 102 "obdclass module cleanup upon error"
+
 if ! combined_mgs_mds ; then
        stop mgs
 fi