Viewing: obd_sysfs.c
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 2011, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*
* Object Devices Class Driver
* These are the only exported functions, they provide some generic
* infrastructure for managing object devices
*/
#define DEBUG_SUBSYSTEM S_CLASS
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/lp.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/highmem.h>
#include <asm/io.h>
#include <asm/ioctls.h>
#include <asm/poll.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/seq_file.h>
#include <linux/kobject.h>
#include <linux/lnet/lnet_crypto.h>
#include <obd_support.h>
#include <obd_class.h>
#include <lprocfs_status.h>
#include <uapi/linux/lnet/lnetctl.h>
#include <uapi/linux/lustre/lustre_ioctl.h>
#include <uapi/linux/lustre/lustre_ver.h>
bool obd_enable_health_write;
EXPORT_SYMBOL(obd_enable_health_write);
bool obd_enable_fname_encoding = false;
EXPORT_SYMBOL(obd_enable_fname_encoding);
struct static_lustre_uintvalue_attr {
struct {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t len);
} u;
int *value;
};
static ssize_t static_uintvalue_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct static_lustre_uintvalue_attr *lattr = (void *)attr;
return sprintf(buf, "%d\n", *lattr->value);
}
static ssize_t static_uintvalue_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer, size_t count)
{
struct static_lustre_uintvalue_attr *lattr = (void *)attr;
unsigned int val;
int rc;
rc = kstrtouint(buffer, 10, &val);
if (rc)
return rc;
*lattr->value = val;
return count;
}
#define LUSTRE_STATIC_UINT_ATTR(name, value) \
static struct static_lustre_uintvalue_attr lustre_sattr_##name = \
{ __ATTR(name, 0644, static_uintvalue_show, \
static_uintvalue_store), value }
LUSTRE_STATIC_UINT_ATTR(debug_peer_on_timeout, &obd_debug_peer_on_timeout);
LUSTRE_STATIC_UINT_ATTR(dump_on_timeout, &obd_dump_on_timeout);
LUSTRE_STATIC_UINT_ATTR(at_min, &at_min);
LUSTRE_STATIC_UINT_ATTR(at_max, &at_max);
LUSTRE_STATIC_UINT_ATTR(at_extra, &at_extra);
LUSTRE_STATIC_UINT_ATTR(at_early_margin, &at_early_margin);
LUSTRE_STATIC_UINT_ATTR(at_history, &at_history);
LUSTRE_STATIC_UINT_ATTR(at_unhealthy_factor, &at_unhealthy_factor);
LUSTRE_STATIC_UINT_ATTR(enable_stats_header, &obd_enable_stats_header);
LUSTRE_STATIC_UINT_ATTR(ping_interval, &ping_interval);
#ifdef CONFIG_LUSTRE_FS_SERVER
LUSTRE_STATIC_UINT_ATTR(ldlm_timeout, &ldlm_timeout);
LUSTRE_STATIC_UINT_ATTR(bulk_timeout, &bulk_timeout);
static ssize_t expected_clients_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%u\n", class_expected_clients_get());
}
static ssize_t expected_clients_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer, size_t count)
{
unsigned int val;
int rc;
rc = kstrtouint(buffer, 10, &val);
if (rc)
return rc;
if (val == 0)
return -EINVAL;
if (val > LR_MAX_CLIENTS)
return -EINVAL;
class_expected_clients_set(val);
return count;
}
LUSTRE_RW_ATTR(expected_clients);
static ssize_t allow_register_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", allow_register);
}
static ssize_t allow_register_store(struct kobject *kobj,
struct attribute *attr, const char *buffer,
size_t count)
{
int val, rc;
rc = kstrtoint(buffer, 10, &val);
if (rc)
return rc;
allow_register = val;
return count;
}
LUSTRE_ATTR(allow_register, 0644, allow_register_show, allow_register_store);
#endif
static ssize_t memused_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return sprintf(buf, "%llu\n", obd_memory_sum());
}
LUSTRE_RO_ATTR(memused);
static ssize_t memused_max_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return sprintf(buf, "%llu\n", obd_memory_max());
}
LUSTRE_RO_ATTR(memused_max);
static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return sprintf(buf, "%lu\n",
obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT)));
}
static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
unsigned long val;
int rc;
rc = kstrtoul(buffer, 10, &val);
if (rc)
return rc;
val *= 1 << (20 - PAGE_SHIFT); /* convert to pages */
if (val > ((compat_totalram_pages() / 10) * 9)) {
/* Somebody wants to assign too much memory to dirty pages */
return -EINVAL;
}
if (val < 4 << (20 - PAGE_SHIFT)) {
/* Less than 4 Mb for dirty cache is also bad */
return -EINVAL;
}
obd_max_dirty_pages = val;
return count;
}
LUSTRE_RW_ATTR(max_dirty_mb);
#ifdef CONFIG_LUSTRE_FS_SERVER
static ssize_t no_transno_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer, size_t count)
{
struct obd_device *obd;
unsigned int idx;
int rc;
rc = kstrtouint(buffer, 10, &idx);
if (rc)
return rc;
obd = class_num2obd(idx);
if (!obd || !test_bit(OBDF_ATTACHED, obd->obd_flags)) {
if (obd)
CERROR("%s: not attached\n", obd->obd_name);
return -ENODEV;
}
spin_lock(&obd->obd_dev_lock);
obd->obd_no_transno = 1;
spin_unlock(&obd->obd_dev_lock);
return count;
}
LUSTRE_WO_ATTR(no_transno);
#endif /* CONFIG_LUSTRE_FS_SERVER */
static ssize_t version_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", LUSTRE_VERSION_STRING);
}
static ssize_t pinger_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
#ifdef CONFIG_LUSTRE_FS_PINGER
const char *state = "on";
#else
const char *state = "off";
#endif
return sprintf(buf, "%s\n", state);
}
/**
* Check all obd devices health
*
* \param kobj
* \param buf [in]
*
* \retval number of characters printed if healthy
*/
static ssize_t
health_check_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct obd_device *obd = NULL;
unsigned long dev_no = 0;
bool healthy = true;
size_t len = 0;
if (libcfs_catastrophe)
return sprintf(buf, "LBUG\n");
obd_device_lock();
obd_device_for_each_cond(dev_no, obd,
test_bit(OBDF_ATTACHED, obd->obd_flags) &&
test_bit(OBDF_SET_UP, obd->obd_flags) &&
!test_bit(OBDF_STOPPING, obd->obd_flags) &&
!obd->obd_read_only) {
LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
class_incref(obd, __func__, current);
obd_device_unlock();
if (obd_health_check(NULL, obd)) {
CERROR("%s: device reported unhealthy\n",
obd->obd_name);
healthy = false;
}
obd_device_lock();
class_decref(obd, __func__, current);
if (!healthy)
break;
}
obd_device_unlock();
if (healthy)
len = sprintf(buf, "healthy\n");
else
len = sprintf(buf, "NOT HEALTHY\n");
return len;
}
#ifdef CONFIG_LUSTRE_FS_SERVER
static ssize_t enable_health_write_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%u\n",
obd_enable_health_write);
}
static ssize_t enable_health_write_store(struct kobject *kobj,
struct attribute *attr,
const char *buf, size_t count)
{
int rc = 0;
rc = kstrtobool(buf, &obd_enable_health_write);
if (rc)
return rc;
return count;
}
LUSTRE_RW_ATTR(enable_health_write);
#endif /* CONFIG_LUSTRE_FS_SERVER */
static ssize_t enable_fname_encoding_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%u\n",
obd_enable_fname_encoding);
}
static ssize_t enable_fname_encoding_store(struct kobject *kobj,
struct attribute *attr,
const char *buf, size_t count)
{
int rc = 0;
rc = kstrtobool(buf, &obd_enable_fname_encoding);
if (rc)
return rc;
return count;
}
LUSTRE_RW_ATTR(enable_fname_encoding);
static ssize_t jobid_var_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
int rc = 0;
if (strlen(obd_jobid_var))
rc = scnprintf(buf, PAGE_SIZE, "%s\n", obd_jobid_var);
return rc;
}
static ssize_t jobid_var_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
if (!count || count > JOBSTATS_JOBID_VAR_MAX_LEN)
return -EINVAL;
memset(obd_jobid_var, 0, JOBSTATS_JOBID_VAR_MAX_LEN + 1);
memcpy(obd_jobid_var, buffer, count);
/* Trim the trailing '\n' if any */
if (obd_jobid_var[count - 1] == '\n')
obd_jobid_var[count - 1] = 0;
return count;
}
static ssize_t jobid_name_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
int rc = 0;
if (strlen(obd_jobid_name))
rc = scnprintf(buf, PAGE_SIZE, "%s\n", obd_jobid_name);
return rc;
}
static ssize_t jobid_name_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
if (!count || count > LUSTRE_JOBID_SIZE)
return -EINVAL;
if (strcmp(obd_jobid_var, JOBSTATS_NODELOCAL) != 0 &&
!strchr(buffer, '%')) {
lustre_jobid_clear(buffer);
return count;
}
/* clear previous value */
memset(obd_jobid_name, 0, LUSTRE_JOBID_SIZE);
memcpy(obd_jobid_name, buffer, count);
/* Trim the trailing '\n' if any */
if (obd_jobid_name[count - 1] == '\n') {
/* Don't echo just a newline */
if (count == 1)
return -EINVAL;
obd_jobid_name[count - 1] = 0;
}
return count;
}
static ssize_t jobid_this_session_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
char *jid;
int ret = -ENOENT;
rcu_read_lock();
jid = jobid_current();
if (jid)
ret = scnprintf(buf, PAGE_SIZE, "%s\n", jid);
rcu_read_unlock();
return ret;
}
static ssize_t jobid_this_session_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
char *jobid;
int len;
int ret;
if (!count || count > LUSTRE_JOBID_SIZE)
return -EINVAL;
jobid = kstrndup(buffer, count, GFP_KERNEL);
if (!jobid)
return -ENOMEM;
len = strcspn(jobid, "\n ");
jobid[len] = '\0';
ret = jobid_set_current(jobid);
kfree(jobid);
return ret ?: count;
}
static ssize_t timeout_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
return sprintf(buf, "%u\n", obd_timeout);
}
static ssize_t timeout_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
unsigned int val;
int rc;
rc = kstrtouint(buffer, 10, &val);
if (rc)
return rc;
obd_timeout = val ?: 1U;
ping_interval = max(obd_timeout / 4, 1U);
return count;
}
static ssize_t debug_raw_pointers_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", get_debug_raw_pointers());
}
static ssize_t debug_raw_pointers_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
bool initial = get_debug_raw_pointers();
bool val;
int rc;
rc = kstrtobool(buffer, &val);
if (rc)
return rc;
if ((initial && val) || (!initial && !val))
return count;
if (val) {
rc = debug_format_buffer_alloc_buffers();
if (rc)
return rc;
} else {
debug_format_buffer_free_buffers();
}
set_debug_raw_pointers(val);
return count;
}
static const char *const eviction_names[] = {
"1", /* DUMP_SUBS_OLD */
"llite", /* DUMP_PTLRPC_CONN */
"ldlm", /* DUMP_LDLM_LOCK */
"stale", /* DUMP_RECOVERY_STALE */
"pinger" /* DUMP_PINGER */
};
static inline const char *eviction_type2str(int type)
{
if (type >= 0 && type < ARRAY_SIZE(eviction_names))
return eviction_names[type];
return NULL;
}
static ssize_t dump_on_eviction_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
return cfs_mask2str(buf, PAGE_SIZE, obd_dump_on_eviction,
eviction_type2str, ' ');
}
static ssize_t both_on_eviction_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count, unsigned int *val)
{
u64 fl = *val;
u64 max_mask = (1 << (ARRAY_SIZE(eviction_names) + 1)) - 1;
int rc;
rc = kstrtou64(buffer, 0, &fl);
/* check flags fits to str array */
if (!rc && !(fl & ~max_mask)) {
*val = fl;
return count;
}
rc = cfs_str2mask(buffer, eviction_type2str, &fl, 0, max_mask, 0);
if (!rc && fl != *val)
*val = fl;
return count;
}
static ssize_t dump_on_eviction_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
return both_on_eviction_store(kobj, attr, buffer, count,
&obd_dump_on_eviction);
}
static ssize_t lbug_on_eviction_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
return cfs_mask2str(buf, PAGE_SIZE, obd_lbug_on_eviction,
eviction_type2str, ' ');
}
static ssize_t lbug_on_eviction_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
return both_on_eviction_store(kobj, attr, buffer, count,
&obd_lbug_on_eviction);
}
/* Root for /sys/kernel/debug/lustre */
struct dentry *debugfs_lustre_root;
EXPORT_SYMBOL_GPL(debugfs_lustre_root);
#ifdef CONFIG_PROC_FS
/* Root for /proc/fs/lustre */
struct proc_dir_entry *proc_lustre_root;
EXPORT_SYMBOL(proc_lustre_root);
#else
#define lprocfs_base NULL
#endif /* CONFIG_PROC_FS */
LUSTRE_RO_ATTR(version);
LUSTRE_RO_ATTR(pinger);
LUSTRE_RO_ATTR(health_check);
LUSTRE_RW_ATTR(jobid_var);
LUSTRE_RW_ATTR(jobid_name);
LUSTRE_RW_ATTR(jobid_this_session);
LUSTRE_RW_ATTR(timeout);
LUSTRE_RW_ATTR(debug_raw_pointers);
LUSTRE_RW_ATTR(dump_on_eviction);
LUSTRE_RW_ATTR(lbug_on_eviction);
static struct attribute *lustre_attrs[] = {
&lustre_attr_version.attr,
&lustre_attr_pinger.attr,
&lustre_sattr_enable_stats_header.u.attr,
&lustre_attr_health_check.attr,
&lustre_attr_jobid_name.attr,
&lustre_attr_jobid_var.attr,
&lustre_attr_jobid_this_session.attr,
&lustre_attr_timeout.attr,
&lustre_attr_debug_raw_pointers.attr,
&lustre_attr_max_dirty_mb.attr,
&lustre_sattr_debug_peer_on_timeout.u.attr,
&lustre_sattr_dump_on_timeout.u.attr,
&lustre_attr_dump_on_eviction.attr,
&lustre_sattr_at_min.u.attr,
&lustre_sattr_at_max.u.attr,
&lustre_sattr_at_extra.u.attr,
&lustre_sattr_at_early_margin.u.attr,
&lustre_sattr_at_history.u.attr,
&lustre_sattr_at_unhealthy_factor.u.attr,
&lustre_attr_memused_max.attr,
&lustre_attr_memused.attr,
#ifdef CONFIG_LUSTRE_FS_SERVER
&lustre_attr_allow_register.attr,
&lustre_attr_enable_health_write.attr,
&lustre_attr_expected_clients.attr,
&lustre_attr_no_transno.attr,
&lustre_sattr_bulk_timeout.u.attr,
&lustre_sattr_ldlm_timeout.u.attr,
#endif
&lustre_attr_enable_fname_encoding.attr,
&lustre_attr_lbug_on_eviction.attr,
&lustre_sattr_ping_interval.u.attr,
NULL,
};
static void *obd_device_list_seq_start(struct seq_file *p, loff_t *pos)
{
struct obd_device *obd;
unsigned long devno;
devno = *pos;
obd_device_lock();
obd = obd_device_find(devno);
if (!obd) {
obd_device_unlock();
return NULL;
}
*pos = devno;
class_incref(obd, "obd_device_list_seq", obd);
obd_device_unlock();
return obd;
}
static void obd_device_list_seq_stop(struct seq_file *p, void *v)
{
struct obd_device *obd = v;
if (!obd)
return;
obd_device_lock();
class_decref(obd, "obd_device_list_seq", obd);
obd_device_unlock();
}
static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos)
{
struct obd_device *obd = v;
unsigned long devno;
obd_device_lock();
class_decref(obd, "obd_device_list_seq", obd);
devno = *pos;
obd = obd_device_find_after(devno);
if (!obd) {
(*pos)++;
obd_device_unlock();
return NULL;
}
*pos = devno;
class_incref(obd, "obd_device_list_seq", obd);
obd_device_unlock();
return obd;
}
static int obd_device_list_seq_show(struct seq_file *p, void *v)
{
struct obd_device *obd = v;
char *status;
int dev_no;
if (!obd)
return 0;
LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
dev_no = obd->obd_minor;
if (test_bit(OBDF_STOPPING, obd->obd_flags))
status = "ST";
else if (obd->obd_inactive)
status = "IN";
else if (test_bit(OBDF_SET_UP, obd->obd_flags))
status = "UP";
else if (test_bit(OBDF_ATTACHED, obd->obd_flags))
status = "AT";
else
status = "--";
seq_printf(p, "%3d %s %s %s %s %d\n",
dev_no, status, obd->obd_type->typ_name,
obd->obd_name, obd->obd_uuid.uuid,
kref_read(&obd->obd_refcount));
return 0;
}
static const struct seq_operations obd_device_list_sops = {
.start = obd_device_list_seq_start,
.stop = obd_device_list_seq_stop,
.next = obd_device_list_seq_next,
.show = obd_device_list_seq_show,
};
static int obd_device_list_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = seq_open(file, &obd_device_list_sops);
if (rc)
return rc;
seq = file->private_data;
seq->private = inode->i_private;
return 0;
}
static const struct file_operations obd_device_list_fops = {
.owner = THIS_MODULE,
.open = obd_device_list_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
/* checksum_speed */
static void *checksum_speed_start(struct seq_file *p, loff_t *pos)
{
return pos;
}
static void checksum_speed_stop(struct seq_file *p, void *v)
{
}
static void *checksum_speed_next(struct seq_file *p, void *v, loff_t *pos)
{
++(*pos);
if (*pos >= CFS_HASH_ALG_SPEED_MAX - 1)
return NULL;
return pos;
}
static int checksum_speed_show(struct seq_file *p, void *v)
{
loff_t index = *(loff_t *)v;
if (!index || index > CFS_HASH_ALG_SPEED_MAX - 1)
return 0;
seq_printf(p, "%s: %d\n", cfs_crypto_hash_name(index),
cfs_crypto_hash_speeds[index]);
return 0;
}
static const struct seq_operations checksum_speed_sops = {
.start = checksum_speed_start,
.stop = checksum_speed_stop,
.next = checksum_speed_next,
.show = checksum_speed_show,
};
static int checksum_speed_open(struct inode *inode, struct file *file)
{
int rc = seq_open(file, &checksum_speed_sops);
if (rc)
return rc;
return 0;
}
static const struct file_operations checksum_speed_fops = {
.owner = THIS_MODULE,
.open = checksum_speed_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
struct kset *lustre_kset;
EXPORT_SYMBOL_GPL(lustre_kset);
static struct attribute_group lustre_attr_group = {
.attrs = lustre_attrs,
};
ssize_t class_set_global(const char *param)
{
const char *value = strchr(param, '=') + 1;
size_t off = value - param - 1;
ssize_t count = -ENOENT;
int i;
for (i = 0; lustre_attrs[i]; i++) {
if (!strncmp(lustre_attrs[i]->name, param, off)) {
count = lustre_attr_store(&lustre_kset->kobj,
lustre_attrs[i], value,
strlen(value));
break;
}
}
return count;
}
int class_procfs_init(void)
{
struct proc_dir_entry *entry;
int rc = -ENOMEM;
ENTRY;
lustre_kset = kset_create_and_add("lustre", NULL, fs_kobj);
if (!lustre_kset)
goto out;
/* Create the files associated with this kobject */
rc = sysfs_create_group(&lustre_kset->kobj, &lustre_attr_group);
if (rc) {
kset_unregister(lustre_kset);
goto out;
}
rc = jobid_cache_init();
if (rc) {
kset_unregister(lustre_kset);
goto out;
}
debugfs_lustre_root = debugfs_create_dir("lustre", NULL);
debugfs_create_file("devices", 0444, debugfs_lustre_root, NULL,
&obd_device_list_fops);
debugfs_create_file("checksum_speed", 0444, debugfs_lustre_root,
NULL, &checksum_speed_fops);
entry = lprocfs_register("fs/lustre", NULL, NULL, NULL);
if (IS_ERR(entry)) {
rc = PTR_ERR(entry);
CERROR("cannot create '/proc/fs/lustre': rc = %d\n", rc);
debugfs_remove_recursive(debugfs_lustre_root);
kset_unregister(lustre_kset);
goto out;
}
proc_lustre_root = entry;
out:
RETURN(rc);
}
int class_procfs_clean(void)
{
ENTRY;
debugfs_remove_recursive(debugfs_lustre_root);
debugfs_lustre_root = NULL;
jobid_cache_fini();
if (proc_lustre_root)
lprocfs_remove(&proc_lustre_root);
sysfs_remove_group(&lustre_kset->kobj, &lustre_attr_group);
kset_unregister(lustre_kset);
RETURN(0);
}
/* filename encoding */
#define ENCODE_FN_LEN BASE64URL_CHARS(sizeof(__u64)) + 2
#define FN_COUNT 64 /* must be power-of-two value */
const char *encode_fn_len(const char *fname, size_t namelen)
{
static char fn_array[FN_COUNT][ENCODE_FN_LEN];
static atomic_t fn_index;
char *new_fn = NULL;
char *tmp;
int encode_len = ENCODE_FN_LEN;
int rc;
__u64 hash;
CDEBUG(D_TRACE, "Process filename at %p\n", &fname);
if (!fname || !namelen || !obd_enable_fname_encoding)
return fname;
if (unlikely(namelen > NAME_MAX))
namelen = NAME_MAX;
hash = lustre_hash_fnv_1a_64(fname, namelen);
new_fn = fn_array[atomic_inc_return(&fn_index) & (FN_COUNT - 1)];
tmp = new_fn;
rc = gss_base64url_encode(&tmp, &encode_len, (__u8 *)&hash,
sizeof(hash));
if (rc < 0) {
if (encode_len == -1)
CERROR("Encode buffer size(%d) is too small: rc = %d\n",
(int)ENCODE_FN_LEN, rc);
else
CERROR("Failed to encode name(%zu): rc = %d\n",
namelen, rc);
}
return new_fn;
}
EXPORT_SYMBOL(encode_fn_len);