From 210803a2475862464045b609eee43237d74e853b Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Tue, 22 Feb 2022 20:34:37 +0300 Subject: [PATCH] LU-15653 client: able to cleanup devices manually Using 'lctl cleanup/detach' could be needed in situations with unclean umount. Meanwhile that doesn't work now for LMV and also could cause panic after all Patch restores ability to cleanup/detach client devices manually. - debugfs and lprocfs cleanup in lmv_precleanup() are moved lmv_cleanup() to be not cleared too early. This prevents hang on 'lctl cleanup' for LMV device - test 172 is added in sanity. It skips device cleanup during normal umount, keeping device alive without client mount then manually cleanups/detaches them - prevent negative lov_connections in lov_disconnect() and handle it gracefully - remove obd_cleanup_client_import() in mdc_precleanup(), it is called already inside osc_precleanup_common() Signed-off-by: Mikhail Pershin Change-Id: I8a3868fabd1d805e827d04852d1614a3fe57ce35 Reviewed-on: https://review.whamcloud.com/46859 Reviewed-by: John L. Hammond Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/include/obd_support.h | 1 + lustre/llite/llite_lib.c | 5 +++++ lustre/lmv/lmv_obd.c | 12 ++++++------ lustre/lov/lov_obd.c | 8 +++++++- lustre/mdc/mdc_request.c | 8 ++++---- lustre/tests/sanity.sh | 30 ++++++++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index 80afed0..f6aea9a 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -479,6 +479,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_OBD_ZERO_NLINK_RACE 0x60b #define OBD_FAIL_OBD_STOP_MDS_RACE 0x60c #define OBD_FAIL_OBD_SETUP 0x60d +#define OBD_FAIL_OBD_CLEANUP 0x60e #define OBD_FAIL_TGT_REPLY_NET 0x700 #define OBD_FAIL_TGT_CONN_RACE 0x701 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 1e33055..9fc44a8 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -1482,10 +1482,15 @@ void ll_put_super(struct super_block *sb) client_common_put_super(sb); } + /* imitate failed cleanup */ + if (OBD_FAIL_CHECK(OBD_FAIL_OBD_CLEANUP)) + goto skip_cleanup; + next = 0; while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next))) class_manual_cleanup(obd); +skip_cleanup: if (test_bit(LL_SBI_VERBOSE, sbi->ll_flags)) LCONSOLE_WARN("Unmounted %s\n", profilenm ? profilenm : ""); diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 1431ec4..9de2f12 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -545,10 +545,8 @@ static int lmv_disconnect(struct obd_export *exp) if (lmv->lmv_tgts_kobj) kobject_put(lmv->lmv_tgts_kobj); - if (!lmv->connected) - class_export_put(exp); - rc = class_disconnect(exp); lmv->connected = 0; + rc = class_disconnect(exp); RETURN(rc); } @@ -1161,6 +1159,11 @@ static int lmv_cleanup(struct obd_device *obd) ENTRY; fld_client_fini(&lmv->lmv_fld); + fld_client_debugfs_fini(&lmv->lmv_fld); + + lprocfs_obd_cleanup(obd); + lprocfs_free_md_stats(obd); + lmv_foreach_tgt_safe(lmv, tgt, tmp) lmv_del_target(lmv, tgt); lu_tgt_descs_fini(&lmv->lmv_mdt_descs); @@ -3116,9 +3119,6 @@ static int lmv_precleanup(struct obd_device *obd) { ENTRY; libcfs_kkuc_group_rem(&obd->obd_uuid, 0, KUC_GRP_HSM); - fld_client_debugfs_fini(&obd->u.lmv.lmv_fld); - lprocfs_obd_cleanup(obd); - lprocfs_free_md_stats(obd); RETURN(0); } diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 3efba72..b7512bd 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -309,8 +309,14 @@ static int lov_disconnect(struct obd_export *exp) goto out; /* Only disconnect the underlying layers on the final disconnect. */ + if (lov->lov_connects == 0) { + CWARN("%s: was disconnected already #%d\n", + obd->obd_name, lov->lov_connects); + RETURN(0); + } + lov->lov_connects--; - if (lov->lov_connects != 0) { + if (lov->lov_connects > 0) { /* why should there be more than 1 connect? */ CWARN("%s: unexpected disconnect #%d\n", obd->obd_name, lov->lov_connects); diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index c032849..8f61982 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -2951,12 +2951,12 @@ static int mdc_precleanup(struct obd_device *obd) ENTRY; osc_precleanup_common(obd); - mdc_changelog_cdev_finish(obd); - obd_cleanup_client_import(obd); - ptlrpc_lprocfs_unregister_obd(obd); - lprocfs_free_md_stats(obd); + mdc_changelog_cdev_finish(obd); mdc_llog_finish(obd); + lprocfs_free_md_stats(obd); + ptlrpc_lprocfs_unregister_obd(obd); + RETURN(0); } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 4ddad5e..b906786 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -17857,6 +17857,36 @@ test_171() { # bug20592 } run_test 171 "test libcfs_debug_dumplog_thread stuck in do_exit() ======" +test_172() { + + #define OBD_FAIL_OBD_CLEANUP 0x60e + $LCTL set_param fail_loc=0x60e + umount $MOUNT || error "umount $MOUNT failed" + stack_trap "mount_client $MOUNT" + + (( $($LCTL dl | egrep -c " osc | lov | lmv | mdc ") > 0 )) || + error "no client OBDs are remained" + + $LCTL dl | while read devno state type name foo; do + case $type in + lov|osc|lmv|mdc) + $LCTL --device $name cleanup + $LCTL --device $name detach + ;; + *) + # skip server devices + ;; + esac + done + + if (( $($LCTL dl | egrep -c " osc | lov | lmv | mdc ") > 0 )); then + $LCTL dl | egrep " osc | lov | lmv | mdc " + error "some client OBDs are still remained" + fi + +} +run_test 172 "manual device removal with lctl cleanup/detach ======" + # it would be good to share it with obdfilter-survey/iokit-libecho code setup_obdecho_osc () { local rc=0 -- 1.8.3.1