Viewing: nodemap_lproc.c
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2013, Trustees of Indiana University
*
* Copyright (c) 2014, 2017, Intel Corporation.
*
* Author: Joshua Walgenbach <jjw@iu.edu>
*/
#define NODEMAP_LDEBUGFS_ID_LEN 16
#define NODEMAP_LDEBUGFS_FLAG_LEN 2
#include <lprocfs_status.h>
#include <lustre_net.h>
#include <lustre_export.h>
#include <obd_class.h>
#include <linux/libcfs/libcfs_caps.h>
#include "nodemap_internal.h"
static LIST_HEAD(nodemap_pde_list);
/* nodemap debugfs root directory under lustre */
static struct dentry *nodemap_root;
/**
* nodemap_idmap_show() - Reads and prints the idmap for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative on failure
*/
static int nodemap_idmap_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
struct lu_idmap *idmap;
struct rb_node *node;
bool cont = false;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_puts(m, "[");
down_read(&nodemap->nm_idmap_lock);
for (node = rb_first(&nodemap->nm_client_to_fs_uidmap); node;
node = rb_next(node)) {
idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
if (idmap == NULL)
continue;
if (cont)
seq_puts(m, ",");
cont = true;
seq_printf(m, "\n { idtype: uid, client_id: %u, fs_id: %u }",
idmap->id_client, idmap->id_fs);
}
for (node = rb_first(&nodemap->nm_client_to_fs_gidmap);
node; node = rb_next(node)) {
idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
if (idmap == NULL)
continue;
if (cont)
seq_puts(m, ",");
cont = true;
seq_printf(m, "\n { idtype: gid, client_id: %u, fs_id: %u }",
idmap->id_client, idmap->id_fs);
}
for (node = rb_first(&nodemap->nm_client_to_fs_projidmap);
node; node = rb_next(node)) {
idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
if (idmap == NULL)
continue;
if (cont)
seq_puts(m, ",");
cont = true;
seq_printf(m, "\n { idtype: projid, client_id: %u, fs_id: %u }",
idmap->id_client, idmap->id_fs);
}
up_read(&nodemap->nm_idmap_lock);
if (cont)
seq_puts(m, "\n");
seq_printf(m, "]\n");
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_idmap_open() - Attaches nodemap_idmap_show to proc file.
* @inode: inode of seq file in proc fs
* @file: seq file
*
* Return:
* * %0 on success
* * %negative on failure
*/
static int nodemap_idmap_open(struct inode *inode, struct file *file)
{
return single_open(file, nodemap_idmap_show, inode->i_private);
}
/**
* nodemap_offset_seq_show() - Reads and prints the UID/GID/PROJID offsets for
* the given nodemap.
* @m: seq file in proc fs Return:
* @data: unused
*
* Return
* * %0 on success
* * %negative on failure
*/
static int nodemap_offset_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("%s: nodemap not found: rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_puts(m, "{\n");
seq_printf(m, " start_uid: %u,\n", nodemap->nm_offset_start_uid);
seq_printf(m, " limit_uid: %u,\n", nodemap->nm_offset_limit_uid);
seq_printf(m, " start_gid: %u,\n", nodemap->nm_offset_start_gid);
seq_printf(m, " limit_gid: %u,\n", nodemap->nm_offset_limit_gid);
seq_printf(m, " start_projid: %u,\n", nodemap->nm_offset_start_projid);
seq_printf(m, " limit_projid: %u\n", nodemap->nm_offset_limit_projid);
seq_puts(m, "}\n");
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_capabilities_seq_show() - Reads and prints capabilities definitions.
* @m: seq file in proc fs
* @unused: unused
*
* Return:
* * %0 on success
*/
static int nodemap_capabilities_seq_show(struct seq_file *m, void *unused)
{
struct lu_nodemap *nodemap;
const char *type;
char *caps;
u64 val;
int i, rc = 0;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("%s: nodemap not found: rc = %d\n",
(char *)m->private, rc);
return rc;
}
type = nodemap_captype_names[0].ncn_name;
for (i = 0; i < ARRAY_SIZE(nodemap_captype_names); i++) {
if (nodemap_captype_names[i].ncn_type ==
nodemap->nmf_caps_type) {
type = nodemap_captype_names[i].ncn_name;
break;
}
}
/* if not applicable, stop here */
if (nodemap->nmf_caps_type == NODEMAP_CAP_OFF) {
seq_printf(m, "%s\n", type);
goto out;
}
val = libcfs_cap2num(nodemap->nm_capabilities);
i = cfs_mask2str(NULL, 0, val, libcfs_cap2str, ',');
OBD_ALLOC(caps, i + 2);
if (!caps)
GOTO(out, rc = -ENOMEM);
cfs_mask2str(caps, i + 2, val, libcfs_cap2str, ',');
seq_printf(m, "type: %s\n", type);
seq_printf(m, "caps: %s", caps);
OBD_FREE(caps, i + 2);
out:
nodemap_putref(nodemap);
return rc;
}
/**
* nodemap_ranges_show() - Reads and prints the regular NID ranges
* for the given nodemap
* @m: seq file in proc fs
* @unused: unused
*
* Return:
* * %0 success
* * %-errno on failure
*/
static int nodemap_ranges_show(struct seq_file *m, void *unused)
{
struct lu_nodemap *nodemap;
struct lu_nid_range *range;
char start_nidstr[LNET_NIDSTR_SIZE];
char end_nidstr[LNET_NIDSTR_SIZE];
bool cont = false;
int rc;
mutex_lock(&active_config_lock);
nodemap = nodemap_lookup_locked(m->private);
if (IS_ERR(nodemap)) {
mutex_unlock(&active_config_lock);
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_puts(m, "[");
down_read(&active_config->nmc_range_tree_lock);
list_for_each_entry(range, &nodemap->nm_ranges, rn_list) {
if (cont)
seq_puts(m, ",");
cont = true;
libcfs_nidstr_r(&range->rn_start, start_nidstr, sizeof(start_nidstr));
libcfs_nidstr_r(&range->rn_end, end_nidstr, sizeof(end_nidstr));
seq_printf(m, "\n { id: %u, start_nid: %s, end_nid: %s }",
range->rn_id, start_nidstr, end_nidstr);
}
up_read(&active_config->nmc_range_tree_lock);
mutex_unlock(&active_config_lock);
if (cont)
seq_puts(m, "\n");
seq_printf(m, "]\n");
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_ranges_open() - Connects nodemap_ranges_show to proc file
* @inode: inode of seq file in proc fs
* @file: seq file
*
* Return:
* * %0 success
* * %-errno on failure
*/
static int nodemap_ranges_open(struct inode *inode, struct file *file)
{
return single_open(file, nodemap_ranges_show, inode->i_private);
}
/**
* nodemap_ban_ranges_show() - Reads and prints the banned NID ranges
* for the given nodemap
* @m: seq file in proc fs
* @unused: unused
*
* Return:
* * %0 success
* * %-errno on failure
*/
static int nodemap_ban_ranges_show(struct seq_file *m, void *unused)
{
char start_nidstr[LNET_NIDSTR_SIZE];
char end_nidstr[LNET_NIDSTR_SIZE];
struct lu_nodemap *nodemap;
struct lu_nid_range *range;
bool cont = false;
int rc;
mutex_lock(&active_config_lock);
nodemap = nodemap_lookup_locked(m->private);
if (IS_ERR(nodemap)) {
mutex_unlock(&active_config_lock);
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_puts(m, "[");
down_read(&active_config->nmc_ban_range_tree_lock);
list_for_each_entry(range, &nodemap->nm_ban_ranges, rn_list) {
if (cont)
seq_puts(m, ",");
cont = true;
libcfs_nidstr_r(&range->rn_start, start_nidstr,
sizeof(start_nidstr));
libcfs_nidstr_r(&range->rn_end, end_nidstr, sizeof(end_nidstr));
seq_printf(m, "\n { id: %u, start_nid: %s, end_nid: %s }",
range->rn_id, start_nidstr, end_nidstr);
}
up_read(&active_config->nmc_ban_range_tree_lock);
mutex_unlock(&active_config_lock);
if (cont)
seq_puts(m, "\n");
seq_printf(m, "]\n");
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_ban_ranges_open() - Connects nodemap_ban_ranges_show to proc file
* @inode: inode of seq file in proc fs
* @file: seq file
*
* Return:
* * %0 success
* * %-errno on failure
*/
static int nodemap_ban_ranges_open(struct inode *inode, struct file *file)
{
return single_open(file, nodemap_ban_ranges_show, inode->i_private);
}
/**
* nodemap_fileset_seq_show() - Reads and prints fileset for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return
* * %0 on success
* * %negative on failure
*/
static int nodemap_fileset_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
struct lu_fileset_alt *fileset_alt;
struct rb_node *node;
bool cont = false;
int rc = 0;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_puts(m, "[");
if (nodemap->nm_fileset_prim && nodemap->nm_fileset_prim[0] != '\0') {
seq_printf(m, "\n { primary: %s%s }",
nodemap->nm_fileset_prim,
nodemap->nm_fileset_prim_ro ? ", mode: ro" : "");
cont = true;
}
down_read(&nodemap->nm_fileset_alt_lock);
for (node = rb_first(&nodemap->nm_fileset_alt); node;
node = rb_next(node)) {
if (cont)
seq_puts(m, ",");
cont = true;
fileset_alt = rb_entry(node, struct lu_fileset_alt, nfa_rb);
seq_printf(m, "\n { alternate: %s%s }", fileset_alt->nfa_path,
fileset_alt->nfa_ro ? ", mode: ro" : "");
}
up_read(&nodemap->nm_fileset_alt_lock);
seq_puts(m, "\n]\n");
nodemap_putref(nodemap);
return rc;
}
/**
* nodemap_fileset_seq_write() - Set a fileset on a nodemap.
* @file: proc file
* @buffer: string, "<fileset>"
* @count: @buffer length
* @off: unused
*
* Return
* * %0 on success
* * %negative on failure
*/
static ssize_t
nodemap_fileset_seq_write(struct file *file,
const char __user *buffer,
size_t count, loff_t *off)
{
struct seq_file *m = file->private_data;
char *nm_fileset;
int rc = 0;
ENTRY;
if (count == 0)
RETURN(0);
if (count > PATH_MAX)
RETURN(-EINVAL);
OBD_ALLOC(nm_fileset, count + 1);
/* OBD_ALLOC zero-fills the buffer */
if (nm_fileset == NULL)
RETURN(-ENOMEM);
if (copy_from_user(nm_fileset, buffer, count))
GOTO(out, rc = -EFAULT);
rc = nodemap_set_fileset_prim_lproc(m->private, nm_fileset, false);
if (rc != 0)
GOTO(out, rc = -EINVAL);
rc = count;
out:
OBD_FREE(nm_fileset, count + 1);
return rc;
}
LDEBUGFS_SEQ_FOPS(nodemap_fileset);
/**
* nodemap_sepol_seq_show() - Reads/prints SELinux policy info for given nodemap
* @m: seq file in proc fs
* @data: unused
*
* Return
* * %0 on success
* * %negative on failure
*/
static int nodemap_sepol_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc = 0;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%s\n", nodemap_get_sepol(nodemap));
nodemap_putref(nodemap);
return rc;
}
/**
* nodemap_sepol_seq_write() - Set SELinux policy info on a nodemap.
* @file: proc file
* @buffer: string, "<sepol>"
* @count: @buffer length
* @off: unused
*
* Return
* * %0 on success
* * %negative on failure
*/
static ssize_t
nodemap_sepol_seq_write(struct file *file,
const char __user *buffer,
size_t count, loff_t *off)
{
struct seq_file *m = file->private_data;
char sepol[LUSTRE_NODEMAP_SEPOL_LENGTH + 1];
int rc = 0;
BUILD_BUG_ON(sizeof(sepol) !=
sizeof(((struct lu_nodemap *)0)->nm_sepol));
if (count > 0) {
if (count >= sizeof(sepol))
GOTO(out, rc = -ENAMETOOLONG);
if (copy_from_user(sepol, buffer, count))
GOTO(out, rc = -EFAULT);
sepol[count] = '\0';
rc = nodemap_set_sepol(m->private, sepol, false);
}
out:
if (rc != 0)
return rc;
return count;
}
LDEBUGFS_SEQ_FOPS(nodemap_sepol);
/**
* nodemap_exports_show() - Reads and prints the exports attached
* to the given nodemap
* @m: seq file in proc fs, stores nodemap
* @unused: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_exports_show(struct seq_file *m, void *unused)
{
struct lu_nodemap *nodemap;
struct obd_export *exp;
char nidstr[LNET_NIDSTR_SIZE];
bool cont = false;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_puts(m, "[");
mutex_lock(&nodemap->nm_member_list_lock);
list_for_each_entry(exp, &nodemap->nm_member_list,
exp_target_data.ted_nodemap_member) {
if (exp->exp_connection)
libcfs_nidstr_r(&exp->exp_connection->c_peer.nid,
nidstr, sizeof(nidstr));
else
strscpy(nidstr, "<unknown>", sizeof(nidstr));
if (cont)
seq_puts(m, ",");
cont = true;
seq_printf(m, "\n { nid: %s, uuid: %s, dev: %s%s }", nidstr,
exp->exp_client_uuid.uuid, exp->exp_obd->obd_name,
exp->exp_banned ? ", banned: true" : "");
}
mutex_unlock(&nodemap->nm_member_list_lock);
if (cont)
seq_puts(m, "\n");
seq_printf(m, "]\n");
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_exports_open() - Attaches nodemap_exports_show to proc file
* @inode: inode of seq file in proc fs
* @file: seq file
*
* Return:
* * %0 success
* * %-errno on failure
*/
static int nodemap_exports_open(struct inode *inode, struct file *file)
{
return single_open(file, nodemap_exports_show, inode->i_private);
}
/**
* nodemap_active_seq_show() - Reads and prints active flag for given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
*/
static int nodemap_active_seq_show(struct seq_file *m, void *data)
{
seq_printf(m, "%u\n", (unsigned int)nodemap_active);
return 0;
}
/**
* nodemap_active_seq_write() - Activate/deactivate nodemap.
* @file: proc file
* @buffer: string, "1" or "0" to activate/deactivate nodemap
* @count: @buffer length
* @off: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static ssize_t
nodemap_active_seq_write(struct file *file, const char __user *buffer,
size_t count, loff_t *off)
{
char active_string[NODEMAP_LDEBUGFS_FLAG_LEN + 1];
unsigned long active;
int rc;
if (count == 0)
return 0;
if (count >= sizeof(active_string))
return -EINVAL;
if (copy_from_user(active_string, buffer, count))
return -EFAULT;
active_string[count] = '\0';
rc = kstrtoul(active_string, 10, &active);
if (rc != 0)
return -EINVAL;
rc = nodemap_activate(active);
return rc ? rc : count;
}
LDEBUGFS_SEQ_FOPS(nodemap_active);
/**
* nodemap_id_seq_show() - Reads and prints the nodemap ID for the given nodemap
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_id_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
int rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%u\n", nodemap->nm_id);
nodemap_putref(nodemap);
return 0;
}
LDEBUGFS_SEQ_FOPS_RO(nodemap_id);
/**
* nodemap_squash_uid_seq_show() - Read/print root squash UID for given nodemap
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
int rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%u\n", nodemap->nm_squash_uid);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_squash_gid_seq_show() - Read/print root squash GID for given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
int rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%u\n", nodemap->nm_squash_gid);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_squash_projid_seq_show() - Read/print squash PROJID for given nodemap
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_squash_projid_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
int rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%u\n", nodemap->nm_squash_projid);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_trusted_seq_show() - Read/print trusted flag for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_trusted_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
int rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_admin_seq_show() - Read/print the admin flag for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_admin_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_map_mode_seq_show() - Read/print mapping mode for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_map_mode_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
bool need_sep = false;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
if (nodemap->nmf_map_mode == NODEMAP_MAP_ALL) {
seq_puts(m, "all\n");
} else {
if (nodemap->nmf_map_mode & NODEMAP_MAP_UID) {
seq_puts(m, "uid");
need_sep = true;
}
if (nodemap->nmf_map_mode & NODEMAP_MAP_GID) {
seq_puts(m, need_sep ? ",gid" : "gid");
need_sep = true;
}
if (nodemap->nmf_map_mode & NODEMAP_MAP_PROJID)
seq_puts(m, need_sep ? ",projid" : "projid");
seq_puts(m, "\n");
}
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_rbac_seq_show() - Reads and prints the rbac for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_rbac_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
char *sep = "";
int i, rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
if (nodemap->nmf_rbac == NODEMAP_RBAC_ALL) {
for (i = 0; i < ARRAY_SIZE(nodemap_rbac_names); i++) {
/* local_admin only makes sense on non default nodemap
* where root can be mapped or offset
*/
if (nodemap_rbac_names[i].nrn_mode ==
NODEMAP_RBAC_LOCAL_ADMIN &&
is_default_nodemap(nodemap))
continue;
seq_printf(m, "%s%s", i == 0 ? "" : ",",
nodemap_rbac_names[i].nrn_name);
}
seq_puts(m, "\n");
} else if (nodemap->nmf_rbac == NODEMAP_RBAC_NONE) {
seq_puts(m, "none\n");
} else {
for (i = 0; i < ARRAY_SIZE(nodemap_rbac_names); i++) {
if (nodemap->nmf_rbac &
nodemap_rbac_names[i].nrn_mode) {
seq_printf(m, "%s%s", sep,
nodemap_rbac_names[i].nrn_name);
sep = ",";
}
}
seq_puts(m, "\n");
}
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_deny_unknown_seq_show() - Read/print deny_unknown flag for given
* nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_deny_unknown_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_deny_unknown);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_audit_mode_seq_show() - Reads and prints the audit_mode flag for the
* given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_audit_mode_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_enable_audit);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_forbid_encryption_seq_show() - Reads and prints the forbid_encryption
* flag for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_forbid_encryption_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_forbid_encryption);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_raise_privs_seq_show() - Reads and prints the raise_privs property
* for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_raise_privs_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
char *sep = "";
int i, rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
if (nodemap->nmf_raise_privs == NODEMAP_RAISE_PRIV_ALL) {
for (i = 0; i < ARRAY_SIZE(nodemap_priv_names); i++)
seq_printf(m, "%s%s", i == 0 ? "" : ",",
nodemap_priv_names[i].npn_name);
sep = ",";
} else if (nodemap->nmf_raise_privs == NODEMAP_RAISE_PRIV_NONE) {
seq_puts(m, "none");
} else {
for (i = 0; i < ARRAY_SIZE(nodemap_priv_names); i++) {
if (nodemap->nmf_raise_privs &
nodemap_priv_names[i].npn_priv) {
seq_printf(m, "%s%s", sep,
nodemap_priv_names[i].npn_name);
sep = ",";
}
}
}
if (!(nodemap->nmf_raise_privs & NODEMAP_RAISE_PRIV_RBAC))
goto putref;
if (nodemap->nmf_rbac_raise == NODEMAP_RBAC_ALL) {
for (i = 0; i < ARRAY_SIZE(nodemap_rbac_names); i++) {
seq_printf(m, "%s%s", sep,
nodemap_rbac_names[i].nrn_name);
sep = ",";
}
} else if (nodemap->nmf_rbac_raise != NODEMAP_RBAC_NONE) {
for (i = 0; i < ARRAY_SIZE(nodemap_rbac_names); i++) {
if (nodemap->nmf_rbac_raise &
nodemap_rbac_names[i].nrn_mode) {
seq_printf(m, "%s%s", sep,
nodemap_rbac_names[i].nrn_name);
sep = ",";
}
}
}
putref:
seq_puts(m, "\n");
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_readonly_mount_seq_show() - Reads and prints the readonly_mount flag
* for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_readonly_mount_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_readonly_mount);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_deny_mount_seq_show() - Reads and prints the deny_mount flag for the
* given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_deny_mount_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_deny_mount);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_parent_seq_show() - Reads and prints the name of the parent nodemap
* for the given nodemap.
* @seq: seq file in proc fs
* @data: unused
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
static int nodemap_parent_seq_show(struct seq_file *seq, void *data)
{
struct lu_nodemap *nodemap;
char *pname;
int rc;
nodemap = nodemap_lookup_unlocked(seq->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)seq->private, rc);
return rc;
}
if (nodemap->nm_dyn) {
if (nodemap->nm_parent_nm)
pname = nodemap->nm_parent_nm->nm_name;
else
pname = DEFAULT_NODEMAP;
} else {
pname = "";
}
seq_printf(seq, "%s\n", pname);
nodemap_putref(nodemap);
return 0;
}
/**
* nodemap_gssonly_identify_seq_show() - Reads & prints gssonly_identification
* flag for the given nodemap.
* @m: seq file in proc fs
* @data: unused
*
* Returns:
* * %0 success
* * %negative failure
*/
static int nodemap_gssonly_identify_seq_show(struct seq_file *m, void *data)
{
struct lu_nodemap *nodemap;
int rc;
nodemap = nodemap_lookup_unlocked(m->private);
if (IS_ERR(nodemap)) {
rc = PTR_ERR(nodemap);
CERROR("cannot find nodemap '%s': rc = %d\n",
(char *)m->private, rc);
return rc;
}
seq_printf(m, "%d\n", (int)nodemap->nmf_gss_identify);
nodemap_putref(nodemap);
return 0;
}
static struct ldebugfs_vars lprocfs_nm_module_vars[] = {
{
.name = "active",
.fops = &nodemap_active_fops,
},
{
NULL
}
};
LDEBUGFS_SEQ_FOPS_RO(nodemap_trusted);
LDEBUGFS_SEQ_FOPS_RO(nodemap_admin);
LDEBUGFS_SEQ_FOPS_RO(nodemap_squash_uid);
LDEBUGFS_SEQ_FOPS_RO(nodemap_squash_gid);
LDEBUGFS_SEQ_FOPS_RO(nodemap_squash_projid);
LDEBUGFS_SEQ_FOPS_RO(nodemap_deny_unknown);
LDEBUGFS_SEQ_FOPS_RO(nodemap_map_mode);
LDEBUGFS_SEQ_FOPS_RO(nodemap_offset);
LDEBUGFS_SEQ_FOPS_RO(nodemap_capabilities);
LDEBUGFS_SEQ_FOPS_RO(nodemap_rbac);
LDEBUGFS_SEQ_FOPS_RO(nodemap_audit_mode);
LDEBUGFS_SEQ_FOPS_RO(nodemap_forbid_encryption);
LDEBUGFS_SEQ_FOPS_RO(nodemap_raise_privs);
LDEBUGFS_SEQ_FOPS_RO(nodemap_readonly_mount);
LDEBUGFS_SEQ_FOPS_RO(nodemap_deny_mount);
LDEBUGFS_SEQ_FOPS_RO(nodemap_parent);
LDEBUGFS_SEQ_FOPS_RO(nodemap_gssonly_identify);
static const struct file_operations nodemap_ranges_fops = {
.open = nodemap_ranges_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release
};
static const struct file_operations nodemap_ban_ranges_fops = {
.open = nodemap_ban_ranges_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release
};
static const struct file_operations nodemap_idmap_fops = {
.open = nodemap_idmap_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release
};
static const struct file_operations nodemap_exports_fops = {
.open = nodemap_exports_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release
};
static struct ldebugfs_vars lprocfs_nodemap_vars[] = {
/* in alphabetical order */
{
.name = "admin_nodemap",
.fops = &nodemap_admin_fops,
},
{
.name = "audit_mode",
.fops = &nodemap_audit_mode_fops,
},
{
.name = "deny_unknown",
.fops = &nodemap_deny_unknown_fops,
},
{
.name = "enable_cap_mask",
.fops = &nodemap_capabilities_fops,
},
{
.name = "exports",
.fops = &nodemap_exports_fops,
},
{
.name = "fileset",
.fops = &nodemap_fileset_fops,
},
{
.name = "forbid_encryption",
.fops = &nodemap_forbid_encryption_fops,
},
{
.name = "gssonly_identification",
.fops = &nodemap_gssonly_identify_fops,
},
{
.name = "id",
.fops = &nodemap_id_fops,
},
{
.name = "idmap",
.fops = &nodemap_idmap_fops,
},
{
.name = "offset",
.fops = &nodemap_offset_fops,
},
{
.name = "map_mode",
.fops = &nodemap_map_mode_fops,
},
{
.name = "parent",
.fops = &nodemap_parent_fops,
},
{
.name = "child_raise_privileges",
.fops = &nodemap_raise_privs_fops,
},
{
.name = "ranges",
.fops = &nodemap_ranges_fops,
},
{
.name = "banlist",
.fops = &nodemap_ban_ranges_fops,
},
{
.name = "rbac",
.fops = &nodemap_rbac_fops,
},
{
.name = "readonly_mount",
.fops = &nodemap_readonly_mount_fops,
},
{
.name = "deny_mount",
.fops = &nodemap_deny_mount_fops,
},
{
.name = "sepol",
.fops = &nodemap_sepol_fops,
},
{
.name = "squash_gid",
.fops = &nodemap_squash_gid_fops,
},
{
.name = "squash_projid",
.fops = &nodemap_squash_projid_fops,
},
{
.name = "squash_uid",
.fops = &nodemap_squash_uid_fops,
},
{
.name = "trusted_nodemap",
.fops = &nodemap_trusted_fops,
},
{
NULL
}
};
static struct ldebugfs_vars lprocfs_default_nodemap_vars[] = {
/* in alphabetical order */
{
.name = "admin_nodemap",
.fops = &nodemap_admin_fops,
},
{
.name = "audit_mode",
.fops = &nodemap_audit_mode_fops,
},
{
.name = "deny_unknown",
.fops = &nodemap_deny_unknown_fops,
},
{
.name = "enable_cap_mask",
.fops = &nodemap_capabilities_fops,
},
{
.name = "exports",
.fops = &nodemap_exports_fops,
},
{
.name = "fileset",
.fops = &nodemap_fileset_fops,
},
{
.name = "forbid_encryption",
.fops = &nodemap_forbid_encryption_fops,
},
{
.name = "id",
.fops = &nodemap_id_fops,
},
{
.name = "map_mode",
.fops = &nodemap_map_mode_fops,
},
{
.name = "child_raise_privileges",
.fops = &nodemap_raise_privs_fops,
},
{
.name = "banlist",
.fops = &nodemap_ban_ranges_fops,
},
{
.name = "rbac",
.fops = &nodemap_rbac_fops,
},
{
.name = "readonly_mount",
.fops = &nodemap_readonly_mount_fops,
},
{
.name = "deny_mount",
.fops = &nodemap_deny_mount_fops,
},
{
.name = "squash_gid",
.fops = &nodemap_squash_gid_fops,
},
{
.name = "squash_projid",
.fops = &nodemap_squash_projid_fops,
},
{
.name = "squash_uid",
.fops = &nodemap_squash_uid_fops,
},
{
.name = "trusted_nodemap",
.fops = &nodemap_trusted_fops,
},
{
NULL
}
};
/**
* nodemap_procfs_init() - Initialize the nodemap procfs directory.
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
int nodemap_procfs_init(void)
{
int rc = 0;
nodemap_root = debugfs_create_dir(LUSTRE_NODEMAP_NAME,
debugfs_lustre_root);
if (!nodemap_root) {
int rc = -EINVAL;
CERROR("cannot create 'nodemap' directory: rc = %d\n",
rc);
} else {
ldebugfs_add_vars(nodemap_root, lprocfs_nm_module_vars, NULL);
}
return rc;
}
/*
* Cleanup nodemap proc entry data structures.
*/
void nodemap_procfs_exit(void)
{
struct nodemap_pde *nm_pde;
struct nodemap_pde *tmp;
debugfs_remove_recursive(nodemap_root);
list_for_each_entry_safe(nm_pde, tmp, &nodemap_pde_list,
npe_list_member) {
list_del(&nm_pde->npe_list_member);
OBD_FREE_PTR(nm_pde);
}
}
/*
* Remove a nodemap's procfs entry and related data.
*/
void lprocfs_nodemap_remove(struct nodemap_pde *nm_pde)
{
debugfs_remove_recursive(nm_pde->npe_debugfs_entry);
list_del(&nm_pde->npe_list_member);
OBD_FREE_PTR(nm_pde);
}
/**
* lprocfs_nodemap_register() - Register the proc directory for a nodemap
* @nodemap: nodemap to make the proc dir for
* @is_default: 1 if default nodemap
*
* Return:
* * %0 on success
* * %negative error code on failure
*/
int lprocfs_nodemap_register(struct lu_nodemap *nodemap, bool is_default)
{
struct nodemap_pde *nm_entry;
int rc = 0;
OBD_ALLOC_PTR(nm_entry);
if (!nm_entry)
GOTO(out, rc = -ENOMEM);
nm_entry->npe_debugfs_entry = debugfs_create_dir(nodemap->nm_name,
nodemap_root);
if (!nm_entry->npe_debugfs_entry)
GOTO(out, rc = -ENOENT);
snprintf(nm_entry->npe_name, sizeof(nm_entry->npe_name), "%s",
nodemap->nm_name);
/* Use the nodemap name as stored on the PDE as the private data. This
* is so a nodemap struct can be replaced without updating the proc
* entries.
*/
ldebugfs_add_vars(nm_entry->npe_debugfs_entry,
(is_default ? lprocfs_default_nodemap_vars :
lprocfs_nodemap_vars),
nm_entry->npe_name);
list_add(&nm_entry->npe_list_member, &nodemap_pde_list);
out:
if (rc != 0) {
CERROR("cannot create 'nodemap/%s': rc = %d\n",
nodemap->nm_name, rc);
if (nm_entry != NULL) {
OBD_FREE_PTR(nm_entry);
nm_entry = NULL;
}
}
nodemap->nm_pde_data = nm_entry;
return rc;
}