brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · 60cb531 Raw
782 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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.attr38 39STATIC ssize_t40xfs_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_t51xfs_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 72const struct 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 DEBUG79/* debug */80 81STATIC ssize_t82bug_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	else99		return -EINVAL;100 101	return count;102}103 104STATIC ssize_t105bug_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_t114log_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_t135log_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_t144mount_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_t165mount_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_t174always_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_t188always_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/*197 * Override how many threads the parallel work queue is allowed to create.198 * This has to be a debug-only global (instead of an errortag) because one of199 * the main users of parallel workqueues is mount time quotacheck.200 */201STATIC ssize_t202pwork_threads_store(203	struct kobject	*kobject,204	const char	*buf,205	size_t		count)206{207	int		ret;208	int		val;209 210	ret = kstrtoint(buf, 0, &val);211	if (ret)212		return ret;213 214	if (val < -1 || val > num_possible_cpus())215		return -EINVAL;216 217	xfs_globals.pwork_threads = val;218 219	return count;220}221 222STATIC ssize_t223pwork_threads_show(224	struct kobject	*kobject,225	char		*buf)226{227	return sysfs_emit(buf, "%d\n", xfs_globals.pwork_threads);228}229XFS_SYSFS_ATTR_RW(pwork_threads);230 231/*232 * The "LARP" (Logged extended Attribute Recovery Persistence) debugging knob233 * sets the XFS_DA_OP_LOGGED flag on all xfs_attr_set operations performed on234 * V5 filesystems.  As a result, the intermediate progress of all setxattr and235 * removexattr operations are tracked via the log and can be restarted during236 * recovery.  This is useful for testing xattr recovery prior to merging of the237 * parent pointer feature which requires it to maintain consistency, and may be238 * enabled for userspace xattrs in the future.239 */240static ssize_t241larp_store(242	struct kobject	*kobject,243	const char	*buf,244	size_t		count)245{246	ssize_t		ret;247 248	ret = kstrtobool(buf, &xfs_globals.larp);249	if (ret < 0)250		return ret;251	return count;252}253 254STATIC ssize_t255larp_show(256	struct kobject	*kobject,257	char		*buf)258{259	return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.larp);260}261XFS_SYSFS_ATTR_RW(larp);262 263STATIC ssize_t264bload_leaf_slack_store(265	struct kobject	*kobject,266	const char	*buf,267	size_t		count)268{269	int		ret;270	int		val;271 272	ret = kstrtoint(buf, 0, &val);273	if (ret)274		return ret;275 276	xfs_globals.bload_leaf_slack = val;277	return count;278}279 280STATIC ssize_t281bload_leaf_slack_show(282	struct kobject	*kobject,283	char		*buf)284{285	return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bload_leaf_slack);286}287XFS_SYSFS_ATTR_RW(bload_leaf_slack);288 289STATIC ssize_t290bload_node_slack_store(291	struct kobject	*kobject,292	const char	*buf,293	size_t		count)294{295	int		ret;296	int		val;297 298	ret = kstrtoint(buf, 0, &val);299	if (ret)300		return ret;301 302	xfs_globals.bload_node_slack = val;303	return count;304}305 306STATIC ssize_t307bload_node_slack_show(308	struct kobject	*kobject,309	char		*buf)310{311	return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bload_node_slack);312}313XFS_SYSFS_ATTR_RW(bload_node_slack);314 315static struct attribute *xfs_dbg_attrs[] = {316	ATTR_LIST(bug_on_assert),317	ATTR_LIST(log_recovery_delay),318	ATTR_LIST(mount_delay),319	ATTR_LIST(always_cow),320	ATTR_LIST(pwork_threads),321	ATTR_LIST(larp),322	ATTR_LIST(bload_leaf_slack),323	ATTR_LIST(bload_node_slack),324	NULL,325};326ATTRIBUTE_GROUPS(xfs_dbg);327 328const struct kobj_type xfs_dbg_ktype = {329	.release = xfs_sysfs_release,330	.sysfs_ops = &xfs_sysfs_ops,331	.default_groups = xfs_dbg_groups,332};333 334#endif /* DEBUG */335 336/* stats */337 338static inline struct xstats *339to_xstats(struct kobject *kobject)340{341	struct xfs_kobj *kobj = to_kobj(kobject);342 343	return container_of(kobj, struct xstats, xs_kobj);344}345 346STATIC ssize_t347stats_show(348	struct kobject	*kobject,349	char		*buf)350{351	struct xstats	*stats = to_xstats(kobject);352 353	return xfs_stats_format(stats->xs_stats, buf);354}355XFS_SYSFS_ATTR_RO(stats);356 357STATIC ssize_t358stats_clear_store(359	struct kobject	*kobject,360	const char	*buf,361	size_t		count)362{363	int		ret;364	int		val;365	struct xstats	*stats = to_xstats(kobject);366 367	ret = kstrtoint(buf, 0, &val);368	if (ret)369		return ret;370 371	if (val != 1)372		return -EINVAL;373 374	xfs_stats_clearall(stats->xs_stats);375	return count;376}377XFS_SYSFS_ATTR_WO(stats_clear);378 379static struct attribute *xfs_stats_attrs[] = {380	ATTR_LIST(stats),381	ATTR_LIST(stats_clear),382	NULL,383};384ATTRIBUTE_GROUPS(xfs_stats);385 386const struct kobj_type xfs_stats_ktype = {387	.release = xfs_sysfs_release,388	.sysfs_ops = &xfs_sysfs_ops,389	.default_groups = xfs_stats_groups,390};391 392/* xlog */393 394static inline struct xlog *395to_xlog(struct kobject *kobject)396{397	struct xfs_kobj *kobj = to_kobj(kobject);398 399	return container_of(kobj, struct xlog, l_kobj);400}401 402STATIC ssize_t403log_head_lsn_show(404	struct kobject	*kobject,405	char		*buf)406{407	int cycle;408	int block;409	struct xlog *log = to_xlog(kobject);410 411	spin_lock(&log->l_icloglock);412	cycle = log->l_curr_cycle;413	block = log->l_curr_block;414	spin_unlock(&log->l_icloglock);415 416	return sysfs_emit(buf, "%d:%d\n", cycle, block);417}418XFS_SYSFS_ATTR_RO(log_head_lsn);419 420STATIC ssize_t421log_tail_lsn_show(422	struct kobject	*kobject,423	char		*buf)424{425	int cycle;426	int block;427	struct xlog *log = to_xlog(kobject);428 429	xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block);430	return sysfs_emit(buf, "%d:%d\n", cycle, block);431}432XFS_SYSFS_ATTR_RO(log_tail_lsn);433 434STATIC ssize_t435reserve_grant_head_bytes_show(436	struct kobject	*kobject,437	char		*buf)438{439	return sysfs_emit(buf, "%lld\n",440			atomic64_read(&to_xlog(kobject)->l_reserve_head.grant));441}442XFS_SYSFS_ATTR_RO(reserve_grant_head_bytes);443 444STATIC ssize_t445write_grant_head_bytes_show(446	struct kobject	*kobject,447	char		*buf)448{449	return sysfs_emit(buf, "%lld\n",450			atomic64_read(&to_xlog(kobject)->l_write_head.grant));451}452XFS_SYSFS_ATTR_RO(write_grant_head_bytes);453 454static struct attribute *xfs_log_attrs[] = {455	ATTR_LIST(log_head_lsn),456	ATTR_LIST(log_tail_lsn),457	ATTR_LIST(reserve_grant_head_bytes),458	ATTR_LIST(write_grant_head_bytes),459	NULL,460};461ATTRIBUTE_GROUPS(xfs_log);462 463const struct kobj_type xfs_log_ktype = {464	.release = xfs_sysfs_release,465	.sysfs_ops = &xfs_sysfs_ops,466	.default_groups = xfs_log_groups,467};468 469/*470 * Metadata IO error configuration471 *472 * The sysfs structure here is:473 *	...xfs/<dev>/error/<class>/<errno>/<error_attrs>474 *475 * where <class> allows us to discriminate between data IO and metadata IO,476 * and any other future type of IO (e.g. special inode or directory error477 * handling) we care to support.478 */479static inline struct xfs_error_cfg *480to_error_cfg(struct kobject *kobject)481{482	struct xfs_kobj *kobj = to_kobj(kobject);483	return container_of(kobj, struct xfs_error_cfg, kobj);484}485 486static inline struct xfs_mount *487err_to_mp(struct kobject *kobject)488{489	struct xfs_kobj *kobj = to_kobj(kobject);490	return container_of(kobj, struct xfs_mount, m_error_kobj);491}492 493static ssize_t494max_retries_show(495	struct kobject	*kobject,496	char		*buf)497{498	int		retries;499	struct xfs_error_cfg *cfg = to_error_cfg(kobject);500 501	if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)502		retries = -1;503	else504		retries = cfg->max_retries;505 506	return sysfs_emit(buf, "%d\n", retries);507}508 509static ssize_t510max_retries_store(511	struct kobject	*kobject,512	const char	*buf,513	size_t		count)514{515	struct xfs_error_cfg *cfg = to_error_cfg(kobject);516	int		ret;517	int		val;518 519	ret = kstrtoint(buf, 0, &val);520	if (ret)521		return ret;522 523	if (val < -1)524		return -EINVAL;525 526	if (val == -1)527		cfg->max_retries = XFS_ERR_RETRY_FOREVER;528	else529		cfg->max_retries = val;530	return count;531}532XFS_SYSFS_ATTR_RW(max_retries);533 534static ssize_t535retry_timeout_seconds_show(536	struct kobject	*kobject,537	char		*buf)538{539	int		timeout;540	struct xfs_error_cfg *cfg = to_error_cfg(kobject);541 542	if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)543		timeout = -1;544	else545		timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;546 547	return sysfs_emit(buf, "%d\n", timeout);548}549 550static ssize_t551retry_timeout_seconds_store(552	struct kobject	*kobject,553	const char	*buf,554	size_t		count)555{556	struct xfs_error_cfg *cfg = to_error_cfg(kobject);557	int		ret;558	int		val;559 560	ret = kstrtoint(buf, 0, &val);561	if (ret)562		return ret;563 564	/* 1 day timeout maximum, -1 means infinite */565	if (val < -1 || val > 86400)566		return -EINVAL;567 568	if (val == -1)569		cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;570	else {571		cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);572		ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);573	}574	return count;575}576XFS_SYSFS_ATTR_RW(retry_timeout_seconds);577 578static ssize_t579fail_at_unmount_show(580	struct kobject	*kobject,581	char		*buf)582{583	struct xfs_mount	*mp = err_to_mp(kobject);584 585	return sysfs_emit(buf, "%d\n", mp->m_fail_unmount);586}587 588static ssize_t589fail_at_unmount_store(590	struct kobject	*kobject,591	const char	*buf,592	size_t		count)593{594	struct xfs_mount	*mp = err_to_mp(kobject);595	int		ret;596	int		val;597 598	ret = kstrtoint(buf, 0, &val);599	if (ret)600		return ret;601 602	if (val < 0 || val > 1)603		return -EINVAL;604 605	mp->m_fail_unmount = val;606	return count;607}608XFS_SYSFS_ATTR_RW(fail_at_unmount);609 610static struct attribute *xfs_error_attrs[] = {611	ATTR_LIST(max_retries),612	ATTR_LIST(retry_timeout_seconds),613	NULL,614};615ATTRIBUTE_GROUPS(xfs_error);616 617static const struct kobj_type xfs_error_cfg_ktype = {618	.release = xfs_sysfs_release,619	.sysfs_ops = &xfs_sysfs_ops,620	.default_groups = xfs_error_groups,621};622 623static const struct kobj_type xfs_error_ktype = {624	.release = xfs_sysfs_release,625	.sysfs_ops = &xfs_sysfs_ops,626};627 628/*629 * Error initialization tables. These need to be ordered in the same630 * order as the enums used to index the array. All class init tables need to631 * define a "default" behaviour as the first entry, all other entries can be632 * empty.633 */634struct xfs_error_init {635	char		*name;636	int		max_retries;637	int		retry_timeout;	/* in seconds */638};639 640static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {641	{ .name = "default",642	  .max_retries = XFS_ERR_RETRY_FOREVER,643	  .retry_timeout = XFS_ERR_RETRY_FOREVER,644	},645	{ .name = "EIO",646	  .max_retries = XFS_ERR_RETRY_FOREVER,647	  .retry_timeout = XFS_ERR_RETRY_FOREVER,648	},649	{ .name = "ENOSPC",650	  .max_retries = XFS_ERR_RETRY_FOREVER,651	  .retry_timeout = XFS_ERR_RETRY_FOREVER,652	},653	{ .name = "ENODEV",654	  .max_retries = 0,	/* We can't recover from devices disappearing */655	  .retry_timeout = 0,656	},657};658 659static int660xfs_error_sysfs_init_class(661	struct xfs_mount	*mp,662	int			class,663	const char		*parent_name,664	struct xfs_kobj		*parent_kobj,665	const struct xfs_error_init init[])666{667	struct xfs_error_cfg	*cfg;668	int			error;669	int			i;670 671	ASSERT(class < XFS_ERR_CLASS_MAX);672 673	error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,674				&mp->m_error_kobj, parent_name);675	if (error)676		return error;677 678	for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {679		cfg = &mp->m_error_cfg[class][i];680		error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,681					parent_kobj, init[i].name);682		if (error)683			goto out_error;684 685		cfg->max_retries = init[i].max_retries;686		if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)687			cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;688		else689			cfg->retry_timeout = msecs_to_jiffies(690					init[i].retry_timeout * MSEC_PER_SEC);691	}692	return 0;693 694out_error:695	/* unwind the entries that succeeded */696	for (i--; i >= 0; i--) {697		cfg = &mp->m_error_cfg[class][i];698		xfs_sysfs_del(&cfg->kobj);699	}700	xfs_sysfs_del(parent_kobj);701	return error;702}703 704int705xfs_error_sysfs_init(706	struct xfs_mount	*mp)707{708	int			error;709 710	/* .../xfs/<dev>/error/ */711	error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,712				&mp->m_kobj, "error");713	if (error)714		return error;715 716	error = sysfs_create_file(&mp->m_error_kobj.kobject,717				  ATTR_LIST(fail_at_unmount));718 719	if (error)720		goto out_error;721 722	/* .../xfs/<dev>/error/metadata/ */723	error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,724				"metadata", &mp->m_error_meta_kobj,725				xfs_error_meta_init);726	if (error)727		goto out_error;728 729	return 0;730 731out_error:732	xfs_sysfs_del(&mp->m_error_kobj);733	return error;734}735 736void737xfs_error_sysfs_del(738	struct xfs_mount	*mp)739{740	struct xfs_error_cfg	*cfg;741	int			i, j;742 743	for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {744		for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {745			cfg = &mp->m_error_cfg[i][j];746 747			xfs_sysfs_del(&cfg->kobj);748		}749	}750	xfs_sysfs_del(&mp->m_error_meta_kobj);751	xfs_sysfs_del(&mp->m_error_kobj);752}753 754struct xfs_error_cfg *755xfs_error_get_cfg(756	struct xfs_mount	*mp,757	int			error_class,758	int			error)759{760	struct xfs_error_cfg	*cfg;761 762	if (error < 0)763		error = -error;764 765	switch (error) {766	case EIO:767		cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];768		break;769	case ENOSPC:770		cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];771		break;772	case ENODEV:773		cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];774		break;775	default:776		cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];777		break;778	}779 780	return cfg;781}782