Whamcloud - gitweb
LU-9224 fid: race between client_fid_fini and seq_client_flush 79/26079/4
authorFan Yong <fan.yong@intel.com>
Tue, 8 Nov 2016 16:47:59 +0000 (00:47 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 30 Mar 2017 03:54:39 +0000 (03:54 +0000)
When the client mount failed or umount, the client_fid_fini() will
be called. At that time, the async connection failure will trigger
seq_client_flush() which parameter may have been released by the
client_fid_fini() by race.

Introduce client_obd::cl_seq_rwsem to protect client_obd::cl_seq.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I96b195676b0d1356a8ae7438cdf69d2e258abd23
Reviewed-on: https://review.whamcloud.com/26079
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/fid/fid_request.c
lustre/include/obd.h
lustre/ldlm/ldlm_lib.c
lustre/mdc/mdc_request.c

index 4e34794..28a6b1e 100644 (file)
@@ -544,26 +544,30 @@ int client_fid_init(struct obd_device *obd,
        int rc;
        ENTRY;
 
+       down_write(&cli->cl_seq_rwsem);
        OBD_ALLOC_PTR(cli->cl_seq);
-       if (cli->cl_seq == NULL)
-               RETURN(-ENOMEM);
+       if (!cli->cl_seq)
+               GOTO(out, rc = -ENOMEM);
 
        OBD_ALLOC(prefix, MAX_OBD_NAME + 5);
-       if (prefix == NULL)
-               GOTO(out_free_seq, rc = -ENOMEM);
+       if (!prefix)
+               GOTO(out, rc = -ENOMEM);
 
        snprintf(prefix, MAX_OBD_NAME + 5, "cli-%s", obd->obd_name);
 
        /* Init client side sequence-manager */
        rc = seq_client_init(cli->cl_seq, exp, type, prefix, NULL);
        OBD_FREE(prefix, MAX_OBD_NAME + 5);
-       if (rc)
-               GOTO(out_free_seq, rc);
 
-       RETURN(rc);
-out_free_seq:
-       OBD_FREE_PTR(cli->cl_seq);
-       cli->cl_seq = NULL;
+       GOTO(out, rc);
+
+out:
+       if (rc && cli->cl_seq) {
+               OBD_FREE_PTR(cli->cl_seq);
+               cli->cl_seq = NULL;
+       }
+       up_write(&cli->cl_seq_rwsem);
+
        return rc;
 }
 EXPORT_SYMBOL(client_fid_init);
@@ -573,11 +577,13 @@ int client_fid_fini(struct obd_device *obd)
        struct client_obd *cli = &obd->u.cli;
        ENTRY;
 
-       if (cli->cl_seq != NULL) {
+       down_write(&cli->cl_seq_rwsem);
+       if (cli->cl_seq) {
                seq_client_fini(cli->cl_seq);
                OBD_FREE_PTR(cli->cl_seq);
                cli->cl_seq = NULL;
        }
+       up_write(&cli->cl_seq_rwsem);
 
        RETURN(0);
 }
index 77c61b3..b399149 100644 (file)
@@ -323,6 +323,7 @@ struct client_obd {
 
        /* sequence manager */
        struct lu_client_seq    *cl_seq;
+       struct rw_semaphore      cl_seq_rwsem;
 
        atomic_t             cl_resends; /* resend count */
 
index 3677da1..ced1198 100644 (file)
@@ -350,10 +350,12 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 
        init_rwsem(&cli->cl_sem);
        mutex_init(&cli->cl_mgc_mutex);
-        cli->cl_conn_count = 0;
-        memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
-               min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2),
-                     sizeof(server_uuid)));
+       cli->cl_seq = NULL;
+       init_rwsem(&cli->cl_seq_rwsem);
+       cli->cl_conn_count = 0;
+       memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
+              min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2),
+                    sizeof(server_uuid)));
 
        cli->cl_dirty_pages = 0;
        cli->cl_avail_grant = 0;
index 2426ce8..2c45545 100644 (file)
@@ -2516,8 +2516,10 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
                 * Flush current sequence to make client obtain new one
                 * from server in case of disconnect/reconnect.
                 */
-               if (cli->cl_seq != NULL)
+               down_read(&cli->cl_seq_rwsem);
+               if (cli->cl_seq)
                        seq_client_flush(cli->cl_seq);
+               up_read(&cli->cl_seq_rwsem);
 
                rc = obd_notify_observer(obd, obd, OBD_NOTIFY_INACTIVE);
                break;
@@ -2553,9 +2555,16 @@ int mdc_fid_alloc(const struct lu_env *env, struct obd_export *exp,
                  struct lu_fid *fid, struct md_op_data *op_data)
 {
        struct client_obd *cli = &exp->exp_obd->u.cli;
-       struct lu_client_seq *seq = cli->cl_seq;
+       int rc = -EIO;
+
        ENTRY;
-       RETURN(seq_client_alloc_fid(env, seq, fid));
+
+       down_read(&cli->cl_seq_rwsem);
+       if (cli->cl_seq)
+               rc = seq_client_alloc_fid(env, cli->cl_seq, fid);
+       up_read(&cli->cl_seq_rwsem);
+
+       RETURN(rc);
 }
 
 static struct obd_uuid *mdc_get_uuid(struct obd_export *exp)