/** * Disconnect a connected client. * * This function terminates the client connection. The client export is * disconnected (cleaned up) and client data on persistent storage is removed. * * \param[in] exp OBD export * * \retval 0 if successful * \retval negative value on error */ int ofd_obd_disconnect(struct obd_export *exp) { struct ofd_device *ofd = ofd_exp(exp); struct lu_env env; int rc; ENTRY; LASSERT(exp); class_export_get(exp); if (!(exp->exp_flags & OBD_OPT_FORCE)) ofd_grant_sanity_check(ofd_obd(ofd), __FUNCTION__); nodemap_del_member(exp); rc = server_disconnect_export(exp); ofd_grant_discard(exp); /* Do not erase record for recoverable client. */ if (exp->exp_obd->obd_replayable && (!exp->exp_obd->obd_fail || exp->exp_failed)) { rc = lu_env_init(&env, LCT_DT_THREAD); if (rc) GOTO(out, rc); tgt_client_del(&env, exp); lu_env_fini(&env); } out: class_export_put(exp); RETURN(rc); }
/** * Re-initialize export upon client reconnection. * * This function parses connection data from reconnect and resets * export statistics. * * \param[in] env execution environment * \param[in] exp OBD export * \param[in] obd OFD device * \param[in] cluuid NID of client * \param[in] data connection data from request * \param[in] localdata client NID * * \retval 0 if successful * \retval negative value on error */ static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp, struct obd_device *obd, struct obd_uuid *cluuid, struct obd_connect_data *data, void *client_nid) { struct ofd_device *ofd; int rc; ENTRY; if (exp == NULL || obd == NULL || cluuid == NULL) RETURN(-EINVAL); rc = nodemap_add_member(*(lnet_nid_t *)client_nid, exp); if (rc != 0 && rc != -EEXIST) RETURN(rc); ofd = ofd_dev(obd->obd_lu_dev); rc = ofd_parse_connect_data(env, exp, data, false); if (rc == 0) ofd_export_stats_init(ofd, exp, client_nid); else nodemap_del_member(exp); RETURN(rc); }
/** * Initialize new client connection. * * This function handles new connection to the OFD. The new export is * created (in context of class_connect()) and persistent client data is * initialized on storage. * * \param[in] env execution environment * \param[out] _exp stores pointer to new export * \param[in] obd OFD device * \param[in] cluuid client UUID * \param[in] data connection data from request * \param[in] localdata client NID * * \retval 0 if successful * \retval negative value on error */ static int ofd_obd_connect(const struct lu_env *env, struct obd_export **_exp, struct obd_device *obd, struct obd_uuid *cluuid, struct obd_connect_data *data, void *localdata) { struct obd_export *exp; struct ofd_device *ofd; struct lustre_handle conn = { 0 }; int rc; ENTRY; if (_exp == NULL || obd == NULL || cluuid == NULL) RETURN(-EINVAL); ofd = ofd_dev(obd->obd_lu_dev); rc = class_connect(&conn, obd, cluuid); if (rc) RETURN(rc); exp = class_conn2export(&conn); LASSERT(exp != NULL); if (localdata != NULL) { rc = nodemap_add_member(*(lnet_nid_t *)localdata, exp); if (rc != 0 && rc != -EEXIST) GOTO(out, rc); } else { CDEBUG(D_HA, "%s: cannot find nodemap for client %s: " "nid is null\n", obd->obd_name, cluuid->uuid); } rc = ofd_parse_connect_data(env, exp, data, true); if (rc) GOTO(out, rc); if (obd->obd_replayable) { struct tg_export_data *ted = &exp->exp_target_data; memcpy(ted->ted_lcd->lcd_uuid, cluuid, sizeof(ted->ted_lcd->lcd_uuid)); rc = tgt_client_new(env, exp); if (rc != 0) GOTO(out, rc); ofd_export_stats_init(ofd, exp, localdata); } CDEBUG(D_HA, "%s: get connection from MDS %d\n", obd->obd_name, data ? data->ocd_group : -1); out: if (rc != 0) { class_disconnect(exp); nodemap_del_member(exp); *_exp = NULL; } else { *_exp = exp; } RETURN(rc); }