Whamcloud - gitweb
LU-17431 ptlrpc: move nodemap related ioctls to ptlrpc
[fs/lustre-release.git] / lustre / ptlrpc / nodemap_handler.c
index a6da068..f2cf2de 100644 (file)
@@ -2015,3 +2015,366 @@ int nodemap_test_id(struct lnet_nid *nid, enum nodemap_id_type idtype,
        return 0;
 }
 EXPORT_SYMBOL(nodemap_test_id);
+
+static int cfg_nodemap_cmd(enum lcfg_command_type cmd, const char *nodemap_name,
+                          char *param, bool dynamic)
+{
+       struct lnet_nid nid[2];
+       bool bool_switch;
+       u8 netmask = 0;
+       u32 idmap[2];
+       u32 int_id;
+       int rc = 0;
+
+       ENTRY;
+       switch (cmd) {
+       case LCFG_NODEMAP_ADD:
+               rc = nodemap_add(nodemap_name);
+               break;
+       case LCFG_NODEMAP_DEL:
+               rc = nodemap_del(nodemap_name);
+               break;
+       case LCFG_NODEMAP_ADD_RANGE:
+               rc = nodemap_parse_range(param, nid, &netmask);
+               if (rc != 0)
+                       break;
+               rc = nodemap_add_range(nodemap_name, nid, netmask);
+               break;
+       case LCFG_NODEMAP_DEL_RANGE:
+               rc = nodemap_parse_range(param, nid, &netmask);
+               if (rc != 0)
+                       break;
+               rc = nodemap_del_range(nodemap_name, nid, netmask);
+               break;
+       case LCFG_NODEMAP_ADMIN:
+               rc = kstrtobool(param, &bool_switch);
+               if (rc)
+                       break;
+               rc = nodemap_set_allow_root(nodemap_name, bool_switch);
+               break;
+       case LCFG_NODEMAP_DENY_UNKNOWN:
+               rc = kstrtobool(param, &bool_switch);
+               if (rc)
+                       break;
+               rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
+               break;
+       case LCFG_NODEMAP_AUDIT_MODE:
+               rc = kstrtobool(param, &bool_switch);
+               if (rc == 0)
+                       rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
+               break;
+       case LCFG_NODEMAP_FORBID_ENCRYPT:
+               rc = kstrtobool(param, &bool_switch);
+               if (rc == 0)
+                       rc = nodemap_set_forbid_encryption(nodemap_name,
+                                                          bool_switch);
+               break;
+       case LCFG_NODEMAP_READONLY_MOUNT:
+               rc = kstrtobool(param, &bool_switch);
+               if (rc == 0)
+                       rc = nodemap_set_readonly_mount(nodemap_name,
+                                                       bool_switch);
+               break;
+       case LCFG_NODEMAP_MAP_MODE:
+       {
+               char *p;
+               __u8 map_mode = 0;
+
+               if ((p = strstr(param, "all")) != NULL) {
+                       if ((p == param || *(p-1) == ',') &&
+                           (*(p+3) == '\0' || *(p+3) == ',')) {
+                               map_mode = NODEMAP_MAP_ALL;
+                       } else {
+                               rc = -EINVAL;
+                               break;
+                       }
+               } else {
+                       while ((p = strsep(&param, ",")) != NULL) {
+                               if (!*p)
+                                       break;
+
+                               if (strcmp("both", p) == 0)
+                                       map_mode |= NODEMAP_MAP_BOTH;
+                               else if (strcmp("uid_only", p) == 0 ||
+                                        strcmp("uid", p) == 0)
+                                       map_mode |= NODEMAP_MAP_UID;
+                               else if (strcmp("gid_only", p) == 0 ||
+                                        strcmp("gid", p) == 0)
+                                       map_mode |= NODEMAP_MAP_GID;
+                               else if (strcmp("projid_only", p) == 0 ||
+                                        strcmp("projid", p) == 0)
+                                       map_mode |= NODEMAP_MAP_PROJID;
+                               else
+                                       break;
+                       }
+                       if (p) {
+                               rc = -EINVAL;
+                               break;
+                       }
+               }
+
+               rc = nodemap_set_mapping_mode(nodemap_name, map_mode);
+               break;
+       }
+       case LCFG_NODEMAP_RBAC:
+       {
+               enum nodemap_rbac_roles rbac;
+               char *p;
+
+               if (strcmp(param, "all") == 0) {
+                       rbac = NODEMAP_RBAC_ALL;
+               } else if (strcmp(param, "none") == 0) {
+                       rbac = NODEMAP_RBAC_NONE;
+               } else {
+                       rbac = NODEMAP_RBAC_NONE;
+                       while ((p = strsep(&param, ",")) != NULL) {
+                               int i;
+
+                               if (!*p)
+                                       break;
+
+                               for (i = 0; i < ARRAY_SIZE(nodemap_rbac_names);
+                                    i++) {
+                                       if (strcmp(p,
+                                                nodemap_rbac_names[i].nrn_name)
+                                           == 0) {
+                                               rbac |=
+                                                nodemap_rbac_names[i].nrn_mode;
+                                               break;
+                                       }
+                               }
+                               if (i == ARRAY_SIZE(nodemap_rbac_names))
+                                       break;
+                       }
+                       if (p) {
+                               rc = -EINVAL;
+                               break;
+                       }
+               }
+
+               rc = nodemap_set_rbac(nodemap_name, rbac);
+               break;
+       }
+       case LCFG_NODEMAP_TRUSTED:
+               rc = kstrtobool(param, &bool_switch);
+               if (rc)
+                       break;
+               rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
+               break;
+       case LCFG_NODEMAP_SQUASH_UID:
+               rc = kstrtouint(param, 10, &int_id);
+               if (rc)
+                       break;
+               rc = nodemap_set_squash_uid(nodemap_name, int_id);
+               break;
+       case LCFG_NODEMAP_SQUASH_GID:
+               rc = kstrtouint(param, 10, &int_id);
+               if (rc)
+                       break;
+               rc = nodemap_set_squash_gid(nodemap_name, int_id);
+               break;
+       case LCFG_NODEMAP_SQUASH_PROJID:
+               rc = kstrtouint(param, 10, &int_id);
+               if (rc)
+                       break;
+               rc = nodemap_set_squash_projid(nodemap_name, int_id);
+               break;
+       case LCFG_NODEMAP_ADD_UIDMAP:
+       case LCFG_NODEMAP_ADD_GIDMAP:
+       case LCFG_NODEMAP_ADD_PROJIDMAP:
+               rc = nodemap_parse_idmap(param, idmap);
+               if (rc != 0)
+                       break;
+               if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
+                       rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
+                                              idmap);
+               else if (cmd == LCFG_NODEMAP_ADD_GIDMAP)
+                       rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
+                                              idmap);
+               else if (cmd == LCFG_NODEMAP_ADD_PROJIDMAP)
+                       rc = nodemap_add_idmap(nodemap_name, NODEMAP_PROJID,
+                                              idmap);
+               else
+                       rc = -EINVAL;
+               break;
+       case LCFG_NODEMAP_DEL_UIDMAP:
+       case LCFG_NODEMAP_DEL_GIDMAP:
+       case LCFG_NODEMAP_DEL_PROJIDMAP:
+               rc = nodemap_parse_idmap(param, idmap);
+               if (rc != 0)
+                       break;
+               if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
+                       rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
+                                              idmap);
+               else if (cmd == LCFG_NODEMAP_DEL_GIDMAP)
+                       rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
+                                              idmap);
+               else if (cmd == LCFG_NODEMAP_DEL_PROJIDMAP)
+                       rc = nodemap_del_idmap(nodemap_name, NODEMAP_PROJID,
+                                              idmap);
+               else
+                       rc = -EINVAL;
+               break;
+       case LCFG_NODEMAP_SET_FILESET:
+               rc = nodemap_set_fileset(nodemap_name, param);
+               break;
+       case LCFG_NODEMAP_SET_SEPOL:
+               rc = nodemap_set_sepol(nodemap_name, param);
+               break;
+       default:
+               rc = -EINVAL;
+       }
+
+       RETURN(rc);
+}
+
+int server_iocontrol_nodemap(struct obd_device *obd,
+                            struct obd_ioctl_data *data, bool dynamic)
+{
+       char name_buf[LUSTRE_NODEMAP_NAME_LENGTH + 1];
+       struct lustre_cfg *lcfg = NULL;
+       const char *nodemap_name = NULL;
+       const char *client_idstr = NULL;
+       const char *idtype_str = NULL;
+       const char *nidstr = NULL;
+       unsigned long client_id;
+       struct lnet_nid nid;
+       char *param = NULL;
+       char fs_idstr[16];
+       __u32 fs_id, cmd;
+       int idtype;
+       int rc = 0;
+
+       ENTRY;
+
+       if (data->ioc_plen1 > PAGE_SIZE)
+               GOTO(out, rc = -E2BIG);
+
+       OBD_ALLOC(lcfg, data->ioc_plen1);
+       if (lcfg == NULL)
+               GOTO(out, rc = -ENOMEM);
+
+       if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
+               GOTO(out_lcfg, rc = -EFAULT);
+
+       cmd = lcfg->lcfg_command;
+
+       switch (cmd) {
+       case LCFG_NODEMAP_ACTIVATE:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               param = lustre_cfg_string(lcfg, 1);
+               if (strcmp(param, "1") == 0)
+                       nodemap_activate(1);
+               else
+                       nodemap_activate(0);
+               break;
+       case LCFG_NODEMAP_ADD:
+       case LCFG_NODEMAP_DEL:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               rc = cfg_nodemap_cmd(cmd, nodemap_name, param, dynamic);
+               break;
+       case LCFG_NODEMAP_TEST_NID:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nidstr = lustre_cfg_string(lcfg, 1);
+               rc = libcfs_strnid(&nid, nidstr);
+               if (rc < 0)
+                       GOTO(out_lcfg, rc);
+
+               nodemap_test_nid(&nid, name_buf, sizeof(name_buf));
+               rc = copy_to_user(data->ioc_pbuf1, name_buf,
+                                 min_t(size_t, data->ioc_plen1,
+                                       sizeof(name_buf)));
+               if (rc != 0)
+                       GOTO(out_lcfg, rc = -EFAULT);
+               break;
+       case LCFG_NODEMAP_TEST_ID:
+               if (lcfg->lcfg_bufcount != 4)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nidstr = lustre_cfg_string(lcfg, 1);
+               idtype_str = lustre_cfg_string(lcfg, 2);
+               client_idstr = lustre_cfg_string(lcfg, 3);
+
+               rc = libcfs_strnid(&nid, nidstr);
+               if (rc < 0)
+                       GOTO(out_lcfg, rc);
+
+               if (strcmp(idtype_str, "uid") == 0)
+                       idtype = NODEMAP_UID;
+               else if (strcmp(idtype_str, "gid") == 0)
+                       idtype = NODEMAP_GID;
+               else if (strcmp(idtype_str, "projid") == 0)
+                       idtype = NODEMAP_PROJID;
+               else
+                       GOTO(out_lcfg, rc = -EINVAL);
+
+               rc = kstrtoul(client_idstr, 10, &client_id);
+               if (rc != 0)
+                       GOTO(out_lcfg, rc = -EINVAL);
+
+               rc = nodemap_test_id(&nid, idtype, client_id, &fs_id);
+               if (rc < 0)
+                       GOTO(out_lcfg, rc = -EINVAL);
+
+               if (data->ioc_plen1 < sizeof(fs_idstr))
+                       GOTO(out_lcfg, rc = -EINVAL);
+
+               snprintf(fs_idstr, sizeof(fs_idstr), "%u", fs_id);
+               if (copy_to_user(data->ioc_pbuf1, fs_idstr,
+                                sizeof(fs_idstr)) != 0)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               break;
+       case LCFG_NODEMAP_ADD_RANGE:
+       case LCFG_NODEMAP_DEL_RANGE:
+       case LCFG_NODEMAP_ADD_UIDMAP:
+       case LCFG_NODEMAP_DEL_UIDMAP:
+       case LCFG_NODEMAP_ADD_GIDMAP:
+       case LCFG_NODEMAP_DEL_GIDMAP:
+       case LCFG_NODEMAP_ADD_PROJIDMAP:
+       case LCFG_NODEMAP_DEL_PROJIDMAP:
+       case LCFG_NODEMAP_SET_FILESET:
+       case LCFG_NODEMAP_SET_SEPOL:
+               if (lcfg->lcfg_bufcount != 3)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               param = lustre_cfg_string(lcfg, 2);
+               rc = cfg_nodemap_cmd(cmd, nodemap_name, param, dynamic);
+               break;
+       case LCFG_NODEMAP_ADMIN:
+       case LCFG_NODEMAP_TRUSTED:
+       case LCFG_NODEMAP_DENY_UNKNOWN:
+       case LCFG_NODEMAP_SQUASH_UID:
+       case LCFG_NODEMAP_SQUASH_GID:
+       case LCFG_NODEMAP_SQUASH_PROJID:
+       case LCFG_NODEMAP_MAP_MODE:
+       case LCFG_NODEMAP_AUDIT_MODE:
+       case LCFG_NODEMAP_FORBID_ENCRYPT:
+       case LCFG_NODEMAP_READONLY_MOUNT:
+       case LCFG_NODEMAP_RBAC:
+               if (lcfg->lcfg_bufcount != 4)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               param = lustre_cfg_string(lcfg, 3);
+               rc = cfg_nodemap_cmd(cmd, nodemap_name, param, dynamic);
+               break;
+       default:
+               rc = -ENOTTY;
+       }
+
+       if (rc) {
+               CDEBUG_LIMIT(rc == -EEXIST ? D_INFO : D_ERROR,
+                            "%s: OBD_IOC_NODEMAP command %X for %s: rc = %d\n",
+                            obd->obd_name, lcfg->lcfg_command,
+                            nodemap_name, rc);
+               GOTO(out_lcfg, rc);
+       }
+
+out_lcfg:
+       OBD_FREE(lcfg, data->ioc_plen1);
+out:
+       RETURN(rc);
+}
+EXPORT_SYMBOL(server_iocontrol_nodemap);