From: Li Dongyang Date: Fri, 7 Oct 2022 12:09:10 +0000 (+1100) Subject: LU-15305 obdclass: fix race in class_del_profile X-Git-Tag: 2.15.53~128 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=83d3f42118579d7fb7c3002533c047badcf41e0d;p=fs%2Flustre-release.git LU-15305 obdclass: fix race in class_del_profile Move profile lookup and remove from lustre_profile_list into the same critical section, otherwise we could race with class_del_profiles or another class_del_profile. Do not create duplicate mount opts in the client config, otherwise we will add duplicate lustre_profile to lustre_profile_list for a single mount. Change-Id: I648aa206716213b064d045f546516b219337e0ed Signed-off-by: Li Dongyang Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/48802 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- diff --git a/lustre/mgs/mgs_llog.c b/lustre/mgs/mgs_llog.c index de9daf4..58a57c2 100644 --- a/lustre/mgs/mgs_llog.c +++ b/lustre/mgs/mgs_llog.c @@ -2340,6 +2340,37 @@ out_ctxt: RETURN(rc); } +/* mount opt is the third thing in client logs */ +static int mgs_write_log_mount_opt(const struct lu_env *env, + struct mgs_device *mgs, struct fs_db *fsdb, + char *logname) +{ + struct llog_handle *llh = NULL; + int rc = 0; + + ENTRY; + + CDEBUG(D_MGS, "Writing mount options log for %s\n", logname); + + rc = record_start_log(env, mgs, &llh, logname); + if (rc) + RETURN(rc); + + rc = record_marker(env, llh, fsdb, CM_START, logname, "mount opts"); + if (rc) + GOTO(out_end, rc); + rc = record_mount_opt(env, llh, logname, fsdb->fsdb_clilov, + fsdb->fsdb_clilmv); + if (rc) + GOTO(out_end, rc); + rc = record_marker(env, llh, fsdb, CM_END, logname, "mount opts"); + if (rc) + GOTO(out_end, rc); +out_end: + record_end_log(env, &llh); + RETURN(rc); +} + /* lmv is the second thing for client logs */ /* copied from mgs_write_log_lov. Please refer to that. */ static int mgs_write_log_lmv(const struct lu_env *env, @@ -2865,6 +2896,9 @@ static int mgs_write_log_mdt(const struct lu_env *env, fsdb->fsdb_clilmv); if (rc) GOTO(out_free, rc); + rc = mgs_write_log_mount_opt(env, mgs, fsdb, cliname); + if (rc) + GOTO(out_free, rc); } /* @@ -2873,7 +2907,6 @@ static int mgs_write_log_mdt(const struct lu_env *env, #11 L setup 0:MDC_uml1_mdsA_MNT_client 1:mdsA_UUID 2:uml1_UUID #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID #13 L add_conn 0:MDC_uml1_mdsA_MNT_client 1:uml2_UUID - #14 L mount_option 0: 1:client 2:lov1 3:MDC_uml1_mdsA_MNT_client */ /* copy client info about lov/lmv */ @@ -2889,22 +2922,10 @@ static int mgs_write_log_mdt(const struct lu_env *env, if (rc) GOTO(out_free, rc); - /* add mountopts */ rc = record_start_log(env, mgs, &llh, cliname); if (rc) GOTO(out_free, rc); - rc = record_marker(env, llh, fsdb, CM_START, cliname, "mount opts"); - if (rc) - GOTO(out_end, rc); - rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov, - fsdb->fsdb_clilmv); - if (rc) - GOTO(out_end, rc); - rc = record_marker(env, llh, fsdb, CM_END, cliname, "mount opts"); - if (rc) - GOTO(out_end, rc); - /* for_all_existing_mdt except current one */ for (i = 0; i < INDEX_MAP_SIZE * 8; i++) { if (i != mti->mti_stripe_index && @@ -3184,6 +3205,9 @@ out_end: fsdb->fsdb_clilmv); if (rc) GOTO(out_free, rc); + rc = mgs_write_log_mount_opt(env, mgs, fsdb, logname); + if (rc) + GOTO(out_free, rc); } rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "", fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags); diff --git a/lustre/obdclass/obd_config.c b/lustre/obdclass/obd_config.c index f8840b0..0d37443 100644 --- a/lustre/obdclass/obd_config.c +++ b/lustre/obdclass/obd_config.c @@ -1027,22 +1027,30 @@ static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg) static LIST_HEAD(lustre_profile_list); static DEFINE_SPINLOCK(lustre_profile_list_lock); -struct lustre_profile *class_get_profile(const char *prof) +static struct lustre_profile *class_get_profile_nolock(const char *prof) { struct lustre_profile *lprof; ENTRY; - spin_lock(&lustre_profile_list_lock); list_for_each_entry(lprof, &lustre_profile_list, lp_list) { - if (!strcmp(lprof->lp_profile, prof)) { + if (strcmp(lprof->lp_profile, prof) == 0) { lprof->lp_refs++; - spin_unlock(&lustre_profile_list_lock); RETURN(lprof); } } - spin_unlock(&lustre_profile_list_lock); RETURN(NULL); } + +struct lustre_profile *class_get_profile(const char *prof) +{ + struct lustre_profile *lprof; + + ENTRY; + spin_lock(&lustre_profile_list_lock); + lprof = class_get_profile_nolock(prof); + spin_unlock(&lustre_profile_list_lock); + RETURN(lprof); +} EXPORT_SYMBOL(class_get_profile); /** @@ -1112,9 +1120,9 @@ void class_del_profile(const char *prof) CDEBUG(D_CONFIG, "Del profile %s\n", prof); - lprof = class_get_profile(prof); + spin_lock(&lustre_profile_list_lock); + lprof = class_get_profile_nolock(prof); if (lprof) { - spin_lock(&lustre_profile_list_lock); /* because get profile increments the ref counter */ lprof->lp_refs--; list_del(&lprof->lp_list); @@ -1122,6 +1130,8 @@ void class_del_profile(const char *prof) spin_unlock(&lustre_profile_list_lock); class_put_profile(lprof); + } else { + spin_unlock(&lustre_profile_list_lock); } EXIT; }