From: Fan Yong Date: Tue, 8 Nov 2016 16:47:59 +0000 (+0800) Subject: LU-9224 fid: race between client_fid_fini and seq_client_flush X-Git-Tag: 2.9.55~3 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=c0d30fc79be0788fca19bfa7e3b5048881195fc6 LU-9224 fid: race between client_fid_fini and seq_client_flush 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 Change-Id: I96b195676b0d1356a8ae7438cdf69d2e258abd23 Reviewed-on: https://review.whamcloud.com/26079 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- diff --git a/lustre/fid/fid_request.c b/lustre/fid/fid_request.c index 4e34794..28a6b1e 100644 --- a/lustre/fid/fid_request.c +++ b/lustre/fid/fid_request.c @@ -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); } diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 77c61b3..b399149 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -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 */ diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c index 3677da1..ced1198 100644 --- a/lustre/ldlm/ldlm_lib.c +++ b/lustre/ldlm/ldlm_lib.c @@ -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; diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 2426ce8..2c45545 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -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)