Viewing: lproc_osp.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) 2012, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*
* Lustre OST Proxy Device (OSP), procfs functions
*
* Author: Alex Zhuravlev <alexey.zhuravlev@intel.com>
*/
#define DEBUG_SUBSYSTEM S_CLASS
#include <lustre_log.h>
#include "osp_internal.h"
/**
* active_show() - Show OSP active status
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t active_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
struct obd_import *imp;
int rc;
if (!obd)
return -ENOENT;
with_imp_locked(obd, imp, rc)
rc = scnprintf(buf, PAGE_SIZE, "%d\n",
!test_bit(IMPF_DEACTIVE, imp->imp_flags));
return rc;
}
/**
* active_store() - Activate/Deactivate OSP
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string, which is "1" or "0" to
* activate/deactivate OSP)
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t active_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
struct obd_import *imp, *imp0;
bool val;
int rc;
rc = kstrtobool(buffer, &val);
if (rc)
return rc;
with_imp_locked(obd, imp0, rc)
imp = class_import_get(imp0);
if (rc)
return rc;
/* opposite senses */
if (test_bit(IMPF_DEACTIVE, imp->imp_flags) == val)
rc = ptlrpc_set_import_active(imp, val);
else
CDEBUG(D_CONFIG, "activate %u: ignoring repeat request\n",
(unsigned int)val);
class_import_put(imp);
return rc ?: count;
}
LUSTRE_RW_ATTR(active);
/**
* sync_in_flight_show() - Show number of RPCs in flight
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t sync_in_flight_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n", atomic_read(&osp->opd_sync_rpcs_in_flight));
}
LUSTRE_RO_ATTR(sync_in_flight);
/**
* sync_in_progress_show() - Show number of RPCs in processing
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t sync_in_progress_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n", atomic_read(&osp->opd_sync_rpcs_in_progress));
}
LUSTRE_RO_ATTR(sync_in_progress);
/**
* sync_changes_show() - Show number of changes to sync
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t sync_changes_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n", atomic_read(&osp->opd_sync_changes));
}
/**
* sync_changes_store() - Sync changes
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t sync_changes_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
struct lu_env env;
int rc;
rc = lu_env_init(&env, LCT_LOCAL);
if (rc != 0)
return rc;
rc = dt_sync(&env, &osp->opd_dt_dev);
lu_env_fini(&env);
return rc == 0 ? count : rc;
}
LUSTRE_RW_ATTR(sync_changes);
static ssize_t max_sync_changes_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n", osp->opd_sync_max_changes);
}
static ssize_t max_sync_changes_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
int val;
int rc;
rc = kstrtoint(buffer, 0, &val);
if (rc)
return rc;
if (val <= 0)
return -ERANGE;
osp->opd_sync_max_changes = val;
return count;
}
LUSTRE_RW_ATTR(max_sync_changes);
static ssize_t sync_current_llog_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
struct llog_handle *cath, *lgh;
struct llog_ctxt *ctxt;
struct llog_logid *catid = NULL;
struct llog_logid *plid = NULL;
int rc = 0;
ctxt = llog_get_context(osp->opd_obd, LLOG_MDS_OST_ORIG_CTXT);
if (IS_ERR_OR_NULL(ctxt))
return 0;
cath = ctxt->loc_handle;
if (!cath || !cath->lgh_hdr)
goto out;
LASSERT(cath->lgh_hdr->llh_flags & LLOG_F_IS_CAT);
catid = &cath->lgh_id;
lgh = cath->u.chd.chd_current_log;
if (lgh) {
plid = &lgh->lgh_id;
rc = snprintf(buf, PAGE_SIZE,
DFID" (%d plains), current "DFID"\n",
PLOGID(catid),
cath->lgh_hdr ? cath->lgh_hdr->llh_count : 0,
PLOGID(plid));
} else {
rc = snprintf(buf, PAGE_SIZE,
DFID" (%d plains)\n", PLOGID(catid),
cath->lgh_hdr ? cath->lgh_hdr->llh_count : 0);
}
out:
llog_ctxt_put(ctxt);
return rc;
}
LUSTRE_RO_ATTR(sync_current_llog);
/**
* max_rpcs_in_flight_show() - Show maximum number of RPCs in flight allowed
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t max_rpcs_in_flight_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n", osp->opd_sync_max_rpcs_in_flight);
}
/**
* max_rpcs_in_flight_store() - Change maximum number of RPCs in flight allowed
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string which represents maximum number)
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t max_rpcs_in_flight_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
rc = kstrtouint(buffer, 0, &val);
if (rc)
return rc;
if (val == 0)
return -ERANGE;
osp->opd_sync_max_rpcs_in_flight = val;
return count;
}
LUSTRE_RW_ATTR(max_rpcs_in_flight);
static ssize_t max_mod_rpcs_in_flight_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
u16 max;
max = obd_get_max_mod_rpcs_in_flight(&obd->u.cli);
return scnprintf(buf, PAGE_SIZE, "%hu\n", max);
}
static ssize_t max_mod_rpcs_in_flight_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
u16 val;
int rc;
rc = kstrtou16(buffer, 10, &val);
if (rc)
return rc;
rc = obd_set_max_mod_rpcs_in_flight(&obd->u.cli, val);
if (rc)
count = rc;
return count;
}
LUSTRE_RW_ATTR(max_mod_rpcs_in_flight);
/**
* max_rpcs_in_progress_show() - Show maximum number of RPCs in processing
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t max_rpcs_in_progress_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n", osp->opd_sync_max_rpcs_in_progress);
}
/**
* max_rpcs_in_progress_store() - Change maximum number of RPCs in processing
* allowed
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string which represents maximum number)
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t max_rpcs_in_progress_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
rc = kstrtouint(buffer, 0, &val);
if (rc)
return rc;
if (val == 0)
return -ERANGE;
osp->opd_sync_max_rpcs_in_progress = val;
return count;
}
LUSTRE_RW_ATTR(max_rpcs_in_progress);
/**
* create_count_show() - Show number of objects to precreate next time
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t create_count_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
if (!osp->opd_pre)
return -EINVAL;
return sprintf(buf, "%d\n", osp->opd_pre_create_count);
}
/**
* create_count_store() - Change number of objects to precreate next time
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string represents number of objs to
* precreate)
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t create_count_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
if (!osp->opd_pre)
return -EINVAL;
rc = kstrtouint(buffer, 0, &val);
if (rc)
return rc;
/* The MDT ALWAYS needs to limit the precreate count to
* OST_MAX_PRECREATE, and the constant cannot be changed
* because it is a value shared between the OSP and OST
* that is the maximum possible number of objects that will
* ever be handled by MDT->OST recovery processing.
*
* The OSP enforces the pre_create_count to amaximum of
* one half of opd_pre_max_create_count.
*
* If the OST ever gets a request to delete more orphans,
* this implies that something has gone badly on the MDT
* and the OST will refuse to delete so much data from the
* filesystem as a safety measure.
*/
if (val < OST_MIN_PRECREATE)
return -ERANGE;
if (val > osp->opd_pre_max_create_count / 2)
val = osp->opd_pre_max_create_count / 2;
/* set to largest value <= 32, 64, 128 or a multiple of 256 */
if (val > 256)
osp->opd_pre_create_count = val & 0xffffff00;
else
osp->opd_pre_create_count = rounddown_pow_of_two(val);
if (osp->opd_pre_create_count + osp->opd_pre_reserved >
osp_objs_precreated(osp))
wake_up(&osp->opd_pre_waitq);
return count;
}
LUSTRE_RW_ATTR(create_count);
/**
* max_create_count_show() - Show maximum number of objects to precreate
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t max_create_count_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
if (!osp->opd_pre)
return -EINVAL;
return sprintf(buf, "%d\n", osp->opd_pre_max_create_count);
}
/**
* max_create_count_store() - Change maximum number of objects to precreate
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string which represents maximum number)
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t max_create_count_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
if (!osp->opd_pre)
return -EINVAL;
rc = kstrtouint(buffer, 0, &val);
if (rc)
return rc;
if (val && (val < OST_MIN_PRECREATE ||
val > OST_MAX_PRECREATE))
return -ERANGE;
if (osp->opd_pre_create_count > val)
osp->opd_pre_create_count = val;
/* Can be 0 after setting max_create_count to 0 */
if (osp->opd_pre_create_count == 0 && val != 0)
osp->opd_pre_create_count = OST_MIN_PRECREATE;
osp->opd_pre_max_create_count = val;
return count;
}
LUSTRE_RW_ATTR(max_create_count);
/**
* prealloc_next_id_show() - Show last id to assign in creation
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t prealloc_next_id_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
struct lu_fid *fid;
u64 id;
__u64 seq_width;
if (!osp->opd_pre)
return -EINVAL;
fid = &osp->opd_pre_used_fid;
seq_width = osp->opd_pre_seq_width;
if (fid_is_idif(fid)) {
id = fid_idif_id(fid_seq(fid), fid_oid(fid), fid_ver(fid));
if (unlikely(id >= min(IDIF_MAX_OID, seq_width)))
id = 1;
else
id++;
} else {
id = unlikely(fid_oid(fid) >= min(OBIF_MAX_OID, seq_width)) ?
1 : fid_oid(fid) + 1;
}
return sprintf(buf, "%llu\n", id);
}
LUSTRE_RO_ATTR(prealloc_next_id);
/**
* prealloc_last_id_show() - Show last created id OST reported
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t prealloc_last_id_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
struct lu_fid *fid;
u64 id;
if (!osp->opd_pre)
return -EINVAL;
fid = &osp->opd_pre_last_created_fid;
id = fid_is_idif(fid) ?
fid_idif_id(fid_seq(fid), fid_oid(fid), fid_ver(fid)) :
fid_oid(fid);
return sprintf(buf, "%llu\n", id);
}
LUSTRE_RO_ATTR(prealloc_last_id);
/**
* prealloc_next_seq_show() - Show next FID sequence to precreate
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t prealloc_next_seq_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
struct lu_fid *fid;
if (!osp->opd_pre)
return -EINVAL;
fid = &osp->opd_pre_used_fid;
return sprintf(buf, "%#llx\n", fid_is_idif(fid) ?
fid_seq(fid) & (~0xffff) : fid_seq(fid));
}
LUSTRE_RO_ATTR(prealloc_next_seq);
/**
* prealloc_last_seq_show() - Show last created FID sequence OST reported
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t prealloc_last_seq_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
struct lu_fid *fid;
if (!osp->opd_pre)
return -EINVAL;
fid = &osp->opd_pre_last_created_fid;
return sprintf(buf, "%#llx\n", fid_is_idif(fid) ?
fid_seq(fid) & (~0xffff) : fid_seq(fid));
}
LUSTRE_RO_ATTR(prealloc_last_seq);
/**
* prealloc_reserved_show() - Show the number of ids reserved by declare
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t prealloc_reserved_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
if (!osp->opd_pre)
return -EINVAL;
return sprintf(buf, "%llu\n", osp->opd_pre_reserved);
}
LUSTRE_RO_ATTR(prealloc_reserved);
/**
* maxage_show() - Show interval (in seconds) to update statfs data
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t maxage_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%lld\n", osp->opd_statfs_maxage);
}
/**
* maxage_store() - Change interval to update statfs data
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string which represents statfs interval
* (in seconds))
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t maxage_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
rc = kstrtouint(buffer, 0, &val);
if (rc)
return rc;
if (val == 0)
return -ERANGE;
osp->opd_statfs_maxage = val;
return count;
}
LUSTRE_RW_ATTR(maxage);
/**
* prealloc_status_show() - Show current precreation status: output 0 means
* success, otherwise negative number is printed
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t prealloc_status_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
if (!osp->opd_pre)
return -EINVAL;
return sprintf(buf, "%d\n", osp->opd_pre_status);
}
LUSTRE_RO_ATTR(prealloc_status);
static ssize_t prealloc_force_new_seq_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
if (!osp->opd_pre)
return -EINVAL;
return scnprintf(buf, PAGE_SIZE, "%d\n", osp->opd_pre_force_new_seq);
}
static ssize_t prealloc_force_new_seq_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
bool val;
int rc;
if (!osp->opd_pre)
return -EINVAL;
rc = kstrtobool(buffer, &val);
if (rc)
return rc;
osp->opd_pre_force_new_seq = val;
return count;
}
LUSTRE_RW_ATTR(prealloc_force_new_seq);
/**
* destroys_in_flight_show() - destroy in-flight show
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Show the number of RPCs in processing (including uncommitted by OST) plus
* changes to sync, i.e. this is the total number of changes OST needs to apply
* and commit.
*
* This counter is used to determine if OST has space returned. A zero value
* indicates that OST storage space consumed by destroyed objects has been freed
* on disk, the associated llog records have been cleared, and no synchronous
* RPC are being processed.
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t destroys_in_flight_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%u\n",
atomic_read(&osp->opd_sync_rpcs_in_progress) +
atomic_read(&osp->opd_sync_changes));
}
LUSTRE_RO_ATTR(destroys_in_flight);
/**
* old_sync_processed_show() - Show changes synced from previous mount
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t old_sync_processed_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return sprintf(buf, "%d\n", osp->opd_sync_prev_done);
}
LUSTRE_RO_ATTR(old_sync_processed);
/**
* lfsck_max_rpcs_in_flight_show() - Show maximum number of RPCs in flight
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t lfsck_max_rpcs_in_flight_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
u32 max;
max = obd_get_max_rpcs_in_flight(&obd->u.cli);
return sprintf(buf, "%u\n", max);
}
/**
* lfsck_max_rpcs_in_flight_store() - Change maximum number of RPCs in flight
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buffer: Buffer in kernel memory (string which represents maximum number of
* RPCs in flight)
* @count: @buffer length
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t lfsck_max_rpcs_in_flight_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
unsigned int val;
int rc;
rc = kstrtouint(buffer, 0, &val);
if (rc)
return rc;
rc = obd_set_max_rpcs_in_flight(&obd->u.cli, val);
return rc ? rc : count;
}
LUSTRE_RW_ATTR(lfsck_max_rpcs_in_flight);
static ssize_t osp_ping_show(struct kobject *kobj, struct attribute *attr,
char *buffer)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
int rc;
rc = ptlrpc_obd_ping(obd);
return rc;
}
LUSTRE_ATTR(ping, 0444, osp_ping_show, NULL);
static ssize_t osp_conn_uuid_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_device *lu = dt2lu_dev(dt);
struct obd_device *obd = lu->ld_obd;
struct obd_import *imp;
struct ptlrpc_connection *conn;
ssize_t count;
with_imp_locked(obd, imp, count) {
conn = imp->imp_connection;
if (conn)
count = sprintf(buf, "%s\n",
libcfs_nidstr(&conn->c_peer.nid));
else
count = sprintf(buf, "%s\n", "<none>");
}
return count;
}
LUSTRE_ATTR(ost_conn_uuid, 0444, osp_conn_uuid_show, NULL);
LUSTRE_ATTR(mdt_conn_uuid, 0444, osp_conn_uuid_show, NULL);
LDEBUGFS_SEQ_FOPS_RO_TYPE(osp, connect_flags);
LDEBUGFS_SEQ_FOPS_RO_TYPE(osp, server_uuid);
LDEBUGFS_SEQ_FOPS_RO_TYPE(osp, timeouts);
LDEBUGFS_SEQ_FOPS_RW_TYPE(osp, import);
LDEBUGFS_SEQ_FOPS_RO_TYPE(osp, state);
static int osp_rpc_stats_seq_show(struct seq_file *seq, void *v)
{
struct obd_device *dev = seq->private;
return obd_mod_rpc_stats_seq_show(&dev->u.cli, seq);
}
static ssize_t osp_rpc_stats_seq_write(struct file *file,
const char __user *buf,
size_t len, loff_t *off)
{
struct seq_file *seq = file->private_data;
struct obd_device *dev = seq->private;
struct client_obd *cli = &dev->u.cli;
lprocfs_oh_clear(&cli->cl_mod_rpcs_hist);
cli->cl_mod_rpcs_init = ktime_get_real();
return len;
}
LDEBUGFS_SEQ_FOPS(osp_rpc_stats);
/**
* reserved_mb_high_show() - show high watermark (in MB)
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Show high watermark (in megabytes). If available free space at OST is greater
* than high watermark and object allocation for OST is disabled, enable it.
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t reserved_mb_high_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return snprintf(buf, PAGE_SIZE, "%u\n", osp->opd_reserved_mb_high);
}
/*
* Change high watermark
*/
static ssize_t reserved_mb_high_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
u64 val;
int rc;
rc = sysfs_memparse(buffer, count, &val, "MiB");
if (rc < 0)
return rc;
val >>= 20;
if (val < 1)
return -ERANGE;
spin_lock(&osp->opd_pre_lock);
osp->opd_reserved_mb_high = val;
if (val <= osp->opd_reserved_mb_low)
osp->opd_reserved_mb_low = val - 1;
spin_unlock(&osp->opd_pre_lock);
return count;
}
LUSTRE_RW_ATTR(reserved_mb_high);
/**
* reserved_mb_low_show() - show low watermark (in MB)
* @kobj: kernel object associated with the sysfs
* @attr: pointer to the attribute structure
* @buf: Buffer in kernel memory
*
* Show low watermark (in megabytes). If available free space at OST is less
* than low watermark, object allocation for OST is disabled.
*
* Return:
* * %>0 return the number of bytes written
* * %negative number on error
*/
static ssize_t reserved_mb_low_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return snprintf(buf, PAGE_SIZE, "%u\n", osp->opd_reserved_mb_low);
}
/*
* Change low watermark
*/
static ssize_t reserved_mb_low_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
u64 val;
int rc;
rc = sysfs_memparse(buffer, count, &val, "MiB");
if (rc < 0)
return rc;
val >>= 20;
spin_lock(&osp->opd_pre_lock);
osp->opd_reserved_mb_low = val;
if (val >= osp->opd_reserved_mb_high)
osp->opd_reserved_mb_high = val + 1;
spin_unlock(&osp->opd_pre_lock);
return count;
}
LUSTRE_RW_ATTR(reserved_mb_low);
/*
* Show high watermark of inode.
*/
static ssize_t reserved_ino_high_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return snprintf(buf, PAGE_SIZE, "%u\n", osp->opd_reserved_ino_high);
}
/*
* Change high watermark of inode.
*/
static ssize_t reserved_ino_high_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
rc = kstrtouint(buffer, 0, &val);
if (rc < 0)
return rc;
if (val < 1)
return -ERANGE;
spin_lock(&osp->opd_pre_lock);
osp->opd_reserved_ino_high = val;
if (val <= osp->opd_reserved_ino_low)
osp->opd_reserved_ino_low = val >> 1;
spin_unlock(&osp->opd_pre_lock);
return count;
}
LUSTRE_RW_ATTR(reserved_ino_high);
/*
* Show low watermark.
*/
static ssize_t reserved_ino_low_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
return snprintf(buf, PAGE_SIZE, "%u\n", osp->opd_reserved_ino_low);
}
/*
* Change low watermark
*/
static ssize_t reserved_ino_low_store(struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct osp_device *osp = dt2osp_dev(dt);
unsigned int val;
int rc;
rc = kstrtouint(buffer, 0, &val);
if (rc < 0)
return rc;
if (val & (1UL << 31))
return -EOVERFLOW;
spin_lock(&osp->opd_pre_lock);
osp->opd_reserved_ino_low = val;
if (val >= osp->opd_reserved_ino_high)
osp->opd_reserved_ino_high = val << 1;
spin_unlock(&osp->opd_pre_lock);
return count;
}
LUSTRE_RW_ATTR(reserved_ino_low);
static ssize_t force_sync_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
struct dt_device *dt = container_of(kobj, struct dt_device,
dd_kobj);
struct lu_env env;
int rc;
rc = lu_env_init(&env, LCT_LOCAL);
if (rc)
return rc;
rc = dt_sync(&env, dt);
lu_env_fini(&env);
return rc == 0 ? count : rc;
}
LUSTRE_WO_ATTR(force_sync);
static int osp_sync_error_list_seq_show(struct seq_file *m, void *data)
{
struct obd_device *dev = m->private;
struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev);
struct osp_job_args *ja;
if (osp == NULL)
return -EINVAL;
if (list_empty(&osp->opd_sync_error_list))
return 0;
spin_lock(&osp->opd_sync_lock);
list_for_each_entry(ja, &osp->opd_sync_error_list, ja_error_link) {
seq_printf(m, "%u ["DOSTID"] llog=["DOSTID"] idx %d\n",
ja->ja_op, POSTID(&ja->ja_body.oa.o_oi),
POSTID(&ja->ja_lcookie.lgc_lgl.lgl_oi),
ja->ja_lcookie.lgc_index);
}
spin_unlock(&osp->opd_sync_lock);
return 0;
}
LDEBUGFS_SEQ_FOPS_RO(osp_sync_error_list);
static struct ldebugfs_vars ldebugfs_osp_obd_vars[] = {
{ .name = "connect_flags",
.fops = &osp_connect_flags_fops },
{ .name = "ost_server_uuid",
.fops = &osp_server_uuid_fops },
{ .name = "timeouts",
.fops = &osp_timeouts_fops },
{ .name = "import",
.fops = &osp_import_fops },
{ .name = "state",
.fops = &osp_state_fops },
{ .name = "error_list",
.fops = &osp_sync_error_list_fops },
{ NULL }
};
static struct ldebugfs_vars ldebugfs_osp_md_vars[] = {
{ .name = "connect_flags",
.fops = &osp_connect_flags_fops },
{ .name = "mdt_server_uuid",
.fops = &osp_server_uuid_fops },
{ .name = "timeouts",
.fops = &osp_timeouts_fops },
{ .name = "import",
.fops = &osp_import_fops },
{ .name = "state",
.fops = &osp_state_fops },
{ .name = "rpc_stats",
.fops = &osp_rpc_stats_fops },
{ NULL }
};
static struct attribute *osp_obd_attrs[] = {
/* First two for compatiability reasons */
&lustre_attr_lfsck_max_rpcs_in_flight.attr,
&lustre_attr_destroys_in_flight.attr,
&lustre_attr_active.attr,
&lustre_attr_max_rpcs_in_flight.attr,
&lustre_attr_max_rpcs_in_progress.attr,
&lustre_attr_maxage.attr,
&lustre_attr_ost_conn_uuid.attr,
&lustre_attr_ping.attr,
&lustre_attr_prealloc_status.attr,
&lustre_attr_prealloc_next_id.attr,
&lustre_attr_prealloc_last_id.attr,
&lustre_attr_prealloc_next_seq.attr,
&lustre_attr_prealloc_last_seq.attr,
&lustre_attr_prealloc_reserved.attr,
&lustre_attr_prealloc_force_new_seq.attr,
&lustre_attr_sync_in_flight.attr,
&lustre_attr_sync_in_progress.attr,
&lustre_attr_sync_changes.attr,
&lustre_attr_max_sync_changes.attr,
&lustre_attr_force_sync.attr,
&lustre_attr_old_sync_processed.attr,
&lustre_attr_sync_current_llog.attr,
&lustre_attr_create_count.attr,
&lustre_attr_max_create_count.attr,
&lustre_attr_reserved_mb_high.attr,
&lustre_attr_reserved_mb_low.attr,
&lustre_attr_reserved_ino_high.attr,
&lustre_attr_reserved_ino_low.attr,
NULL,
};
ATTRIBUTE_GROUPS(osp_obd); /* creates osp_obd_groups from osp_obd_attrs */
static struct attribute *osp_md_attrs[] = {
/* First two for compatiability reasons */
&lustre_attr_lfsck_max_rpcs_in_flight.attr,
&lustre_attr_destroys_in_flight.attr,
&lustre_attr_active.attr,
&lustre_attr_max_rpcs_in_flight.attr,
&lustre_attr_max_mod_rpcs_in_flight.attr,
&lustre_attr_max_rpcs_in_progress.attr,
&lustre_attr_maxage.attr,
&lustre_attr_mdt_conn_uuid.attr,
&lustre_attr_ping.attr,
&lustre_attr_prealloc_status.attr,
&lustre_attr_reserved_mb_high.attr,
&lustre_attr_reserved_mb_low.attr,
&lustre_attr_reserved_ino_high.attr,
&lustre_attr_reserved_ino_low.attr,
NULL,
};
ATTRIBUTE_GROUPS(osp_md); /* creates osp_md_groups from osp_md_attrs */
void osp_tunables_fini(struct osp_device *osp)
{
struct obd_device *obd = osp->opd_obd;
struct kobject *osc;
osc = kset_find_obj(lustre_kset, "osc");
if (osc) {
sysfs_remove_link(osc, obd->obd_name);
kobject_put(osc);
}
debugfs_remove_recursive(osp->opd_debugfs);
osp->opd_debugfs = NULL;
ptlrpc_lprocfs_unregister_obd(obd);
debugfs_remove_recursive(obd->obd_debugfs_entry);
obd->obd_debugfs_entry = NULL;
dt_tunables_fini(&osp->opd_dt_dev);
}
/**
* osp_tunables_init() - Initialize OSP sysfs / debugfs
* @osp: OSP device
*/
void osp_tunables_init(struct osp_device *osp)
{
struct obd_device *obd = osp->opd_obd;
struct kobject *osc;
int rc;
if (osp->opd_connect_mdt) {
osp->opd_dt_dev.dd_ktype.default_groups = osp_md_groups;
obd->obd_debugfs_vars = ldebugfs_osp_md_vars;
} else {
osp->opd_dt_dev.dd_ktype.default_groups = osp_obd_groups;
obd->obd_debugfs_vars = ldebugfs_osp_obd_vars;
}
rc = dt_tunables_init(&osp->opd_dt_dev, obd->obd_type, obd->obd_name,
NULL);
if (rc) {
CERROR("%s: failed to setup DT tunables: %d\n",
obd->obd_name, rc);
return;
}
/* Since we register the obd device with ptlrpc / sptlrpc we
* have to register debugfs with obd_device
*/
obd->obd_debugfs_entry = debugfs_create_dir(obd->obd_name,
obd->obd_type->typ_debugfs_entry);
ldebugfs_add_vars(obd->obd_debugfs_entry, obd->obd_debugfs_vars, obd);
sptlrpc_lprocfs_cliobd_attach(obd);
ptlrpc_lprocfs_register_obd(obd);
if (osp->opd_connect_mdt || !strstr(obd->obd_name, "osc"))
return;
/* If the real OSC is present which is the case for setups
* with both server and clients on the same node then use
* the OSC's proc root
*/
osc = kset_find_obj(lustre_kset, "osc");
if (osc) {
rc = sysfs_create_link(osc, &osp->opd_dt_dev.dd_kobj,
obd->obd_name);
kobject_put(osc);
}
osp->opd_debugfs = ldebugfs_add_symlink(obd->obd_name, "osc",
"../osp/%s", obd->obd_name);
if (!osp->opd_debugfs)
CERROR("%s: failed to create OSC debugfs symlink\n",
obd->obd_name);
}