- req = mdt_info_req(info);
- rc = target_handle_connect(req);
- if (rc == 0) {
- LASSERT(req->rq_export != NULL);
- info->mti_mdt = mdt_dev(req->rq_export->exp_obd->obd_lu_dev);
- rc = mdt_init_sec_level(info);
- if (rc == 0)
- rc = mdt_init_idmap(info);
- if (rc != 0)
- obd_disconnect(class_export_get(req->rq_export));
- } else {
- rc = err_serious(rc);
- }
- return rc;
+ rc = target_handle_connect(req);
+ if (rc != 0)
+ return err_serious(rc);
+
+ LASSERT(req->rq_export != NULL);
+ info->mti_mdt = mdt_dev(req->rq_export->exp_obd->obd_lu_dev);
+ rc = mdt_init_sec_level(info);
+ if (rc != 0) {
+ obd_disconnect(class_export_get(req->rq_export));
+ return rc;
+ }
+
+ /* To avoid exposing partially initialized connection flags, changes up
+ * to this point have been staged in reply->ocd_connect_flags. Now that
+ * connection handling has completed successfully, atomically update
+ * the connect flags in the shared export data structure. LU-1623 */
+ reply = req_capsule_server_get(info->mti_pill, &RMF_CONNECT_DATA);
+ exp = req->rq_export;
+ cfs_spin_lock(&exp->exp_lock);
+ exp->exp_connect_flags = reply->ocd_connect_flags;
+ cfs_spin_unlock(&exp->exp_lock);
+
+ rc = mdt_init_idmap(info);
+ if (rc != 0)
+ obd_disconnect(class_export_get(req->rq_export));
+
+ return rc;
-/* mds_connect_internal */
+/**
+ * Match client and server connection feature flags.
+ *
+ * Compute the compatibility flags for a connection request based on
+ * features mutually supported by client and server.
+ *
+ * The obd_export::exp_connect_flags field in \a exp must not be updated
+ * here, otherwise a partially initialized value may be exposed. After
+ * the connection request is successfully processed, the top-level MDT
+ * connect request handler atomically updates the export connect flags
+ * from the obd_connect_data::ocd_connect_flags field of the reply.
+ * \see mdt_connect().
+ *
+ * \param exp the obd_export associated with this client/target pair
+ * \param mdt the target device for the connection
+ * \param data stores data for this connect request
+ *
+ * \retval 0 success
+ * \retval -EPROTO \a data unexpectedly has zero obd_connect_data::ocd_brw_size
+ * \retval -EBADE client and server feature requirements are incompatible
+ */
- struct mdt_device *mdt,
- struct obd_connect_data *data)
-{
- if (data != NULL) {
- data->ocd_connect_flags &= MDT_CONNECT_SUPPORTED;
- data->ocd_ibits_known &= MDS_INODELOCK_FULL;
-
- /* If no known bits (which should not happen, probably,
- as everybody should support LOOKUP and UPDATE bits at least)
- revert to compat mode with plain locks. */
- if (!data->ocd_ibits_known &&
- data->ocd_connect_flags & OBD_CONNECT_IBITS)
- data->ocd_connect_flags &= ~OBD_CONNECT_IBITS;
-
- if (!mdt->mdt_opts.mo_acl)
- data->ocd_connect_flags &= ~OBD_CONNECT_ACL;
-
- if (!mdt->mdt_opts.mo_user_xattr)
- data->ocd_connect_flags &= ~OBD_CONNECT_XATTR;
-
- if (!mdt->mdt_som_conf)
- data->ocd_connect_flags &= ~OBD_CONNECT_SOM;
-
- if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
- data->ocd_brw_size = min(data->ocd_brw_size,
- (__u32)(PTLRPC_MAX_BRW_PAGES << CFS_PAGE_SHIFT));
- if (data->ocd_brw_size == 0) {
- CERROR("%s: cli %s/%p ocd_connect_flags: "LPX64
- " ocd_version: %x ocd_grant: %d "
- "ocd_index: %u ocd_brw_size is "
- "unexpectedly zero, network data "
- "corruption? Refusing connection of this"
- " client\n",
- exp->exp_obd->obd_name,
- exp->exp_client_uuid.uuid,
- exp, data->ocd_connect_flags, data->ocd_version,
- data->ocd_grant, data->ocd_index);
- return -EPROTO;
- }
- }
+ struct mdt_device *mdt,
+ struct obd_connect_data *data)
+{
+ LASSERT(data != NULL);
+
+ data->ocd_connect_flags &= MDT_CONNECT_SUPPORTED;
+ data->ocd_ibits_known &= MDS_INODELOCK_FULL;
+
+ /* If no known bits (which should not happen, probably,
+ as everybody should support LOOKUP and UPDATE bits at least)
+ revert to compat mode with plain locks. */
+ if (!data->ocd_ibits_known &&
+ data->ocd_connect_flags & OBD_CONNECT_IBITS)
+ data->ocd_connect_flags &= ~OBD_CONNECT_IBITS;
+
+ if (!mdt->mdt_opts.mo_acl)
+ data->ocd_connect_flags &= ~OBD_CONNECT_ACL;
+
+ if (!mdt->mdt_opts.mo_user_xattr)
+ data->ocd_connect_flags &= ~OBD_CONNECT_XATTR;
+
+ if (!mdt->mdt_som_conf)
+ data->ocd_connect_flags &= ~OBD_CONNECT_SOM;
+
+ if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
+ data->ocd_brw_size = min(data->ocd_brw_size,
+ (__u32)(PTLRPC_MAX_BRW_PAGES << CFS_PAGE_SHIFT));
+ if (data->ocd_brw_size == 0) {
+ CERROR("%s: cli %s/%p ocd_connect_flags: "LPX64
+ " ocd_version: %x ocd_grant: %d "
+ "ocd_index: %u ocd_brw_size is "
+ "unexpectedly zero, network data "
+ "corruption? Refusing connection of this"
+ " client\n",
+ exp->exp_obd->obd_name,
+ exp->exp_client_uuid.uuid,
+ exp, data->ocd_connect_flags, data->ocd_version,
+ data->ocd_grant, data->ocd_index);
+ return -EPROTO;
+ }
+ }
- cfs_spin_lock(&exp->exp_lock);
- exp->exp_connect_flags = data->ocd_connect_flags;
- cfs_spin_unlock(&exp->exp_lock);
- data->ocd_version = LUSTRE_VERSION_CODE;
- exp->exp_mdt_data.med_ibits_known = data->ocd_ibits_known;
- }
+ /* NB: Disregard the rule against updating exp_connect_flags in this
+ * case, since tgt_client_new() needs to know if this is a lightweight
+ * connection, and it is safe to expose this flag before connection
+ * processing completes. */
+ if (data->ocd_connect_flags & OBD_CONNECT_LIGHTWEIGHT) {
+ cfs_spin_lock(&exp->exp_lock);
+ exp->exp_connect_flags |= OBD_CONNECT_LIGHTWEIGHT;
+ cfs_spin_unlock(&exp->exp_lock);
+ }