+static
+int mds_req_add_idmapping(struct ptlrpc_request *req,
+ struct mds_export_data *med)
+{
+ struct mds_req_sec_desc *rsd;
+ struct lustre_sec_desc *lsd;
+ int rc;
+
+ if (!med->med_remote)
+ return 0;
+
+ /* maybe we should do it more completely: invalidate the gss ctxt? */
+ if (req->rq_mapped_uid == MDS_IDMAP_NOTFOUND) {
+ CWARN("didn't find mapped uid\n");
+ return -EPERM;
+ }
+
+ rsd = lustre_swab_mds_secdesc(req, MDS_REQ_SECDESC_OFF);
+ if (!rsd) {
+ CERROR("Can't unpack security desc\n");
+ return -EPROTO;
+ }
+
+ lsd = mds_get_lsd(req->rq_mapped_uid);
+ if (!lsd) {
+ CERROR("can't get LSD(%u), no mapping added\n",
+ req->rq_mapped_uid);
+ return -EPERM;
+ }
+
+ rc = mds_idmap_add(med->med_idmap, rsd->rsd_uid, lsd->lsd_uid,
+ rsd->rsd_gid, lsd->lsd_gid);
+ mds_put_lsd(lsd);
+ return rc;
+}
+
+static
+int mds_req_del_idmapping(struct ptlrpc_request *req,
+ struct mds_export_data *med)
+{
+ struct mds_req_sec_desc *rsd;
+ struct lustre_sec_desc *lsd;
+ int rc;
+
+ if (!med->med_remote)
+ return 0;
+
+ rsd = lustre_swab_mds_secdesc(req, MDS_REQ_SECDESC_OFF);
+ if (!rsd) {
+ CERROR("Can't unpack security desc\n");
+ return -EPROTO;
+ }
+
+ LASSERT(req->rq_mapped_uid != -1);
+ lsd = mds_get_lsd(req->rq_mapped_uid);
+ if (!lsd) {
+ CERROR("can't get LSD(%u), no idmapping deleted\n",
+ req->rq_mapped_uid);
+ return -EPERM;
+ }
+
+ rc = mds_idmap_del(med->med_idmap, rsd->rsd_uid, lsd->lsd_uid,
+ rsd->rsd_gid, lsd->lsd_gid);
+ mds_put_lsd(lsd);
+ return rc;
+}
+
+static int mds_init_export_data(struct ptlrpc_request *req,
+ struct mds_export_data *med)
+{
+ struct obd_connect_data *data, *reply;
+ int ask_remote, ask_local;
+ ENTRY;
+
+ data = lustre_msg_buf(req->rq_reqmsg, 5, sizeof(*data));
+ reply = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*data));
+ LASSERT(data && reply);
+
+ if (med->med_initialized) {
+ CWARN("med already initialized, reconnect?\n");
+ goto reply;
+ }
+
+ ask_remote = data->ocd_connect_flags & OBD_CONNECT_REMOTE;
+ ask_local = data->ocd_connect_flags & OBD_CONNECT_LOCAL;
+
+ /* currently the policy is simple: satisfy client as possible
+ * as we can.
+ */
+ if (req->rq_auth_uid == -1) {
+ if (ask_remote)
+ CWARN("null sec is used, force to be local\n");
+ med->med_remote = 0;
+ } else {
+ if (ask_remote) {
+ if (!req->rq_remote_realm)
+ CWARN("local realm asked to be remote\n");
+ med->med_remote = 1;
+ } else if (ask_local) {
+ if (req->rq_remote_realm)
+ CWARN("remote realm asked to be local\n");
+ med->med_remote = 0;
+ } else
+ med->med_remote = (req->rq_remote_realm != 0);
+ }
+
+ med->med_nllu = data->ocd_nllu[0];
+ med->med_nllg = data->ocd_nllu[1];
+
+ med->med_initialized = 1;
+reply:
+ reply->ocd_connect_flags &= ~(OBD_CONNECT_REMOTE | OBD_CONNECT_LOCAL);
+ if (med->med_remote) {
+ if (!med->med_idmap)
+ med->med_idmap = mds_idmap_alloc();
+
+ if (!med->med_idmap)
+ CERROR("Failed to alloc idmap, following request from "
+ "this client will be refused\n");
+
+ reply->ocd_connect_flags |= OBD_CONNECT_REMOTE;
+ CDEBUG(D_SEC, "set client as remote\n");
+ } else {
+ reply->ocd_connect_flags |= OBD_CONNECT_LOCAL;
+ CDEBUG(D_SEC, "set client as local\n");
+ }
+
+ RETURN(0);
+}
+
+static void mds_free_export_data(struct mds_export_data *med)
+{
+ if (!med->med_idmap)
+ return;
+
+ LASSERT(med->med_remote);
+ mds_idmap_free(med->med_idmap);
+ med->med_idmap = NULL;
+}