All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hou Tao <houtao1@huawei.com>
To: linux-xfs@vger.kernel.org
Cc: darrick.wong@oracle.com, david@fromorbit.com, cmaiolino@redhat.com
Subject: [PATCH 3/7] xfs: make the default values of error configuration customizable and workable
Date: Thu, 31 Aug 2017 22:15:54 +0800	[thread overview]
Message-ID: <1504188958-18374-4-git-send-email-houtao1@huawei.com> (raw)
In-Reply-To: <1504188958-18374-1-git-send-email-houtao1@huawei.com>

Because there is no "default" option for the values of the default error
configuration sysfs, we use bit XFS_ERR_CFG_BIT_ALWAYS_PRIV to distinguish
the default error configurations from the fs-specific ones in store() and
show() functions of these error configuration sysfs.

For each error configuration, a corresponding bit is defined to denote
whether or not an explicit value has been set on the error configuration,
and the bit can be cleared by writing "default" to the sysfs file.

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 fs/xfs/xfs_mount.c |   2 +-
 fs/xfs/xfs_mount.h |  21 ++++++++++
 fs/xfs/xfs_sysfs.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++------
 fs/xfs/xfs_sysfs.h |   2 +-
 4 files changed, 122 insertions(+), 13 deletions(-)

diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 3970066..19f729e 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -715,7 +715,7 @@ xfs_mountfs(
 	if (error)
 		goto out_remove_sysfs;
 
-	error = xfs_error_sysfs_init(&mp->m_eobj, &mp->m_kobj, "error");
+	error = xfs_error_sysfs_init(&mp->m_eobj, &mp->m_kobj, "error", 0);
 	if (error)
 		goto out_del_stats;
 
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 15e35f7..906c3a4 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -57,6 +57,23 @@ enum {
 
 #define XFS_ERR_RETRY_FOREVER	-1
 
+enum {
+	/*
+	 * Used by the default error configuration, because it doesn't
+	 * have a "default" value.
+	 */
+	XFS_ERR_CFG_BIT_ALWAYS_PRIV = 0,
+
+	/*
+	 * Use to denote whether or not the error cfg has a private
+	 * value. The private value will not be influenced by the value
+	 * of the corresponding default error configuration.
+	 */
+	XFS_ERR_CFG_BIT_PRIV_FAIL_UNMOUNT = 1,
+	XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES = 2,
+	XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT = 3,
+};
+
 /*
  * Although retry_timeout is in jiffies which is normally an unsigned long,
  * we limit the retry timeout to 86400 seconds, or one day.  So even a
@@ -70,6 +87,8 @@ struct xfs_error_cfg {
 
 struct xfs_error_cfg_kobj {
 	struct xfs_kobj kobj;
+	/* Refer to XFS_ERR_CFG_BIT_* */
+	unsigned long flags;
 	struct xfs_error_cfg cfg;
 };
 
@@ -78,6 +97,8 @@ struct xfs_error_obj {
 	struct xfs_kobj meta_kobj;
 	struct xfs_error_cfg_kobj
 		cfg_kobj[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
+	/* Refer to XFS_ERR_CFG_BIT_* */
+	unsigned long flags;
 	bool fail_unmount;
 };
 
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index 4a19fad..64f33b1 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -27,6 +27,9 @@
 #include "xfs_stats.h"
 #include "xfs_mount.h"
 
+#define XFS_ERR_CFG_DEFAULT_VALUE "default"
+#define XFS_ERR_CFG_DEFAULT_VALUE_LEN 7
+
 struct xfs_sysfs_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct kobject *kobject, char *buf);
@@ -326,19 +329,19 @@ struct kobj_type xfs_log_ktype = {
  *
  * The sysfs structure here is:
  *	...xfs/<dev>/error/<class>/<errno>/<error_attrs>
+ *	or
+ *	...xfs/default_error/<class>/<errno>/<error_attrs>
  *
  * where <class> allows us to discriminate between data IO and metadata IO,
  * and any other future type of IO (e.g. special inode or directory error
  * handling) we care to support.
  */
-static inline struct xfs_error_cfg *
-to_error_cfg(struct kobject *kobject)
+static inline struct xfs_error_cfg_kobj *
+to_error_cfg_kobj(struct kobject *kobject)
 {
 	struct xfs_kobj *kobj = to_kobj(kobject);
-	struct xfs_error_cfg_kobj *cfg_kobj =
-		container_of(kobj, struct xfs_error_cfg_kobj, kobj);
 
-	return &cfg_kobj->cfg;
+	return container_of(kobj, struct xfs_error_cfg_kobj, kobj);
 }
 
 static inline struct xfs_error_obj *
@@ -348,14 +351,47 @@ err_to_mp(struct kobject *kobject)
 	return container_of(kobj, struct xfs_error_obj, kobj);
 }
 
+static inline ssize_t
+dft_error_cfg_show(
+	char	*buf)
+{
+	return snprintf(buf, PAGE_SIZE, XFS_ERR_CFG_DEFAULT_VALUE "\n");
+}
+
+static inline bool
+is_dft_error_cfg(
+	unsigned long *flags,
+	unsigned int cfg)
+{
+	return (!test_bit(XFS_ERR_CFG_BIT_ALWAYS_PRIV, flags) &&
+			!test_bit(cfg, flags));
+}
+
+static inline bool
+is_value_of_dft_error_cfg(
+	const char	*buf)
+{
+	return (!strncmp(buf, XFS_ERR_CFG_DEFAULT_VALUE,
+				XFS_ERR_CFG_DEFAULT_VALUE_LEN) &&
+			(buf[XFS_ERR_CFG_DEFAULT_VALUE_LEN] == '\0' ||
+			 (buf[XFS_ERR_CFG_DEFAULT_VALUE_LEN] == '\n' &&
+			  buf[XFS_ERR_CFG_DEFAULT_VALUE_LEN + 1] == '\0')));
+}
+
 static ssize_t
 max_retries_show(
 	struct kobject	*kobject,
 	char		*buf)
 {
 	int		retries;
-	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
+	struct xfs_error_cfg_kobj *cfg_kobj = to_error_cfg_kobj(kobject);
+	struct xfs_error_cfg *cfg;
 
+	if (is_dft_error_cfg(&cfg_kobj->flags,
+				XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES))
+		return dft_error_cfg_show(buf);
+
+	cfg = &cfg_kobj->cfg;
 	if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)
 		retries = -1;
 	else
@@ -370,10 +406,18 @@ max_retries_store(
 	const char	*buf,
 	size_t		count)
 {
-	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
+	struct xfs_error_cfg_kobj *cfg_kobj = to_error_cfg_kobj(kobject);
+	struct xfs_error_cfg *cfg;
+	bool	fs_cfg;
 	int		ret;
 	int		val;
 
+	fs_cfg = !test_bit(XFS_ERR_CFG_BIT_ALWAYS_PRIV, &cfg_kobj->flags);
+	if (fs_cfg && is_value_of_dft_error_cfg(buf)) {
+		clear_bit(XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES, &cfg_kobj->flags);
+		return count;
+	}
+
 	ret = kstrtoint(buf, 0, &val);
 	if (ret)
 		return ret;
@@ -381,10 +425,15 @@ max_retries_store(
 	if (val < -1)
 		return -EINVAL;
 
+	cfg = &cfg_kobj->cfg;
 	if (val == -1)
 		cfg->max_retries = XFS_ERR_RETRY_FOREVER;
 	else
 		cfg->max_retries = val;
+
+	if (fs_cfg)
+		set_bit(XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES, &cfg_kobj->flags);
+
 	return count;
 }
 XFS_SYSFS_ATTR_RW(max_retries);
@@ -395,8 +444,14 @@ retry_timeout_seconds_show(
 	char		*buf)
 {
 	int		timeout;
-	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
+	struct xfs_error_cfg_kobj *cfg_kobj = to_error_cfg_kobj(kobject);
+	struct xfs_error_cfg *cfg;
 
+	if (is_dft_error_cfg(&cfg_kobj->flags,
+				XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT))
+		return dft_error_cfg_show(buf);
+
+	cfg = &cfg_kobj->cfg;
 	if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
 		timeout = -1;
 	else
@@ -411,10 +466,18 @@ retry_timeout_seconds_store(
 	const char	*buf,
 	size_t		count)
 {
-	struct xfs_error_cfg *cfg = to_error_cfg(kobject);
+	struct xfs_error_cfg_kobj *cfg_kobj = to_error_cfg_kobj(kobject);
+	struct xfs_error_cfg *cfg;
+	bool	fs_cfg;
 	int		ret;
 	int		val;
 
+	fs_cfg = !test_bit(XFS_ERR_CFG_BIT_ALWAYS_PRIV, &cfg_kobj->flags);
+	if (fs_cfg && is_value_of_dft_error_cfg(buf)) {
+		clear_bit(XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT, &cfg_kobj->flags);
+		return count;
+	}
+
 	ret = kstrtoint(buf, 0, &val);
 	if (ret)
 		return ret;
@@ -423,12 +486,17 @@ retry_timeout_seconds_store(
 	if (val < -1 || val > 86400)
 		return -EINVAL;
 
+	cfg = &cfg_kobj->cfg;
 	if (val == -1)
 		cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
 	else {
 		cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
 		ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);
 	}
+
+	if (fs_cfg)
+		set_bit(XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT, &cfg_kobj->flags);
+
 	return count;
 }
 XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
@@ -440,6 +508,9 @@ fail_at_unmount_show(
 {
 	struct xfs_error_obj *eobj = err_to_mp(kobject);
 
+	if (is_dft_error_cfg(&eobj->flags, XFS_ERR_CFG_BIT_PRIV_FAIL_UNMOUNT))
+		return dft_error_cfg_show(buf);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", eobj->fail_unmount);
 }
 
@@ -450,9 +521,16 @@ fail_at_unmount_store(
 	size_t		count)
 {
 	struct xfs_error_obj *eobj = err_to_mp(kobject);
+	bool	fs_cfg;
 	int		ret;
 	int		val;
 
+	fs_cfg = !test_bit(XFS_ERR_CFG_BIT_ALWAYS_PRIV, &eobj->flags);
+	if (fs_cfg && is_value_of_dft_error_cfg(buf)) {
+		clear_bit(XFS_ERR_CFG_BIT_PRIV_FAIL_UNMOUNT, &eobj->flags);
+		return count;
+	}
+
 	ret = kstrtoint(buf, 0, &val);
 	if (ret)
 		return ret;
@@ -461,6 +539,10 @@ fail_at_unmount_store(
 		return -EINVAL;
 
 	eobj->fail_unmount = val;
+
+	if (fs_cfg)
+		set_bit(XFS_ERR_CFG_BIT_PRIV_FAIL_UNMOUNT, &eobj->flags);
+
 	return count;
 }
 XFS_SYSFS_ATTR_RW(fail_at_unmount);
@@ -537,6 +619,8 @@ xfs_error_sysfs_init_class(
 		struct xfs_error_cfg *cfg;
 
 		cfg_kobj = &eobj->cfg_kobj[class][i];
+		cfg_kobj->flags = eobj->flags &
+			BIT(XFS_ERR_CFG_BIT_ALWAYS_PRIV);
 		error = xfs_sysfs_init(&cfg_kobj->kobj, &xfs_error_cfg_ktype,
 					parent_kobj, init[i].name);
 		if (error)
@@ -567,10 +651,13 @@ int
 xfs_error_sysfs_init(
 	struct xfs_error_obj	*eobj,
 	struct xfs_kobj	*parent,
-	const char	*name)
+	const char	*name,
+	unsigned long	flags)
 {
 	int			error;
 
+	eobj->flags = flags & BIT(XFS_ERR_CFG_BIT_ALWAYS_PRIV);
+
 	/* .../xfs/default_error/ or .../xfs/<dev>/error/ */
 	error = xfs_sysfs_init(&eobj->kobj, &xfs_error_ktype,
 				parent, name);
@@ -621,7 +708,8 @@ xfs_dft_error_sysfs_init(
 	xfs_dft_eobj.kobj.kobject.kset = xfs_kset;
 	xfs_dft_eobj.fail_unmount = true;
 
-	return xfs_error_sysfs_init(&xfs_dft_eobj, NULL, "default_error");
+	return xfs_error_sysfs_init(&xfs_dft_eobj, NULL, "default_error",
+			BIT(XFS_ERR_CFG_BIT_ALWAYS_PRIV));
 }
 
 void
diff --git a/fs/xfs/xfs_sysfs.h b/fs/xfs/xfs_sysfs.h
index 90970c6..77773e5 100644
--- a/fs/xfs/xfs_sysfs.h
+++ b/fs/xfs/xfs_sysfs.h
@@ -65,7 +65,7 @@ int xfs_dft_error_sysfs_init(struct kset *xfs_kset);
 void xfs_dft_error_sysfs_del(void);
 
 int xfs_error_sysfs_init(struct xfs_error_obj *eobj,
-		struct xfs_kobj *parent, const char *name);
+		struct xfs_kobj *parent, const char *name, unsigned long flags);
 void xfs_error_sysfs_del(struct xfs_error_obj *eobj);
 
 #endif	/* __XFS_SYSFS_H__ */
-- 
2.5.0


  parent reply	other threads:[~2017-08-31 14:11 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-31 14:15 [PATCH 0/7] xfs: add customizable default values for error configuration Hou Tao
2017-08-31 14:15 ` [PATCH 1/7] xfs: prepare for the customizable default values of " Hou Tao
2017-08-31 14:15 ` [PATCH 2/7] xfs: add sysfs files for " Hou Tao
2017-08-31 14:15 ` Hou Tao [this message]
2017-08-31 14:15 ` [PATCH 4/7] xfs: merge the initialization table into the default " Hou Tao
2017-08-31 14:15 ` [PATCH 5/7] xfs: construct the values of error configuration for XFS error handler Hou Tao
2017-08-31 14:15 ` [PATCH 6/7] xfs: show the summary of error configurations for debugging purpose Hou Tao
2017-08-31 14:15 ` [PATCH 7/7] xfs: document the customizable default values of error configuration Hou Tao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1504188958-18374-4-git-send-email-houtao1@huawei.com \
    --to=houtao1@huawei.com \
    --cc=cmaiolino@redhat.com \
    --cc=darrick.wong@oracle.com \
    --cc=david@fromorbit.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.