cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xfs_sysfs.c (14372B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2014 Red Hat, Inc.
      4 * All Rights Reserved.
      5 */
      6
      7#include "xfs.h"
      8#include "xfs_shared.h"
      9#include "xfs_format.h"
     10#include "xfs_log_format.h"
     11#include "xfs_trans_resv.h"
     12#include "xfs_sysfs.h"
     13#include "xfs_log.h"
     14#include "xfs_log_priv.h"
     15#include "xfs_mount.h"
     16
     17struct xfs_sysfs_attr {
     18	struct attribute attr;
     19	ssize_t (*show)(struct kobject *kobject, char *buf);
     20	ssize_t (*store)(struct kobject *kobject, const char *buf,
     21			 size_t count);
     22};
     23
     24static inline struct xfs_sysfs_attr *
     25to_attr(struct attribute *attr)
     26{
     27	return container_of(attr, struct xfs_sysfs_attr, attr);
     28}
     29
     30#define XFS_SYSFS_ATTR_RW(name) \
     31	static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name)
     32#define XFS_SYSFS_ATTR_RO(name) \
     33	static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name)
     34#define XFS_SYSFS_ATTR_WO(name) \
     35	static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name)
     36
     37#define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr
     38
     39STATIC ssize_t
     40xfs_sysfs_object_show(
     41	struct kobject		*kobject,
     42	struct attribute	*attr,
     43	char			*buf)
     44{
     45	struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
     46
     47	return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0;
     48}
     49
     50STATIC ssize_t
     51xfs_sysfs_object_store(
     52	struct kobject		*kobject,
     53	struct attribute	*attr,
     54	const char		*buf,
     55	size_t			count)
     56{
     57	struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
     58
     59	return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0;
     60}
     61
     62static const struct sysfs_ops xfs_sysfs_ops = {
     63	.show = xfs_sysfs_object_show,
     64	.store = xfs_sysfs_object_store,
     65};
     66
     67static struct attribute *xfs_mp_attrs[] = {
     68	NULL,
     69};
     70ATTRIBUTE_GROUPS(xfs_mp);
     71
     72struct kobj_type xfs_mp_ktype = {
     73	.release = xfs_sysfs_release,
     74	.sysfs_ops = &xfs_sysfs_ops,
     75	.default_groups = xfs_mp_groups,
     76};
     77
     78#ifdef DEBUG
     79/* debug */
     80
     81STATIC ssize_t
     82bug_on_assert_store(
     83	struct kobject		*kobject,
     84	const char		*buf,
     85	size_t			count)
     86{
     87	int			ret;
     88	int			val;
     89
     90	ret = kstrtoint(buf, 0, &val);
     91	if (ret)
     92		return ret;
     93
     94	if (val == 1)
     95		xfs_globals.bug_on_assert = true;
     96	else if (val == 0)
     97		xfs_globals.bug_on_assert = false;
     98	else
     99		return -EINVAL;
    100
    101	return count;
    102}
    103
    104STATIC ssize_t
    105bug_on_assert_show(
    106	struct kobject		*kobject,
    107	char			*buf)
    108{
    109	return sysfs_emit(buf, "%d\n", xfs_globals.bug_on_assert);
    110}
    111XFS_SYSFS_ATTR_RW(bug_on_assert);
    112
    113STATIC ssize_t
    114log_recovery_delay_store(
    115	struct kobject	*kobject,
    116	const char	*buf,
    117	size_t		count)
    118{
    119	int		ret;
    120	int		val;
    121
    122	ret = kstrtoint(buf, 0, &val);
    123	if (ret)
    124		return ret;
    125
    126	if (val < 0 || val > 60)
    127		return -EINVAL;
    128
    129	xfs_globals.log_recovery_delay = val;
    130
    131	return count;
    132}
    133
    134STATIC ssize_t
    135log_recovery_delay_show(
    136	struct kobject	*kobject,
    137	char		*buf)
    138{
    139	return sysfs_emit(buf, "%d\n", xfs_globals.log_recovery_delay);
    140}
    141XFS_SYSFS_ATTR_RW(log_recovery_delay);
    142
    143STATIC ssize_t
    144mount_delay_store(
    145	struct kobject	*kobject,
    146	const char	*buf,
    147	size_t		count)
    148{
    149	int		ret;
    150	int		val;
    151
    152	ret = kstrtoint(buf, 0, &val);
    153	if (ret)
    154		return ret;
    155
    156	if (val < 0 || val > 60)
    157		return -EINVAL;
    158
    159	xfs_globals.mount_delay = val;
    160
    161	return count;
    162}
    163
    164STATIC ssize_t
    165mount_delay_show(
    166	struct kobject	*kobject,
    167	char		*buf)
    168{
    169	return sysfs_emit(buf, "%d\n", xfs_globals.mount_delay);
    170}
    171XFS_SYSFS_ATTR_RW(mount_delay);
    172
    173static ssize_t
    174always_cow_store(
    175	struct kobject	*kobject,
    176	const char	*buf,
    177	size_t		count)
    178{
    179	ssize_t		ret;
    180
    181	ret = kstrtobool(buf, &xfs_globals.always_cow);
    182	if (ret < 0)
    183		return ret;
    184	return count;
    185}
    186
    187static ssize_t
    188always_cow_show(
    189	struct kobject	*kobject,
    190	char		*buf)
    191{
    192	return sysfs_emit(buf, "%d\n", xfs_globals.always_cow);
    193}
    194XFS_SYSFS_ATTR_RW(always_cow);
    195
    196#ifdef DEBUG
    197/*
    198 * Override how many threads the parallel work queue is allowed to create.
    199 * This has to be a debug-only global (instead of an errortag) because one of
    200 * the main users of parallel workqueues is mount time quotacheck.
    201 */
    202STATIC ssize_t
    203pwork_threads_store(
    204	struct kobject	*kobject,
    205	const char	*buf,
    206	size_t		count)
    207{
    208	int		ret;
    209	int		val;
    210
    211	ret = kstrtoint(buf, 0, &val);
    212	if (ret)
    213		return ret;
    214
    215	if (val < -1 || val > num_possible_cpus())
    216		return -EINVAL;
    217
    218	xfs_globals.pwork_threads = val;
    219
    220	return count;
    221}
    222
    223STATIC ssize_t
    224pwork_threads_show(
    225	struct kobject	*kobject,
    226	char		*buf)
    227{
    228	return sysfs_emit(buf, "%d\n", xfs_globals.pwork_threads);
    229}
    230XFS_SYSFS_ATTR_RW(pwork_threads);
    231
    232static ssize_t
    233larp_store(
    234	struct kobject	*kobject,
    235	const char	*buf,
    236	size_t		count)
    237{
    238	ssize_t		ret;
    239
    240	ret = kstrtobool(buf, &xfs_globals.larp);
    241	if (ret < 0)
    242		return ret;
    243	return count;
    244}
    245
    246STATIC ssize_t
    247larp_show(
    248	struct kobject	*kobject,
    249	char		*buf)
    250{
    251	return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.larp);
    252}
    253XFS_SYSFS_ATTR_RW(larp);
    254#endif /* DEBUG */
    255
    256static struct attribute *xfs_dbg_attrs[] = {
    257	ATTR_LIST(bug_on_assert),
    258	ATTR_LIST(log_recovery_delay),
    259	ATTR_LIST(mount_delay),
    260	ATTR_LIST(always_cow),
    261#ifdef DEBUG
    262	ATTR_LIST(pwork_threads),
    263	ATTR_LIST(larp),
    264#endif
    265	NULL,
    266};
    267ATTRIBUTE_GROUPS(xfs_dbg);
    268
    269struct kobj_type xfs_dbg_ktype = {
    270	.release = xfs_sysfs_release,
    271	.sysfs_ops = &xfs_sysfs_ops,
    272	.default_groups = xfs_dbg_groups,
    273};
    274
    275#endif /* DEBUG */
    276
    277/* stats */
    278
    279static inline struct xstats *
    280to_xstats(struct kobject *kobject)
    281{
    282	struct xfs_kobj *kobj = to_kobj(kobject);
    283
    284	return container_of(kobj, struct xstats, xs_kobj);
    285}
    286
    287STATIC ssize_t
    288stats_show(
    289	struct kobject	*kobject,
    290	char		*buf)
    291{
    292	struct xstats	*stats = to_xstats(kobject);
    293
    294	return xfs_stats_format(stats->xs_stats, buf);
    295}
    296XFS_SYSFS_ATTR_RO(stats);
    297
    298STATIC ssize_t
    299stats_clear_store(
    300	struct kobject	*kobject,
    301	const char	*buf,
    302	size_t		count)
    303{
    304	int		ret;
    305	int		val;
    306	struct xstats	*stats = to_xstats(kobject);
    307
    308	ret = kstrtoint(buf, 0, &val);
    309	if (ret)
    310		return ret;
    311
    312	if (val != 1)
    313		return -EINVAL;
    314
    315	xfs_stats_clearall(stats->xs_stats);
    316	return count;
    317}
    318XFS_SYSFS_ATTR_WO(stats_clear);
    319
    320static struct attribute *xfs_stats_attrs[] = {
    321	ATTR_LIST(stats),
    322	ATTR_LIST(stats_clear),
    323	NULL,
    324};
    325ATTRIBUTE_GROUPS(xfs_stats);
    326
    327struct kobj_type xfs_stats_ktype = {
    328	.release = xfs_sysfs_release,
    329	.sysfs_ops = &xfs_sysfs_ops,
    330	.default_groups = xfs_stats_groups,
    331};
    332
    333/* xlog */
    334
    335static inline struct xlog *
    336to_xlog(struct kobject *kobject)
    337{
    338	struct xfs_kobj *kobj = to_kobj(kobject);
    339
    340	return container_of(kobj, struct xlog, l_kobj);
    341}
    342
    343STATIC ssize_t
    344log_head_lsn_show(
    345	struct kobject	*kobject,
    346	char		*buf)
    347{
    348	int cycle;
    349	int block;
    350	struct xlog *log = to_xlog(kobject);
    351
    352	spin_lock(&log->l_icloglock);
    353	cycle = log->l_curr_cycle;
    354	block = log->l_curr_block;
    355	spin_unlock(&log->l_icloglock);
    356
    357	return sysfs_emit(buf, "%d:%d\n", cycle, block);
    358}
    359XFS_SYSFS_ATTR_RO(log_head_lsn);
    360
    361STATIC ssize_t
    362log_tail_lsn_show(
    363	struct kobject	*kobject,
    364	char		*buf)
    365{
    366	int cycle;
    367	int block;
    368	struct xlog *log = to_xlog(kobject);
    369
    370	xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block);
    371	return sysfs_emit(buf, "%d:%d\n", cycle, block);
    372}
    373XFS_SYSFS_ATTR_RO(log_tail_lsn);
    374
    375STATIC ssize_t
    376reserve_grant_head_show(
    377	struct kobject	*kobject,
    378	char		*buf)
    379
    380{
    381	int cycle;
    382	int bytes;
    383	struct xlog *log = to_xlog(kobject);
    384
    385	xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes);
    386	return sysfs_emit(buf, "%d:%d\n", cycle, bytes);
    387}
    388XFS_SYSFS_ATTR_RO(reserve_grant_head);
    389
    390STATIC ssize_t
    391write_grant_head_show(
    392	struct kobject	*kobject,
    393	char		*buf)
    394{
    395	int cycle;
    396	int bytes;
    397	struct xlog *log = to_xlog(kobject);
    398
    399	xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes);
    400	return sysfs_emit(buf, "%d:%d\n", cycle, bytes);
    401}
    402XFS_SYSFS_ATTR_RO(write_grant_head);
    403
    404static struct attribute *xfs_log_attrs[] = {
    405	ATTR_LIST(log_head_lsn),
    406	ATTR_LIST(log_tail_lsn),
    407	ATTR_LIST(reserve_grant_head),
    408	ATTR_LIST(write_grant_head),
    409	NULL,
    410};
    411ATTRIBUTE_GROUPS(xfs_log);
    412
    413struct kobj_type xfs_log_ktype = {
    414	.release = xfs_sysfs_release,
    415	.sysfs_ops = &xfs_sysfs_ops,
    416	.default_groups = xfs_log_groups,
    417};
    418
    419/*
    420 * Metadata IO error configuration
    421 *
    422 * The sysfs structure here is:
    423 *	...xfs/<dev>/error/<class>/<errno>/<error_attrs>
    424 *
    425 * where <class> allows us to discriminate between data IO and metadata IO,
    426 * and any other future type of IO (e.g. special inode or directory error
    427 * handling) we care to support.
    428 */
    429static inline struct xfs_error_cfg *
    430to_error_cfg(struct kobject *kobject)
    431{
    432	struct xfs_kobj *kobj = to_kobj(kobject);
    433	return container_of(kobj, struct xfs_error_cfg, kobj);
    434}
    435
    436static inline struct xfs_mount *
    437err_to_mp(struct kobject *kobject)
    438{
    439	struct xfs_kobj *kobj = to_kobj(kobject);
    440	return container_of(kobj, struct xfs_mount, m_error_kobj);
    441}
    442
    443static ssize_t
    444max_retries_show(
    445	struct kobject	*kobject,
    446	char		*buf)
    447{
    448	int		retries;
    449	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
    450
    451	if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)
    452		retries = -1;
    453	else
    454		retries = cfg->max_retries;
    455
    456	return sysfs_emit(buf, "%d\n", retries);
    457}
    458
    459static ssize_t
    460max_retries_store(
    461	struct kobject	*kobject,
    462	const char	*buf,
    463	size_t		count)
    464{
    465	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
    466	int		ret;
    467	int		val;
    468
    469	ret = kstrtoint(buf, 0, &val);
    470	if (ret)
    471		return ret;
    472
    473	if (val < -1)
    474		return -EINVAL;
    475
    476	if (val == -1)
    477		cfg->max_retries = XFS_ERR_RETRY_FOREVER;
    478	else
    479		cfg->max_retries = val;
    480	return count;
    481}
    482XFS_SYSFS_ATTR_RW(max_retries);
    483
    484static ssize_t
    485retry_timeout_seconds_show(
    486	struct kobject	*kobject,
    487	char		*buf)
    488{
    489	int		timeout;
    490	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
    491
    492	if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
    493		timeout = -1;
    494	else
    495		timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;
    496
    497	return sysfs_emit(buf, "%d\n", timeout);
    498}
    499
    500static ssize_t
    501retry_timeout_seconds_store(
    502	struct kobject	*kobject,
    503	const char	*buf,
    504	size_t		count)
    505{
    506	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
    507	int		ret;
    508	int		val;
    509
    510	ret = kstrtoint(buf, 0, &val);
    511	if (ret)
    512		return ret;
    513
    514	/* 1 day timeout maximum, -1 means infinite */
    515	if (val < -1 || val > 86400)
    516		return -EINVAL;
    517
    518	if (val == -1)
    519		cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
    520	else {
    521		cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
    522		ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);
    523	}
    524	return count;
    525}
    526XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
    527
    528static ssize_t
    529fail_at_unmount_show(
    530	struct kobject	*kobject,
    531	char		*buf)
    532{
    533	struct xfs_mount	*mp = err_to_mp(kobject);
    534
    535	return sysfs_emit(buf, "%d\n", mp->m_fail_unmount);
    536}
    537
    538static ssize_t
    539fail_at_unmount_store(
    540	struct kobject	*kobject,
    541	const char	*buf,
    542	size_t		count)
    543{
    544	struct xfs_mount	*mp = err_to_mp(kobject);
    545	int		ret;
    546	int		val;
    547
    548	ret = kstrtoint(buf, 0, &val);
    549	if (ret)
    550		return ret;
    551
    552	if (val < 0 || val > 1)
    553		return -EINVAL;
    554
    555	mp->m_fail_unmount = val;
    556	return count;
    557}
    558XFS_SYSFS_ATTR_RW(fail_at_unmount);
    559
    560static struct attribute *xfs_error_attrs[] = {
    561	ATTR_LIST(max_retries),
    562	ATTR_LIST(retry_timeout_seconds),
    563	NULL,
    564};
    565ATTRIBUTE_GROUPS(xfs_error);
    566
    567static struct kobj_type xfs_error_cfg_ktype = {
    568	.release = xfs_sysfs_release,
    569	.sysfs_ops = &xfs_sysfs_ops,
    570	.default_groups = xfs_error_groups,
    571};
    572
    573static struct kobj_type xfs_error_ktype = {
    574	.release = xfs_sysfs_release,
    575	.sysfs_ops = &xfs_sysfs_ops,
    576};
    577
    578/*
    579 * Error initialization tables. These need to be ordered in the same
    580 * order as the enums used to index the array. All class init tables need to
    581 * define a "default" behaviour as the first entry, all other entries can be
    582 * empty.
    583 */
    584struct xfs_error_init {
    585	char		*name;
    586	int		max_retries;
    587	int		retry_timeout;	/* in seconds */
    588};
    589
    590static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
    591	{ .name = "default",
    592	  .max_retries = XFS_ERR_RETRY_FOREVER,
    593	  .retry_timeout = XFS_ERR_RETRY_FOREVER,
    594	},
    595	{ .name = "EIO",
    596	  .max_retries = XFS_ERR_RETRY_FOREVER,
    597	  .retry_timeout = XFS_ERR_RETRY_FOREVER,
    598	},
    599	{ .name = "ENOSPC",
    600	  .max_retries = XFS_ERR_RETRY_FOREVER,
    601	  .retry_timeout = XFS_ERR_RETRY_FOREVER,
    602	},
    603	{ .name = "ENODEV",
    604	  .max_retries = 0,	/* We can't recover from devices disappearing */
    605	  .retry_timeout = 0,
    606	},
    607};
    608
    609static int
    610xfs_error_sysfs_init_class(
    611	struct xfs_mount	*mp,
    612	int			class,
    613	const char		*parent_name,
    614	struct xfs_kobj		*parent_kobj,
    615	const struct xfs_error_init init[])
    616{
    617	struct xfs_error_cfg	*cfg;
    618	int			error;
    619	int			i;
    620
    621	ASSERT(class < XFS_ERR_CLASS_MAX);
    622
    623	error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,
    624				&mp->m_error_kobj, parent_name);
    625	if (error)
    626		return error;
    627
    628	for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
    629		cfg = &mp->m_error_cfg[class][i];
    630		error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,
    631					parent_kobj, init[i].name);
    632		if (error)
    633			goto out_error;
    634
    635		cfg->max_retries = init[i].max_retries;
    636		if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
    637			cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
    638		else
    639			cfg->retry_timeout = msecs_to_jiffies(
    640					init[i].retry_timeout * MSEC_PER_SEC);
    641	}
    642	return 0;
    643
    644out_error:
    645	/* unwind the entries that succeeded */
    646	for (i--; i >= 0; i--) {
    647		cfg = &mp->m_error_cfg[class][i];
    648		xfs_sysfs_del(&cfg->kobj);
    649	}
    650	xfs_sysfs_del(parent_kobj);
    651	return error;
    652}
    653
    654int
    655xfs_error_sysfs_init(
    656	struct xfs_mount	*mp)
    657{
    658	int			error;
    659
    660	/* .../xfs/<dev>/error/ */
    661	error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
    662				&mp->m_kobj, "error");
    663	if (error)
    664		return error;
    665
    666	error = sysfs_create_file(&mp->m_error_kobj.kobject,
    667				  ATTR_LIST(fail_at_unmount));
    668
    669	if (error)
    670		goto out_error;
    671
    672	/* .../xfs/<dev>/error/metadata/ */
    673	error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,
    674				"metadata", &mp->m_error_meta_kobj,
    675				xfs_error_meta_init);
    676	if (error)
    677		goto out_error;
    678
    679	return 0;
    680
    681out_error:
    682	xfs_sysfs_del(&mp->m_error_kobj);
    683	return error;
    684}
    685
    686void
    687xfs_error_sysfs_del(
    688	struct xfs_mount	*mp)
    689{
    690	struct xfs_error_cfg	*cfg;
    691	int			i, j;
    692
    693	for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {
    694		for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {
    695			cfg = &mp->m_error_cfg[i][j];
    696
    697			xfs_sysfs_del(&cfg->kobj);
    698		}
    699	}
    700	xfs_sysfs_del(&mp->m_error_meta_kobj);
    701	xfs_sysfs_del(&mp->m_error_kobj);
    702}
    703
    704struct xfs_error_cfg *
    705xfs_error_get_cfg(
    706	struct xfs_mount	*mp,
    707	int			error_class,
    708	int			error)
    709{
    710	struct xfs_error_cfg	*cfg;
    711
    712	if (error < 0)
    713		error = -error;
    714
    715	switch (error) {
    716	case EIO:
    717		cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];
    718		break;
    719	case ENOSPC:
    720		cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];
    721		break;
    722	case ENODEV:
    723		cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];
    724		break;
    725	default:
    726		cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];
    727		break;
    728	}
    729
    730	return cfg;
    731}