Whamcloud - gitweb
LU-15305 obdclass: fix race in class_del_profile 02/48802/4
authorLi Dongyang <dongyangli@ddn.com>
Fri, 7 Oct 2022 12:09:10 +0000 (23:09 +1100)
committerOleg Drokin <green@whamcloud.com>
Tue, 25 Oct 2022 17:27:36 +0000 (17:27 +0000)
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 <dongyangli@ddn.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/48802
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/mgs/mgs_llog.c
lustre/obdclass/obd_config.c

index de9daf4..58a57c2 100644 (file)
@@ -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);
index f8840b0..0d37443 100644 (file)
@@ -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;
 }